ede/efinder/globber.c
2007-03-15 01:06:18 +00:00

305 lines
8.1 KiB
C

/* globber.c */
/*
Copyright 2000-2001 Edscott Wilson Garcia
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/*****************************************************************/
#include "globber.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <glob.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_SNPRINTF
# include "snprintf.h"
#endif
#ifdef DMALLOC
# include "dmalloc.h"
#endif
/** tripas **/
/* private */
#ifndef GLOB_TILDE
#define GLOB_TILDE 0x0
#endif
#ifndef GLOB_ONLYDIR
#define GLOB_ONLYDIR 0x0
#endif
#define MONTH_T 2628000
#define DAY_T 86400
#define HOUR_T 3600
#define MIN_T 60
typedef struct objeto_globber {
int options;
int type;
int user;
int group;
long unsigned sizeG;
long unsigned sizeL;
long unsigned month_t;
long unsigned day_t;
long unsigned hour_t;
long unsigned min_t;
/* private variables, not to be duplicated on recursion: */
struct stat *stinit;
struct stat st;
int pass;
time_t tiempo;
time_t actual;
int dostat;
} objeto_globber;
static int display(char *input){
printf("%s\n",input); /*fflush(NULL);*/
return 0;
}
#define DO_CHECK_PARAM if (!address) return 0; else objeto = (objeto_globber *)address;
/* public */
int glob_clear_options(void *address){
objeto_globber *objeto;
DO_CHECK_PARAM;
objeto->stinit=NULL;
objeto->user=-1,
objeto->group=-1,
objeto->options=0x0,
objeto->sizeG=0x0,
objeto->sizeL=0x0,
objeto->type=0x0,
objeto->month_t=0x0,
objeto->day_t=0x0,
objeto->hour_t=0x0;
objeto->min_t=0x0;
objeto->pass=0x0;
objeto->dostat=0x0;
return 1;
}
void *globber_create(void){
objeto_globber *objeto;
objeto=(objeto_globber *)malloc(sizeof(objeto_globber));
glob_clear_options((void *)objeto);
return (void *)objeto;
}
void *globber_destroy(void *address){
objeto_globber *objeto;
DO_CHECK_PARAM;
if (address) free(address);
if (objeto->stinit) free(objeto->stinit);
return NULL;
}
int glob_set_options(void *address,int options){
objeto_globber *objeto;
DO_CHECK_PARAM;
objeto->options |= options;
return 1;
}
int glob_set_type(void *address,int type){
objeto_globber *objeto;
DO_CHECK_PARAM;
objeto->type=type;
return 1;
}
int glob_set_sizeG(void *address,long unsigned size){
objeto_globber *objeto;
DO_CHECK_PARAM;
glob_set_options(objeto,GLOBBER_SIZE);
objeto->sizeG=size;
return 1;
}
int glob_set_sizeL(void *address,long unsigned size){
objeto_globber *objeto;
DO_CHECK_PARAM;
objeto->sizeL=size;
return 1;
}
int glob_set_user(void *address,int user){
objeto_globber *objeto;
DO_CHECK_PARAM;
glob_set_options(objeto,GLOBBER_USER);
objeto->user=user;
return 1;
}
int glob_set_group(void *address,int group){
objeto_globber *objeto;
DO_CHECK_PARAM;
glob_set_options(objeto,GLOBBER_GROUP);
objeto->group=group;
return 1;
}
int glob_set_time(void *address,long unsigned month_t,long unsigned day_t,
long unsigned hour_t,long unsigned min_t){
objeto_globber *objeto;
DO_CHECK_PARAM;
objeto->month_t=month_t;
objeto->day_t=day_t;
objeto->hour_t=hour_t;
objeto->min_t=min_t;
return 1;
}
/* if the user defined "operate" function returns TRUE, Globber will exit
* and return to calling module with the same return value */
int globber(void *address,char *path,int (*operate)(char *),char *filter) {
/* these variables must be kept on the heap */
glob_t dirlist;
int i;
char *globstring;
objeto_globber *object;
if (!address) object= (objeto_globber *)globber_create();
else object = (objeto_globber *)address;
if (object->options&GLOBBER_VERBOSE) fprintf(stderr,"path= %s\n",path);
if (object->options&GLOBBER_TIME) {
if (object->options&GLOBBER_MTIME)
object->options &=((GLOBBER_CTIME|GLOBBER_ATIME)^0xffffffff);
else if (object->options&GLOBBER_CTIME)
object->options &=(GLOBBER_ATIME^0xffffffff);
}
dirlist.gl_offs=2;
if (!operate) operate=display;
if (filter){
globstring = (char *)malloc(strlen(path)+strlen(filter)+2);
strcpy(globstring,path);
if (path[strlen(path)-1]!='/') strcat(globstring,"/");
strcat(globstring,filter);
} else globstring = path;
if (glob(globstring,GLOB_ERR|GLOB_TILDE,NULL,&dirlist) != 0) {
if (object->options&GLOBBER_VERBOSE) fprintf(stderr,"%s: no match\n",globstring);
}
else for (i=0;i<dirlist.gl_pathc;i++) {
if (object->options&GLOBBER_STAT) {
lstat(dirlist.gl_pathv[i],&(object->st));
if (object->options&GLOBBER_USER){
if (object->user != object->st.st_uid)
continue;
}
if (object->options&GLOBBER_GROUP){
if (object->group != object->st.st_gid)
continue;
}
if (object->options&GLOBBER_TIME){
object->actual=time(NULL);
if (object->options&GLOBBER_MTIME) object->tiempo=object->st.st_mtime;
if (object->options&GLOBBER_ATIME) object->tiempo=object->st.st_atime;
if (object->options&GLOBBER_CTIME) object->tiempo=object->st.st_ctime;
if ((object->min_t > 0) && ((object->actual-object->tiempo)/MIN_T > object->min_t))
continue;
if ((object->hour_t > 0) && ((object->actual-object->tiempo)/HOUR_T > object->hour_t))
continue;
if ((object->day_t > 0) && ((object->actual-object->tiempo)/DAY_T > object->day_t))
continue;
if ((object->month_t > 0) && ((object->actual-object->tiempo)/MONTH_T > object->month_t))
continue;
}
if (object->options&GLOBBER_SIZE){
if ((object->sizeL > 0)&&(object->st.st_size > object->sizeL))
continue;
if (object->st.st_size < object->sizeG)
continue;
}
if (object->options&GLOBBER_PERM){
if ((object->st.st_mode & 07777) & (object->type & 07777));
else {
if ((object->st.st_mode & 07777)==(object->type & 07777));
else continue;
}
}
if (object->options&GLOBBER_TYPE) {
if ((object->st.st_mode & S_IFMT)!=(object->type & S_IFMT))
continue;
}
} /* done lstat'ing */
if ((object->pass=(*(operate))(dirlist.gl_pathv[i]))!=0) break;
}
if (filter) free(globstring);
globfree(&dirlist);
if (object->pass) {
if (object->stinit) {free(object->stinit); object->stinit=NULL;}
return (object->pass); /* error returned from function */
}
if (object->options&GLOBBER_RECURSIVE) {
globstring = (char *)malloc(strlen(path)+3);
strcpy(globstring,path);
strcat(globstring,(globstring[strlen(globstring)-1]=='/')?"*":"/*");
if (glob(globstring,GLOB_ERR|GLOB_ONLYDIR|GLOB_TILDE,NULL,&dirlist) != 0) {
if (object->options&GLOBBER_VERBOSE) fprintf(stderr,"%s: no match\n",globstring);
}
else for (i=0;i<dirlist.gl_pathc;i++) {
lstat(dirlist.gl_pathv[i],&(object->st));
if ((object->st.st_mode & S_IFMT)!=S_IFDIR) continue; /* dont follow non-dirs. */
if ((object->st.st_mode & S_IFMT)==S_IFLNK) continue; /* dont follow symlinks */
if (object->options&GLOBBER_XDEV){
if (object->stinit==NULL) {
object->stinit=(struct stat *) malloc(sizeof (struct stat));
lstat(dirlist.gl_pathv[i],object->stinit);
}
else {
if (object->st.st_dev != object->stinit->st_dev) continue;
/* dont leave filesystem */
}
}
if (object->options&GLOBBER_VERBOSE)
fprintf(stderr,"directory: %s \n",dirlist.gl_pathv[i]);
object->pass=globber(address,dirlist.gl_pathv[i],operate,filter);
if (object->pass) break;
}
free(globstring);
globfree(&dirlist);
}
if (object->stinit) {free(object->stinit);object->stinit=NULL;}
return (object->pass);
}