[libvirt] [Resend][PATCH 1/3] Add dnsmasq module

Jim Meyering jim at meyering.net
Tue Apr 20 17:42:45 UTC 2010


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;
> +}




More information about the libvir-list mailing list