commit f4b0df7bfe0f4016bb2d3ff90f36f00b76a02f57
parent 312fb51c9cc56cd9bc5dc1fb72c331b847a37eec
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sun, 28 Feb 2016 17:35:48 +0100

sfeed_frames: fix TOCTTUO with access() and fopen()

... and use futimens() in favor of deprecated utime().
a minor difference in behaviour is now filetimes are only updated when the
file doesn't exist.

minor cleanup: remove namelen, its variable was unused (reported by cppcheck).

Diffstat:
Msfeed_frames.c | 38+++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/sfeed_frames.c b/sfeed_frames.c @@ -4,6 +4,7 @@ #include <ctype.h> #include <err.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdarg.h> #include <stdio.h> @@ -18,7 +19,7 @@ static struct feed **feeds; static char *line; static size_t linesize; -static struct utimbuf contenttime; +static struct timespec times[2]; static time_t comparetime; static unsigned long totalnew; @@ -109,7 +110,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) FILE *fpcontent = NULL; unsigned int isnew; time_t parsedtime; - int r; + int fd, r; if (f->name[0]) feedname = f->name; @@ -117,7 +118,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) feedname = "unnamed"; /* make directory for feedname */ - if (!(namelen = normalizepath(feedname, name, sizeof(name)))) + if (!normalizepath(feedname, name, sizeof(name))) return; strlcpy(dirpath, name, sizeof(dirpath)); @@ -144,16 +145,22 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) if (!parseline(line, fields)) break; /* write content */ - if (!(namelen = normalizepath(fields[FieldTitle], name, sizeof(name)))) + if (!normalizepath(fields[FieldTitle], name, sizeof(name))) continue; r = snprintf(filepath, sizeof(filepath), "%s/%s.html", dirpath, name); if (r == -1 || (size_t)r >= sizeof(filepath)) errx(1, "snprintf: path truncation: '%s/%s.html'", dirpath, name); + parsedtime = 0; + strtotime(fields[FieldUnixTimestamp], &parsedtime); + /* content file doesn't exist yet and has write access */ - if (access(filepath, F_OK) != 0) { - if (!(fpcontent = fopen(filepath, "w+b"))) - err(1, "fopen: %s", filepath); + if ((fd = open(filepath, O_CREAT | O_EXCL)) == -1) { + if (errno == EACCES) + err(1, "open: %s", filepath); + } else { + if (!(fpcontent = fdopen(fd, "w+b"))) + err(1, "fdopen: %s", filepath); fputs("<html><head>" "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../style.css\" />" "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />" @@ -175,15 +182,16 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) fputs("</pre>", fpcontent); } fputs("</div></body></html>", fpcontent); - fclose(fpcontent); - } - /* set modified and access time of file to time of item. */ - parsedtime = 0; - if (strtotime(fields[FieldUnixTimestamp], &parsedtime) != -1) { - contenttime.actime = parsedtime; - contenttime.modtime = parsedtime; - utime(filepath, &contenttime); + /* set modified and access time of file to time of item. */ + if (parsedtime) { + times[0].tv_sec = parsedtime; + times[1].tv_sec = parsedtime; + + if (futimens(fd, times) == -1) + err(1, "futimens"); + } + fclose(fpcontent); } isnew = (parsedtime >= comparetime) ? 1 : 0;