Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / genisoimage / diag / dump.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)dump.c   1.24 05/05/15 joerg */
14 /*
15  * File dump.c - dump a file/device both in hex and in ASCII.
16  *
17  * Written by Eric Youngdale (1993).
18  *
19  * Copyright 1993 Yggdrasil Computing, Incorporated
20  * Copyright (c) 1999-2004 J. Schilling
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License version 2
24  * as published by the Free Software Foundation.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License along with
32  * this program; see the file COPYING.  If not, write to the Free Software
33  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35
36 #include <mconfig.h>
37 #include <stdxlib.h>
38 #include <unixstd.h>
39 #include <strdefs.h>
40 #include <utypes.h>
41
42 #include <stdio.h>
43 #include <standard.h>
44 #include <ttydefs.h>
45 #include <signal.h>
46 #include <schily.h>
47
48 #include "../scsi.h"
49 #include "../../wodim/defaults.h"
50
51 /*
52  * Note: always use these macros to avoid problems.
53  *
54  * ISO_ROUND_UP(X)      may cause an integer overflow and thus give
55  *                      incorrect results. So avoid it if possible.
56  *
57  * ISO_BLOCKS(X)        is overflow safe. Prefer this when ever it is possible.
58  */
59 #define SECTOR_SIZE     (2048)
60 #define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
61 #define ISO_BLOCKS(X)   (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
62
63 #define infile  in_image
64 FILE            *infile = NULL;
65 static  off_t           file_addr;
66 static  off_t           sec_addr = (off_t)-1;
67 static  Uchar           sector[2048];
68 #define PAGE    256
69 static  Uchar           buffer[PAGE];
70 static  Uchar           search[64];
71
72 #ifdef  USE_V7_TTY
73 static  struct sgttyb   savetty;
74 static  struct sgttyb   newtty;
75 #else
76 static  struct termios  savetty;
77 static  struct termios  newtty;
78 #endif
79
80 static void     reset_tty(void);
81 static void     set_tty(void);
82 static void     onsusp(int sig);
83 static void     crsr2(int row, int col);
84 static void     readblock(void);
85 static void     showblock(int flag);
86 static int      getbyte(void);
87 static void     usage(int excode);
88
89 static void
90 reset_tty()
91 {
92 #ifdef USE_V7_TTY
93         if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
94 #else
95 #ifdef TCSANOW
96         if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
97 #else
98         if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
99 #endif
100 #endif
101 #ifdef  USE_LIBSCHILY
102                 comerr("Cannot put tty into normal mode\n");
103 #else
104                 printf("Cannot put tty into normal mode\n");
105                 exit(1);
106 #endif
107         }
108 }
109
110 static void
111 set_tty()
112 {
113 #ifdef USE_V7_TTY
114         if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
115 #else
116 #ifdef TCSANOW
117         if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
118 #else
119         if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
120 #endif
121 #endif
122 #ifdef  USE_LIBSCHILY
123                 comerr("Cannot put tty into raw mode\n");
124 #else
125                 printf("Cannot put tty into raw mode\n");
126                 exit(1);
127 #endif
128         }
129 }
130
131
132 /*
133  * Come here when we get a suspend signal from the terminal
134  */
135 static void
136 onsusp(int sig)
137 {
138 #ifdef  SIGTTOU
139         /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
140         signal(SIGTTOU, SIG_IGN);
141 #endif
142         reset_tty();
143         fflush(stdout);
144 #ifdef  SIGTTOU
145         signal(SIGTTOU, SIG_DFL);
146         /* Send the TSTP signal to suspend our process group */
147         signal(SIGTSTP, SIG_DFL);
148         /*    sigsetmask(0);*/
149         kill(0, SIGTSTP);
150         /* Pause for station break */
151
152         /* We're back */
153         signal(SIGTSTP, onsusp);
154 #endif
155         set_tty();
156 }
157
158
159 static void
160 crsr2(int row, int col)
161 {
162         printf("\033[%d;%dH", row, col);
163 }
164
165 static void
166 readblock()
167 {
168         off_t   dpos = file_addr - sec_addr;
169
170         if (sec_addr < 0 ||
171             dpos < 0 || (dpos + sizeof (buffer)) > sizeof (sector)) {
172                 sec_addr = file_addr & ~2047;
173 #ifdef  USE_SCG
174                 readsecs(sec_addr/2048, sector, ISO_BLOCKS(sizeof (sector)));
175 #else
176                 lseek(fileno(infile), sec_addr, SEEK_SET);
177                 read(fileno(infile), sector, sizeof (sector));
178 #endif
179                 dpos = file_addr - sec_addr;
180         }
181         movebytes(&sector[dpos], buffer, sizeof (buffer));
182 }
183
184 static void
185 showblock(int flag)
186 {
187         unsigned int    k;
188         int             i;
189         int             j;
190
191         readblock();
192         if (flag) {
193                 for (i = 0; i < 16; i++) {
194                         crsr2(i+3, 1);
195                         if (sizeof (file_addr) > sizeof (long)) {
196                                 printf("%16.16llx ", (Llong)file_addr+(i<<4));
197                         } else {
198                                 printf("%8.8lx ", (long)file_addr+(i<<4));
199                         }
200                         for (j = 15; j >= 0; j--) {
201                                 printf("%2.2x", buffer[(i<<4)+j]);
202                                 if (!(j & 0x3))
203                                         printf(" ");
204                         }
205                         for (j = 0; j < 16; j++) {
206                                 k = buffer[(i << 4) + j];
207                                 if (k >= ' ' && k < 0x80)
208                                         printf("%c", k);
209                                 else
210                                         printf(".");
211                         }
212                 }
213         }
214         crsr2(20, 1);
215         if (sizeof (file_addr) > sizeof (long)) {
216                 printf(" Zone, zone offset: %14llx %12.12llx  ",
217                         (Llong)file_addr>>11, (Llong)file_addr & 0x7ff);
218         } else {
219                 printf(" Zone, zone offset: %6lx %4.4lx  ",
220                         (long)(file_addr>>11), (long)(file_addr & 0x7ff));
221         }
222         fflush(stdout);
223 }
224
225 static int
226 getbyte()
227 {
228         char    c1;
229
230         c1 = buffer[file_addr & (PAGE-1)];
231         file_addr++;
232         if ((file_addr & (PAGE-1)) == 0)
233                 showblock(0);
234         return (c1);
235 }
236
237 static void
238 usage(int excode)
239 {
240         errmsgno(EX_BAD, "Usage: %s [options] [image]\n",
241                                                 get_progname());
242
243         fprintf(stderr, "Options:\n");
244         fprintf(stderr, "\t-help, -h    Print this help\n");
245         fprintf(stderr, "\t-version     Print version info and exit\n");
246         fprintf(stderr, "\t-i filename  Filename to read ISO-9660 image from\n");
247         fprintf(stderr, "\tdev=target   SCSI target to use as CD/DVD-Recorder\n");
248         fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
249         exit(excode);
250 }
251
252 int
253 main(int argc, char *argv[])
254 {
255         int     cac;
256         char    * const *cav;
257         char    *opts = "help,h,version,i*,dev*";
258         BOOL    help = FALSE;
259         BOOL    prvers = FALSE;
260         char    *filename = NULL;
261         char    *devname = NULL;
262         char    c;
263         int     i;
264         int     j;
265
266         save_args(argc, argv);
267
268         cac = argc - 1;
269         cav = argv + 1;
270         if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
271                         &filename, &devname) < 0) {
272                 errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
273                 usage(EX_BAD);
274         }
275         if (help)
276                 usage(0);
277         if (prvers) {
278                 printf("devdump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
279                 exit(0);
280         }
281         cac = argc - 1;
282         cav = argv + 1;
283         if (filename == NULL && devname == NULL) {
284                 if (getfiles(&cac, &cav, opts) != 0) {
285                         filename = cav[0];
286                         cac--, cav++;
287                 }
288         }
289         if (getfiles(&cac, &cav, opts) != 0) {
290                 errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
291                 usage(EX_BAD);
292         }
293         if (filename != NULL && devname != NULL) {
294                 errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
295                 usage(EX_BAD);
296         }
297 #ifdef  USE_SCG
298         if (filename == NULL && devname == NULL)
299                 cdr_defaults(&devname, NULL, NULL, NULL);
300 #endif
301         if (filename == NULL && devname == NULL) {
302 #ifdef  USE_LIBSCHILY
303                 errmsgno(EX_BAD, "ISO-9660 image not specified\n");
304 #else
305                 fprintf(stderr, "ISO-9660 image not specified\n");
306 #endif
307                 usage(EX_BAD);
308         }
309
310         if (filename != NULL)
311                 infile = fopen(filename, "rb");
312         else
313                 filename = devname;
314
315         if (infile != NULL) {
316                 /* EMPTY */;
317 #ifdef  USE_SCG
318         } else if (scsidev_open(filename) < 0) {
319 #else
320         } else {
321 #endif
322 #ifdef  USE_LIBSCHILY
323                 comerr("Cannot open '%s'\n", filename);
324 #else
325                 fprintf(stderr, "Cannot open '%s'\n", filename);
326                 exit(1);
327 #endif
328         }
329
330         for (i = 0; i < 30; i++)
331                 printf("\n");
332         file_addr = (off_t)0;
333
334         /*
335          * Now setup the keyboard for single character input.
336          */
337 #ifdef USE_V7_TTY
338         if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
339 #else
340 #ifdef TCSANOW
341         if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
342 #else
343         if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
344 #endif
345 #endif
346 #ifdef  USE_LIBSCHILY
347                 comerr("Stdin must be a tty\n");
348 #else
349                 printf("Stdin must be a tty\n");
350                 exit(1);
351 #endif
352         }
353         newtty = savetty;
354 #ifdef USE_V7_TTY
355         newtty.sg_flags  &= ~(ECHO|CRMOD);
356         newtty.sg_flags  |= CBREAK;
357 #else
358         newtty.c_lflag   &= ~ICANON;
359         newtty.c_lflag   &= ~ECHO;
360         newtty.c_cc[VMIN] = 1;
361 #endif
362         set_tty();
363 #ifdef  SIGTSTP
364         signal(SIGTSTP, onsusp);
365 #endif
366         on_comerr((void(*)(int, void *))reset_tty, NULL);
367
368         do {
369                 if (file_addr < (off_t)0) file_addr = (off_t)0;
370                 showblock(1);
371                 read(STDIN_FILENO, &c, 1); /* FIXME: check return value */
372                 if (c == 'a')
373                         file_addr -= PAGE;
374                 if (c == 'b')
375                         file_addr += PAGE;
376                 if (c == 'g') {
377                         crsr2(20, 1);
378                         printf("Enter new starting block (in hex):");
379                         if (sizeof (file_addr) > sizeof (long)) {
380                                 Llong   ll;
381                                 scanf("%llx", &ll); /* FIXME: check return value */
382                                 file_addr = (off_t)ll;
383                         } else {
384                                 long    l;
385                                 scanf("%lx", &l); /* FIXME: check return value */
386                                 file_addr = (off_t)l;
387                         }
388                         file_addr = file_addr << 11;
389                         crsr2(20, 1);
390                         printf("                                     ");
391                 }
392                 if (c == 'f') {
393                         crsr2(20, 1);
394                         printf("Enter new search string:");
395                         fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */
396                         while (search[strlen((char *)search)-1] == '\n')
397                                 search[strlen((char *)search)-1] = 0;
398                         crsr2(20, 1);
399                         printf("                                     ");
400                 }
401                 if (c == '+') {
402                         while (1 == 1) {
403                                 int     slen;
404
405                                 while (1 == 1) {
406                                         c = getbyte();
407                                         if (c == search[0])
408                                                 break;
409                                 }
410                                 slen = (int)strlen((char *)search);
411                                 for (j = 1; j < slen; j++) {
412                                         if (search[j] != getbyte())
413                                                 break;
414                                 }
415                                 if (j == slen)
416                                         break;
417                         }
418                         file_addr &= ~(PAGE-1);
419                         showblock(1);
420                 }
421                 if (c == 'q')
422                         break;
423         } while (1 == 1);
424         reset_tty();
425         if (infile != NULL)
426                 fclose(infile);
427         return (0);
428 }