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.
34 struct makedirlist
*last
,*next
;
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
)
58 struct FileInfoBlock __aligned myfinfo
;
59 struct FileInfoBlock __aligned enfinfo
;
82 struct recpath
*crec
=NULL
,*trec
;
83 struct RecursiveDirectory
*cur_recurse
,
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
) {
103 if (dowhat
&R_GETNAMES
) {
105 recurse_dir_key
=NULL
;
107 addparent_recurse
=NULL
;
110 current_recurse
=NULL
;
114 dos_global_bytecount
=0;
115 dos_global_copiedbytes
=0;
116 dos_global_deletedbytes
=0;
117 dos_global_blocksneeded
=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
);
131 if (!(mylock
=Lock(fdir
,ACCESS_READ
))) {
135 Examine(mylock
,&myfinfo
);
137 if (!(name
=LAllocRemember(&memkey
,5*512,MEMF_CLEAR
))) {
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
);
147 if (!(a
=copymakedir(&memkey
,&first_makedir
,dest
,&myfinfo
)) || a
==-1) {
153 if (mylock
) to_do
=ExNext(mylock
,&myfinfo
);
156 lister
.firstentry
=lister
.firstfile
=lister
.firstdir
=NULL
;
157 lister
.total
=lister
.filesel
=lister
.dirsel
=lister
.dirtot
=lister
.filetot
=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
;
169 if (status_haveaborted
) {
175 if (current_recurse
) {
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
;
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
) {
207 if (config
->copyflags
©_DATE
) {
208 TackOn(ddir
,myfinfo
.fib_FileName
,512);
209 setdate(ddir
,&myfinfo
.fib_Date
);
215 if (dowhat
&R_COMMENT
) {
217 if (!(SetComment(name
,dest
))) {
218 doerror(err
=IoErr());
219 a
=checkerror(globstring
[STR_COMMENTING
],myfinfo
.fib_FileName
,err
);
227 else if (dowhat
&R_PROTECT
) {
229 b
=getnewprot(myfinfo
.fib_Protection
,pstuff
[0],pstuff
[1]);
231 if (!(SetProtection(name
,b
))) {
232 doerror(err
=IoErr());
233 a
=checkerror(globstring
[STR_PROTECTING
],myfinfo
.fib_FileName
,err
);
241 else if (dowhat
&R_DATESTAMP
) {
243 if ((err
=setdate(name
,(struct DateStamp
*)data
))!=1) {
245 a
=checkerror(globstring
[STR_DATESTAMPING
],myfinfo
.fib_FileName
,err
);
253 if (mylock
) to_do
=ExNext(mylock
,&myfinfo
);
256 arcfillfib(&myfinfo
,entry
= entry
->next
);
259 if (dowhat
&R_DELETE
&& depth
>0) {
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) {
268 if (a
==2) glob_unprotect_all
=1;
275 CopyMemQuick((char *)&myfinfo
,(char *)&enfinfo
,sizeof(struct FileInfoBlock
));
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) {
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
;
295 else if (!first_recurse
) {
296 first_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
;
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
;
316 pos_rec
=pos_rec
->next
;
320 else cur_recurse
=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));
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
;
338 if ((a
=copymakedir(&memkey
,&first_makedir
,ddir
,&enfinfo
))==-1) {
342 else if (a
==0) adir
=NULL
;
344 if (dowhat
&R_DELETE
) {
347 if (!DeleteFile(name
)) {
348 if (config
->deleteflags
&8 && rtry
==1 && IoErr()==222) {
350 SetProtection(name
,0);
353 adir
=dir
; adest
=dest
; adata
=data
; ndir
=name
; ndest
=dname
;
356 if (config
->dynamicflags
&UPDATE_FREE
) seename(data_active_window
);
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
;
365 if (!(addrecurse(&memkey
,adir
,adest
,adata
,adata2
,adata3
,mylock
,&enfinfo
,mylock
?NULL
:entry
,&lister
))) {
369 //D(bug("recursedir_2: %lx\n",ndir));
371 //D(bug("recursedir_3: %lx\n",ndest));
375 if (!(mylock
=Lock(dir
,ACCESS_READ
))) {
379 Examine(mylock
,&myfinfo
);
380 to_do
=ExNext(mylock
,&myfinfo
);
384 lister
.firstentry
=lister
.firstfile
=lister
.firstdir
=NULL
;
385 lister
.total
=lister
.filesel
=lister
.dirsel
=lister
.dirtot
=lister
.filetot
=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
;
396 if (depth
>recurse_max_depth
) recurse_max_depth
=depth
;
401 if (enfinfo
.fib_DirEntryType
<0) {
403 dos_global_bytecount
+=enfinfo
.fib_Size
;
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*/))) {
416 D(bug("recursedir_4: %s\n",name
+data
));
417 strcpy(trec
->path
,&name
[data
]);
418 if (crec
) crec
->next
=trec
;
420 if (!rec_firstpath
) rec_firstpath
=trec
;
423 if (!str_filter_parsed
[0] ||
424 LMatchPatternI(str_filter_parsed
,enfinfo
.fib_FileName
)) {
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
));
433 char tempname
[FILEBUF_SIZE
];
436 if (! unarcfiledir(&lister
,name
,tempname
,enfinfo
.fib_FileName
)) continue;
437 AddPart(name
,tempname
,512);
441 if ((a
=checkexistreplace(name
,dname
,&enfinfo
.fib_Date
,1,1))==REPLACE_ABORT
) {
446 if (a
==REPLACE_ALL
) {
449 else if (a
==REPLACE_SKIPALL
) {
453 // if (a==REPLACE_SKIP)
455 if (!autoskip
&& (a
!=REPLACE_SKIP
))
459 if (!(a
=copyfile(name
,dname
,&err
,/*-1,*/NULL
,0))) {
461 a
=checkerror(globstring
[STR_COPYING
],enfinfo
.fib_FileName
,err
);
463 if (a
!=3) seename(data_active_window
);
471 if (dowhat
==R_COPY
) {
472 if (config
->copyflags
©_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
);
480 dotaskmsg(hotkeymsg_port
,PROGRESS_INCREASE
,1,0,NULL
,0);
481 if (!mylock
) removetemparcfile(name
);
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) {
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
) {
509 if (!(SetComment(name
,dest
))) {
510 doerror(err
=IoErr());
511 a
=checkerror(globstring
[STR_COMMENTING
],enfinfo
.fib_FileName
,err
);
521 else if (dowhat
&R_PROTECT
) {
523 b
=getnewprot(enfinfo
.fib_Protection
,pstuff
[0],pstuff
[1]);
525 if (!(SetProtection(name
,b
))) {
526 doerror(err
=IoErr());
527 a
=checkerror(globstring
[STR_PROTECTING
],enfinfo
.fib_FileName
,err
);
537 else if (dowhat
&R_DATESTAMP
) {
539 if ((err
=setdate(name
,(struct DateStamp
*)data
))!=1) {
540 doerror(err
=IoErr());
541 a
=checkerror(globstring
[STR_DATESTAMPING
],enfinfo
.fib_FileName
,err
);
551 else if (dowhat
&R_HUNT
) {
552 suc
=huntfile(enfinfo
.fib_FileName
,name
,&a
);
563 else if (dowhat
&R_SEARCH
) {
564 D(bug("file: %s\n",name
));
567 char tempname
[FILEBUF_SIZE
];
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
);
578 if (!simplerequest(globstring
[STR_CONTINUE_WITH_SEARCH
],
579 globstring
[STR_CONTINUE
],str_cancelstring
,NULL
)) {
594 if (mylock
) to_do
=ExNext(mylock
,&myfinfo
);
597 arcfillfib(&myfinfo
,entry
= entry
->next
);
603 while (current_recurse
) {
604 UnLock(current_recurse
->lock
);
605 current_recurse
=current_recurse
->last
;
609 str_filter_parsed
[0]) {
611 struct makedirlist
*last
=first_makedir
;
613 while (last
->next
) last
=last
->next
;
616 DeleteFile(last
->path
);
621 if (memkey
) LFreeRemember(&memkey
);
625 int addrecurse(key
,dir
,dest
,data
,data2
,data3
,lock
,info
,entry
,lister
)
626 struct DOpusRemember
**key
;
631 struct FileInfoBlock
*info
;
632 struct Directory
*entry
;
633 struct DirectoryWindow
*lister
;
637 if (!(rec
=LAllocRemember(key
,sizeof(struct recurse
),MEMF_ANY
/*MEMF_CLEAR*/)))
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*/)))
643 strcpy(rec
->dir
,dir
);
644 strcpy(rec
->dest
,dest
);
651 if (entry
) rec
->lister
=*lister
;
656 int copymakedir(key
,first
,dirname
,finfo
)
657 struct DOpusRemember
**key
;
658 struct makedirlist
**first
;
660 struct FileInfoBlock
*finfo
;
665 exist
=CheckExist(dirname
,NULL
);
668 if (exist
<0 || !(mylock
=CreateDir(dirname
))) {
669 err
= (exist
<0) ? 203: IoErr();
671 a
=checkerror(globstring
[STR_CREATING
],finfo
->fib_FileName
,err
);
677 struct makedirlist
*list
,*pos
;
681 if (config
->copyflags
©_DATE
) setdate(dirname
,&finfo
->fib_Date
);
682 if (config
->copyflags
©_PROT
) SetProtection(dirname
,finfo
->fib_Protection
&(~FIBF_ARCHIVE
));
683 if (config
->copyflags
©_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
;
690 while (pos
->next
) pos
=pos
->next
;
700 int getdircontentsinfo(char *path
, unsigned long long *size
, ULONG
*files
)
703 struct ExAllControl
*eac
;
704 struct ExAllData
*ead
;
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
))
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
);
741 *size
+= ead
->ed_Size
;
748 FreeDosObject(DOS_EXALLCONTROL
, eac
);