]> git.saurik.com Git - apple/file_cmds.git/commitdiff
file_cmds-251.tar.gz os-x-1011 os-x-10111 os-x-10112 os-x-10113 os-x-10114 os-x-10115 os-x-10116 v251
authorApple <opensource@apple.com>
Thu, 9 Jul 2015 01:14:12 +0000 (01:14 +0000)
committerApple <opensource@apple.com>
Thu, 9 Jul 2015 01:14:12 +0000 (01:14 +0000)
chmod/chmod_acl.c
cp/utils.c
dd/dd.entitlements [new file with mode: 0644]
dd/install_symlink.sh [new file with mode: 0644]
df/df.c
file_cmds.xcodeproj/project.pbxproj
ipcs/ipcs.c
ls/print.c
pax/pax_format.c

index 2bb8e3916a5bfa9debf8f66ab36420908cb60bd2..34708fc0490757d726d7aac6c49368201b4b104c 100644 (file)
@@ -100,31 +100,22 @@ static struct {
 
 uuid_t *
 name_to_uuid(char *tok, int nametype) {
-       struct passwd *tpass = NULL;
-       struct group *tgrp = NULL;
        uuid_t *entryg = NULL;
+       size_t len = strlen(tok);
 
-       if ((entryg = (uuid_t *) calloc(1,sizeof(uuid_t))) == NULL)
-               err(1, "Unable to allocate a uuid");
-
-       if (nametype & NAME_USER)
-               tpass = getpwnam(tok);
-
-       if (NULL == tpass && (nametype & NAME_GROUP))
-               tgrp = getgrnam(tok);
+       if ((entryg = (uuid_t *) calloc(1, sizeof(uuid_t))) == NULL) {
+               errx(1, "Unable to allocate a uuid");
+       }
 
-       if (tpass) {
-               if (0 != mbr_uid_to_uuid(tpass->pw_uid, *entryg)) {
-                       errx(1, "mbr_uid_to_uuid(): Unable to translate uid %d", tpass->pw_uid);
-               }
-       } else if (tgrp) {
-               if (0 != mbr_gid_to_uuid(tgrp->gr_gid, *entryg)) {
-                       errx(1, "mbr_gid_to_uuid(): Unable to translate gid %d", tgrp->gr_gid);
-               }
-       } else {
-               errx(1, "Unable to translate '%s' to a UID/GID", tok);
+       if ((nametype & NAME_USER) && mbr_identifier_to_uuid(ID_TYPE_USERNAME, tok, len, *entryg) == 0) {
+               return entryg;
+       }
+       
+       if ((nametype & NAME_GROUP) && mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, tok, len, *entryg) == 0) {
+               return entryg;
        }
-       return entryg;
+       
+       errx(1, "Unable to translate '%s' to a UUID", tok);
 }
 
 /* Convert an acl entry in string form to an acl_entry_t */
index 5995672640d450281ebfce859448e99b8f5a52d0..a2d031df5fbd0c96ac585fd434b0563b68004f58 100644 (file)
@@ -358,26 +358,20 @@ setfile(struct stat *fs, int fd)
        rval = 0;
        fdval = fd != -1;
        islink = !fdval && S_ISLNK(fs->st_mode);
-       fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
-                      S_IRWXU | S_IRWXG | S_IRWXO;
+       fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
 
        TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
        TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
-#ifdef __APPLE__
-       if (islink ? 0 : utimes(to.p_path, tv)) {
-#else
-       if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
-#endif /* __APPLE__ */
-               warn("%sutimes: %s", islink ? "l" : "", to.p_path);
+       if (fdval ? futimes(fd, tv) : (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv))) {
+               warn("%sutimes: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
                rval = 1;
        }
-       if (fdval ? fstat(fd, &ts) :
-           (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
+       if (fdval ? fstat(fd, &ts) : (islink ? lstat(to.p_path, &ts) :
+                                     stat(to.p_path, &ts))) {
                gotstat = 0;
-       else {
+       else {
                gotstat = 1;
-               ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
-                             S_IRWXU | S_IRWXG | S_IRWXO;
+               ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
        }
        /*
         * Changing the ownership probably won't succeed, unless we're root
@@ -385,34 +379,37 @@ setfile(struct stat *fs, int fd)
         * the mode; current BSD behavior is to remove all setuid bits on
         * chown.  If chown fails, lose setuid/setgid bits.
         */
-       if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
-               if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
-                   (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
-                   chown(to.p_path, fs->st_uid, fs->st_gid))) {
-                       if (errno != EPERM) {
-                               warn("%schown: %s", islink ? "l" : "", to.p_path);
-                               rval = 1;
-                       }
-                       fs->st_mode &= ~(S_ISUID | S_ISGID);
-               }
+       if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) {
+               if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) : (islink ?
+                                                                 lchown(to.p_path, fs->st_uid, fs->st_gid) :
+                                                                 chown(to.p_path, fs->st_uid, fs->st_gid))) {
+                           if (errno != EPERM) {
+                                   warn("%schown: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+                                   rval = 1;
+                           }
+                           fs->st_mode &= ~(S_ISUID | S_ISGID);
+                   }
+       }
 
-       if (!gotstat || fs->st_mode != ts.st_mode)
-               if (fdval ? fchmod(fd, fs->st_mode) :
-                   (islink ? lchmod(to.p_path, fs->st_mode) :
-                   chmod(to.p_path, fs->st_mode))) {
-                       warn("%schmod: %s", islink ? "l" : "", to.p_path);
+       if (!gotstat || fs->st_mode != ts.st_mode) {
+               if (fdval ? fchmod(fd, fs->st_mode) : (islink ?
+                                                      lchmod(to.p_path, fs->st_mode) :
+                                                      chmod(to.p_path, fs->st_mode))) {
+                       warn("%schmod: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
                        rval = 1;
                }
+       }
 
-       if (!gotstat || fs->st_flags != ts.st_flags)
-               if (fdval ?
-                   fchflags(fd, fs->st_flags) :
-                   (islink ? lchflags(to.p_path, fs->st_flags) :
-                   chflags(to.p_path, fs->st_flags))) {
-                       warn("%schflags: %s", islink ? "l" : "", to.p_path);
-                       rval = 1;
+       if (!gotstat || fs->st_flags != ts.st_flags) {
+               if (fdval ? fchflags(fd, fs->st_flags) : (islink ?
+                                                         lchflags(to.p_path, fs->st_flags) :
+                                                         chflags(to.p_path, fs->st_flags))) {
+                       if (errno != EPERM) {
+                               warn("%schflags: %s", fdval ? "f" : (islink ? "l" : ""), to.p_path);
+                               rval = 1;
+                       }
                }
-
+       }
        return (rval);
 }
 
diff --git a/dd/dd.entitlements b/dd/dd.entitlements
new file mode 100644 (file)
index 0000000..abb8bc5
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.private.security.disk-device-access</key>
+       <true/>
+</dict>
+</plist>
+
diff --git a/dd/install_symlink.sh b/dd/install_symlink.sh
new file mode 100644 (file)
index 0000000..4b8cd15
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+set -e
+set -x
+
+case "$PLATFORM_NAME" in
+iphoneos|appletvos|watchos)
+    ln -hfs /usr/local/bin/dd "$DSTROOT"/bin/dd
+    ;;
+macosx)
+    ;;
+*)
+    echo "Unsupported platform: $PLATFORM_NAME"
+    exit 1
+    ;;
+esac
+
diff --git a/df/df.c b/df/df.c
index 142bbf193ff12f35a1d9b2ee2427bfac486913f5..7e576d781b8de05968fbcef810b8f1fc02ae45ba 100644 (file)
--- a/df/df.c
+++ b/df/df.c
@@ -121,7 +121,7 @@ unit_t unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
 int      bread(off_t, void *, int);
 int      checkvfsname(const char *, char **);
 char    *getmntpt(char *);
-int      longwidth(long long);
+int      int64width(int64_t);
 char    *makenetvfslist(void);
 char   **makevfslist(const char *);
 void     prthuman(struct statfs *, uint64_t);
@@ -500,8 +500,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
        if (iflag) {
                inodes = sfsp->f_files;
                used = inodes - sfsp->f_ffree;
-               (void)printf(" %*llu %*lu %4.0f%% ", mwp->iused, used,
-                   mwp->ifree, (unsigned long)sfsp->f_ffree, inodes == 0 ? 100.0 :
+               (void)printf(" %*llu %*llu %4.0f%% ", mwp->iused, used,
+                   mwp->ifree, sfsp->f_ffree, inodes == 0 ? 100.0 :
                    (double)used / (double)inodes * 100.0);
        } else
                (void)printf("  ");
@@ -522,20 +522,20 @@ update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp)
                getbsize(&dummy, &blocksize);
 
        mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname));
