* Allow $DM_DEVDIR envvar to override default of "/dev".
@ 2007-10-08 17:25 ` Jim Meyering
0 siblings, 0 replies; 12+ messages in thread
From: Jim Meyering @ 2007-10-08 17:25 UTC (permalink / raw)
To: device-mapper development; +Cc: LVM
In making LVM tests more reproducible and insulating them from
any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify
a different /dev directory. However, that broke down for tests
that ran dmsetup, since dmsetup hard-codes /dev.
Here's a patch to make dmsetup honor a new DM_DEVDIR envvar,
in using that value in place of "/dev":
Allow $DM_DEVDIR envvar to override default of "/dev".
* dmsetup/dmsetup.c (DEV_PATH): Remove definition.
(parse_loop_device_name): Add parameter: dev_dir.
Declare the "dev" parameter to be "const".
Use dev_dir, not DEV_PATH. Handle the case in which dev_dir
does not end in a "/".
(_get_abspath): Declare "path" parameter "const", to match.
(_process_losetup_switches): Add parameter: dev_dir.
Pass dev_dir to parse_loop_device_name.
(_process_switches): Add parameter: dev_dir.
Pass dev_dir to _process_losetup_switches.
(main): Set dev_dir from the DM_DEVDIR envvar, else to "/dev".
Call dm_set_dev_dir.
* lib/libdm-common.c (dm_set_dev_dir): Rewrite to be careful
about boundary conditions, now that dev_dir may be tainted.
As for the way I call dm_set_dev_dir in main, note that I call
it only when using a value from DM_DEVDIR, and not when using
the default of "/dev". That's sort of ugly, but using "/dev"
is the default that is hard-coded into libdevmapper, via this:
lib/libdm-common.c:
#define DEV_DIR "/dev/"
static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
Ideally, libdevmapper wouldn't rely on any such static variable,
of course, but there may well be existing callers, so I won't
try to change that.
Signed-off-by: Jim Meyering <meyering@redhat.com>
---
dmsetup/dmsetup.c | 35 ++++++++++++++++++++++++++---------
lib/libdm-common.c | 15 +++++++++++++--
2 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c
index 562f628..ca864b8 100644
--- a/dmsetup/dmsetup.c
+++ b/dmsetup/dmsetup.c
@@ -97,7 +97,6 @@ extern char *optarg;
/* FIXME Should be elsewhere */
#define SECTOR_SHIFT 9L
-#define DEV_PATH "/dev/"
#define err(msg, x...) fprintf(stderr, msg "\n", ##x)
@@ -2129,7 +2128,7 @@ static int _process_tree_options(const char *options)
* Returns the full absolute path, or NULL if the path could
* not be resolved.
*/
-static char *_get_abspath(char *path)
+static char *_get_abspath(const char *path)
{
char *_path;
@@ -2141,7 +2140,7 @@ static char *_get_abspath(char *path)
return _path;
}
-static char *parse_loop_device_name(char *dev)
+static char *parse_loop_device_name(const char *dev, const char *dev_dir)
{
char *buf;
char *device;
@@ -2153,7 +2152,13 @@ static char *parse_loop_device_name(char *dev)
if (!(device = _get_abspath(dev)))
goto error;
- if (strncmp(device, DEV_PATH, strlen(DEV_PATH)))
+ if (strncmp(device, dev_dir, strlen(dev_dir)))
+ goto error;
+
+ /* If dev_dir does not end in a slash, ensure that the
+ following byte in the device string is "/". */
+ if (dev_dir[strlen(dev_dir) - 1] != '/'
+ && device[strlen(dev_dir)] != '/')
goto error;
strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
@@ -2234,7 +2239,8 @@ error:
return 0;
}
-static int _process_losetup_switches(const char *base, int *argc, char ***argv)
+static int _process_losetup_switches(const char *base, int *argc, char ***argv,
+ const char *dev_dir)
{
static int ind;
int c;
@@ -2297,7 +2303,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv)
return 0;
}
- if (!(device_name = parse_loop_device_name((*argv)[0]))) {
+ if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) {
fprintf(stderr, "%s: Could not parse loop_device %s\n",
base, (*argv)[0]);
_losetup_usage(stderr);
@@ -2344,7 +2350,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv)
return 1;
}
-static int _process_switches(int *argc, char ***argv)
+static int _process_switches(int *argc, char ***argv, const char *dev_dir)
{
char *base, *namebase;
static int ind;
@@ -2422,7 +2428,7 @@ static int _process_switches(int *argc, char ***argv)
}
if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
- r = _process_losetup_switches(base, argc, argv);
+ r = _process_losetup_switches(base, argc, argv, dev_dir);
free(namebase);
return r;
}
@@ -2539,10 +2545,21 @@ int main(int argc, char **argv)
{
struct command *c;
int r = 1;
+ const char *dev_dir;
(void) setlocale(LC_ALL, "");
- if (!_process_switches(&argc, &argv)) {
+ dev_dir = getenv ("DM_DEVDIR");
+ if (dev_dir && *dev_dir) {
+ if (!dm_set_dev_dir(dev_dir)) {
+ fprintf(stderr, "Invalid DM_DEVDIR envvar value.\n");
+ goto out;
+ }
+ } else {
+ dev_dir = "/dev";
+ }
+
+ if (!_process_switches(&argc, &argv, dev_dir)) {
fprintf(stderr, "Couldn't process command line.\n");
goto out;
}
diff --git a/lib/libdm-common.c b/lib/libdm-common.c
index c8c3500..c87903a 100644
--- a/lib/libdm-common.c
+++ b/lib/libdm-common.c
@@ -463,9 +463,20 @@ void update_devs(void)
_pop_node_ops();
}
-int dm_set_dev_dir(const char *dir)
+int dm_set_dev_dir(const char *dev_dir)
{
- snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR);
+ size_t len;
+ const char *slash;
+ if (*dev_dir != '/')
+ return 0;
+
+ len = strlen(dev_dir);
+ slash = dev_dir[len-1] == '/' ? "" : "/";
+
+ if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR)
+ >= sizeof _dm_dir)
+ return 0;
+
return 1;
}
--
1.5.3.4.206.g58ba4
^ permalink raw reply related [flat|nested] 12+ messages in thread* Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-08 17:25 ` Jim Meyering 0 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-08 17:25 UTC (permalink / raw) To: lvm-devel In making LVM tests more reproducible and insulating them from any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify a different /dev directory. However, that broke down for tests that ran dmsetup, since dmsetup hard-codes /dev. Here's a patch to make dmsetup honor a new DM_DEVDIR envvar, in using that value in place of "/dev": Allow $DM_DEVDIR envvar to override default of "/dev". * dmsetup/dmsetup.c (DEV_PATH): Remove definition. (parse_loop_device_name): Add parameter: dev_dir. Declare the "dev" parameter to be "const". Use dev_dir, not DEV_PATH. Handle the case in which dev_dir does not end in a "/". (_get_abspath): Declare "path" parameter "const", to match. (_process_losetup_switches): Add parameter: dev_dir. Pass dev_dir to parse_loop_device_name. (_process_switches): Add parameter: dev_dir. Pass dev_dir to _process_losetup_switches. (main): Set dev_dir from the DM_DEVDIR envvar, else to "/dev". Call dm_set_dev_dir. * lib/libdm-common.c (dm_set_dev_dir): Rewrite to be careful about boundary conditions, now that dev_dir may be tainted. As for the way I call dm_set_dev_dir in main, note that I call it only when using a value from DM_DEVDIR, and not when using the default of "/dev". That's sort of ugly, but using "/dev" is the default that is hard-coded into libdevmapper, via this: lib/libdm-common.c: #define DEV_DIR "/dev/" static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR; Ideally, libdevmapper wouldn't rely on any such static variable, of course, but there may well be existing callers, so I won't try to change that. Signed-off-by: Jim Meyering <meyering@redhat.com> --- dmsetup/dmsetup.c | 35 ++++++++++++++++++++++++++--------- lib/libdm-common.c | 15 +++++++++++++-- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c index 562f628..ca864b8 100644 --- a/dmsetup/dmsetup.c +++ b/dmsetup/dmsetup.c @@ -97,7 +97,6 @@ extern char *optarg; /* FIXME Should be elsewhere */ #define SECTOR_SHIFT 9L -#define DEV_PATH "/dev/" #define err(msg, x...) fprintf(stderr, msg "\n", ##x) @@ -2129,7 +2128,7 @@ static int _process_tree_options(const char *options) * Returns the full absolute path, or NULL if the path could * not be resolved. */ -static char *_get_abspath(char *path) +static char *_get_abspath(const char *path) { char *_path; @@ -2141,7 +2140,7 @@ static char *_get_abspath(char *path) return _path; } -static char *parse_loop_device_name(char *dev) +static char *parse_loop_device_name(const char *dev, const char *dev_dir) { char *buf; char *device; @@ -2153,7 +2152,13 @@ static char *parse_loop_device_name(char *dev) if (!(device = _get_abspath(dev))) goto error; - if (strncmp(device, DEV_PATH, strlen(DEV_PATH))) + if (strncmp(device, dev_dir, strlen(dev_dir))) + goto error; + + /* If dev_dir does not end in a slash, ensure that the + following byte in the device string is "/". */ + if (dev_dir[strlen(dev_dir) - 1] != '/' + && device[strlen(dev_dir)] != '/') goto error; strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX); @@ -2234,7 +2239,8 @@ error: return 0; } -static int _process_losetup_switches(const char *base, int *argc, char ***argv) +static int _process_losetup_switches(const char *base, int *argc, char ***argv, + const char *dev_dir) { static int ind; int c; @@ -2297,7 +2303,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 0; } - if (!(device_name = parse_loop_device_name((*argv)[0]))) { + if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) { fprintf(stderr, "%s: Could not parse loop_device %s\n", base, (*argv)[0]); _losetup_usage(stderr); @@ -2344,7 +2350,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 1; } -static int _process_switches(int *argc, char ***argv) +static int _process_switches(int *argc, char ***argv, const char *dev_dir) { char *base, *namebase; static int ind; @@ -2422,7 +2428,7 @@ static int _process_switches(int *argc, char ***argv) } if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){ - r = _process_losetup_switches(base, argc, argv); + r = _process_losetup_switches(base, argc, argv, dev_dir); free(namebase); return r; } @@ -2539,10 +2545,21 @@ int main(int argc, char **argv) { struct command *c; int r = 1; + const char *dev_dir; (void) setlocale(LC_ALL, ""); - if (!_process_switches(&argc, &argv)) { + dev_dir = getenv ("DM_DEVDIR"); + if (dev_dir && *dev_dir) { + if (!dm_set_dev_dir(dev_dir)) { + fprintf(stderr, "Invalid DM_DEVDIR envvar value.\n"); + goto out; + } + } else { + dev_dir = "/dev"; + } + + if (!_process_switches(&argc, &argv, dev_dir)) { fprintf(stderr, "Couldn't process command line.\n"); goto out; } diff --git a/lib/libdm-common.c b/lib/libdm-common.c index c8c3500..c87903a 100644 --- a/lib/libdm-common.c +++ b/lib/libdm-common.c @@ -463,9 +463,20 @@ void update_devs(void) _pop_node_ops(); } -int dm_set_dev_dir(const char *dir) +int dm_set_dev_dir(const char *dev_dir) { - snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR); + size_t len; + const char *slash; + if (*dev_dir != '/') + return 0; + + len = strlen(dev_dir); + slash = dev_dir[len-1] == '/' ? "" : "/"; + + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) + >= sizeof _dm_dir) + return 0; + return 1; } -- 1.5.3.4.206.g58ba4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". 2007-10-08 17:25 ` Jim Meyering @ 2007-10-09 2:00 ` Alasdair G Kergon -1 siblings, 0 replies; 12+ messages in thread From: Alasdair G Kergon @ 2007-10-09 2:00 UTC (permalink / raw) To: Jim Meyering; +Cc: device-mapper development, LVM On Mon, Oct 08, 2007 at 07:25:56PM +0200, Jim Meyering wrote: > any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify > Here's a patch to make dmsetup honor a new DM_DEVDIR envvar, Small point, but should that be DM_DEV_DIR for consistency with LVM_SYSTEM_DIR ? > + } else { > + dev_dir = "/dev"; Can you make that a #define at the top of the file? (Try to keep hard-coded values easy to spot.) > + if (*dev_dir != '/') > + return 0; log_error ? (Functions should produce an error message as close as possible to the place the problem is detected; all functions that return failure must log a message before returning - using a macro like 'stack' if you don't want the user to see it. The only exceptions (very rare) are functions expected to fail frequently that would produce too many log messages.) > + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) > + >= sizeof _dm_dir) > + return 0; and here Also consider dm_snprintf rather than snprintf. [lvm2 uses this, but bits of dm haven't been converted] Alasdair -- agk@redhat.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-09 2:00 ` Alasdair G Kergon 0 siblings, 0 replies; 12+ messages in thread From: Alasdair G Kergon @ 2007-10-09 2:00 UTC (permalink / raw) To: lvm-devel On Mon, Oct 08, 2007 at 07:25:56PM +0200, Jim Meyering wrote: > any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify > Here's a patch to make dmsetup honor a new DM_DEVDIR envvar, Small point, but should that be DM_DEV_DIR for consistency with LVM_SYSTEM_DIR ? > + } else { > + dev_dir = "/dev"; Can you make that a #define at the top of the file? (Try to keep hard-coded values easy to spot.) > + if (*dev_dir != '/') > + return 0; log_error ? (Functions should produce an error message as close as possible to the place the problem is detected; all functions that return failure must log a message before returning - using a macro like 'stack' if you don't want the user to see it. The only exceptions (very rare) are functions expected to fail frequently that would produce too many log messages.) > + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) > + >= sizeof _dm_dir) > + return 0; and here Also consider dm_snprintf rather than snprintf. [lvm2 uses this, but bits of dm haven't been converted] Alasdair -- agk at redhat.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". 2007-10-09 2:00 ` Alasdair G Kergon @ 2007-10-09 11:43 ` Jim Meyering -1 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 11:43 UTC (permalink / raw) To: device-mapper development, Alasdair G. Kergon; +Cc: LVM Alasdair G Kergon <agk@redhat.com> wrote: > On Mon, Oct 08, 2007 at 07:25:56PM +0200, Jim Meyering wrote: >> any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify > >> Here's a patch to make dmsetup honor a new DM_DEVDIR envvar, > > Small point, but should that be DM_DEV_DIR for consistency with > LVM_SYSTEM_DIR ? Yep. I prefer that, too. >> + } else { >> + dev_dir = "/dev"; > Can you make that a #define at the top of the file? Ok. >> + if (*dev_dir != '/') >> + return 0; > > log_error ? > (Functions should produce an error message as close as possible to the > place the problem is detected; all functions that return failure must > log a message before returning - using a macro like 'stack' if you don't > want the user to see it. The only exceptions (very rare) are functions > expected to fail frequently that would produce too many log messages.) > >> + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) >> + >= sizeof _dm_dir) >> + return 0; > > and here I can do that, but then the diagnostic can no longer say that the DM_DEV_DIR envvar is at fault. There is a slight advantage to diagnosing "too long" and "dir name is not absolute" separately, but nonetheless, I have a slight preference for being able to point directly to the DM_DEV_DIR envvar. With my original patch, I got this diagnostic: Invalid DM_DEVDIR envvar value. with the patch below, I get one of these Invalid dev_dir value, x: not an absolute name. Invalid dev_dir value, ...: name too long. > Also consider dm_snprintf rather than snprintf. > [lvm2 uses this, but bits of dm haven't been converted] Sounds like a good idea for a separate patch. There are many uses of snprintf. IMHO, it'd be best to change them all at once. Here's the incremental patch, then the full one: diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c index ca864b8..6244959 100644 --- a/dmsetup/dmsetup.c +++ b/dmsetup/dmsetup.c @@ -90,6 +90,8 @@ extern char *optarg; #define ARGS_MAX 256 #define LOOP_TABLE_SIZE (PATH_MAX + 255) +#define DEFAULT_DM_DEV_DIR "/dev" + /* FIXME Should be imported */ #ifndef DM_MAX_TYPE_NAME # define DM_MAX_TYPE_NAME 16 @@ -2549,14 +2551,12 @@ int main(int argc, char **argv) (void) setlocale(LC_ALL, ""); - dev_dir = getenv ("DM_DEVDIR"); + dev_dir = getenv ("DM_DEV_DIR"); if (dev_dir && *dev_dir) { - if (!dm_set_dev_dir(dev_dir)) { - fprintf(stderr, "Invalid DM_DEVDIR envvar value.\n"); + if (!dm_set_dev_dir(dev_dir)) goto out; - } } else { - dev_dir = "/dev"; + dev_dir = DEFAULT_DM_DEV_DIR; } if (!_process_switches(&argc, &argv, dev_dir)) { diff --git a/lib/libdm-common.c b/lib/libdm-common.c index c87903a..577bbd8 100644 --- a/lib/libdm-common.c +++ b/lib/libdm-common.c @@ -467,15 +467,20 @@ int dm_set_dev_dir(const char *dev_dir) { size_t len; const char *slash; - if (*dev_dir != '/') + if (*dev_dir != '/') { + log_error("Invalid dev_dir value, %s: " + "not an absolute name.", dev_dir); return 0; + } len = strlen(dev_dir); slash = dev_dir[len-1] == '/' ? "" : "/"; if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) - >= sizeof _dm_dir) + >= sizeof _dm_dir) { + log_error("Invalid dev_dir value, %s: name too long.", dev_dir); return 0; + } return 1; } ====================================================================== Allow $DM_DEV_DIR envvar to override default of "/dev". * dmsetup/dmsetup.c (DEV_PATH): Remove definition. (parse_loop_device_name): Add parameter: dev_dir. Declare the "dev" parameter to be "const". Use dev_dir, not DEV_PATH. Handle the case in which dev_dir does not end in a "/". (_get_abspath): Declare "path" parameter "const", to match. (_process_losetup_switches): Add parameter: dev_dir. Pass dev_dir to parse_loop_device_name. (_process_switches): Add parameter: dev_dir. Pass dev_dir to _process_losetup_switches. (main): Set dev_dir from the DM_DEV_DIR envvar, else to "/dev". Call dm_set_dev_dir. * lib/libdm-common.c (dm_set_dev_dir): Rewrite to be careful about boundary conditions, now that dev_dir may be tainted. Signed-off-by: Jim Meyering <meyering@redhat.com> --- dmsetup/dmsetup.c | 35 ++++++++++++++++++++++++++--------- lib/libdm-common.c | 20 ++++++++++++++++++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c index 562f628..6244959 100644 --- a/dmsetup/dmsetup.c +++ b/dmsetup/dmsetup.c @@ -90,6 +90,8 @@ extern char *optarg; #define ARGS_MAX 256 #define LOOP_TABLE_SIZE (PATH_MAX + 255) +#define DEFAULT_DM_DEV_DIR "/dev" + /* FIXME Should be imported */ #ifndef DM_MAX_TYPE_NAME # define DM_MAX_TYPE_NAME 16 @@ -97,7 +99,6 @@ extern char *optarg; /* FIXME Should be elsewhere */ #define SECTOR_SHIFT 9L -#define DEV_PATH "/dev/" #define err(msg, x...) fprintf(stderr, msg "\n", ##x) @@ -2129,7 +2130,7 @@ static int _process_tree_options(const char *options) * Returns the full absolute path, or NULL if the path could * not be resolved. */ -static char *_get_abspath(char *path) +static char *_get_abspath(const char *path) { char *_path; @@ -2141,7 +2142,7 @@ static char *_get_abspath(char *path) return _path; } -static char *parse_loop_device_name(char *dev) +static char *parse_loop_device_name(const char *dev, const char *dev_dir) { char *buf; char *device; @@ -2153,7 +2154,13 @@ static char *parse_loop_device_name(char *dev) if (!(device = _get_abspath(dev))) goto error; - if (strncmp(device, DEV_PATH, strlen(DEV_PATH))) + if (strncmp(device, dev_dir, strlen(dev_dir))) + goto error; + + /* If dev_dir does not end in a slash, ensure that the + following byte in the device string is "/". */ + if (dev_dir[strlen(dev_dir) - 1] != '/' + && device[strlen(dev_dir)] != '/') goto error; strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX); @@ -2234,7 +2241,8 @@ error: return 0; } -static int _process_losetup_switches(const char *base, int *argc, char ***argv) +static int _process_losetup_switches(const char *base, int *argc, char ***argv, + const char *dev_dir) { static int ind; int c; @@ -2297,7 +2305,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 0; } - if (!(device_name = parse_loop_device_name((*argv)[0]))) { + if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) { fprintf(stderr, "%s: Could not parse loop_device %s\n", base, (*argv)[0]); _losetup_usage(stderr); @@ -2344,7 +2352,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 1; } -static int _process_switches(int *argc, char ***argv) +static int _process_switches(int *argc, char ***argv, const char *dev_dir) { char *base, *namebase; static int ind; @@ -2422,7 +2430,7 @@ static int _process_switches(int *argc, char ***argv) } if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){ - r = _process_losetup_switches(base, argc, argv); + r = _process_losetup_switches(base, argc, argv, dev_dir); free(namebase); return r; } @@ -2539,10 +2547,19 @@ int main(int argc, char **argv) { struct command *c; int r = 1; + const char *dev_dir; (void) setlocale(LC_ALL, ""); - if (!_process_switches(&argc, &argv)) { + dev_dir = getenv ("DM_DEV_DIR"); + if (dev_dir && *dev_dir) { + if (!dm_set_dev_dir(dev_dir)) + goto out; + } else { + dev_dir = DEFAULT_DM_DEV_DIR; + } + + if (!_process_switches(&argc, &argv, dev_dir)) { fprintf(stderr, "Couldn't process command line.\n"); goto out; } diff --git a/lib/libdm-common.c b/lib/libdm-common.c index c8c3500..577bbd8 100644 --- a/lib/libdm-common.c +++ b/lib/libdm-common.c @@ -463,9 +463,25 @@ void update_devs(void) _pop_node_ops(); } -int dm_set_dev_dir(const char *dir) +int dm_set_dev_dir(const char *dev_dir) { - snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR); + size_t len; + const char *slash; + if (*dev_dir != '/') { + log_error("Invalid dev_dir value, %s: " + "not an absolute name.", dev_dir); + return 0; + } + + len = strlen(dev_dir); + slash = dev_dir[len-1] == '/' ? "" : "/"; + + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) + >= sizeof _dm_dir) { + log_error("Invalid dev_dir value, %s: name too long.", dev_dir); + return 0; + } + return 1; } -- 1.5.3.4.206.g58ba4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-09 11:43 ` Jim Meyering 0 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 11:43 UTC (permalink / raw) To: lvm-devel Alasdair G Kergon <agk@redhat.com> wrote: > On Mon, Oct 08, 2007 at 07:25:56PM +0200, Jim Meyering wrote: >> any existing LVM set-up, I've been using LVM_SYSTEM_DIR to specify > >> Here's a patch to make dmsetup honor a new DM_DEVDIR envvar, > > Small point, but should that be DM_DEV_DIR for consistency with > LVM_SYSTEM_DIR ? Yep. I prefer that, too. >> + } else { >> + dev_dir = "/dev"; > Can you make that a #define at the top of the file? Ok. >> + if (*dev_dir != '/') >> + return 0; > > log_error ? > (Functions should produce an error message as close as possible to the > place the problem is detected; all functions that return failure must > log a message before returning - using a macro like 'stack' if you don't > want the user to see it. The only exceptions (very rare) are functions > expected to fail frequently that would produce too many log messages.) > >> + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) >> + >= sizeof _dm_dir) >> + return 0; > > and here I can do that, but then the diagnostic can no longer say that the DM_DEV_DIR envvar is at fault. There is a slight advantage to diagnosing "too long" and "dir name is not absolute" separately, but nonetheless, I have a slight preference for being able to point directly to the DM_DEV_DIR envvar. With my original patch, I got this diagnostic: Invalid DM_DEVDIR envvar value. with the patch below, I get one of these Invalid dev_dir value, x: not an absolute name. Invalid dev_dir value, ...: name too long. > Also consider dm_snprintf rather than snprintf. > [lvm2 uses this, but bits of dm haven't been converted] Sounds like a good idea for a separate patch. There are many uses of snprintf. IMHO, it'd be best to change them all at once. Here's the incremental patch, then the full one: diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c index ca864b8..6244959 100644 --- a/dmsetup/dmsetup.c +++ b/dmsetup/dmsetup.c @@ -90,6 +90,8 @@ extern char *optarg; #define ARGS_MAX 256 #define LOOP_TABLE_SIZE (PATH_MAX + 255) +#define DEFAULT_DM_DEV_DIR "/dev" + /* FIXME Should be imported */ #ifndef DM_MAX_TYPE_NAME # define DM_MAX_TYPE_NAME 16 @@ -2549,14 +2551,12 @@ int main(int argc, char **argv) (void) setlocale(LC_ALL, ""); - dev_dir = getenv ("DM_DEVDIR"); + dev_dir = getenv ("DM_DEV_DIR"); if (dev_dir && *dev_dir) { - if (!dm_set_dev_dir(dev_dir)) { - fprintf(stderr, "Invalid DM_DEVDIR envvar value.\n"); + if (!dm_set_dev_dir(dev_dir)) goto out; - } } else { - dev_dir = "/dev"; + dev_dir = DEFAULT_DM_DEV_DIR; } if (!_process_switches(&argc, &argv, dev_dir)) { diff --git a/lib/libdm-common.c b/lib/libdm-common.c index c87903a..577bbd8 100644 --- a/lib/libdm-common.c +++ b/lib/libdm-common.c @@ -467,15 +467,20 @@ int dm_set_dev_dir(const char *dev_dir) { size_t len; const char *slash; - if (*dev_dir != '/') + if (*dev_dir != '/') { + log_error("Invalid dev_dir value, %s: " + "not an absolute name.", dev_dir); return 0; + } len = strlen(dev_dir); slash = dev_dir[len-1] == '/' ? "" : "/"; if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) - >= sizeof _dm_dir) + >= sizeof _dm_dir) { + log_error("Invalid dev_dir value, %s: name too long.", dev_dir); return 0; + } return 1; } ====================================================================== Allow $DM_DEV_DIR envvar to override default of "/dev". * dmsetup/dmsetup.c (DEV_PATH): Remove definition. (parse_loop_device_name): Add parameter: dev_dir. Declare the "dev" parameter to be "const". Use dev_dir, not DEV_PATH. Handle the case in which dev_dir does not end in a "/". (_get_abspath): Declare "path" parameter "const", to match. (_process_losetup_switches): Add parameter: dev_dir. Pass dev_dir to parse_loop_device_name. (_process_switches): Add parameter: dev_dir. Pass dev_dir to _process_losetup_switches. (main): Set dev_dir from the DM_DEV_DIR envvar, else to "/dev". Call dm_set_dev_dir. * lib/libdm-common.c (dm_set_dev_dir): Rewrite to be careful about boundary conditions, now that dev_dir may be tainted. Signed-off-by: Jim Meyering <meyering@redhat.com> --- dmsetup/dmsetup.c | 35 ++++++++++++++++++++++++++--------- lib/libdm-common.c | 20 ++++++++++++++++++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/dmsetup/dmsetup.c b/dmsetup/dmsetup.c index 562f628..6244959 100644 --- a/dmsetup/dmsetup.c +++ b/dmsetup/dmsetup.c @@ -90,6 +90,8 @@ extern char *optarg; #define ARGS_MAX 256 #define LOOP_TABLE_SIZE (PATH_MAX + 255) +#define DEFAULT_DM_DEV_DIR "/dev" + /* FIXME Should be imported */ #ifndef DM_MAX_TYPE_NAME # define DM_MAX_TYPE_NAME 16 @@ -97,7 +99,6 @@ extern char *optarg; /* FIXME Should be elsewhere */ #define SECTOR_SHIFT 9L -#define DEV_PATH "/dev/" #define err(msg, x...) fprintf(stderr, msg "\n", ##x) @@ -2129,7 +2130,7 @@ static int _process_tree_options(const char *options) * Returns the full absolute path, or NULL if the path could * not be resolved. */ -static char *_get_abspath(char *path) +static char *_get_abspath(const char *path) { char *_path; @@ -2141,7 +2142,7 @@ static char *_get_abspath(char *path) return _path; } -static char *parse_loop_device_name(char *dev) +static char *parse_loop_device_name(const char *dev, const char *dev_dir) { char *buf; char *device; @@ -2153,7 +2154,13 @@ static char *parse_loop_device_name(char *dev) if (!(device = _get_abspath(dev))) goto error; - if (strncmp(device, DEV_PATH, strlen(DEV_PATH))) + if (strncmp(device, dev_dir, strlen(dev_dir))) + goto error; + + /* If dev_dir does not end in a slash, ensure that the + following byte in the device string is "/". */ + if (dev_dir[strlen(dev_dir) - 1] != '/' + && device[strlen(dev_dir)] != '/') goto error; strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX); @@ -2234,7 +2241,8 @@ error: return 0; } -static int _process_losetup_switches(const char *base, int *argc, char ***argv) +static int _process_losetup_switches(const char *base, int *argc, char ***argv, + const char *dev_dir) { static int ind; int c; @@ -2297,7 +2305,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 0; } - if (!(device_name = parse_loop_device_name((*argv)[0]))) { + if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) { fprintf(stderr, "%s: Could not parse loop_device %s\n", base, (*argv)[0]); _losetup_usage(stderr); @@ -2344,7 +2352,7 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv) return 1; } -static int _process_switches(int *argc, char ***argv) +static int _process_switches(int *argc, char ***argv, const char *dev_dir) { char *base, *namebase; static int ind; @@ -2422,7 +2430,7 @@ static int _process_switches(int *argc, char ***argv) } if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){ - r = _process_losetup_switches(base, argc, argv); + r = _process_losetup_switches(base, argc, argv, dev_dir); free(namebase); return r; } @@ -2539,10 +2547,19 @@ int main(int argc, char **argv) { struct command *c; int r = 1; + const char *dev_dir; (void) setlocale(LC_ALL, ""); - if (!_process_switches(&argc, &argv)) { + dev_dir = getenv ("DM_DEV_DIR"); + if (dev_dir && *dev_dir) { + if (!dm_set_dev_dir(dev_dir)) + goto out; + } else { + dev_dir = DEFAULT_DM_DEV_DIR; + } + + if (!_process_switches(&argc, &argv, dev_dir)) { fprintf(stderr, "Couldn't process command line.\n"); goto out; } diff --git a/lib/libdm-common.c b/lib/libdm-common.c index c8c3500..577bbd8 100644 --- a/lib/libdm-common.c +++ b/lib/libdm-common.c @@ -463,9 +463,25 @@ void update_devs(void) _pop_node_ops(); } -int dm_set_dev_dir(const char *dir) +int dm_set_dev_dir(const char *dev_dir) { - snprintf(_dm_dir, sizeof(_dm_dir), "%s%s", dir, DM_DIR); + size_t len; + const char *slash; + if (*dev_dir != '/') { + log_error("Invalid dev_dir value, %s: " + "not an absolute name.", dev_dir); + return 0; + } + + len = strlen(dev_dir); + slash = dev_dir[len-1] == '/' ? "" : "/"; + + if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR) + >= sizeof _dm_dir) { + log_error("Invalid dev_dir value, %s: name too long.", dev_dir); + return 0; + } + return 1; } -- 1.5.3.4.206.g58ba4 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". 2007-10-09 11:43 ` Jim Meyering @ 2007-10-09 11:56 ` Alasdair G Kergon -1 siblings, 0 replies; 12+ messages in thread From: Alasdair G Kergon @ 2007-10-09 11:56 UTC (permalink / raw) To: Jim Meyering; +Cc: device-mapper development, LVM On Tue, Oct 09, 2007 at 01:43:22PM +0200, Jim Meyering wrote: > I can do that, but then the diagnostic can no longer say that > the DM_DEV_DIR envvar is at fault. Then do the 'stack' or 'return_0' macro thing - or log the detailed error with log_debug so people will normally just see the 'clean' error. Alasdair -- agk@redhat.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-09 11:56 ` Alasdair G Kergon 0 siblings, 0 replies; 12+ messages in thread From: Alasdair G Kergon @ 2007-10-09 11:56 UTC (permalink / raw) To: lvm-devel On Tue, Oct 09, 2007 at 01:43:22PM +0200, Jim Meyering wrote: > I can do that, but then the diagnostic can no longer say that > the DM_DEV_DIR envvar is at fault. Then do the 'stack' or 'return_0' macro thing - or log the detailed error with log_debug so people will normally just see the 'clean' error. Alasdair -- agk at redhat.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". 2007-10-09 2:00 ` Alasdair G Kergon @ 2007-10-09 11:54 ` Jim Meyering -1 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 11:54 UTC (permalink / raw) To: device-mapper development, Alasdair G. Kergon; +Cc: LVM BTW, here's a proposed update for the man page: diff --git a/man/dmsetup.8 b/man/dmsetup.8 index 5b2ed9f..74a5f1b 100644 --- a/man/dmsetup.8 +++ b/man/dmsetup.8 @@ -341,6 +341,11 @@ for creating devices with holes in them. .br 2056320 2875602 linear /dev/hdb 1028160 +.SH FILES +These commands normally operate on files in \fB/dev\fP. +However, if you set the DM_DEV_DIR environment variable to some +other absolute directory name, they will use it instead. + .SH AUTHORS Original version: Joe Thornber (thornber@sistina.com) ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-09 11:54 ` Jim Meyering 0 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 11:54 UTC (permalink / raw) To: lvm-devel BTW, here's a proposed update for the man page: diff --git a/man/dmsetup.8 b/man/dmsetup.8 index 5b2ed9f..74a5f1b 100644 --- a/man/dmsetup.8 +++ b/man/dmsetup.8 @@ -341,6 +341,11 @@ for creating devices with holes in them. .br 2056320 2875602 linear /dev/hdb 1028160 +.SH FILES +These commands normally operate on files in \fB/dev\fP. +However, if you set the DM_DEV_DIR environment variable to some +other absolute directory name, they will use it instead. + .SH AUTHORS Original version: Joe Thornber (thornber at sistina.com) ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". 2007-10-09 11:54 ` Jim Meyering @ 2007-10-09 12:04 ` Jim Meyering -1 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 12:04 UTC (permalink / raw) To: device-mapper development; +Cc: Alasdair G. Kergon, LVM Jim Meyering <jim@meyering.net> wrote: > BTW, here's a proposed update for the man page: > > diff --git a/man/dmsetup.8 b/man/dmsetup.8 > index 5b2ed9f..74a5f1b 100644 > --- a/man/dmsetup.8 > +++ b/man/dmsetup.8 > @@ -341,6 +341,11 @@ for creating devices with holes in them. > .br > 2056320 2875602 linear /dev/hdb 1028160 > > +.SH FILES > +These commands normally operate on files in \fB/dev\fP. > +However, if you set the DM_DEV_DIR environment variable to some > +other absolute directory name, they will use it instead. I'm redoing it like LVM_SYSTEM_DIR in lvm.8. ^ permalink raw reply [flat|nested] 12+ messages in thread
* [dm-devel] Re: [lvm-devel] Allow $DM_DEVDIR envvar to override default of "/dev". @ 2007-10-09 12:04 ` Jim Meyering 0 siblings, 0 replies; 12+ messages in thread From: Jim Meyering @ 2007-10-09 12:04 UTC (permalink / raw) To: lvm-devel Jim Meyering <jim@meyering.net> wrote: > BTW, here's a proposed update for the man page: > > diff --git a/man/dmsetup.8 b/man/dmsetup.8 > index 5b2ed9f..74a5f1b 100644 > --- a/man/dmsetup.8 > +++ b/man/dmsetup.8 > @@ -341,6 +341,11 @@ for creating devices with holes in them. > .br > 2056320 2875602 linear /dev/hdb 1028160 > > +.SH FILES > +These commands normally operate on files in \fB/dev\fP. > +However, if you set the DM_DEV_DIR environment variable to some > +other absolute directory name, they will use it instead. I'm redoing it like LVM_SYSTEM_DIR in lvm.8. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2007-10-09 12:04 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-10-08 17:25 Allow $DM_DEVDIR envvar to override default of "/dev" Jim Meyering 2007-10-08 17:25 ` Jim Meyering 2007-10-09 2:00 ` [lvm-devel] " Alasdair G Kergon 2007-10-09 2:00 ` Alasdair G Kergon 2007-10-09 11:43 ` [lvm-devel] " Jim Meyering 2007-10-09 11:43 ` Jim Meyering 2007-10-09 11:56 ` [lvm-devel] " Alasdair G Kergon 2007-10-09 11:56 ` Alasdair G Kergon 2007-10-09 11:54 ` [lvm-devel] " Jim Meyering 2007-10-09 11:54 ` Jim Meyering 2007-10-09 12:04 ` Re: [lvm-devel] " Jim Meyering 2007-10-09 12:04 ` [dm-devel] " Jim Meyering
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.