diff options
author | Pietro Cerutti <gahr@FreeBSD.org> | 2013-04-12 14:32:16 +0000 |
---|---|---|
committer | Pietro Cerutti <gahr@FreeBSD.org> | 2013-04-12 14:32:16 +0000 |
commit | 1a47f28b717b3304de8032f832798d45ca7bf527 (patch) | |
tree | 9f8189b3b246e3c19a80932bc65de70e50b6a43a /usr.bin/at/at.c | |
parent | b9e6237dabc02e4b40624deb8a3244f79a66eb90 (diff) | |
download | src-1a47f28b717b3304de8032f832798d45ca7bf527.tar.gz src-1a47f28b717b3304de8032f832798d45ca7bf527.zip |
- Do not bail out if stat(2) fails with ENOENT in the spool directory. This
happens if another atrm process removes a job while we're scanning through
the directory.
- While at it, optimize a bit the directory scanning, so that we quit looping
as soon as all jobs specified in argv have been dealt with.
Approved by: cognet
Notes
Notes:
svn path=/head/; revision=249406
Diffstat (limited to 'usr.bin/at/at.c')
-rw-r--r-- | usr.bin/at/at.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/usr.bin/at/at.c b/usr.bin/at/at.c index cb2fadb97419..5f4500ba343b 100644 --- a/usr.bin/at/at.c +++ b/usr.bin/at/at.c @@ -531,6 +531,10 @@ process_jobs(int argc, char **argv, int what) /* Delete every argument (job - ID) given */ int i; + int rc; + int nofJobs; + int nofDone; + int statErrno; struct stat buf; DIR *spool; struct dirent *dirent; @@ -538,6 +542,9 @@ process_jobs(int argc, char **argv, int what) char queue; long jobno; + nofJobs = argc - optind; + nofDone = 0; + PRIV_START if (chdir(ATJOB_DIR) != 0) @@ -553,9 +560,20 @@ process_jobs(int argc, char **argv, int what) while((dirent = readdir(spool)) != NULL) { PRIV_START - if (stat(dirent->d_name, &buf) != 0) - perr("cannot stat in " ATJOB_DIR); + rc = stat(dirent->d_name, &buf); + statErrno = errno; PRIV_END + /* There's a race condition between readdir above and stat here: + * another atrm process could have removed the file from the spool + * directory under our nose. If this happens, stat will set errno to + * ENOENT, which we shouldn't treat as fatal. + */ + if (rc != 0) { + if (statErrno == ENOENT) + continue; + else + perr("cannot stat in " ATJOB_DIR); + } if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3) continue; @@ -601,9 +619,15 @@ process_jobs(int argc, char **argv, int what) errx(EXIT_FAILURE, "internal error, process_jobs = %d", what); } + + /* All arguments have been processed + */ + if (++nofDone == nofJobs) + goto end; } } } +end: closedir(spool); } /* delete_jobs */ |