[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ftw must *not* strip trailing slashes
From: |
Jim Meyering |
Subject: |
ftw must *not* strip trailing slashes |
Date: |
Sat, 25 Jan 2003 21:32:08 +0100 |
Currently, ftw and nftw strip trailing slashes.
Isn't that contrary to POSIX? In the section on pathname resolution,
it says that a symlink to a directory that is specified with a trailing
slash must be treated as if `.' were appended.
Accordingly, these commands
mkdir -p d/x
ln -s d slink
a.out slink/
should produce output like this:
slink/
slink/x
given that a.out calls nftw/FTW_PHYS|FTW_CHDIR with its command line
argument and the callback simply prints the name of each file.
Without the following change, the program prints only `slink'.
I don't see a simple patch to give the desired behavior,
but using the base_name function (e.g. from coreutils or gnulib),
it's easy:
2003-01-25 Jim Meyering <address@hidden>
* ftw.c [_LIBC] (ISSLASH, FILESYSTEM_PREFIX_LEN): Define.
(base_name): New function.
(ftw_startup): Don't strip trailing slashes.
Use base_name to find the offset of the basename.
Index: ftw.c
===================================================================
RCS file: /fetish/cu/lib/ftw.c,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 ftw.c
--- ftw.c 25 Jan 2003 16:44:07 -0000 1.10
+++ ftw.c 25 Jan 2003 18:17:03 -0000
@@ -561,6 +561,51 @@ ftw_dir (struct ftw_data *data, struct S
}
+#ifdef _LIBC
+# define ISSLASH(C) ((C) == '/')
+# define FILESYSTEM_PREFIX_LEN(Filename) 0
+#endif
+
+/* 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 address of the last file name component of NAME. If
+ NAME has no file name components because it is all slashes, return
+ NAME if it is empty, the address of its last slash otherwise. */
+
+static char *
+base_name (char const *name)
+{
+ char const *base = name + FILESYSTEM_PREFIX_LEN (name);
+ char const *p;
+
+ for (p = base; *p; p++)
+ {
+ if (ISSLASH (*p))
+ {
+ /* Treat multiple adjacent slashes like a single slash. */
+ do p++;
+ while (ISSLASH (*p));
+
+ /* If the file name ends in slash, use the trailing slash as
+ the basename if no non-slashes have been found. */
+ if (! *p)
+ {
+ if (ISSLASH (*base))
+ base = p - 1;
+ break;
+ }
+
+ /* *P is a non-slash preceded by a slash. */
+ base = p;
+ }
+ }
+
+ return (char *) base;
+}
+
+
static int
internal_function
ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
@@ -571,7 +616,7 @@ ftw_startup (const char *dir, int is_nft
int result = 0;
int save_err;
char *cwd = NULL;
- char *cp;
+ size_t dir_len;
/* First make sure the parameters are reasonable. */
if (dir[0] == '\0')
@@ -586,26 +631,21 @@ ftw_startup (const char *dir, int is_nft
* sizeof (struct dir_data *));
memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
+ dir_len = strlen (dir);
#ifdef PATH_MAX
- data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
+ data.dirbufsize = MAX (2 * dir_len, PATH_MAX);
#else
- data.dirbufsize = 2 * strlen (dir);
+ data.dirbufsize = 2 * dir_len;
#endif
data.dirbuf = (char *) malloc (data.dirbufsize);
if (data.dirbuf == NULL)
return -1;
- cp = __stpcpy (data.dirbuf, dir);
- /* Strip trailing slashes. */
- while (cp > data.dirbuf + 1 && cp[-1] == '/')
- --cp;
- *cp = '\0';
+ memcpy (data.dirbuf, dir, dir_len + 1);
data.ftw.level = 0;
- /* Find basename. */
- while (cp > data.dirbuf && cp[-1] != '/')
- --cp;
- data.ftw.base = cp - data.dirbuf;
+ /* Find offset of basename. */
+ data.ftw.base = base_name (data.dirbuf) - data.dirbuf;
data.flags = flags;
pgpZmltFSAj5j.pgp
Description: PGP signature
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- ftw must *not* strip trailing slashes,
Jim Meyering <=