1
2 /* globber.c */
3 /*
4 Copyright 2000-2001 Edscott Wilson Garcia
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; */
18
19 /*****************************************************************/
20
21 #include "fgr-globber.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdarg.h>
29 #include <glob.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32 #include <sys/signal.h>
33 #include <time.h>
34 #include <sys/types.h>
35 #include <dirent.h>
36
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40
41 #ifdef DMALLOC
42 # include "dmalloc.h"
43 // exit(1) taken care of below.
44 #endif
45
46 /** tripas **/
47 /* private */
48 #ifndef GLOB_TILDE
49 # define GLOB_TILDE 0x0
50 #endif
51 #ifndef GLOB_ONLYDIR
52 # define GLOB_ONLYDIR 0x0
53 #endif
54
55 #define MONTH_T 2628000
56 #define DAY_T 86400
57 #define HOUR_T 3600
58 #define MIN_T 60
59
60 typedef struct objeto_globber {
61 int options;
62 int type;
63 int user;
64 int group;
65 off_t sizeG;
66 off_t sizeL;
67 long unsigned month_t;
68 long unsigned day_t;
69 long unsigned hour_t;
70 long unsigned min_t;
71 /* private variables, not to be duplicated on recursion: */
72 struct stat st;
73 int pass;
74 time_t tiempo;
75 time_t actual;
76 int dostat;
77 } objeto_globber;
78
79 static int
display(char * input)80 display (char *input) {
81 printf ("%s\n", input); /*fflush(stdout); */
82 return 0;
83 }
84
85 /* public */
86 int
glob_clear_options(void * address)87 glob_clear_options (void *address) {
88 if (!address) return 1;
89 objeto_globber *objeto = address;
90 memset(objeto, 0, sizeof(objeto_globber));
91 objeto->user = -1;
92 objeto->group = -1;
93 objeto->sizeL = -1;
94 objeto->sizeG = -1;
95 objeto->min_t = -1;
96 objeto->hour_t = -1;
97 objeto->day_t = -1;
98 objeto->month_t = -1;
99 return 1;
100 }
101
102 void *
globber_create(void)103 globber_create (void) {
104 objeto_globber *objeto;
105 objeto = (objeto_globber *) malloc (sizeof (objeto_globber));
106 if (!objeto) {
107 fprintf(stderr, "Unable to malloc basic structure.\n");
108 exit(1);
109 }
110 glob_clear_options ((void *)objeto);
111 return (void *)objeto;
112 }
113
114 void *
globber_destroy(void * address)115 globber_destroy (void *address) {
116 if(address)
117 free (address);
118 return NULL;
119 }
120
121 int
glob_set_options(void * address,int options)122 glob_set_options (void *address, int options) {
123 if (!address){
124 fprintf(stderr, "broken call to glob_set_options()\n");
125 exit(0);
126 }
127 objeto_globber *objeto = address;
128 objeto->options |= options;
129 return 1;
130 }
131
132 int
glob_set_type(void * address,int type)133 glob_set_type (void *address, int type) {
134 if (!address){
135 fprintf(stderr, "broken call to glob_set_type()\n");
136 exit(0);
137 }
138 objeto_globber *objeto = address;
139 objeto->type = type;
140 return 1;
141 }
142
143 int
glob_set_sizeG(void * address,off_t size)144 glob_set_sizeG (void *address, off_t size) {
145 if (!address){
146 fprintf(stderr, "broken call to glob_set_sizeG()\n");
147 exit(0);
148 }
149 objeto_globber *objeto = address;
150 glob_set_options (objeto, GLOBBER_SIZE);
151 objeto->sizeG = size;
152 return 1;
153 }
154
155 int
glob_set_sizeL(void * address,off_t size)156 glob_set_sizeL (void *address, off_t size) {
157 if (!address){
158 fprintf(stderr, "broken call to glob_set_sizeL()\n");
159 exit(0);
160 }
161 objeto_globber *objeto = address;
162 glob_set_options (objeto, GLOBBER_SIZE);
163 objeto->sizeL = size;
164 return 1;
165 }
166
167 int
glob_set_user(void * address,int user)168 glob_set_user (void *address, int user) {
169 if (!address){
170 fprintf(stderr, "broken call to glob_set_user()\n");
171 exit(0);
172 }
173 objeto_globber *objeto = address;
174 glob_set_options (objeto, GLOBBER_USER);
175 objeto->user = user;
176 return 1;
177 }
178
179 int
glob_set_group(void * address,int group)180 glob_set_group (void *address, int group) {
181 if (!address){
182 fprintf(stderr, "broken call to glob_set_group()\n");
183 exit(0);
184 }
185 objeto_globber *objeto = address;
186 ;
187 glob_set_options (objeto, GLOBBER_GROUP);
188 objeto->group = group;
189 return 1;
190 }
191
192 int
glob_set_minutes(void * address,long unsigned min_t)193 glob_set_minutes (void *address, long unsigned min_t) {
194 if (!address){
195 fprintf(stderr, "broken call to glob_set_time()\n");
196 exit(0);
197 }
198 objeto_globber *objeto = address;
199 objeto->min_t = min_t;
200 return 1;
201 }
202
203 int
glob_set_hours(void * address,long unsigned hour_t)204 glob_set_hours (void *address, long unsigned hour_t) {
205 if (!address){
206 fprintf(stderr, "broken call to glob_set_time()\n");
207 exit(0);
208 }
209 objeto_globber *objeto = address;
210 objeto->hour_t = hour_t;
211 return 1;
212 }
213
214 int
glob_set_days(void * address,long unsigned day_t)215 glob_set_days (void *address,long unsigned day_t) {
216 if (!address){
217 fprintf(stderr, "broken call to glob_set_time()\n");
218 exit(0);
219 }
220 objeto_globber *objeto = address;
221 objeto->day_t = day_t;
222 return 1;
223 }
224
225 int
glob_set_months(void * address,long unsigned month_t)226 glob_set_months (void *address, long unsigned month_t) {
227 if (!address){
228 fprintf(stderr, "broken call to glob_set_time()\n");
229 exit(0);
230 }
231 objeto_globber *objeto = address;
232 objeto->month_t = month_t;
233 return 1;
234 }
235
236 /* if the user defined "operate" function returns TRUE, Globber will exit
237 * and return to calling module with the same return value */
238
239 int
globber(void * address,char * path,int (* operate)(char *),char * filter)240 globber (void *address, char *path, int (*operate) (char *), char *filter) {
241 /* these variables must be kept on the heap */
242 glob_t dirlist;
243 int i;
244 char *globstring,
245 *dot_filter = NULL,
246 *actual_filter = NULL;
247 objeto_globber *object;
248 struct stat path_st;
249 errno=0;
250 /* if (!path || !strlen(path)) {
251 fprintf(stderr, "invalid path: %s\n", path?"\"\"":"NULL");
252 return -1;
253 }*/
254 if(!address)
255 object = (objeto_globber *) globber_create ();
256 else
257 object = (objeto_globber *) address;
258
259 // this is debug rather than verbose...
260 // if (object->options & GLOBBER_VERBOSE) fprintf(stderr, "---> %s\n", path);
261 if(object->options & GLOBBER_TIME) {
262 if(object->options & GLOBBER_MTIME)
263 object->options &= ((GLOBBER_CTIME | GLOBBER_ATIME) ^ 0xffffffff);
264 else if(object->options & GLOBBER_CTIME)
265 object->options &= (GLOBBER_ATIME ^ 0xffffffff);
266 }
267
268 dirlist.gl_offs = 2;
269 if(!operate)
270 operate = display;
271 actual_filter = filter;
272 filter_repeat:
273
274 if(actual_filter) {
275 globstring = (char *)malloc (strlen (path) + strlen (actual_filter) + 2);
276 if (!globstring){fprintf(stderr,"malloc: %s", strerror(errno)); exit(1);}
277 strcpy (globstring, path);
278 if(path[strlen (path) - 1] != '/')
279 strcat (globstring, "/");
280 strcat (globstring, actual_filter);
281 } else
282 globstring = path;
283
284 // If file cannot be stat(), assume it is not there (whatever).
285 // coverity[fs_check_call : FALSE]
286 if(stat (path, &path_st) < 0) {
287 fprintf(stderr, "%s: %s\n", path, strerror (errno));
288 int pass = object->pass;
289 if (!address) free(object);
290 if (actual_filter) free(globstring);
291 return (pass);
292 }
293 if(glob (globstring, GLOB_ERR | GLOB_TILDE, NULL, &dirlist) != 0) {
294 // this is debug rather than verbose...
295 // if (object->options & GLOBBER_VERBOSE)
296 // fprintf(stderr, "%s: %s\n", globstring,strerror(ENOENT));
297 } else {
298 for(i = 0; i < dirlist.gl_pathc; i++) {
299 if((object->options & GLOBBER_STAT) && lstat (dirlist.gl_pathv[i], &(object->st))>=0) {
300 if(object->options & GLOBBER_USER) {
301 if(object->user != object->st.st_uid)
302 continue;
303 }
304 if(object->options & GLOBBER_GROUP) {
305 if(object->group != object->st.st_gid)
306 continue;
307 }
308 if(object->options & GLOBBER_TIME) {
309 object->actual = time (NULL);
310 if(object->options & GLOBBER_MTIME)
311 object->tiempo = object->st.st_mtime;
312 if(object->options & GLOBBER_ATIME)
313 object->tiempo = object->st.st_atime;
314 if(object->options & GLOBBER_CTIME)
315 object->tiempo = object->st.st_ctime;
316
317 if((object->min_t > 0) && ((object->actual - object->tiempo) / MIN_T > object->min_t))
318 continue;
319 if((object->hour_t > 0) && ((object->actual - object->tiempo) / HOUR_T > object->hour_t))
320 continue;
321 if((object->day_t > 0) && ((object->actual - object->tiempo) / DAY_T > object->day_t))
322 continue;
323
324 if((object->month_t > 0) && ((object->actual - object->tiempo) / MONTH_T > object->month_t))
325 continue;
326
327
328 }
329 if(object->options & GLOBBER_SIZE) {
330 if((object->sizeL >= 0) && (object->st.st_size > object->sizeL))
331 continue;
332 if((object->sizeG > 0) && object->st.st_size < object->sizeG)
333 continue;
334 }
335 if(object->options & GLOBBER_PERM) {
336 if((object->st.st_mode & 07777) & (object->type & 07777)) ;
337 else {
338 if((object->st.st_mode & 07777) == (object->type & 07777)) ;
339 else
340 continue;
341 }
342 }
343
344 if(object->options & GLOBBER_TYPE) {
345 if((object->st.st_mode & S_IFMT) != (object->type & S_IFMT))
346 continue;
347 }
348 }
349 /* done lstat'ing */
350 if((object->pass = (*(operate)) (dirlist.gl_pathv[i])) != 0)
351 break;
352 }
353 } /* initial glob is done */
354 if(actual_filter) free (globstring);
355 globfree (&dirlist);
356 if(!dot_filter && object->options & GLOBBER_ADD_DOT_FILTER) {
357 dot_filter = (char *)malloc (strlen (filter) + 2);
358 if (!dot_filter){fprintf(stderr,"malloc: %s", strerror(errno)); exit(1);}
359 strcpy (dot_filter, ".");
360 strcat (dot_filter, filter);
361 actual_filter = dot_filter;
362 goto filter_repeat;
363 }
364 if(dot_filter) {
365 free (dot_filter);
366 dot_filter = NULL;
367 actual_filter = NULL;
368 }
369 if(object->pass) {
370 int pass = object->pass;
371 if (!address) free(object);
372 return (pass); /* error returned from function */
373 }
374
375 if(object->options & GLOBBER_RECURSIVE) {
376 DIR *directory;
377 struct dirent *d;
378 directory = opendir (path);
379 if(directory)
380 while((d = readdir (directory)) != NULL) {
381 char *fullpath;
382 if(strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
383 continue;
384 fullpath = (char *)malloc (strlen (path) + strlen (d->d_name) + 2);
385 if (!fullpath){fprintf(stderr,"malloc: %s", strerror(errno)); exit(1);}
386 sprintf (fullpath, "%s/%s", path, d->d_name);
387
388 if(lstat (fullpath, &(object->st)) < 0) {
389 free (fullpath);
390 continue;
391 }
392
393 if(!S_ISDIR (object->st.st_mode) || (object->st.st_mode & S_IFMT) == S_IFLNK) {
394 free (fullpath);
395 continue; /* dont follow symlinks */
396 }
397 if(S_ISDIR (object->st.st_mode) && *(d->d_name) == '.' && (object->options & GLOBBER_RECURSIVE_NO_HIDDEN)) {
398 /*printf("object->options=0x%x\n",(unsigned)object->options); */
399 free (fullpath);
400 continue; /* dont recurse into hidden directories */
401 }
402 if(object->options & GLOBBER_XDEV && object->st.st_dev != path_st.st_dev) {
403 free (fullpath);
404 continue; /* dont leave device */
405 }
406 // this is debug rather than verbose...
407 // if (object->options & GLOBBER_VERBOSE) fprintf(stderr, "%s: --->\n",fullpath);
408
409 object->pass = globber (address, fullpath, operate, filter);
410 if(object->pass) {
411 free (fullpath);
412 break;
413 }
414 free (fullpath);
415 }
416 closedir (directory);
417
418 }
419 int pass = object->pass;
420 if (!address) free(object);
421 return (pass);
422 }
423