1 /* nmcopyopdir.cc
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2001-2014 Ralf Hoffmann.
4  * You can contact me at: ralf@boomerangsworld.de
5  *   or http://www.boomerangsworld.de/worker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "nmcopyopdir.hh"
23 #include "copyopwin.hh"
24 #include "deleteop.h"
25 #include "simplelist.hh"
26 #include "verzeichnis.hh"
27 #include "fileentry.hh"
28 #include "copyorder.hh"
29 #include "deleteorder.hh"
30 
NM_CopyOp_Dir(const FileEntry * fe)31 NM_CopyOp_Dir::NM_CopyOp_Dir(const FileEntry *fe)
32 {
33   int erg;
34 
35   fileentry=fe;
36   subdirs=new List();
37   verz=new Verzeichnis();
38   files=dirs=error_counter=0;
39   bytes = 0;
40   ok=false;
41   user_abort = false;
42 
43   erg = verz->readDir( fe->fullname );
44   if ( erg == 0 ) ok = true;
45   else if ( erg > 0 ) user_abort = true;
46 }
47 
~NM_CopyOp_Dir()48 NM_CopyOp_Dir::~NM_CopyOp_Dir()
49 {
50   int id=subdirs->initEnum();
51   NM_CopyOp_Dir *cod=(NM_CopyOp_Dir*)subdirs->getFirstElement(id);
52   while(cod!=NULL) {
53     delete cod;
54     cod=(NM_CopyOp_Dir*)subdirs->getNextElement(id);
55   }
56   subdirs->closeEnum( id );
57   delete subdirs;
58   delete verz;
59 }
60 
61 int
createSubDirs(std::shared_ptr<struct copyorder> co,unsigned long * gf,unsigned long * gd)62 NM_CopyOp_Dir::createSubDirs( std::shared_ptr< struct copyorder > co,unsigned long *gf,unsigned long *gd)
63 {
64   NM_CopyOp_Dir *cod1;
65   bool enter;
66   bool cancel=false;
67 
68   /*TODO: vielleicht sollte der Fehler weitergereicht werden, aber cancel=true soll nicht entstehen
69     daher erstmal 0 zurueckgeben */
70   if(ok==false) return 0;
71 
72   if ( verz->dirOpened() == false ) return 0;
73 
74 /*TODO:Vorerst zu langsam, kann aber an MemSystem liegen, daher nochmal ohne
75        das pruefen
76   if(co->cowin!=NULL) {
77     co->cowin->setmessage(verz->getDir(),1);
78     if ( co->cowin->redraw() != 0 ) cancel = true;
79   }*/
80 
81   for ( Verzeichnis::verz_it fe_it1 = verz->begin();
82         fe_it1 != verz->end() && cancel == false;
83         fe_it1++ ) {
84     FileEntry *fe = *fe_it1;
85     if(strcmp(fe->name,"..")!=0) {
86       enter=false;
87       if(fe->isDir()==true) {
88         // fe is a dir, check if it is a link and take it only when follow_symlinks==true
89 	// entry is a dir so it cannot be a corrupt link so no need to check
90         if(fe->isLink==false) enter=true;
91         else if(co->follow_symlinks==true) enter=true;
92       }
93       if(enter==true) {
94         // fe is a dir so creating corresponding entry
95         cod1=new NM_CopyOp_Dir(fe);
96         if ( cod1->user_abort == false ) {
97           // recursive call
98           if(cod1->createSubDirs(co,gf,gd)!=0) cancel=true;
99         } else cancel = true;
100         // add the values from this subdir to this dir
101         files+=cod1->files;
102         dirs+=cod1->dirs;
103         bytes+=cod1->bytes;
104 
105         // add this subdir to the list
106         subdirs->addElement(cod1);
107 
108         // this is a dir so inc the counter
109         dirs++;
110         (*gd)++;
111 
112         if(co->cowin!=NULL) {
113           co->cowin->set_files_to_copy(*gf);
114           co->cowin->set_dirs_to_copy(*gd);
115           if ( co->cowin->redraw() & 1 ) cancel = true;
116         }
117       } else {
118         // is not dir (mostly a file but can also be links ...)
119         files++;
120         (*gf)++;
121         if ( ( fe->isLink == true ) &&
122              ( co->follow_symlinks == true ) &&
123              ( fe->isCorrupt == false ) ) {
124 	  bytes += fe->dsize();
125         } else {
126           bytes += fe->size();
127         }
128       }
129     }
130   }
131   return (cancel==true)?1:0;
132 }
133 
134 int
createSubDirs(struct deleteorder * delorder,unsigned long * gf,unsigned long * gd)135 NM_CopyOp_Dir::createSubDirs(struct deleteorder *delorder,unsigned long *gf,unsigned long *gd)
136 {
137   NM_CopyOp_Dir *cod1;
138   bool enter;
139   bool cancel=false;
140 
141   if(ok==false) return 0;
142 
143   if ( verz->dirOpened() == false ) return 0;
144 
145   for ( Verzeichnis::verz_it fe_it1 = verz->begin();
146         fe_it1 != verz->end() && cancel == false;
147         fe_it1++ ) {
148     FileEntry *fe = *fe_it1;
149     if(strcmp(fe->name,"..")!=0) {
150       enter=false;
151       if(fe->isDir()==true) {
152         // fe is a dir, check if it is a link and take it only when follow_symlinks==true
153         if(fe->isLink==false) enter=true;
154       }
155       if(enter==true) {
156         // fe is a dir so creating corresponding entry
157         cod1=new NM_CopyOp_Dir(fe);
158         if ( cod1->user_abort == false ) {
159           // recursive call
160           if(cod1->createSubDirs(delorder,gf,gd)!=0) cancel=true;
161         } else cancel = true;
162         // add the values from this subdir to this dir
163         files+=cod1->files;
164         dirs+=cod1->dirs;
165         bytes+=cod1->bytes;
166 
167         // add this subdir to the list
168         subdirs->addElement(cod1);
169 
170         // this is a dir so inc the counter
171         dirs++;
172         (*gd)++;
173 
174         if(delorder->dowin!=NULL) {
175           delorder->dowin->set_files_to_delete(*gf);
176           delorder->dowin->set_dirs_to_delete(*gd);
177           if(delorder->dowin->redraw()!=0) cancel=true;
178         }
179       } else {
180         // is not dir (mostly a file but can also be links ...)
181         files++;
182         (*gf)++;
183         // when deleting only size of file, not the dest matters
184         bytes += fe->size();
185       }
186     }
187   }
188   return (cancel==true)?1:0;
189 }
190 
191 int
createSubDirs()192 NM_CopyOp_Dir::createSubDirs()
193 {
194   NM_CopyOp_Dir *cod1;
195   bool enter;
196 
197   if(ok==false) return 0;
198 
199   if ( verz->dirOpened() == false ) return 0;
200 
201   for ( Verzeichnis::verz_it fe_it1 = verz->begin();
202         fe_it1 != verz->end();
203         fe_it1++ ) {
204     FileEntry *fe = *fe_it1;
205     if(strcmp(fe->name,"..")!=0) {
206       enter=false;
207       if(fe->isDir()==true) {
208         // fe is a dir, check if it is a link and take it only when follow_symlinks==true
209         if(fe->isLink==false) enter=true;
210       }
211       if(enter==true) {
212         // fe is a dir so creating corresponding entry
213         cod1=new NM_CopyOp_Dir(fe);
214         // recursive call
215         cod1->createSubDirs();
216 
217         // add this subdir to the list
218         subdirs->addElement(cod1);
219       }
220     }
221   }
222   return 0;
223 }
224