/* * Salvage, Purge, Lsdel source * Copyright (c)2004-2005 by Marek Zelem */ #include #include #include #include #include "libdare.h" union strint { char *s; unsigned long i; }; struct args { char mount[PATH_MAX+1]; char dir[PATH_MAX+1]; char tmp[PATH_MAX+1]; unsigned int uid; char *me; int numeric; int verbose; int recursive; int interactive; int argc; int pos; union strint argv[0]; }; /* what: & 0x01 - deleted file , 0x02 - original directory */ static int permission( struct args *args, struct dare_info *info, int what ) { if( args->uid!=0 && (what & 0x01) ) { if( info->uid!=args->uid ) return(0); } if( args->uid!=0 && (what & 0x02) ) { char *p,*s; struct stat st; p=dare_orig_path(info); if( (s=strrchr(p,'/'))!=NULL ) *s=0; else *p=0; if( *p==0 ) p="/"; if( lstat(p,&st)!=0 ) return(0); if( st.st_uid!=args->uid ) return(0); } return(1); } int tmp2mount_dir( struct args *args ) { FILE *f; char buf[1024+1]; char *p; int x; args->mount[0]=0; args->dir[0]=0; if( (f=fopen("/proc/mounts","r"))==NULL ) { if( (f=fopen("/etc/mtab","r"))==NULL ) { strcpy(args->dir,args->tmp); return(0); } } while( (p=fgets(buf,1024,f))!=NULL ) { p+=strcspn(p," "); p+=strspn(p," "); x=strcspn(p," "); p[x]=0; if( x==0 ) continue; if( !strncmp(args->tmp,p,x) && (args->tmp[x]==0 || args->tmp[x]=='/') && x>strlen(args->mount) ) { strncpy(args->mount,p,PATH_MAX); } } fclose(f); x=strlen(args->mount); if( args->tmp[x]=='/' ) x++; args->dir[0]='/'; strncpy(args->dir+1,args->tmp+x,PATH_MAX-1-1); if( args->dir[strlen(args->dir)-1]!='/' ) strcpy(args->dir+strlen(args->dir),"/"); return(0); } static int test_patterns( struct args *args, struct dare_info *info ) { int i; if( args->numeric ) { for(i=0;iargc;i++) { if( args->argv[i].i==info->ino ) return(1); } } else { for(i=0;iargc;i++) { if( !fnmatch(args->argv[i].s,dare_minimize_path(args->dir,info->path),FNM_PATHNAME|FNM_PERIOD) ) return(1); } } return(0); } int func_lsdel( struct args *args, struct dare_info *info ) { char *buf; if( !dare_is_in_dir(info,args->dir,args->recursive) || (args->argc>0 && !test_patterns(args,info)) || !permission(args,info,2) || !dare_exist(info) ) { free(info); return(0); } if( (buf=dare_ls(info,(args->verbose==0 ? 2 : 3),args->dir))!=NULL ) printf("%s\n",buf); free(info); return(1); } static int interactive_test( struct args *args, struct dare_info *info, char *prompt ) { char *buf; int c; if( (buf=dare_ls(info,3,args->dir))==NULL ) return(0); fprintf(stdout,"%s\n%s (y/n) : ",buf,prompt); fflush(stdout); for(;;) { c=fgetc(stdin); if( c<0 ) { return(0); } if( strchr("yn",c)!=NULL ) break; } fprintf(stdout,"%c\n",c); if( c=='y' ) return(1); return(0); } int func_purge( struct args *args, struct dare_info *info ) { int r=0; if( !dare_is_in_dir(info,args->dir,args->recursive) || (args->argc>0 && !test_patterns(args,info)) || !permission(args,info,3) || !dare_exist(info) ) { free(info); return(0); } if( args->interactive==0 || interactive_test(args,info,"Purge this file?") ) { if( dare_purge(info)<0 ) perror(args->me); else { printf("%s purged\n",dare_minimize_path(args->dir,info->path)); r=1; } } free(info); return(r); } int func_salvage( struct args *args, struct dare_info *info ) { int r=0; if( !dare_is_in_dir(info,args->dir,args->recursive) || (args->argc>0 && !test_patterns(args,info)) || !permission(args,info,3) || !dare_exist(info) ) { free(info); return(0); } if( args->interactive==0 || interactive_test(args,info,"Salvage this file?") ) { if( dare_salvage(info)<0 ) perror(args->me); else { printf("%s salvaged\n",dare_minimize_path(args->dir,info->path)); r=1; } } free(info); return(r); } void usage( char *me ) { printf( "Usage: %s [-p path] [-r] [-y] [-v] [--] pattern ... \n" " %s [-p path] [-r] [-y] [-v] -n inode ... \n" ,me,me); } int main( int argc, char *argv[] ) { int a,noopt; char *p; struct args *args; struct termios oldterm,newterm; if( (args=malloc(sizeof(struct args)+argc*sizeof(char *)))==NULL ) { perror("Out of memory\n"); return(-1); } args->uid=getuid(); args->numeric=0; args->verbose=0; args->recursive=0; args->interactive=1; args->argc=0; args->pos=0; noopt=0; a=0; args->me=argv[a++]; if( (p=strrchr(args->me,'/'))!=NULL ) args->me=p+1; if( !strcmp(args->me,"lsdel") ) args->interactive=0; args->tmp[0]=0; getcwd(args->tmp,PATH_MAX); while( a=argc ) { usage(args->me); return(-1); } a++; if( argv[a][0]=='/' ) strncpy(args->tmp,argv[a],PATH_MAX); else snprintf(args->tmp+strlen(args->tmp),PATH_MAX-strlen(args->tmp)-1,"/%s",argv[a]); args->tmp[PATH_MAX]=0; } else if( !strcmp(argv[a],"-n") ) { if( args->argc>0 ) { usage(args->me); return(-1); } args->numeric=1; } else if( !strcmp(argv[a],"-v") ) { args->verbose++; } else if( !strcmp(argv[a],"-r") ) { args->recursive=1; } else if( !strcmp(argv[a],"-y") ) { args->interactive=0; } else if( !strcmp(argv[a],"--") ) { noopt=1; } else { usage(args->me); return(0); } a++; } else { if( args->numeric ) { char *end; if( argv[a][0]==0 ) { usage(args->me); return(-1); } args->argv[args->argc++].i=strtoul(argv[a++],&end,10); if( *end ) { usage(args->me); return(-1); } } else args->argv[args->argc++].s=argv[a++]; } } tmp2mount_dir(args); // printf("me: %s\nmountpoint: %s\ndir: %s\nall: %s\n",args->me,args->mount,args->dir,args->tmp); if( !dare_is_supported(args->mount) ) { fprintf(stderr,"%s: Not supported for this directory\n",args->me); free(args); return(0); } if( args->interactive ) { if( tcgetattr(0,&oldterm)<0 ) { perror(args->me); free(args); return(-1); } newterm=oldterm; newterm.c_iflag=(BRKINT); newterm.c_oflag=(OPOST|ONLCR); newterm.c_cflag=(CS8|CLOCAL); newterm.c_lflag=(ISIG); tcsetattr(0,TCSANOW,&newterm); } if( !strcmp(args->me,"lsdel") ) { if( dare_info_foreach_inf(args->mount,dare_info_foreach,(dare_info_do_t)func_lsdel,(void *)args)<0 ) perror(args->me); } else if( !strcmp(args->me,"salvage") ) { if( dare_info_foreach_inf(args->mount,dare_info_foreach,(dare_info_do_t)func_salvage,(void *)args)<0 ) perror(args->me); } else if( !strcmp(args->me,"purge") ) { if( dare_info_foreach_inf(args->mount,dare_info_foreach,(dare_info_do_t)func_purge,(void *)args)<0 ) perror(args->me); } if( args->interactive ) { tcsetattr(0,TCSANOW,&oldterm); } free(args); return(0); }