Satoru SATOH wrote: > This patch adds the files implements dnsmasq (hostsfile) module. Here is some feedback not on the overall structure or utility, but more on a few implementation details that stood out. ... > diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c ... > +static void > +dhcphostFree(dnsmasqDhcpHost *host) > +{ > + VIR_FREE(host->host); > +} > + > +static void > +hostsfileFree(dnsmasqHostsfile *hostsfile) > +{ > + int i; Making that unsigned int i; is slightly better (if possible[*]), since it's obvious "i" will never need to be signed. [*] whether it is possible depends on the type of the nhosts member and the set of gcc warnings enabled. Build with --enable-compile-warnings=error to check. > + > + if (hostsfile->hosts) { > + for (i = 0; i < hostsfile->nhosts; i++) > + dhcphostFree(&hostsfile->hosts[i]); > + > + VIR_FREE(hostsfile->hosts); > + > + hostsfile->nhosts = 0; > + } > + > + hostsfile->path[0] = '\0'; > + > + VIR_FREE(hostsfile); > +} ... > +static dnsmasqHostsfile * > +hostsfileNew(const char *name, > + const char *config_dir) > +{ > + int err; > + dnsmasqHostsfile *hostsfile; > + > + if (VIR_ALLOC(hostsfile) < 0) > + return NULL; > + > + hostsfile->hosts = NULL; > + hostsfile->nhosts = 0; > + > + if ((err = virFileMakePath(config_dir))) { > + virReportSystemError(err, _("cannot create config directory '%s'"), > + config_dir); > + goto error; > + } > + > + if (virFileBuildPath(config_dir, name, ".hostsfile", hostsfile->path, > + sizeof(hostsfile->path)) < 0) { > + virReportSystemError(err, > + _("config filename '%s/%s.%s' is too long"), > + config_dir, name, ".hostsfile"); > + goto error; > + } > + > + return hostsfile; > + > + error: > + hostsfileFree(hostsfile); > + return NULL; > +} > + > +static int > +hostsfileWrite(const char *path, dnsmasqDhcpHost *hosts, int nhosts) > +{ > + char tmp[PATH_MAX]; It's good to avoid use of PATH_MAX. Declare it like this instead, ... char *tmp; > + FILE *f; > + int istmp; > + int i; > + > + if (nhosts == 0 && unlink(path) == 0) > + return 0; > + > + if (snprintf(tmp, PATH_MAX, "%s.new", path) >= PATH_MAX) > + return EINVAL; ... and here, use virAsprintf instead of snprintf. If the name ends up being too long, you'll catch it when fopen fails. > + istmp = 1; > + > + if (!(f = fopen(tmp, "w"))) { > + istmp = 0; > + if (!(f = fopen(path, "w"))) > + return errno; > + } > + > + for (i = 0; i < nhosts; i++) { > + if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) { > + fclose(f); fclose may well clobber the fputs-set errno. Save it, with this, just before the fclose. int saved_errno = errno > + if (istmp) > + unlink(tmp); unlink may clobber errno, too. So here, you should use "return saved_errno;" > + return errno; > + } > + } > + > + fclose(f); The fputs calls can succeed, yet fclose's write or close can still fail. So you must check for fclose failure, too. > + > + if (istmp && rename(tmp, path) < 0) { Save errno here too, so unlink can't clobber it. int saved_errno = errno > + unlink(tmp); > + return errno; and use saved_errno here. > + } > + > + if (istmp) > + unlink(tmp); > + > + return 0; > +} -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list