Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
sane_basename.c
[詳解]
1 /*++
2 /* NAME
3 /* sane_basename 3
4 /* SUMMARY
5 /* split pathname into last component and parent directory
6 /* SYNOPSIS
7 /* #include <stringops.h>
8 /*
9 /* char *sane_basename(buf, path)
10 /* VSTRING *buf;
11 /* const char *path;
12 /*
13 /* char *sane_dirname(buf, path)
14 /* VSTRING *buf;
15 /* const char *path;
16 /* DESCRIPTION
17 /* These functions split a pathname into its last component
18 /* and its parent directory, excluding any trailing "/"
19 /* characters from the input. The result is a pointer to "/"
20 /* when the input is all "/" characters, or a pointer to "."
21 /* when the input is a null pointer or zero-length string.
22 /*
23 /* sane_basename() and sane_dirname() differ as follows
24 /* from standard basename() and dirname() implementations:
25 /* .IP \(bu
26 /* They can use caller-provided storage or private storage.
27 /* .IP \(bu
28 /* They never modify their input.
29 /* .PP
30 /* sane_basename() returns a pointer to string with the last
31 /* pathname component.
32 /*
33 /* sane_dirname() returns a pointer to string with the parent
34 /* directory. The result is a pointer to "." when the input
35 /* contains no '/' character.
36 /*
37 /* Arguments:
38 /* .IP buf
39 /* Result storage. If a null pointer is specified, each function
40 /* uses its own private memory that is overwritten upon each call.
41 /* .IP path
42 /* The input pathname.
43 /* LICENSE
44 /* .ad
45 /* .fi
46 /* The Secure Mailer license must be distributed with this
47 /* software.
48 /* AUTHOR(S)
49 /* Wietse Venema
50 /* IBM T.J. Watson Research
51 /* P.O. Box 704
52 /* Yorktown Heights, NY 10598, USA
53 /*--*/
54 
55 /* System library. */
56 
57 #include <sys_defs.h>
58 #include <string.h>
59 
60 /* Utility library. */
61 
62 #include <vstring.h>
63 #include <stringops.h>
64 
65 #define STR(x) vstring_str(x)
66 
67 /* sane_basename - skip directory prefix */
68 
69 char *sane_basename(VSTRING *bp, const char *path)
70 {
71  static VSTRING *buf;
72  const char *first;
73  const char *last;
74 
75  /*
76  * Your buffer or mine?
77  */
78  if (bp == 0) {
79  bp = buf;
80  if (bp == 0)
81  bp = buf = vstring_alloc(10);
82  }
83 
84  /*
85  * Special case: return "." for null or zero-length input.
86  */
87  if (path == 0 || *path == 0)
88  return (STR(vstring_strcpy(bp, ".")));
89 
90  /*
91  * Remove trailing '/' characters from input. Return "/" if input is all
92  * '/' characters.
93  */
94  last = path + strlen(path) - 1;
95  while (*last == '/') {
96  if (last == path)
97  return (STR(vstring_strcpy(bp, "/")));
98  last--;
99  }
100 
101  /*
102  * The pathname does not end in '/'. Skip to last '/' character if any.
103  */
104  first = last - 1;
105  while (first >= path && *first != '/')
106  first--;
107 
108  return (STR(vstring_strncpy(bp, first + 1, last - first)));
109 }
110 
111 /* sane_dirname - keep directory prefix */
112 
113 char *sane_dirname(VSTRING *bp, const char *path)
114 {
115  static VSTRING *buf;
116  const char *last;
117 
118  /*
119  * Your buffer or mine?
120  */
121  if (bp == 0) {
122  bp = buf;
123  if (bp == 0)
124  bp = buf = vstring_alloc(10);
125  }
126 
127  /*
128  * Special case: return "." for null or zero-length input.
129  */
130  if (path == 0 || *path == 0)
131  return (STR(vstring_strcpy(bp, ".")));
132 
133  /*
134  * Remove trailing '/' characters from input. Return "/" if input is all
135  * '/' characters.
136  */
137  last = path + strlen(path) - 1;
138  while (*last == '/') {
139  if (last == path)
140  return (STR(vstring_strcpy(bp, "/")));
141  last--;
142  }
143 
144  /*
145  * This pathname does not end in '/'. Skip to last '/' character if any.
146  */
147  while (last >= path && *last != '/')
148  last--;
149  if (last < path) /* no '/' */
150  return (STR(vstring_strcpy(bp, ".")));
151 
152  /*
153  * Strip trailing '/' characters from dirname (not strictly needed).
154  */
155  while (last > path && *last == '/')
156  last--;
157 
158  return (STR(vstring_strncpy(bp, path, last - path + 1)));
159 }
160 
161 #ifdef TEST
162 #include <vstring_vstream.h>
163 
164 int main(int argc, char **argv)
165 {
166  VSTRING *buf = vstring_alloc(10);
167  char *dir;
168  char *base;
169 
170  while (vstring_get_nonl(buf, VSTREAM_IN) > 0) {
171  dir = sane_dirname((VSTRING *) 0, STR(buf));
172  base = sane_basename((VSTRING *) 0, STR(buf));
173  vstream_printf("input=\"%s\" dir=\"%s\" base=\"%s\"\n",
174  STR(buf), dir, base);
175  }
177  vstring_free(buf);
178  return (0);
179 }
180 
181 #endif
int vstring_get_nonl(VSTRING *vp, VSTREAM *fp)
#define VSTREAM_OUT
Definition: vstream.h:67
int main(int argc, char **argv)
Definition: anvil.c:1010
#define VSTREAM_IN
Definition: vstream.h:66
char * sane_dirname(VSTRING *bp, const char *path)
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define STR(x)
Definition: sane_basename.c:65
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
char * sane_basename(VSTRING *bp, const char *path)
Definition: sane_basename.c:69
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
Definition: vstring.c:445