Don't copy DirectoryOpus.CFG because that file works
[AROS-Contrib.git] / dopus / Program / main18.c
blob9861f0c4e5ecda2e3aca9b4e5b9c06c81da3a129
1 /*
3 Directory Opus 4
4 Original GPL release version 4.12
5 Copyright 1993-2000 Jonathan Potter
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 All users of Directory Opus 4 (including versions distributed
22 under the GPL) are entitled to upgrade to the latest version of
23 Directory Opus version 5 at a reduced price. Please see
24 http://www.gpsoft.com.au for more information.
26 The release of Directory Opus 4 under the GPL in NO WAY affects
27 the existing commercial status of Directory Opus 5.
31 #include "dopus.h"
33 struct makedirlist {
34 struct makedirlist *last,*next;
35 char *path;
38 struct recurse {
39 struct recurse *last;
40 char *dir,*dest;
41 long data;
42 APTR data2;
43 APTR data3;
44 BPTR lock;
45 struct FileInfoBlock info;
46 struct Directory *entry;
47 struct DirectoryWindow lister;
50 int copymakedir(struct DOpusRemember **,struct makedirlist **,char *,struct FileInfoBlock *);
52 struct recurse *current_recurse;
54 int recursedir(fdir,fdest,dowhat,fdata)
55 char *fdir,*fdest;
56 int dowhat,fdata;
58 struct FileInfoBlock __aligned myfinfo;
59 struct FileInfoBlock __aligned enfinfo;
60 BPTR mylock;
61 char *name,
62 *dir,
63 *dest,
64 *dname,
65 *ddir,
66 *adir,
67 *adest,
68 *ndir,
69 *ndest;
70 int suc,
71 to_do,
72 ret=0,
74 err,
75 adata,
76 depth=0,
78 rtry,
79 blocks;
80 long *pstuff,
81 data=fdata;
82 struct recpath *crec=NULL,*trec;
83 struct RecursiveDirectory *cur_recurse,
84 *addparent_recurse,
85 *new_rec,
86 *pos_rec,
87 *cur_parent,
88 *cur_lastparent=NULL;
89 APTR data2=NULL,
90 adata2=NULL,
91 data3=NULL,
92 adata3=NULL;
93 struct DOpusRemember *memkey=NULL;
94 struct makedirlist *first_makedir=NULL;
95 struct DirectoryWindow lister;
96 struct Directory *entry = NULL;
98 if (dowhat&R_STARDIR) {
99 rec_firstpath=NULL;
100 rec_pathkey=NULL;
103 if (dowhat&R_GETNAMES) {
104 first_recurse=NULL;
105 recurse_dir_key=NULL;
106 cur_recurse=NULL;
107 addparent_recurse=NULL;
110 current_recurse=NULL;
112 recurse_max_depth=0;
114 dos_global_bytecount=0;
115 dos_global_copiedbytes=0;
116 dos_global_deletedbytes=0;
117 dos_global_blocksneeded=0;
118 dos_global_files=0;
120 //D(bug("recursedir: %s\n",fdir));
121 if (dopus_curwin[data_active_window]->xai)
123 lister = *(dopus_curwin[data_active_window]);
124 for(entry = lister.firstentry; entry && (!(entry->selected));) entry=entry->next;
125 arcfillfib(&myfinfo,entry);
127 mylock = NULL;
129 else
131 if (!(mylock=Lock(fdir,ACCESS_READ))) {
132 doerror(-1);
133 return(-1);
135 Examine(mylock,&myfinfo);
137 if (!(name=LAllocRemember(&memkey,5*512,MEMF_CLEAR))) {
138 doerror(-1);
139 return(-1);
141 dir=name+512; dest=dir+512; dname=dest+512; ddir=dname+512;
142 if (fdir) strcpy(dir,fdir);
143 if (fdest) strcpy(dest,fdest);
145 if (dowhat&R_COPY) {
146 strcpy(ddir,dest);
147 if (!(a=copymakedir(&memkey,&first_makedir,dest,&myfinfo)) || a==-1) {
148 UnLock(mylock);
149 ret = a ? -10 : -3;
150 goto goaway;
153 if (mylock) to_do=ExNext(mylock,&myfinfo);
154 else
156 lister.firstentry=lister.firstfile=lister.firstdir=NULL;
157 lister.total=lister.filesel=lister.dirsel=lister.dirtot=lister.filetot=0;
158 lister.bytessel = 0;
159 lister.bytestot = 0;
160 strcpy(lister.directory,dir);
161 strcat(lister.directory,"/");
162 readarchive(&lister,0);
163 D(for(entry = lister.firstentry; entry; entry=entry->next) bug("entry: %s\n",entry->name));
164 arcfillfib(&myfinfo,entry = lister.firstentry);
165 to_do = lister.total;
168 FOREVER {
169 if (status_haveaborted) {
170 myabort();
171 ret=-10;
172 break;
174 if (!to_do) {
175 if (current_recurse) {
176 UnLock(mylock);
177 strcpy(dname,dir);
178 mylock=current_recurse->lock;
179 if ((entry = current_recurse->entry))
181 struct Directory *t_entry;
183 lister = current_recurse->lister;
184 for (to_do = lister.total, t_entry = lister.firstentry; t_entry != entry; to_do--, t_entry = t_entry->next);
186 myfinfo=current_recurse->info;
187 //D(bug("current_recurse->dir=%s\n",current_recurse->dir));
188 strcpy(dir,current_recurse->dir);
189 //D(bug("current_recurse->dest=%s\n",current_recurse->dest));
190 strcpy(dest,current_recurse->dest);
191 data=current_recurse->data;
192 data2=current_recurse->data2;
193 data3=current_recurse->data3;
194 current_recurse=current_recurse->last;
196 strcpy(name,dir);
197 TackOn(name,myfinfo.fib_FileName,512);
199 if (dowhat&R_GETNAMES) {
200 cur_recurse=(struct RecursiveDirectory *)data2;
201 cur_lastparent=(struct RecursiveDirectory *)data3;
202 addparent_recurse=NULL;
205 else if (dowhat&R_COPY) {
206 strcpy(ddir,dest);
207 if (config->copyflags&COPY_DATE) {
208 TackOn(ddir,myfinfo.fib_FileName,512);
209 setdate(ddir,&myfinfo.fib_Date);
210 strcpy(ddir,dest);
214 a=0;
215 if (dowhat&R_COMMENT) {
216 FOREVER {
217 if (!(SetComment(name,dest))) {
218 doerror(err=IoErr());
219 a=checkerror(globstring[STR_COMMENTING],myfinfo.fib_FileName,err);
220 if (a==1) continue;
222 break;
224 if (a==3) break;
227 else if (dowhat&R_PROTECT) {
228 pstuff=(long *)data;
229 b=getnewprot(myfinfo.fib_Protection,pstuff[0],pstuff[1]);
230 FOREVER {
231 if (!(SetProtection(name,b))) {
232 doerror(err=IoErr());
233 a=checkerror(globstring[STR_PROTECTING],myfinfo.fib_FileName,err);
234 if (a==1) continue;
236 break;
238 if (a==3) break;
241 else if (dowhat&R_DATESTAMP) {
242 FOREVER {
243 if ((err=setdate(name,(struct DateStamp *)data))!=1) {
244 doerror(err);
245 a=checkerror(globstring[STR_DATESTAMPING],myfinfo.fib_FileName,err);
246 if (a==1) continue;
248 break;
250 if (a==3) break;
253 if (mylock) to_do=ExNext(mylock,&myfinfo);
254 else
256 arcfillfib(&myfinfo,entry = entry->next);
257 to_do--;
259 if (dowhat&R_DELETE && depth>0) {
260 a=strlen(dname);
261 if (a>0 && dname[a-1]=='/') dname[a-1]=0;
262 if ((a=delfile(dname,BaseName(dname),globstring[STR_DELETING],
263 glob_unprotect_all,1))==-1) {
264 myabort();
265 ret=-10;
266 break;
268 if (a==2) glob_unprotect_all=1;
270 --depth;
271 continue;
273 else break;
275 CopyMemQuick((char *)&myfinfo,(char *)&enfinfo,sizeof(struct FileInfoBlock));
277 strcpy(name,dir);
278 TackOn(name,enfinfo.fib_FileName,512);
280 //D(bug("direntrytype: %ld\n",enfinfo.fib_DirEntryType));
281 if (enfinfo.fib_DirEntryType>0) {
282 ++dos_global_blocksneeded;
283 if (enfinfo.fib_DirEntryType!=4) {
284 adir=NULL;
285 dofilename(name);
286 if (dowhat&R_GETNAMES) {
287 if ((new_rec=LAllocRemember(&recurse_dir_key,sizeof(struct RecursiveDirectory),MEMF_CLEAR))) {
288 strcpy(new_rec->name,enfinfo.fib_FileName);
289 CopyMem((char *)&enfinfo.fib_Date,(char *)&new_rec->date,sizeof(struct DateStamp));
290 if (addparent_recurse) {
291 addparent_recurse->child=new_rec;
292 cur_lastparent=addparent_recurse;
293 cur_recurse=new_rec;
295 else if (!first_recurse) {
296 first_recurse=new_rec;
297 cur_recurse=new_rec;
299 else if (cur_recurse) {
300 if (Stricmp(new_rec->name,cur_recurse->name)<0) {
301 if (first_recurse==cur_recurse) first_recurse=new_rec;
302 if (cur_lastparent && cur_lastparent->child==cur_recurse)
303 cur_lastparent->child=new_rec;
304 new_rec->next=cur_recurse;
305 cur_recurse=new_rec;
307 else {
308 pos_rec=cur_recurse;
309 FOREVER {
310 if (!pos_rec->next ||
311 (Stricmp(new_rec->name,pos_rec->next->name)<0)) {
312 new_rec->next=pos_rec->next;
313 pos_rec->next=new_rec;
314 break;
316 pos_rec=pos_rec->next;
320 else cur_recurse=new_rec;
321 cur_parent=new_rec;
323 adir=dir; adest=dest; ndir=name; ndest=dest;
324 adata2=(APTR)cur_recurse;
325 adata3=(APTR)cur_lastparent;
326 addparent_recurse=cur_parent;
328 //D(bug("recursedir_1: %lx\n",dest));
329 strcpy(dname,dest);
330 if (dowhat&R_COPY) {
332 dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-2,0,enfinfo.fib_FileName,1);
334 TackOn(dname,enfinfo.fib_FileName,512);
335 D(bug("name: %s\n",dname));
336 adir=dir; adest=dest; adata=data; ndir=name; ndest=dname;
337 strcpy(ddir,dname);
338 if ((a=copymakedir(&memkey,&first_makedir,ddir,&enfinfo))==-1) {
339 ret=-10;
340 break;
342 else if (a==0) adir=NULL;
344 if (dowhat&R_DELETE) {
345 rtry=1;
346 delloop:
347 if (!DeleteFile(name)) {
348 if (config->deleteflags&8 && rtry==1 && IoErr()==222) {
349 rtry=0;
350 SetProtection(name,0);
351 goto delloop;
353 adir=dir; adest=dest; adata=data; ndir=name; ndest=dname;
355 else {
356 if (config->dynamicflags&UPDATE_FREE) seename(data_active_window);
357 adir=NULL;
360 else if (dowhat&(R_HUNT|R_SEARCH|R_COMMENT|R_PROTECT|R_DATESTAMP|R_GETBYTES|R_STARDIR)) {
361 adir=dir; adest=dest; adata=data; ndir=name; ndest=dest;
362 adata2=data2; adata3=data3;
364 if (adir) {
365 if (!(addrecurse(&memkey,adir,adest,adata,adata2,adata3,mylock,&enfinfo,mylock?NULL:entry,&lister))) {
366 if (mylock) to_do=0;
367 continue;
369 //D(bug("recursedir_2: %lx\n",ndir));
370 strcpy(dir,ndir);
371 //D(bug("recursedir_3: %lx\n",ndest));
372 strcpy(dest,ndest);
373 if (mylock)
375 if (!(mylock=Lock(dir,ACCESS_READ))) {
376 to_do=0;
377 continue;
379 Examine(mylock,&myfinfo);
380 to_do=ExNext(mylock,&myfinfo);
382 else
384 lister.firstentry=lister.firstfile=lister.firstdir=NULL;
385 lister.total=lister.filesel=lister.dirsel=lister.dirtot=lister.filetot=0;
386 lister.bytessel = 0;
387 lister.bytestot = 0;
388 strcpy(lister.directory,dir);
389 strcat(lister.directory,"/");
390 readarchive(&lister,0);
391 D(for(entry = lister.firstentry; entry; entry=entry->next) bug("entry: %s\n",entry->name));
392 arcfillfib(&myfinfo,entry = lister.firstentry);
393 to_do = lister.total;
395 ++depth;
396 if (depth>recurse_max_depth) recurse_max_depth=depth;
397 continue;
401 if (enfinfo.fib_DirEntryType<0) {
402 a=0;
403 dos_global_bytecount+=enfinfo.fib_Size;
404 dos_global_files++;
405 if (dowhat&R_GETBYTES && data) {
406 blocks=(enfinfo.fib_Size+(data-1))/data;
407 dos_global_blocksneeded+=blocks+(blocks/72)+1;
410 if (dowhat&R_GETNAMES) goto skipgetnam;
411 // if (!(dowhat & (R_GETBYTES | R_DELETE | R_HUNT))) dofilename(name);
412 else if (dowhat&R_STARDIR) {
413 if ((trec=LAllocRemember(&rec_pathkey,sizeof(struct recpath),MEMF_ANY/*CLEAR*/)) &&
414 (trec->path=LAllocRemember(&rec_pathkey,(strlen(name)+1)-data,MEMF_ANY/*CLEAR*/))) {
415 trec->next=NULL;
416 D(bug("recursedir_4: %s\n",name+data));
417 strcpy(trec->path,&name[data]);
418 if (crec) crec->next=trec;
419 crec=trec;
420 if (!rec_firstpath) rec_firstpath=trec;
423 if (!str_filter_parsed[0] ||
424 LMatchPatternI(str_filter_parsed,enfinfo.fib_FileName)) {
425 if (dowhat&R_COPY) {
426 strcpy(dname,ddir);
427 TackOn(dname,enfinfo.fib_FileName,512);
429 dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-2,0,enfinfo.fib_FileName,1);
430 D(bug("file: %s\n",name));
431 if (!mylock)
433 char tempname[FILEBUF_SIZE];
435 strcpy(name,"T:");
436 if (! unarcfiledir(&lister,name,tempname,enfinfo.fib_FileName)) continue;
437 AddPart(name,tempname,512);
439 a=0;
440 if (askeach) {
441 if ((a=checkexistreplace(name,dname,&enfinfo.fib_Date,1,1))==REPLACE_ABORT) {
442 myabort();
443 ret=-10;
444 break;
446 if (a==REPLACE_ALL) {
447 askeach=0;
449 else if (a==REPLACE_SKIPALL) {
450 askeach = 0;
451 autoskip = 1;
453 // if (a==REPLACE_SKIP)
455 if (!autoskip && (a!=REPLACE_SKIP))
457 a=0;
458 FOREVER {
459 if (!(a=copyfile(name,dname,&err,/*-1,*/NULL,0))) {
460 doerror(err);
461 a=checkerror(globstring[STR_COPYING],enfinfo.fib_FileName,err);
462 if (a==1) continue;
463 if (a!=3) seename(data_active_window);
465 else if (a==-1) {
466 myabort();
467 a=3;
468 break;
470 else {
471 if (dowhat==R_COPY) {
472 if (config->copyflags&COPY_ARC && !(enfinfo.fib_Protection&FIBF_ARCHIVE))
473 SetProtection(name,enfinfo.fib_Protection|FIBF_ARCHIVE);
475 dos_global_copiedbytes+=enfinfo.fib_Size;
477 if (config->dynamicflags&UPDATE_FREE) seename(data_active_window);
478 break;
480 dotaskmsg(hotkeymsg_port,PROGRESS_INCREASE,1,0,NULL,0);
481 if (!mylock) removetemparcfile(name);
482 if (a==3) {
483 ret=-10;
484 break;
486 else if (config->dynamicflags&UPDATE_FREE) {
487 seename(data_active_window);
488 seename(1-data_active_window);
491 else if (!mylock) removetemparcfile(name);
493 if (dowhat&R_DELETE) {
494 if (!((dowhat&R_COPY) && (a==2)))
496 if ((a=delfile(name,enfinfo.fib_FileName,globstring[STR_DELETING],
497 glob_unprotect_all,1))==-1) {
498 myabort();
499 ret=-10;
500 break;
502 if (a==2) glob_unprotect_all=1;
503 if (config->dynamicflags&UPDATE_FREE) seename(data_active_window);
504 dos_global_deletedbytes+=enfinfo.fib_Size;
507 else if (dowhat&R_COMMENT) {
508 FOREVER {
509 if (!(SetComment(name,dest))) {
510 doerror(err=IoErr());
511 a=checkerror(globstring[STR_COMMENTING],enfinfo.fib_FileName,err);
512 if (a==1) continue;
514 break;
516 if (a==3) {
517 ret=-10;
518 break;
521 else if (dowhat&R_PROTECT) {
522 pstuff=(long *)data;
523 b=getnewprot(enfinfo.fib_Protection,pstuff[0],pstuff[1]);
524 FOREVER {
525 if (!(SetProtection(name,b))) {
526 doerror(err=IoErr());
527 a=checkerror(globstring[STR_PROTECTING],enfinfo.fib_FileName,err);
528 if (a==1) continue;
530 break;
532 if (a==3) {
533 ret=-10;
534 break;
537 else if (dowhat&R_DATESTAMP) {
538 FOREVER {
539 if ((err=setdate(name,(struct DateStamp *)data))!=1) {
540 doerror(err=IoErr());
541 a=checkerror(globstring[STR_DATESTAMPING],enfinfo.fib_FileName,err);
542 if (a==1) continue;
544 break;
546 if (a==3) {
547 ret=-10;
548 break;
551 else if (dowhat&R_HUNT) {
552 suc=huntfile(enfinfo.fib_FileName,name,&a);
553 ret+=a;
554 if (suc) {
555 if (suc==-1) {
556 myabort();
557 ret=-10;
559 else ret=suc;
560 break;
563 else if (dowhat&R_SEARCH) {
564 D(bug("file: %s\n",name));
565 if (!mylock)
567 char tempname[FILEBUF_SIZE];
569 strcpy(name,"T:");
570 if (! unarcfiledir(&lister,name,tempname,enfinfo.fib_FileName)) continue;
571 AddPart(name,tempname,256);
573 suc=filesearch(name,&a,0);
574 if (!mylock) removetemparcfile(name);
575 ret+=a;
576 busy();
577 if (suc==2) {
578 if (!simplerequest(globstring[STR_CONTINUE_WITH_SEARCH],
579 globstring[STR_CONTINUE],str_cancelstring,NULL)) {
580 okay();
581 ret=-2;
582 break;
585 skipgetnam:
586 if (suc==-1) {
587 myabort();
588 ret=-10;
589 break;
594 if (mylock) to_do=ExNext(mylock,&myfinfo);
595 else
597 arcfillfib(&myfinfo,entry = entry->next);
598 to_do--;
602 UnLock(mylock);
603 while (current_recurse) {
604 UnLock(current_recurse->lock);
605 current_recurse=current_recurse->last;
607 if (first_makedir &&
608 dowhat==R_COPY &&
609 str_filter_parsed[0]) {
611 struct makedirlist *last=first_makedir;
613 while (last->next) last=last->next;
615 while (last) {
616 DeleteFile(last->path);
617 last=last->last;
620 goaway:
621 if (memkey) LFreeRemember(&memkey);
622 return(ret);
625 int addrecurse(key,dir,dest,data,data2,data3,lock,info,entry,lister)
626 struct DOpusRemember **key;
627 char *dir,*dest;
628 int data;
629 APTR data2,data3;
630 BPTR lock;
631 struct FileInfoBlock *info;
632 struct Directory *entry;
633 struct DirectoryWindow *lister;
635 struct recurse *rec;
637 if (!(rec=LAllocRemember(key,sizeof(struct recurse),MEMF_ANY/*MEMF_CLEAR*/)))
638 return(0);
639 rec->last = current_recurse;
640 if (!(rec->dir=LAllocRemember(key,strlen(dir)+1,MEMF_ANY/*MEMF_CLEAR*/)) ||
641 !(rec->dest=LAllocRemember(key,strlen(dest)+1,MEMF_ANY/*MEMF_CLEAR*/)))
642 return(0);
643 strcpy(rec->dir,dir);
644 strcpy(rec->dest,dest);
645 rec->data=data;
646 rec->data2=data2;
647 rec->data3=data3;
648 rec->lock=lock;
649 rec->info=*info;
650 rec->entry=entry;
651 if (entry) rec->lister=*lister;
652 current_recurse=rec;
653 return(1);
656 int copymakedir(key,first,dirname,finfo)
657 struct DOpusRemember **key;
658 struct makedirlist **first;
659 char *dirname;
660 struct FileInfoBlock *finfo;
662 int exist,a,err;
663 BPTR mylock;
665 exist=CheckExist(dirname,NULL);
666 if (exist<=0) {
667 loop:
668 if (exist<0 || !(mylock=CreateDir(dirname))) {
669 err = (exist<0) ? 203: IoErr();
670 doerror(err);
671 a=checkerror(globstring[STR_CREATING],finfo->fib_FileName,err);
672 if (a==1) goto loop;
673 if (a==2) return(0);
674 return(-1);
676 if (mylock) {
677 struct makedirlist *list,*pos;
679 UnLock(mylock);
681 if (config->copyflags&COPY_DATE) setdate(dirname,&finfo->fib_Date);
682 if (config->copyflags&COPY_PROT) SetProtection(dirname,finfo->fib_Protection&(~FIBF_ARCHIVE));
683 if (config->copyflags&COPY_NOTE) SetComment(dirname,finfo->fib_Comment);
685 if ((list=LAllocRemember(key,sizeof(struct makedirlist),MEMF_CLEAR)) &&
686 (list->path=LAllocRemember(key,strlen(dirname)+1,0))) {
687 strcpy(list->path,dirname);
688 if (!(pos=*first)) *first=list;
689 else {
690 while (pos->next) pos=pos->next;
691 pos->next=list;
692 list->last=pos;
697 return(1);
700 int getdircontentsinfo(char *path, unsigned long long *size, ULONG *files)
702 char *buf, *c;
703 struct ExAllControl *eac;
704 struct ExAllData *ead;
705 BPTR lock;
706 int more, ret = 1;
708 D(bug("getdircontentsinfo(%s)\n",path));
709 if ((lock = Lock(path,ACCESS_READ)))
711 if ((buf = AllocMem(1024,MEMF_ANY)))
713 if ((eac = AllocDosObject(DOS_EXALLCONTROL,NULL)))
715 eac->eac_LastKey = 0;
719 ead = (struct ExAllData *)buf;
720 more = ExAll(lock,ead,1024,ED_SIZE,eac);
721 if ((! more) && (IoErr() != ERROR_NO_MORE_ENTRIES))
723 ret = 0;
724 break;
726 if (eac->eac_Entries == 0) continue;
728 for (; ead; ead = ead->ed_Next)
730 if (ead->ed_Type > 0)
732 AddPart(path,ead->ed_Name,256);
734 ret = getdircontentsinfo(path,size,files);
736 c = PathPart(path);
737 if (c) *c = 0;
739 else
741 *size += ead->ed_Size;
742 (*files)++;
746 while (more);
748 FreeDosObject(DOS_EXALLCONTROL, eac);
750 else ret = 0;
751 FreeMem(buf,1024);
753 else ret = 0;
754 UnLock(lock);
756 else ret = 0;
757 return ret;