*/
#include "sysincludes.h"
-#include "msdos.h"
#include "mtools.h"
-#include "vfat.h"
#include "fs.h"
#include "mainloop.h"
#include "plain_io.h"
/* drive letter present? */
s = buf;
if (buf[0] && buf[1] == ':') {
- strncpy(ans, buf, 2);
+ memcpy(ans, buf, 2);
ans[2] = '\0';
s = &buf[2];
} else {
return ans;
}
-int unix_dir_loop(Stream_t *Stream, MainParam_t *mp);
-int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp, char *arg,
- int follow_dir_link);
-
static int _unix_loop(Stream_t *Dir, MainParam_t *mp,
const char *filename UNUSEDP)
{
{
int ret;
int isdir=0;
- int unixNameLength;
+ size_t unixNameLength;
mp->File = NULL;
mp->direntry = NULL;
fprintf(stderr,
"skipping directory symlink %s\n",
arg);
- return 0;
+ return 0;
}
#endif
if(! (mp->lookupflags & ACCEPT_DIR))
return ret;
}
-
-int isSpecial(const char *name)
-{
- if(name[0] == '\0')
- return 1;
- if(!strcmp(name,"."))
- return 1;
- if(!strcmp(name,".."))
- return 1;
- return 0;
-}
-
-#ifdef HAVE_WCHAR_H
-int isSpecialW(const wchar_t *name)
-{
- if(name[0] == '\0')
- return 1;
- if(!wcscmp(name,L"."))
- return 1;
- if(!wcscmp(name,L".."))
- return 1;
- return 0;
-}
-#endif
-
static int checkForDot(int lookupflags, const wchar_t *name)
{
return (lookupflags & NO_DOTS) && isSpecialW(name);
}
static int handle_leaf(direntry_t *direntry, MainParam_t *mp,
- lookupState_t *lookupState)
+ lookupState_t *lookupState,
+ Stream_t **DeferredFileP)
{
Stream_t *MyFile=0;
int ret;
return 0;
case 1: /* we have already a directory */
FREE(&lookupState->Dir);
- fprintf(stderr,"Ambigous\n");
+ fprintf(stderr,"Ambiguous\n");
return STOP_NOW | ERROR_ONE;
default:
return STOP_NOW | ERROR_ONE;
MyFile = mp->File = OpenFileByDirentry(direntry);
ret = mp->dirCallback(direntry, mp);
} else {
- if(mp->lookupflags & DO_OPEN)
+ if(mp->lookupflags & DO_OPEN) {
+ if(DeferredFileP && *DeferredFileP) {
+ /* Already a deferred file => close it and error */
+ FREE(DeferredFileP);
+ fprintf(stderr,
+ "Attempt to copy multiple files to non-directory\n");
+ return STOP_NOW | ERROR_ONE;
+ }
+
MyFile = mp->File = OpenFileByDirentry(direntry);
+ if(DeferredFileP) {
+ *DeferredFileP = MyFile;
+ return 0;
+ }
+ }
ret = mp->callback(direntry, mp);
}
FREE(&MyFile);
- if(isUniqueTarget(mp->targetName))
- ret |= STOP_NOW;
return ret;
}
static int _dos_loop(Stream_t *Dir, MainParam_t *mp, const char *filename)
-{
+{
Stream_t *MyFile=0;
direntry_t entry;
int ret;
r=0;
initializeDirentry(&entry, Dir);
while(!got_signal &&
- (r=vfat_lookup(&entry, filename, -1,
- mp->lookupflags, mp->shortname,
- mp->longname)) == 0 ){
+ (r=vfat_lookup_zt(&entry, filename,
+ mp->lookupflags,
+ mp->shortname.data, mp->shortname.len,
+ mp->longname.data, mp->longname.len)) == 0 ){
mp->File = NULL;
if(!checkForDot(mp->lookupflags,entry.name)) {
MyFile = 0;
static int recurs_dos_loop(MainParam_t *mp, const char *filename0,
const char *filename1,
- lookupState_t *lookupState)
+ lookupState_t *lookupState,
+ Stream_t **DeferredFileP)
{
/* Dir is de-allocated by the same entity which allocated it */
const char *ptr;
direntry_t entry;
- int length;
+ size_t length;
int lookupflags;
int ret;
int have_one;
(!strcmp(filename0, "..") && filename1)) {
/* up one level */
mp->File = getDirentry(mp->File)->Dir;
- return recurs_dos_loop(mp, filename0+2, filename1, lookupState);
+ return recurs_dos_loop(mp, filename0+2, filename1, lookupState,
+ DeferredFileP);
}
doing_mcwd = !!filename1;
ptr = strchr(filename0, '/');
- if(!ptr) {
- length = strlen(filename0);
+ if(!ptr) {
+ length = strlen(filename0);
ptr = filename1;
filename1 = 0;
} else {
- length = ptr - filename0;
+ length = ptrdiff(ptr, filename0);
ptr++;
}
if(!ptr) {
if(mp->lookupflags & OPEN_PARENT) {
mp->targetName = filename0;
ret = handle_leaf(getDirentry(mp->File), mp,
- lookupState);
+ lookupState, NULL);
mp->targetName = 0;
return ret;
}
-
+
if(!strcmp(filename0, ".") || !filename0[0]) {
return handle_leaf(getDirentry(mp->File),
- mp, lookupState);
+ mp, lookupState, NULL);
}
if(!strcmp(filename0, "..")) {
return handle_leaf(getParent(getDirentry(mp->File)), mp,
- lookupState);
+ lookupState, NULL);
}
lookupflags = mp->lookupflags;
-
+
if(lookupState) {
lookupState->filename = filename0;
if(lookupState->nbContainers + lookupState->nbDirs > 0){
!got_signal &&
(r=vfat_lookup(&entry, filename0, length,
lookupflags | NO_MSG,
- mp->shortname, mp->longname)) == 0 ){
+ mp->shortname.data, mp->shortname.len,
+ mp->longname.data, mp->longname.len)) == 0 ){
if(checkForDot(lookupflags, entry.name))
/* while following the path, ignore the
* special entries if they were not
if(ptr) {
Stream_t *SubDir;
SubDir = mp->File = OpenFileByDirentry(&entry);
- ret |= recurs_dos_loop(mp, ptr, filename1, lookupState);
+ ret |= recurs_dos_loop(mp, ptr, filename1, lookupState,
+ DeferredFileP);
FREE(&SubDir);
} else {
- ret |= handle_leaf(&entry, mp, lookupState);
- if(isUniqueTarget(mp->targetName))
- return ret | STOP_NOW;
+ ret |= handle_leaf(&entry, mp, lookupState,
+ DeferredFileP);
}
if(doing_mcwd)
break;
Stream_t *RootDir;
const char *cwd;
char drive;
+ Stream_t *DeferredFile=NULL;
+ Stream_t **DeferredFileP=NULL;
int ret;
mp->loop = _dos_loop;
-
+
drive='\0';
cwd = "";
if(*pathname && pathname[1] == ':') {
if(!mp->File)
return ERROR_ONE;
- ret = recurs_dos_loop(mp, cwd, pathname, lookupState);
+ if(mp->originalArg && strpbrk(mp->originalArg, "*[?") != 0 &&
+ (mp->lookupflags & DEFERABLE) &&
+ isUniqueTarget(mp->targetName))
+ DeferredFileP = &DeferredFile;
+
+ ret = recurs_dos_loop(mp, cwd, pathname, lookupState, DeferredFileP);
if(ret & NO_CWD) {
/* no CWD */
*mp->mcwd = '\0';
unlink_mcwd();
- ret = recurs_dos_loop(mp, "", pathname, lookupState);
+ ret = recurs_dos_loop(mp, "", pathname, lookupState, DeferredFileP);
+ }
+ if(DeferredFile) {
+ mp->File = DeferredFile;
+ ret = mp->callback(NULL, mp);
+ FREE(&DeferredFile);
}
FREE(&RootDir);
return ret;
}
-static int dos_target_lookup(MainParam_t *mp, const char *arg)
+int dos_target_lookup(MainParam_t *mp, const char *arg)
{
lookupState_t lookupState;
int ret;
return ret;
default:
/* too much */
- fprintf(stderr, "Ambigous %s\n", arg);
- return ERROR_ONE;
- }
-}
-
-static int unix_target_lookup(MainParam_t *mp, const char *arg)
-{
- char *ptr;
- mp->unixTarget = strdup(arg);
- /* try complete filename */
- if(access(mp->unixTarget, F_OK) == 0)
- return GOT_ONE;
- ptr = strrchr(mp->unixTarget, '/');
- if(!ptr) {
- mp->targetName = mp->unixTarget;
- mp->unixTarget = strdup(".");
- return GOT_ONE;
- } else {
- *ptr = '\0';
- mp->targetName = ptr+1;
- return GOT_ONE;
+ fprintf(stderr, "Ambiguous %s\n", arg);
+ return ERROR_ONE;
}
}
-int target_lookup(MainParam_t *mp, const char *arg)
-{
- if((mp->lookupflags & NO_UNIX) || (arg[0] && arg[1] == ':' ))
- return dos_target_lookup(mp, arg);
- else
- return unix_target_lookup(mp, arg);
-}
-
int main_loop(MainParam_t *mp, char **argv, int argc)
{
int i;
int ret, Bret;
-
+
Bret = 0;
if(argc != 1 && mp->targetName) {
fprintf(stderr,
"Several file names given, but last argument (%s) not a directory\n", mp->targetName);
+ FREE(&mp->targetDir);
+ return 1;
}
for (i = 0; i < argc; i++) {
ret = unix_loop(0, mp, argv[i], 1);
else
ret = dos_loop(mp, argv[i]);
-
+
if (! (ret & (GOT_ONE | ERROR_ONE)) ) {
/* one argument was unmatched */
fprintf(stderr, "%s: File \"%s\" not found\n",
{
fix_mcwd(mp->mcwd);
mp->openflags = O_RDONLY;
+ mp->lookupflags = 0;
mp->targetName = 0;
mp->targetDir = 0;
- mp->unixTarget = 0;
mp->dirCallback = dispatchToFile;
mp->unixcallback = NULL;
- mp->shortname = mp->longname = 0;
+ mp->shortname.data = mp->longname.data = 0;
+ mp->shortname.len = mp->longname.len = 0;
mp->File = 0;
mp->fast_quit = 0;
+ mp->originalArg = 0;
}
const char *mpGetBasename(MainParam_t *mp)
{
if(mp->direntry) {
wchar_to_native(mp->direntry->name, mp->targetBuffer,
- MAX_VNAMELEN+1);
+ MAX_VNAMELEN+1, sizeof(mp->targetBuffer));
return mp->targetBuffer;
} else
return _basename(mp->unixSourceName);
else
return mpGetBasename(mp);
}
-
-char *mpBuildUnixFilename(MainParam_t *mp)
-{
- const char *target;
- char *ret;
- char *tmp;
-
- target = mpPickTargetName(mp);
- ret = malloc(strlen(mp->unixTarget) + 2 + strlen(target));
- if(!ret)
- return 0;
- strcpy(ret, mp->unixTarget);
- if(*target) {
-#if 1 /* fix for 'mcopy -n x:file existingfile' -- H. Lermen 980816 */
- if(!mp->targetName && !mp->targetDir) {
- struct MT_STAT buf;
- if (!MT_STAT(ret, &buf) && !S_ISDIR(buf.st_mode))
- return ret;
- }
-#endif
- strcat(ret, "/");
- if(!strcmp(target, ".")) {
- target="DOT";
- } else if(!strcmp(target, "..")) {
- target="DOTDOT";
- }
- while( (tmp=strchr(target, '/')) ) {
- strncat(ret, target, tmp-target);
- strcat(ret, "\\");
- target=tmp+1;
- }
- strcat(ret, target);
- }
- return ret;
-}