chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / file.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2007 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "file.h"
26 #include "util.h"
27 #include <dirent.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 char              **
35 E_ls(const char *dir, int *num)
36 {
37    int                 i, dirlen;
38    int                 done = 0;
39    DIR                *dirp;
40    char              **names;
41    struct dirent      *dp;
42
43    if ((!dir) || (!*dir))
44       return NULL;
45    dirp = opendir(dir);
46    if (!dirp)
47      {
48         *num = 0;
49         return NULL;
50      }
51    /* count # of entries in dir (worst case) */
52    for (dirlen = 0; (dp = readdir(dirp)) != NULL; dirlen++)
53       ;
54    if (!dirlen)
55      {
56         closedir(dirp);
57         *num = dirlen;
58         return NULL;
59      }
60    names = EMALLOC(char *, dirlen);
61
62    if (!names)
63       return NULL;
64
65    rewinddir(dirp);
66    for (i = 0; i < dirlen;)
67      {
68         dp = readdir(dirp);
69         if (!dp)
70            break;
71         if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, "..")))
72           {
73              names[i] = Estrdup(dp->d_name);
74              i++;
75           }
76      }
77
78    if (i < dirlen)
79       dirlen = i;               /* dir got shorter... */
80    closedir(dirp);
81    *num = dirlen;
82
83    /* do a simple bubble sort here to alphanumberic it */
84    while (!done)
85      {
86         done = 1;
87         for (i = 0; i < dirlen - 1; i++)
88           {
89              if (strcmp(names[i], names[i + 1]) > 0)
90                {
91                   char               *tmp;
92
93                   tmp = names[i];
94                   names[i] = names[i + 1];
95                   names[i + 1] = tmp;
96                   done = 0;
97                }
98           }
99      }
100    return names;
101 }
102
103 void
104 E_md(const char *s)
105 {
106    if ((!s) || (!*s))
107       return;
108    mkdir(s, S_IRWXU);
109 }
110
111 void
112 E_mv(const char *s, const char *ss)
113 {
114    if ((!s) || (!ss) || (!*s) || (!*ss))
115       return;
116    rename(s, ss);
117 }
118
119 void
120 E_rm(const char *s)
121 {
122    if ((!s) || (!*s))
123       return;
124    unlink(s);
125 }
126
127 int
128 file_test(const char *s, unsigned int test)
129 {
130    struct stat         st;
131    int                 mode;
132
133    if (!s || !*s)
134       return 0;
135
136 #define EFILE_ALL (EFILE_ANY | EFILE_REG | EFILE_DIR)
137    if (test & EFILE_ALL)
138      {
139         if (stat(s, &st) < 0)
140            return 0;
141         if ((test & EFILE_REG) && !S_ISREG(st.st_mode))
142            return 0;
143         if ((test & EFILE_DIR) && !S_ISDIR(st.st_mode))
144            return 0;
145      }
146
147 #define EPERM_ALL (EPERM_R | EPERM_W | EPERM_X)
148    if (test & EPERM_ALL)
149      {
150         mode = 0;
151         if (test & EPERM_R)
152            mode |= R_OK;
153         if (test & EPERM_W)
154            mode |= W_OK;
155         if (test & EPERM_X)
156            mode |= X_OK;
157         if (access(s, mode))
158            return 0;
159      }
160
161    return 1;
162 }
163
164 time_t
165 moddate(const char *s)
166 {
167    struct stat         st;
168
169    if ((!s) || (!*s))
170       return 0;
171    if (stat(s, &st) < 0)
172       return 0;
173    if (st.st_mtime > st.st_ctime)
174       return st.st_mtime;
175    return st.st_ctime;
176 }
177
178 #if 0                           /* Unused */
179 int
180 filesize(const char *s)
181 {
182    struct stat         st;
183
184    if ((!s) || (!*s))
185       return 0;
186    if (stat(s, &st) < 0)
187       return 0;
188    return (int)st.st_size;
189 }
190 #endif
191
192 int
193 fileinode(const char *s)
194 {
195    struct stat         st;
196
197    if ((!s) || (!*s))
198       return 0;
199    if (stat(s, &st) < 0)
200       return 0;
201    return (int)st.st_ino;
202 }
203
204 int
205 filedev(const char *s)
206 {
207    struct stat         st;
208
209    if ((!s) || (!*s))
210       return 0;
211    if (stat(s, &st) < 0)
212       return 0;
213    return filedev_map((int)st.st_dev);
214 }
215
216 int
217 filedev_map(int dev)
218 {
219 #ifdef __linux__
220    /* device numbers in the anonymous range can't be relied
221     * upon, so map them all on a single one */
222    switch (dev >> 8)
223      {
224      default:
225         return dev;
226      case 0:
227      case 144:
228      case 145:
229      case 146:
230         return 1;
231      }
232 #else
233    return dev;
234 #endif
235 }
236
237 int
238 isabspath(const char *path)
239 {
240    return path[0] == '/';
241 }
242
243 const char         *
244 fileext(const char *file)
245 {
246    const char         *p;
247
248    p = strrchr(file, '.');
249    if (p != NULL)
250      {
251         return p + 1;
252      }
253    return "";
254 }
255
256 char               *
257 fileof(const char *path)
258 {
259    const char         *s1, *s2;
260
261    s1 = strrchr(path, '/');
262    s1 = (s1) ? s1 + 1 : path;
263    s2 = strrchr(s1, '.');
264    if (!s2)
265       return Estrdup(s1);
266
267    return Estrndup(s1, s2 - s1);
268 }
269
270 const char         *
271 fullfileof(const char *path)
272 {
273    const char         *s;
274
275    if (!path)
276       return NULL;
277    s = strrchr(path, '/');
278    return (s) ? s + 1 : path;
279 }
280
281 char               *
282 path_test(const char *file, unsigned int test)
283 {
284    char               *cp, *ep;
285    char               *s, *p;
286    unsigned int        len, exelen;
287
288    if (!file)
289       return NULL;
290
291    if (isabspath(file))
292      {
293         if (file_test(file, test))
294            return Estrdup(file);
295         return NULL;
296      }
297    cp = getenv("PATH");
298    if (!cp)
299       return Estrdup(file);
300
301    exelen = strlen(file);
302    s = NULL;
303    ep = cp;
304    for (; ep; cp = ep + 1)
305      {
306         ep = strchr(cp, ':');
307         len = (ep) ? (unsigned int)(ep - cp) : strlen(cp);
308         if (len == 0)
309            continue;
310         p = EREALLOC(char, s, len + exelen + 2);
311
312         if (!p)
313            break;
314         s = p;
315         memcpy(s, cp, len);
316         s[len] = '/';
317         memcpy(s + len + 1, file, exelen + 1);
318         if (file_test(s, test))
319            return s;
320      }
321    Efree(s);
322    return NULL;
323 }
324
325 int
326 path_canexec(const char *file)
327 {
328    char               *s;
329
330    s = path_test(file, EFILE_REG | EPERM_X);
331    if (!s)
332       return 0;
333    Efree(s);
334    return 1;
335 }