OSDN Git Service

287080d472cb9dfe32f3785075bc697b8d441ab5
[lha/olha.git] / pathlib.c
1 /*
2   Copyright (c) 2002 Koji Arai
3
4   Permission is hereby granted, free of charge, to any person
5   obtaining a copy of this software and associated documentation files
6   (the "Software"), to deal in the Software without restriction,
7   including without limitation the rights to use, copy, modify, merge,
8   publish, distribute, sublicense, and/or sell copies of the Software,
9   and to permit persons to whom the Software is furnished to do so,
10   subject to the following conditions:
11
12   The above copyright notice and this permission notice shall be
13   included in all copies or substantial portions of the Software.
14
15   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   SOFTWARE.
23 */
24
25 #include <string.h>
26 #define HAVE_BASENAME 0
27 #define HAVE_DIRNAME 1
28
29 int
30 path_addsep(char *path, size_t size)
31 {
32     int len = strlen(path);
33
34     if (len > 0 && path[len-1] != '/' && len + 1 < size) {
35         path[len++] = '/';
36         path[len] = 0;
37     }
38
39     return len;
40 }
41
42 #if !HAVE_BASENAME
43 char *
44 xbasename(char *path)
45 {
46     char *p1, *p2;
47     int len;
48
49     len = strlen(path);
50     if (len == 0)
51         return path;
52     if (len == 1 && path[0] == '/')
53         return path;
54     if (path[len-1] == '/')
55         path[len-1] = '\0';
56
57     for (p1 = p2 = path; *p1 != '\0'; p1++) {
58         if (*p1 == '/') {
59             p2 = p1 + 1;
60         }
61     }
62
63     return p2;
64 }
65 #endif /* !HAVE_BASENAME */
66
67 #if !HAVE_DIRNAME
68 char *
69 dirname(char *path)
70 {
71     char *p1, *p2;
72     int len;
73     static char current[] = ".";
74
75     len = strlen(path);
76     if (len == 0)
77         return current;
78     if (len == 1 && path[0] == '/')
79         return path;
80     if (path[len-1] == '/')
81         path[len-1] = '\0';
82
83     for (p1 = p2 = path; *p1 != '\0'; p1++) {
84         if (*p1 == '/') {
85             p2 = p1;
86         }
87     }
88     if (*p2 == '/' && p2 == path)
89         p2++;
90     *p2 = '\0';
91
92     if (path[0] == '\0')
93         return current;
94
95     return path;
96 }
97 #endif /* !HAVE_DIRNAME */
98
99 int
100 makepath(char *dest, int dest_size,
101          char *dir, char *file, char *ext)
102 {
103     int len;
104     char *p;
105     int size;
106
107     p = dest;
108     size = dest_size;
109
110     /* copy directory part */
111     if (dir) {
112         len = string_copy(p, dir, size);
113         size -= len;
114
115         if (len > 0 && size > 0) {
116             if (p[len-1] != '/') {
117                 p[len++] = '/';
118                 size--;
119             }
120         }
121         p += len;
122     }
123
124     /* copy filename part */
125     if (file) {
126         len = string_copy(p, file, size);
127         size -= len;
128         p += len;
129     }
130
131     /* copy suffix part */
132     if (ext) {
133         if (ext[0] != '.' && size > 0) {
134             *(p++) = '.';
135             size--;
136         }
137
138         len = string_copy(p, ext, size);
139         size -= len;
140         p += len;
141     }
142
143     return p - dest;   /* result string length */
144 }
145
146 #ifdef DEBUG
147
148 #include <stdio.h>
149 #define basename glibc2_basename
150 #include <string.h>             /* strdup() */
151 #undef basename
152
153 #include <assert.h>
154
155 split_path(char *path)
156 {
157     printf("\"%s\"\t= \"%s\" \"%s\"\n",
158            path,
159            dirname(strdup(path)),
160            basename(strdup(path)));
161 }
162
163 main()
164 {
165     char work[256];
166     int len;
167
168     split_path("/foo/bar");
169     split_path("/bar");
170     split_path("bar");
171     split_path("bar/");         /* should print "." and "bar" */
172     split_path("/");            /* should print "/" and "/" */
173     split_path("");             /* should print "." and "" */
174
175
176     len = makepath(work, sizeof work, "foo", "bar", "baz");
177     assert(strcmp(work, "foo/bar.baz") == 0 && len == 11);
178     printf("\"%s\"\n", work);
179
180     len = makepath(work, sizeof work, "foo/", "bar", ".baz");
181     assert(strcmp(work, "foo/bar.baz") == 0 && len == 11);
182     printf("\"%s\"\n", work);
183
184     len = makepath(work, strlen("foo/bar.baz")+1, "foo", "bar", "baz");
185     assert(strcmp(work, "foo/bar.baz") == 0 && len == 11);
186     printf("\"%s\"\n", work);
187
188     len = makepath(work, strlen("foo/bar.baz")+1, "foo", "bar.baz", NULL);
189     assert(strcmp(work, "foo/bar.baz") == 0 && len == 11);
190     printf("\"%s\"\n", work);
191
192     memset(work, '*', sizeof(work)-1);
193     work[sizeof(work)-1] = 0;
194     len = makepath(work+10, sizeof(work)-10, "foo", "bar", "baz");
195     assert(strcmp(work+10, "foo/bar.baz") == 0 && len == 11);
196     printf("\"%s\"\n", work);
197     memset(work+10, '*', strlen("foo/bar.baz")+1);
198     {
199         int i;
200         for (i = 0; i < sizeof(work)-1; i++)
201             assert(work[i] == '*');
202     }
203     printf("\"%s\"\n", work);
204
205     len = makepath(work, strlen("foo/bar.baz"), "foo", "bar", "baz");
206     assert(strcmp(work, "foo/bar.ba") == 0 && len == 10);
207     printf("\"%s\"\n", work);
208
209     return 0;
210 }
211 #endif /* DEBUG */