mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Fix memleak in cmd/mount_zfs.c
Convert dynamic allocation to static buffer, simplify parse_dataset function return path. Add tests specific to the mount helper. Reviewed-by: Mateusz Guzik <mjguzik@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Sterling Jensen <sterlingjensen@users.noreply.github.com> Closes #11098
This commit is contained in:
+27
-41
@@ -47,46 +47,34 @@ libzfs_handle_t *g_zfs;
|
||||
* is expected to be of the form pool/dataset, however may also refer to
|
||||
* a block device if that device contains a valid zfs label.
|
||||
*/
|
||||
static char *
|
||||
parse_dataset(char *dataset)
|
||||
static void
|
||||
parse_dataset(const char *target, char **dataset)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
struct stat64 statbuf;
|
||||
int error;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* We expect a pool/dataset to be provided, however if we're
|
||||
* given a device which is a member of a zpool we attempt to
|
||||
* extract the pool name stored in the label. Given the pool
|
||||
* name we can mount the root dataset.
|
||||
*/
|
||||
error = stat64(dataset, &statbuf);
|
||||
if (error == 0) {
|
||||
nvlist_t *config;
|
||||
char *name;
|
||||
int fd;
|
||||
int fd = open(target, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
nvlist_t *config = NULL;
|
||||
if (zpool_read_label(fd, &config, NULL) != 0)
|
||||
config = NULL;
|
||||
if (close(fd))
|
||||
perror("close");
|
||||
|
||||
fd = open(dataset, O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto out;
|
||||
|
||||
error = zpool_read_label(fd, &config, NULL);
|
||||
(void) close(fd);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = nvlist_lookup_string(config,
|
||||
ZPOOL_CONFIG_POOL_NAME, &name);
|
||||
if (error) {
|
||||
if (config) {
|
||||
char *name = NULL;
|
||||
if (!nvlist_lookup_string(config,
|
||||
ZPOOL_CONFIG_POOL_NAME, &name))
|
||||
(void) strlcpy(*dataset, name, PATH_MAX);
|
||||
nvlist_free(config);
|
||||
} else {
|
||||
dataset = strdup(name);
|
||||
nvlist_free(config);
|
||||
return (dataset);
|
||||
if (name)
|
||||
return;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
/*
|
||||
* If a file or directory in your current working directory is
|
||||
* named 'dataset' then mount(8) will prepend your current working
|
||||
@@ -94,16 +82,14 @@ out:
|
||||
* behavior so we simply check for it and strip the prepended
|
||||
* patch when it is added.
|
||||
*/
|
||||
if (getcwd(cwd, PATH_MAX) == NULL)
|
||||
return (dataset);
|
||||
|
||||
len = strlen(cwd);
|
||||
|
||||
/* Do not add one when cwd already ends in a trailing '/' */
|
||||
if (strncmp(cwd, dataset, len) == 0)
|
||||
return (dataset + len + (cwd[len-1] != '/'));
|
||||
|
||||
return (dataset);
|
||||
char cwd[PATH_MAX];
|
||||
if (getcwd(cwd, PATH_MAX) != NULL) {
|
||||
int len = strlen(cwd);
|
||||
/* Do not add one when cwd already ends in a trailing '/' */
|
||||
if (strncmp(cwd, target, len) == 0)
|
||||
target += len + (cwd[len-1] != '/');
|
||||
}
|
||||
strlcpy(*dataset, target, PATH_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -176,7 +162,7 @@ main(int argc, char **argv)
|
||||
char badopt[MNT_LINE_MAX] = { '\0' };
|
||||
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
||||
char mntpoint[PATH_MAX];
|
||||
char *dataset;
|
||||
char dataset[PATH_MAX], *pdataset = dataset;
|
||||
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
||||
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
||||
int error, c;
|
||||
@@ -232,7 +218,7 @@ main(int argc, char **argv)
|
||||
return (MOUNT_USAGE);
|
||||
}
|
||||
|
||||
dataset = parse_dataset(argv[0]);
|
||||
parse_dataset(argv[0], &pdataset);
|
||||
|
||||
/* canonicalize the mount point */
|
||||
if (realpath(argv[1], mntpoint) == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user