From 3340301b02ae647cdb286112c32772bda0faf503 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sat, 29 Nov 2025 01:02:02 -0500 Subject: unalf: actually use timestamps from the alf header (and add -T option to not use them). --- src/alf.1 | 8 +++++++- src/alf.c | 3 ++- src/alf.rst | 6 ++++++ src/extract.c | 34 +++++++++++++++++++++++++++++++++- src/opts.c | 3 ++- src/unalf.1 | 18 +++++++++++------- src/unalf.h | 1 + src/unalf.rst | 12 ++++++++---- 8 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/alf.1 b/src/alf.1 index 1030589..87d0a36 100644 --- a/src/alf.1 +++ b/src/alf.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "ALF" 1 "2025-11-28" "0.2.0" "Urchlay's Atari 8-bit Tools" +.TH "ALF" 1 "2025-11-29" "0.2.0" "Urchlay's Atari 8-bit Tools" .SH NAME alf \- create Atari 8-bit ALF archives .\" RST source for alf(1) man page. Convert with: @@ -151,6 +151,12 @@ systems, so there\(aqs no option for that. Note that \fBalf\fP is a complete reverse\-engineered rewrite in C, \fInot\fP a port of the original 6502 code as \fBunalf\fP is. It\(aqs still being tested, and may still contain bugs. +.sp +A note about the Atari filenames: \fBDZ.COM\fP is sometimes found on +old disk images as \fBUNALF.COM\fP, and \fBLZ.COM\fP is sometimes called +\fBALF.COM\fP or \fBALFER.COM\fP\&. I\(aqve used the original names partly +out of respect for the original author, and partly to avoid confusion +between my \fBalf\fP/\fBunalf\fP and his Atari ones. .SS File Size Limits .sp \fBalf\fP (and \fBLZ.COM\fP) have a 16MB file size limit. \fBuanlf\fP diff --git a/src/alf.c b/src/alf.c index 49e69c2..88cb316 100644 --- a/src/alf.c +++ b/src/alf.c @@ -143,7 +143,8 @@ unsigned long get_msdos_date_time(void) { msdos_year = tm->tm_year + 1900 - 1980; - ms_date = tm->tm_mday | (tm->tm_mon << 5) | (msdos_year << 9); + /* tm_mon + 1 because MS uses 1-12 for months, and struct tm uses 0-11 */ + ms_date = (tm->tm_mday) | (((tm->tm_mon + 1) << 5)) | (msdos_year << 9); ms_time = (tm->tm_sec >> 1) | (tm->tm_min << 5) | (tm->tm_hour << 11); return ms_date | (ms_time << 16); } diff --git a/src/alf.rst b/src/alf.rst index 3110180..4b011aa 100644 --- a/src/alf.rst +++ b/src/alf.rst @@ -127,6 +127,12 @@ Note that **alf** is a complete reverse-engineered rewrite in C, *not* a port of the original 6502 code as **unalf** is. It's still being tested, and may still contain bugs. +A note about the Atari filenames: **DZ.COM** is sometimes found on +old disk images as **UNALF.COM**, and **LZ.COM** is sometimes called +**ALF.COM** or **ALFER.COM**. I've used the original names partly +out of respect for the original author, and partly to avoid confusion +between my **alf**\/**unalf** and his Atari ones. + File Size Limits ---------------- diff --git a/src/extract.c b/src/extract.c index 305cd4a..6d940a2 100644 --- a/src/extract.c +++ b/src/extract.c @@ -1,5 +1,7 @@ #include "unalf.h" #include "addrs.h" +#include +#include int bad_checksum, bad_checksum_count = 0; int new_file = 0; @@ -101,6 +103,32 @@ void fix_filename(void) { } } +void set_datetime() { + u16 t, d; + struct tm tm; + time_t time; + struct utimbuf utb; + + t = dpeek(alf_hdr_time0); + d = dpeek(alf_hdr_date0); + + tm.tm_sec = (t & 0x1f) << 1; + tm.tm_hour = t >> 11; + if(tm.tm_hour == 24) tm.tm_hour = 0; + tm.tm_min = (t >> 5) & 0x3f; + + tm.tm_year = (d >> 9) + 1980 - 1900; + tm.tm_mon = ((d >> 5) & 0x0f) - 1; + tm.tm_mday = (d & 0x1f); + + time = mktime(&tm); + + if(time != (time_t) -1) { + utb.actime = utb.modtime = time; + utime(out_filename, &utb); /* ignore errors */ + } +} + void make_backup(void) { /* up to 12-char FILENAME.EXT, plus a ~, plus null terminator = 14 */ char backup[14]; @@ -162,7 +190,11 @@ void extract_alf(void) { fprintf(stderr, "%s: %s should be %u bytes, but extracted to %u.\n", self, out_filename, getquad(alf_hdr_origsize0), bytes_written); - if(!opts.extract_to_stdout) fclose(out_file); + if(!opts.extract_to_stdout) { + fclose(out_file); + if(!opts.ignore_datetime) + set_datetime(); + } out_filename = 0; } diff --git a/src/opts.c b/src/opts.c index 416163c..aca6e83 100644 --- a/src/opts.c +++ b/src/opts.c @@ -1,6 +1,6 @@ #include "unalf.h" -#define OPTIONS "aefklLopqtvVd:x:" +#define OPTIONS "aefklLopqtTvVd:x:" /* uncomment to test exclude/include glob lists */ // #define DEBUG_GLOBS @@ -44,6 +44,7 @@ void parse_opts(int argc, char * const *argv) { case 'p': opts.extract_to_stdout++; opts.quiet++; break; case 'q': opts.quiet++; break; case 't': opts.testonly++; opts.listonly = 0; break; + case 'T': opts.ignore_datetime = 1; break; case 'v': opts.listonly = 1; opts.testonly = 0; opts.verbose_list++; break; case 'V': puts(VERSION); exit(0); break; case 'd': opts.outdir = optarg; break; diff --git a/src/unalf.1 b/src/unalf.1 index a8149c5..3306279 100644 --- a/src/unalf.1 +++ b/src/unalf.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "UNALF" 1 "2025-11-28" "0.2.0" "Urchlay's Atari 8-bit Tools" +.TH "UNALF" 1 "2025-11-29" "0.2.0" "Urchlay's Atari 8-bit Tools" .SH NAME unalf \- extract Atari 8-bit ALF archives .\" RST source for unalf(1) man page. Convert with: @@ -187,13 +187,18 @@ anywhere. . .INDENT 0.0 .TP +.B \-T +Ignore timestamps in \fIalf\-file\fP, when extracting. Normally the extracted files +have their \fBmtime\fP set to the time saved in the archive. With \fB\-T\fP, the +extracted files will have \fBmtime\fP set to the current time. +.TP .B \-v Verbose listing of archive contents, with compressed and original sizes, compression ration, date/time stamps, and checksum. The output format is similar to that of \fBarc \-v\fP, minus the \fIStowage\fP column, since \fIALF\fP doesn\(aqt support multiple compression types. The date and time are displayed, but in most .alf files these are the -default values of "8 Jan 82 12:24a". +default values of "8 Jan 82 12:24:38a". .sp Unlike \fB\-l\fP, the \fB\-v\fP listing shows the filenames exactly as stored in the archive (ignores \fB\-L\fP, enables \fB\-k\fP), and always @@ -357,17 +362,16 @@ to standard output and text file EOL conversion. .IP \(bu 2 Turning the screen off for speed makes no sense on modern operating systems, so there\(aqs no option for that. +.IP \(bu 2 +The timestamps saved in the archive are actually used to set the +date/time of the extracted files (though this can be disabled with \fB\-T\fP). .UNINDENT .sp -Neither this \fBunalf\fP nor \fBDZ.COM\fP actually use the dates/times -stored in the archive. Extracted files will have their timestamps set -to the current date/time. -.sp A note about the Atari filenames: \fBDZ.COM\fP is sometimes found on old disk images as \fBUNALF.COM\fP, and \fBLZ.COM\fP is sometimes called \fBALF.COM\fP or \fBALFER.COM\fP\&. I\(aqve used the original names partly out of respect for the original author, and partly to avoid confusion -between my \fBunalf\fP and the Atari one. +between my \fBalf\fP/\fBunalf\fP and his Atari ones. .SH BUGS .sp A minor one: \fBunalf\fP can\(aqt correctly extract files larger than about diff --git a/src/unalf.h b/src/unalf.h index 743282d..2d0072e 100644 --- a/src/unalf.h +++ b/src/unalf.h @@ -83,6 +83,7 @@ typedef struct { int quiet; int verbose_list; int fixjunk; + int ignore_datetime; } opts_t; #define MAX_EXCLUDES 256 diff --git a/src/unalf.rst b/src/unalf.rst index 1c04c3b..c43d8d4 100644 --- a/src/unalf.rst +++ b/src/unalf.rst @@ -149,6 +149,11 @@ OPTIONS .. test archive. +-T + Ignore timestamps in *alf-file*, when extracting. Normally the extracted files + have their **mtime** set to the time saved in the archive. With **-T**, the + extracted files will have **mtime** set to the current time. + -v Verbose listing of archive contents, with compressed and original sizes, compression ration, date/time stamps, and checksum. The @@ -312,15 +317,14 @@ aka **UNALF.COM**, with the following differences: - Turning the screen off for speed makes no sense on modern operating systems, so there's no option for that. -Neither this **unalf** nor **DZ.COM** actually use the dates/times -stored in the archive. Extracted files will have their timestamps set -to the current date/time. +- The timestamps saved in the archive are actually used to set the + date/time of the extracted files (though this can be disabled with **-T**). A note about the Atari filenames: **DZ.COM** is sometimes found on old disk images as **UNALF.COM**, and **LZ.COM** is sometimes called **ALF.COM** or **ALFER.COM**. I've used the original names partly out of respect for the original author, and partly to avoid confusion -between my **unalf** and the Atari one. +between my **alf**\/**unalf** and his Atari ones. BUGS ==== -- cgit v1.2.3