Back to index

nordugrid-arc-nox  1.1.0~rc6
delete.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <unistd.h>
00008 #include <cstring>
00009 #include <cstdio>
00010 #include <cstdlib>
00011  
00012 #include <string>
00013 
00014 #include <glibmm.h>
00015 
00016 #include "../files/info_types.h"
00017 #include "delete.h"
00018 
00019 struct FL_p {
00020   const char* s;
00021   FL_p* next;
00022   FL_p* prev;
00023 };
00024 
00025 /* return values: 0 - empty, 1 - has files, 2 - failed */
00026 static int delete_all_recur(const std::string &dir_base,
00027                             const std::string &dir_cur,
00028                             FL_p **fl_list,bool excl) {
00029   /* take corresponding members of fl_list */
00030   FL_p* fl_new = NULL;  /* new list */
00031   FL_p* fl_cur = (*fl_list); /* pointer in old list */
00032   int l = dir_cur.length();
00033   /* extract suitable files from list */
00034   for(;;) {
00035     if(fl_cur == NULL) break;
00036     FL_p* tmp = fl_cur->next;
00037     if(!strncmp(fl_cur->s,dir_cur.c_str(),l)) {
00038       if(fl_cur->s[l] == '/') {
00039         /* remove from list */
00040         if(fl_cur->prev == NULL) { (*fl_list)=fl_cur->next; }
00041         else { fl_cur->prev->next=fl_cur->next; };
00042         if(fl_cur->next == NULL) { }
00043         else { fl_cur->next->prev=fl_cur->prev; };
00044         /* add to list */
00045         fl_cur->prev=NULL; fl_cur->next=fl_new;
00046         if(fl_new == NULL) { fl_new=fl_cur; }
00047         else { fl_new->prev = fl_cur; fl_new=fl_cur; };
00048       };
00049     };
00050     fl_cur=tmp;
00051   };
00052   /* go through directory and remove files */
00053   std::string file;
00054   std::string dir_s = dir_base+dir_cur;
00055   int files = 0;
00056   try {
00057     Glib::Dir dir(dir_s);
00058     for(;;) {
00059       file=dir.read_name();
00060       if(file.empty()) break;
00061       if(file == ".") continue;
00062       if(file == "..") continue;
00063       fl_cur = fl_new;
00064       for(;;) {
00065         if(fl_cur == NULL) break;
00066         if(!strcmp(file.c_str(),(fl_cur->s)+(l+1))) {
00067           /* do not delete or delete */
00068           break;
00069         };
00070         fl_cur=fl_cur->next;
00071       };
00072       if(excl) {
00073         if(fl_cur == NULL) {
00074           /* delete */
00075           struct stat f_st;
00076           std::string fname=dir_s+'/'+file;
00077           if(lstat(fname.c_str(),&f_st) != 0) { files++; }
00078           else if(S_ISDIR(f_st.st_mode)) {
00079             if(delete_all_recur(dir_base,
00080                           dir_cur+'/'+file,&fl_new,excl) != 0) {
00081               files++;
00082             }
00083             else {
00084               if(remove(fname.c_str()) != 0) { files++; };
00085             };
00086           }
00087           else {
00088             if(remove(fname.c_str()) != 0) { files++; };
00089           };
00090         }
00091         else { files++; };
00092       }
00093       else {
00094         struct stat f_st;
00095         std::string fname=dir_s+'/'+file;
00096         if(lstat(fname.c_str(),&f_st) != 0) { files++; }
00097         else if(S_ISDIR(f_st.st_mode)) {
00098           if(fl_cur != NULL) { /* MUST delete it */
00099             FL_p* e = NULL;
00100             if(delete_all_recur(dir_base,
00101                           dir_cur+'/'+file,&e,true) != 0) {
00102               files++;
00103             }
00104             else { 
00105               if(remove(fname.c_str()) != 0) { files++; }; 
00106             };
00107           }
00108           else { /* CAN delete if empty, and maybe files inside */
00109             if(delete_all_recur(dir_base,
00110                           dir_cur+'/'+file,&fl_new,excl) != 0) {
00111               files++;
00112             }
00113             else {
00114               if(remove(fname.c_str()) != 0) { files++; };
00115             };
00116           };
00117         }
00118         else {
00119           if(fl_cur != NULL) { /* MUST delete this file */
00120             if(remove(fname.c_str()) != 0) { files++; };
00121           }
00122           else { files++; };
00123         };
00124       };
00125     };
00126   } catch(Glib::FileError& e) { return 2; };
00127   if(files) return 1;
00128   return 0;
00129 }
00130 
00131 
00132 static int delete_links_recur(const std::string &dir_base,const std::string &dir_cur) {
00133   std::string file;
00134   std::string dir_s = dir_base+dir_cur;
00135   int res = 0;
00136   try {
00137     Glib::Dir dir(dir_s);
00138     for(;;) {
00139       file=dir.read_name();
00140       if(file.empty()) break;
00141       if(file == ".") continue;
00142       if(file == "..") continue;
00143       struct stat f_st;
00144       std::string fname=dir_s+'/'+file;
00145       if(lstat(fname.c_str(),&f_st) != 0) { res|=1; }
00146       else if(S_ISDIR(f_st.st_mode)) {
00147         res|=delete_links_recur(dir_base,dir_cur+'/'+file);
00148       }
00149       else {
00150         if(remove(fname.c_str()) != 0) { res|=1; };
00151       };
00152     };
00153   } catch(Glib::FileError& e) { return 2; };
00154   return res;
00155 }
00156 
00157 int delete_all_links(const std::string &dir_base,const std::list<FileData>&) {
00158   std::string dir_cur("");
00159   return delete_links_recur(dir_base,dir_cur);
00160 }
00161 
00162 /* filenames should start from / and not to have / at end */
00163 int delete_all_files(const std::string &dir_base,const std::list<FileData> &files,
00164              bool excl,bool lfn_exs,bool lfn_mis) {
00165   int n = files.size();
00166   FL_p* fl_list = NULL;
00167   if(n != 0) { 
00168     if((fl_list=(FL_p*)malloc(sizeof(FL_p)*n)) == NULL) { return 2; };
00169     std::list<FileData>::const_iterator file=files.begin();
00170 //    fl_list[0].s=file->pfn.c_str();
00171     int i;
00172     for(i=0;i<n;) {
00173       if(((lfn_exs) && (file->lfn.find(':') != std::string::npos)) ||
00174          ((lfn_mis) && (file->lfn.find(':') == std::string::npos))) {
00175         if(excl) {
00176           if(file->pfn == "/") { /* keep all requested */
00177             free(fl_list); return 0;
00178           };
00179         };
00180         fl_list[i].s=file->pfn.c_str();
00181         if(i) { fl_list[i].prev=fl_list+(i-1); fl_list[i-1].next=fl_list+i; }
00182         else { fl_list[i].prev=NULL; };
00183         fl_list[i].next=NULL;
00184         i++;
00185       };
00186       ++file; if(file == files.end()) break;
00187     };
00188     if(i==0) { free(fl_list); fl_list=NULL; };
00189   };
00190   std::string dir_cur("");
00191   FL_p* fl_list_tmp = fl_list;
00192   int res=delete_all_recur(dir_base,dir_cur,&fl_list_tmp,excl);
00193   if(fl_list) free(fl_list);
00194   return res;
00195 }
00196