1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include <stdio.h>
#include <stdlib.h>
#include <f65.h>
#include "unalf.h"
#include "addrs.h"
static const char *monthnames[] = {
"???",
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec",
"???", "???", "???",
};
u16 getword(int offs) {
return mem[offs] | (mem[offs + 1] << 8);
}
unsigned int getquad(int offs) {
return getword(offs) | ((getword(offs + 2) << 16));
}
/* see Arcinfo for details */
void format_msdos_time(char *buf) {
u16 t, hour, min;
char ampm;
t = getword(alf_hdr_time0);
/* don't bother with seconds (arc doesn't print them either) */
hour = t >> 11;
min = (t >> 5) & 0x3f;
/* midnight prints as 12pm, not 12am... but 0:01 (1 min past
midnight) prints as 12:01am */
if(hour == 0 && min == 0) hour = 24;
ampm = (hour > 11 ? 'p' : 'a');
hour %= 12;
/* midnight and noon print as 12, not 0 */
if(hour == 0) hour = 12;
sprintf(buf, "%2d:%02d%c", hour, min, ampm);
}
/* see Arcinfo for details */
void format_msdos_date(char *buf) {
u16 d, year, month, day;
d = getword(alf_hdr_date0);
/* year actually ranges 1980 to 2107... */
year = (d >> 9) + 1980;
year %= 100; /* ...but only print last 2 digits */
/* valid months range 1 to 12. values 0, 13, 14, 15 are possible
but invalid (print as ???) */
month = (d >> 5) && 0x0f;
/* valid day range is 1 to 31. 0 is invalid, print as-is. */
day = d & 0x1f;
sprintf(buf, "%2d %3s %02d", day, monthnames[month], year);
}
/* small files may be "compressed" larger than the original, so this
has to return a signed type. */
static int comp_percent(unsigned int orig, unsigned int comp) {
if(orig == 0) return 0; /* no division by zero please */
return 100 - (int)((float)comp / (float)orig * 100.0);
}
/* output similar to "arc v", except we omit the compression type column
since there's only one type. also, don't call the checksum a CRC, it
isn't. */
void list_alf(void) {
unsigned int c = 0, orig_size, comp_size, total_osize = 0, total_csize = 0;
char buf[100];
char *filename;
puts("Name Length Size now Comp Date Time CkSum");
puts("============ ======== ======== ==== ========= ====== =====");
while(read_alf_header()) {
c++;
orig_size = getquad(alf_hdr_origsize0);
comp_size = getquad(alf_hdr_compsize0);
filename = (char *)(mem + alf_hdr_filename);
total_osize += orig_size;
total_csize += comp_size;
printf("%-12s ", filename);
printf("%8d ", orig_size);
printf("%8d ", comp_size);
printf("%3d%% ", comp_percent(orig_size, comp_size));
format_msdos_date(buf);
printf("%9s ", buf);
format_msdos_time(buf);
printf("%6s ", buf);
printf(" %04x", getword(alf_hdr_cksum_l));
putchar('\n');
if(fseek(in_file, comp_size, SEEK_CUR) != 0) {
fputs(self, stderr);
perror(": fseek");
exit(1);
}
}
fputs(" ==== ======== ======== ====\nTotal ", stdout);
printf("%4d ", c);
printf("%8d ", total_osize);
printf("%8d ", total_csize);
printf("%3d%% ", comp_percent(total_osize, total_csize));
putchar('\n');
}
|