1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18 names of its contributors may be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <limits.h>
41 #include "fricas_c_macros.h"
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #include "cfuns-c.H1"
46
47 /* Most versions of Windows don't have the POSIX functions getuid(),
48 geteuid(), getgid(), and getegid(). The following definitions are
49 approximations, to patch for the deficiencies of Windows
50 POSIX interface. */
51
52 #if !HAVE_DECL_GETUID
53 # define getuid() 0
54 #endif
55
56 #if !HAVE_DECL_GETGID
57 # define getgid() 0
58 #endif
59
60 #if !HAVE_DECL_GETEUID
61 # define geteuid() getuid()
62 #endif
63
64 #if !HAVE_DECL_GETEGID
65 # define getegid() getgid()
66 #endif
67
68 int
addtopath(char * dir)69 addtopath(char *dir)
70 {
71 char *path, *newpath;
72
73 path = getenv("PATH");
74 if (path == NULL)
75 return -1;
76
77 newpath = (char *) malloc(1 + strlen(path) + strlen(dir) + strlen("PATH=:"));
78 if (newpath == NULL)
79 return -1;
80
81 sprintf(newpath, "PATH=%s;%s", path, dir); /* MSYS/MinGW ??? */
82
83 return putenv(newpath);
84 }
85
86 /*
87 * Test whether the path is the name of a directory. Returns 1 if so, 0 if
88 * not, -1 if it doesn't exist.
89 */
90
91
92 int
directoryp(char * path)93 directoryp(char *path)
94 {
95 struct stat buf;
96 int code;
97
98 code = stat(path, &buf);
99 if (code == -1) {
100 return (-1);
101 }
102 else {
103 return ((buf.st_mode & S_IFDIR) != 0);
104 }
105 }
106
107
108 /* Make a directory returning 0 for success and -1 for failure */
109
110 int
makedir(char * path)111 makedir(char *path)
112 {
113 #ifdef HAVE_TWO_ARG_MKDIR
114 return ( mkdir (path,(S_IRWXU | S_IRWXO | S_IRWXG)) );
115 #else
116 return ( mkdir (path) );
117 #endif
118 }
119
120 int
make_path_from_file(char * s,char * t)121 make_path_from_file(char *s, char *t)
122 {
123 char *pos = NULL;
124 char *c;
125
126 /** simply copies the path name from t into s **/
127 for (c = t + strlen(t); c != t; c--)
128 if ( ( *c == '/' ) || ( *c == '\\' ) ) {
129 pos = c;
130 break;
131 }
132 /** Check to see if the path was actually present **/
133 if (c == t) { /** No Path, so return the pwd **/
134 return (-1);
135 }
136 /** now just do the copying **/
137 strncpy(s, t, pos - t);
138 return 1;
139 }
140
141 /* The functions writeablep() and readablep() determine write and
142 read access of a file designated by its name.
143
144 The access is determined based on the POSIX semantics; see
145 "Advanced Programming in the UNIX Environement", section 4.5.
146
147 1. If the effective user ID of the process is 0 (the superuser),
148 access is allowed. This gives the superuser free rein throughout
149 the entire file system.
150
151 2. If the effective user ID of the process equals the owner ID of
152 the file (i.e., the process owns the file), access is allowed
153 if the appropriate user access permission bit is set. [...]
154
155 3. If the effective group ID of the process or one of the
156 supplementary group IDs of the process equals the group ID
157 of the file, access is allowed if the appropriate
158 group access permission bit is set. Otherwise, permission
159 is denied.
160
161 4. If the appropriate other access permission bit is set, access is
162 allowed. Otherwise, permission is defined. */
163
164 /* Return
165 -1 if the file designated by PATH is inexistent.
166 0 if the file exists but wirte access is denied.
167 1 if the file exists and process has write access.
168 2 if the file does not exists but process has write
169 has write access to the dirname of path. */
170
171 int
writeablep(char * path)172 writeablep(char *path)
173 {
174 struct stat buf;
175 char newpath[100];
176 int code;
177
178 code = stat(path, &buf);
179 if (code == -1) {
180 /** The file does not exist, so check to see
181 if the directory is writable *****/
182 if (make_path_from_file(newpath, path) == -1 ||
183 stat(newpath, &buf) == -1) {
184 return (-1);
185 }
186 }
187 else if (geteuid() == buf.st_uid) {
188 return ((buf.st_mode & S_IWUSR) != 0);
189 #ifdef S_IWGRP
190 }
191 else if (getegid() == buf.st_gid) {
192 return ((buf.st_mode & S_IWGRP) != 0);
193 #endif
194 #ifdef S_IWOTH
195 }
196 else {
197 return ((buf.st_mode & S_IWOTH) != 0);
198 #endif
199 };
200 return ( 1 ); /* MSYS/MinGW */
201 }
202
203
204 int
readablep(char * path)205 readablep(char *path)
206 {
207 struct stat buf;
208 int code;
209
210 code = stat(path, &buf);
211 if (code == -1) {
212 return (-1);
213 }
214 else if (geteuid() == buf.st_uid) {
215 return ((buf.st_mode & S_IREAD) != 0);
216 #ifdef S_IRGRP
217 }
218 else if (getegid() == buf.st_gid) {
219 return ((buf.st_mode & S_IRGRP) != 0);
220 #endif
221 #ifdef S_IROTH
222 }
223 else {
224 return ((buf.st_mode & S_IROTH) != 0);
225 #endif
226 };
227 return ( 1 ); /* MSYS/MinGW */
228 }
229
230
231 long
findString(char * file,char * string)232 findString(char *file, char *string)
233 {
234 int nstring, charpos;
235 FILE *fn;
236 char buffer[1024];
237
238 if ((fn = fopen(file, "r")) == NULL)
239 return -1;
240
241 for (charpos = 0, nstring = strlen(string);
242 fgets(buffer, sizeof buffer, fn) != NULL;
243 charpos += strlen(buffer)
244 )
245 if (!strncmp(buffer, string, nstring))
246 return charpos;
247 return -1;
248
249 }
250
251 #ifdef HOST_HAS_DIRECTORY_OPERATIONS
252
253 #include <dirent.h>
254
fricas_copy_string(char * str)255 char * fricas_copy_string(char *str)
256 {
257 char * res = malloc(strlen(str) + 1);
258 if (res) {
259 strcpy(res, str);
260 } else {
261 fprintf(stderr, "Malloc failed (fricas_copy_string)\n");
262 }
263 return res;
264 }
265
266 int
remove_directory(char * name)267 remove_directory(char * name)
268 {
269 #ifdef HOST_HAS_DIRFD_FCHDIR
270 DIR * cur_dir = opendir(".");
271 int cur_dir_fd;
272 int dir_fd;
273 #else
274 size_t name_len = strlen(name);
275 #endif
276 DIR * dir;
277 struct dirent * entry;
278 struct file_list {
279 struct file_list * next;
280 char * file;
281 };
282 struct file_list * flst = 0;
283 #ifdef HOST_HAS_DIRFD_FCHDIR
284 if (!cur_dir) {
285 fprintf(stderr, "Unable to open current directory\n");
286 return -1;
287 }
288 #else
289 if (name_len > INT_MAX/5) {
290 fprintf(stderr, "directory name too long\n");
291 return -1;
292 }
293 #endif
294 dir = opendir(name);
295 if (!dir) {
296 fprintf(stderr, "Unable to open directory to be removed\n");
297 goto err1;
298 }
299 #ifdef HOST_HAS_DIRFD_FCHDIR
300 cur_dir_fd = dirfd(cur_dir);
301 dir_fd = dirfd(dir);
302 if (cur_dir_fd == -1 || dir_fd == -1) {
303 fprintf(stderr, "dirfd failed\n");
304 goto err2;
305 }
306 #endif
307 while ((entry = readdir(dir))) {
308 char * fname = &(entry->d_name[0]);
309 if (strlen(fname) > INT_MAX/5) {
310 break;
311 }
312 if (!strcmp(fname, ".")) {
313 continue;
314 } else if (!strcmp(fname, "..")) {
315 continue;
316 } else {
317 struct file_list * npos = malloc(sizeof(*npos));
318 if (!npos) {
319 fprintf(stderr, "Malloc failed (npos)\n");
320 break;
321 }
322 npos->file = fricas_copy_string(fname);
323 if (!(npos->file)) {
324 free(npos);
325 break;
326 }
327 npos->next = flst;
328 flst = npos;
329 }
330 }
331 #ifdef HOST_HAS_DIRFD_FCHDIR
332 if (fchdir(dir_fd)) {
333 perror("Failed to change directory to directory to be removed");
334 while (flst) {
335 struct file_list * npos = flst->next;
336 free(flst->file);
337 free(flst);
338 flst = npos;
339 }
340 goto err2;
341 }
342 #endif
343 while (flst) {
344 struct file_list * npos = flst->next;
345 #ifdef HOST_HAS_DIRFD_FCHDIR
346 if (unlink(flst->file)) {
347 perror("Unlink failed");
348 }
349 #else
350 char pathbuf[PATH_MAX];
351 if (strlen(flst->file) + name_len + 1 < PATH_MAX) {
352 strcpy(pathbuf, name);
353 strcat(pathbuf, "/");
354 strcat(pathbuf, flst->file);
355 if (unlink(pathbuf)) {
356 perror("Unlink failed");
357 }
358 } else {
359 fprintf(stderr, "panthname too long\n");
360 }
361 #endif
362 free(flst->file);
363 free(flst);
364 flst = npos;
365 }
366 #ifdef HOST_HAS_DIRFD_FCHDIR
367 if (fchdir(cur_dir_fd)) {
368 closedir(dir);
369 closedir(cur_dir);
370 return -1;
371 }
372 err2:
373 #endif
374 closedir(dir);
375 err1:
376 #ifdef HOST_HAS_DIRFD_FCHDIR
377 closedir(cur_dir);
378 #endif
379 {
380 int res = rmdir(name);
381 if (res) {
382 perror("rmdir failed");
383 }
384 return res;
385 }
386 }
387
388 #endif
389