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 | } |