2 Copyright © 2000, The AROS Development Team. All rights reserved.
5 Desc: SortCopy from Thomas Richter
9 /*****************************************************************
11 ** © 1996-2000 THOR-Software **
13 ** sortiert kopieren **
14 ** (Hard)Links mitlinken **
15 *****************************************************************/
17 /* Converted to AROS by SDuvan 18.11.2000 (some bugs fixed too) */
20 #include <exec/types.h>
21 #include <exec/nodes.h>
22 #include <exec/lists.h>
23 #include <exec/memory.h>
24 #include <exec/alerts.h>
27 #include <dos/dosextens.h>
28 #include <dos/dosasl.h>
30 #include <proto/alib.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
33 #include <proto/utility.h>
37 #include <aros/debug.h>
38 #include <exec/rawfmt.h>
41 #include <thor/tinyio.h>
44 extern void __builtin__emit(int);
45 #define BreakPoint __builtin_emit(0x4afc)
53 #define SIGMASK (1<<12)
54 #define MAXSOFTNEST 16
55 #define BUFFERSIZE 2048
59 /* Verwaltung eines Eintrages in der Directory */
63 struct DirEntry
*de_next
;
64 struct DirEntry
*de_pred
;
65 ULONG de_flags
; /* Siehe unten */
67 struct DateStamp de_date
;
69 BPTR de_sourcelock
; /* Nur in Sonderfällen: Lock auf
71 BPTR de_dirlock
; /* Nur bei Links verwendet: BPTR
72 Directory, wo der Link hinsoll
74 BPTR de_linklock
; /* Bei Links: Directory, in dem
75 das Objekt liegt, zu dem der
77 struct MinList de_sublist
;
78 char de_name
[MAXFILENAMELENGTH
];
79 char de_comment
[MAXCOMMENTLENGTH
];
81 /* Name des Zielobjektes (Quellobject, d.h. Name des Links) in name */
82 char de_linkname
[MAXFILENAMELENGTH
];
86 /* Einträge in den Flags */
87 #define DEF_SOFTLINK (1 << 0) /* entry is a softlink */
88 #define DEF_HARDLINK (1 << 1) /* entry is a hardlink */
89 #define DEF_DIR (1 << 2) /* entry is a directory */
90 #define DEF_FORGET (1 << 3) /* failed to copy, ignore */
91 #define DEF_NORESOLVE (1 << 4) /* failed to read the link, do not resolve */
92 #define DEF_CREATED (1 << 5) /* directory has been created */
93 #define DEF_FLATDIR (1 << 6) /* directory wasn't created, contents
95 #define DEF_REMOVED (1 << 7) /* directory has been removed */
98 /* Diese Node wird zum Kopieren von Files verwendet. */
102 struct Message cn_DosMessage
; /* a message for the DOS process */
103 struct DosPacket cn_DosPacket
; /* the message to be posted */
104 APTR cn_Buffer
; /* Pointer to the buffer */
105 ULONG cn_BufSize
; /* size of the buffer to allocate */
106 ULONG cn_WriteSize
; /* number of bytes to be written out */
107 UWORD cn_Command
; /* last command sent */
108 BOOL cn_release
; /* release me? */
109 struct CopyNode
*cn_BackTick
; /* just to make sure that this is
116 // These should be allocated by AllocDosObject()
117 struct FileInfoBlock fib
;
118 struct FileInfoBlock dirfib
;
119 struct AnchorPath ap
;
121 struct DosLibrary
*DOSBase
;
122 struct UtilityBase
*UtilityBase
;
132 struct MinList resolvelist
;
134 BOOL quiet
, quieter
, seta
, onlya
, overwrite
, leaveempty
, deletecopied
,
136 BOOL purge
, nocopy
, sourcewild
;
138 UBYTE buffer
[BUFFERSIZE
];
139 char failbuffer
[512];
141 struct CopyNode lastchancenode
;
142 struct MsgPort ioport
;
146 char version
[] = "$VER: SortCopy 41.1 (18.11.2000)";
152 void PostFailure(LONG error
, char *failtext
, ...);
153 BOOL
ReadDir(BPTR lock
, struct MinList
*dirlist
, char *name
);
154 BOOL
CopyFile(BPTR source
, BPTR dest
, char *name
);
155 BOOL
CopyDir(BPTR sourcelock
, BPTR destlock
, struct MinList
*dirlist
);
157 BOOL
CheckAbort(void);
158 BOOL
RecursiveCopy(BPTR source
, BPTR dest
, struct MinList
*dirlist
, char *name
);
159 void FreeDirList(struct MinList
*dirlist
, BOOL links
);
160 BOOL
IsDir(BPTR lock
, char *name
);
161 BOOL
FindSoftOrginal(struct DirEntry
*de
);
162 BOOL
FindHardOrginal(struct DirEntry
*de
);
163 BOOL
PathRelative(BPTR relpath
, BPTR path
, char *name
, char *buffer
,
165 BOOL
ResolveLinks(struct MinList
*list
, BPTR dest
);
166 BOOL
CreateLink(char *name
, BPTR melock
, char *linkname
, BPTR linklock
,
169 BOOL
CloneFlags(struct DirEntry
*de
);
170 ULONG
CopyMain(char *sourcename
, char *destname
);
171 BOOL
SetAFlag(struct DirEntry
*de
);
173 BOOL
DirEmpty(BPTR lock
, char *name
);
174 BOOL
KillForce(char *name
, BOOL force
);
175 BOOL
RecursiveDelete(BPTR lock
, struct MinList
*dirlist
, BOOL all
, char *name
);
176 void DeleteEntry(struct DirEntry
*de
, BOOL all
);
177 BOOL
RecursiveSetA(BPTR source
, struct MinList
*dirlist
, char *name
);
179 BOOL
PurgeDir(BPTR sourcelock
, BPTR destlock
, struct MinList
*dirlist
,
181 void FreeDirEntry(struct DirEntry
*de
, BOOL locks
);
182 BOOL
FindDirEntry(struct MinList
*dirlist
, struct DirEntry
*de
);
183 BOOL
DeleteDirList(BPTR source
, struct MinList
*dirlist
, BOOL all
);
184 BOOL
MustUpdate(BPTR destlock
, struct DirEntry
*de
);
185 BOOL
CopyFileEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
);
186 BOOL
CopyDirEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
);
187 struct DirEntry
*AllocDirEntry(struct FileInfoBlock
*fib
);
188 ULONG
CopyBodyMatch(struct AnchorPath
*ap
, char *pattern
, BPTR source
,
190 BOOL
FillDirEntry(struct DirEntry
*de
, struct FileInfoBlock
*fib
);
191 BOOL
CopyEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
);
192 BOOL
CopySubDirectory(struct DirEntry
*de
, BPTR source
, BPTR dest
);
193 BOOL
PrepareLink(struct DirEntry
*de
, BPTR source
, BPTR dest
);
194 void EnqueueEntry(struct MinList
*dirlist
, struct DirEntry
*de
);
195 BOOL
CopyEntryList(struct MinList
*dirlist
, BPTR dest
);
196 BOOL
AddMatch(struct AnchorPath
*ap
, struct MinList
*dirlist
);
197 struct DirEntry
*DupDirEntry(struct DirEntry
*se
);
198 BOOL
DupDirList(struct MinList
*source
, struct MinList
*dest
);
199 BOOL
SetAList(BPTR source
, struct MinList
*dirlist
);
200 ULONG
FillDirList(char *pattern
, struct MinList
*dirlist
);
201 ULONG
MainCopyProcess(BPTR source
, BPTR dest
, struct MinList
*dirlist
,
202 struct MinList
*copylist
);
203 BOOL
SetRootLock(struct DirEntry
*de
);
204 void FreeCopyNode(struct CopyNode
*cn
, ULONG
*limit
);
206 #ifdef USE_AROS_PACKETS
207 struct CopyNode
*AllocCopyNode_AROS(BPTR from
, ULONG size
, ULONG
*limit
);
208 BOOL
AsyncCopy_AROS(BPTR from
, BPTR to
, ULONG readsize
, char *name
);
210 struct CopyNode
*AllocCopyNode(BPTR from
, ULONG size
, ULONG
*limit
);
211 BOOL
AsyncCopy(BPTR from
, BPTR to
, ULONG readsize
, char *name
);
216 #define ARG_TEMPLATE "FROM/A,TO/A,QT=QUIET/S,QTR=QUIETER/S,SETA=SETARCHIVE/S,NONA=NONAONLY/S,OVR=OVERWRITE/S,LVE=LEAVEEMPTY/S,DELC=DELETECOPIED/S,FORCE/S,UPD=UPDATE/S,PRB=PURGEBACKUP/S,PRO=PURGEONLY/S,BUFSIZE/K/N"
221 struct Process
*this;
229 memset(args
, 0, 14*sizeof(char *));
231 this = (struct Process
*)FindTask(NULL
);
233 if(this->pr_CLI
== BNULL
)
235 msg
= WaitPort(&(this->pr_MsgPort
));
236 msg
= GetMsg(&(this->pr_MsgPort
));
243 /* Can't be started from WB */
245 tclower
= (IPTR
)(this->pr_Task
.tc_SPLower
);
247 DOSBase
= (struct DosLibrary
*)(OpenLibrary("dos.library", 37L));
252 oldlock
= CurrentDir(BNULL
);
255 UtilityBase
= (struct UtilityBase
*)OpenLibrary("utility.library", 37L);
257 if(UtilityBase
!= NULL
)
259 ra
= ReadArgs(ARG_TEMPLATE
, args
, NULL
);
263 quiet
= (BOOL
)args
[2];
264 quieter
= (BOOL
)args
[3];
269 seta
= (BOOL
)args
[4];
270 onlya
= (BOOL
)args
[5];
271 overwrite
= (BOOL
)args
[6];
272 leaveempty
= (BOOL
)args
[7];
273 deletecopied
= (BOOL
)args
[8];
274 force
= (BOOL
)args
[9];
275 update
= (BOOL
)args
[10];
276 purge
= (BOOL
)args
[11];
277 nocopy
= (BOOL
)args
[12];
281 bufsize
= *((LONG
*)args
[13]);
285 bufsize
= 0x7ffffff0;
294 D(bug("Calling CopyMain()\n"));
296 res
= CopyMain((STRPTR
)args
[0], (STRPTR
)args
[1]);
301 PrintFault(IoErr(), "SortCopy failed");
305 CloseLibrary((struct Library
*)UtilityBase
);
309 Printf("SortCopy: Need utility.library V37!\n");
314 CloseLibrary((struct Library
*)DOSBase
);
327 /* Hole den I/O-Fehlercode, brich bei fatalem Fehler ab */
344 ULONG
CopyMain(char *sourcename
, char *destname
)
346 BPTR dest
, sourcelock
;
349 struct MinList dirlist
, copylist
;
351 sourcelock
= CurrentDir(BNULL
);
352 SetSignal(0L, SIGMASK
);
354 NewList((struct List
*)&resolvelist
);
355 NewList((struct List
*)&dirlist
);
356 NewList((struct List
*)©list
);
359 CurrentDir(sourcelock
);
361 switch(ParsePatternNoCase(destname
, buffer
, BUFFERSIZE
))
364 Printf("SortCopy: Wildcards not allowed in destination.\n");
372 PostFailure(ERROR_BAD_TEMPLATE
, "Wildcard parsing failed");
377 switch(ParsePatternNoCase(sourcename
, buffer
, BUFFERSIZE
))
388 PostFailure(ERROR_BAD_TEMPLATE
, "Wildcard parsing failed");
393 D(bug("CopyMain part 2\n"));
397 res
= MatchFirst(sourcename
, &ap
);
401 if(res
== ERROR_NO_MORE_ENTRIES
)
402 res
= ERROR_OBJECT_NOT_FOUND
;
404 PostFailure(res
, "Can't access \"%s\"", sourcename
);
411 D(bug("CopyMain part 3\n"));
415 dest
= Lock(destname
, SHARED_LOCK
);
419 D(bug("Destination not found\n"));
421 if(IoErr() == ERROR_OBJECT_NOT_FOUND
)
425 dest
= CreateDir(destname
);
430 "Can't create destination drawer \"%s\"",
436 if(!(ChangeMode(CHANGE_LOCK
, dest
, SHARED_LOCK
)))
439 "Can't change the lock to \"%s\"",
442 dest
= BNULL
; /* SDuvan: Was a bug here! */
443 DeleteFile(destname
);
452 "Can't lock destination drawer \"%s\"",destname
);
458 D(bug("CopyMain part 3b\n"));
462 D(bug("Checking IsDir() on %s\n", destname
));
464 if(!IsDir(dest
, destname
))
466 D(bug("%s was no dir; calling Printf()\n", destname
));
468 Printf("SortCopy: \"%s\" is not a directory.\n", destname
);
471 D(bug("Unlocking dest lock\n"));
475 D(bug("Dest unlocked\n"));
481 D(bug("CopyMain part 3c\n"));
485 CurrentDir(sourcelock
);
486 res
= FillDirList(sourcename
, &dirlist
);
490 D(bug("Calling MainCopyProcess()\n"));
491 res
= MainCopyProcess(sourcelock
, dest
, &dirlist
, ©list
);
498 FreeDirList(&dirlist
, TRUE
);
499 FreeDirList(©list
, TRUE
);
500 FreeDirList(&resolvelist
, TRUE
);
502 CurrentDir(sourcelock
);
509 ULONG
FillDirList(char *pattern
, struct MinList
*dirlist
)
511 ULONG res
= RETURN_OK
;
518 if(!(err
= MatchFirst(pattern
, &ap
)))
527 if(!AddMatch(&ap
, dirlist
))
533 ap
.ap_Flags
&= ~APF_DODIR
;
534 err
= MatchNext(&ap
);
538 if(err
!= ERROR_NO_MORE_ENTRIES
&& err
)
540 PostFailure(err
, "Can't resolve pattern \"%s\"", pattern
);
545 PostFailure(ERROR_OBJECT_NOT_FOUND
, "No information for \"%s\"",
552 PostFailure(err
, "Can't resolve pattern \"%s\"", pattern
);
563 ULONG
MainCopyProcess(BPTR source
, BPTR dest
, struct MinList
*dirlist
,
564 struct MinList
*copylist
)
566 ULONG res
= RETURN_OK
;
573 /* Create a copy of it */
574 DupDirList(dirlist
, copylist
);
576 /* And now for the heavy stuff */
580 /* Copy the list contents */
581 if(!(CopyEntryList(dirlist
, dest
)))
584 /* Move all the other stuff to the resolvelist */
585 FreeDirList(dirlist
, FALSE
);
590 /* create now all links */
591 if((!nocopy
) && (resolvelist
.mlh_Head
->mln_Succ
!= NULL
))
594 Printf("\nResolving outstanding links...\n\n");
596 if(!(ResolveLinks(&resolvelist
,dest
)))
603 FreeDirList(&resolvelist
,TRUE
);
608 /* Set now the archive bits in the source drawer */
609 if(seta
&& (failcondition
== 0) && (!nocopy
))
611 if(DupDirList(copylist
, dirlist
))
614 Printf("\n\nSetting the archive bits, please wait...\n");
616 if(!(SetAList(BNULL
, dirlist
)))
621 FreeDirList(dirlist
, TRUE
);
626 /* delete now the source files if the user selected this */
627 if(deletecopied
&& (res
== 0) && (!nocopy
))
631 Printf("\nA fail condition occured while copying. The deletion"
632 "of files is therefore disabled for security.\n");
637 Printf("\nRemoving old files...\n\n");
639 if(!(DeleteDirList(BNULL
, copylist
, FALSE
)))
651 BOOL
CopyEntryList(struct MinList
*dirlist
, BPTR dest
)
653 struct DirEntry
*de
, *next
;
658 /* Copy all files, create directories and setup dummies for the
659 linked files and directories */
662 if(!CopyDir(BNULL
, dest
, dirlist
))
668 /* Purge the destination: Not good if we gave a pattern... */
670 /* First free all the files and get the locks for the links */
671 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
675 if(de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
))
677 Remove((struct Node
*)de
);
678 PrepareLink(de
, de
->de_sourcelock
, dest
);
682 if(!(de
->de_flags
& DEF_DIR
))
684 Remove((struct Node
*)de
);
685 FreeDirEntry(de
, TRUE
);
692 /* Now copy the subdirectories recursively */
693 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
700 if(!(de
->de_flags
& DEF_FORGET
))
702 if(de
->de_flags
& DEF_DIR
)
707 if(!CopySubDirectory(de
, de
->de_sourcelock
, dest
))
713 Remove((struct Node
*)de
);
714 FreeDirEntry(de
, TRUE
);
718 FreeDirList(dirlist
, FALSE
);
725 BOOL
AddMatch(struct AnchorPath
*ap
, struct MinList
*dirlist
)
732 protection
= ap
->ap_Info
.fib_Protection
;
734 if(!(de
= AllocDirEntry(&(ap
->ap_Info
))))
737 oldlock
= CurrentDir(ap
->ap_Current
->an_Lock
);
739 de
->de_sourcelock
= DupLock(ap
->ap_Current
->an_Lock
);
741 if(de
->de_sourcelock
!= BNULL
)
743 /* We need to call this first to find out if this
744 is a directory or not.... */
746 FillDirEntry(de
, &(ap
->ap_Info
));
748 if((de
->de_flags
& DEF_DIR
) == 0)
750 if(onlya
&& (protection
& FIBF_ARCHIVE
))
751 de
->de_flags
|= DEF_FORGET
;
755 de
->de_flags
|= DEF_FLATDIR
;
758 EnqueueEntry(dirlist
,de
);
762 PostFailure(IoErr(), "Can't lock source directory \"%s\"",
763 ap
->ap_Info
.fib_FileName
);
764 FreeDirEntry(de
, TRUE
);
778 BOOL
IsDir(BPTR lock
, char *name
)
780 if(!Examine(lock
, &fib
))
782 PostFailure(Fatal(), "Can't examine object \"%s\"", name
);
786 /* No need to worry about links.... they are already resolved when we
789 if(fib
.fib_DirEntryType
> 0)
807 PrintFault(ERROR_BREAK
, NULL
);
812 BOOL
CheckAbort(void)
817 // FIXME: Take care of stack check
819 if((getreg(REG_A7
) - tclower
) < 1024)
821 PrintFault(ERROR_TOO_MANY_LEVELS
, "SortCopy failed");
822 Printf("Increase the stack size with \"STACK\" and retry.\n");
830 if(CheckSignal(SIGMASK
))
853 void PostFailure(LONG error
, char *failtext
, ...)
857 va_start(args
, failtext
);
863 VNewRawDoFmt(failtext
, RAWFMTFUNC_STRING
, failbuffer
, args
);
865 tinyvsprintf(failbuffer
, failtext
, args
);
868 Fault(error
, failbuffer
, buffer
, BUFFERSIZE
- 1);
869 Printf("\nSortCopy : %s \n", buffer
);
870 failcondition
= TRUE
;
878 BOOL
FindSoftOrginal(struct DirEntry
*de
)
880 BPTR dirlock
, objectlock
= BNULL
;
882 struct FileLock
*flock
;
887 de
->de_flags
|= DEF_NORESOLVE
;
889 if(scount
> MAXSOFTNEST
)
891 SetIoErr(ERROR_TOO_MANY_LEVELS
);
895 dirlock
= CurrentDir(BNULL
);
898 // NOTICE: Using lock internals here
900 flock
= (struct FileLock
*)(BADDR(dirlock
));
902 if(flock
->fl_Task
== NULL
)
903 { /* softlink at NIL:? Bizarre! */
904 SetIoErr(ERROR_OBJECT_WRONG_TYPE
);
908 if(!ReadLink(flock
->fl_Task
, dirlock
, de
->de_name
, buffer
, BUFFERSIZE
))
912 /* Locate the object the link is going to */
913 if(!(dirlock
= Lock(buffer
, SHARED_LOCK
)))
916 if(Examine(dirlock
, &fib
))
918 objectlock
= ParentDir(dirlock
);
920 if(objectlock
!= BNULL
)
922 strcpy(de
->de_linkname
, FilePart(buffer
));
924 /* Fill in file name */
938 CurrentDir(objectlock
);
939 switch(fib
.fib_DirEntryType
)
943 fine
= FindSoftOrginal(de
);
950 de
->de_flags
|= DEF_DIR
;
952 /* läuft hier hinein! */
955 fine
= FindHardOrginal(de
);
961 if(fib
.fib_DirEntryType
> 0)
962 de
->de_flags
|= DEF_DIR
;
964 de
->de_linklock
= objectlock
;
974 de
->de_flags
&= ~DEF_NORESOLVE
;
984 BOOL
FindHardOrginal(struct DirEntry
*de
)
986 BPTR lock
; /* Resolve the link by getting the name */
989 if(!(lock
= Lock(de
->de_name
, SHARED_LOCK
)))
992 if(Examine(lock
, &fib
))
994 de
->de_linklock
= ParentDir(lock
);
996 if(de
->de_linklock
!= BNULL
)
998 strcpy(de
->de_linkname
, fib
.fib_FileName
);
1011 /* old stuff, way too complicated...
1013 fine = NameFromLock(lock, buffer, BUFFERSIZE);
1023 strcpy(de->de_linkname, FilePart(buffer));
1024 *PathPart(buffer) = 0;
1025 de->de_linklock = Lock(buffer,SHARED_LOCK);
1027 if(!(de->de_linklock))
1037 BOOL
SetAFlag(struct DirEntry
*de
)
1041 BPTR oldlock
= BNULL
;
1047 if(de
->de_sourcelock
!= BNULL
)
1048 oldlock
= CurrentDir(de
->de_sourcelock
);
1050 lock
= Lock(de
->de_name
, SHARED_LOCK
);
1054 if(Examine(lock
, &fib
))
1056 parent
= (BPTR
)(-1);
1058 /* check if this the root directory. If so, don't set the A bit */
1059 if(fib
.fib_DirEntryType
> 0)
1061 parent
= ParentDir(lock
);
1075 if((!(fib
.fib_Protection
& FIBF_ARCHIVE
)) ||
1076 (de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
)))
1078 if(!SetProtection(de
->de_name
,
1079 fib
.fib_Protection
| FIBF_ARCHIVE
))
1092 if(de
->de_sourcelock
)
1093 CurrentDir(oldlock
);
1097 PostFailure(err
,"Can't set the archive bit of \"%s\"", de
->de_name
);
1106 BOOL
CloneFlags(struct DirEntry
*de
)
1108 /* Die Directory wurde nicht angelegt, sondern der Inhalt
1110 if((de
->de_flags
& DEF_DIR
) && (de
->de_flags
& (DEF_FLATDIR
| DEF_REMOVED
)))
1113 if(!SetComment(de
->de_name
, de
->de_comment
))
1115 PostFailure(IoErr(), "Can't set the file comment of \"%s\"",
1121 if(!SetFileDate(de
->de_name
, &(de
->de_date
)))
1123 PostFailure(IoErr(), "Can't set the file date of \"%s\"",
1129 if(!SetProtection(de
->de_name
,de
->de_protection
))
1131 PostFailure(IoErr(), "Can't set protection flags of \"%s\"",
1142 void EnqueueEntry(struct MinList
*dirlist
, struct DirEntry
*de
)
1144 struct DirEntry
*cmp
;
1146 /* Suche jetzt die richtige Einfügeposition für die neue Node */
1147 for(cmp
= (struct DirEntry
*)(dirlist
->mlh_Head
); cmp
->de_next
;
1150 if(Strnicmp(cmp
->de_name
, de
->de_name
, 108) > 0)
1154 if(cmp
->de_next
== NULL
)
1156 AddTail((struct List
*)dirlist
, (struct Node
*)de
);
1162 if(cmp
->de_pred
== NULL
)
1163 AddHead((struct List
*)dirlist
, (struct Node
*)de
);
1165 Insert((struct List
*)dirlist
, (struct Node
*)de
,
1166 (struct Node
*)cmp
);
1172 /* Eine komplette Directory zusammenbauen. Directory ist in BPTR lock */
1173 BOOL
ReadDir(BPTR lock
, struct MinList
*dirlist
, char *dirname
)
1175 struct DirEntry
*de
= NULL
;
1180 if(!Examine(lock
, &dirfib
))
1182 PostFailure(Fatal(), "Can't examine the directory \"%s\"", dirname
);
1187 /* So, jetzt können wir den Rest der Directory lesen */
1193 if(!ExNext(lock
, &dirfib
))
1196 protection
= dirfib
.fib_Protection
;
1198 if(!(de
= AllocDirEntry(&dirfib
)))
1201 FillDirEntry(de
, &dirfib
);
1203 /* selbst wenn es Probleme gibt, das Teil mit aufnehmen */
1205 if((de
->de_flags
& DEF_DIR
) == 0)
1207 if(onlya
&& (protection
& FIBF_ARCHIVE
))
1208 de
->de_flags
|= DEF_FORGET
;
1211 EnqueueEntry(dirlist
, de
);
1214 if(IoErr() == ERROR_NO_MORE_ENTRIES
)
1220 PostFailure(Fatal(), "Can't examine the directory \"%s\"", dirname
);
1228 BOOL
CopyFile(BPTR source
, BPTR dest
, char *name
)
1232 if(ExamineFH(source
, &fib
))
1234 size
= fib
.fib_Size
;
1238 /* Works like this, too, but takes *huge* amount of memoy */
1242 #ifdef USE_AROS_PACKETS
1243 return AsyncCopy_AROS(source
, dest
, size
, name
);
1245 return AsyncCopy(source
, dest
, size
, name
);
1251 BOOL
MustUpdate(BPTR destlock
, struct DirEntry
*de
)
1256 CurrentDir(destlock
);
1257 dest
= Lock(de
->de_name
, SHARED_LOCK
);
1261 if(!Examine(dest
, &fib
))
1264 PostFailure(Fatal(), "Can't examine the destination file \"%s\"",
1266 de
->de_flags
|= DEF_FORGET
;
1271 if(fib
.fib_Size
== de
->de_length
)
1273 if(CompareDates(&(fib
.fib_Date
), &(de
->de_date
)) <= 0)
1274 fine
= FALSE
; /* no need to copy the file,
1275 we suppose they are identical */
1283 if(IoErr() != ERROR_OBJECT_NOT_FOUND
)
1285 PostFailure(Fatal(), "Can't lock the destination file \"%s\"",
1287 de
->de_flags
|= DEF_FORGET
;
1297 /* Ein ganzes File kopieren. Achtung! Das muß auch wirklich ein File
1299 BOOL
CopyFileEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
)
1302 BPTR source
, dest
, tmp
;
1304 struct MinList dirlist
;
1306 if((!update
) || MustUpdate(destlock
, de
))
1308 CurrentDir(sourcelock
);
1309 source
= Open(de
->de_name
, MODE_OLDFILE
);
1313 PostFailure(IoErr(), "Can't open the source file \"%s\"",
1315 de
->de_flags
|= DEF_FORGET
;
1320 CurrentDir(destlock
);
1322 /* Now check the destination object. Delete it if required */
1325 tmp
= Lock(de
->de_name
, EXCLUSIVE_LOCK
);
1329 if(ChangeMode(CHANGE_LOCK
, tmp
, SHARED_LOCK
))
1331 /* Make it delete-able */
1332 if(SetProtection(de
->de_name
, 0))
1334 if(Examine(tmp
, &fib
))
1336 switch(fib
.fib_DirEntryType
)
1339 if(fib
.fib_DirEntryType
> 0)
1341 Printf("found obsolete directory, deleting.\n");
1343 NewList((struct List
*)&dirlist
);
1345 if(ReadDir(tmp
, &dirlist
, de
->de_name
))
1347 fine
= DeleteDirList(tmp
, &dirlist
,
1353 CurrentDir(destlock
);
1354 FreeDirList(&dirlist
, TRUE
);
1367 fine
= DeleteFile(de
->de_name
);
1389 if(IoErr() != ERROR_OBJECT_NOT_FOUND
)
1397 PostFailure(err
, "Can't delete the old entry \"%s\"",
1399 de
->de_flags
|= DEF_FORGET
; /* nicht kopiert -> nicht löschen */
1405 dest
= Open(de
->de_name
, MODE_NEWFILE
);
1411 PostFailure(err
, "Can't create the destination file \"%s\"",
1413 de
->de_flags
|= DEF_FORGET
;
1418 fine
= CopyFile(source
, dest
, de
->de_name
);
1424 CurrentDir(destlock
);
1425 DeleteFile(de
->de_name
);
1426 PostFailure(Fatal(), "Can't copy the file \"%s\"", de
->de_name
);
1427 de
->de_flags
|= DEF_FORGET
; /* nicht kopiert -> nicht löschen */
1433 de
->de_flags
|= DEF_CREATED
;
1442 Printf("(up to date)\n");
1450 BOOL
CopyDirEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
)
1456 CurrentDir(destlock
);
1458 newlock
= Lock(de
->de_name
, SHARED_LOCK
);
1460 if(newlock
!= BNULL
)
1462 if(!IsDir(newlock
, de
->de_name
))
1468 /* This is NOT a directory, erase it now */
1469 SetProtection(de
->de_name
, 0);
1471 if(!(DeleteFile(de
->de_name
)))
1473 PostFailure(IoErr(),
1474 "Can't remove \"%s\" to make room for a new directory",
1476 de
->de_flags
|= DEF_FORGET
;
1483 PostFailure(ERROR_OBJECT_WRONG_TYPE
,
1484 "Destination \"%s\" is not a directory",
1486 de
->de_flags
|= DEF_FORGET
;
1497 if(newlock
!= BNULL
)
1501 /* This is not good in the case of a lock !*/
1502 if(de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
))
1504 Printf("Warning: The name \"%s\" of the link is already in use.\n",
1506 de
->de_flags
|= DEF_NORESOLVE
| DEF_FORGET
; /* Diesen Link nicht erzeugen */
1517 if(err
!= ERROR_OBJECT_NOT_FOUND
&& err
!= 0)
1519 PostFailure(IoErr(), "Can't lock the directory \"%s\"",
1521 de
->de_flags
|= DEF_FORGET
;
1527 /* Don't create a directory in the case we replace it later
1529 if(de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
))
1531 dest
= Open(de
->de_name
, MODE_NEWFILE
);
1535 PostFailure(Fatal(),
1536 "Can't create dummy link directory \"%s\"",
1538 de
->de_flags
|= DEF_FORGET
; /* But try to resolve later */
1542 de
->de_flags
|= DEF_CREATED
;
1545 Printf("(created)\n");
1552 newlock
= CreateDir(de
->de_name
);
1554 if(newlock
== BNULL
)
1556 PostFailure(Fatal(), "Can't create new directory \"%s\"",
1558 de
->de_flags
|= DEF_FORGET
;
1564 de
->de_flags
|= DEF_CREATED
;
1567 Printf("(created)\n");
1580 BOOL
CopyEntry(struct DirEntry
*de
, BPTR sourcelock
, BPTR destlock
)
1584 if(de
->de_flags
& DEF_FORGET
||
1585 ((de
->de_flags
& DEF_DIR
) && (de
->de_flags
& DEF_FLATDIR
)))
1591 Printf("%s...",de
->de_name
);
1595 if(de
->de_flags
& DEF_DIR
)
1597 if(!CopyDirEntry(de
, sourcelock
, destlock
))
1602 if(!CopyFileEntry(de
, sourcelock
, destlock
))
1606 if(!(de
->de_flags
& DEF_FORGET
))
1608 if((de
->de_flags
& (DEF_DIR
| DEF_SOFTLINK
| DEF_HARDLINK
)) == 0)
1610 oldlock
= CurrentDir(destlock
);
1612 CurrentDir(oldlock
);
1621 BOOL
SetRootLock(struct DirEntry
*de
)
1633 if(de
->de_flags
& DEF_DIR
)
1635 /* Are we copying the root of a tree ? */
1637 oldlock
= CurrentDir(de
->de_sourcelock
);
1638 rootlock
= Lock(de
->de_name
, SHARED_LOCK
);
1642 PostFailure(Fatal(), "Can't look the root directory \"%s\"\n",
1647 CurrentDir(oldlock
);
1656 /* Eine Directory nach Vorschrift kopieren */
1657 BOOL
CopyDir(BPTR sourcelock
, BPTR destlock
, struct MinList
*dirlist
)
1659 struct DirEntry
*de
;
1662 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
;
1670 if(sourcelock
== BNULL
)
1672 if(!SetRootLock(de
))
1676 if(!(CopyEntry(de
, (de
->de_sourcelock
) ? (de
->de_sourcelock
) :
1677 sourcelock
, destlock
)))
1681 if(sourcelock
== BNULL
)
1689 BOOL
DupDirList(struct MinList
*source
, struct MinList
*dest
)
1691 struct DirEntry
*se
, *de
;
1693 NewList((struct List
*)dest
);
1695 for(se
= (struct DirEntry
*)(source
->mlh_Head
); se
->de_next
;
1698 if(!(de
= DupDirEntry(se
)))
1700 FreeDirList(dest
, TRUE
);
1705 AddTail((struct List
*)dest
, (struct Node
*)de
);
1713 struct DirEntry
*DupDirEntry(struct DirEntry
*se
)
1715 struct DirEntry
*de
;
1717 de
= AllocMem(sizeof(struct DirEntry
), MEMF_PUBLIC
);
1722 PostFailure(Fatal(), "Can't allocate directory buffer");
1725 /* Liste der bestehenden DirEntries wird von oben abgeräumt */
1728 /* Kopiere jetzt die Daten */
1729 memcpy(de
, se
, sizeof(struct DirEntry
));
1730 de
->de_sourcelock
= BNULL
;
1731 de
->de_linklock
= BNULL
;
1732 de
->de_dirlock
= BNULL
; /* Erstmal löschen */
1733 NewList((struct List
*)(&(de
->de_sublist
))); /* Wird nicht geduppt */
1735 if(se
->de_sourcelock
== 0 ||
1736 (de
->de_sourcelock
= DupLock(se
->de_sourcelock
)))
1738 if(se
->de_linklock
== 0 || (de
->de_linklock
= DupLock(se
->de_linklock
)))
1740 if(se
->de_dirlock
== 0 || (de
->de_dirlock
=DupLock(se
->de_dirlock
)))
1747 PostFailure(Fatal(), "Can't duplicate directory buffer");
1748 FreeDirEntry(de
, TRUE
);
1755 struct DirEntry
*AllocDirEntry(struct FileInfoBlock
*fib
)
1757 struct DirEntry
*de
;
1759 de
= AllocMem(sizeof(struct DirEntry
), MEMF_PUBLIC
);
1764 PostFailure(Fatal(), "Can't allocate directory buffer");
1767 /* Liste der bestehenden DirEntries wird von oben abgeräumt */
1770 /* Kopiere jetzt die Daten */
1771 strcpy(de
->de_name
, fib
->fib_FileName
);
1772 strcpy(de
->de_comment
, fib
->fib_Comment
);
1773 de
->de_protection
= fib
->fib_Protection
;
1774 de
->de_date
= fib
->fib_Date
;
1776 de
->de_sourcelock
= BNULL
;
1777 de
->de_linklock
= BNULL
;
1778 de
->de_dirlock
= BNULL
; /* Muß vom Caller ausgefüllt werden */
1779 de
->de_linkname
[0] = 0;
1780 de
->de_length
= fib
->fib_Size
;
1781 NewList((struct List
*)(&(de
->de_sublist
)));
1788 BOOL
FillDirEntry(struct DirEntry
*de
, struct FileInfoBlock
*fib
)
1792 switch(fib
->fib_DirEntryType
)
1795 de
->de_flags
|= DEF_SOFTLINK
;
1797 /* We never set this up as a directory */
1798 fine
= FindSoftOrginal(de
);
1802 de
->de_flags
|= DEF_DIR
;
1806 de
->de_flags
|= DEF_HARDLINK
;
1807 fine
= FindHardOrginal(de
);
1811 if(fib
->fib_DirEntryType
> 0)
1812 de
->de_flags
|= DEF_DIR
;
1819 PostFailure(IoErr(), "Can't resolve link \"%s\"", de
->de_name
);
1820 de
->de_flags
|= DEF_NORESOLVE
;
1828 void FreeDirEntry(struct DirEntry
*de
, BOOL locks
)
1830 FreeDirList(&(de
->de_sublist
), locks
);
1831 UnLock(de
->de_sourcelock
);
1832 UnLock(de
->de_dirlock
);
1833 UnLock(de
->de_linklock
);
1834 FreeMem(de
, sizeof(struct DirEntry
));
1839 void FreeDirList(struct MinList
*dirlist
, BOOL locks
)
1841 struct DirEntry
*de
, *next
;
1843 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
1846 Remove((struct Node
*)de
);
1848 if((de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
)) && (locks
== FALSE
))
1850 AddTail((struct List
*)&resolvelist
, (struct Node
*)(de
));
1854 FreeDirEntry(de
, locks
);
1863 BOOL
DirEmpty(BPTR lock
, char *name
)
1865 if(Examine(lock
, &fib
))
1867 if(ExNext(lock
, &fib
))
1870 if(IoErr() == ERROR_NO_MORE_ENTRIES
)
1873 PostFailure(IoErr(), "Can't inspect directory \"%s\"", name
);
1878 PostFailure(IoErr(), "Can't inspect directory \"%s\"", name
);
1885 BOOL
KillForce(char *name
, BOOL force
)
1889 lock
= Lock(name
, EXCLUSIVE_LOCK
);
1896 SetProtection(name
, 0);
1898 /* We'll see if this works... */
1900 if(DeleteFile(name
))
1903 PostFailure(IoErr(), "Can't remove empty directory \"%s\"", name
);
1908 if(IoErr() != ERROR_OBJECT_IN_USE
)
1910 PostFailure(IoErr(), "Can't remove empty directory \"%s\"", name
);
1917 /// CopySubDirectory
1918 BOOL
CopySubDirectory(struct DirEntry
*de
, BPTR source
, BPTR dest
)
1920 BPTR newdest
= BNULL
;
1925 /* find new destination lock of the directory */
1928 if(de
->de_flags
& DEF_FLATDIR
)
1934 newdest
= Lock(de
->de_name
, SHARED_LOCK
);
1936 if(newdest
== BNULL
)
1938 if((IoErr() != ERROR_OBJECT_NOT_FOUND
) || (!nocopy
))
1939 PostFailure(Fatal(), "Can't lock the new directory \"%s\"",
1942 de
->de_flags
|= DEF_FORGET
;
1952 /* find the new source of the directory */
1953 CurrentDir((de
->de_sourcelock
) ? (de
->de_sourcelock
) : (source
));
1954 newsource
= Lock(de
->de_name
, SHARED_LOCK
);
1956 if(newsource
== BNULL
)
1958 PostFailure(IoErr(), "Can't lock the source directory \"%s\"",
1960 de
->de_flags
|= DEF_FORGET
;
1972 Printf("%sing the directory \"%s\":\n", (nocopy
) ? ("Check") :("Copy"),
1978 fine
= RecursiveCopy(newsource
, destlock
, &(de
->de_sublist
), de
->de_name
);
1981 if((de
->de_flags
& DEF_CREATED
) &&
1982 (de
->de_protection
& FIBF_ARCHIVE
) && onlya
)
1984 /* Falls erzeugt, überprüfe, ob leer. In diesem Falle löschen */
1985 if((!leaveempty
) && (!nocopy
) && DirEmpty(newdest
, de
->de_name
))
1991 if(KillForce(de
->de_name
, TRUE
))
1996 Printf("\"%s\" is empty. Removed.\n", de
->de_name
);
1997 de
->de_flags
|= DEF_REMOVED
;
2006 if(!CloneFlags(de
)) /* smart enough not to set the flags if REMOVED or FLATDIR */
2015 Printf("...done with directory \"%s\".\n", de
->de_name
);
2025 BOOL
PrepareLink(struct DirEntry
*de
, BPTR source
, BPTR dest
)
2029 if(!(de
->de_sourcelock
))
2031 if(rootlock
== BNULL
)
2033 PostFailure(ERROR_OBJECT_NOT_FOUND
,
2034 "The root lock of the link \"%s\" is not set.\n",
2038 else if(!(de
->de_sourcelock
= DupLock(rootlock
)))
2041 PostFailure(IoErr(),
2042 "Can't duplock root dir of link \"%s\"",de
->de_name
);
2046 if(!(de
->de_dirlock
= DupLock(dest
)))
2048 PostFailure(IoErr(), "Can't duplock destination dir of link \"%s\"",
2054 de
->de_flags
|= DEF_NORESOLVE
;
2056 AddTail((struct List
*)&resolvelist
, (struct Node
*)(de
));
2063 BOOL
RecursiveCopy(BPTR source
, BPTR dest
, struct MinList
*dirlist
,
2066 struct DirEntry
*de
, *next
;
2074 if(!ReadDir(source
, dirlist
, dirname
))
2076 FreeDirList(dirlist
, FALSE
);
2083 FreeDirList(dirlist
, FALSE
);
2088 /* Copy all files, create directories and setup dummies for the
2089 linked files and directories */
2092 if(!CopyDir(source
, dest
, dirlist
))
2100 FreeDirList(dirlist
, FALSE
);
2105 /* Purge the destination */
2108 if(!PurgeDir(source
, dest
, dirlist
, dirname
))
2116 FreeDirList(dirlist
, FALSE
);
2121 /* First free all the files and get the locks for the links */
2122 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2126 if(de
->de_flags
& (DEF_SOFTLINK
| DEF_HARDLINK
))
2128 Remove((struct Node
*)de
);
2129 PrepareLink(de
, source
, dest
);
2133 if(!(de
->de_flags
& DEF_DIR
))
2135 Remove((struct Node
*)de
);
2136 FreeDirEntry(de
, TRUE
);
2143 /* Now copy the subdirectories recursively */
2144 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2151 if(!(de
->de_flags
& DEF_FORGET
))
2153 if(de
->de_flags
& DEF_DIR
)
2155 if(!(CopySubDirectory(de
, source
, dest
)))
2160 Remove((struct Node
*)(de
));
2161 FreeDirEntry(de
, TRUE
);
2165 FreeDirList(dirlist
, FALSE
);
2172 BOOL
PathRelative(BPTR relpath
, BPTR path
, char *name
, char *buffer
,
2179 bufend
= buffer
+ bufsize
- strlen(name
) - 1;
2183 SetIoErr(ERROR_LINE_TOO_LONG
);
2187 strcpy(bufend
, name
);
2189 lock
= DupLock(path
);
2196 if(SameLock(relpath
, lock
) == LOCK_SAME
)
2197 break; /* If done */
2199 if(Examine(lock
, &fib
) == FALSE
)
2203 return FALSE
; /* Can't examine */
2208 bufend
= bufend
- strlen(fib
.fib_FileName
);
2212 SetIoErr(ERROR_LINE_TOO_LONG
);
2218 strcpy(bufend
, fib
.fib_FileName
);
2220 newlock
= ParentDir(lock
);
2224 if(newlock
== BNULL
)
2226 /* Either something got wrong or the object we are looking for is
2227 not related to the relative path */
2231 SetIoErr(ERROR_OBJECT_NOT_FOUND
);
2240 newlock = ParentDir(lock);
2243 if(newlock == BNULL)
2255 strcpy(buffer
, bufend
);
2263 BOOL
CreateLink(char *name
, BPTR melock
, char *linkname
, BPTR linklock
,
2269 /* First, get a lock to the object we are linking to */
2270 /* linkname MIGHT be NULL. In this case, we already have a lock */
2273 CurrentDir(linklock
);
2274 lock
= Lock(linkname
, SHARED_LOCK
);
2278 PostFailure(IoErr(), "Can't lock the object \"%s\" the link is going to",
2292 /* if this is a softlink, get the full name of the object */
2295 if(!NameFromLock(lock
, buffer
, BUFFERSIZE
))
2297 PostFailure(IoErr(), "Can't find the full name of \"%s\"",
2307 /* Now find the place of the lock. Delete the placeholder */
2310 if(!DeleteFile(name
))
2312 PostFailure(IoErr(), "Can't delete the placeholder \"%s\"", name
);
2322 if(!MakeLink(name
, (SIPTR
)buffer
, TRUE
))
2324 PostFailure(IoErr(), "Can't create the softlink \"%s\"", name
);
2334 if(!MakeLink(name
, (SIPTR
)lock
, FALSE
))
2336 PostFailure(IoErr(), "Can't create the hardlink \"%s\"", name
);
2353 BOOL
ResolveLinks(struct MinList
*list
, BPTR dest
)
2355 struct DirEntry
*de
;
2357 BOOL fine
, resolved
;
2361 for(de
= (struct DirEntry
*)(list
->mlh_Head
); de
->de_next
; de
= de
->de_next
)
2369 Printf("%s...", de
->de_name
);
2375 if(de
->de_flags
& (DEF_FORGET
| DEF_NORESOLVE
))
2377 if(de
->de_flags
& DEF_NORESOLVE
)
2378 Printf("\nDue to a former error, the link to \"%s\" can't be resolved.\n",
2383 fine
= PathRelative(de
->de_sourcelock
, de
->de_linklock
,
2384 de
->de_linkname
, buffer
, BUFFERSIZE
);
2388 if(IoErr() != ERROR_OBJECT_NOT_FOUND
)
2390 PostFailure(IoErr(), "Can't find relative path of \"%s\"",
2396 /* This might be O.K. */
2397 if(SameLock(de
->de_sourcelock
, dest
) == LOCK_SAME_VOLUME
)
2399 Printf("Warning: Link destination of \"%s\" not copied, using the original path.\n",
2403 if(CreateLink(de
->de_name
, de
->de_dirlock
,
2404 de
->de_linkname
, de
->de_linklock
,
2405 de
->de_flags
& DEF_SOFTLINK
))
2413 if(!(de
->de_flags
& DEF_DIR
))
2415 Printf("Warning: Link destination of \"%s\" not present, using a copy instead.\n",
2425 /* Found the relative path. Find a lock to the object
2428 destlock
= Lock(buffer
, SHARED_LOCK
);
2430 /* If the destination can't be found... */
2431 if(destlock
== BNULL
)
2433 if(IoErr() == ERROR_OBJECT_NOT_FOUND
)
2435 if(!(de
->de_flags
& DEF_DIR
))
2437 Printf("Warning: Link destination of \"%s\" not present, using a copy instead.\n",
2445 PostFailure(IoErr(), "Can't lock the object \"%s\" the link is relative to",
2452 /* Found the destination */
2453 if(CreateLink(de
->de_name
, de
->de_dirlock
, NULL
, destlock
,
2454 de
->de_flags
& DEF_SOFTLINK
))
2467 if(!resolved
&& (de
->de_flags
& DEF_CREATED
))
2469 CurrentDir(de
->de_dirlock
);
2471 if(de
->de_flags
& DEF_DIR
)
2473 /* Create an empty directory instead */
2474 if(DeleteFile(de
->de_name
))
2476 if((de
->de_flags
& DEF_CREATED
) &&
2477 (de
->de_protection
& FIBF_ARCHIVE
) && onlya
)
2479 Printf("Warning: The archived directory link \"%s\" was left out.\n",
2484 else if((destlock
= CreateDir(de
->de_name
)) != BNULL
)
2488 Printf("Warning: Created an empty directory for \"%s\" instead.\n",
2494 PostFailure(IoErr(), "Can't delete the placeholder \"%s\"",
2499 DeleteFile(de
->de_name
); /* Don't mind if this worked */
2500 Printf("Warning: The link to \"%s\" can't be resolved.\n",
2508 CurrentDir(de
->de_dirlock
);
2518 void DeleteEntry(struct DirEntry
*de
, BOOL all
)
2520 BPTR oldlock
= BNULL
;
2522 if(all
|| (!(onlya
&& (de
->de_protection
& FIBF_ARCHIVE
))))
2530 Printf("%s...", de
->de_name
);
2534 if(de
->de_sourcelock
)
2535 oldlock
= CurrentDir(de
->de_sourcelock
);
2538 SetProtection(de
->de_name
, 0);
2540 if(!DeleteFile(de
->de_name
))
2542 PostFailure(IoErr(), "Can't delete the file \"%s\"", de
->de_name
);
2547 Printf("(deleted)\n");
2551 if(de
->de_sourcelock
)
2552 CurrentDir(oldlock
);
2554 Remove((struct Node
*)(de
));
2555 FreeDirEntry(de
, TRUE
);
2560 BOOL
DeleteDirList(BPTR source
, struct MinList
*dirlist
, BOOL all
)
2562 struct DirEntry
*de
, *next
;
2569 FreeDirList(dirlist
, TRUE
);
2574 /* Delete all files */
2575 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2579 if((de
->de_flags
& DEF_DIR
) == 0)
2580 DeleteEntry(de
, all
);
2585 /* Delete recursively all directories first ! */
2586 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2593 if(de
->de_flags
& DEF_DIR
)
2595 CurrentDir((de
->de_sourcelock
) ? (de
->de_sourcelock
) : (source
));
2596 newsource
= Lock(de
->de_name
, SHARED_LOCK
);
2598 if(newsource
== BNULL
)
2600 PostFailure(Fatal(), "Can't lock new directory \"%s\"",
2602 de
->de_flags
|= DEF_FORGET
;
2609 Printf("Cleaning the directory \"%s\":\n", de
->de_name
);
2614 if(!RecursiveDelete(newsource
, &(de
->de_sublist
), all
,
2623 Printf("...done with directory \"%s\".\n", de
->de_name
);
2626 CurrentDir((de
->de_sourcelock
) ? (de
->de_sourcelock
) :
2629 if(DirEmpty(newsource
, de
->de_name
))
2634 SetProtection(de
->de_name
, 0);
2636 if(!DeleteFile(de
->de_name
))
2638 PostFailure(IoErr(),
2639 "Can't delete the directory \"%s\"",
2647 Remove((struct Node
*)de
);
2648 FreeDirEntry(de
, TRUE
);
2654 /* Delete now all (archived) files */
2657 /* Free now all remaining stuff */
2658 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2661 DeleteEntry(de
, FALSE
);
2665 FreeDirList(dirlist
, TRUE
);
2672 BOOL
RecursiveDelete(BPTR source
, struct MinList
*dirlist
, BOOL all
,
2680 if(!ReadDir(source
, dirlist
, dirname
))
2682 FreeDirList(dirlist
, TRUE
);
2684 return FALSE
; /* Continue anyway */
2687 return DeleteDirList(source
, dirlist
, all
);
2692 BOOL
SetAList(BPTR source
, struct MinList
*dirlist
)
2694 struct DirEntry
*de
, *next
;
2701 /* Set the archive bit of all files */
2702 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2706 if((de
->de_flags
& DEF_DIR
) == 0)
2709 Remove((struct Node
*)de
);
2710 FreeDirEntry(de
, TRUE
);
2716 /* Set the archive bit of all directories */
2717 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2724 if(de
->de_flags
& DEF_DIR
)
2726 CurrentDir((de
->de_sourcelock
) ? (de
->de_sourcelock
) : (source
));
2727 newsource
= Lock(de
->de_name
, SHARED_LOCK
);
2729 if(newsource
== BNULL
)
2731 PostFailure(IoErr(), "Can't lock new directory \"%s\"",
2733 de
->de_flags
|= DEF_FORGET
;
2740 Printf("Setting the archive bit of the directory \"%s\"...\n",
2746 if(!(RecursiveSetA(newsource
, &(de
->de_sublist
), de
->de_name
)))
2756 Remove((struct Node
*)de
);
2757 FreeDirEntry(de
, TRUE
);
2765 /* Set now the A flag of all remaining stuff */
2766 for(de
= (struct DirEntry
*)(dirlist
->mlh_Head
); de
->de_next
; )
2771 Remove((struct Node
*)(de
));
2772 FreeDirEntry(de
, TRUE
);
2776 FreeDirList(dirlist
, TRUE
);
2783 BOOL
RecursiveSetA(BPTR source
, struct MinList
*dirlist
, char *dirname
)
2790 if(!ReadDir(source
, dirlist
, dirname
))
2792 FreeDirList(dirlist
, TRUE
);
2800 FreeDirList(dirlist
, TRUE
);
2805 return SetAList(source
, dirlist
);
2810 BOOL
FindDirEntry(struct MinList
*dirlist
, struct DirEntry
*de
)
2812 struct DirEntry
*look
;
2814 for(look
= (struct DirEntry
*)(dirlist
->mlh_Head
); look
->de_next
;
2815 look
= look
->de_next
)
2817 if(!(Stricmp(de
->de_name
, look
->de_name
)))
2826 BOOL
PurgeDir(BPTR sourcelock
, BPTR destlock
, struct MinList
*dirlist
,
2829 struct MinList destlist
;
2830 struct DirEntry
*de
, *next
;
2834 NewList((struct List
*)&destlist
);
2839 Printf("Purging...");
2845 /* Read destination directory */
2847 if(!ReadDir(destlock
, &destlist
, dirname
))
2849 FreeDirList(&destlist
, TRUE
);
2856 /* Remove all the stuff we already have in the source */
2857 for(de
= (struct DirEntry
*)(destlist
.mlh_Head
); de
->de_next
; )
2861 if(FindDirEntry(dirlist
, de
))
2863 Remove((struct Node
*)de
);
2864 FreeDirEntry(de
, TRUE
);
2871 result
= DeleteDirList(destlock
, &destlist
, TRUE
);
2878 Printf("...done\n");
2887 struct CopyNode
*AllocCopyNode(BPTR from
, ULONG size
, ULONG
*limit
)
2889 struct CopyNode
*cn
= NULL
;
2898 cn
= AllocVec(sizeof(struct CopyNode
) + size
,
2899 MEMF_PUBLIC
| MEMF_NO_EXPUNGE
);
2904 if(lastchancebusy
== FALSE
)
2906 lastchancebusy
= TRUE
;
2907 cn
= &lastchancenode
;
2908 cn
->cn_Buffer
= buffer
;
2909 cn
->cn_release
= FALSE
;
2916 cn
->cn_Buffer
= (cn
+ 1);
2917 cn
->cn_release
= TRUE
;
2922 cn
->cn_DosMessage
.mn_Node
.ln_Type
= NT_MESSAGE
;
2923 cn
->cn_DosMessage
.mn_Node
.ln_Pri
= 0;
2924 cn
->cn_DosMessage
.mn_Node
.ln_Name
= (APTR
)(&(cn
->cn_DosPacket
));
2925 cn
->cn_DosMessage
.mn_ReplyPort
= &ioport
;
2926 cn
->cn_DosPacket
.dp_Port
= &ioport
;
2927 cn
->cn_DosMessage
.mn_Length
= sizeof(struct StandardPacket
);
2928 cn
->cn_DosPacket
.dp_Link
= &(cn
->cn_DosMessage
);
2929 cn
->cn_DosPacket
.dp_Type
= ACTION_READ
; /* Read */
2930 cn
->cn_Command
= ACTION_READ
;
2931 cn
->cn_DosPacket
.dp_Arg1
= ((struct FileHandle
*)BADDR(from
))->fh_Arg1
;
2932 cn
->cn_DosPacket
.dp_Arg2
= (SIPTR
)cn
->cn_Buffer
;
2933 cn
->cn_DosPacket
.dp_Arg3
= size
;
2934 cn
->cn_BufSize
= size
;
2935 cn
->cn_BackTick
= cn
;
2944 void FreeCopyNode(struct CopyNode
*cn
, ULONG
*limit
)
2948 *limit
+= cn
->cn_BufSize
;
2952 lastchancebusy
= FALSE
;
2958 BOOL
AsyncCopy(BPTR from
, BPTR to
, ULONG readsize
, char *name
)
2960 struct MsgPort
*readport
, *writeport
;
2961 struct CopyNode
*cn
;
2966 BOOL busy
, stop
, report
;
2967 LONG readerror
, writeerror
;
2971 ioport
.mp_Node
.ln_Type
= NT_MSGPORT
;
2972 ioport
.mp_Node
.ln_Pri
= 0;
2973 ioport
.mp_Node
.ln_Name
= NULL
;
2974 ioport
.mp_Flags
= PA_SIGNAL
;
2975 ioport
.mp_SigBit
= SIGB_DOS
;
2976 ioport
.mp_SigTask
= FindTask(NULL
);
2977 NewList(&(ioport
.mp_MsgList
));
2978 limit
= AvailMem(MEMF_PUBLIC
| MEMF_LARGEST
);
2988 readport
= ((struct FileHandle
*)BADDR(from
))->fh_Type
;
2989 writeport
= ((struct FileHandle
*)BADDR(to
))->fh_Type
;
2990 arg1
= ((struct FileHandle
*)BADDR(to
))->fh_Arg1
;
2992 /* if source or destination is NIL:, return no error
2993 but copy zero bytes anyhow */
2994 if((readport
== NULL
) || (writeport
== NULL
))
2997 /* if there's nothing to do, abort now */
3006 lastchancebusy
= FALSE
;
3011 /* Check whether we should still read bytes from the input */
3014 /* If user hit ^C, then abort reading */
3020 readsize
= 0; /* Do not demand reading if halt required */
3025 /* Go for a reasonable buffer size */
3028 if(bufsize
> buffer
)
3031 if(buffer
> readsize
)
3036 if(limit
> BUFFERSIZE
)
3042 cn
= AllocCopyNode(from
, buffer
, &limit
);
3046 /* Might fill in another value if no memory */
3047 readsize
-= cn
->cn_BufSize
;
3049 SendPkt(&(cn
->cn_DosPacket
), readport
, &ioport
);
3055 /* Allocation of the packet failed. If at least one packet
3056 is busy, wait for its return as we may re-use it.
3057 else generate an error */
3058 if(packetcount
== 0)
3060 readerror
= ERROR_NO_FREE_STORE
;
3061 SetIoErr(readerror
);
3062 PostFailure(Fatal(), "Can't read from \"%s\"", name
);
3064 /* Fatal sets also abortFlag */
3069 cn
= (struct CopyNode
*)GetMsg(&ioport
);
3075 /* A Queue packet failure ? */
3076 if(cn
->cn_BackTick
!= cn
)
3082 if(cn
->cn_Command
== ACTION_READ
)
3084 if(cn
->cn_DosPacket
.dp_Res1
> 0)
3086 /* If this is an emergency stop, do not send a
3091 FreeCopyNode(cn
, &limit
);
3095 /* Everything went fine, initialize this packet
3096 for writing and let it go */
3097 cn
->cn_DosPacket
.dp_Type
= ACTION_WRITE
;
3098 cn
->cn_Command
= ACTION_WRITE
;
3099 cn
->cn_DosPacket
.dp_Arg1
= arg1
;
3100 cn
->cn_DosPacket
.dp_Arg2
= (SIPTR
)cn
->cn_Buffer
;
3101 readsize
+= cn
->cn_BufSize
;
3102 cn
->cn_DosPacket
.dp_Arg3
= cn
->cn_DosPacket
.dp_Res1
;
3103 cn
->cn_WriteSize
= cn
->cn_DosPacket
.dp_Res1
;
3104 readsize
-= cn
->cn_DosPacket
.dp_Res1
;
3105 SendPkt(&(cn
->cn_DosPacket
), writeport
, &ioport
);
3110 /* Uhoh, something went wrong. An error? */
3111 if(cn
->cn_DosPacket
.dp_Res1
< 0)
3114 /* If this is the first fault, print it */
3120 if(ErrorReport(cn
->cn_DosPacket
.dp_Res2
,
3121 REPORT_STREAM
, (SIPTR
)from
,
3127 } /* continue with the next read-packet,
3130 /* Abort and print error in case the user
3134 readerror
= cn
->cn_DosPacket
.dp_Res2
;
3135 SetIoErr(readerror
);
3136 PostFailure(readerror
,
3137 "Can't read from \"%s\"", name
);
3142 /* A read error is non-fatal */
3145 stop
= TRUE
; /* EOF, Reading done */
3148 FreeCopyNode(cn
, &limit
);
3151 else if(cn
->cn_Command
== ACTION_WRITE
)
3153 if(cn
->cn_DosPacket
.dp_Res1
!= cn
->cn_BufSize
)
3155 if(cn
->cn_DosPacket
.dp_Res1
< 0)
3157 /* A real error? If so, report to the user
3158 if not aborted anyhow */
3161 if(ErrorReport(cn
->cn_DosPacket
.dp_Res2
,
3162 REPORT_STREAM
, (SIPTR
)to
, NULL
))
3169 /* Re-initialize the packet, and retry
3170 the write request */
3171 cn
->cn_DosPacket
.dp_Type
= ACTION_WRITE
;
3172 cn
->cn_DosPacket
.dp_Arg1
= arg1
;
3173 cn
->cn_DosPacket
.dp_Arg2
= (SIPTR
)cn
->cn_Buffer
;
3174 cn
->cn_DosPacket
.dp_Arg3
= cn
->cn_WriteSize
;
3175 SendPkt(&(cn
->cn_DosPacket
), writeport
,
3183 /* If this is the first write error, print it */
3184 if(report
== FALSE
&& writeerror
== 0)
3186 if(cn
->cn_DosPacket
.dp_Res1
< 0)
3188 writeerror
= cn
->cn_DosPacket
.dp_Res2
;
3191 writeerror
= ERROR_OBJECT_WRONG_TYPE
;
3193 SetIoErr(writeerror
);
3194 PostFailure(Fatal(), "Can't write to \"%s\"", name
);
3196 /* Fatal() sets also abortFlag and therefore
3202 FreeCopyNode(cn
, &limit
);
3205 Alert(AN_QPktFail
); /* Huh, an unkown command returned? */
3209 if(packetcount
== 0 && readsize
== 0)
3214 signals
= Wait((ULONG
)(SIGF_DOS
| SIGBREAKF_CTRL_C
));
3216 if(signals
& SIGBREAKF_CTRL_C
)
3223 if(readerror
|| writeerror
)