Added callbacks to cpio to allow -h to work.
authorewt <devnull@localhost>
Tue, 6 May 1997 15:27:46 +0000 (15:27 +0000)
committerewt <devnull@localhost>
Tue, 6 May 1997 15:27:46 +0000 (15:27 +0000)
CVS patchset: 1596
CVS date: 1997/05/06 15:27:46

lib/cpio.c
lib/cpio.h
lib/install.c

index ddff7a4..7bc5541 100644 (file)
@@ -148,10 +148,7 @@ static int createDirectory(char * path) {
     struct stat sb;
     int dounlink;
 
-    if (!access(path, X_OK)) {
-       if (lstat(path, &sb))
-           return CPIO_STAT_FAILED;
-
+    if (!lstat(path, &sb)) {
        if (S_ISDIR(sb.st_mode)) {
            return 0;
        } else if (S_ISLNK(sb.st_mode)) {
@@ -240,14 +237,17 @@ static int checkDirectory(char * filename) {
     return rc;
 }
 
-static int expandRegular(struct ourfd * fd, struct cpioHeader * hdr) {
+static int expandRegular(struct ourfd * fd, struct cpioHeader * hdr,
+                        cpioCallback cb, void * cbData) {
     int out;
-    char buf[16384];
+    char buf[8192];
     int bytesRead;
     int left = hdr->size;
     int rc = 0;
+    struct cpioCallbackInfo cbInfo;
+    struct stat sb;
 
-    if (!access(hdr->path, X_OK))
+    if (!lstat(hdr->path, &sb))
        if (unlink(hdr->path))
            return CPIO_UNLINK_FAILED;
 
@@ -255,6 +255,9 @@ static int expandRegular(struct ourfd * fd, struct cpioHeader * hdr) {
     if (out < 0) 
        return CPIO_OPEN_FAILED;
 
+    cbInfo.file = hdr->path;
+    cbInfo.fileSize = hdr->size;
+
     while (left) {
        bytesRead = ourread(fd, buf, left < sizeof(buf) ? left : sizeof(buf));
        if (bytesRead <= 0) {
@@ -268,6 +271,13 @@ static int expandRegular(struct ourfd * fd, struct cpioHeader * hdr) {
        }
 
        left -= bytesRead;
+
+       /* don't call this with fileSize == fileComplete */
+       if (!rc && cb && left) {
+           cbInfo.fileComplete = hdr->size - left;
+           cbInfo.bytesProcessed = fd->pos;
+           cb(&cbInfo, cbData);
+       }
     }
 
     close(out);
@@ -277,8 +287,9 @@ static int expandRegular(struct ourfd * fd, struct cpioHeader * hdr) {
 
 static int expandSymlink(struct ourfd * fd, struct cpioHeader * hdr) {
     char buf[2048];
+    struct stat sb;
 
-    if (!access(hdr->path, X_OK))
+    if (!lstat(hdr->path, &sb))
        if (unlink(hdr->path))
            return CPIO_UNLINK_FAILED;
 
@@ -299,10 +310,7 @@ static int expandSymlink(struct ourfd * fd, struct cpioHeader * hdr) {
 static int expandFifo(struct ourfd * fd, struct cpioHeader * hdr) {
     struct stat sb;
 
-    if (!access(hdr->path, X_OK)) {
-       if (lstat(hdr->path, &sb))
-           return CPIO_STAT_FAILED;
-
+    if (!lstat(hdr->path, &sb)) {
        if (S_ISFIFO(sb.st_mode)) return 0;
 
        if (unlink(hdr->path))
@@ -316,7 +324,9 @@ static int expandFifo(struct ourfd * fd, struct cpioHeader * hdr) {
 }
 
 static int expandDevice(struct ourfd * fd, struct cpioHeader * hdr) {
-    if (!access(hdr->path, X_OK))
+    struct stat sb;
+
+    if (!lstat(hdr->path, &sb))
        if (unlink(hdr->path))
            return CPIO_UNLINK_FAILED;
 
@@ -327,7 +337,8 @@ static int expandDevice(struct ourfd * fd, struct cpioHeader * hdr) {
 }
 
 int cpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings, 
-                      int numMappings, cpioCallback cb, char ** failedFile) {
+                      int numMappings, cpioCallback cb, void * cbData,
+                      char ** failedFile) {
     struct cpioHeader ch;
     struct ourfd fd;
     int rc = 0;
@@ -335,6 +346,7 @@ int cpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings,
     struct cpioFileMapping needle;
     mode_t cpioMode;
     int olderr;
+    struct cpioCallbackInfo cbInfo;
 
     fd.fd = stream;
     fd.pos = 0;
@@ -377,7 +389,7 @@ int cpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings,
 
            if (!rc) {
                if (S_ISREG(ch.mode))
-                   rc = expandRegular(&fd, &ch);
+                   rc = expandRegular(&fd, &ch, cb, cbData);
                else if (S_ISDIR(ch.mode))
                    rc = createDirectory(ch.path);
                else if (S_ISLNK(ch.mode))
@@ -407,6 +419,15 @@ int cpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings,
        }
 
        padfd(&fd, 4);
+
+       if (!rc && cb) {
+           cbInfo.file = ch.path;
+           cbInfo.fileSize = ch.size;
+           cbInfo.fileComplete = ch.size;
+           cbInfo.bytesProcessed = fd.pos;
+           cb(&cbInfo, cbData);
+       }
+
        free(ch.path);
     } while (1 && !rc);
 
index 2105d9a..1f3b1e7 100644 (file)
@@ -39,7 +39,14 @@ struct cpioFileMapping {
     int mapFlags;
 };
 
-typedef void (*cpioCallback)(char * filespec);
+struct cpioCallbackInfo {
+    char * file;
+    long fileSize;                     /* total file size */
+    long fileComplete;                 /* amount of file unpacked */
+    long bytesProcessed;               /* bytes in archive read */
+};
+
+typedef void (*cpioCallback)(struct cpioCallbackInfo * filespec, void * data);
 
 /* If no mappings are passed, this installs everything! If one is passed
    it should be sorted according to cpioFileMapCmp() and only files included
@@ -49,7 +56,8 @@ typedef void (*cpioCallback)(char * filespec);
    for the file type. The owner/group mappings are ignored for the nonroot
    user. If *failedFile is non-NULL on return, it should be free()d. */
 int cpioInstallArchive(gzFile stream, struct cpioFileMapping * mappings, 
-                      int numMappings, cpioCallback cb, char ** failedFile);
+                      int numMappings, cpioCallback cb, void * cbData,
+                      char ** failedFile);
 
 /* This is designed to be qsort/bsearch compatible */
 int cpioFileMapCmp(const void * a, const void * b);
index a87cd81..f4616d1 100644 (file)
 enum instActions { UNKNOWN, CREATE, BACKUP, KEEP, SAVE, SKIP };
 enum fileTypes { XDIR, BDEV, CDEV, SOCK, PIPE, REG, LINK } ;
 
+struct callbackInfo {
+    unsigned long archiveSize;
+    rpmNotifyFunction notify;
+};
+
 struct fileMemory {
     char ** md5s;
     char ** links;
@@ -573,7 +578,11 @@ int rpmInstallPackage(char * rootdir, rpmdb db, int fd, char * location,
     return 0;
 }
 
-#define BLOCKSIZE 1024
+static void callback(struct cpioCallbackInfo * cpioInfo, void * data) {
+    struct callbackInfo * ourInfo = data;
+
+    ourInfo->notify(cpioInfo->bytesProcessed, ourInfo->archiveSize);
+}
 
 /* NULL files means install all files */
 static int installArchive(char * prefix, int fd, struct fileInfo * files,
@@ -583,6 +592,7 @@ static int installArchive(char * prefix, int fd, struct fileInfo * files,
     int rc, i;
     struct cpioFileMapping * map;
     char * failedFile;
+    struct callbackInfo info;
 
     if (!files) {
        /* install all files */
@@ -592,6 +602,9 @@ static int installArchive(char * prefix, int fd, struct fileInfo * files,
        return 0;
     }
 
+    info.archiveSize = archiveSize;
+    info.notify = notify;
+
     if (specFile) *specFile = NULL;
 
     map = alloca(sizeof(*map) * fileCount);
@@ -611,18 +624,23 @@ static int installArchive(char * prefix, int fd, struct fileInfo * files,
     qsort(map, fileCount, sizeof(*map), cpioFileMapCmp);
 
     stream = gzdopen(fd, "r");
-    rc = cpioInstallArchive(stream, map, fileCount, NULL, &failedFile);
+    rc = cpioInstallArchive(stream, map, fileCount, 
+                           (notify && archiveSize) ? callback : NULL, 
+                           &info, &failedFile);
 
     if (rc) {
        /* this would probably be a good place to check if disk space
           was used up - if so, we should return a different error */
-       rpmError(RPMERR_CPIO, "unpacking of archive failed on file %s: %d", 
-                failedFile, rc);
+       rpmError(RPMERR_CPIO, "unpacking of archive failed on file %s: %d: %s", 
+                failedFile, rc, strerror(errno));
        return 1;
     }
 
-    if (notify)
+    if (notify && archiveSize)
        notify(archiveSize, archiveSize);
+    else if (notify) {
+       notify(100, 100);
+    }
 
     return 0;
 }