OSDN Git Service

treat timestamp in header
authorKoji Arai <jca02266@gmail.com>
Sat, 3 May 2008 15:17:40 +0000 (00:17 +0900)
committerKoji Arai <jca02266@gmail.com>
Sat, 3 May 2008 15:17:40 +0000 (00:17 +0900)
ar.c
ar.h
filelib.c
makefile

diff --git a/ar.c b/ar.c
index 35319bc..ce7fa47 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -50,6 +50,8 @@ Structure of archive block (low order byte first):
 #include <errno.h>
 #include <dirent.h>
 #include <sys/stat.h>
+#include <time.h>
+#include <utime.h>
 #include "ar.h"
 
 extern char *basename(const char *);
@@ -248,6 +250,58 @@ put_char(char *buf, char *p, size_t size)
     memcpy(buf, p, size);
 }
 
+time_t
+ftime_to_time_t(uint32_t ftime)
+{
+    struct tm tm;
+    /* ftime is time structure on MS-DOS
+
+      32              24              16               8
+       7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+      |-------------|-------|---------|---------|-----------|---------|
+       year(-1980)   month   day       hour      minute      second/2
+       (1-127)       (1-12)  (1-31)    (0-23)    (0-59)      (0-29)
+    */
+
+    memset(&tm, 0, sizeof(tm));
+    tm.tm_year = (ftime >> 25) + 1980 - 1900;
+    tm.tm_mon  = ((ftime >> 21) & 0x0f) - 1;
+    tm.tm_mday = (ftime >> 16) & 0x1f;
+    tm.tm_hour = (ftime >> 11) & 0x1f;
+    tm.tm_min  = (ftime >>  5) & 0x3f;
+    tm.tm_sec  = (ftime & 0x1f) * 2;
+
+    return mktime(&tm);
+}
+
+uint32_t
+time_t_to_ftime(time_t t)
+{
+    struct tm tm;
+    uint32_t ftime;
+    /* ftime is time structure on MS-DOS
+
+    32              24              16               8
+     0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+      |-------------|-------|---------|---------|-----------|---------|
+       year(-1980)   month   day       hour      minute      second/2
+       (1-127)       (1-12)  (1-31)    (0-23)    (0-59)      (0-29)
+    */
+
+#if HAVE_LOCALTIME_R
+    localtime(&t, &tm);
+#else
+    tm = *localtime(&t);
+#endif
+
+    return (uint32_t)(tm.tm_year + 1900 - 1980) << 25
+        | (uint32_t)(tm.tm_mon + 1) << 21
+        | (uint32_t)(tm.tm_mday)    << 16
+        | (uint32_t)(tm.tm_hour)    << 11
+        | (uint32_t)(tm.tm_min)     <<  5
+        | (uint32_t)(tm.tm_sec / 2);
+}
+
 static int
 read_header_lv0(FILE *fp, char *buf, struct lzh_header *h)
 {
@@ -268,7 +322,7 @@ read_header_lv0(FILE *fp, char *buf, struct lzh_header *h)
     get_char(&buf[0], h->method, 5);
     h->compsize = get_dword(&buf[5]);
     h->origsize = get_dword(&buf[9]);
-    h->ftime    = get_dword(&buf[13]);
+    h->mtime    = ftime_to_time_t(get_dword(&buf[13]));
     /* attrib   = get_byte(&buf[17]); */
     h->level    = get_byte(&buf[18]); /* header level */
     h->namelen = get_byte(&buf[19]);
@@ -300,7 +354,7 @@ read_header_lv1(FILE *fp, char *buf, struct lzh_header *h)
     get_char(&buf[0], h->method, 5);
     h->compsize = get_dword(&buf[5]);
     h->origsize = get_dword(&buf[9]);
-    h->ftime    = get_dword(&buf[13]);
+    h->mtime    = ftime_to_time_t(get_dword(&buf[13]));
     /* attrib   = get_byte(&buf[17]); */
     h->level    = get_byte(&buf[18]); /* header level */
     h->namelen = get_byte(&buf[19]);
@@ -345,7 +399,7 @@ read_header_lv2(FILE *fp, char *buf, struct lzh_header *h)
     get_char(&buf[2], h->method, 5);
     h->compsize = get_dword(&buf[7]);
     h->origsize = get_dword(&buf[11]);
-    h->ftime    = get_dword(&buf[15]);
+    h->mtime    = get_dword(&buf[15]);
     /* attrib   = get_byte(&buf[19]); */
     h->level    = get_byte(&buf[20]); /* header level */
     h->file_crc = get_word(&buf[21]);
@@ -444,7 +498,7 @@ write_header_lv0(FILE *fp, struct lzh_header *h)
     put_char(&buf[2], h->method, 5);
     put_dword(&buf[7], h->compsize);    /* packed size */
     put_dword(&buf[11], h->origsize);   /* original size */
-    put_dword(&buf[15], h->ftime);      /* ftime */
+    put_dword(&buf[15], time_t_to_ftime(h->mtime));      /* ftime */
     put_byte(&buf[19], 0x20);           /* attribute */
     put_byte(&buf[20], 0);              /* level */
     put_byte(&buf[21], h->namelen);     /* length of pathname */
@@ -474,7 +528,7 @@ write_header_lv1(FILE *fp, struct lzh_header *h)
     put_char(&buf[2], h->method, 5);
     put_dword(&buf[7], h->compsize);    /* packed size */
     put_dword(&buf[11], h->origsize);   /* original size */
-    put_dword(&buf[15], h->ftime);      /* ftime */
+    put_dword(&buf[15], time_t_to_ftime(h->mtime));      /* ftime */
     put_byte(&buf[19], 0x20);           /* attribute */
     put_byte(&buf[20], 1);              /* level */
     put_byte(&buf[21], h->namelen);     /* length of pathname */
@@ -506,7 +560,7 @@ write_header_lv2(FILE *fp, struct lzh_header *h)
     put_char(&buf[2], h->method, 5);
     put_dword(&buf[7], h->compsize);    /* packed size */
     put_dword(&buf[11], h->origsize);   /* original size */
-    put_dword(&buf[15], h->ftime);      /* time_t */
+    put_dword(&buf[15], h->mtime);      /* time_t */
     put_byte(&buf[19], 0x20);           /* DOS attribute (0x20 fixed) */
     put_byte(&buf[20], 2);              /* level */
     put_word(&buf[21], h->file_crc);
@@ -734,6 +788,7 @@ add(int replace_flag, char *filename, int namelen)
 
     stat(h.filename, &st);
 
+    h.mtime = st.st_mtime;
     if (S_ISDIR(st.st_mode)) {
         DIR *dir;
         struct dirent *ent;
@@ -853,8 +908,14 @@ extract(int to_file, struct lzh_header *h)
 
     if (to_file) {
         fprintf(stdout, "\n");
-        if (outfile)
+        if (outfile) {
+            struct utimbuf ut;
+
             fclose(outfile);
+
+            ut.actime = ut.modtime = h->mtime;
+            utime(h->filename, &ut);
+        }
     }
     outfile = NULL;
 }
@@ -1154,8 +1215,6 @@ main(int argc, char *argv[])
 
     /* change directory to extract dir */
     if (cmd == 'x') {
-        struct stat *stbuf;
-
         if (opts.outdir) {
             if (mkdir(opts.outdir, 0777) == -1) {
                 if (errno != EEXIST)
diff --git a/ar.h b/ar.h
index 630c3fa..f9a48ef 100644 (file)
--- a/ar.h
+++ b/ar.h
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <limits.h>
+#include <sys/types.h>
 
 typedef unsigned char uchar;    /*  8 bits or more */
 typedef unsigned int uint;      /* 16 bits or more */
@@ -16,7 +17,7 @@ struct lzh_header {
     char method[5];
     int compsize;
     int origsize;
-    int ftime;
+    time_t mtime;
     int file_crc;
     char os_id;
     int level;
index 413658b..5384144 100644 (file)
--- a/filelib.c
+++ b/filelib.c
@@ -7,10 +7,10 @@
 int
 file_exists(char *file)
 {
-    struct stat stbuf;
+    struct stat st;
     int ret;
 
-    ret = stat(file, &stbuf);
+    ret = stat(file, &st);
     if (ret == 0)
         return 1;
     else if (ret == -1 && errno == ENOENT)
index d32049d..e838b49 100644 (file)
--- a/makefile
+++ b/makefile
@@ -33,7 +33,7 @@ install: $(TARGET)
        install -m 755 olha$(EXEEXT) /usr/local/bin
 
 check: $(TARGET) randtest
-       sh ./tests/lha-test.sh 2 10 3 4 5
+       sh ./tests/lha-test.sh 2 10 3 4 5 7
        sh ./test.sh
 
 t: $(TARGET)