1 /*
2 * Cross-platform basename/dirname
3 *
4 * Copyright 2005 Syd Logan, All Rights Reserved
5 *
6 * This code is distributed without warranty. You are free to use this
7 * code for any purpose, however, if this code is republished or
8 * redistributed in its original form, as hardcopy or electronically,
9 * then you must include this copyright notice along with the code.
10 *
11 * Minor changes 2008 by Stefan Ludewig stefan.ludewig@exitgames.com
12 * for WIN32 version RRDtool
13 */
14 #ifndef HAVE_LIBGEN_H
16 #include <memory.h>
17 #include <stdlib.h>
18 #include "plbasename.h"
19 #include <string.h>
20 #if defined(TEST)
21 #include <stdio.h>
22 #endif
24 #if defined(__cplusplus)
25 extern "C" {
26 #endif
28 const char *
29 PL_basename(const char *name)
30 {
31 const char *base;
32 char *p;
33 static char *tmp = NULL;
34 int len;
36 if (tmp) {
37 free(tmp);
38 tmp = NULL;
39 }
41 if (!name || !strcmp(name, ""))
42 return "";
44 if (!strcmp(name, "/"))
45 return "/";
47 len = strlen(name);
48 if (name[len - 1] == '/') {
49 // ditch the trailing '/'
50 p = tmp = (char*)malloc(len);
51 strncpy(p, name, len - 1);
52 } else {
53 p = (char *) name;
54 }
56 for (base = p; *p; p++)
57 if (*p == '/')
58 base = p + 1;
60 return base;
61 }
63 const char *
64 PL_dirname(const char *name)
65 {
66 static char *ret = NULL;
67 int len;
68 int size = 0;
69 const char *p;
71 if (ret) {
72 free(ret);
73 ret = NULL;
74 }
76 if (!name || !strcmp(name, "") || !strstr(name, "/"))
77 return(".");
79 if (!strcmp(name, "/"))
80 return(name);
82 /* find the last slash in the string */
84 len = strlen(name);
85 p = &name[len - 1];
87 if (*p == '/') p--; /* skip the trailing */
89 while (p != name && *p != '/') p--;
91 size = p - name;
92 if (size) {
93 ret = (char*)malloc(size + 1);
94 memcpy(ret, name, size);
95 ret[size] = '\0';
96 } else if (*p == '/')
97 return "/";
98 else
99 return "";
101 return (const char *) ret;
102 }
104 #if defined(__cplusplus)
105 }
106 #endif
108 #if defined(TEST)
110 int
111 main(int argc, char *argv[])
112 {
113 /* run the following tests:
115 path dirname basename
116 "/usr/lib" "/usr" "lib"
117 "/usr/" "/" "usr"
118 "usr" "." "usr"
119 "/" "/" "/"
120 "." "." "."
121 ".." "." ".."
122 NULL "." ""
123 "" "." ""
124 "./.." "." ".."
126 These results can be verified by running the unix commands
127 basename(1) and dirname(1). One tweek to the test strategy
128 used here would be, on darwin and linux, to shell out to
129 get the expected results vs hardcoding.
130 */
131 if (!strcmp(PL_basename("/usr/lib"), "lib"))
132 printf("PL_basename /usr/lib passed\n");
133 else
134 printf("PL_basename /usr/lib failed expected lib\n");
135 if (!strcmp(PL_dirname("/usr/lib"), "/usr"))
136 printf("PL_dirname /usr/lib passed\n");
137 else
138 printf("PL_dirname /usr/lib failed expected /usr\n");
139 if (!strcmp(PL_basename("/usr/"), "usr"))
140 printf("PL_basename /usr/ passed\n");
141 else
142 printf("PL_basename /usr/ failed expected usr\n");
143 if (!strcmp(PL_dirname("/usr/"), "/"))
144 printf("PL_dirname /usr/ passed\n");
145 else
146 printf("PL_dirname /usr/ failed expected /\n");
147 if (!strcmp(PL_basename("usr"), "usr"))
148 printf("PL_basename usr passed\n");
149 else
150 printf("PL_basename usr failed expected usr\n");
151 if (!strcmp(PL_dirname("usr"), "."))
152 printf("PL_dirname usr passed\n");
153 else
154 printf("PL_dirname usr failed expected .\n");
155 if (!strcmp(PL_basename("/"), "/"))
156 printf("PL_basename / passed\n");
157 else
158 printf("PL_basename / failed expected /\n");
159 if (!strcmp(PL_dirname("/"), "/"))
160 printf("PL_dirname / passed\n");
161 else
162 printf("PL_dirname / failed expected /\n");
163 if (!strcmp(PL_basename("."), "."))
164 printf("PL_basename . passed\n");
165 else
166 printf("PL_basename . failed\n");
167 if (!strcmp(PL_dirname("."), "."))
168 printf("PL_dirname . passed\n");
169 else
170 printf("PL_dirname . failed expected .\n");
171 if (!strcmp(PL_basename(".."), ".."))
172 printf("PL_basename .. passed\n");
173 else
174 printf("PL_basename .. failed expected ..\n");
175 if (!strcmp(PL_dirname(".."), "."))
176 printf("PL_dirname .. passed\n");
177 else
178 printf("PL_dirname .. failed expected .\n");
179 if (!strcmp(PL_basename(NULL), ""))
180 printf("PL_basename NULL passed\n");
181 else
182 printf("PL_basename NULL failed expected \"\"\n");
183 if (!strcmp(PL_dirname(NULL), "."))
184 printf("PL_dirname NULL passed\n");
185 else
186 printf("PL_dirname NULL failed expected .\n");
187 if (!strcmp(PL_basename(""), ""))
188 printf("PL_basename \"\" passed\n");
189 else
190 printf("PL_basename \"\" failed expected \"\"\n");
191 if (!strcmp(PL_dirname(""), "."))
192 printf("PL_dirname \"\" passed\n");
193 else
194 printf("PL_dirname \"\" failed expected .\n");
196 if (!strcmp(PL_basename("./.."), ".."))
197 printf("PL_basename ./.. passed\n");
198 else
199 printf("PL_basename ./.. failed expected ..\n");
200 if (!strcmp(PL_dirname("./.."), "."))
201 printf("PL_dirname ./.. passed\n");
202 else
203 printf("PL_dirname ./.. failed expected .\n");
204 }
205 #endif
207 #endif /* HAVE_LIBGEN_H */