summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-01-25 20:32:44 +0000
committerJim Meyering <jim@meyering.net>2003-01-25 20:32:44 +0000
commit91b31aa87c972e6fe51b369c4b7fa210e736e7ee (patch)
treeb8ddfc8f6aac56b1d69646d3b4096f91d41624a3
parent431d1b624180925a9be02590d4c5af845b8e2fce (diff)
downloadcoreutils-91b31aa87c972e6fe51b369c4b7fa210e736e7ee.tar.xz
[_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.
-rw-r--r--lib/ftw.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/lib/ftw.c b/lib/ftw.c
index 238691063..ccbb71a05 100644
--- a/lib/ftw.c
+++ b/lib/ftw.c
@@ -561,6 +561,51 @@ ftw_dir (struct ftw_data *data, struct STAT *st)
}
+#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_nftw, void *func, int descriptors,
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_nftw, void *func, int descriptors,
* 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;