📄 atheos.c
字号:
}/*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) {#ifdef SHORT_NAMES char *old_end = end;#endif Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*G.end = *pathcomp++) != '\0') { ++G.end;#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(G.end = old_end + FILENAME_MAX) = '\0';#endif if ((G.end-G.buildpath) >= FILNAMSIZ) { *--G.end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; }/*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*//* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to "));#ifdef ACORN_FTYPE_NFS if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ (uO.acorn_nfs_ext ? 5 : 1)))#else if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))#endif == (char *)NULL) return MPN_NOMEM; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.end = G.buildpath; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); return MPN_OK; }/*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if necessary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/#if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { char *tmproot; if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (tmproot[G.rootlen-1] == '/') { tmproot[--G.rootlen] = '\0'; } if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* create the directory (could add loop here scanning tmproot * to create more than one level, but why really necessary?) */ if (mkdir(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", FnFilter1(tmproot))); free(tmproot); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } tmproot[G.rootlen++] = '/'; tmproot[G.rootlen] = '\0'; if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { free(tmproot); G.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; }#endif /* !SFX || SFX_EXDIR *//*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */} /* end function checkdir() */static int get_extattribs OF((__GPRO__ iztimes *pzt, ush z_uidgid[2]));static int get_extattribs(__G__ pzt, z_uidgid) __GDEF iztimes *pzt; ush z_uidgid[2];{/*--------------------------------------------------------------------------- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT time: adjust base year from 1980 to 1970, do usual conversions from yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- light savings time differences. If we have a Unix extra field, however, we're laughing: both mtime and atime are ours. On the other hand, we then have to check for restoration of UID/GID. ---------------------------------------------------------------------------*/ int have_uidgid_flg; unsigned eb_izux_flg; eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,#ifdef IZ_CHECK_TZ (G.tz_is_valid ? pzt : NULL),#else pzt,#endif z_uidgid) : 0); if (eb_izux_flg & EB_UT_FL_MTIME) { TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", pzt->mtime)); } else { pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); } if (eb_izux_flg & EB_UT_FL_ATIME) { TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", pzt->atime)); } else { pzt->atime = pzt->mtime; TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", pzt->mtime)); } /* if -X option was specified and we have UID/GID info, restore it */ have_uidgid_flg =#ifdef RESTORE_UIDGID (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));#else 0;#endif return have_uidgid_flg;}/****************************//* Function close_outfile() *//****************************/void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF{ union { iztimes t3; /* mtime, atime, ctime */ struct utimbuf t2; /* modtime, actime */ } zt; ush z_uidgid[2]; int have_uidgid_flg; fclose(G.outfile);/*--------------------------------------------------------------------------- If symbolic links are supported, allocate storage for a symlink control structure, put the uncompressed "data" and other required info in it, and add the structure to the "deferred symlinks" chain. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/#ifdef SYMLINKS if (G.symlnk) { unsigned ucsize = (unsigned)G.lrec.ucsize; unsigned AtheOSef_len = 0; extent slnk_entrysize; uch *AtheOS_exfld = NULL; slinkentry *slnk_entry; if (!uO.J_flag) { /* attributes for symlinks are supported too */ AtheOS_exfld = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (AtheOS_exfld) { AtheOSef_len = makeword(EB_LEN + AtheOS_exfld) + EB_HEADSIZE; } } slnk_entrysize = sizeof(slinkentry) + AtheOSef_len + ucsize + strlen(G.filename); if ((unsigned)slnk_entrysize < ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: mem alloc overflow\n", FnFilter1(G.filename))); return; } if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); return; } slnk_entry->next = NULL; slnk_entry->targetlen = ucsize; slnk_entry->attriblen = AtheOSef_len; slnk_entry->target = slnk_entry->buf + AtheOSef_len; slnk_entry->fname = slnk_entry->target + ucsize + 1; strcpy(slnk_entry->fname, G.filename); if (AtheOSef_len > 0) /* AtheOS_exfld should not be NULL because AtheOSef_len > 0 */ memcpy(slnk_entry->buf, AtheOS_exfld, AtheOSef_len); /* reopen the "link data" file for reading */ G.outfile = fopen(G.filename, FOPR); if (!G.outfile || fread(slnk_entry->target, 1, ucsize, G.outfile) != (int)ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); free(slnk_entry); fclose(G.outfile); return; } fclose(G.outfile); /* close "link" file for good... */ slnk_entry->target[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", FnFilter1(slnk_entry->target))); /* add this symlink record to the list of deferred symlinks */ if (G.slink_last != NULL) G.slink_last->next = slnk_entry; else G.slink_head = slnk_entry; G.slink_last = slnk_entry; return; }#endif /* SYMLINKS */ /* handle the AtheOS extra field if present */ if (!uO.J_flag) { void *ptr = scanAtheOSexfield(G.extra_field, G.lrec.extra_field_length); if (ptr) { setAtheOSexfield(G.filename, ptr); } } have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); /* if -X option was specified and we have UID/GID info, restore it */ if (have_uidgid_flg) { TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: cannot set UID %d and/or GID %d for %s\n", z_uidgid[0], z_uidgid[1], FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set UID %d and/or GID %d", z_uidgid[0], z_uidgid[1])); } } /* set the file's access and modification times */ if (utime(G.filename, &(zt.t2))) { if (uO.qflag) Info(slide, 0x201, ((char *)slide, "warning: cannot set times for %s\n", FnFilter1(G.filename))); else Info(slide, 0x201, ((char *)slide, " (warning) cannot set times")); }/*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/#ifndef NO_CHMOD if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) perror("chmod (file attributes) error");#endif} /* end function close_outfile() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -