diff options
author | наб <[email protected]> | 2021-05-17 18:13:18 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2021-12-17 12:53:54 -0800 |
commit | c53f2e9b5086051a9aede27254a109983443e557 (patch) | |
tree | 1f2b7b583070e83317c675befb0bc4a450c3fb1e /lib/libshare/nfs.c | |
parent | f50697f95b1601d40e7c33249ab1b5d8163d9f64 (diff) |
libshare: nfs: open temporary file once
Reviewed-by: Don Brady <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: John Kennedy <[email protected]>
Signed-off-by: Ahelenia Ziemiańska <[email protected]>
Closes #12067
Diffstat (limited to 'lib/libshare/nfs.c')
-rw-r--r-- | lib/libshare/nfs.c | 83 |
1 files changed, 54 insertions, 29 deletions
diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c index 2b0c70001..e7037b104 100644 --- a/lib/libshare/nfs.c +++ b/lib/libshare/nfs.c @@ -77,10 +77,18 @@ nfs_exports_unlock(const char *name) nfs_lock_fd = -1; } -static char * -nfs_init_tmpfile(const char *prefix, const char *mdir) +struct tmpfile { + /* + * This only needs to be as wide as ZFS_EXPORTS_FILE and mktemp suffix, + * 64 is more than enough. + */ + char name[64]; + FILE *fp; +}; + +static boolean_t +nfs_init_tmpfile(const char *prefix, const char *mdir, struct tmpfile *tmpf) { - char *tmpfile = NULL; struct stat sb; if (mdir != NULL && @@ -88,72 +96,89 @@ nfs_init_tmpfile(const char *prefix, const char *mdir) mkdir(mdir, 0755) < 0) { fprintf(stderr, "failed to create %s: %s\n", mdir, strerror(errno)); - return (NULL); + return (B_FALSE); } - if (asprintf(&tmpfile, "%s.XXXXXXXX", prefix) == -1) { - fprintf(stderr, "Unable to allocate temporary file\n"); - return (NULL); - } + strcpy(tmpf->name, prefix); + strcat(tmpf->name, ".XXXXXXXX"); - int fd = mkostemp(tmpfile, O_CLOEXEC); + int fd = mkostemp(tmpf->name, O_CLOEXEC); if (fd == -1) { fprintf(stderr, "Unable to create temporary file: %s", strerror(errno)); - free(tmpfile); - return (NULL); + return (B_FALSE); + } + + tmpf->fp = fdopen(fd, "w+"); + if (tmpf->fp == NULL) { + fprintf(stderr, "Unable to reopen temporary file: %s", + strerror(errno)); + close(fd); + return (B_FALSE); } - close(fd); - return (tmpfile); + + return (B_TRUE); +} + +static void +nfs_abort_tmpfile(struct tmpfile *tmpf) +{ + unlink(tmpf->name); + fclose(tmpf->fp); } static int -nfs_fini_tmpfile(const char *exports, char *tmpfile) +nfs_fini_tmpfile(const char *exports, struct tmpfile *tmpf) { - if (rename(tmpfile, exports) == -1) { - fprintf(stderr, "Unable to rename %s: %s\n", tmpfile, + if (fflush(tmpf->fp) != 0) { + fprintf(stderr, "Failed to write to temporary file: %s\n", strerror(errno)); - unlink(tmpfile); - free(tmpfile); + nfs_abort_tmpfile(tmpf); + return (SA_SYSTEM_ERR); + } + + if (rename(tmpf->name, exports) == -1) { + fprintf(stderr, "Unable to rename %s -> %s: %s\n", + tmpf->name, exports, strerror(errno)); + nfs_abort_tmpfile(tmpf); return (SA_SYSTEM_ERR); } - free(tmpfile); + + fclose(tmpf->fp); return (SA_OK); } int nfs_toggle_share(const char *lockfile, const char *exports, const char *expdir, sa_share_impl_t impl_share, - int(*cbk)(sa_share_impl_t impl_share, char *filename)) + int(*cbk)(sa_share_impl_t impl_share, FILE *tmpfile)) { int error; - char *filename; + struct tmpfile tmpf; - if ((filename = nfs_init_tmpfile(exports, expdir)) == NULL) + if (!nfs_init_tmpfile(exports, expdir, &tmpf)) return (SA_SYSTEM_ERR); error = nfs_exports_lock(lockfile); if (error != 0) { - unlink(filename); - free(filename); + nfs_abort_tmpfile(&tmpf); return (error); } - error = nfs_copy_entries(filename, impl_share->sa_mountpoint); + error = nfs_copy_entries(tmpf.fp, impl_share->sa_mountpoint); if (error != SA_OK) goto fullerr; - error = cbk(impl_share, filename); + error = cbk(impl_share, tmpf.fp); if (error != SA_OK) goto fullerr; - error = nfs_fini_tmpfile(exports, filename); + error = nfs_fini_tmpfile(exports, &tmpf); nfs_exports_unlock(lockfile); return (error); fullerr: - unlink(filename); - free(filename); + nfs_abort_tmpfile(&tmpf); nfs_exports_unlock(lockfile); return (error); } |