📄 untar.c
字号:
{ sum += (*scan) & 0xff; if (sunny && (*scan & 0x80) != 0) sum -= 256; } return sum;}/* list files in an archive, and optionally extract them as well */static int untar_block(Uchar_t *blk) { static char nbuf[256];/* storage space for prefix+name, combined */ static char *name,*n2;/* prefix and name, combined */ static int first = 1;/* Boolean: first block of archive? */ long sum; /* checksum for this block */ int i; tar_t tblk[1];#ifdef _POSIX_SOURCE static mode_t mode; /* file permissions */ static struct utimbuf timestamp; /* file timestamp */#endif /* make a local copy of the block, and treat it as a tar header */ tblk[0] = *(tar_t *)blk; /* process each type of tape block differently */ if (outsize > TSIZE) { /* data block, but not the last one */ if (outfp) cvtwrite(blk, (Ulong_t)TSIZE, outfp); outsize -= TSIZE; } else if (outsize > 0) { /* last data block of current file */ if (outfp) { cvtwrite(blk, outsize, outfp); fclose(outfp); outfp = NULL;#ifdef _POSIX_SOURCE utime(nbuf, ×tamp); chmod(nbuf, mode);#endif } outsize = 0; } else if ((tblk)->filename[0] == '\0') { /* end-of-archive marker */ if (didabs) untar_warning("Removed leading slashes because \"ABSPATH option\" wasn't given.\n"); return 1; } else { /* file header */ /* half-assed verification -- does it look like header? */ if ((tblk)->filename[99] != '\0' || ((tblk)->size[0] < '0' && (tblk)->size[0] != ' ') || (tblk)->size[0] > '9') { if (first) { untar_error("%s: not a valid tar file\n", inname); return 0; } else { untar_error("Garbage detected; preceding file may be damaged\n"); return 0; } } /* combine prefix and filename */ memset(nbuf, 0, sizeof nbuf); name = nbuf; if ((tblk)->prefix[0]) { strncpy(name, (tblk)->prefix, sizeof (tblk)->prefix); strcat(name, "/"); strncat(name + strlen(name), (tblk)->filename, sizeof (tblk)->filename); } else { strncpy(name, (tblk)->filename, sizeof (tblk)->filename); } /* Convert any backslashes to forward slashes, and guard * against doubled-up slashes. (Some DOS versions of "tar" * get this wrong.) Also strip off leading slashes. */ if (!ABSPATH && (*name == '/' || *name == '\\')) didabs = 1; for (n2 = nbuf; *name; name++) { if (*name == '\\') *name = '/'; if (*name != '/' || (ABSPATH && n2 == nbuf) || (n2 != nbuf && n2[-1] != '/')) *n2++ = *name; } if (n2 == nbuf) *n2++ = '/'; *n2 = '\0'; /* verify the checksum */ for (sum = 0L, i = 0; i < sizeof((tblk)->checksum); i++) { if ((tblk)->checksum[i] >= '0' && (tblk)->checksum[i] <= '7') sum = sum * 8 + (tblk)->checksum[i] - '0'; } if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1)) { if (!first) untar_error("Garbage detected; preceding file may be damaged\n"); untar_error("%s: header has bad checksum for %s\n", inname, nbuf); return 0; } /* From this point on, we don't care whether this is the first * block or not. Might as well reset the "first" flag now. */ first = 0; /* if last character of name is '/' then assume directory */ if (*nbuf && nbuf[strlen(nbuf) - 1] == '/') (tblk)->type = '5'; /* convert file size */ for (outsize = 0L, i = 0; i < sizeof((tblk)->size); i++) { if ((tblk)->size[i] >= '0' && (tblk)->size[i] <= '7') outsize = outsize * 8 + (tblk)->size[i] - '0'; }#ifdef _POSIX_SOURCE /* convert file timestamp */ for (timestamp.modtime=0L, i=0; i < sizeof((tblk)->mtime); i++) { if ((tblk)->mtime[i] >= '0' && (tblk)->mtime[i] <= '7') timestamp.modtime = timestamp.modtime * 8 + (tblk)->mtime[i] - '0'; } timestamp.actime = timestamp.modtime; /* convert file permissions */ for (mode = i = 0; i < sizeof((tblk)->mode); i++) { if ((tblk)->mode[i] >= '0' && (tblk)->mode[i] <= '7') mode = mode * 8 + (tblk)->mode[i] - '0'; }#endif /* If we have an "only" list, and this file isn't in it, * then skip it. */ if (nonlys > 0) { for (i = 0; i < nonlys && strcmp(only[i], nbuf) && (strncmp(only[i], nbuf, strlen(only[i])) || nbuf[strlen(only[i])] != '/'); i++) { } if (i >= nonlys) { outfp = NULL; return 1; } } /* list the file */ if (VERBOSE) untar_verbose("%c %s", ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']), nbuf); else if (!QUIET) untar_verbose("%s\n", nbuf); /* if link, then do the link-or-copy thing */ if (tblk->type == '1' || tblk->type == '2') { if (VERBOSE) untar_verbose(" -> %s\n", tblk->linkto); if (!LISTING) linkorcopy(tblk->linkto, nbuf, tblk->type == '2'); outsize = 0L; return 1; } /* If directory, then make a weak attempt to create it. * Ideally we would do the "create path" thing, but that * seems like more trouble than it's worth since traditional * tar archives don't contain directories anyway. */ if (tblk->type == '5') { if (LISTING) n2 = " directory";#ifdef _POSIX_SOURCE else if (mkdir(nbuf, mode) == 0)#else else if (g_mkdir(nbuf, 0755) == 0)#endif n2 = " created"; else n2 = " ignored"; if (VERBOSE) untar_verbose("%s\n", n2); return 1; } /* if not a regular file, then skip it */ if (!ISREGULAR(*tblk)) { if (VERBOSE) untar_verbose(" ignored\n"); outsize = 0L; return 1; } /* print file statistics */ if (VERBOSE) { untar_verbose(" (%ld byte%s, %ld tape block%s)\n", outsize, outsize == 1 ? "" : "s", (outsize + TSIZE - 1) / TSIZE, (outsize > 0 && outsize <= TSIZE) ? "" : "s"); } /* if extracting, then try to create the file */ if (!LISTING) outfp = createpath(nbuf); else outfp = NULL; /* if file is 0 bytes long, then we're done already! */ if (outsize == 0 && outfp) { fclose(outfp);#ifdef _POSIX_SOURCE utime(nbuf, ×tamp); chmod(nbuf, mode);#endif } } return 1;}/* Process an archive file. This involves reading the blocks one at a time * and passing them to a untar() function. */int untar(const char *filename, const char* destdir, untar_opt options) { int ret=1; char curdir[_MAX_PATH]; untarops = options; /* open the archive */ inname = filename; infp = g_fopen(filename, "rb"); if (!infp) { untar_error("Error opening: %s\n", filename); return 0; } /* Set current directory */ if(!GetCurrentDirectory(_MAX_PATH, curdir)) { untar_error("Could not get current directory (error %d).\n", GetLastError()); fclose(infp); return 0; } if(!SetCurrentDirectory(destdir)) { untar_error("Could not set current directory to (error %d): %s\n", GetLastError(), destdir); fclose(infp); return 0; } else { /* UNCOMPRESSED */ /* send each block to the untar_block() function */ while (fread(slide, 1, TSIZE, infp) == TSIZE) { if(!untar_block(slide)) { untar_error("untar failure: %s\n", filename); fclose(infp); ret=0; } } if (outsize > 0 && ret) { untar_warning("Last file might be truncated!\n"); fclose(outfp); outfp = NULL; } if(!SetCurrentDirectory(curdir)) { untar_error("Could not set current dir back to original (error %d).\n", GetLastError()); ret=0; } } /* close the archive file. */ fclose(infp); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -