Thanks again for your advice!
On Fri, Apr 23, 2010 at 10:42:14AM +0200, Jim Meyering wrote:
Satoru SATOH wrote:
...
> +static int
> +hostsfileWrite(const char *path,
> + dnsmasqDhcpHost *hosts,
> + unsigned int nhosts)
> +{
> + char *tmp;
> + FILE *f;
> + bool istmp = true;
> + unsigned int i;
> + int saved_errno;
> +
> + if (nhosts == 0 && unlink(path) == 0)
> + return 0;
> +
> + if (virAsprintf(&tmp, "%s.new", path) < 0)
> + return -1;
Any return after this point must be preceded by
code that frees "tmp". Otherwise it is a leak.
oops, abosolutely right. fixed locally.
> + if (!(f = fopen(tmp, "w"))) {
> + istmp = false;
> + if (!(f = fopen(path, "w")))
> + return errno;
> + }
> +
> + for (i = 0; i < nhosts; i++) {
> + if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) {
> + saved_errno = errno;
> + fclose(f);
> +
> + if (istmp)
> + unlink(tmp);
> +
> + return saved_errno;
> + }
> + }
> +
> + fclose(f);
I mentioned this already.
You must detect write failure here.
sorry, missed.
> + if (istmp && rename(tmp, path) < 0) {
> + saved_errno = errno;
> + unlink(tmp);
> +
> + return saved_errno;
> + }
> +
> + if (istmp)
> + unlink(tmp);
Failure to remove this temporary file might deserve a warning.
No big deal either way.
fixed.
> +
> + return 0;
> +}
...
> +static int
> +hostsfileDelete(dnsmasqHostsfile *hostsfile)
> +{
> + if (!virFileExists(hostsfile->path))
> + return 0;
> +
> + if (unlink(hostsfile->path) < 0) {
> + virReportSystemError(errno, _("cannot remove config file
'%s'"),
I think saying "failed to..." is slightly clearer than "cannot...".
> + hostsfile->path);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * dnsmasqAddDhcpHost:
> + * @ctx: pointer to the dnsmasq context for each network
> + * @mac: pointer to the string contains mac address of the host
> + * @ip: pointer to the string contains ip address of the host
> + * @name: pointer to the string contains hostname of the host or NULL
> + *
> + * Add dhcp-host entry.
> + */
> +void
> +dnsmasqAddDhcpHost(dnsmasqContext *ctx,
> + const char *mac,
> + const char *ip,
> + const char *name)
> +{
> + if (ctx->hostsfile)
> + hostsfileAdd(ctx->hostsfile, mac, ip, name);
Would a caller ever want to know if this function fails?
If so, don't ignore hostsfileAdd failure.
That would be more consistent with how the following functions work, too.
right but I want to keep as it is for a while.
BTW, shouldn't hostsfileAdd be spelled hostsFileAdd (with a
capital "F")?
> +}
> +
> +/**
> + * dnsmasqSave:
> + * @ctx: pointer to the dnsmasq context for each network
> + *
> + * Saves all the configurations associated with a context to disk.
> + */
> +int
> +dnsmasqSave(const dnsmasqContext *ctx)
> +{
> + if (ctx->hostsfile)
> + return hostsfileSave(ctx->hostsfile);
> + return 0;
> +}