From: Koji Arai Date: Sat, 3 May 2008 15:17:40 +0000 (+0900) Subject: treat timestamp in header X-Git-Url: http://git.osdn.net/view?p=lha%2Folha.git;a=commitdiff_plain;h=be7db7882fd980087e8e5c7e203262ac1dfeaf81 treat timestamp in header --- diff --git a/ar.c b/ar.c index 35319bc..ce7fa47 100644 --- a/ar.c +++ b/ar.c @@ -50,6 +50,8 @@ Structure of archive block (low order byte first): #include #include #include +#include +#include #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 --- a/ar.h +++ b/ar.h @@ -4,6 +4,7 @@ #include #include #include +#include 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; diff --git a/filelib.c b/filelib.c index 413658b..5384144 100644 --- 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) diff --git a/makefile b/makefile index d32049d..e838b49 100644 --- 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)