aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-11-15 03:21:17 -0500
committerB. Watson <urchlay@slackware.uk>2025-11-15 03:21:17 -0500
commit1d45bb35abcac352f916180128bf40622ba0bc11 (patch)
tree9342f41d160ea2f5d6eabab61802a00f243e6da0 /src
parent74e2c3a2cbccc6ead2d059cc1e54ece28e26595f (diff)
downloadunalf-1d45bb35abcac352f916180128bf40622ba0bc11.tar.gz
Improve & document filename & size sanity-checking.
Diffstat (limited to 'src')
-rw-r--r--src/extract.c82
-rw-r--r--src/unalf.115
-rw-r--r--src/unalf.rst13
3 files changed, 76 insertions, 34 deletions
diff --git a/src/extract.c b/src/extract.c
index dc6a4f1..af3efeb 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -19,41 +19,23 @@ u16 dpeek(int addr) {
return mem[addr] | (mem[addr + 1] << 8);
}
-void fix_filename(void) {
- char *p;
-
- if(!out_filename) return;
-
- if(strlen(out_filename) > 12) {
- fprintf(stderr, "%s: filename in ALF header not null-terminated, fixing.\n", self);
- out_filename[12] = '\0';
- }
-
- if(opts.lowercase) {
- for(p = out_filename; *p; p++)
- *p = tolower(*p);
- }
+static void bad_atari_filename(const char *msg) {
+ char fn[50] = "";
+ char xbuf[5];
+ int i;
+ u8 c;
- if(!opts.keepdot) {
- for(p = out_filename; *p; p++)
- if(p[0] == '.' && !p[1])
- *p = '\0';
+ for(i = 0; (c = (u8)out_filename[i]) && i < 12; i++) {
+ if(c < ' ' || c > '|') {
+ /* not printable, insert a hex escape */
+ sprintf(xbuf, "$%02X", c);
+ strcat(fn, xbuf);
+ } else {
+ strncat(fn, (char *)&c, 1);
+ }
}
-}
-
-void make_backup(void) {
- /* up to 12-char FILENAME.EXT, plus a ~, plus null terminator = 14 */
- char backup[14];
- strncpy(backup, out_filename, 13);
- strncat(backup, "~", 13);
-
- /* silently ignore errors! */
- rename(out_filename, backup);
-}
-
-static void bad_atari_filename(const char *msg) {
- fprintf(stderr, "%s: bad Atari filename: %s\n", self, msg);
+ fprintf(stderr, "%s: bad Atari filename \"%s\": %s\n", self, fn, msg);
}
/* note to self: it's tempting to use isalpha(), isprint(), etc
@@ -93,6 +75,41 @@ static void sanity_check_filename(void) {
bad_atari_filename("invalid characters. corrupt ALF file?");
}
+void fix_filename(void) {
+ char *p;
+
+ if(!out_filename) return;
+
+ if(strlen(out_filename) > 12) {
+ fprintf(stderr, "%s: filename in ALF header not null-terminated, fixing.\n", self);
+ out_filename[12] = '\0';
+ }
+
+ sanity_check_filename();
+
+ if(opts.lowercase) {
+ for(p = out_filename; *p; p++)
+ *p = tolower(*p);
+ }
+
+ if(!opts.keepdot) {
+ for(p = out_filename; *p; p++)
+ if(p[0] == '.' && !p[1])
+ *p = '\0';
+ }
+}
+
+void make_backup(void) {
+ /* up to 12-char FILENAME.EXT, plus a ~, plus null terminator = 14 */
+ char backup[14];
+
+ strncpy(backup, out_filename, 13);
+ strncat(backup, "~", 13);
+
+ /* silently ignore errors! */
+ rename(out_filename, backup);
+}
+
void extract_alf(void) {
/* get ready to call fake 6502 stuff. set up memory like the Atari. */
dpoke(MEMTOP, 0xbc1f);
@@ -100,7 +117,6 @@ void extract_alf(void) {
while(read_alf_header()) {
out_filename = (char *)(mem + alf_hdr_filename);
- sanity_check_filename();
fix_filename();
if(!file_wanted(out_filename)) {
diff --git a/src/unalf.1 b/src/unalf.1
index 9303f0b..b2f918f 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-14" "0.1.0" "Urchlay's Atari 8-bit Tools"
+.TH "UNALF" 1 "2025-11-15" "0.1.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:
@@ -266,6 +266,19 @@ If you have an ALF file that does this, try it
with the Atari \fBUNALF14.COM\fP and see if it has the same problem.
If it does, you\(aqve found a bug in \fBunalf\fP, please send me the
\&.alf file via email (see \fBAUTHOR\fP, below).
+.TP
+.B \fBbad Atari filename\fP \fI<filename>\fP \fI<reason>\fP
+The filename stored in the ALF header doesn\(aqt follow the rules for
+Atari DOS filenames. \fI<reason>\fP will be something like "doesn\(aqt start
+with A\-Z" or "invalid character". The filename will be printed with
+any unprintable characters as hex values (e.g. \fB$01\fP).
+.TP
+.B \fBheader #<n> (compressed|original) size is...\fP
+Followed by "impossibly large", "suspiciously large", or "too large
+to fit on a floppy disk". May indicate a corrupt archive, or someone
+really might have created an ALF file with files this big... though
+"impossibly large" means >16MB. \fBunalf\fP can\(aqt extract a file
+that big.
.UNINDENT
.SH NOTES
.sp
diff --git a/src/unalf.rst b/src/unalf.rst
index b829bf9..2e716a1 100644
--- a/src/unalf.rst
+++ b/src/unalf.rst
@@ -221,6 +221,19 @@ Besides the standard error messages such as "no such file or directory":
If it does, you've found a bug in **unalf**, please send me the
.alf file via email (see **AUTHOR**, below).
+**bad Atari filename** *<filename>* *<reason>*
+ The filename stored in the ALF header doesn't follow the rules for
+ Atari DOS filenames. *<reason>* will be something like "doesn't start
+ with A-Z" or "invalid character". The filename will be printed with
+ any unprintable characters as hex values (e.g. **$01**).
+
+**header #<n> (compressed|original) size is...**
+ Followed by "impossibly large", "suspiciously large", or "too large
+ to fit on a floppy disk". May indicate a corrupt archive, or someone
+ really might have created an ALF file with files this big... though
+ "impossibly large" means >=16MB. **unalf** can't extract a file
+ that big.
+
NOTES
=====