aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-11-27 19:14:50 -0500
committerB. Watson <urchlay@slackware.uk>2025-11-27 19:14:50 -0500
commit0a1b08e58e1ef9a5d60295deb4bf158562718909 (patch)
tree4775128dfa048e1bbb07aca75f935d518b4c2dda
parent8aec307634ac63cf88e77df0e48fde1de0649b03 (diff)
downloadunalf-0a1b08e58e1ef9a5d60295deb4bf158562718909.tar.gz
Add -f (fix EOF junk) option to unalf.
-rw-r--r--TODO.txt2
-rw-r--r--src/io.c19
-rw-r--r--src/opts.c3
-rw-r--r--src/unalf.19
-rw-r--r--src/unalf.h1
-rw-r--r--src/unalf.rst7
-rw-r--r--src/usage.c1
7 files changed, 35 insertions, 7 deletions
diff --git a/TODO.txt b/TODO.txt
index fa913d8..12c3fbf 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,5 +1,3 @@
-- unalf -f option (fix, by removing the junk at EOF if found)
-
- rename project. calling it "unalf" when it contains both alf and
unalf is confusing. think of a good name first.
diff --git a/src/io.c b/src/io.c
index 4e20505..53bc0dd 100644
--- a/src/io.c
+++ b/src/io.c
@@ -14,8 +14,16 @@ static void die_not_alf(void) {
exit(1);
}
-static void eof_junk(void) {
- fprintf(stderr, "%s: junk at EOF (ignoring)\n", self);
+/* truncating the file by name could be a race condition, but I don't
+ think it's going to be a real-world problem for anyone. */
+static void eof_junk(long pos) {
+ fprintf(stderr, "%s: junk at EOF (%s)\n", self, opts.fixjunk ? "removing" : "ignoring");
+ if(opts.fixjunk) {
+ if(truncate(in_filename, pos) < 0) {
+ fprintf(stderr, "%s: could not remove junk: ", self);
+ perror(in_filename);
+ }
+ }
}
static void check_hdr_size(const char *name, unsigned long size) {
@@ -49,6 +57,9 @@ static void sanity_check_header(void) {
int read_alf_header(void) {
u8 h1, h2;
int bytes;
+ long read_pos;
+
+ read_pos = ftell(in_file);
bytes = fread(mem + alf_header, 1, 29, in_file);
@@ -59,7 +70,7 @@ int read_alf_header(void) {
die_not_alf();
} else if(bytes < 29) {
if(headers_read) {
- eof_junk();
+ eof_junk(read_pos);
return 0;
} else {
die_not_alf();
@@ -79,7 +90,7 @@ int read_alf_header(void) {
}
if(headers_read)
- eof_junk();
+ eof_junk(read_pos);
else
die_not_alf();
diff --git a/src/opts.c b/src/opts.c
index 58a13c2..416163c 100644
--- a/src/opts.c
+++ b/src/opts.c
@@ -1,6 +1,6 @@
#include "unalf.h"
-#define OPTIONS "aeklLopqtvVd:x:"
+#define OPTIONS "aefklLopqtvVd:x:"
/* uncomment to test exclude/include glob lists */
// #define DEBUG_GLOBS
@@ -37,6 +37,7 @@ void parse_opts(int argc, char * const *argv) {
case 'a': opts.txtconv++; break;
case 'e': opts.listonly = opts.testonly = 0; break;
case 'k': opts.keepdot++; break;
+ case 'f': opts.fixjunk++; opts.testonly = 1; opts.listonly = 0; opts.quiet = 1; break;
case 'l': opts.listonly++; opts.testonly = 0; break;
case 'L': opts.lowercase++; break;
case 'o': opts.overwrite++; break;
diff --git a/src/unalf.1 b/src/unalf.1
index 396a5f6..36b7802 100644
--- a/src/unalf.1
+++ b/src/unalf.1
@@ -102,6 +102,15 @@ default action.
.
.INDENT 0.0
.TP
+.B \-f
+Fix (remove) junk at EOF. This option truncates the \fIalf\-file\fP\&.
+It is the only \fBunalf\fP option that writes to the input file. No
+backup is made.
+.UNINDENT
+.\" fix (remove) junk at EOF.
+.
+.INDENT 0.0
+.TP
.B \-h\fP,\fB \-\-help
Show built\-in help message.
.UNINDENT
diff --git a/src/unalf.h b/src/unalf.h
index 1cb71bf..743282d 100644
--- a/src/unalf.h
+++ b/src/unalf.h
@@ -82,6 +82,7 @@ typedef struct {
int extract_to_stdout;
int quiet;
int verbose_list;
+ int fixjunk;
} opts_t;
#define MAX_EXCLUDES 256
diff --git a/src/unalf.rst b/src/unalf.rst
index 24774e6..c6ad52c 100644
--- a/src/unalf.rst
+++ b/src/unalf.rst
@@ -82,6 +82,13 @@ OPTIONS
.. extract files (redundant; this is the default action).
+-f
+ Fix (remove) junk at EOF. This option truncates the *alf-file*.
+ It is the only **unalf** option that writes to the input file. No
+ backup is made.
+
+.. fix (remove) junk at EOF.
+
-h, --help
Show built-in help message.
diff --git a/src/usage.c b/src/usage.c
index 9808f35..f25e707 100644
--- a/src/usage.c
+++ b/src/usage.c
@@ -2,6 +2,7 @@ const char *usage_msg[] = {
" -a: convert EOLs and tabs in text files.",
" -d output-dir: set output directory (created if needed).",
" -e: extract files (redundant; this is the default action).",
+ " -f: fix (remove) junk at EOF.",
" -h, --help: show this help message.",
" -k: keep trailing periods (dots) in filenames.",
" -l: list files in archive (filenames only).",