home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copy.c - Copyright © 1991 by S.R. & P.C.
- *
- * Created: 02 Mar 1991 15:50:36
- * Modified: 20 Jul 1991 12:25:40
- *
- * Make>> make
- */
-
- #include "Global.h"
- #include "FileList.h"
- #include "Actions.h"
- #include "ActionBack.h"
- #include "Process.h"
- #include "proto/Copy.h"
- #include "proto/Actions.h"
- #include "proto/ActionBack.h"
- #include "proto/Request.h"
- #include "proto/File.h"
- #include "proto/FileList.h"
-
-
- extern struct ExecBase *SysBase;
- extern char *ReqTitle;
-
-
- #define BUFFSIZEUNIT 11528
- #define MAXBUFFER_MOUNTED 200000
- #define MAXBUFFER_UNMOUNTED 902000
-
-
- /*
- * Compute how many buffers max will be used for this copy. If destination volume
- * and one of sources volumes are mounted, MAXBUFFER_MOUNTED memory will be used.
- * Else, MAXBUFFER_UNMOUNTED which is bigger will be used to minimize disk swapping.
- */
-
- static void InitMaxBuf(struct HeadFileList *hfl)
- {
- struct BrowserDir *bd, *nextbd;
- struct InfoData *info;
- struct Process *pp;
- APTR WindowPtr;
-
- if (!(info = AllocMem(sizeof(struct InfoData), MEMF_PUBLIC|MEMF_CLEAR)))
- return;
- pp = (struct Process *)SysBase->ThisTask;
- WindowPtr = pp->pr_WindowPtr;
- pp->pr_WindowPtr = (APTR)-1L;
- hfl->MaxBuffer = MAXBUFFER_UNMOUNTED;
- /* Info() needs volume referenced by the lock to be mounted. If Info() fails, volume is not mounted */
- if (Info(hfl->DestDir, info)) {
- bd = (struct BrowserDir *)hfl->DirList.mlh_Head;
- while(nextbd = (struct BrowserDir *)bd->Node.mln_Succ) {
- if (Info(bd->DirLock, info)) {
- hfl->MaxBuffer = MAXBUFFER_MOUNTED;
- break;
- }
- bd = nextbd;
- }
- }
- pp->pr_WindowPtr = WindowPtr;
- FreeMem(info, sizeof(struct InfoData));
- }
-
-
- static BOOL Mem(struct HeadFileList *hfl, long AskSize)
- {
- long AfterUse;
- long Avail;
-
- if (hfl->ActualUse + AskSize > hfl->MaxBuffer)
- return FALSE;
- Avail = AvailMem(MEMF_PUBLIC);
- /* Never use more than 80% of initial available mem, and allways leave at least 15 KB free */
- AfterUse = hfl->StartMem - Avail - AskSize;
- if (Avail < BUFFSIZEUNIT+5000 || hfl->StartMem * 8 < AfterUse * 10)
- return FALSE;
- return TRUE;
- }
-
-
- /* Copy Quick handling routine. Skip file if older than existing one. If return TRUE, file must be copied */
-
- static BOOL CheckDest(BPTR DestDir, struct SuperFileInfo *sfi)
- {
- struct FileInfoBlock *fib;
- BPTR CD;
- BOOL ret = TRUE;
-
- if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)))
- return FALSE;
- CD = CurrentDir(DestDir);
- if (GetFib(sfi->FileInfo.fi_Name, fib, FALSE) == A_RETRY) {
- if (Date2Secs(&fib->fib_Date) >= sfi->FileInfo.fi_Secs) {
- sfi->Flags |= SFI_REMOVE|SFI_NOSELECT;
- ret = FALSE;
- }
- }
- CurrentDir(CD);
- FreeMem(fib, sizeof(struct FileInfoBlock));
- return ret;
- }
-
-
- /* Obtain lock on destination directory if exists */
-
- static short GetDestDir(BPTR DestDir, struct SuperFileInfo *sfi)
- {
- struct FileInfoBlock *fib;
- BPTR CD, DirLock;
- char *Name;
- short Ok = A_RETRY;
-
- if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)))
- return A_STOP;
- CD = CurrentDir(DestDir);
- Name = sfi->FileInfo.fi_Name;
- while(Ok == A_RETRY && (DirLock = Lock(Name, ACCESS_READ))) {
- while (Ok == A_RETRY && !Examine(DirLock, fib))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't get info for \"%s\"\n%s.", Name, StrIoErr());
- if (Ok == A_RETRY) {
- if (fib->fib_DirEntryType > 0) {
- Fib2Fi(&sfi->FileInfo, fib); /* get info from dest dir for action back */
- break;
- }
- else {
- UnLock(DirLock);
- Ok = ThreeGadRequest("Retry", "Skip", "Can't create dir \"%s\"\nA file already exists.", Name);
- if (Ok != A_RETRY) {
- sfi->Flags |= SFI_REMOVE;
- DirLock = NULL;
- }
- }
- }
- }
- FreeMem(fib, sizeof(struct FileInfoBlock));
- sfi->FileDir.Dir.DestDir = DirLock;
- CurrentDir(CD);
- return Ok;
- }
-
-
- static short HandleCopyFlags(struct SuperFileInfo *sfi, struct FileInfoBlock *fib, UBYTE CopyFlags)
- {
- char *Name;
- short Ok = A_RETRY;
-
- Name = sfi->FileInfo.fi_Name;
- if (CopyFlags & (CF_CLONE|CF_DATE))
- Ok = Touch(Name, &sfi->FileInfo.fi_Date);
- if (Ok == A_RETRY && CopyFlags & (CF_CLONE|CF_PROTECT))
- Ok = Protect(Name, sfi->FileInfo.fi_Protection & ~FIBF_ARCHIVE);
- if (Ok == A_RETRY && CopyFlags & (CF_CLONE|CF_COMMENT))
- Ok = Comment(Name, sfi->FileInfo.fi_Comment);
- if (Ok == A_RETRY && (Ok = GetFib(Name, fib, TRUE) == A_RETRY))
- Fib2Fi(&sfi->FileInfo, fib);
- if (Ok == A_RETRY)
- sfi->ActionBack |= AB_NEW_ENTRY;
- return Ok;
- }
-
-
- /* Try to obtain destination directory. If doesn't exists, create it */
-
- static short MakeDestDir(struct SuperFileInfo *sfi, struct FileInfoBlock *fib, UBYTE CopyFlags, UBYTE CopyMode)
- {
- BPTR CurrentDir, DirLock;
- char *Name;
- short Ok = A_RETRY;
-
- if (sfi->FileDir.Dir.DestDir)
- return A_RETRY;
- CurrentDir = ((struct Process *)SysBase->ThisTask)->pr_CurrentDir;
- if (sfi->FileInfo.fi_Type == DLX_DIR && (CopyMode & CM_COPY_HIERARCHY)) {
- if ((Ok = GetDestDir(CurrentDir, sfi)) == A_RETRY) {
- if (!sfi->FileDir.Dir.DestDir) {
- /* dir doesn't exist so, create it */
- Name = sfi->FileInfo.fi_Name;
- while(Ok == A_RETRY && !(DirLock = CreateDir(Name)))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't create dir \"%s\"\n%s.", Name, StrIoErr());
- if (Ok == A_RETRY) {
- /* replace the ACCESS_WRITE lock given by CreateDir() by an ACCESS_READ lock so people can access it */
- UnLock(DirLock);
- DirLock = NULL;
- Ok = HandleCopyFlags(sfi, fib, CopyFlags);
- while(Ok == A_RETRY && !(DirLock = Lock(Name, ACCESS_READ)))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't access \"%s\"\n%s.", Name, StrIoErr());
- }
- sfi->FileDir.Dir.DestDir = DirLock;
- }
- }
- }
- else /* volumes, devices, assigns, or don't copy hierarchy */
- sfi->FileDir.Dir.DestDir = DupLock(CurrentDir);
- return Ok;
- }
-
-
- static short PurgeBuffer(struct SuperFileInfo *sfi)
- {
- struct BufferList *Cur;
- char *Buffer;
- long ToBeWritten;
- short Ok = A_RETRY;
-
- while(Ok == A_RETRY && (Cur = sfi->FileDir.File.BufferList)) {
- sfi->FileDir.File.BufferList = Cur->Next;
- ToBeWritten = Cur->Size;
- Buffer = Cur->Memory;
- while(Ok == A_RETRY && (ToBeWritten -= Write(sfi->FileDir.File.FH_D, Buffer, ToBeWritten)) != 0) {
- Buffer = Cur->Memory + Cur->Size - ToBeWritten;
- Ok = ThreeGadRequest("Retry", "Skip", "Error writing \"%s\"\n%s.", sfi->FileInfo.fi_Name, StrIoErr());
- }
- FreeMem(Cur, Cur->Size+sizeof(struct BufferList));
- }
- return Ok;
- }
-
-
- static short WriteFile(struct SuperFileInfo *sfi, struct FileInfoBlock *fib, UBYTE CopyFlags, UBYTE CopyMode)
- {
- BPTR FileLock;
- char *Name;
- short Ok = A_RETRY;
-
- Name = sfi->FileInfo.fi_Name;
- if ((sfi->ActionBack & AB_DELETE_DEST) && sfi->FileDir.File.FH_D) {
- Close(sfi->FileDir.File.FH_D);
- sfi->FileDir.File.FH_D = NULL;
- DeleteDest(Name);
- }
- if (sfi->FileDir.File.BufferList) {
- if (!sfi->FileDir.File.FH_D) {
- if ((CopyMode & (CM_ASK_OVERWRITE|CM_DONT_OVERWRITE)) && (FileLock = Lock(Name, ACCESS_READ))) {
- UnLock(FileLock);
- if (CopyMode & CM_DONT_OVERWRITE) {
- Ok = A_SKIP;
- sfi->Flags |= SFI_REMOVE|SFI_NOSELECT;
- }
- else if (!TwoGadRequest(ReqTitle, "File \"%s\" already exists\nOverwrite it ?", Name))
- Ok = A_SKIP;
- }
- while (Ok == A_RETRY && !(sfi->FileDir.File.FH_D = Open(Name, MODE_NEWFILE)))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't open \"%s\" for writing\n%s.", Name, StrIoErr());
- }
- if (Ok != A_RETRY)
- sfi->Flags |= SFI_REMOVE;
- else if ((Ok = PurgeBuffer(sfi)) != A_RETRY) {
- sfi->FileDir.File.ToBeRead = 0; /* something wrong happened, so don't continue reading ! */
- Close(sfi->FileDir.File.FH_D);
- sfi->FileDir.File.FH_D = NULL;
- sfi->Flags |= SFI_REMOVE;
- if (TwoGadRequest(ReqTitle, "File \"%s\" couldn't be copied\nDelete bad copy ?", Name))
- DeleteDest(Name);
- }
- else if (sfi->Flags & SFI_READ_FINISHED) {
- Close(sfi->FileDir.File.FH_D); /* close if nothing else must be read */
- sfi->FileDir.File.FH_D = NULL;
- Ok = HandleCopyFlags(sfi, fib, CopyFlags);
- }
- FreeFileBuffers(sfi);
- }
- return Ok;
- }
-
-
- static short WriteDir(struct HeadFileList *hfl, struct SuperFileInfo *StartSFI, struct FileInfoBlock *fib);
-
- static short WriteEntry(struct HeadFileList *hfl, struct SuperFileInfo *sfi, struct FileInfoBlock *fib)
- {
- short Ok = A_RETRY;
- BPTR CD;
-
- if ((sfi->FileInfo.fi_Type != DLX_FILE) && (sfi->Flags & (SFI_READING|SFI_READ_FINISHED))) {
- if ((Ok = MakeDestDir(sfi, fib, hfl->CopyFlags, hfl->CopyMode)) == A_RETRY) {
- CD = CurrentDir(sfi->FileDir.Dir.DestDir);
- Ok = WriteDir(hfl, sfi, fib);
- CurrentDir(CD);
- }
- else
- sfi->Flags |= SFI_REMOVE;
- }
- else
- Ok = WriteFile(sfi, fib, hfl->CopyFlags, hfl->CopyMode);
- return Ok;
- }
-
-
- static short WriteDir(struct HeadFileList *hfl, struct SuperFileInfo *StartSFI, struct FileInfoBlock *fib)
- {
- struct SuperFileInfo *sfi, *nextsfi;
- short Ok = A_RETRY;
-
- sfi = (struct SuperFileInfo *)StartSFI->FileDir.Dir.SuperFileList.mlh_Head;
- while(Ok != A_STOP && (nextsfi = (struct SuperFileInfo *)sfi->Node.mln_Succ)) {
- Ok = WriteEntry(hfl, sfi, fib);
- if (sfi->Flags & (SFI_READ_FINISHED|SFI_REMOVE)) {
- if (sfi->Flags & SFI_REMOVE && !(sfi->Flags & SFI_NOSELECT))
- sfi->ActionBack = (sfi->ActionBack & ~AB_DESELECT) | AB_SELECT;
- SendActionBack(sfi, StartSFI->FileDir.Dir.SrcDir, StartSFI->FileDir.Dir.DestDir);
- if (!(sfi->Flags & SFI_READING)) {
- Remove((struct Node *)sfi);
- FreeSuperFileInfo(sfi, NULL, NULL);
- }
- }
- if (Ok != A_RETRY)
- hfl->CopySuccessfull = FALSE;
- sfi = nextsfi;
- }
- if ((StartSFI->Flags & SFI_READ_FINISHED) && (hfl->CopyMode & CM_COPY_HIERARCHY))
- SendUpdateDir(StartSFI->FileDir.Dir.DestDir);
- return Ok;
- }
-
-
- static short WriteFileList(struct HeadFileList *hfl)
- {
- struct FileInfoBlock *fib;
- struct SuperFileInfo *sfi, *nextsfi;
- struct BrowserDir *bd;
- short Ok = A_RETRY;
- BPTR CD;
- BOOL Duplicate;
-
- /* if hfl->NewName isn't empty, the action is Duplicate, else Copy */
- Duplicate = (hfl->ActionArgs.NewName[0]) ? TRUE : FALSE;
- /* Allocate a fib for WriteFile() to examine dest file */
- if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)))
- return A_STOP;
- CD = CurrentDir(hfl->DestDir);
- bd = (struct BrowserDir *)hfl->DirList.mlh_Head;
- while(Ok != A_STOP && bd->Node.mln_Succ) {
- if (Duplicate && bd->DirLock)
- CurrentDir(bd->DirLock);
- sfi = (struct SuperFileInfo *)bd->SuperFileList.mlh_Head;
- while(Ok != A_STOP && (nextsfi = (struct SuperFileInfo *)sfi->Node.mln_Succ)) {
- if ((Ok = WriteEntry(hfl, sfi, fib)) != A_RETRY)
- hfl->CopySuccessfull = FALSE;
- if ((sfi->Flags & SFI_REMOVE) || (sfi->Flags & SFI_READ_FINISHED) && !(hfl->CopyMode & CM_ALLWAYS_MOVE)) {
- if (sfi->Flags & SFI_REMOVE && !(sfi->Flags & SFI_NOSELECT))
- sfi->ActionBack = (sfi->ActionBack & ~AB_DESELECT) | AB_SELECT;
- SendActionBack(sfi, bd->DirLock, (Duplicate) ? bd->DirLock : hfl->DestDir);
- }
- if ((sfi->Flags & SFI_REMOVE) && !(sfi->Flags & SFI_READING)) {
- Remove((struct Node *)sfi);
- FreeSuperFileInfo(sfi, NULL, NULL);
- }
- sfi = nextsfi;
- }
- if (Duplicate)
- SendUpdateDir(bd->DirLock);
- bd = (struct BrowserDir *)bd->Node.mln_Succ;
- }
- FreeMem(fib, sizeof(struct FileInfoBlock));
- CurrentDir(CD);
- /* ok, memory released now */
- hfl->StartMem = AvailMem(MEMF_PUBLIC); /* reset the base mem */
- hfl->ActualUse = 0;
- return Ok;
- }
-
-
- static short Read2Buffer(struct HeadFileList *hfl, struct SuperFileInfo *sfi, struct BufferList **bl)
- {
- char *Buffer;
- long ToBeRead, size;
- short Ok = A_RETRY;
-
- size = (sfi->FileDir.File.ToBeRead > BUFFSIZEUNIT) ? BUFFSIZEUNIT : sfi->FileDir.File.ToBeRead;
- if (!Mem(hfl, size+sizeof(struct BufferList)))
- return -1; /* Mem() say there is not enough memory */
- if (!(*bl = AllocMem(size+sizeof(struct BufferList), MEMF_PUBLIC)))
- return -1; /* Can't alloc buffer, so return a mem error */
- ToBeRead = (*bl)->Size = size;
- (*bl)->Next = NULL;
- Buffer = (*bl)->Memory;
- while(Ok == A_RETRY && (ToBeRead -= Read(sfi->FileDir.File.FH_S, Buffer, ToBeRead)) != 0) {
- Buffer = (*bl)->Memory + size - ToBeRead;
- Ok = ThreeGadRequest("Retry", "Skip", "Error reading \"%s\"\n%s.", sfi->FileInfo.fi_Name, StrIoErr());
- }
- sfi->FileDir.File.ToBeRead -= size;
- hfl->ActualUse += size+sizeof(struct BufferList);
- return Ok;
- }
-
-
- static short CopyFile(struct HeadFileList *hfl, struct SuperFileInfo *sfi)
- {
- struct BufferList **CBL = NULL;
- char *Name;
- short Ok = A_RETRY;
-
- Name = sfi->OldName;
- while (Ok == A_RETRY && !(sfi->FileDir.File.FH_S = Open(Name, MODE_OLDFILE)))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't open \"%s\" for reading\n%s.", Name, StrIoErr());
- if (Ok == A_RETRY) {
- sfi->Flags |= SFI_READING;
- sfi->FileDir.File.ToBeRead = sfi->FileInfo.fi_Size;
- CBL = &sfi->FileDir.File.BufferList;
- while(Ok == A_RETRY && sfi->FileDir.File.ToBeRead) {
- switch(Ok = Read2Buffer(hfl, sfi, CBL)) {
- case -1:
- if (hfl->ActualUse == 0)
- Ok = A_STOP; /* Not enough memory for Copy */
- else
- Ok = WriteFileList(hfl);
- CBL = &(sfi->FileDir.File.BufferList); /* reset the mem ptr: return to beginning */
- break;
- case A_RETRY:
- CBL = &(*CBL)->Next;
- break;
- default: /* Skip or Cancel */
- sfi->ActionBack = AB_SELECT|AB_DELETE_DEST;
- FreeFileBuffers(sfi); /* free memory used by this file */
- /* now recompute ActualUse. This not really valid since number_of_buffer * sizeof(struct BufferList) is lost,
- * but as we don't know the number of buffers, it better than loosing everything! */
- hfl->ActualUse -= sfi->FileInfo.fi_Size - sfi->FileDir.File.ToBeRead;
- hfl->CopySuccessfull = FALSE;
- }
- }
- Close(sfi->FileDir.File.FH_S);
- sfi->FileDir.File.FH_S = NULL;
- sfi->Flags = (sfi->Flags & ~SFI_READING) | SFI_READ_FINISHED;
- }
- else
- sfi->Flags |= SFI_REMOVE;
- return Ok;
- }
-
-
- static short CopyDir(struct HeadFileList *hfl, struct SuperFileInfo *StartSFI, struct FileInfoBlock *StartFib)
- {
- struct SuperFileInfo *sfi;
- struct FileInfoBlock *fib;
- BPTR CD, DirLock;
- char *Name;
- BOOL NoCheck = FALSE; /* Copy Quick handling. If dest dir don't exists yet, no use to check for presence of a file in it! */
- short err, Ok = A_RETRY;
-
- if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)))
- return A_STOP;
- if ((hfl->CopyMode & CM_UPDATE) && !StartSFI->FileDir.Dir.DestDir)
- NoCheck = TRUE;
- Name = StartSFI->OldName;
- while(Ok == A_RETRY && !(DirLock = Lock(Name, ACCESS_READ)))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't access \"%s\"\n%s.", Name, StrIoErr());
- if (Ok != A_RETRY) {
- StartSFI->Flags |= SFI_REMOVE;
- StartSFI->ActionBack = AB_SELECT;
- }
- else {
- StartSFI->FileDir.Dir.SrcDir = DirLock;
- CD = CurrentDir(DirLock);
- NewMinList(&StartSFI->FileDir.Dir.SuperFileList);
- *fib = *StartFib;
- StartSFI->Flags |= SFI_READING|SFI_DIREMPTY;
- while (Ok != A_STOP && ExNext(DirLock, fib)) {
- if (sfi = AllocMem(sizeof(struct SuperFileInfo), MEMF_PUBLIC|MEMF_CLEAR)) {
- Ok = A_RETRY;
- Fib2Fi(&sfi->FileInfo, fib);
- if (!(hfl->Select.si_Flags & SI_AFFECT_SUBDIRS) || MatchFilters(&sfi->FileInfo, &hfl->Select)) {
- /* link file to current dir filelist */
- AddTail((struct List *)&StartSFI->FileDir.Dir.SuperFileList, (struct Node *)sfi);
- strcpy(sfi->OldName, sfi->FileInfo.fi_Name);
- if (sfi->FileInfo.fi_Type == DLX_FILE) {
- if (!(hfl->CopyMode & CM_UPDATE) || NoCheck || CheckDest(StartSFI->FileDir.Dir.DestDir, sfi))
- Ok = CopyFile(hfl, sfi);
- }
- else {
- if (hfl->CopyMode & CM_UPDATE)
- Ok = GetDestDir(StartSFI->FileDir.Dir.DestDir, sfi);
- if (Ok == A_RETRY && !(sfi->Flags & SFI_REMOVE))
- Ok = CopyDir(hfl, sfi, fib);
- }
- if (Ok == A_RETRY && !(sfi->Flags & SFI_DIREMPTY))
- StartSFI->Flags &= ~SFI_DIREMPTY;
- if (sfi->Flags & SFI_REMOVE) {
- /* no dest dir for action back here, file wasn't written */
- if (!(sfi->Flags & SFI_NOSELECT))
- sfi->ActionBack = (sfi->ActionBack & ~AB_DESELECT) | AB_SELECT;
- Remove((struct Node *)sfi);
- FreeSuperFileInfo(sfi, DirLock, NULL);
- }
- }
- else {
- CleanFileInfo(&sfi->FileInfo);
- FreeMem(sfi, sizeof(struct SuperFileInfo));
- }
- }
- else
- Ok = A_STOP;
- }
- if (Ok == A_RETRY && (err = IoErr()) != ERROR_NO_MORE_ENTRIES)
- Ok = ThreeGadRequest("Skip", NULL, "Error reading directory \"%s\"\n%s.", Name, DosError(err)) << 1;
- if (!(hfl->CopyMode & CM_COPY_EMPTYDIRS) && (StartSFI->Flags & SFI_DIREMPTY))
- StartSFI->Flags |= SFI_REMOVE;
- CurrentDir(CD);
- }
- if (Ok != A_RETRY)
- hfl->CopySuccessfull = FALSE;
- StartSFI->Flags = (StartSFI->Flags & ~SFI_READING) | SFI_READ_FINISHED;
- FreeMem(fib, sizeof(struct FileInfoBlock));
- return Ok;
- }
-
-
- static short MoveFile(struct SuperFileInfo *sfi, BPTR DestDir)
- {
- short Ok = A_RETRY;
- char *OldName, *NewName;
- char Buffer[300];
-
- OldName = sfi->FileInfo.fi_Name;
- PathName(DestDir, Buffer, 255);
- /* remove volume name from path to avoid disk confusion if two volumes have the same name */
- NewName = Buffer;
- while(*NewName && *NewName != ':') NewName++;
- TackOn(NewName, OldName);
- while(Ok == A_RETRY && !Rename(OldName, NewName))
- Ok = ThreeGadRequest("Retry", "Skip", "Couldn't move \"%s\"\n%s.", OldName, StrIoErr());
- if (Ok == A_RETRY)
- sfi->ActionBack |= (AB_DELETE_SOURCE|AB_NEW_ENTRY);
- else
- sfi->ActionBack = AB_SELECT;
- return Ok;
- }
-
-
- void CopyMove(struct HeadFileList *hfl)
- {
- struct FileInfoBlock *fib;
- struct SuperFileInfo *sfi, *nextsfi;
- struct BrowserDir *bd, *nextbd;
- BOOL Duplicate;
- short Ok = A_RETRY;
-
- if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)))
- return;
- Duplicate = (hfl->ActionArgs.NewName[0]) ? TRUE : FALSE;
- /* init some global var for test mem use */
- hfl->StartMem = AvailMem(MEMF_PUBLIC); /* init base mem */
- hfl->ActualUse = 0;
- hfl->CopySuccessfull = TRUE;
- InitMaxBuf(hfl);
-
- bd = (struct BrowserDir *)hfl->DirList.mlh_Head;
- while(Ok != A_STOP && (nextbd = (struct BrowserDir *)bd->Node.mln_Succ)) {
- if (bd->DirLock)
- CurrentDir(bd->DirLock);
- sfi = (struct SuperFileInfo *)bd->SuperFileList.mlh_Head;
- if (!(hfl->CopyMode & CM_ALLWAYS_COPY) && bd->RootLock && !CompareLock(bd->RootLock, hfl->DestRoot)) {
- while(Ok != A_STOP && (nextsfi = (struct SuperFileInfo *)sfi->Node.mln_Succ)) {
- Ok = MoveFile(sfi, hfl->DestDir);
- SendActionBack(sfi, bd->DirLock, hfl->DestDir);
- sfi = nextsfi;
- }
- Remove((struct Node *)bd);
- FreeBrowserDir(bd, NULL);
- }
- else {
- while(Ok != A_STOP && (nextsfi = (struct SuperFileInfo *)sfi->Node.mln_Succ)) {
- if ((Ok = GetFib(sfi->FileInfo.fi_Name, fib, TRUE)) == A_RETRY) {
- /* Don't Fib2Fi() for a device, volume or assign. It removes
- * ending colon from name */
- if (sfi->FileInfo.fi_Type == DLX_FILE || sfi->FileInfo.fi_Type == DLX_DIR)
- Fib2Fi(&sfi->FileInfo, fib);
- }
- if (Ok == A_RETRY && Duplicate)
- Ok = MakeNewName(sfi->FileInfo.fi_Name, hfl->ActionArgs.NewName, sfi->OldName);
- if (Ok == A_RETRY) {
- switch(sfi->FileInfo.fi_Type) {
- case DLX_FILE:
- if (!(hfl->CopyMode & CM_UPDATE) || CheckDest((Duplicate) ? bd->DirLock : hfl->DestDir, sfi))
- Ok = CopyFile(hfl, sfi);
- break;
- case DLX_DIR:
- if (hfl->CopyMode & CM_UPDATE)
- Ok = GetDestDir(hfl->DestDir, sfi);
- if (Ok == A_RETRY && !(sfi->Flags & SFI_REMOVE))
- Ok = CopyDir(hfl, sfi, fib);
- break;
- default: /* Volume, Device, or Assign */
- Ok = CopyDir(hfl, sfi, fib);
- }
- }
- if (sfi->Flags & SFI_REMOVE) {
- /* no dest dir for action back here, file wasn't written */
- if (!(sfi->Flags & SFI_NOSELECT))
- sfi->ActionBack = (sfi->ActionBack & ~AB_DESELECT) | AB_SELECT;
- Remove((struct Node *)sfi);
- FreeSuperFileInfo(sfi, bd->DirLock, NULL);
- }
- sfi = nextsfi;
- }
- }
- bd = nextbd;
- }
- FreeMem(fib, sizeof(struct FileInfoBlock));
- if (Ok != A_STOP)
- Ok = WriteFileList(hfl);
- if (Ok != A_STOP && (hfl->CopyMode & CM_ALLWAYS_MOVE)) {
- if (!hfl->CopySuccessfull)
- Ok = TwoGadRequest(ReqTitle, "One or more file(s) not copied\nDelete source(s) anyway ?");
- if (Ok != A_STOP)
- DoAction(hfl, BROWSERACTION_DELETE);
- }
- CurrentDir(((struct TaskData *)SysBase->ThisTask->tc_UserData)->td_InitialDir);
- }
-
-
-