diff options
Diffstat (limited to 'gl/dirname.c')
| -rw-r--r-- | gl/dirname.c | 64 |
1 files changed, 9 insertions, 55 deletions
diff --git a/gl/dirname.c b/gl/dirname.c index c27e5b5d..953a9acc 100644 --- a/gl/dirname.c +++ b/gl/dirname.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* dirname.c -- return all but the last element in a file name | 1 | /* dirname.c -- return all but the last element in a file name |
| 2 | 2 | ||
| 3 | Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software | 3 | Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software |
| 4 | Foundation, Inc. | 4 | Foundation, Inc. |
| 5 | 5 | ||
| 6 | This program is free software: you can redistribute it and/or modify | 6 | This program is free software: you can redistribute it and/or modify |
| @@ -20,65 +20,19 @@ | |||
| 20 | 20 | ||
| 21 | #include "dirname.h" | 21 | #include "dirname.h" |
| 22 | 22 | ||
| 23 | #include <stdlib.h> | ||
| 23 | #include <string.h> | 24 | #include <string.h> |
| 24 | #include "xalloc.h" | 25 | #include "xalloc.h" |
| 25 | 26 | ||
| 26 | /* Return the length of the prefix of FILE that will be used by | 27 | /* Just like mdir_name (dirname-lgpl.c), except, rather than |
| 27 | dir_name. If FILE is in the working directory, this returns zero | 28 | returning NULL upon malloc failure, here, we report the |
| 28 | even though `dir_name (FILE)' will return ".". Works properly even | 29 | "memory exhausted" condition and exit. */ |
| 29 | if there are trailing slashes (by effectively ignoring them). */ | ||
| 30 | |||
| 31 | size_t | ||
| 32 | dir_len (char const *file) | ||
| 33 | { | ||
| 34 | size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); | ||
| 35 | size_t length; | ||
| 36 | |||
| 37 | /* Advance prefix_length beyond important leading slashes. */ | ||
| 38 | prefix_length += (prefix_length != 0 | ||
| 39 | ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE | ||
| 40 | && ISSLASH (file[prefix_length])) | ||
| 41 | : (ISSLASH (file[0]) | ||
| 42 | ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT | ||
| 43 | && ISSLASH (file[1]) && ! ISSLASH (file[2]) | ||
| 44 | ? 2 : 1)) | ||
| 45 | : 0)); | ||
| 46 | |||
| 47 | /* Strip the basename and any redundant slashes before it. */ | ||
| 48 | for (length = last_component (file) - file; | ||
| 49 | prefix_length < length; length--) | ||
| 50 | if (! ISSLASH (file[length - 1])) | ||
| 51 | break; | ||
| 52 | return length; | ||
| 53 | } | ||
| 54 | |||
| 55 | |||
| 56 | /* In general, we can't use the builtin `dirname' function if available, | ||
| 57 | since it has different meanings in different environments. | ||
| 58 | In some environments the builtin `dirname' modifies its argument. | ||
| 59 | |||
| 60 | Return the leading directories part of FILE, allocated with xmalloc. | ||
| 61 | Works properly even if there are trailing slashes (by effectively | ||
| 62 | ignoring them). Unlike POSIX dirname(), FILE cannot be NULL. | ||
| 63 | |||
| 64 | If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); | ||
| 65 | lstat (base_name (FILE)); } will access the same file. Likewise, | ||
| 66 | if the sequence { chdir (dir_name (FILE)); | ||
| 67 | rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE | ||
| 68 | to "foo" in the same directory FILE was in. */ | ||
| 69 | 30 | ||
| 70 | char * | 31 | char * |
| 71 | dir_name (char const *file) | 32 | dir_name (char const *file) |
| 72 | { | 33 | { |
| 73 | size_t length = dir_len (file); | 34 | char *result = mdir_name (file); |
| 74 | bool append_dot = (length == 0 | 35 | if (!result) |
| 75 | || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE | 36 | xalloc_die (); |
| 76 | && length == FILE_SYSTEM_PREFIX_LEN (file) | 37 | return result; |
| 77 | && file[2] != '\0' && ! ISSLASH (file[2]))); | ||
| 78 | char *dir = xmalloc (length + append_dot + 1); | ||
| 79 | memcpy (dir, file, length); | ||
| 80 | if (append_dot) | ||
| 81 | dir[length++] = '.'; | ||
| 82 | dir[length] = '\0'; | ||
| 83 | return dir; | ||
| 84 | } | 38 | } |
