X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Futilities.c;h=f17bd9ce458a7214ab50050f787c794d79a033a1;hp=c93c8540fa29a634275326664dfc090279c7f8cd;hb=f32a70b091d3ee6524e760ec2cb21080f67fe2ee;hpb=b45f51d61e911ac8a040bef1efda6afd82261e03 diff --git a/restore/utilities.c b/restore/utilities.c index c93c854..f17bd9c 100644 --- a/restore/utilities.c +++ b/restore/utilities.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999 - * + * Stelian Pop , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000-2002 */ /* @@ -18,11 +18,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -40,34 +36,46 @@ */ #ifndef lint -#if 0 -static char sccsid[] = "@(#)utilities.c 8.5 (Berkeley) 4/28/95"; -#endif static const char rcsid[] = - "$Id: utilities.c,v 1.2 1999/10/11 12:53:25 stelian Exp $"; + "$Id: utilities.c,v 1.28 2005/03/30 13:21:45 stelian Exp $"; #endif /* not lint */ +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #ifdef __linux__ #include +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif +#include #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#include +#else #include #include +#endif #endif /* __linux__ */ - -#include -#include -#include -#include - -#ifdef __linux__ -#include +#ifdef DUMP_MACOSX +#include "darwin.h" #endif - #include "restore.h" #include "extern.h" @@ -75,10 +83,9 @@ static const char rcsid[] = * Insure that all the components of a pathname exist. */ void -pathcheck(name) - char *name; +pathcheck(char *name) { - register char *cp; + char *cp; struct entry *ep; char *start; @@ -104,8 +111,7 @@ pathcheck(name) * Change a name to a unique temporary name. */ void -mktempname(ep) - register struct entry *ep; +mktempname(struct entry *ep) { char oldname[MAXPATHLEN]; @@ -123,8 +129,7 @@ mktempname(ep) * Generate a temporary name for an entry. */ char * -gentempname(ep) - struct entry *ep; +gentempname(struct entry *ep) { static char name[MAXPATHLEN]; struct entry *np; @@ -135,7 +140,7 @@ gentempname(ep) i++; if (np == NULL) badentry(ep, "not on ino list"); - (void) sprintf(name, "%s%ld%lu", TMPHDR, i, (u_long)ep->e_ino); + (void) snprintf(name, sizeof(name), "%s%ld%lu", TMPHDR, i, (unsigned long)ep->e_ino); return (name); } @@ -143,26 +148,22 @@ gentempname(ep) * Rename a file or directory. */ void -renameit(from, to) - char *from, *to; +renameit(char *from, char *to) { if (!Nflag && rename(from, to) < 0) { - fprintf(stderr, "warning: cannot rename %s to %s: %s\n", - from, to, strerror(errno)); + warn("cannot rename %s to %s", from, to); return; } - vprintf(stdout, "rename %s to %s\n", from, to); + Vprintf(stdout, "rename %s to %s\n", from, to); } /* * Create a new node (directory). */ void -newnode(np) - struct entry *np; +newnode(struct entry *np) { char *cp; - if (np->e_type != NODE) badentry(np, "newnode: not a node"); cp = myname(np); @@ -170,41 +171,44 @@ newnode(np) if (!Nflag && mkdir(cp, 0777) < 0 && !uflag) { np->e_flags |= EXISTED; - fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); + warn("%s", cp); return; } - vprintf(stdout, "Make node %s\n", cp); + Vprintf(stdout, "Make node %s\n", cp); } /* * Remove an old node (directory). */ void -removenode(ep) - register struct entry *ep; +removenode(struct entry *ep) { char *cp; if (ep->e_type != NODE) badentry(ep, "removenode: not a node"); - if (ep->e_entries != NULL) - badentry(ep, "removenode: non-empty directory"); + if (ep->e_entries != NULL) { + int i; + for (i = 0; i < DIRHASH_SIZE; i++) { + if (ep->e_entries[i] != NULL) + badentry(ep, "removenode: non-empty directory"); + } + } ep->e_flags |= REMOVED; ep->e_flags &= ~TMPNAME; cp = myname(ep); if (!Nflag && rmdir(cp) < 0) { - fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); + warn("%s", cp); return; } - vprintf(stdout, "Remove node %s\n", cp); + Vprintf(stdout, "Remove node %s\n", cp); } /* * Remove a leaf. */ void -removeleaf(ep) - register struct entry *ep; +removeleaf(struct entry *ep) { char *cp; @@ -216,19 +220,17 @@ removeleaf(ep) ep->e_flags &= ~TMPNAME; cp = myname(ep); if (!Nflag && unlink(cp) < 0) { - fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno)); + warn("%s", cp); return; } - vprintf(stdout, "Remove leaf %s\n", cp); + Vprintf(stdout, "Remove leaf %s\n", cp); } /* * Create a link. */ int -linkit(existing, new, type) - char *existing, *new; - int type; +linkit(char *existing, char *new, int type) { /* if we want to unlink first, do it now so *link() won't fail */ @@ -237,9 +239,8 @@ linkit(existing, new, type) if (type == SYMLINK) { if (!Nflag && symlink(existing, new) < 0) { - fprintf(stderr, - "warning: cannot create symbolic link %s->%s: %s\n", - new, existing, strerror(errno)); + warn("cannot create symbolic link %s->%s", + new, existing); return (FAIL); } } else if (type == HARDLINK) { @@ -247,7 +248,7 @@ linkit(existing, new, type) if (!Nflag && (ret = link(existing, new)) < 0) { -#ifndef __linux__ +#if !defined(__linux__) && !defined(sunos) struct stat s; /* @@ -259,11 +260,25 @@ linkit(existing, new, type) ret = link(existing, new); chflags(existing, s.st_flags); } +#else + unsigned long s; + + /* + * Most likely, the immutable or append-only attribute + * is set. Clear the attributes and try again. + */ +#ifdef sunos +#else + if (lgetflags (existing, &s) != -1 && + lsetflags (existing, 0) != -1) { + ret = link(existing, new); + lsetflags(existing, s); + } +#endif #endif if (ret < 0) { - fprintf(stderr, "warning: cannot create " - "hard link %s->%s: %s\n", - new, existing, strerror(errno)); + warn("warning: cannot create hard link %s->%s", + new, existing); return (FAIL); } } @@ -271,26 +286,24 @@ linkit(existing, new, type) panic("linkit: unknown type %d\n", type); return (FAIL); } - vprintf(stdout, "Create %s link %s->%s\n", + Vprintf(stdout, "Create %s link %s->%s\n", type == SYMLINK ? "symbolic" : "hard", new, existing); return (GOOD); } -#ifndef __linux__ +#if !defined(__linux__) && !defined(sunos) /* * Create a whiteout. */ int -addwhiteout(name) - char *name; +addwhiteout(char *name) { if (!Nflag && mknod(name, S_IFWHT, 0) < 0) { - fprintf(stderr, "warning: cannot create whiteout %s: %s\n", - name, strerror(errno)); + warn("cannot create whiteout %s", name); return (FAIL); } - vprintf(stdout, "Create whiteout %s\n", name); + Vprintf(stdout, "Create whiteout %s\n", name); return (GOOD); } @@ -298,8 +311,7 @@ addwhiteout(name) * Delete a whiteout. */ void -delwhiteout(ep) - register struct entry *ep; +delwhiteout(struct entry *ep) { char *name; @@ -309,22 +321,20 @@ delwhiteout(ep) ep->e_flags &= ~TMPNAME; name = myname(ep); if (!Nflag && undelete(name) < 0) { - fprintf(stderr, "warning: cannot delete whiteout %s: %s\n", - name, strerror(errno)); + warn("cannot delete whiteout %s", name); return; } - vprintf(stdout, "Delete whiteout %s\n", name); + Vprintf(stdout, "Delete whiteout %s\n", name); } #endif /* * find lowest number file (above "start") that needs to be extracted */ -ino_t -lowerbnd(start) - ino_t start; +dump_ino_t +lowerbnd(dump_ino_t start) { - register struct entry *ep; + struct entry *ep; for ( ; start < maxino; start++) { ep = lookupino(start); @@ -339,11 +349,10 @@ lowerbnd(start) /* * find highest number file (below "start") that needs to be extracted */ -ino_t -upperbnd(start) - ino_t start; +dump_ino_t +upperbnd(dump_ino_t start) { - register struct entry *ep; + struct entry *ep; for ( ; start > ROOTINO; start--) { ep = lookupino(start); @@ -359,9 +368,7 @@ upperbnd(start) * report on a badly formed entry */ void -badentry(ep, msg) - register struct entry *ep; - char *msg; +badentry(struct entry *ep, const char *msg) { fprintf(stderr, "bad entry: %s\n", msg); @@ -369,8 +376,15 @@ badentry(ep, msg) fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); if (ep->e_sibling != NULL) fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); - if (ep->e_entries != NULL) - fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); + if (ep->e_entries != NULL) { + int i; + for (i = 0; i < DIRHASH_SIZE; i++) { + if (ep->e_entries[i] != NULL) { + fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries[i])); + break; + } + } + } if (ep->e_links != NULL) fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); if (ep->e_next != NULL) @@ -378,7 +392,7 @@ badentry(ep, msg) "next hashchain name: %s\n", myname(ep->e_next)); fprintf(stderr, "entry type: %s\n", ep->e_type == NODE ? "NODE" : "LEAF"); - fprintf(stderr, "inode number: %lu\n", (u_long)ep->e_ino); + fprintf(stderr, "inode number: %lu\n", (unsigned long)ep->e_ino); panic("flags: %s\n", flagvalues(ep)); } @@ -386,8 +400,7 @@ badentry(ep, msg) * Construct a string indicating the active flag bits of an entry. */ char * -flagvalues(ep) - register struct entry *ep; +flagvalues(struct entry *ep) { static char flagbuf[BUFSIZ]; @@ -411,12 +424,11 @@ flagvalues(ep) /* * Check to see if a name is on a dump tape. */ -ino_t -dirlookup(name) - const char *name; +dump_ino_t +dirlookup(const char *name) { struct direct *dp; - ino_t ino; + dump_ino_t ino; ino = ((dp = pathsearch(name)) == NULL) ? 0 : dp->d_ino; @@ -429,8 +441,7 @@ dirlookup(name) * Elicit a reply. */ int -reply(question) - char *question; +reply(const char *question) { char c; @@ -450,14 +461,14 @@ reply(question) /* * handle unexpected inconsistencies */ -#if __STDC__ +#ifdef __STDC__ #include #else #include #endif void -#if __STDC__ +#ifdef __STDC__ panic(const char *fmt, ...) #else panic(fmt, va_alist) @@ -466,7 +477,7 @@ panic(fmt, va_alist) #endif { va_list ap; -#if __STDC__ +#ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); @@ -476,8 +487,285 @@ panic(fmt, va_alist) if (yflag) return; if (reply("abort") == GOOD) { - if (reply("dump core") == GOOD) + if (reply("dump core") == GOOD) { + fchdir(wdfd); abort(); - done(1); + } + exit(1); + } +} + +void resizemaps(dump_ino_t oldmax, dump_ino_t newmax) +{ + char *map; + + if (usedinomap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for active inode map"); + memcpy(map, usedinomap, howmany(oldmax, NBBY)); + free(usedinomap); + usedinomap = map; + } + if (dumpmap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for file dump list"); + memcpy(map, dumpmap, howmany(oldmax, NBBY)); + free(dumpmap); + dumpmap = map; + } +} + +void +GetPathFile(char *source, char *path, char *fname) +{ + char *p, *s; + + *path = 0; + *fname = 0; + p = s = source; + while (*s) { + if (*s == '/') { + p = s + 1; + } + s++; + } + if (p == source) { + *path = 0; + } else { + strncpy(path, source, p - source); + path[p - source] = 0; + } + strcpy(fname, p); +} + +#ifdef USE_QFA +/* + * search for ino in QFA file + * + * if exactmatch: + * if ino found return tape number and tape position + * if ino not found return tnum=0 and tpos=0 + * + * if not exactmatch: + * if ino found return tape number and tape position + * if ino not found return tape number and tape position of last smaller ino + * if no smaller inode found return tnum=0 and tpos=0 + */ +int +Inode2Tapepos(dump_ino_t ino, long *tnum, long long *tpos, int exactmatch) +{ + char *p, *pp; + char numbuff[32]; + unsigned long tmpino; + long tmptnum; + long long tmptpos; + + *tpos = 0; + *tnum = 0; + if (fseek(gTapeposfp, gSeekstart, SEEK_SET) == -1) + return errno; + while (1) { + gSeekstart = ftell(gTapeposfp); /* remember for later use */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) { + return 0; + } + gTps[strlen(gTps) - 1] = 0; /* delete end of line */ + p = gTps; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read inode */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmpino = atol(numbuff); + if (*p == 0) + return 1; /* may NOT happen */ + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapenum */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + if (*p == 0) + return 1; /* may NOT happen */ + tmptnum = atol(numbuff); + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapepos */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmptpos = atoll(numbuff); + + if (exactmatch) { + if (tmpino == ino) { + *tnum = tmptnum; + *tpos = tmptpos; + return 0; + } + } else { + if (tmpino > ino) { + return 0; + } else { + *tnum = tmptnum; + *tpos = tmptpos; + } + } + } + return 0; +} + +#ifdef sunos +int +GetSCSIIDFromPath(char *devPath, long *id) +{ + int len; + char fbuff[2048]; + char path[2048]; + char fname[2048]; + char *fpn = fname; + char idstr[32]; + char *ip = idstr; + + bzero(fbuff, sizeof(fbuff)); + if ((len = readlink(devPath, fbuff, 2048)) == -1) { + return errno; + } + fbuff[len] = 0; + GetPathFile(fbuff, path, fname); + (void)memset(idstr, 0, sizeof(idstr)); + while (*fpn && (*fpn != ',')) { + if (*fpn <= '9' && *fpn >= '0') { + *ip = *fpn; + ip++; + } + fpn++; + } + if (*idstr) { + *id = atol(idstr); + } else { + *id = -1; + } + return 0; +} +#endif +#endif /* USE_QFA */ + +#ifdef DUMP_MACOSX +int +CreateAppleDoubleFileRes(char *oFile, FndrFileInfo *finderinfo, mode_t mode, int flags, + struct timeval *timep, u_int32_t uid, u_int32_t gid) +{ + int err = 0; + int fdout; + char *p; + char *pp; + ASDHeaderPtr hp; + ASDEntryPtr ep; + long thesize; + long n; + + + n = 1; /* number of entries in double file ._ only finderinfo */ + /* + no data fork + n++; + currently no resource fork + n++; + */ + + thesize = sizeof(ASDHeader) + (n * sizeof(ASDEntry)) + INFOLEN; + if ((pp = p = (char *)malloc(thesize)) == NULL) { + err = errno; + return err; + } + + hp = (ASDHeaderPtr)p; + p += sizeof(ASDHeader); + ep = (ASDEntryPtr)p; + p += sizeof(ASDEntry) * n; + + hp->magic = ADOUBLE_MAGIC; + hp->version = ASD_VERSION2; + + bzero(&hp->filler, sizeof(hp->filler)); + hp->entries = (short)n; + + ep->entryID = EntryFinderInfo; + ep->offset = p - pp - CORRECT; + ep->len = INFOLEN; /* sizeof(MacFInfo) + sizeof(FXInfo); */ + bzero(p, ep->len); + bcopy(finderinfo, p, sizeof(FndrFileInfo)); + p += ep->len; + ep++; + + if ((fdout = open(oFile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + err = errno; + free(pp); + return err; + } + + /* write the ASDHeader */ + if (write(fdout, pp, sizeof(ASDHeader) - CORRECT) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; + } + /* write the ASDEntries */ + if (write(fdout, pp + sizeof(ASDHeader), thesize - sizeof(ASDHeader)) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; + } + + (void)fchown(fdout, uid, gid); + (void)fchmod(fdout, mode); + close(fdout); + (void)lsetflags(oFile, flags); + utimes(oFile, timep); + free(pp); + return err; +} +#endif /* DUMP_MACOSX */ + +int +lgetflags(const char *path, unsigned long *flags) +{ + int err; + struct STAT sb; + + err = LSTAT(path, &sb); + if (err < 0) + return err; + + if (S_ISLNK(sb.st_mode) || S_ISFIFO(sb.st_mode)) { + // no way to get/set flags on a symlink + *flags = 0; + return 0; + } + else + return fgetflags(path, flags); +} + +int +lsetflags(const char *path, unsigned long flags) +{ + int err; + struct STAT sb; + + err = LSTAT(path, &sb); + if (err < 0) + return err; + + if (S_ISLNK(sb.st_mode) || S_ISFIFO(sb.st_mode)) { + // no way to get/set flags on a symlink + return 0; } + else + return fsetflags(path, flags); }