-       mwp->total = imax(mwp->total, longwidth(fsbtoblk(sfsp->f_blocks,
+       mwp->total = imax(mwp->total, int64width(fsbtoblk(sfsp->f_blocks,
                                                         sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
        if (sfsp->f_blocks >= sfsp->f_bfree)
-               mwp->used = imax(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
+               mwp->used = imax(mwp->used, int64width(fsbtoblk(sfsp->f_blocks -
                                                               sfsp->f_bfree, sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
-       mwp->avail = imax(mwp->avail, longwidth(fsbtoblk(sfsp->f_bavail,
+       mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail,
                                                         sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
-       mwp->iused = imax(mwp->iused, longwidth((unsigned)(sfsp->f_files - sfsp->f_ffree)));
-       mwp->ifree = imax(mwp->ifree, longwidth((unsigned)(sfsp->f_ffree)));
+       mwp->iused = imax(mwp->iused, int64width(sfsp->f_files - sfsp->f_ffree));
+       mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree));
 }
 
 /* Return the width in characters of the specified long. */
 int
-longwidth(long long val)
+int64width(int64_t val)
 {
        int len;
 
index e1155492903600f2c28c32de319372488c7ea803..eddbd0afaaca6078f915ebffdabad701fd535ce0 100644 (file)
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               0773099A1A3A4DFE00E9B4EA /* dd.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = dd.entitlements; sourceTree = "<group>"; };
                FC8A8B1214B648D7001B97AD /* chmod */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = chmod; sourceTree = BUILT_PRODUCTS_DIR; };
                FC8A8B1A14B648E0001B97AD /* chown */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = chown; sourceTree = BUILT_PRODUCTS_DIR; };
                FC8A8B2214B648E3001B97AD /* cksum */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cksum; sourceTree = BUILT_PRODUCTS_DIR; };
                FCB1BDF814B6460C0070FACB /* dd */ = {
                        isa = PBXGroup;
                        children = (
+                               0773099A1A3A4DFE00E9B4EA /* dd.entitlements */,
                                FCB1BDF914B6460C0070FACB /* args.c */,
                                FCB1BDFA14B6460C0070FACB /* conv.c */,
                                FCB1BDFB14B6460C0070FACB /* conv_tab.c */,
                                FC8A8B3514B648EA001B97AD /* Sources */,
                                FC8A8B3614B648EA001B97AD /* Frameworks */,
                                FC8A8B3714B648EA001B97AD /* CopyFiles */,
+                               72E62BA81A3A62960015FC8E /* ShellScript */,
                        );
                        buildRules = (
                        );
                FCB1BDAF14B645D00070FACB /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0600;
+                               LastUpgradeCheck = 0610;
                                ORGANIZATIONNAME = "Apple Inc.";
                        };
                        buildConfigurationList = FCB1BDB214B645D00070FACB /* Build configuration list for PBXProject "file_cmds" */;
                        shellScript = "install -d -g ${GROUP} -o ${USER} -m 0755 ${INSTALL_DIR}\ninstall -d -g ${GROUP} -o ${USER} -m 0755 ${DSTROOT}/usr/share\ninstall -d -g ${GROUP} -o ${USER} -m 0755 ${DSTROOT}/usr/share/man\ninstall -d -g ${GROUP} -o ${USER} -m 0755 ${DSTROOT}/usr/share/man/man{1,7,8}";
                        showEnvVarsInLog = 0;
                };
+               72E62BA81A3A62960015FC8E /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 8;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+                       shellPath = /bin/sh;
+                       shellScript = ". ${SRCROOT}/dd/install_symlink.sh";
+                       showEnvVarsInLog = 0;
+               };
                FC8A8C4C14B64DF9001B97AD /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 8;
                FC8A8B3914B648EA001B97AD /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CODE_SIGN_ENTITLEMENTS = dd/dd.entitlements;
+                               "CODE_SIGN_ENTITLEMENTS[sdk=macosx*]" = "";
+                               CODE_SIGN_IDENTITY = "-";
                                INSTALL_PATH = /bin;
+                               "INSTALL_PATH[sdk=appletvos]" = /usr/local/bin;
+                               "INSTALL_PATH[sdk=iphoneos*]" = /usr/local/bin;
                        };
                        name = Release;
                };
                FC8A8B6114B648EC001B97AD /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               INSTALL_MODE_FLAG = "u+s,u+rw,go-rw,a+X";
                                OTHER_CFLAGS = (
                                        "-iquote",
                                        "$(SDKROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders",
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                INSTALL_PATH = /usr/bin;
                                PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
                                VERSIONING_SYSTEM = "apple-generic";
                                WARNING_CFLAGS = (
                                        "-Wall",
index b5f6e759d4fd3cc5d0f6bc9ca76e5509612176e2..986b229efc035159435f6f882b79565bc4dbcff0 100644 (file)
@@ -117,26 +117,6 @@ usage(void)
        errx(EX_USAGE, "%s","usage: ipcs [-abcmopqstMQST]\n");
 }
 
-static int
-safe_sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen)
-{
-       int rv, sv_errno=0;
-
-       if (seteuid(0)) /* iterator needs root write access to sysctl */
-               err(1, "seteuid(0) failed");
-
-       rv = sysctlbyname(name, oldp, oldlenp, newp, newlen);
-       if (rv < 0)
-               sv_errno = errno;
-
-       if (seteuid(getuid()))
-               err(1, "seteuid(%d) failed", getuid());
-
-       if (rv < 0)
-               errno = sv_errno;
-       return rv;
-}
-
 int
 main(argc, argv)
        int     argc;
@@ -149,9 +129,6 @@ main(argc, argv)
        char    datestring[100];
        int     i;
 
-       if (seteuid(getuid()))  /* run as user */
-               err(1, "seteuid(%d) failed", getuid());
-
        while ((i = getopt(argc, argv, "MmQqSsabcoptT")) != -1)
                switch (i) {
                case 'M':
@@ -219,7 +196,7 @@ main(argc, argv)
                        ic.ipcs_data = &msginfo;
                        ic.ipcs_datalen = sizeof(msginfo);
 
-                       if (safe_sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                       if (sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
                                if (errno != EPERM) {
                                        char buffer[1024];
                                        snprintf(buffer, 1024, "sysctlbyname(IPCS_MSG_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
@@ -270,7 +247,7 @@ main(argc, argv)
 
                        memset(msqptr, 0, sizeof(*msqptr));
 
-                       while(!(safe_sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                       while(!(sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                ic.ipcs_data = msqptr;
 
                                if (msqptr->msg_qbytes != 0) {
@@ -345,7 +322,7 @@ main(argc, argv)
                        ic.ipcs_data = &shminfo;
                        ic.ipcs_datalen = sizeof(shminfo);
 
-                       if (safe_sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                       if (sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
                                if (errno != EPERM) {
                                        errx(1, "sysctlbyname(IPCS_SHM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d failed: %s\n",
                                             sizeof(ic), ic.ipcs_datalen, strerror(errno));
@@ -391,7 +368,7 @@ main(argc, argv)
                        ic.ipcs_data = shmptr;
                        memset(shmptr, 0, sizeof(*shmptr));
 
-                       while(!(safe_sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                       while(!(sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                ic.ipcs_data = shmptr; /* xnu workaround */
 
                                if (shmptr->shm_perm.mode & 0x0800) {
@@ -467,7 +444,7 @@ else
                        ic.ipcs_data = &seminfo;
                        ic.ipcs_datalen = sizeof(seminfo);
 
-                       if (safe_sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                       if (sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
                                if (errno != EPERM) {
                                        char buffer[1024];
                                        snprintf(buffer, 1024, "sysctlbyname(IPCS_SEM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
@@ -522,7 +499,7 @@ else
 
                        memset(semaptr, 0, sizeof(*semaptr));
 
-                       while(!(safe_sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                       while(!(sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                ic.ipcs_data = semaptr; /* xnu workaround */
 
                                if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0) {
index d13715695b282396448c0b60ce9ae9cf5fb446d9..b43f6b7b0cdf7bc10203c3612f39b1e08794f65b 100644 (file)
@@ -204,48 +204,35 @@ static char *
 uuid_to_name(uuid_t *uu) 
 {
 #if TARGET_OS_EMBEDDED
-  return strdup("<UNKNOWN>");
+       return strdup("<UNKNOWN>");
 #else  /* !TARGET_OS_EMBEDDED */
-  int is_gid = -1;
-  struct group *tgrp = NULL;
-  struct passwd *tpass = NULL;
-  char *name = NULL;
-  uid_t id;
-
-
+       int type;
+       char *name = NULL;
+       char *recname = NULL;
+       
 #define MAXNAMETAG (MAXLOGNAME + 6) /* + strlen("group:") */
-  name = (char *) malloc(MAXNAMETAG);
-  
-  if (NULL == name)
-         err(1, "malloc");
-
-       if (!f_numericonly) {
-  if (0 != mbr_uuid_to_id(*uu, &id, &is_gid))
-         goto errout;
+       name = (char *) malloc(MAXNAMETAG);
+       
+       if (NULL == name) {
+               err(1, "malloc");
+       }
+       
+       if (f_numericonly) {
+               goto errout;
        }
-  
-  switch (is_gid) {
-  case ID_TYPE_UID:
-         tpass = getpwuid(id);
-         if (!tpass) {
-                 goto errout;
-         }
-         snprintf(name, MAXNAMETAG, "%s:%s", "user", tpass->pw_name);
-         break;
-  case ID_TYPE_GID:
-         tgrp = getgrgid((gid_t) id);
-         if (!tgrp) {
-                 goto errout;
-         }
-         snprintf(name, MAXNAMETAG, "%s:%s", "group", tgrp->gr_name);
-         break;
-  default:
+       
+       if (mbr_identifier_translate(ID_TYPE_UUID, *uu, sizeof(*uu), ID_TYPE_NAME, (void **) &recname, &type)) {
                goto errout;
-  }
-  return name;
- errout:
-  uuid_unparse_upper(*uu, name);
-  return name;
+       }
+       
+       snprintf(name, MAXNAMETAG, "%s:%s", (type == MBR_REC_TYPE_USER ? "user" : "group"), recname);
+       free(recname);
+       
+       return name;
+errout:
+       uuid_unparse_upper(*uu, name);
+       
+       return name;
 #endif /* !TARGET_OS_EMBEDDED */
 }
 
index 3b34ca8cdd383b38dd9400eda3f461b10e26b1b9..3ac97ed41068311520863b890096fe7d6790bf3e 100644 (file)
@@ -117,6 +117,7 @@ char        *pax_list_opt_format;
 
 #define KW_PATH_CASE   0
 #define KW_SKIP_CASE   -1
+#define KW_ATIME_CASE  -2
 
 typedef struct {
        char *  name;
@@ -136,7 +137,7 @@ typedef struct {
 
 O_OPTION_TYPE o_option_table[] = {
        { "atime",      5,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
-       &atime_g,       &atime_x,       &atime_g_current,       &atime_x_current,       0,      KW_SKIP_CASE    },
+       &atime_g,       &atime_x,       &atime_g_current,       &atime_x_current,       0,      KW_ATIME_CASE   },
        { "charset",    7,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
        &charset_g,     &charset_x,     &charset_g_current,     &charset_x_current,     0,      KW_SKIP_CASE    },
        { "comment",    7,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
@@ -757,53 +758,67 @@ expand_extended_headers(ARCHD *arcn, HD_USTAR *hd)
        /* Acceleration: check during command option processing. If there are no -o
           options, and no changes from any header, do not need to run through this loop. */
           
-       current_value = NULL;
        for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
                int header_len, free_it;
-               if (!o_option_table[i].active) continue; /* deleted keywords */
+               if (!o_option_table[i].active) {
+                       continue; /* deleted keywords */
+               }
                header_len = o_option_table[i].header_len;
+               if (header_len == KW_SKIP_CASE) {
+                       continue;
+               }
                free_it = 0;
-               if (header_len >= 0) {  /* Normal keywords */
+               /* Calculate values for all non-skip keywords */
+               current_value = NULL;
+               if (o_option_table[i].x_value) {
                        current_value = *o_option_table[i].x_value;
-                       if (!current_value) {   /* No -o := */
+               }
+               if (!current_value) {   /* No -o := */
+                       if (o_option_table[i].x_value_current) {
                                current_value = *o_option_table[i].x_value_current;
-                               if (current_value) {
-                                       /* Must remove it: x header values not valid beyond this header */
-                                       *o_option_table[i].x_value_current = NULL;
-                                       free_it = 1;
-                               } else {        /* No x values, try globals */
-                                       current_value = *o_option_table[i].g_value;
-                                       if (!current_value)
-                                               current_value = *o_option_table[i].g_value_current;
-                               }
                        }
                        if (current_value) {
-                               /* Update current header with this value */
-                               /*
+                               /* Must remove it: x header values not valid beyond this header */
+                               *o_option_table[i].x_value_current = NULL;
+                               free_it = 1;
+                       } else {        /* No x values, try globals */
+                               current_value = *o_option_table[i].g_value;
+                               if (!current_value) {
+                                       current_value = *o_option_table[i].g_value_current;
+                               }
+                       }
+               }
+               if (current_value) {
+                       /* Update current header with this value */
+                       /*
                                printf ("Found current_value:%s for %s,  pids=%d\n",
-                                       current_value, o_option_table[i].name, pids);
+                        current_value, o_option_table[i].name, pids);
                                */
-                               len = strlen(current_value);
-                               if (header_len == KW_PATH_CASE) {       /* Special case for path keyword */
-                                       path_replaced = 1;
-                                       arcn->nlen = len;
-                                       strlcpy(arcn->name,current_value,sizeof(arcn->name));
+                       len = strlen(current_value);
+                       if (header_len == KW_ATIME_CASE) {
+                               time_t asecs = strtoul(current_value, NULL, 10);
+                               arcn->sb.st_atimespec.tv_sec = asecs;
+                       } else if (header_len == KW_PATH_CASE) {        /* Special case for path keyword */
+                               path_replaced = 1;
+                               arcn->nlen = len;
+                               strlcpy(arcn->name,current_value,sizeof(arcn->name));
+                       } else if (header_len >= 0) { // Skip negative values
+                               if (len > header_len) {
+                                       paxwarn(1," length of string from extended header bigger than header field:"
+                                               " THAT won't work!\n");
                                } else {
-                                       if (len > header_len) {
-                                               paxwarn(1," length of string from extended header bigger than header field:"
-                                                       " THAT won't work!\n");
-                                       } else {
-                                               char * p = (char *) myhd;
-                                               memcpy(&p[o_option_table[i].header_inx], 
-                                                       current_value, len);
-                                               if (len != header_len) {
-                                                       /* pad with ? */
-                                                       p[o_option_table[i].header_inx+len] = '\0';
-                                               }
+                                       char * p = (char *) myhd;
+                                       memcpy(&p[o_option_table[i].header_inx],
+                                              current_value, len);
+                                       if (len != header_len) {
+                                               /* pad with ? */
+                                               p[o_option_table[i].header_inx+len] = '\0';
                                        }
                                }
                        }
-                       if (free_it) free(current_value);
+                       if (free_it) {
+                               free(current_value);
+                       }
                }
        }
 
@@ -931,7 +946,10 @@ pax_rd(ARCHD *arcn, char *buf)
        arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
 #endif
        arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
-       arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+       if (arcn->sb.st_atimespec.tv_sec == 0) { // Can be set from header
+               arcn->sb.st_atime = arcn->sb.st_mtime;
+       }
+       arcn->sb.st_ctime = arcn->sb.st_mtime;
 
        /*
         * If we can find the ascii names for gname and uname in the password