OSDN Git Service

Fix a buffer overflow bug in getbytes()
[lha/lha.git] / src / lhlist.c
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX                                                             */
3 /*              lhlist.c -- LHarc list                                      */
4 /*                                                                          */
5 /*      Copyright (C) MCMLXXXIX Yooichi.Tagawa                              */
6 /*      Modified                Nobutaka Watazaki                           */
7 /*                                                                          */
8 /*  Ver. 0.00   Original                        1988.05.23  Y.Tagawa        */
9 /*  Ver. 1.00   Fixed                           1989.09.22  Y.Tagawa        */
10 /*  Ver. 1.01   Bug Fix for month name          1989.12.25  Y.Tagawa        */
11 /*  Ver. 1.10   Changed list format             1993.10.01  N.Watazaki      */
12 /*  Ver. 1.14   Source All chagned              1995.01.14  N.Watazaki      */
13 /*  Ver. 1.14e  Bug Fix for many problems       1999.05.25  T.Okamoto       */
14 /* ------------------------------------------------------------------------ */
15 #include "lha.h"
16
17 /* ------------------------------------------------------------------------ */
18 /* Print Stuff                                                              */
19 /* ------------------------------------------------------------------------ */
20 /* need 14 or 22 (when verbose_listing is TRUE) column spaces */
21 static void
22 print_size(off_t packed_size, off_t original_size)
23 {
24 #if SIZEOF_OFF_T == 8
25     if (verbose_listing)
26         printf("%7llu ", packed_size);
27
28     printf("%7llu ", original_size);
29 #else
30     if (verbose_listing)
31         printf("%7lu ", packed_size);
32
33     printf("%7lu ", original_size);
34 #endif
35     if (original_size == 0L)
36         printf("******");
37     else    /* Changed N.Watazaki */
38         printf("%5.1f%%", packed_size * 100.0 / original_size);
39 }
40
41 /* ------------------------------------------------------------------------ */
42 /* need 12 or 17 (when verbose_listing is TRUE) column spaces */
43 static void
44 print_stamp(t)
45     time_t t;
46 {
47     static unsigned int threshold;
48     static char     t_month[12 * 3 + 1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
49     struct tm      *p;
50
51     if (t == 0) {
52         if (verbose_listing && verbose)
53             printf("                   "); /* 19 spaces */
54         else
55             printf("            "); /* 12 spaces */
56         return;
57     }
58
59     if (!threshold) {
60         time_t now = time(0);
61         p = localtime(&now);
62         threshold = p->tm_year * 12 + p->tm_mon - 6;
63     }
64
65     p = localtime(&t);
66
67     if (verbose_listing && verbose)
68         printf("%04d-%02d-%02d %02d:%02d:%02d",
69                p->tm_year+1900, p->tm_mon+1, p->tm_mday,
70                p->tm_hour, p->tm_min, p->tm_sec);
71     else if (p->tm_year * 12 + p->tm_mon > threshold)
72         printf("%.3s %2d %02d:%02d",
73         &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min);
74     else
75         printf("%.3s %2d  %04d",
76             &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900);
77 }
78
79 /* ------------------------------------------------------------------------ */
80 static void
81 print_bar()
82 {
83     if (verbose_listing) {
84         if (verbose)
85             /*      PERMISSION  UID  GID    PACKED    SIZE  RATIO METHOD CRC     STAMP            LV */
86             printf("---------- ----------- ------- ------- ------ ---------- ------------------- ---\n");
87         else
88             /*      PERMISSION  UID  GID    PACKED    SIZE  RATIO METHOD CRC     STAMP     NAME */
89             printf("---------- ----------- ------- ------- ------ ---------- ------------ ----------\n");
90     }
91     else {
92         if (verbose)
93             /*      PERMISSION  UID  GID      SIZE  RATIO     STAMP     LV */
94             printf("---------- ----------- ------- ------ ------------ ---\n");
95         else
96             /*      PERMISSION  UID  GID      SIZE  RATIO     STAMP           NAME */
97             printf("---------- ----------- ------- ------ ------------ --------------------\n");
98     }
99 }
100
101 /* ------------------------------------------------------------------------ */
102 /*                                                                          */
103 /* ------------------------------------------------------------------------ */
104 static void
105 list_header()
106 {
107     if (verbose_listing) {
108         if (verbose)
109             printf("PERMISSION  UID  GID    PACKED    SIZE  RATIO METHOD CRC     STAMP            LV\n");
110         else
111             printf("PERMISSION  UID  GID    PACKED    SIZE  RATIO METHOD CRC     STAMP     NAME\n");
112     }
113     else {
114         if (verbose)
115             printf("PERMISSION  UID  GID      SIZE  RATIO     STAMP     LV\n");
116         else
117             printf("PERMISSION  UID  GID      SIZE  RATIO     STAMP           NAME\n");
118     }
119     print_bar();
120 }
121
122 /* ------------------------------------------------------------------------ */
123 static void
124 list_one(hdr)
125     register LzHeader *hdr;
126 {
127     register int    mode = 0;
128     register char  *p;
129     char            method[6];
130     char modebits[11];
131
132     if (verbose) {
133         if ((hdr->unix_mode & UNIX_FILE_SYMLINK) != UNIX_FILE_SYMLINK)
134             printf("%s\n", hdr->name);
135         else
136             printf("%s -> %s\n", hdr->name, hdr->realname);
137     }
138
139     strncpy(method, hdr->method, 5);
140     method[5] = '\0';
141
142     switch (hdr->extend_type) {
143     case EXTEND_UNIX:
144         mode = hdr->unix_mode;
145
146         if (mode & UNIX_FILE_DIRECTORY)
147             modebits[0] = 'd';
148         else if ((mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK)
149             modebits[0] = 'l';
150         else
151             modebits[0] = '-';
152         modebits[1] = ((mode & UNIX_OWNER_READ_PERM) ? 'r' : '-');
153         modebits[2] = ((mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-');
154         modebits[3] = (mode & UNIX_SETUID) ? 's' :
155             ((mode & UNIX_OWNER_EXEC_PERM) ? 'x' : '-');
156         modebits[4] = ((mode & UNIX_GROUP_READ_PERM) ? 'r' : '-');
157         modebits[5] = ((mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-');
158         modebits[6] = (mode & UNIX_SETGID) ? 's' :
159             ((mode & UNIX_GROUP_EXEC_PERM) ? 'x' : '-');
160         modebits[7] = ((mode & UNIX_OTHER_READ_PERM) ? 'r' : '-');
161         modebits[8] = ((mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-');
162         modebits[9] = (mode & UNIX_STICKYBIT) ? 't' :
163             ((mode & UNIX_OTHER_EXEC_PERM) ? 'x' : '-');
164         modebits[10] = 0;
165
166         printf("%s ", modebits);
167         break;
168     case EXTEND_OS68K:
169      /**/ case EXTEND_XOSK:/**/
170         mode = hdr->unix_mode;
171         printf("%c%c%c%c%c%c%c%c   ",
172                ((mode & OSK_DIRECTORY_PERM) ? 'd' : '-'),
173                ((mode & OSK_SHARED_PERM) ? 's' : '-'),
174                ((mode & OSK_OTHER_EXEC_PERM) ? 'e' : '-'),
175                ((mode & OSK_OTHER_WRITE_PERM) ? 'w' : '-'),
176                ((mode & OSK_OTHER_READ_PERM) ? 'r' : '-'),
177                ((mode & OSK_OWNER_EXEC_PERM) ? 'e' : '-'),
178                ((mode & OSK_OWNER_WRITE_PERM) ? 'w' : '-'),
179                ((mode & OSK_OWNER_READ_PERM) ? 'r' : '-'));
180
181         break;
182     default:
183         switch (hdr->extend_type) { /* max 18 characters */
184         case EXTEND_GENERIC:
185             p = "[generic]";
186             break;
187         case EXTEND_CPM:
188             p = "[CP/M]";
189             break;
190         case EXTEND_FLEX:
191             p = "[FLEX]";
192             break;
193         case EXTEND_OS9:
194             p = "[OS-9]";
195             break;
196         case EXTEND_OS68K:
197             p = "[OS-9/68K]";
198             break;
199         case EXTEND_MSDOS:
200             p = "[MS-DOS]";
201             break;
202         case EXTEND_MACOS:
203             p = "[Mac OS]";
204             break;
205         case EXTEND_OS2:
206             p = "[OS/2]";
207             break;
208         case EXTEND_HUMAN:
209             p = "[Human68K]";
210             break;
211         case EXTEND_OS386:
212             p = "[OS-386]";
213             break;
214         case EXTEND_RUNSER:
215             p = "[Runser]";
216             break;
217 #ifdef EXTEND_TOWNSOS
218             /* This ID isn't fixed */
219         case EXTEND_TOWNSOS:
220             p = "[TownsOS]";
221             break;
222 #endif
223         case EXTEND_JAVA:
224             p = "[JAVA]";
225             break;
226             /* Ouch!  Please customize it's ID.  */
227         default:
228             p = "[unknown]";
229             break;
230         }
231         printf("%-11.11s", p);
232         break;
233     }
234
235     switch (hdr->extend_type) {
236     case EXTEND_UNIX:
237     case EXTEND_OS68K:
238     case EXTEND_XOSK:
239         if (hdr->user[0])
240             printf("%5.5s/", hdr->user);
241         else
242             printf("%5d/", hdr->unix_uid);
243
244         if (hdr->group[0])
245             printf("%-5.5s ", hdr->group);
246         else
247             printf("%-5d ", hdr->unix_gid);
248         break;
249     default:
250         printf("%12s", "");
251         break;
252     }
253
254     print_size(hdr->packed_size, hdr->original_size);
255
256     if (verbose_listing) {
257         if (hdr->has_crc)
258             printf(" %s %04x", method, hdr->crc);
259         else
260             printf(" %s ****", method);
261     }
262
263     printf(" ");
264     print_stamp(hdr->unix_last_modified_stamp);
265
266     if (!verbose) {
267         if ((hdr->unix_mode & UNIX_FILE_SYMLINK) != UNIX_FILE_SYMLINK)
268             printf(" %s", hdr->name);
269         else {
270             printf(" %s -> %s", hdr->name, hdr->realname);
271         }
272     }
273     if (verbose)
274         printf(" [%d]", hdr->header_level);
275     printf("\n");
276
277 }
278
279 /* ------------------------------------------------------------------------ */
280 static void
281 list_tailer(list_files, packed_size_total, original_size_total)
282     int list_files;
283     off_t packed_size_total, original_size_total;
284 {
285     struct stat     stbuf;
286
287     print_bar();
288
289     printf(" Total %9d file%c ",
290            list_files, (list_files == 1) ? ' ' : 's');
291     print_size(packed_size_total, original_size_total);
292     printf(" ");
293
294     if (verbose_listing)
295         printf("           ");
296
297     if (stat(archive_name, &stbuf) < 0)
298         print_stamp((time_t) 0);
299     else
300         print_stamp(stbuf.st_mtime);
301
302     printf("\n");
303 }
304
305 /* ------------------------------------------------------------------------ */
306 /* LIST COMMAND MAIN                                                        */
307 /* ------------------------------------------------------------------------ */
308 void
309 cmd_list()
310 {
311     FILE           *afp;
312     LzHeader        hdr;
313     int             i;
314
315     off_t packed_size_total;
316     off_t original_size_total;
317     int list_files;
318
319     /* initialize total count */
320     packed_size_total = 0L;
321     original_size_total = 0L;
322     list_files = 0;
323
324     /* open archive file */
325     if ((afp = open_old_archive()) == NULL) {
326         error("Cannot open archive \"%s\"", archive_name);
327         exit(1);
328     }
329     if (archive_is_msdos_sfx1(archive_name))
330         seek_lha_header(afp);
331
332     /* print header message */
333     if (!quiet)
334         list_header();
335
336     /* print each file information */
337     while (get_header(afp, &hdr)) {
338         if (need_file(hdr.name)) {
339             list_one(&hdr);
340             list_files++;
341             packed_size_total += hdr.packed_size;
342             original_size_total += hdr.original_size;
343         }
344
345         if (afp != stdin)
346             fseeko(afp, hdr.packed_size, SEEK_CUR);
347         else {
348             i = hdr.packed_size;
349             while (i--)
350                 fgetc(afp);
351         }
352     }
353
354     /* close archive file */
355     fclose(afp);
356
357     /* print tailer message */
358     if (!quiet)
359         list_tailer(list_files, packed_size_total, original_size_total);
360
361     return;
362 }