📄 extract.c
字号:
if (data == NULL) { /* Check it... */ msg("Unexpected EOF on archive file"); break; } /* * JK - If the file is sparse, use the sparsearray * that we created before to lseek into the new * file the proper amount, and to see how many * bytes we want to write at that position. *//* if (head->header.linkflag == LF_SPARSE) { off_t pos; pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0); printf("%d at %d\n", (int) pos, sparse_ind); written = sparsearray[sparse_ind++].numbytes; } else*/ written = endofrecs()->charptr - data; if (written > size) written = size; errno = 0; check = write(fd, data, written); /* * The following is in violation of strict * typing, since the arg to userec * should be a struct rec *. FIXME. */ userec((union record *)(data + written - 1)); if (check == written) continue; /* * Error in writing to file. * Print it, skip to next file in archive. */ if(check<0) msg_perror("couldn't write to file %s",skipcrud+head->header.name); else msg("could only write %d of %d bytes to file %s",written,check,skipcrud+head->header.name); skip_file((long)(size - written)); break; /* Still do the close, mod time, chmod, etc */ } if(f_multivol) save_name = 0; /* If writing to stdout, don't try to do anything to the filename; it doesn't exist, or we don't want to touch it anyway */ if(f_exstdout) break; /* if (head->header.isextended) { register union record *exhdr; register int i; for (i = 0; i < 21; i++) { long offset; if (!exhdr->ext_hdr.sp[i].numbytes) break; offset = from_oct(1+12, exhdr->ext_hdr.sp[i].offset); written = from_oct(1+12, exhdr->ext_hdr.sp[i].numbytes); lseek(fd, offset, 0); check = write(fd, data, written); if (check == written) continue; } }*/ check = close(fd); if (check < 0) { msg_perror("Error while closing %s",skipcrud+head->header.name); } set_filestat: /* * If we are root, set the owner and group of the extracted * file. This does what is wanted both on real Unix and on * System V. If we are running as a user, we extract as that * user; if running as root, we extract as the original owner. */ if (we_are_root) { if (chown(skipcrud+head->header.name, hstat.st_uid, hstat.st_gid) < 0) { msg_perror("cannot chown file %s to uid %d gid %d",skipcrud+head->header.name,hstat.st_uid,hstat.st_gid); } } /* * If '-k' is not set, open() or creat() could have saved * the permission bits from a previously created file, * ignoring the ones we specified. * Even if -k is set, if the file has abnormal * mode bits, we must chmod since writing or chown() has * probably reset them. * * If -k is set, we know *we* created this file, so the mode * bits were set by our open(). If the file is "normal", we * skip the chmod. This works because we did umask(0) if -p * is set, so umask will have left the specified mode alone. */ if ((!f_keep) || (hstat.st_mode & (S_ISUID|S_ISGID|S_ISVTX))) { if (chmod(skipcrud+head->header.name, notumask & (int)hstat.st_mode) < 0) { msg_perror("cannot change mode of file %s to %ld",skipcrud+head->header.name,notumask & (int)hstat.st_mode); } } /* * Set the modified time of the file. * * Note that we set the accessed time to "now", which * is really "the time we started extracting files". * unless f_gnudump is used, in which case .st_atime is used */ if (!f_modified) { /* fixme if f_gnudump should set ctime too, but how? */ if(f_gnudump) acc_upd_times[0]=hstat.st_atime; else acc_upd_times[0] = now; /* Accessed now */ acc_upd_times[1] = hstat.st_mtime; /* Mod'd */ if (utime(skipcrud+head->header.name, acc_upd_times) < 0) { msg_perror("couldn't change access and modification times of %s",skipcrud+head->header.name); } } quit: break; case LF_LINK: again_link: check = link (head->header.linkname, skipcrud+head->header.name); if (check == 0) break; if (make_dirs(skipcrud+head->header.name)) goto again_link; if(f_gnudump && errno==EEXIST) break; msg_perror("Could not link %s to %s", skipcrud+head->header.name,head->header.linkname); break;#ifdef S_IFLNK case LF_SYMLINK: again_symlink: check = symlink(head->header.linkname, skipcrud+head->header.name); /* FIXME, don't worry uid, gid, etc... */ if (check == 0) break; if (make_dirs(skipcrud+head->header.name)) goto again_symlink; msg_perror("Could not create symlink to %s",head->header.linkname); break;#endif#ifdef S_IFCHR case LF_CHR: hstat.st_mode |= S_IFCHR; goto make_node;#endif#ifdef S_IFBLK case LF_BLK: hstat.st_mode |= S_IFBLK; goto make_node;#endif#ifdef S_IFIFO /* If local system doesn't support FIFOs, use default case */ case LF_FIFO: hstat.st_mode |= S_IFIFO; hstat.st_rdev = 0; /* FIXME, do we need this? */ goto make_node;#endif make_node: check = mknod(skipcrud+head->header.name, (int) hstat.st_mode, (int) hstat.st_rdev); if (check != 0) { if (make_dirs(skipcrud+head->header.name)) goto make_node; msg_perror("Could not make %s",skipcrud+head->header.name); break; }; goto set_filestat; case LF_DIR: case LF_DUMPDIR: namelen = strlen(skipcrud+head->header.name)-1; really_dir: /* Check for trailing /, and zap as many as we find. */ while (namelen && head->header.name[skipcrud+namelen] == '/') head->header.name[skipcrud+namelen--] = '\0'; if(f_gnudump) { /* Read the entry and delete files that aren't listed in the archive */ gnu_restore(skipcrud); } else if(head->header.linkflag==LF_DUMPDIR) skip_file((long)(hstat.st_size)); again_dir: check = mkdir(skipcrud+head->header.name, 0300 | (int)hstat.st_mode); if (check != 0) { if (make_dirs(skipcrud+head->header.name)) goto again_dir; /* If we're trying to create '.', let it be. */ if (head->header.name[skipcrud+namelen] == '.' && (namelen==0 || head->header.name[skipcrud+namelen-1]=='/')) goto check_perms; if(f_gnudump && errno==EEXIST) break; msg_perror("Could not make directory %s",skipcrud+head->header.name); break; } check_perms: if (0300 != (0300 & (int) hstat.st_mode)) { hstat.st_mode |= 0300; msg("Added write and execute permission to directory %s", skipcrud+head->header.name); } goto set_filestat; /* FIXME, Remember timestamps for after files created? */ /* FIXME, change mode after files created (if was R/O dir) */ case LF_VOLHDR: if(f_verbose) { printf("Reading %s\n",head->header.name); } break; case LF_MULTIVOL: msg("Can't extract '%s'--file is continued from another volume\n",head->header.name); skip_file((long)hstat.st_size); break; } /* We don't need to save it any longer. */ saverec((union record **) 0); /* Unsave it */}/* * After a file/link/symlink/dir creation has failed, see if * it's because some required directory was not present, and if * so, create all required dirs. */intmake_dirs(pathname) char *pathname;{ char *p; /* Points into path */ int madeone = 0; /* Did we do anything yet? */ int save_errno = errno; /* Remember caller's errno */ int check; if (errno != ENOENT) return 0; /* Not our problem */ for (p = index(pathname, '/'); p != NULL; p = index(p+1, '/')) { /* Avoid mkdir of empty string, if leading or double '/' */ if (p == pathname || p[-1] == '/') continue; /* Avoid mkdir where last part of path is '.' */ if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/')) continue; *p = 0; /* Truncate the path there */ check = mkdir (pathname, 0777); /* Try to create it as a dir */ if (check == 0) { /* Fix ownership */ if (we_are_root) { if (chown(pathname, hstat.st_uid, hstat.st_gid) < 0) { msg_perror("cannot change owner of %s to uid %d gid %d",pathname,hstat.st_uid,hstat.st_gid); } } pr_mkdir(pathname, p-pathname, notumask&0777); madeone++; /* Remember if we made one */ *p = '/'; continue; } *p = '/'; if (errno == EEXIST) /* Directory already exists */ continue; /* * Some other error in the mkdir. We return to the caller. */ break; } errno = save_errno; /* Restore caller's errno */ return madeone; /* Tell them to retry if we made one */}extract_sparse_file(fd, sizeleft, totalsize, name) int fd; long *sizeleft, totalsize; char *name;{ register char *data; union record *datarec; int sparse_ind = 0; int written, count; /* assuming sizeleft is initially totalsize */ while (*sizeleft > 0) { datarec = findrec(); if (datarec == NULL) { msg("Unexpected EOF on archive file"); return; } lseek(fd, sparsearray[sparse_ind].offset, 0); written = sparsearray[sparse_ind++].numbytes; while (written > RECORDSIZE) { count = write(fd, datarec->charptr, RECORDSIZE); if (count < 0) msg_perror("couldn't write to file %s", name); written -= count; *sizeleft -= count; userec(datarec); datarec = findrec(); } count = write(fd, datarec->charptr, written); if (count < 0) { msg_perror("couldn't write to file %s", name); } else if (count != written) { msg("could only write %d of %d bytes to file %s", totalsize - *sizeleft, totalsize, name); skip_file((long) (*sizeleft)); } written -= count; *sizeleft -= count; userec(datarec); } free(sparsearray);/* if (end_nulls) { register int i; printf("%d\n", (int) end_nulls); for (i = 0; i < end_nulls; i++) write(fd, "\000", 1); }*/ userec(datarec);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -