home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d540
/
browser.lha
/
Browser
/
BrowserII_Src.LZH
/
Copy.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-28
|
20KB
|
612 lines
/*
* 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);
}