📄 ar_subs.c
字号:
if (res == 0) { if (uflag && Dflag) { if ((arcn->sb.st_mtime<=sb.st_mtime) && (arcn->sb.st_ctime<=sb.st_ctime)) continue; } else if (Dflag) { if (arcn->sb.st_ctime <= sb.st_ctime) continue; } else if (arcn->sb.st_mtime <= sb.st_mtime) continue; } } /* * this file is considered selected. See if this is a hard link * to a previous file; modify the name as requested by the * user; set the final destination. */ ftree_sel(arcn); if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0)) break; if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) { /* * skip file, purge from link table */ purg_lnk(arcn); continue; } /* * Non standard -Y and -Z flag. When the exisiting file is * same age or newer skip */ if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) { if (Yflag && Zflag) { if ((arcn->sb.st_mtime <= sb.st_mtime) && (arcn->sb.st_ctime <= sb.st_ctime)) continue; } else if (Yflag) { if (arcn->sb.st_ctime <= sb.st_ctime) continue; } else if (arcn->sb.st_mtime <= sb.st_mtime) continue; } if (vflag) { (void)fputs(arcn->name, stderr); vfpart = 1; } ++flcnt; /* * try to create a hard link to the src file if requested * but make sure we are not trying to overwrite ourselves. */ if (lflag) res = cross_lnk(arcn); else res = chk_same(arcn); if (res <= 0) { if (vflag && vfpart) { (void)putc('\n', stderr); vfpart = 0; } continue; } /* * have to create a new file */ if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) { /* * create a link or special file */ if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) res = lnk_creat(arcn); else res = node_creat(arcn); if (res < 0) purg_lnk(arcn); if (vflag && vfpart) { (void)putc('\n', stderr); vfpart = 0; } continue; } /* * have to copy a regular file to the destination directory. * first open source file and then create the destination file */ if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) { syswarn(1, errno, "Unable to open %s to read", arcn->org_name); purg_lnk(arcn); continue; } if ((fddest = file_creat(arcn)) < 0) { rdfile_close(arcn, &fdsrc); purg_lnk(arcn); continue; } /* * copy source file data to the destination file */ cp_file(arcn, fdsrc, fddest); file_close(arcn, fddest); rdfile_close(arcn, &fdsrc); if (vflag && vfpart) { (void)putc('\n', stderr); vfpart = 0; } } /* * restore directory modes and times as required; make sure all * patterns were selected block off signals to avoid chance for * multiple entry into the cleanup code. */ (void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL); ar_close(); proc_dir(); ftree_chk();}/* * next_head() * try to find a valid header in the archive. Uses format specific * routines to extract the header and id the trailer. Trailers may be * located within a valid header or in an invalid header (the location * is format specific. The inhead field from the option table tells us * where to look for the trailer). * We keep reading (and resyncing) until we get enough contiguous data * to check for a header. If we cannot find one, we shift by a byte * add a new byte from the archive to the end of the buffer and try again. * If we get a read error, we throw out what we have (as we must have * contiguous data) and start over again. * ASSUMED: headers fit within a BLKMULT header. * Return: * 0 if we got a header, -1 if we are unable to ever find another one * (we reached the end of input, or we reached the limit on retries. see * the specs for rd_wrbuf() for more details) */#if __STDC__static intnext_head(register ARCHD *arcn)#elsestatic intnext_head(arcn) register ARCHD *arcn;#endif{ register int ret; register char *hdend; register int res; register int shftsz; register int hsz; register int in_resync = 0; /* set when we are in resync mode */ int cnt = 0; /* counter for trailer function */ /* * set up initial conditions, we want a whole frmt->hsz block as we * have no data yet. */ res = hsz = frmt->hsz; hdend = hdbuf; shftsz = hsz - 1; for(;;) { /* * keep looping until we get a contiguous FULL buffer * (frmt->hsz is the proper size) */ for (;;) { if ((ret = rd_wrbuf(hdend, res)) == res) break; /* * some kind of archive read problem, try to resync the * storage device, better give the user the bad news. */ if ((ret == 0) || (rd_sync() < 0)) { warn(1,"Premature end of file on archive read"); return(-1); } if (!in_resync) { if (act == APPND) { warn(1, "Archive I/O error, cannot continue"); return(-1); } warn(1,"Archive I/O error. Trying to recover."); ++in_resync; } /* * oh well, throw it all out and start over */ res = hsz; hdend = hdbuf; } /* * ok we have a contiguous buffer of the right size. Call the * format read routine. If this was not a valid header and this * format stores trailers outside of the header, call the * format specific trailer routine to check for a trailer. We * have to watch out that we do not mis-identify file data or * block padding as a header or trailer. Format specific * trailer functions must NOT check for the trailer while we * are running in resync mode. Some trailer functions may tell * us that this block cannot contain a valid header either, so * we then throw out the entire block and start over. */ if ((*frmt->rd)(arcn, hdbuf) == 0) break; if (!frmt->inhead) { /* * this format has trailers outside of valid headers */ if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){ /* * valid trailer found, drain input as required */ ar_drain(); return(-1); } if (ret == 1) { /* * we are in resync and we were told to throw * the whole block out because none of the * bytes in this block can be used to form a * valid header */ res = hsz; hdend = hdbuf; continue; } } /* * Brute force section. * not a valid header. We may be able to find a header yet. So * we shift over by one byte, and set up to read one byte at a * time from the archive and place it at the end of the buffer. * We will keep moving byte at a time until we find a header or * get a read error and have to start over. */ if (!in_resync) { if (act == APPND) { warn(1,"Unable to append, archive header flaw"); return(-1); } warn(1,"Invalid header, starting valid header search."); ++in_resync; } bcopy(hdbuf+1, hdbuf, shftsz); res = 1; hdend = hdbuf + shftsz; } /* * ok got a valid header, check for trailer if format encodes it in the * the header. NOTE: the parameters are different than trailer routines * which encode trailers outside of the header! */ if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) { /* * valid trailer found, drain input as required */ ar_drain(); return(-1); } ++flcnt; return(0);}/* * get_arc() * Figure out what format an archive is. Handles archive with flaws by * brute force searches for a legal header in any supported format. The * format id routines have to be careful to NOT mis-identify a format. * ASSUMED: headers fit within a BLKMULT header. * Return: * 0 if archive found -1 otherwise */#if __STDC__static intget_arc(void)#elsestatic intget_arc()#endif{ register int i; register int hdsz = 0; register int res; register int minhd = BLKMULT; char *hdend; int notice = 0; /* * find the smallest header size in all archive formats and then set up * to read the archive. */ for (i = 0; ford[i] >= 0; ++i) { if (fsub[ford[i]].hsz < minhd) minhd = fsub[ford[i]].hsz; } if (rd_start() < 0) return(-1); res = BLKMULT; hdsz = 0; hdend = hdbuf; for(;;) { for (;;) { /* * fill the buffer with at least the smallest header */ i = rd_wrbuf(hdend, res); if (i > 0) hdsz += i; if (hdsz >= minhd) break; /* * if we cannot recover from a read error quit */ if ((i == 0) || (rd_sync() < 0)) goto out; /* * when we get an error none of the data we already * have can be used to create a legal header (we just * got an error in the middle), so we throw it all out * and refill the buffer with fresh data. */ res = BLKMULT; hdsz = 0; hdend = hdbuf; if (!notice) { if (act == APPND) return(-1); warn(1,"Cannot identify format. Searching..."); ++notice; } } /* * we have at least the size of the smallest header in any * archive format. Look to see if we have a match. The array * ford[] is used to specify the header id order to reduce the * chance of incorrectly id'ing a valid header (some formats * may be subsets of each other and the order would then be * important). */ for (i = 0; ford[i] >= 0; ++i) { if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0) continue; frmt = &(fsub[ford[i]]); /* * yuck, to avoid slow special case code in the extract * routines, just push this header back as if it was * not seen. We have left extra space at start of the * buffer for this purpose. This is a bit ugly, but * adding all the special case code is far worse. */ pback(hdbuf, hdsz); return(0); } /* * We have a flawed archive, no match. we start searching, but * we never allow additions to flawed archives */ if (!notice) { if (act == APPND) return(-1); warn(1, "Cannot identify format. Searching..."); ++notice; } /* * brute force search for a header that we can id. * we shift through byte at a time. this is slow, but we cannot * determine the nature of the flaw in the archive in a * portable manner */ if (--hdsz > 0) { bcopy(hdbuf+1, hdbuf, hdsz); res = BLKMULT - hdsz; hdend = hdbuf + hdsz; } else { res = BLKMULT; hdend = hdbuf; hdsz = 0; } } out: /* * we cannot find a header, bow, apologize and quit */ warn(1, "Sorry, unable to determine archive format."); return(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -