From 48e0ba6d23bdc0fcad1b620cb410bb0a57684edc Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 29 Oct 2009 10:43:31 -0600 Subject: [PATCH] dirname: split into dirname-lgpl dirname.h is proving quite useful from multiple LGPL modules, given the number of trailing slash bugs fixed in syscalls; only the calls to xalloc_die need to remain GPL. * modules/dirname-lgpl: New module. * modules/dirname (Files): Move library-safe files into dirname-lgpl. (Depends-on): Add dirname-lgpl. (configure.ac): Declare witness. * modules/double-slash-root (License): Relax license. * lib/dirname.h (base_name, dir_name): Only declare when using GPL module. * lib/dirname.c (dir_len, mdir_name): Move... * lib/dirname-lgpl.c: ...into new file. * lib/basename.c (last_component, base_len): Move... * lib/basename-lgpl.c: ...into new file. * m4/dirname.m4 (gl_DIRNAME_LGPL): New macro. (gl_DIRNAME): Use it. * MODULES.html.sh (Enhancements for POSIX:2008 functions): Mention new module. * modules/dirname-tests (Depends-on): Add progname. * tests/test-dirname.c (program_name): Delete. Signed-off-by: Eric Blake --- ChangeLog | 20 +++++++++ MODULES.html.sh | 1 + lib/basename-lgpl.c | 75 ++++++++++++++++++++++++++++++++++ lib/basename.c | 74 +-------------------------------- lib/dirname-lgpl.c | 86 +++++++++++++++++++++++++++++++++++++++ lib/dirname.c | 64 +---------------------------- lib/dirname.h | 5 ++- m4/dirname.m4 | 14 +++++-- modules/dirname | 9 ++-- modules/dirname-lgpl | 29 +++++++++++++ modules/dirname-tests | 1 + modules/double-slash-root | 2 +- tests/test-dirname.c | 2 - 13 files changed, 234 insertions(+), 148 deletions(-) create mode 100644 lib/basename-lgpl.c create mode 100644 lib/dirname-lgpl.c create mode 100644 modules/dirname-lgpl diff --git a/ChangeLog b/ChangeLog index 27528cb958..26a0abf57f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2009-10-29 Eric Blake + dirname: split into dirname-lgpl + * modules/dirname-lgpl: New module. + * modules/dirname (Files): Move library-safe files into + dirname-lgpl. + (Depends-on): Add dirname-lgpl. + (configure.ac): Declare witness. + * modules/double-slash-root (License): Relax license. + * lib/dirname.h (base_name, dir_name): Only declare when using GPL + module. + * lib/dirname.c (dir_len, mdir_name): Move... + * lib/dirname-lgpl.c: ...into new file. + * lib/basename.c (last_component, base_len): Move... + * lib/basename-lgpl.c: ...into new file. + * m4/dirname.m4 (gl_DIRNAME_LGPL): New macro. + (gl_DIRNAME): Use it. + * MODULES.html.sh (Enhancements for POSIX:2008 functions): + Mention new module. + * modules/dirname-tests (Depends-on): Add progname. + * tests/test-dirname.c (program_name): Delete. + mkdir: make safe for libraries * modules/mkdir (Depends-on): Drop xalloc. * lib/mkdir.c (rpl_mkdir): Fail with ENOMEM rather than calling diff --git a/MODULES.html.sh b/MODULES.html.sh index 62abf0f6e4..d8677e0ef9 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2404,6 +2404,7 @@ func_all_modules () func_module chdir-long func_module dirent-safer func_module dirname + func_module dirname-lgpl func_module getopt func_module iconv_open-utf func_module unistd-safer diff --git a/lib/basename-lgpl.c b/lib/basename-lgpl.c new file mode 100644 index 0000000000..444f042650 --- /dev/null +++ b/lib/basename-lgpl.c @@ -0,0 +1,75 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, + 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include + +/* Return the address of the last file name component of NAME. If + NAME has no relative file name components because it is a file + system root, return the empty string. */ + +char * +last_component (char const *name) +{ + char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); + char const *p; + bool saw_slash = false; + + while (ISSLASH (*base)) + base++; + + for (p = base; *p; p++) + { + if (ISSLASH (*p)) + saw_slash = true; + else if (saw_slash) + { + base = p; + saw_slash = false; + } + } + + return (char *) base; +} + +/* Return the length of the basename NAME. Typically NAME is the + value returned by base_name or last_component. Act like strlen + (NAME), except omit all trailing slashes. */ + +size_t +base_len (char const *name) +{ + size_t len; + size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) + continue; + + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 + && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) + return 2; + + if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len + && len == prefix_len && ISSLASH (name[prefix_len])) + return prefix_len + 1; + + return len; +} diff --git a/lib/basename.c b/lib/basename.c index 426ed40f1a..a6403f55f7 100644 --- a/lib/basename.c +++ b/lib/basename.c @@ -1,7 +1,7 @@ /* basename.c -- return the last element in a file name - Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free - Software Foundation, Inc. + Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, + 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,52 +24,6 @@ #include "xalloc.h" #include "xstrndup.h" -/* Return the address of the last file name component of NAME. If - NAME has no relative file name components because it is a file - system root, return the empty string. */ - -char * -last_component (char const *name) -{ - char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); - char const *p; - bool saw_slash = false; - - while (ISSLASH (*base)) - base++; - - for (p = base; *p; p++) - { - if (ISSLASH (*p)) - saw_slash = true; - else if (saw_slash) - { - base = p; - saw_slash = false; - } - } - - return (char *) base; -} - - -/* In general, we can't use the builtin `basename' function if available, - since it has different meanings in different environments. - In some environments the builtin `basename' modifies its argument. - - Return the last file name component of NAME, allocated with - xmalloc. On systems with drive letters, a leading "./" - distinguishes relative names that would otherwise look like a drive - letter. Unlike POSIX basename(), NAME cannot be NULL, - base_name("") returns "", and the first trailing slash is not - stripped. - - If lstat (NAME) would succeed, then { chdir (dir_name (NAME)); - lstat (base_name (NAME)); } will access the same file. Likewise, - if the sequence { chdir (dir_name (NAME)); - rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME - to "foo" in the same directory NAME was in. */ - char * base_name (char const *name) { @@ -102,27 +56,3 @@ base_name (char const *name) /* Finally, copy the basename. */ return xstrndup (base, length); } - -/* Return the length of the basename NAME. Typically NAME is the - value returned by base_name or last_component. Act like strlen - (NAME), except omit all trailing slashes. */ - -size_t -base_len (char const *name) -{ - size_t len; - size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); - - for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) - continue; - - if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 - && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) - return 2; - - if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len - && len == prefix_len && ISSLASH (name[prefix_len])) - return prefix_len + 1; - - return len; -} diff --git a/lib/dirname-lgpl.c b/lib/dirname-lgpl.c new file mode 100644 index 0000000000..79ee0b5fba --- /dev/null +++ b/lib/dirname-lgpl.c @@ -0,0 +1,86 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006, 2009 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include +#include + +/* Return the length of the prefix of FILE that will be used by + dir_name. If FILE is in the working directory, this returns zero + even though `dir_name (FILE)' will return ".". Works properly even + if there are trailing slashes (by effectively ignoring them). */ + +size_t +dir_len (char const *file) +{ + size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); + size_t length; + + /* Advance prefix_length beyond important leading slashes. */ + prefix_length += (prefix_length != 0 + ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && ISSLASH (file[prefix_length])) + : (ISSLASH (file[0]) + ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT + && ISSLASH (file[1]) && ! ISSLASH (file[2]) + ? 2 : 1)) + : 0)); + + /* Strip the basename and any redundant slashes before it. */ + for (length = last_component (file) - file; + prefix_length < length; length--) + if (! ISSLASH (file[length - 1])) + break; + return length; +} + + +/* In general, we can't use the builtin `dirname' function if available, + since it has different meanings in different environments. + In some environments the builtin `dirname' modifies its argument. + + Return the leading directories part of FILE, allocated with malloc. + Works properly even if there are trailing slashes (by effectively + ignoring them). Return NULL on failure. + + If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); + lstat (base_name (FILE)); } will access the same file. Likewise, + if the sequence { chdir (dir_name (FILE)); + rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE + to "foo" in the same directory FILE was in. */ + +char * +mdir_name (char const *file) +{ + size_t length = dir_len (file); + bool append_dot = (length == 0 + || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && length == FILE_SYSTEM_PREFIX_LEN (file) + && file[2] != '\0' && ! ISSLASH (file[2]))); + char *dir = malloc (length + append_dot + 1); + if (!dir) + return NULL; + memcpy (dir, file, length); + if (append_dot) + dir[length++] = '.'; + dir[length] = '\0'; + return dir; +} diff --git a/lib/dirname.c b/lib/dirname.c index 20dcaf5b87..d032270a87 100644 --- a/lib/dirname.c +++ b/lib/dirname.c @@ -24,69 +24,7 @@ #include #include "xalloc.h" -/* Return the length of the prefix of FILE that will be used by - dir_name. If FILE is in the working directory, this returns zero - even though `dir_name (FILE)' will return ".". Works properly even - if there are trailing slashes (by effectively ignoring them). */ - -size_t -dir_len (char const *file) -{ - size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); - size_t length; - - /* Advance prefix_length beyond important leading slashes. */ - prefix_length += (prefix_length != 0 - ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && ISSLASH (file[prefix_length])) - : (ISSLASH (file[0]) - ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT - && ISSLASH (file[1]) && ! ISSLASH (file[2]) - ? 2 : 1)) - : 0)); - - /* Strip the basename and any redundant slashes before it. */ - for (length = last_component (file) - file; - prefix_length < length; length--) - if (! ISSLASH (file[length - 1])) - break; - return length; -} - - -/* In general, we can't use the builtin `dirname' function if available, - since it has different meanings in different environments. - In some environments the builtin `dirname' modifies its argument. - - Return the leading directories part of FILE, allocated with malloc. - Works properly even if there are trailing slashes (by effectively - ignoring them). Return NULL on failure. - - If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); - lstat (base_name (FILE)); } will access the same file. Likewise, - if the sequence { chdir (dir_name (FILE)); - rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE - to "foo" in the same directory FILE was in. */ - -char * -mdir_name (char const *file) -{ - size_t length = dir_len (file); - bool append_dot = (length == 0 - || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && length == FILE_SYSTEM_PREFIX_LEN (file) - && file[2] != '\0' && ! ISSLASH (file[2]))); - char *dir = malloc (length + append_dot + 1); - if (!dir) - return NULL; - memcpy (dir, file, length); - if (append_dot) - dir[length++] = '.'; - dir[length] = '\0'; - return dir; -} - -/* Just like mdir_name, above, except, rather than +/* Just like mdir_name (dirname-lgpl.c), except, rather than returning NULL upon malloc failure, here, we report the "memory exhausted" condition and exit. */ diff --git a/lib/dirname.h b/lib/dirname.h index 90a1f0c2c1..df12ccaaa3 100644 --- a/lib/dirname.h +++ b/lib/dirname.h @@ -58,9 +58,12 @@ # endif # define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) +# if GNULIB_DIRNAME char *base_name (char const *file); -char *mdir_name (char const *file); char *dir_name (char const *file); +# endif + +char *mdir_name (char const *file); size_t base_len (char const *file); size_t dir_len (char const *file); char *last_component (char const *file); diff --git a/m4/dirname.m4 b/m4/dirname.m4 index e35da96582..4252b62e3a 100644 --- a/m4/dirname.m4 +++ b/m4/dirname.m4 @@ -1,18 +1,26 @@ -#serial 7 -*- autoconf -*- -dnl Copyright (C) 2002-2006 Free Software Foundation, Inc. +#serial 8 -*- autoconf -*- +dnl Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_DIRNAME], [ + AC_REQUIRE([gl_DIRNAME_LGPL]) AC_LIBOBJ([basename]) AC_LIBOBJ([dirname]) +]) + +AC_DEFUN([gl_DIRNAME_LGPL], +[ + AC_LIBOBJ([basename-lgpl]) + AC_LIBOBJ([dirname-lgpl]) AC_LIBOBJ([stripslash]) dnl Prerequisites of lib/dirname.h. AC_REQUIRE([gl_AC_DOS]) AC_REQUIRE([gl_DOUBLE_SLASH_ROOT]) - dnl No prerequisites of lib/basename.c, lib/dirname.c, lib/stripslash.c. + dnl No prerequisites of lib/basename-lgpl.c, lib/dirname-lgpl.c, + dnl lib/stripslash.c. ]) diff --git a/modules/dirname b/modules/dirname index 7c405c2855..888c8bad48 100644 --- a/modules/dirname +++ b/modules/dirname @@ -2,21 +2,18 @@ Description: Extract specific portions of filenames. Files: -lib/dirname.h lib/dirname.c lib/basename.c lib/stripslash.c -m4/dirname.m4 -m4/dos.m4 Depends-on: -double-slash-root -stdbool +dirname-lgpl xalloc xstrndup configure.ac: gl_DIRNAME +gl_MODULE_INDICATOR([dirname]) Makefile.am: @@ -27,4 +24,4 @@ License: GPL Maintainer: -Jim Meyering +Jim Meyering, Eric Blake diff --git a/modules/dirname-lgpl b/modules/dirname-lgpl new file mode 100644 index 0000000000..38f779abde --- /dev/null +++ b/modules/dirname-lgpl @@ -0,0 +1,29 @@ +Description: +Extract specific portions of filenames. + +Files: +lib/dirname.h +lib/dirname-lgpl.c +lib/basename-lgpl.c +lib/stripslash.c +m4/dirname.m4 +m4/dos.m4 + +Depends-on: +double-slash-root +malloc-posix +stdbool + +configure.ac: +gl_DIRNAME_LGPL + +Makefile.am: + +Include: +"dirname.h" + +License: +LGPLv2+ + +Maintainer: +Jim Meyering, Eric Blake diff --git a/modules/dirname-tests b/modules/dirname-tests index e2e86e658f..49eeb596dd 100644 --- a/modules/dirname-tests +++ b/modules/dirname-tests @@ -2,6 +2,7 @@ Files: tests/test-dirname.c Depends-on: +progname strdup configure.ac: diff --git a/modules/double-slash-root b/modules/double-slash-root index 6b809d067c..af78f2681c 100644 --- a/modules/double-slash-root +++ b/modules/double-slash-root @@ -14,7 +14,7 @@ Makefile.am: Include: License: -LGPL +LGPLv2+ Maintainer: Eric Blake, Paul Eggert, Jim Meyering diff --git a/tests/test-dirname.c b/tests/test-dirname.c index bd75020151..debda3f1c9 100644 --- a/tests/test-dirname.c +++ b/tests/test-dirname.c @@ -23,8 +23,6 @@ #include #include -const char *program_name = "test-dirname"; - struct test { const char *name; /* Name under test. */ const char *dir; /* dir_name (name). */ -- 2.30.2