home *** CD-ROM | disk | FTP | other *** search
- /*
- mmv 1.0
- Copyright (c) 1989 Vladimir Lanin.
- This program may be freely used and copied on a non-commercial basis.
-
- Author may be reached at:
-
- lanin@csd2.nyu.edu
-
- Vladimir Lanin
- 330 Wadsworth Ave, Apt 6F,
- New York, NY 10040
- */
-
- /*
- Define SYSV to compile under System V.
- If your System V has a rename() call, define RENAME.
- Otherwise, mmv will only be able to rename directories (via option -r)
- when running as the super-user.
- There is no reason to set the suid bit on mmv if rename() is available.
- It is important that mmv not be run with effective uid set
- to any value other than either the real uid or the super-user.
- Even when running with effective uid set to super-user,
- mmv will only perform actions permitted to the real uid.
-
- Define MSDOS to compile under MS-D*S Turbo C 1.5.
- If you prefer mmv's output to use /'s instead of \'s under MS-D*S,
- define SLASH.
-
- When neither MSDOS nor SYSV are defined, compiles under BSD.
-
- RENAME is automatically defined under MSDOS and BSD.
-
- If you are running a (UN*X) system that provides the
- "struct dirent" readdir() directory reading standard,
- define DIRENT. Otherwise, mmv uses the BSD-like
- "struct direct" readdir().
- If your (UN*X) system has neither of these, get the "dirent"
- by Doug Gwyn, available as gwyn-dir-lib in volume 9
- of the comp.sources.unix archives.
- */
-
- static char USAGE[] =
- #ifdef MSDOS
-
- "Usage: \
- %s [-m|x%s|c|o|a|z] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
- \n\
- Use #N in the ``to'' pattern to get the string matched\n\
- by the N'th ``from'' pattern wildcard.\n";
-
- #define OTHEROPT (_osmajor < 3 ? "" : "|r")
-
- #else
-
- "Usage: \
- %s [-m|x|r|c|o|a|l%s] [-h] [-d|p] [-g|t] [-v|n] [from to]\n\
- \n\
- Use #[l|u]N in the ``to'' pattern to get the [lowercase|uppercase of the]\n\
- string matched by the N'th ``from'' pattern wildcard.\n\
- \n\
- A ``from'' pattern containing wildcards should be quoted when given\n\
- on the command line.\n";
-
- #ifdef SYSV
- #define OTHEROPT ""
- #else
- #define OTHEROPT "|s"
- #endif
-
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- #ifdef MSDOS
- /* for MS-DOS (under Turbo C 1.5)*/
-
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <dos.h>
- #include <dir.h>
- #include <io.h>
- #include <fcntl.h>
-
- #define ESC '\''
- #ifdef SLASH
- #define SLASH '\\'
- #define OTHERSLASH '/'
- #else
- #define SLASH '/'
- #define OTHERSLASH '\\'
- #endif
-
- typedef int DIRID;
- typedef int DEVID;
-
- static char TTY[] = "/dev/con";
- extern unsigned _stklen = 10000;
-
- #define RENAME
-
- #else
- /* for various flavors of UN*X */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- #include <sys/signal.h>
- #include <fcntl.h>
- extern char *getenv();
- extern long lseek();
- extern char *malloc();
-
- #ifdef DIRENT
- #include <dirent.h>
- typedef struct dirent DIRENTRY;
- #else
- #ifdef SYSV
- #include <sys/dir.h>
- /* might need to be changed to <dir.h> */
- #else
- #include <sys/dir.h>
- #endif
- typedef struct direct DIRENTRY;
- #endif
-
- #define void char /* might want to remove this line */
-
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
- #ifndef R_OK
- #define R_OK 4
- #define W_OK 2
- #define X_OK 1
- #endif
-
- #define ESC '\\'
- #define SLASH '/'
-
- typedef ino_t DIRID;
- typedef dev_t DEVID;
-
- #define MAXPATH 1024
-
- static char TTY[] = "/dev/tty";
-
- #ifdef SYSV
- /* for System V */
-
- struct utimbuf {
- time_t actime;
- time_t modtime;
- };
- #define utimes(f, t) utime((f), (t))
-
-
- #else
- /* for BSD */
-
- #define RENAME
-
- #include <sys/time.h>
-
- #endif
-
- #endif
-
-
- #define mylower(c) (isupper(c) ? (c)-'A'+'a' : (c))
- #define myupper(c) (islower(c) ? (c)-'a'+'A' : (c))
- #define STRLEN(s) (sizeof(s) - 1)
- #define mydup(s) (strcpy((char *)challoc(strlen(s) + 1, 0), (s)))
-
-
- #define DFLT 0x001
- #define NORMCOPY 0x002
- #define OVERWRITE 0x004
- #define NORMMOVE 0x008
- #define XMOVE 0x010
- #define DIRMOVE 0x020
- #define NORMAPPEND 0x040
- #define ZAPPEND 0x080
- #define HARDLINK 0x100
- #define SYMLINK 0x200
-
- #define COPY (NORMCOPY | OVERWRITE)
- #define MOVE (NORMMOVE | XMOVE | DIRMOVE)
- #define APPEND (NORMAPPEND | ZAPPEND)
- #define LINK (HARDLINK | SYMLINK)
-
- static char MOVENAME[] = "mmv";
- static char COPYNAME[] = "mcp";
- static char APPENDNAME[] = "mad";
- static char LINKNAME[] = "mln";
-
- #define ASKDEL 0
- #define ALLDEL 1
- #define NODEL 2
-
- #define ASKBAD 0
- #define SKIPBAD 1
- #define ABORTBAD 2
-
- #define STAY 0
- #define LOWER 1
- #define UPPER 2
-
- #define MAXWILD 20
- #define MAXPATLEN MAXPATH
- #define INITROOM 10
- #define CHUNKSIZE 2048
- #define BUFSIZE 4096
-
- #define FI_STTAKEN 0x01
- #define FI_LINKERR 0x02
- #define FI_INSTICKY 0x04
- #define FI_NODEL 0x08
- #define FI_KNOWWRITE 0x010
- #define FI_CANWRITE 0x20
- #define FI_ISDIR 0x40
- #define FI_ISLNK 0x80
-
- typedef struct {
- char *fi_name;
- struct rep *fi_rep;
- #ifdef MSDOS
- char fi_attrib;
- #else
- short fi_mode;
- char fi_stflags;
- #endif
- } FILEINFO;
-
- #define DI_KNOWWRITE 0x01
- #define DI_CANWRITE 0x02
- #define DI_CLEANED 0x04
-
- typedef struct {
- DEVID di_vid;
- DIRID di_did;
- unsigned di_nfils;
- FILEINFO **di_fils;
- char di_flags;
- } DIRINFO;
-
- #define H_NODIR 1
- #define H_NOREADDIR 2
-
- typedef struct {
- char *h_name;
- DIRINFO *h_di;
- char h_err;
- } HANDLE;
-
- #define R_ISX 0x01
- #define R_SKIP 0x02
- #define R_DELOK 0x04
- #define R_ISALIASED 0x08
- #define R_ISCYCLE 0x10
- #define R_ONEDIRLINK 0x20
-
- typedef struct rep {
- HANDLE *r_hfrom;
- FILEINFO *r_ffrom;
- HANDLE *r_hto;
- char *r_nto; /* non-path part of new name */
- FILEINFO *r_fdel;
- struct rep *r_first;
- struct rep *r_thendo;
- struct rep *r_next;
- char r_flags;
- } REP;
-
- typedef struct {
- REP *rd_p;
- DIRINFO *rd_dto;
- char *rd_nto;
- unsigned rd_i;
- } REPDICT;
-
- typedef struct chunk {
- struct chunk *ch_next;
- unsigned ch_len;
- } CHUNK;
-
- typedef struct {
- CHUNK *sl_first;
- char *sl_unused;
- int sl_len;
- } SLICER;
-
-
- static void init(/* */);
- static void procargs(/* int argc, char **argv,
- char **pfrompat, char **ptopat */);
- static void matchpats(/* char *cfrom, char *cto */);
- static int getpat(/* */);
- static int getword(/* char *buf */);
- static void matchpat(/* */);
- static int parsepat(/* */);
- static int dostage(/* char *lastend, char *pathend,
- char **start1, int *len1, int stage, int anylev */);
- static int trymatch(/* FILEINFO *ffrom, char *pat */);
- static int keepmatch(/* FILEINFO *ffrom, char *pathend,
- int *pk, int needslash, int dirs, int fils */);
- static int badrep(/* HANDLE *hfrom, FILEINFO *ffrom,
- HANDLE **phto, char **pnto, FILEINFO **pfdel, int *pflags */);
- static int checkto(/* HANDLE *hfrom, char *f,
- HANDLE **phto, char **pnto, FILEINFO **pfdel */);
- static char *getpath(/* char *tpath */);
- static int badname(/* char *s */);
- static FILEINFO *fsearch(/* char *s, DIRINFO *d */);
- static int ffirst(/* char *s, int n, DIRINFO *d */);
- static HANDLE *checkdir(/* char *p, char *pathend, int which */);
- static void takedir(/*
- char *p, DIRINFO *di, int sticky
- or
- struct ffblk *pff, DIRINFO *di
- */);
- static int fcmp(/* FILEINFO **pf1, FILEINFO **pf2 */);
- static HANDLE *hadd(/* char *n */);
- static int hsearch(/* char *n, int which, HANDLE **ph */);
- static DIRINFO *dadd(/* DEVID v, DIRID d */);
- static DIRINFO *dsearch(/* DEVID v, DIRID d */);
- static int match(/* char *pat, char *s, char **start1, int *len1 */);
- static void makerep(/* */);
- static void checkcollisions(/* */);
- static int rdcmp(/* REPDICT *rd1, REPDICT *rd2 */);
- static void findorder(/* */);
- static void scandeletes(/* int (*pkilldel)(REP *p) */);
- static int baddel(/* REP *p */);
- static int skipdel(/* REP *p */);
- static void nochains(/* */);
- static void printchain(/* REP *p */);
- static void goonordie(/* */);
- static void doreps(/* */);
- static long appendalias(/* REP *first, REP *p, int *pprintaliased */);
- static int movealias(/* REP *first, REP *p, int *pprintaliased */);
- static int snap(/* REP *first, REP *p */);
- static void showdone(/* REP *fin */);
- static void breakout(/* */);
- static int breakrep(/* */);
- static void breakstat(/* */);
- static void quit(/* */);
- static int copymove(/* REP *p */);
- static int copy(/* FILENFO *f, long len */);
- static int myunlink(/* char *n, FILEINFO *f */);
- static int getreply(/* char *m, int failact */);
- static void *myalloc(/* unsigned k */);
- static void *challoc(/* int k, int which */);
- static void chgive(/* void *p, unsigned k */);
- static int mygetc(/* */);
- #ifdef MSDOS
- static int leave(/* */);
- static void cleanup(/* */);
- #else
- static int getstat(/* char *full, FILEINFO *f */);
- static int dwritable(/* HANDLE *h */);
- static int fwritable(/* char *hname, FILEINFO *f */);
- static void memmove(/* void *to, void *from, int k */);
- #endif
- #ifndef RENAME
- static int rename(/* char *from, char *to */);
- #endif
-
- static int op, badstyle, delstyle, verbose, noex, matchall;
- static int patflags;
-
- static unsigned ndirs = 0, dirroom;
- static DIRINFO **dirs;
- static unsigned nhandles = 0, handleroom;
- static HANDLE **handles;
- static HANDLE badhandle = {"\200", NULL, 0};
- static HANDLE *(lasthandle[2]) = {&badhandle, &badhandle};
- static unsigned nreps = 0;
- static REP hrep, *lastrep = &hrep;
- static CHUNK *freechunks = NULL;
- static SLICER slicer[2] = {{NULL, NULL, 0}, {NULL, NULL, 0}};
-
- static int badreps = 0, paterr = 0, direrr, failed = 0, gotsig = 0, repbad;
- static FILE *outfile = stdout;
-
- static char IDF[] = "$$mmvdid.";
- static char TEMP[] = "$$mmvtmp.";
- static char TOOLONG[] = "(too long)";
- static char EMPTY[] = "(empty)";
-
- static char SLASHSTR[] = {SLASH, '\0'};
-
- static char PATLONG[] = "%.40s... : pattern too long.\n";
-
- static char from[MAXPATLEN], to[MAXPATLEN];
- static int fromlen, tolen;
- static char *(stagel[MAXWILD]), *(firstwild[MAXWILD]), *(stager[MAXWILD]);
- static int nwilds[MAXWILD];
- static int nstages;
- static char pathbuf[MAXPATH];
- static char fullrep[MAXPATH + 1];
- static char *(start[MAXWILD]);
- static int len[MAXWILD];
- static char hasdot[MAXWILD];
- static REP mistake;
- #define MISTAKE (&mistake)
-
- #ifdef MSDOS
-
- static int olddevflag, curdisk, maxdisk;
- static struct {
- char ph_banner[30];
- char ph_name[9];
- int ph_dfltop;
- int ph_safeid;
- int ph_clustoff;
- int ph_driveoff;
- int ph_drivea;
- } patch = {"mmv 1.0 patchable flags", "mmv", XMOVE, 1, 0};
-
- #define DFLTOP (patch.ph_dfltop)
- #define CLUSTNO(pff) (*(int *)(((char *)(pff)) + patch.ph_clustoff))
- #define DRIVENO(pff) (*(((char *)(pff)) + patch.ph_driveoff) - patch.ph_drivea)
-
-
- #else
-
- #define DFLTOP XMOVE
-
- static char *home;
- static int homelen;
- static int uid, euid, oldumask;
- static DIRID cwdd = -1;
- static DEVID cwdv = -1;
-
- #endif
-
-
- int main(argc, argv)
- int argc;
- char *(argv[]);
- {
- char *frompat, *topat;
-
- init();
- procargs(argc, argv, &frompat, &topat);
- matchpats(frompat, topat);
- if (!(op & APPEND))
- checkcollisions();
- findorder();
- if (op & (COPY | LINK))
- nochains();
- scandeletes(baddel);
- goonordie();
- if (!(op & APPEND) && delstyle == ASKDEL)
- scandeletes(skipdel);
- doreps();
- return(failed ? 2 : nreps == 0 && (paterr || badreps));
- }
-
-
- static void init()
- {
- #ifdef MSDOS
- curdisk = getdisk();
- maxdisk = setdisk(curdisk);
- /*
- Read device availability : undocumented internal MS-DOS function.
- If (_DX == 0) then \dev\ must precede device names.
- */
- bdos(0x37, 0, 2);
- olddevflag = _DX;
- /*
- Write device availability: undocumented internal MS-DOS function.
- Specify \dev\ must precede device names.
- */
- bdos(0x37, 0, 3);
- atexit((atexit_t)cleanup);
- ctrlbrk((int (*)())breakout);
- #else
- struct stat dstat;
-
- if ((home = getenv("HOME")) == NULL || strcmp(home, SLASHSTR) == 0)
- home = "";
- if (!stat(".", &dstat)) {
- cwdd = dstat.st_ino;
- cwdv = dstat.st_dev;
- }
- oldumask = umask(0);
- euid = geteuid();
- uid = getuid();
- signal(SIGINT, breakout);
- #endif
-
- dirroom = handleroom = INITROOM;
- dirs = (DIRINFO **)myalloc(dirroom * sizeof(DIRINFO *));
- handles = (HANDLE **)myalloc(handleroom * sizeof(HANDLE *));
- ndirs = nhandles = 0;
- }
-
-
- static void procargs(argc, argv, pfrompat, ptopat)
- int argc;
- char **argv;
- char **pfrompat, **ptopat;
- {
- char *p, c;
- char *cmdname = argv[0];
-
- #ifdef MSDOS
- #define CMDNAME (patch.ph_name)
- #else
- #define CMDNAME cmdname
- #endif
-
- op = DFLT;
- verbose = noex = matchall = 0;
- delstyle = ASKDEL;
- badstyle = ASKBAD;
- for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++)
- for (p = *argv + 1; *p != '\0'; p++) {
- c = mylower(*p);
- if (c == 'v' && !noex)
- verbose = 1;
- else if (c == 'n' && !verbose)
- noex = 1;
- else if (c == 'h')
- matchall = 1;
- else if (c == 'd' && delstyle == ASKDEL)
- delstyle = ALLDEL;
- else if (c == 'p' && delstyle == ASKDEL)
- delstyle = NODEL;
- else if (c == 'g' && badstyle == ASKBAD)
- badstyle = SKIPBAD;
- else if (c == 't' && badstyle == ASKBAD)
- badstyle = ABORTBAD;
- else if (c == 'm' && op == DFLT)
- op = NORMMOVE;
- else if (c == 'x' && op == DFLT)
- op = XMOVE;
- else if (c == 'r' && op == DFLT)
- op = DIRMOVE;
- else if (c == 'c' && op == DFLT)
- op = NORMCOPY;
- else if (c == 'o' && op == DFLT)
- op = OVERWRITE;
- else if (c == 'a' && op == DFLT)
- op = NORMAPPEND;
- #ifdef MSDOS
- else if (c == 'z' && op == DFLT)
- op = ZAPPEND;
- #else
- else if (c == 'l' && op == DFLT)
- op = HARDLINK;
- #ifndef SYSV
- else if (c == 's' && op == DFLT)
- op = SYMLINK;
- #endif
- #endif
- else {
- fprintf(stderr, USAGE, CMDNAME, OTHEROPT);
- exit(1);
- }
- }
-
- if (op == DFLT)
- if (strcmp(cmdname, MOVENAME) == 0)
- op = XMOVE;
- else if (strcmp(cmdname, COPYNAME) == 0)
- op = NORMCOPY;
- else if (strcmp(cmdname, APPENDNAME) == 0)
- op = NORMAPPEND;
- else if (strcmp(cmdname, LINKNAME) == 0)
- op = HARDLINK;
- else
- op = DFLTOP;
- if (
- op & DIRMOVE &&
- #ifdef MSDOS
- _osmajor < 3
- #else
- #ifndef RENAME
- euid != 0
- #else
- 0
- #endif
- #endif
- ) {
- fprintf(stderr,
- "Unable to do directory renames. Option -r refused.\n");
- quit();
- }
-
- #ifndef MSDOS
- if (euid != uid && !(op & DIRMOVE)) {
- setuid(uid);
- setgid(getgid());
- }
- #endif
-
- if (badstyle != ASKBAD && delstyle == ASKDEL)
- delstyle = NODEL;
-
- if (argc == 0)
- *pfrompat = NULL;
- else if (argc == 2) {
- *pfrompat = *(argv++);
- *ptopat = *(argv++);
- }
- else {
- fprintf(stderr, USAGE, CMDNAME, OTHEROPT);
- exit(1);
- }
- }
-
-
- static void matchpats(cfrom, cto)
- char *cfrom, *cto;
- {
- if (cfrom == NULL)
- while (getpat())
- matchpat();
- else if ((fromlen = strlen(cfrom)) >= MAXPATLEN) {
- printf(PATLONG, cfrom);
- paterr = 1;
- }
- else if ((tolen = strlen(cto)) >= MAXPATLEN) {
- printf(PATLONG, cto);
- paterr = 1;
- }
- else {
- strcpy(from, cfrom);
- strcpy(to, cto);
- matchpat();
- }
- }
-
-
- static int getpat()
- {
- int c, gotit = 0;
- char extra[MAXPATLEN];
-
- patflags = 0;
- do {
- if ((fromlen = getword(from)) == 0 || fromlen == -1)
- goto nextline;
-
- do {
- if ((tolen = getword(to)) == 0) {
- printf("%s -> ? : missing replacement pattern.\n", from);
- goto nextline;
- }
- if (tolen == -1)
- goto nextline;
- } while (
- tolen == 2 &&
- (to[0] == '-' || to[0] == '=') &&
- (to[1] == '>' || to[1] == '^')
- );
- if (getword(extra) == 0)
- gotit = 1;
- else if (strcmp(extra, "(*)") == 0) {
- patflags |= R_DELOK;
- gotit = (getword(extra) == 0);
- }
-
- nextline:
- while ((c = mygetc()) != '\n' && c != EOF)
- ;
- if (c == EOF)
- return(0);
- } while (!gotit);
-
- return(1);
- }
-
-
- static int getword(buf)
- char *buf;
- {
- int c, prevc, n;
- char *p;
-
- p = buf;
- prevc = ' ';
- n = 0;
- while ((c = mygetc()) != EOF && (prevc == ESC || !isspace(c))) {
- if (n == -1)
- continue;
- if (n == MAXPATLEN - 1) {
- *p = '\0';
- printf(PATLONG, buf);
- n = -1;
- }
- *(p++) = c;
- n++;
- prevc = c;
- }
- *p = '\0';
- while (c != EOF && isspace(c) && c != '\n')
- c = mygetc();
- if (c != EOF)
- ungetc(c, stdin);
- return(n);
- }
-
-
- static void matchpat()
- {
- if (parsepat())
- paterr = 1;
- else if (dostage(from, pathbuf, start, len, 0, 0)) {
- printf("%s -> %s : no match.\n", from, to);
- paterr = 1;
- }
- }
-
-
- static int parsepat()
- {
- char *p, *lastname, c;
- int totwilds, instage, x, havedot;
- static char TRAILESC[] = "%s -> %s : trailing %c is superfluous.\n";
-
- lastname = from;
- #ifdef MSDOS
- havedot = 0;
- if (from[0] != '\0' && from[1] == ':')
- lastname += 2;
- #else
- if (from[0] == '~' && from[1] == SLASH) {
- if ((homelen = strlen(home)) + fromlen > MAXPATLEN) {
- printf(PATLONG, from);
- return(-1);
- }
- memmove(from + homelen, from + 1, fromlen);
- memmove(from, home, homelen);
- lastname += homelen + 1;
- }
- #endif
- totwilds = nstages = instage = 0;
- for (p = lastname; (c = *p) != '\0'; p++)
- switch (c) {
- #ifdef MSDOS
- case '.':
- havedot = 1;
- break;
- case OTHERSLASH:
- *p = SLASH;
- #endif
- case SLASH:
- #ifdef MSDOS
- if (!havedot && lastname != p) {
- if (fromlen++ == MAXPATLEN) {
- printf(PATLONG, from);
- return(-1);
- }
- memmove(p + 1, p, strlen(p) + 1);
- *(p++) = '.';
- }
- else
- havedot = 0;
- #endif
- lastname = p + 1;
- if (instage) {
- if (firstwild[nstages] == NULL)
- firstwild[nstages] = p;
- stager[nstages++] = p;
- instage = 0;
- }
- break;
- case ';':
- if (lastname != p) {
- printf("%s -> %s : badly placed ;.\n", from, to);
- return(-1);
- }
- case '!':
- case '*':
- case '?':
- case '[':
- #ifdef MSDOS
- if ((hasdot[totwilds] = (c == '!')) != 0)
- havedot = 1;
- #endif
- if (totwilds++ == MAXWILD) {
- printf("%s -> %s : too many wildcards.\n", from, to);
- return(-1);
- }
- if (instage) {
- nwilds[nstages]++;
- if (firstwild[nstages] == NULL)
- firstwild[nstages] = p;
- }
- else {
- stagel[nstages] = lastname;
- firstwild[nstages] = (c == ';' ? NULL : p);
- nwilds[nstages] = 1;
- instage = 1;
- }
- if (c != '[')
- break;
- while ((c = *(++p)) != ']') {
- switch (c) {
- case '\0':
- printf("%s -> %s : missing ].\n", from, to);
- return(-1);
- #ifdef MSDOS
- case '.':
- case ':':
- case OTHERSLASH:
- #endif
- case SLASH:
- printf("%s -> %s : '%c' can not be part of [].\n",
- from, to, c);
- return(-1);
- case ESC:
- if ((c = *(++p)) == '\0') {
- printf(TRAILESC, from, to, ESC);
- return(-1);
- }
- #ifdef MSDOS
- default:
- if (isupper(c))
- *p = c + ('a' - 'A');
- #endif
- }
- }
- break;
- case ESC:
- if ((c = *(++p)) == '\0') {
- printf(TRAILESC, from, to, ESC);
- return(-1);
- }
- #ifdef MSDOS
- default:
- if (isupper(c))
- *p = c + ('a' - 'A');
- #endif
- }
-
- #ifdef MSDOS
- if (!havedot && lastname != p) {
- if (fromlen++ == MAXPATLEN) {
- printf(PATLONG, from);
- return(-1);
- }
- strcpy(p++, ".");
- }
- #endif
-
- if (instage) {
- if (firstwild[nstages] == NULL)
- firstwild[nstages] = p;
- stager[nstages++] = p;
- }
- else {
- stagel[nstages] = lastname;
- nwilds[nstages] = 0;
- firstwild[nstages] = p;
- stager[nstages++] = p;
- }
-
- lastname = to;
- #ifdef MSDOS
- havedot = 0;
- if (to[0] != '\0' && to[1] == ':')
- lastname += 2;
- #else
- if (to[0] == '~' && to[1] == SLASH) {
- if ((homelen = strlen(home)) + tolen > MAXPATLEN) {
- printf(PATLONG, to);
- return(-1);
- }
- memmove(to + homelen, to + 1, tolen);
- memmove(to, home, homelen);
- lastname += homelen + 1;
- }
- #endif
-
- for (p = lastname; (c = *p) != '\0'; p++)
- switch (c) {
- #ifdef MSDOS
- case '.':
- havedot = 1;
- break;
- case OTHERSLASH:
- *p = SLASH;
- #endif
- case SLASH:
- if (op & DIRMOVE) {
- printf("%s -> %s : no path allowed in target under -r.\n",
- from, to);
- return(-1);
- }
- #ifdef MSDOS
- if (!havedot && lastname != p) {
- if (tolen++ == MAXPATLEN) {
- printf(PATLONG, to);
- return(-1);
- }
- memmove(p + 1, p, strlen(p) + 1);
- *(p++) = '.';
- }
- else
- havedot = 0;
- #endif
- lastname = p + 1;
- break;
- case '#':
- c = *(++p);
- if (c == 'l' || c == 'u') {
- #ifdef MSDOS
- strcpy(p, p + 1);
- c = *p;
- #else
- c = *(++p);
- #endif
- }
- if (!isdigit(c)) {
- printf("%s -> %s : expected digit (not '%c') after #.\n",
- from, to, c);
- return(-1);
- }
- for(x = 0; ;x *= 10) {
- x += c - '0';
- c = *(p+1);
- if (!isdigit(c))
- break;
- p++;
- }
- if (x < 1 || x > totwilds) {
- printf("%s -> %s : wildcard #%d does not exist.\n",
- from, to, x);
- return(-1);
- }
- #ifdef MSDOS
- if (hasdot[x - 1])
- havedot = 1;
- #endif
- break;
- case ESC:
- if ((c = *(++p)) == '\0') {
- printf(TRAILESC, from, to, ESC);
- return(-1);
- }
- default:
- if (
- #ifdef MSDOS
- c <= ' ' || c >= 127 ||
- strchr(":/\\*?[]=+;,\"|<>", c) != NULL
- #else
- c & 0x80
- #endif
- ) {
- printf("%s -> %s : illegal character '%c' (0x%02X).\n",
- from, to, c, c);
- return(-1);
- }
- #ifdef MSDOS
- if (isupper(c))
- *p = c + ('a' - 'A');
- #endif
- }
-
- #ifdef MSDOS
- if (!havedot && lastname != p) {
- if (tolen++ == MAXPATLEN) {
- printf(PATLONG, to);
- return(-1);
- }
- strcpy(p++, ".");
- }
- #endif
-
- return(0);
- }
-
-
- static int dostage(lastend, pathend, start1, len1, stage, anylev)
- char *lastend, *pathend;
- char **start1;
- int *len1;
- int stage;
- int anylev;
- {
- DIRINFO *di;
- HANDLE *h, *hto;
- int prelen, litlen, nfils, i, k, flags, try;
- FILEINFO **pf, *fdel;
- char *nto, *firstesc;
- REP *p;
- int wantdirs, ret = 1, laststage = (stage + 1 == nstages);
-
- wantdirs = !laststage ||
- (op & (DIRMOVE | SYMLINK)) ||
- (nwilds[nstages - 1] == 0);
-
- if (!anylev) {
- prelen = stagel[stage] - lastend;
- if (pathend - pathbuf + prelen >= MAXPATH) {
- printf("%s -> %s : search path after %s too long.\n",
- from, to, pathbuf);
- paterr = 1;
- return(1);
- }
- memmove(pathend, lastend, prelen);
- pathend += prelen;
- *pathend = '\0';
- lastend = stagel[stage];
- }
-
- if ((h = checkdir(pathbuf, pathend, 0)) == NULL) {
- if (stage == 0 || direrr == H_NOREADDIR) {
- printf("%s -> %s : directory %s does not %s.\n",
- from, to, pathbuf, direrr == H_NOREADDIR ?
- "allow reads/searches" : "exist");
- paterr = 1;
- }
- return(stage);
- }
- di = h->h_di;
-
- if (*lastend == ';') {
- anylev = 1;
- *start1 = pathend;
- *len1 = 0;
- lastend++;
- }
-
- nfils = di->di_nfils;
-
- #ifndef MSDOS
- if ((op & MOVE) && !dwritable(h)) {
- printf("%s -> %s : directory %s does not allow writes.\n",
- from, to, pathbuf);
- paterr = 1;
- goto skiplev;
- }
- #endif
-
- firstesc = strchr(lastend, ESC);
- if (firstesc == NULL || firstesc > firstwild[stage])
- firstesc = firstwild[stage];
- litlen = firstesc - lastend;
- pf = di->di_fils + (i = ffirst(lastend, litlen, di));
- if (i < nfils)
- do {
- if (
- (try = trymatch(*pf, lastend)) != 0 &&
- (
- try == 1 ||
- match(lastend + litlen, (*pf)->fi_name + litlen,
- start1 + anylev, len1 + anylev)
- ) &&
- keepmatch(*pf, pathend, &k, 0, wantdirs, laststage)
- ) {
- if (!laststage)
- ret &= dostage(stager[stage], pathend + k,
- start1 + nwilds[stage], len1 + nwilds[stage],
- stage + 1, 0);
- else {
- ret = 0;
- makerep();
- if (badrep(h, *pf, &hto, &nto, &fdel, &flags))
- (*pf)->fi_rep = MISTAKE;
- else {
- (*pf)->fi_rep = p = (REP *)challoc(sizeof(REP), 1);
- p->r_flags = flags | patflags;
- p->r_hfrom = h;
- p->r_ffrom = *pf;
- p->r_hto = hto;
- p->r_nto = nto;
- p->r_fdel = fdel;
- p->r_first = p;
- p->r_thendo = NULL;
- p->r_next = NULL;
- lastrep->r_next = p;
- lastrep = p;
- nreps++;
- }
- }
- }
- i++, pf++;
- } while (i < nfils && strncmp(lastend, (*pf)->fi_name, litlen) == 0);
-
- skiplev:
- if (anylev)
- for (pf = di->di_fils, i = 0; i < nfils; i++, pf++)
- if (
- *((*pf)->fi_name) != '.' &&
- #ifdef MSDOS
- ((*pf)->fi_attrib & FA_DIREC) &&
- #endif
- keepmatch(*pf, pathend, &k, 1, 1, 0)
- ) {
- *len1 = pathend - *start1 + k;
- ret &= dostage(lastend, pathend + k, start1, len1, stage, 1);
- }
-
- return(ret);
- }
-
-
- static int trymatch(ffrom, pat)
- FILEINFO *ffrom;
- char *pat;
- {
- char *p;
-
- if (ffrom->fi_rep != NULL)
- return(0);
-
- p = ffrom->fi_name;
-
- #ifdef MSDOS
- if (*p == '.' || (!matchall && ffrom->fi_attrib & (FA_HIDDEN | FA_SYSTEM)))
- return(strcmp(pat, p) == 0);
- #else
- if (*p == '.')
- if (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))
- return(strcmp(pat, p) == 0);
- else if (!matchall && *pat != '.')
- return(0);
- #endif
- return(-1);
- }
-
-
- static int keepmatch(ffrom, pathend, pk, needslash, dirs, fils)
- FILEINFO *ffrom;
- char *pathend;
- int *pk;
- int needslash;
- int dirs, fils;
- {
- *pk = strlen(ffrom->fi_name);
- if (pathend - pathbuf + *pk + needslash >= MAXPATH) {
- *pathend = '\0';
- printf("%s -> %s : search path %s%s too long.\n",
- from, to, pathbuf, ffrom->fi_name);
- paterr = 1;
- return(0);
- }
- strcpy(pathend, ffrom->fi_name);
- #ifdef MSDOS
- if ((ffrom->fi_attrib & FA_DIREC) ? !dirs : !fils)
- #else
- getstat(pathbuf, ffrom);
- if ((ffrom->fi_stflags & FI_ISDIR) ? !dirs : !fils)
- #endif
- return(0);
-
- if (needslash) {
- strcpy(pathend + *pk, SLASHSTR);
- (*pk)++;
- }
- return(1);
- }
-
-
- static int badrep(hfrom, ffrom, phto, pnto, pfdel, pflags)
- HANDLE *hfrom;
- FILEINFO *ffrom;
- HANDLE **phto;
- char **pnto;
- FILEINFO **pfdel;
- int *pflags;
- {
- char *f = ffrom->fi_name;
-
- *pflags = 0;
- if (
- #ifdef MSDOS
- (ffrom->fi_attrib & FA_DIREC) &&
- #else
- (ffrom->fi_stflags & FI_ISDIR) &&
- #endif
- !(op & (DIRMOVE | SYMLINK))
- )
- printf("%s -> %s : source file is a directory.\n", pathbuf, fullrep);
- #ifndef MSDOS
- #ifndef SYSV
- else if ((ffrom->fi_stflags & FI_LINKERR) && !(op & (MOVE | SYMLINK)))
- printf("%s -> %s : source file is a badly aimed symbolic link.\n",
- pathbuf, fullrep);
- else if ((ffrom->fi_stflags & FI_NODEL) && (op & MOVE))
- printf("%s -> %s : no delete permission for source file.\n",
- pathbuf, fullrep);
- #endif
- else if ((op & (COPY | APPEND)) && access(pathbuf, R_OK))
- printf("%s -> %s : no read permission for source file.\n",
- pathbuf, fullrep);
- #endif
- else if (
- *f == '.' &&
- (f[1] == '\0' || strcmp(f, "..") == 0) &&
- !(op & SYMLINK)
- )
- printf("%s -> %s : . and .. can't be renamed.\n", pathbuf, fullrep);
- else if (repbad || checkto(hfrom, f, phto, pnto, pfdel) || badname(*pnto))
- printf("%s -> %s : bad new name.\n", pathbuf, fullrep);
- else if (*phto == NULL)
- printf("%s -> %s : %s.\n", pathbuf, fullrep,
- #ifndef MSDOS
- direrr == H_NOREADDIR ?
- "no read or search permission for target directory" :
- #endif
- "target directory does not exist");
- #ifndef MSDOS
- else if (!dwritable(*phto))
- printf("%s -> %s : no write permission for target directory.\n",
- pathbuf, fullrep);
- #endif
- else if (
- (*phto)->h_di->di_vid != hfrom->h_di->di_vid &&
- (*pflags = R_ISX, (op & (NORMMOVE | HARDLINK)))
- )
- printf("%s -> %s : cross-device move.\n",
- pathbuf, fullrep);
- #ifndef MSDOS
- else if (
- *pflags && (op & MOVE) &&
- !(ffrom->fi_stflags & FI_ISLNK) &&
- access(pathbuf, R_OK)
- )
- printf("%s -> %s : no read permission for source file.\n",
- pathbuf, fullrep);
- #ifndef SYSV
- else if (
- (op & SYMLINK) &&
- !(
- ((*phto)->h_di->di_vid == cwdv && (*phto)->h_di->di_did == cwdd) ||
- *(hfrom->h_name) == SLASH ||
- (*pflags |= R_ONEDIRLINK, hfrom->h_di == (*phto)->h_di)
- )
- )
- printf("%s -> %s : symbolic link would be badly aimed.\n",
- pathbuf, fullrep);
- #endif
- #endif
- else
- return(0);
- badreps++;
- return(-1);
- }
-
-
- static int checkto(hfrom, f, phto, pnto, pfdel)
- HANDLE *hfrom;
- char *f;
- HANDLE **phto;
- char **pnto;
- FILEINFO **pfdel;
- {
- char tpath[MAXPATH + 1];
- char *pathend;
- FILEINFO *fdel;
- int hlen, tlen;
-
- if (op & DIRMOVE) {
- *phto = hfrom;
- hlen = strlen(hfrom->h_name);
- pathend = fullrep + hlen;
- memmove(pathend, fullrep, strlen(fullrep) + 1);
- memmove(fullrep, hfrom->h_name, hlen);
- if ((fdel = *pfdel = fsearch(pathend, hfrom->h_di)) != NULL) {
- *pnto = fdel->fi_name;
- #ifndef MSDOS
- getstat(fullrep, fdel);
- #endif
- }
- else
- *pnto = mydup(pathend);
- }
- else {
- pathend = getpath(tpath);
- hlen = pathend - fullrep;
- *phto = checkdir(tpath, tpath + hlen, 1);
- if (
- *phto != NULL &&
- *pathend != '\0' &&
- (fdel = *pfdel = fsearch(pathend, (*phto)->h_di)) != NULL &&
- #ifdef MSDOS
- (fdel->fi_attrib & FA_DIREC)
- #else
- (getstat(fullrep, fdel), fdel->fi_stflags & FI_ISDIR)
- #endif
- ) {
- tlen = strlen(pathend);
- strcpy(pathend + tlen, SLASHSTR);
- tlen++;
- strcpy(tpath + hlen, pathend);
- pathend += tlen;
- hlen += tlen;
- *phto = checkdir(tpath, tpath + hlen, 1);
- }
-
- if (*pathend == '\0') {
- *pnto = f;
- if (pathend - fullrep + strlen(f) >= MAXPATH) {
- strcpy(fullrep, TOOLONG);
- return(-1);
- }
- strcat(pathend, f);
- if (*phto != NULL) {
- fdel = *pfdel = fsearch(f, (*phto)->h_di);
- #ifndef MSDOS
- if (fdel != NULL)
- getstat(fullrep, fdel);
- #endif
- }
- }
- else if (fdel != NULL)
- *pnto = fdel->fi_name;
- else
- *pnto = mydup(pathend);
- }
- return(0);
- }
-
-
- static char *getpath(tpath)
- char *tpath;
- {
- char *pathstart, *pathend, c;
-
- #ifdef MSDOS
- if (*fullrep != '\0' && fullrep[1] == ':')
- pathstart = fullrep + 2;
- else
- #endif
- pathstart = fullrep;
-
- pathend = pathstart + strlen(pathstart) - 1;
- while (pathend >= pathstart && *pathend != SLASH)
- --pathend;
- pathend++;
-
- c = *pathend;
- *pathend = '\0';
- strcpy(tpath, fullrep);
- *pathend = c;
- return(pathend);
- }
-
-
- static int badname(s)
- char *s;
- {
- char *ext;
-
- return (
- #ifdef MSDOS
- *s == ' ' ||
- *s == '.' ||
- (ext = strchr(s, '.')) - s >= MAXFILE ||
- (*ext == '.' && strchr(ext + 1, '.') != NULL) ||
- strlen(ext) >= MAXEXT ||
- strncmp(s, IDF, STRLEN(IDF)) == 0
- #else
- (*s == '.' && (s[1] == '\0' || strcmp(s, "..") == 0)) ||
- strlen(s) > MAXNAMLEN
- #endif
- );
- }
-
-
- #ifndef MSDOS
- static int getstat(ffull, f)
- char *ffull;
- FILEINFO *f;
- {
- struct stat fstat;
- int flags;
-
- if ((flags = f->fi_stflags) & FI_STTAKEN)
- return(flags & FI_LINKERR);
- flags |= FI_STTAKEN;
- #ifdef SYSV
- if (stat(ffull, &fstat)) {
- fprintf("Strange, couldn't stat %s.\n", ffull);
- quit();
- }
- #else
- if (lstat(ffull, &fstat)) {
- fprintf("Strange, couldn't lstat %s.\n", ffull);
- quit();
- }
- if ((flags & FI_INSTICKY) && fstat.st_uid != uid && uid != 0)
- flags |= FI_NODEL;
- if ((fstat.st_mode & S_IFMT) == S_IFLNK) {
- flags |= FI_ISLNK;
- if (stat(ffull, &fstat)) {
- f->fi_stflags = flags | FI_LINKERR;
- return(1);
- }
- }
- #endif
- if ((fstat.st_mode & S_IFMT) == S_IFDIR)
- flags |= FI_ISDIR;
- f->fi_stflags = flags;
- f->fi_mode = fstat.st_mode;
- return(0);
- }
-
-
- static int dwritable(h)
- HANDLE *h;
- {
- char *p = h->h_name, *myp, *lastslash = NULL, *pathend;
- char *pw = &(h->h_di->di_flags), r;
-
- if (uid == 0)
- return(1);
-
- if (*pw & DI_KNOWWRITE)
- return(*pw & DI_CANWRITE);
-
- pathend = p + strlen(p);
- if (*p == '\0')
- myp = ".";
- else if (pathend == p + 1)
- myp = SLASHSTR;
- else {
- lastslash = pathend - 1;
- *lastslash = '\0';
- myp = p;
- }
- r = !access(myp, W_OK) ? DI_CANWRITE : 0;
- *pw |= DI_KNOWWRITE | r;
-
- if (lastslash != NULL)
- *lastslash = SLASH;
- return(r);
- }
-
-
- static int fwritable(hname, f)
- char *hname;
- FILEINFO *f;
- {
- int r;
-
- if (f->fi_stflags & FI_KNOWWRITE)
- return(f->fi_stflags & FI_CANWRITE);
-
- strcpy(fullrep, hname);
- strcat(fullrep, f->fi_name);
- r = !access(fullrep, W_OK) ? FI_CANWRITE : 0;
- f->fi_stflags |= FI_KNOWWRITE | r;
- return(r);
- }
- #endif
-
-
- static FILEINFO *fsearch(s, d)
- char *s;
- DIRINFO *d;
- {
- FILEINFO **fils = d->di_fils;
- int nfils = d->di_nfils;
- int first, k, last, res;
-
- for(first = 0, last = nfils - 1;;) {
- if (last < first)
- return(NULL);
- k = (first + last) >> 1;
- if ((res = strcmp(s, fils[k]->fi_name)) == 0)
- return(fils[k]);
- if (res < 0)
- last = k - 1;
- else
- first = k + 1;
- }
- }
-
-
- static int ffirst(s, n, d)
- char *s;
- int n;
- DIRINFO *d;
- {
- int first, k, last, res;
- FILEINFO **fils = d->di_fils;
- int nfils = d->di_nfils;
-
- if (nfils == 0 || n == 0)
- return(0);
- first = 0;
- last = nfils - 1;
- for(;;) {
- k = (first + last) >> 1;
- res = strncmp(s, fils[k]->fi_name, n);
- if (first == last)
- return(res == 0 ? k : nfils);
- else if (res > 0)
- first = k + 1;
- else
- last = k;
- }
- }
-
-
- #ifdef MSDOS
- /* checkdir and takedir for MS-D*S */
-
- static HANDLE *checkdir(p, pathend, which)
- char *p, *pathend;
- int which;
- {
- struct ffblk de;
- DIRID d;
- DEVID v;
- HANDLE *h;
- char *dirstart = p;
- int fd;
- int firstfound;
- DIRINFO *di;
-
- if (hsearch(p, which, &h))
- if (h->h_di == NULL) {
- direrr = h->h_err;
- return(NULL);
- }
- else
- return(h);
-
- if (*p == '\0' || p[1] != ':')
- v = curdisk;
- else {
- dirstart += 2;
- v = mylower(p[0]) - 'a';
- if (v < 0 || v >= maxdisk)
- return(NULL);
- }
-
- if (patch.ph_safeid) {
- strcpy(pathend, IDF);
- strcpy(pathend + STRLEN(IDF), "*");
- if (findfirst(p, &de, 0)) {
- if ((d = ndirs) == 1000) {
- fprintf(stderr, "Too many different directories.\n");
- quit();
- }
- sprintf(pathend + STRLEN(IDF), "%03d", d);
- if ((fd = _creat(p, 0)) < 0) {
- direrr = h->h_err = H_NODIR;
- return(NULL);
- }
- _close(fd);
- strcpy(pathend, "*.*");
- if (findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN))
- h->h_di = dadd(v, d);
- else
- takedir(&de, h->h_di = dadd(v, d));
- }
- else if ((d = atoi(de.ff_name + STRLEN(IDF))) < ndirs)
- h->h_di = dirs[d];
- else {
- strcpy(pathend, de.ff_name);
- fprintf(stderr, "Strange dir-id file encountered: %s.\n", p);
- quit();
- }
- *pathend = '\0';
- }
- else {
- strcpy(pathend, "*.*");
- firstfound = !findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN);
- *pathend = '\0';
- if (firstfound) {
- v = DRIVENO(&de);
- d = CLUSTNO(&de);
- }
- else {
- strcpy(pathend, "T.D");
- if (mkdir(p)) {
- *pathend = '\0';
- direrr = h->h_err = H_NODIR;
- return(NULL);
- }
- strcpy(pathend, "*.*");
- firstfound = !findfirst(p, &de, FA_DIREC | FA_SYSTEM | FA_HIDDEN);
- *pathend = '\0';
- v = DRIVENO(&de);
- d = CLUSTNO(&de);
- rmdir(p);
- if (!firstfound || d != 0) {
- fprintf(stderr,
- "Strange, %s does not seem to be a root dir.\n",
- p);
- quit();
- }
- }
-
- if ((di = dsearch(v, d)) == NULL)
- if (firstfound)
- takedir(&de, h->h_di = dadd(v, d));
- else
- h->h_di = dadd(v, d);
- else
- h->h_di = di;
- }
-
- return(h);
- }
-
-
- static void takedir(pff, di)
- struct ffblk *pff;
- DIRINFO *di;
- {
- int cnt, room, namlen, needdot;
- FILEINFO **fils, *f;
- char c, *p, *p1;
-
- room = INITROOM;
- di->di_fils = fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- cnt = 0;
- do {
- if (strnicmp(pff->ff_name, IDF, STRLEN(IDF)) == 0)
- continue;
- if (cnt == room) {
- room *= 2;
- fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- memcpy(fils, di->di_fils, cnt * sizeof(FILEINFO *));
- chgive(di->di_fils, cnt * sizeof(FILEINFO *));
- di->di_fils = fils;
- fils = di->di_fils + cnt;
- }
- needdot = 1;
- for (p = pff->ff_name, namlen = 0; (c = *p) != '\0'; p++, namlen++)
- if (c == '.')
- needdot = 0;
- *fils = f = (FILEINFO *)challoc(sizeof(FILEINFO), 1);
- f->fi_name = p = (char *)challoc(namlen + needdot + 1, 0);
- for (p1 = pff->ff_name; (c = *p1) != '\0'; p1++)
- *(p++) = mylower(c);
- if (needdot)
- *(p++) = '.';
- *p = '\0';
- f->fi_attrib = pff->ff_attrib;
- f->fi_rep = NULL;
- cnt++;
- fils++;
- } while (findnext(pff) == 0);
- qsort(di->di_fils, cnt, sizeof(FILEINFO *), fcmp);
- di->di_nfils = cnt;
- }
-
- #else
- /* checkdir, takedir for Un*x */
-
- static HANDLE *checkdir(p, pathend, which)
- char *p, *pathend;
- int which;
- {
- struct stat dstat;
- DIRID d;
- DEVID v;
- DIRINFO **newdirs, *di;
- int nfils;
- FILEINFO **fils;
- char *myp, *lastslash = NULL;
- int sticky;
- HANDLE *h;
-
- if (hsearch(p, which, &h))
- if (h->h_di == NULL) {
- direrr = h->h_err;
- return(NULL);
- }
- else
- return(h);
-
- if (*p == '\0')
- myp = ".";
- else if (pathend == p + 1)
- myp = SLASHSTR;
- else {
- lastslash = pathend - 1;
- *lastslash = '\0';
- myp = p;
- }
-
- if (stat(myp, &dstat) || (dstat.st_mode & S_IFMT) != S_IFDIR)
- direrr = h->h_err = H_NODIR;
- else if (access(myp, R_OK | X_OK))
- direrr = h->h_err = H_NOREADDIR;
- else {
- direrr = 0;
- sticky = (dstat.st_mode & S_ISVTX) && uid != 0 && uid != dstat.st_uid ?
- FI_INSTICKY : 0;
- v = dstat.st_dev;
- d = dstat.st_ino;
-
- if ((di = dsearch(v, d)) == NULL)
- takedir(myp, di = dadd(v, d), sticky);
- }
-
- if (lastslash != NULL)
- *lastslash = SLASH;
- if (direrr != 0)
- return(NULL);
- h->h_di = di;
- return(h);
- }
-
-
- static void takedir(p, di, sticky)
- char *p;
- DIRINFO *di;
- int sticky;
- {
- int cnt, room;
- DIRENTRY *dp;
- FILEINFO *f, **fils;
- DIR *dirp;
-
- if ((dirp = opendir(p)) == NULL) {
- fprintf(stderr, "Strange, can't scan %s.\n", p);
- quit();
- }
- room = INITROOM;
- di->di_fils = fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- cnt = 0;
- while ((dp = readdir(dirp)) != NULL) {
- if (cnt == room) {
- room *= 2;
- fils = (FILEINFO **)myalloc(room * sizeof(FILEINFO *));
- memcpy(fils, di->di_fils, cnt * sizeof(FILEINFO *));
- chgive(di->di_fils, cnt * sizeof(FILEINFO *));
- di->di_fils = fils;
- fils = di->di_fils + cnt;
- }
- *fils = f = (FILEINFO *)challoc(sizeof(FILEINFO), 1);
- f->fi_name = mydup(dp->d_name);
- f->fi_stflags = sticky;
- f->fi_rep = NULL;
- cnt++;
- fils++;
- }
- closedir(dirp);
- qsort(di->di_fils, cnt, sizeof(FILEINFO *), fcmp);
- di->di_nfils = cnt;
- }
-
- /* end of Un*x checkdir, takedir; back to general program */
- #endif
-
-
- static int fcmp(pf1, pf2)
- FILEINFO **pf1, **pf2;
- {
- return(strcmp((*pf1)->fi_name, (*pf2)->fi_name));
- }
-
-
- static HANDLE *hadd(n)
- char *n;
- {
- HANDLE **newhandles, *h;
-
- if (nhandles == handleroom) {
- handleroom *= 2;
- newhandles = (HANDLE **)myalloc(handleroom * sizeof(HANDLE *));
- memcpy(newhandles, handles, nhandles * sizeof(HANDLE *));
- chgive(handles, nhandles * sizeof(HANDLE *));
- handles = newhandles;
- }
- handles[nhandles++] = h = (HANDLE *)challoc(sizeof(HANDLE), 1);
- h->h_name = (char *)challoc(strlen(n) + 1, 0);
- strcpy(h->h_name, n);
- h->h_di = NULL;
- return(h);
- }
-
-
- static int hsearch(n, which, pret)
- char *n;
- int which;
- HANDLE **pret;
- {
- int i;
- HANDLE **ph;
-
- if (strcmp(n, lasthandle[which]->h_name) == 0) {
- *pret = lasthandle[which];
- return(1);
- }
-
- for(i = 0, ph = handles; i < nhandles; i++, ph++)
- if (strcmp(n, (*ph)->h_name) == 0) {
- lasthandle[which] = *pret = *ph;
- return(1);
- }
-
- lasthandle[which] = *pret = hadd(n);
- return(0);
- }
-
-
- static DIRINFO *dadd(v, d)
- DEVID v;
- DIRID d;
- {
- DIRINFO *di;
- DIRINFO **newdirs;
-
- if (ndirs == dirroom) {
- dirroom *= 2;
- newdirs = (DIRINFO **)myalloc(dirroom * sizeof(DIRINFO *));
- memcpy(newdirs, dirs, ndirs * sizeof(DIRINFO *));
- chgive(dirs, ndirs * sizeof(DIRINFO *));
- dirs = newdirs;
- }
- dirs[ndirs++] = di = (DIRINFO *)challoc(sizeof(DIRINFO), 1);
- di->di_vid = v;
- di->di_did = d;
- di->di_nfils = 0;
- di->di_fils = NULL;
- di->di_flags = 0;
- return(di);
- }
-
-
- static DIRINFO *dsearch(v, d)
- DEVID v;
- DIRID d;
- {
- int i;
- DIRINFO *di;
-
- for(i = 0, di = *dirs; i < ndirs; i++, di++)
- if (v == di->di_vid && d == di->di_did)
- return(di);
- return(NULL);
- }
-
-
- static int match(pat, s, start1, len1)
- char *pat, *s, **start1;
- int *len1;
- {
- char c, *olds;
-
- *start1 = 0;
- for(;;)
- switch (c = *pat) {
- case '\0':
- case SLASH:
- return(*s == '\0');
- #ifdef MSDOS
- case '!':
- *start1 = olds = s;
- if ((s = strchr(s, '.')) == NULL)
- return(0);
- s++;
- *len1 = s - olds;
- if ((c = *(++pat)) == '\0') {
- *len1 += strlen(s);
- return(1);
- }
- for ( ; !match(pat, s, start1 + 1, len1 + 1); (*len1)++, s++)
- if (*s == '\0')
- return(0);
- return(1);
- #endif
- case '*':
- *start1 = s;
- if ((c = *(++pat)) == '\0') {
- *len1 = strlen(s);
- return(1);
- }
- else {
- for (*len1=0; !match(pat, s, start1+1, len1+1); (*len1)++, s++)
- if (
- #ifdef MSDOS
- *s == '.' ||
- #endif
- *s == '\0'
- )
- return(0);
- return(1);
- }
- case '?':
- if (
- #ifdef MSDOS
- *s == '.' ||
- #endif
- *s == '\0'
- )
- return(0);
- *(start1++) = s;
- *(len1++) = 1;
- pat++;
- s++;
- break;
- case '[':
- {
- int matched = 0, notin = 0, inrange = 0;
- char prevc = '\0';
-
- if ((c = *(++pat)) == '^') {
- notin = 1;
- c = *(++pat);
- }
- while (c != ']') {
- if (c == '-' && !inrange)
- inrange = 1;
- else {
- if (c == ESC) {
- c = *(++pat);
- }
- if (inrange) {
- if (*s >= prevc && *s <= c)
- matched = 1;
- inrange = 0;
- }
- else if (c == *s)
- matched = 1;
- prevc = c;
- }
- c = *(++pat);
- }
- if (inrange && *s >= prevc)
- matched = 1;
- if (!(matched ^ notin))
- return(0);
- *(start1++) = s;
- *(len1++) = 1;
- pat++;
- s++;
- }
- break;
- case ESC:
- c = *(++pat);
- default:
- if (c == *s) {
- pat++;
- s++;
- }
- else
- return(0);
- }
- }
-
-
- static void makerep()
- {
- int l, x;
- #ifndef MSDOS
- int i, cnv;
- char *q;
- #endif
- char *p, *pat, c, pc;
-
- repbad = 0;
- p = fullrep;
- for (pat = to, l = 0; (c = *pat) != '\0'; pat++, l++) {
- if (c == '#') {
- c = *(++pat);
- #ifndef MSDOS
- if (c == 'l') {
- cnv = LOWER;
- c = *(++pat);
- }
- if (c == 'u') {
- cnv = UPPER;
- c = *(++pat);
- }
- else
- cnv = STAY;
- #endif
- for(x = 0; ;x *= 10) {
- x += c - '0';
- c = *(pat+1);
- if (!isdigit(c))
- break;
- pat++;
- }
- --x;
- if (l + len[x] >= MAXPATH)
- goto toolong;
- #ifdef MSDOS
- if (
- *(start[x]) == '.' &&
- (
- p == fullrep ||
- *(p - 1) == SLASH
- )
- ) {
- repbad = 1;
- if (l + STRLEN(EMPTY) >= MAXPATH)
- goto toolong;
- strcpy(p, EMPTY);
- p += STRLEN(EMPTY);
- l += STRLEN(EMPTY);
- }
- #else
- switch (cnv) {
- case STAY:
- #endif
- memmove(p, start[x], len[x]);
- p += len[x];
- #ifndef MSDOS
- break;
- case LOWER:
- for (i = len[x], q = start[x]; i > 0; i--, p++, q++)
- *p = mylower(*q);
- break;
- case UPPER:
- for (i = len[x], q = start[x]; i > 0; i--, p++, q++)
- *p = myupper(*q);
- }
- #endif
- }
- else {
- if (c == ESC)
- c = *(++pat);
- if (l == MAXPATH)
- goto toolong;
- if (
- (
- #ifdef MSDOS
- c == '.' ||
- #endif
- c == SLASH
- ) &&
- (
- p == fullrep ? pat != to :
- (
- (
- (pc = *(p - 1)) == SLASH
- #ifdef MSDOS
- || pc == ':'
- #endif
- ) &&
- *(pat - 1) != pc
- )
- )
- ) {
- repbad = 1;
- if (l + STRLEN(EMPTY) >= MAXPATH)
- goto toolong;
- strcpy(p, EMPTY);
- p += STRLEN(EMPTY);
- l += STRLEN(EMPTY);
- }
- *(p++)= c;
- }
- }
- if (p == fullrep) {
- strcpy(fullrep, EMPTY);
- repbad = 1;
- }
- *(p++) = '\0';
- return;
-
- toolong:
- repbad = 1;
- strcpy(fullrep, TOOLONG);
- }
-
-
- static void checkcollisions()
- {
- REPDICT *rd, *prd;
- REP *p, *q;
- int i, mult, oldnreps;
-
- if (nreps == 0)
- return;
- rd = (REPDICT *)myalloc(nreps * sizeof(REPDICT));
- for (
- q = &hrep, p = q->r_next, prd = rd, i = 0;
- p != NULL;
- q = p, p = p->r_next, prd++, i++
- ) {
- prd->rd_p = p;
- prd->rd_dto = p->r_hto->h_di;
- prd->rd_nto = p->r_nto;
- prd->rd_i = i;
- }
- qsort(rd, nreps, sizeof(REPDICT), rdcmp);
- mult = 0;
- for (i = 0, prd = rd, oldnreps = nreps; i < oldnreps; i++, prd++)
- if (
- i < oldnreps - 1 &&
- prd->rd_dto == (prd + 1)->rd_dto &&
- strcmp(prd->rd_nto, (prd + 1)->rd_nto) == 0
- ) {
- if (!mult)
- mult = 1;
- else
- printf(" , ");
- printf("%s%s", prd->rd_p->r_hfrom->h_name,
- prd->rd_p->r_ffrom->fi_name);
- prd->rd_p->r_flags |= R_SKIP;
- prd->rd_p->r_ffrom->fi_rep = MISTAKE;
- nreps--;
- badreps++;
- }
- else if (mult) {
- prd->rd_p->r_flags |= R_SKIP;
- prd->rd_p->r_ffrom->fi_rep = MISTAKE;
- nreps--;
- badreps++;
- printf(" , %s%s -> %s%s : collision.\n",
- prd->rd_p->r_hfrom->h_name, prd->rd_p->r_ffrom->fi_name,
- prd->rd_p->r_hto->h_name, prd->rd_nto);
- mult = 0;
- }
- chgive(rd, oldnreps * sizeof(REPDICT));
- }
-
-
- static int rdcmp(rd1, rd2)
- REPDICT *rd1, *rd2;
- {
- int ret;
-
- if (
- (ret = rd1->rd_dto - rd2->rd_dto) == 0 &&
- (ret = strcmp(rd1->rd_nto, rd2->rd_nto)) == 0
- )
- ret = rd1->rd_i - rd2->rd_i;
- return(ret);
- }
-
-
- static void findorder()
- {
- REP *p, *q, *t, *first, *pred;
- FILEINFO *fi;
-
- for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next)
- if (p->r_flags & R_SKIP) {
- q->r_next = p->r_next;
- p = q;
- }
- else if (
- (fi = p->r_fdel) == NULL ||
- (pred = fi->fi_rep) == NULL ||
- pred == MISTAKE
- )
- continue;
- else if ((first = pred->r_first) == p) {
- p->r_flags |= R_ISCYCLE;
- pred->r_flags |= R_ISALIASED;
- if (op & MOVE)
- p->r_fdel = NULL;
- }
- else {
- if (op & MOVE)
- p->r_fdel = NULL;
- while (pred->r_thendo != NULL)
- pred = pred->r_thendo;
- pred->r_thendo = p;
- for (t = p; t != NULL; t = t->r_thendo)
- t->r_first = first;
- q->r_next = p->r_next;
- p = q;
- }
- }
-
-
- static void nochains()
- {
- REP *p, *q;
-
- for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next)
- if (p->r_flags & R_ISCYCLE || p->r_thendo != NULL) {
- printchain(p);
- printf("%s%s : no chain copies allowed.\n",
- p->r_hto->h_name, p->r_nto);
- q->r_next = p->r_next;
- p = q;
- }
- }
-
-
- static void printchain(p)
- REP *p;
- {
- if (p->r_thendo != NULL)
- printchain(p->r_thendo);
- printf("%s%s -> ", p->r_hfrom->h_name, p->r_ffrom->fi_name);
- badreps++;
- nreps--;
- p->r_ffrom->fi_rep = MISTAKE;
- }
-
-
- static void scandeletes(pkilldel)
- int (*pkilldel)();
- {
- REP *p, *q, *n;
-
- for (q = &hrep, p = q->r_next; p != NULL; q = p, p = p->r_next) {
- if (p->r_fdel != NULL)
- while ((*pkilldel)(p)) {
- nreps--;
- p->r_ffrom->fi_rep = MISTAKE;
- if ((n = p->r_thendo) != NULL) {
- if (op & MOVE)
- n->r_fdel = p->r_ffrom;
- n->r_next = p->r_next;
- q->r_next = p = n;
- }
- else {
- q->r_next = p->r_next;
- p = q;
- break;
- }
- }
- }
- }
-
-
- static int baddel(p)
- REP *p;
- {
- HANDLE *hfrom = p->r_hfrom, *hto = p->r_hto;
- FILEINFO *fto = p->r_fdel;
- char *t = fto->fi_name, *f = p->r_ffrom->fi_name;
- char *hnf = hfrom->h_name, *hnt = hto->h_name;
-
- if (delstyle == NODEL && !(p->r_flags & R_DELOK) && !(op & APPEND))
- printf("%s%s -> %s%s : old %s%s would have to be %s.\n",
- hnf, f, hnt, t, hnt, t,
- (op & OVERWRITE) ? "overwritten" : "deleted");
- else if (fto->fi_rep == MISTAKE)
- printf("%s%s -> %s%s : old %s%s was to be done first.\n",
- hnf, f, hnt, t, hnt, t);
- else if (
- #ifdef MSDOS
- fto->fi_attrib & FA_DIREC
- #else
- fto->fi_stflags & FI_ISDIR
- #endif
- )
- printf("%s%s -> %s%s : %s%s%s is a directory.\n",
- hnf, f, hnt, t, (op & APPEND) ? "" : "old ", hnt, t);
- #ifndef MSDOS
- else if ((fto->fi_stflags & FI_NODEL) && !(op & (APPEND | OVERWRITE)))
- printf("%s%s -> %s%s : old %s%s lacks delete permission.\n",
- hnf, f, hnt, t, hnt, t);
- #endif
- else if (
- (op & (APPEND | OVERWRITE)) &&
- #ifdef MSDOS
- fto->fi_attrib & FA_RDONLY
- #else
- !fwritable(hnt, fto)
- #endif
- ) {
- printf("%s%s -> %s%s : %s%s %s.\n",
- hnf, f, hnt, t, hnt, t,
- #ifndef MSDOS
- #ifndef SYSV
- fto->fi_stflags & FI_LINKERR ?
- "is a badly aimed symbolic link" :
- #endif
- #endif
- "lacks write permission");
- }
- else
- return(0);
- badreps++;
- return(1);
- }
-
-
- static int skipdel(p)
- REP *p;
- {
- if (p->r_flags & R_DELOK)
- return(0);
- fprintf(stderr, "%s%s -> %s%s : ",
- p->r_hfrom->h_name, p->r_ffrom->fi_name,
- p->r_hto->h_name, p->r_nto);
- if (
- #ifdef MSDOS
- p->r_fdel->fi_attrib & FA_RDONLY
- #else
- #ifndef SYSV
- !(p->r_ffrom->fi_stflags & FI_ISLNK) &&
- #endif
- !fwritable(p->r_hto->h_name, p->r_fdel)
- #endif
- )
- fprintf(stderr, "old %s%s lacks write permission. delete it",
- p->r_hto->h_name, p->r_nto);
- else
- fprintf(stderr, "%s old %s%s",
- (op & OVERWRITE) ? "overwrite" : "delete",
- p->r_hto->h_name, p->r_nto);
- return(!getreply("? ", -1));
- }
-
-
- static void goonordie()
- {
- if ((paterr || badreps) && nreps > 0) {
- fprintf(stderr, "Not everything specified can be done.");
- if (badstyle == ABORTBAD) {
- fprintf(stderr, " Aborting.\n");
- exit(1);
- }
- else if (badstyle == SKIPBAD)
- fprintf(stderr, " Proceeding with the rest.\n");
- else if (!getreply(" Proceed with the rest? ", -1))
- exit(1);
- }
- }
-
-
- static void doreps()
- {
- char *fstart;
- int k, printaliased = 0, alias;
- REP *first, *p;
- long aliaslen;
-
- #ifdef MSDOS
- ctrlbrk(breakrep);
- #else
- signal(SIGINT, breakrep);
- #endif
-
- for (first = hrep.r_next, k = 0; first != NULL; first = first->r_next) {
- for (p = first; p != NULL; p = p->r_thendo, k++) {
- if (gotsig) {
- fflush(stdout);
- fprintf(stderr, "User break.\n");
- printaliased = snap(first, p);
- gotsig = 0;
- }
- strcpy(fullrep, p->r_hto->h_name);
- strcat(fullrep, p->r_nto);
- if (!noex && (p->r_flags & R_ISCYCLE))
- if (op & APPEND)
- aliaslen = appendalias(first, p, &printaliased);
- else
- alias = movealias(first, p, &printaliased);
- strcpy(pathbuf, p->r_hfrom->h_name);
- fstart = pathbuf + strlen(pathbuf);
- if ((p->r_flags & R_ISALIASED) && !(op & APPEND))
- sprintf(fstart, "%s%03d", TEMP, alias);
- else
- strcpy(fstart, p->r_ffrom->fi_name);
- if (!noex) {
- if (p->r_fdel != NULL && !(op & (APPEND | OVERWRITE)))
- myunlink(fullrep, p->r_fdel);
- if (
- (op & (COPY | APPEND)) ?
- copy(p->r_ffrom,
- p->r_flags & R_ISALIASED ? aliaslen : -1) :
- #ifndef MSDOS
- (op & HARDLINK) ?
- link(pathbuf, fullrep) :
- #ifndef SYSV
- (op & SYMLINK) ?
- symlink((p->r_flags & R_ONEDIRLINK) ? fstart : pathbuf,
- fullrep) :
- #endif
- #endif
- p->r_flags & R_ISX ?
- copymove(p) :
- /* move */
- rename(pathbuf, fullrep)
- ) {
- fprintf(stderr,
- "%s -> %s has failed.\n", pathbuf, fullrep);
- printaliased = snap(first, p);
- }
- }
- if (verbose || noex) {
- if (p->r_flags & R_ISALIASED && !printaliased)
- strcpy(fstart, p->r_ffrom->fi_name);
- fprintf(outfile, "%s %c%c %s%s%s\n",
- pathbuf,
- p->r_flags & R_ISALIASED ? '=' : '-',
- p->r_flags & R_ISCYCLE ? '^' : '>',
- fullrep,
- (p->r_fdel != NULL && !(op & APPEND)) ? " (*)" : "",
- noex ? "" : " : done");
- }
- }
- printaliased = 0;
- }
- if (k != nreps)
- fprintf(stderr, "Strange, did %d reps; %d were expected.\n",
- k, nreps);
- if (k == 0)
- fprintf(stderr, "Nothing done.\n");
- }
-
-
- static long appendalias(first, p, pprintaliased)
- REP *first, *p;
- int *pprintaliased;
- {
- long ret;
-
- #ifdef MSDOS
- int fd;
-
- if ((fd = open(fullrep, O_RDONLY | O_BINARY, 0)) < 0) {
- fprintf(stderr, "stat on %s has failed.\n", fullrep);
- *pprintaliased = snap(first, p);
- }
- else {
- ret = filelength(fd);
- close(fd);
- }
- #else
- struct stat fstat;
-
- if (stat(fullrep, &fstat)) {
- fprintf(stderr, "append cycle stat on %s has failed.\n", fullrep);
- *pprintaliased = snap(first, p);
- }
- else
- ret = fstat.st_size;
- #endif
-
- return(ret);
- }
-
-
- static int movealias(first, p, pprintaliased)
- REP *first, *p;
- int *pprintaliased;
- {
- char *fstart;
- int ret;
-
- strcpy(pathbuf, p->r_hto->h_name);
- fstart = pathbuf + strlen(pathbuf);
- strcpy(fstart, TEMP);
- for (
- ret = 0;
- sprintf(fstart + STRLEN(TEMP), "%03d", ret),
- fsearch(fstart, p->r_hto->h_di) != NULL;
- ret++
- )
- ;
- if (rename(fullrep, pathbuf)) {
- fprintf(stderr,
- "%s -> %s has failed.\n", fullrep, pathbuf);
- *pprintaliased = snap(first, p);
- }
- return(ret);
- }
-
-
- static int snap(first, p)
- REP *first, *p;
- {
- char fname[80];
- int redirected = 0;
-
- if (noex)
- exit(1);
-
- failed = 1;
- #ifdef MSDOS
- ctrlbrk((int (*)())breakstat);
- #else
- signal(SIGINT, breakstat);
- #endif
- if (
- badstyle == ASKBAD &&
- isatty(fileno(stdout)) &&
- getreply("Redirect standard output to file? ", 0)
- ) {
- redirected = 1;
- #ifndef MSDOS
- umask(oldumask);
- #endif
- while (
- fprintf(stderr, "File name> "),
- (outfile = fopen(gets(fname), "w")) == NULL
- )
- fprintf(stderr, "Can't open %s.\n", fname);
- }
- if (redirected || !verbose)
- showdone(p);
- fprintf(outfile, "The following left undone:\n");
- noex = 1;
- return(first != p);
- }
-
-
- static void showdone(fin)
- REP *fin;
- {
- REP *first, *p;
-
- for (first = hrep.r_next; ; first = first->r_next)
- for (p = first; p != NULL; p = p->r_thendo) {
- if (p == fin)
- return;
- fprintf(outfile, "%s%s %c%c %s%s : done%s\n",
- p->r_hfrom->h_name, p->r_ffrom->fi_name,
- p->r_flags & R_ISALIASED ? '=' : '-',
- p->r_flags & R_ISCYCLE ? '^' : '>',
- p->r_hto->h_name, p->r_nto,
- (p->r_fdel != NULL && !(op & APPEND)) ? " (*)" : "");
- }
- }
-
-
- static void breakout()
- {
- fflush(stdout);
- fprintf(stderr, "Aborting, nothing done.\n");
- exit(1);
- }
-
-
- static int breakrep()
- {
- gotsig = 1;
- return(1);
- }
-
-
- static void breakstat()
- {
- exit(1);
- }
-
-
- static void quit()
- {
- fprintf(stderr, "Aborting, nothing done.\n");
- exit(1);
- }
-
-
- static int copymove(p)
- REP *p;
- {
- #ifndef MSDOS
- #ifndef SYSV
- {
- int llen;
- char linkbuf[MAXPATH];
-
- if ((llen = readlink(pathbuf, linkbuf, MAXPATH - 1)) != 1) {
- linkbuf[llen] = '\0';
- return(symlink(linkbuf, fullrep) || myunlink(pathbuf, p->r_ffrom));
- }
- }
- #endif
- #endif
- return(copy(p->r_ffrom, -1) || myunlink(pathbuf, p->r_ffrom));
- }
-
-
-
- #define IRWMASK (S_IREAD | S_IWRITE)
- #define RWMASK (IRWMASK | (IRWMASK >> 3) | (IRWMASK >> 6))
-
- static int copy(ff, len)
- FILEINFO *ff;
- long len;
- {
- char buf[BUFSIZE], c;
- int f, t, k, mode, perm;
- #ifdef MSDOS
- struct ftime tim;
- #else
- #ifdef SYSV
- struct utimbuf tim;
- #else
- struct timeval tim[2];
- #endif
- struct stat fstat;
- #endif
-
- if ((f = open(pathbuf, O_RDONLY | O_BINARY, 0)) < 0)
- return(-1);
- perm =
- #ifdef MSDOS
- IRWMASK /* will _chmod it later (to get all the attributes) */
- #else
- (op & (APPEND | OVERWRITE)) ?
- (~oldumask & RWMASK) | (ff->fi_mode & ~RWMASK) :
- ff->fi_mode
- #endif
- ;
- mode = O_CREAT |
- #ifdef MSDOS
- O_BINARY | (op & ZAPPEND ? O_RDWR : O_WRONLY)
- #else
- O_WRONLY
- #endif
- ;
- if (!(op & APPEND))
- mode |= O_TRUNC;
- if ((t = open(fullrep, mode, perm)) < 0) {
- close(f);
- return(-1);
- }
- if (op & APPEND)
- lseek(t, 0, 2);
- #ifdef MSDOS
- if (op & ZAPPEND && filelength(t) != 0) {
- if (lseek(t, -1, 1) == -1L || read(t, &c, 1) != 1) {
- close(f);
- close(t);
- return(-1);
- }
- if (c == 26)
- lseek(t, -1, 1);
- }
- #endif
- if ((op & APPEND) && len != -1L) {
- while (
- len != 0 &&
- (k = read(f, buf, len > BUFSIZE ? BUFSIZE : (unsigned)len)) > 0 &&
- write(t, buf, k) == k
- )
- len -= k;
- if (len == 0)
- k = 0;
- }
- else
- while ((k = read(f, buf, BUFSIZE)) > 0 && write(t, buf, k) == k)
- ;
- if (!(op & (APPEND | OVERWRITE)))
- if (
- #ifdef MSDOS
- getftime(f, &tim) ||
- setftime(t, &tim) ||
- _chmod(fullrep, 1, ff->fi_attrib) == -1
- #else
- stat(pathbuf, &fstat) ||
- (
- #ifdef SYSV
- tim.actime = fstat.st_atime,
- tim.modtime = fstat.st_mtime,
- #else
- tim[0].tv_sec = fstat.st_atime,
- tim[1].tv_sec = fstat.st_mtime,
- #endif
- utimes(fullrep, tim)
- )
- #endif
- )
- fprintf(stderr, "Strange, couldn't transfer time from %s to %s.\n",
- pathbuf, fullrep);
-
- close(f);
- close(t);
- if (k != 0) {
- if (!(op & APPEND))
- unlink(fullrep);
- return(-1);
- }
- return(0);
- }
-
-
- #ifndef RENAME
- static int rename(from, to)
- char *from, *to;
- {
- if (link(from, to))
- return(-1);
- if (unlink(from)) {
- unlink(to);
- return(-1);
- }
- return(0);
- }
- #endif
-
-
- static int myunlink(n, f)
- char *n;
- FILEINFO *f;
- {
- #ifdef MSDOS
- int a;
-
- if (((a = f->fi_attrib) & FA_RDONLY) && _chmod(n, 1, a & ~FA_RDONLY) < 0) {
- fprintf(stderr, "Strange, can not _chmod (or unlink) %s.\n", f);
- return(-1);
- }
- #endif
- if (unlink(n)) {
- fprintf(stderr, "Strange, can not unlink %s.\n", n);
- return(-1);
- }
- return(0);
- }
-
-
- static int getreply(m, failact)
- char *m;
- int failact;
- {
- static FILE *tty = NULL;
- int c, r;
-
- fprintf(stderr, m);
- if (tty == NULL && (tty = fopen(TTY, "r")) == NULL) {
- fprintf(stderr, "Can not open %s to get reply.\n", TTY);
- if (failact == -1)
- quit();
- else
- return(failact);
- }
- for (;;) {
- r = fgetc(tty);
- if (r == EOF) {
- fprintf(stderr, "Can not get reply.\n");
- if (failact == -1)
- quit();
- else
- return(failact);
- }
- if (r != '\n')
- while ((c = fgetc(tty)) != '\n' && c != EOF)
- ;
- r = mylower(r);
- if (r == 'y' || r == 'n')
- return(r == 'y');
- fprintf(stderr, "Yes or No? ");
- }
- }
-
-
- static void *myalloc(k)
- unsigned k;
- {
- void *ret;
-
- if (k == 0)
- return(NULL);
- if ((ret = (void *)malloc(k)) == NULL) {
- fprintf(stderr, "Insufficient memory.\n");
- quit();
- }
- return(ret);
- }
-
-
- static void *challoc(k, which)
- int which;
- int k;
- {
- void *ret;
- CHUNK *p, *q;
- SLICER *sl = &(slicer[which]);
-
- if (k > sl->sl_len) {
- for (
- q = NULL, p = freechunks;
- p != NULL && (sl->sl_len = p->ch_len) < k;
- q = p, p = p->ch_next
- )
- ;
- if (p == NULL) {
- sl->sl_len = CHUNKSIZE - sizeof(CHUNK *);
- p = (CHUNK *)myalloc(CHUNKSIZE);
- }
- else if (q == NULL)
- freechunks = p->ch_next;
- else
- q->ch_next = p->ch_next;
- p->ch_next = sl->sl_first;
- sl->sl_first = p;
- sl->sl_unused = (char *)&(p->ch_len);
- }
- sl->sl_len -= k;
- ret = (void *)sl->sl_unused;
- sl->sl_unused += k;
- return(ret);
- }
-
-
- static void chgive(p, k)
- void *p;
- unsigned k;
- {
- ((CHUNK *)p)->ch_len = k - sizeof(CHUNK *);
- ((CHUNK *)p)->ch_next = freechunks;
- freechunks = (CHUNK *)p;
- }
-
-
- #ifndef MSDOS
- static void memmove(to, from, k)
- char *to, *from;
- unsigned k;
- {
- if (from > to)
- while (k-- != 0)
- *(to++) = *(from++);
- else {
- from += k;
- to += k;
- while (k-- != 0)
- *(--to) = *(--from);
- }
- }
- #endif
-
-
- static int mygetc()
- {
- static int lastc = 0;
-
- if (lastc == EOF)
- return(EOF);
- return(lastc = getchar());
- }
-
-
- #ifdef MSDOS
- static int leave()
- {
- return(0);
- }
-
- static void cleanup()
- {
- int i;
-
- if (patch.ph_safeid) {
- for (i = 0; i < nhandles; i++) {
- if (!(handles[i]->h_di->di_flags & DI_CLEANED)) {
- sprintf(pathbuf, "%s%s%03d",
- handles[i]->h_name, IDF, handles[i]->h_di->di_did);
- if (unlink(pathbuf))
- fprintf(stderr, "Strange, couldn't unlink %s.\n", pathbuf);
- handles[i]->h_di->di_flags |= DI_CLEANED;
- }
- }
- }
- /*
- Write device availability: undocumented internal MS-D*S function.
- Restore previous value.
- */
- bdos(0x37, olddevflag, 3);
- }
-
- #endif