7 /* split pathname into last component and parent directory
9 /* #include <stringops.h>
11 /* char *sane_basename(buf, path)
15 /* char *sane_dirname(buf, path)
19 /* These functions split a pathname into its last component
20 /* and its parent directory, excluding any trailing "/"
21 /* characters from the input. The result is a pointer to "/"
22 /* when the input is all "/" characters, or a pointer to "."
23 /* when the input is a null pointer or zero-length string.
25 /* sane_basename() and sane_dirname() differ as follows
26 /* from standard basename() and dirname() implementations:
28 /* They can use caller-provided storage or private storage.
30 /* They never modify their input.
32 /* sane_basename() returns a pointer to string with the last
33 /* pathname component.
35 /* sane_dirname() returns a pointer to string with the parent
36 /* directory. The result is a pointer to "." when the input
37 /* contains no '/' character.
41 /* Result storage. If a null pointer is specified, each function
42 /* uses its own private memory that is overwritten upon each call.
44 /* The input pathname.
48 /* The Secure Mailer license must be distributed with this
52 /* IBM T.J. Watson Research
54 /* Yorktown Heights, NY 10598, USA
62 /* Utility library. */
65 #include <stringops.h>
67 #define STR(x) vstring_str(x)
69 /* sane_basename - skip directory prefix */
71 char *sane_basename(VSTRING
*bp
, const char *path
)
78 * Your buffer or mine?
83 bp
= buf
= vstring_alloc(10);
87 * Special case: return "." for null or zero-length input.
89 if (path
== 0 || *path
== 0)
90 return (STR(vstring_strcpy(bp
, ".")));
93 * Remove trailing '/' characters from input. Return "/" if input is all
96 last
= path
+ strlen(path
) - 1;
97 while (*last
== '/') {
99 return (STR(vstring_strcpy(bp
, "/")));
104 * The pathname does not end in '/'. Skip to last '/' character if any.
107 while (first
>= path
&& *first
!= '/')
110 return (STR(vstring_strncpy(bp
, first
+ 1, last
- first
)));
113 /* sane_dirname - keep directory prefix */
115 char *sane_dirname(VSTRING
*bp
, const char *path
)
121 * Your buffer or mine?
126 bp
= buf
= vstring_alloc(10);
130 * Special case: return "." for null or zero-length input.
132 if (path
== 0 || *path
== 0)
133 return (STR(vstring_strcpy(bp
, ".")));
136 * Remove trailing '/' characters from input. Return "/" if input is all
139 last
= path
+ strlen(path
) - 1;
140 while (*last
== '/') {
142 return (STR(vstring_strcpy(bp
, "/")));
147 * This pathname does not end in '/'. Skip to last '/' character if any.
149 while (last
>= path
&& *last
!= '/')
151 if (last
< path
) /* no '/' */
152 return (STR(vstring_strcpy(bp
, ".")));
155 * Strip trailing '/' characters from dirname (not strictly needed).
157 while (last
> path
&& *last
== '/')
160 return (STR(vstring_strncpy(bp
, path
, last
- path
+ 1)));
164 #include <vstring_vstream.h>
166 int main(int argc
, char **argv
)
168 VSTRING
*buf
= vstring_alloc(10);
172 while (vstring_get_nonl(buf
, VSTREAM_IN
) > 0) {
173 dir
= sane_dirname((VSTRING
*) 0, STR(buf
));
174 base
= sane_basename((VSTRING
*) 0, STR(buf
));
175 vstream_printf("input=\"%s\" dir=\"%s\" base=\"%s\"\n",
176 STR(buf
), dir
, base
);
178 vstream_fflush(VSTREAM_OUT
);