int dir_print_body(char *arg, unsigned long *dircount) { int rv; unsigned long filecount, bytecount; char *pattern, *cachedPattern; char *p; /* Modified to pre-allocate path to 270 bytes so that we don't have to realloc() it later. That was causing "DIR /S" not to work properly. The path variable cannot be reallocated once dir_list() is called, because dir_list() is recursive. This will also help to reduce memory fragmentation. */ if((p = dfnfullpath(arg)) == NULL) { error_out_of_memory(); return E_NoMem; } if((path = realloc(p, 270*sizeof(char))) == NULL) { free(p); error_out_of_memory(); return E_NoMem; } filecount = bytecount = 0; /* print the header */ if((rv = dir_print_header(toupper(path[0]) - 'A')) == 0) { /* There are some directory specs that are not detected by dfnstat() as they are no part of the filesystem in DOS */ pattern = dfnfilename(path); assert(p); if(!*pattern || (dfnstat(path) & DFN_DIRECTORY) != 0) { pattern = strchr(pattern, '\0'); if(pattern[-1] != '\\') ++pattern; rv = dir_list(pattern - path, "*.*", dircount, &filecount , &bytecount ); } else { if((cachedPattern = strdup(pattern)) == NULL) { error_out_of_memory(); rv = E_NoMem; } else { rv = dir_list(pattern - path, cachedPattern, dircount , &filecount, &bytecount ); free(cachedPattern); } } } free(path); return rv || (optS? print_total(filecount, bytecount): 0); }
int dir_print_body(char *arg) { int rv; unsigned long dircount, filecount, bytecount; char *pattern, *cachedPattern; dprintf( ("[DIR: path=\"%s\"]\n", arg) ); if((path = dfnexpand(arg, NULL)) == NULL) { error_out_of_memory(); return E_NoMem; } dircount = filecount = bytecount = 0; pattern = strchr(path, '\0'); if(pattern[-1] == '\\') { /* trailing backslash means that this has to be a directory */ if(!StrAppChr(path, '.')) { error_out_of_memory(); return E_NoMem; } } dprintf( ("[DIR: absolute path=\"%s\"]\n", path) ); /* print the header */ if ((rv = dir_print_header(toupper(path[0]) - 'A')) == 0) { if(dfnstat(path) & DFN_DIRECTORY) { pattern = strchr(path, '\0'); if(pattern[-1] != '\\') ++pattern; rv = dir_list(pattern - path, "*.*", &dircount, &filecount , &bytecount); } else { if((cachedPattern = strdup(pattern = dfnfilename(path))) == NULL) { error_out_of_memory(); rv = E_NoMem; } else { rv = dir_list(pattern - path, cachedPattern, &dircount, &filecount , &bytecount); free(cachedPattern); } } } free(path); return rv; }
int dfnfreplace(const char * const newname, const char * const oldname) { char *bak; DBG_ENTER("dfnfreplace", Suppl_dfn) assert(newname); assert(oldname); DBG_ARGUMENTS( ("to:\"%s\", from=\"%s\"", newname, oldname) ) chkHeap if((bak = dfnbakname(newname)) != 0) { DBG_INFO( ("bakup=\"%s\"", bak) ) unlink(bak); /* delete the backup file, if present */ rename(newname, bak); /* backup current file, if present */ chkHeap free(bak); chkHeap if(!dfnstat(newname)) { /* file doesn't exist (either renamed or not present at all) */ rename(oldname, newname); if(dfnstat(newname)) /* rename succeded */ DBG_RETURN_I( ESUPPL_OK) }
/* * Grab the filename of COMMAND.COM * * If warn != 0, warnings can be issued; otherwise this functions * is silent. */ void grabComFilename(int warn, char far *fnam) { char *buf; size_t len; assert(fnam); /* Copy the filename into the local heap */ len = _fstrlen(fnam); if(len >= INT_MAX || len < 1) { /* no filename specified */ if(warn) error_syntax(NULL); return; } if((buf = malloc(len + 1)) == NULL) { if(warn) error_out_of_memory(); return ; } _fmemcpy((char far*)buf, fnam, len); buf[len] = '\0'; if (buf[1] != ':' || buf[2] != '\\') { char *p; /* expand the string for the user */ p = dfnexpand(buf, NULL); free(buf); if((buf = p) == NULL) { if(warn) error_out_of_memory(); return; } if(warn) error_init_fully_qualified(buf); } if(dfnstat(buf) & DFN_DIRECTORY) { /* The user specified a directory, try if we can find the COMMAND.COM with the standard name in there */ char *p; if((p = realloc(buf, len + sizeof(COM_NAME) + 1)) == NULL) { if(warn) error_out_of_memory(); free(buf); return; } buf = p; strcpy(&buf[len], "\\" COM_NAME); } if(!(dfnstat(buf) & DFN_FILE)) { /* not found */ if(warn) error_open_file(buf); free(buf); return; } free(ComPath); /* Save the found file */ ComPath = buf; }
int grabComFilename(const int warn, const char far * const fnam) { char *buf; size_t len; int rc; dprintf( ("[INIT: grabComFilename(%s)]\n", fnam) ); if(!fnam) return 4; /* Copy the filename into the local heap */ len = _fstrlen(fnam); if(len >= INT_MAX || len < 1) { /* no filename specified */ if(warn) error_syntax(0); return 4; } if((buf = malloc(len + 1)) == 0) { if(warn) error_out_of_memory(); return 4; } _fmemcpy((char far*)buf, fnam, len); buf[len] = '\0'; if (buf[1] != ':' || buf[2] != '\\') { char *p; /* expand the string for the user */ p = abspath(buf, warn); free(buf); if((buf = p) == 0) return 4; if(warn) error_init_fully_qualified(buf); len = strlen(buf); } while(buf[len - 1] == '\\') --len; buf[len] = 0; if(dfnstat(buf) & DFN_DIRECTORY) { /* The user specified a directory, try if we can find the COMMAND.COM with the standard name in there */ char *p; if((p = realloc(buf, len + sizeof(COM_NAME) + 1)) == 0) { if(warn) error_out_of_memory(); free(buf); return 4; } buf = p; strcpy(&buf[len], "\\" COM_NAME); } if(0 != (rc = validResFile(buf))) { if(warn) switch(rc) { default: #ifdef NDEBUG assert(0); #endif case 1: error_open_file(buf); break; case 2: error_fcom_is_device(buf); break; case 3: error_fcom_invalid(buf); break; } free(buf); return rc; } free(ComPath); /* Save the found file */ ComPath = buf; dprintf(("[INIT: new resource file name: %s]\n", ComPath)); isSwapFile = 0; buf = dfnfilename(ComPath); assert(buf); if((buf = strchr(buf, '.')) != 0 && stricmp(buf, ".swp") == 0) { dprintf(("[INIT: VSpawn file found: %s]\n", ComPath)); memcpy(++buf, "COM", 3); isSwapFile = buf - ComPath; } return 0; }
int cmd_del(char *rest) { int ec = E_None; /* exit code */ int i; unsigned count = 0; struct ffblk f; /* Make fullname somewhat larger to ensure that appending a matched name, one backslash and one hope. */ char fullname[MAXPATH + sizeof(f.ff_name) + 2], *p, *q; int len; char **arg; int argc, optc; /* initialize options */ optP = 0; if((arg = scanCmdline(rest, opt_del, 0, &argc, &optc)) == 0) return E_Other; if(!argc) { error_req_param_missing(); ec = E_Useage; } else { i = 0; do { assert(arg[i]); /* Get the pattern fully-qualified */ /* Note: An absolute path always contains: A:\\ --> It's always three bytes long at minimum and always contains a backslash */ p = dfnexpand(arg[i], 0); assert(strlen(p) >= 3); if ((len = strlen(p)) >= MAXPATH) { error_filename_too_long(p); free(p); ec = E_Other; goto errRet; } strcpy(fullname, p); /* Operating over a local buffer simplifies the process; rather than keep the pattern within dynamic memory */ free(p); p = fullname + len; /* check if it is a directory */ if(dfnstat(fullname) & DFN_DIRECTORY) { if (p[-1] != '\\') *p++ = '\\'; } if (p[-1] == '\\') /* delete a whole directory */ p = stpcpy(p, "*.*"); /* p := address to copy the filename to to form the fully-qualified filename */ /* There is at least one backslash within fullname, because of dfnexpand() */ while (*--p != '\\') ; ++p; /* make sure user is sure if all files are to be * deleted */ if (!optP && *p == '*' && ((q = strchr(p, '.')) == 0 || q[1] == '*')) { displayString(TEXT_MSG_DELETE_ALL); if (vcgetcstr("YN\n\r") != 'Y') { ec = E_Other; goto errRet; } } if (FINDFIRST(fullname, &f, FA_ARCH)) { error_sfile_not_found(fullname); } else do { strcpy(p, f.ff_name); /* Make the full path */ if (optP) { printf("%s, Delete(Y/N)?", fullname); switch (vcgetcstr("YN\n\r")) { case '\3': /* ^Break pressed */ ec = E_CBreak; goto errRet; case 'Y': break; /* yes, delete */ default: continue; /* no, don't delete */ } } else if (cbreak) { /* is also probed for in vcgetstr() */ ec = E_CBreak; goto errRet; } #ifdef NODEL /* define NODEL if you want to debug */ puts(fullname); #else if (unlink(fullname) != 0) { perror(fullname); /* notify the user */ } else ++count; #endif } while (FINDNEXT(&f) == 0); } while(++i < argc); } errRet: if(echo) { dispCount(count, "no file", "one file", "%u files"); puts(" removed."); } freep(arg); return ec; }
int cmd_copy(char *rest) { char **argv, *p; int argc, opts, argi; int freeDestFile = 0; struct CopySource *h; /* Initialize options */ optA = optB = optV = optY = 0; /* read the parameters from env */ if ((argv = scanCmdline(getEnv("COPYCMD"), opt_copy, 0, &argc, &opts)) == 0) return 1; freep(argv); /* ignore any parameter from env var */ if((argv = scanCmdline(rest, opt_copy, 0, &argc, &opts)) == 0) return 1; /* scan the trailing '/a' and '/b' options */ while(argc > 0 && isoption(argv[argc - 1])) { p = argv[--argc]; /* argv[] must not be changed */ if(leadOptions(&p, opt_copy1, 0) != E_None) { freep(argv); return 1; } } initContext(); /* Now parse the remaining arguments into the copy file structure */ for(argi = 0; argi < argc; ++argi) if(isoption(p = argv[argi])) { /* infix /a or /b */ if(leadOptions(&p, opt_copy1, 0) != E_None) { killContext(); freep(argv); return 1; } /* Change the flags of the previous argument */ if(lastApp) lastApp->flags = cpyFlags(); } else { /* real argument */ if(*p == '+') { /* to previous argument */ appendToFile = 1; while(*++p == '+'); if(!*p) continue; } if(!addSource(p)) { killContext(); freep(argv); return 1; } } if(appendToFile) { error_trailing_plus(); killContext(); freep(argv); return 1; } if(!last) { /* Nothing to do */ error_nothing_to_do(); killContext(); freep(argv); return 1; } assert(head); /* Now test if a destination was specified */ if(head != last && !last->app) { /* Yeah */ destFile = dfnexpand(last->fnam, 0); if(!destFile) { error_out_of_memory(); goto errRet; } freeDestFile = 1; h = head; /* remove it from argument list */ while(h->nxt != last) { assert(h->nxt); h = h->nxt; } free(last); (last = h)->nxt = 0; p = strchr(destFile, '\0') - 1; if(*p == '\\' || *p == '/') /* must be a directory */ destIsDir = 1; else destIsDir = dfnstat(destFile) & DFN_DIRECTORY; } else { /* Nay */ destFile = "."; destIsDir = 1; } /* Now copy the files */ h = head; while(copyFiles(h) && (h = h->nxt) != 0); if(freeDestFile) free(destFile); errRet: killContext(); freep(argv); return 0; }
int cd_dir(char *param, int cdd, const char * const fctname) { char **argv, *dir; int argc, opts; int rv, freeDir; if((argv = scanCmdline(param, 0, 0, &argc, &opts)) == 0) return 1; freeDir = 0; rv = 1; /* if doing a CD and no parameters given, print out current directory */ if(argc == 0) { if((dir = cwd(0)) != 0) { puts(dir); freeDir = 1; goto okRet; } goto errRet; } else if(argc != 1) { error_syntax(0); goto errRet; } else { assert(argv[0]); #ifdef FEATURE_CDD_FNAME /* if path refers to an existing file and not directory, ignore filename portion */ if (cdd && (dfnstat(argv[0]) & DFN_FILE)) { dir = strrchr(argv[0], '\\'); if (dir == NULL) { dir = argv[0]; if (dir[1] == ':') dir[2]='\0'; /* change drive only, no path */ else goto okRet; /* no drive, no path, so exit early */ } else /* includes a path or refers to root dir */ { *(dir+1) = '\0'; } } #endif dir = strchr(argv[0], '\0'); /* take off trailing \ if any, but ONLY if dir is not the root dir */ while(dir > &argv[0][1] && *--dir == '\\' && dir[-1] != ':') *dir = '\0'; dir = argv[0]; #ifdef FEATURE_LAST_DIR if(strcmp(dir, "-") == 0) { assert(!freeDir); /* change to last directory */ lastDirGet(&dir); freeDir = 1; } lastDirSet(); if(!dir) /* "CD -" without a CD before at all */ goto okRet; #endif if(*dir && dir[1] == ':') { if(cdd) { if(changeDrive(*dir) != 0) goto errRet; if(!dir[2]) /* only change drive */ goto okRet; } else if(!dir[2]) { /* Real CHDIR displays CWD of specified drive */ assert(freeDir == 0); if((dir = cwd(*dir)) != 0) { puts(dir); freeDir = 1; goto okRet; } goto errRet; } } dprintf(("%s: '%s'\n", fctname, dir)); if(chdir(dir) != 0) { error_dirfct_failed(fctname, dir); goto errRet; } } okRet: rv = 0; errRet: freep(argv); if(freeDir) free(dir); return rv; }
/* * Try to create a temporary file with the supplied path, also * fully-qualify it * * If ext != NULL, its contents is appended to a randomized prefix, * most useful, if 'ext' begins with a dot, to give the file to be * created an extension. */ char *mktempfile(const char * const path, const char *ext) { char *fn, *newpath; int cnt, fd; if (!path) /* to simplify the caller function */ return 0; if ((fn = dfnexpand(path, 0)) == 0) { /* out-of-mem */ nomem(); return 0; } if (!ext) /* make sure it's a legal string */ ext = ""; /* The completed name consits of: + the absolute path name, + the '\\' path component delimited path vs. filename + eight (8) characters randomized filename + the user-supplied extension + the '\0' terminator byte */ if ((newpath = realloc(fn, strlen(fn) + strlen(ext) + 10)) == 0) { /* out of mem */ free(fn); nomem(); return 0; } fn = strchr(newpath, '\0'); /* where the '\\' is to be */ if (fn[-1] != '\\') /* maybe 1 byte is wasted here */ *fn++ = '\\'; cnt = 0; do { /* randomize filename and probe if it can be created */ /* OK, this is not that efficient, but easy to implement right now -- 1998/10/27 ska */ sprintf(fn, "CMD%x%s", cnt, ext); if (!++cnt) /* overflow */ goto errRet; /* loop until either the open succeeded or failed with something different then "file already exists" However, this failed in Win98 DOSbox on root of CD-Rom drive: (fd = open(path, O_CREAT | O_EXCL | O_WRONLY , S_IREAD | S_IWRITE)) == -1 && errno == EACCES); Because DOS returned: EACCES Let's assume access() does not fail on directories: */ } while(dfnstat(newpath)); /* such entry already exists */ /* Make semaphore test */ fd = open(newpath, O_CREAT | O_EXCL | O_WRONLY, S_IREAD | S_IWRITE); if (fd != -1) { /* success */ close(fd); return newpath; } errRet: free(newpath); return 0; }