14
14
along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
15
16
16
#include <time.h>
17
+ #include <ctype.h>
17
18
#include <utime.h>
18
19
#include <stdio.h>
19
20
#include <errno.h>
@@ -42,7 +43,9 @@ static const char *type_name[] =
42
43
43
44
#define MAX 518
44
45
static word_t block [MAX ];
46
+ static word_t * data = & block [6 ];
45
47
static int extract = 0 ;
48
+ static word_t tape_flags = 0 ;
46
49
47
50
static FILE * list ;
48
51
static FILE * info ;
@@ -58,8 +61,7 @@ static int tape_number;
58
61
static int file_number ;
59
62
static int page_number ;
60
63
static int record_number ;
61
- static int bfmsg = 3 ;
62
- static int format = 4 ;
64
+ static int format ;
63
65
64
66
/*
65
67
Format:
@@ -167,7 +169,7 @@ close_file (void)
167
169
utimes (file_path , timestamp );
168
170
}
169
171
170
- /* Convert WAITS file name to an acceptable Unix name. */
172
+ /* Convert TENEX file name to an acceptable Unix name. */
171
173
static char *
172
174
mangle (char * string )
173
175
{
@@ -184,6 +186,18 @@ mangle (char *string)
184
186
return string ;
185
187
}
186
188
189
+ static char *
190
+ upcase (char * string )
191
+ {
192
+ char * p = string ;
193
+ while (* p )
194
+ {
195
+ * p = toupper (* p );
196
+ p ++ ;
197
+ }
198
+ return string ;
199
+ }
200
+
187
201
static char *
188
202
find (char * * string , const char * required , char * fail )
189
203
{
@@ -216,7 +230,7 @@ find (char **string, const char *required, char *fail)
216
230
/* Convert a file name from the command line to a TOPS-20 file name. */
217
231
static const char *
218
232
unmangle (char * file_name , char * device , char * name ,
219
- int protection , const char * author )
233
+ int protection , const char * author , int * generation )
220
234
{
221
235
char original_name [100 ];
222
236
char * directories [100 ];
@@ -230,28 +244,36 @@ unmangle (char *file_name, char *device, char *name,
230
244
* d = find (& name , "/" , NULL );
231
245
while (* d ++ != NULL );
232
246
233
- if (d - directories > 1 && format == 0 )
247
+ if (d - directories > 2 && format == 0 )
234
248
return "TENEX doesn't support subdirectories" ;
235
249
236
250
file = find (& name , "." , name );
237
251
type = find (& name , ".;" , name );
238
252
version = find (& name , ";" , name );
253
+ if (version )
254
+ {
255
+ char * end ;
256
+ long x = strtol (version , & end , 10 );
257
+ if (end > version )
258
+ * generation = x ;
259
+ }
239
260
240
261
if (device )
241
262
file_name += sprintf (file_name , "%s:" , device );
242
263
if (directories [0 ] != NULL )
243
264
{
244
265
file_name += sprintf (file_name , "<" );
245
266
for (d = & directories [0 ]; * d != NULL ; d ++ , sep = "." )
246
- file_name += sprintf (file_name , "%s%s" , sep , * d );
267
+ file_name += sprintf (file_name , "%s%s" , sep , upcase ( * d ) );
247
268
file_name += sprintf (file_name , ">" );
248
269
}
249
270
if (file )
250
- file_name += sprintf (file_name , "%s" , file );
271
+ file_name += sprintf (file_name , "%s" , upcase (file ));
272
+ file_name += sprintf (file_name , "." );
251
273
if (type )
252
- file_name += sprintf (file_name , ". %s" , type );
253
- if ( version )
254
- file_name += sprintf ( file_name , "%c%s" , format == 0 ? ';' : '.' , version );
274
+ file_name += sprintf (file_name , "%s" , upcase ( type ) );
275
+ file_name += sprintf ( file_name , "%c%u" ,
276
+ format == 0 ? ';' : '.' , * generation );
255
277
file_name += sprintf (file_name , ";P%06o" , protection );
256
278
if (author )
257
279
file_name += sprintf (file_name , ";A%s" , author );
@@ -409,11 +431,11 @@ read_tape_header (FILE *f, word_t word)
409
431
410
432
word = read_record (f , word );
411
433
412
- //fprintf (stderr, "006: %012llo format\n", block[6 ]);
434
+ //fprintf (stderr, "006: %012llo format\n", data[0 ]);
413
435
414
- read_asciz (name , & block [ 9 ]);
436
+ read_asciz (name , & data [ 3 ]);
415
437
fprintf (stderr , "DUMPER tape #%d, %s, " , right (block [2 ]), name );
416
- print_timestamp (stderr , block [ 8 ]);
438
+ print_timestamp (stderr , data [ 2 ]);
417
439
fputc ('\n' , stderr );
418
440
419
441
return word ;
@@ -428,7 +450,7 @@ read_file (int offset)
428
450
if (offset != 0206 )
429
451
return ;
430
452
431
- read_asciz (name , & block [ 6 ]);
453
+ read_asciz (name , & data [ 0 ]);
432
454
p = strchr (name , ';' );
433
455
if (p )
434
456
* p = 0 ;
@@ -440,7 +462,7 @@ read_file (int offset)
440
462
(block [offset + 011 ] >> 24 ) & 077 );
441
463
442
464
#if 0
443
- fprintf (stderr , "006: %012llo file name\n" , block [ 6 ]);
465
+ fprintf (stderr , "006: %012llo file name\n" , data [ 0 ]);
444
466
fprintf (stderr , "Timestamp, last write: " );
445
467
print_timestamp (stderr , block [offset + 5 ]);
446
468
fputc ('\n' , stderr );
@@ -529,28 +551,42 @@ write_asciz (const char *string, word_t *data)
529
551
}
530
552
531
553
static void
532
- write_record (FILE * f , int type , word_t flags )
554
+ write_mark (void )
555
+ {
556
+ tape_flags = START_FILE ;
557
+ }
558
+
559
+ static void
560
+ write_record (FILE * f , int type )
533
561
{
534
562
word_t checksum = 0 ;
535
563
int i ;
536
564
537
- fprintf (stderr , "\nWrite record %s" , type_name [type ]);
565
+ if (tape_flags & START_FILE )
566
+ fprintf (debug , "\nWrite mark" );
567
+
568
+ fprintf (debug , "\nWrite record %s" , type_name [type ]);
569
+
570
+ memset (block , 0 , 6 * sizeof (word_t ));
538
571
539
- block [1 ] = 0 ;
540
572
block [2 ] = (saveset_number << 18 ) | tape_number ;
573
+ if (format > 0 )
574
+ block [2 ] |= saveset_number ;
541
575
block [3 ] = page_number ;
542
- fprintf (stderr , ", page %d" , page_number );
576
+ fprintf (debug , ", page %d, record %d " , page_number , record_number );
543
577
if (0 )
544
578
block [3 ] |= file_number << 18 ;
545
579
block [4 ] = (- type ) & 0777777777777LL ;
546
580
block [5 ] = record_number ++ ;
547
581
548
582
for (i = 0 ; i < MAX ; i ++ )
549
583
checksum = sum (checksum , block [i ]);
550
- block [0 ] = (checksum ^ 0777777777777LL ) | START_RECORD | flags ;
584
+ block [0 ] = (checksum ^ 0777777777777LL ) | START_RECORD | tape_flags ;
585
+ tape_flags = 0 ;
551
586
552
- for (i = 0 ; i < MAX ; i ++ )
553
- write_word (f , block [i ]);
587
+ write_word (f , block [0 ]);
588
+ for (i = 1 ; i < MAX ; i ++ )
589
+ write_word (f , block [i ] & 0777777777777LL );
554
590
555
591
memset (block , 0 , sizeof block );
556
592
}
@@ -562,7 +598,7 @@ get_page (FILE *f)
562
598
int ok = 0 ;
563
599
int i ;
564
600
565
- memset (block + 6 , 0 , 512 * sizeof (word_t ));
601
+ memset (data , 0 , 512 * sizeof (word_t ));
566
602
567
603
/* If the first word indicates EOF, return "no page".
568
604
In other cases, return a partial or full page. */
@@ -571,7 +607,7 @@ get_page (FILE *f)
571
607
word = get_word (f );
572
608
if (word == -1 )
573
609
return ok ;
574
- block [ 6 + i ] = word ;
610
+ data [ i ] = word ;
575
611
ok = 1 ;
576
612
}
577
613
@@ -607,11 +643,11 @@ write_file (FILE *f, char *name)
607
643
generation = 1 ;
608
644
author = "OPERATOR" ;
609
645
610
- error = unmangle (file_name , device , name , protection , author );
646
+ error = unmangle (file_name , device , name , protection , author , & generation );
611
647
if (error )
612
- fprintf (debug , "\nERROR: Bad file name \"%s\": %s" , file_name , error );
648
+ fprintf (stderr , "\nERROR: Bad file name \"%s\": %s" , file_name , error );
613
649
else
614
- fprintf (debug , "\nFILE: %s" , file_name );
650
+ fprintf (list , "\n %s" , file_name );
615
651
616
652
memset (fdb , 0 , sizeof fdb );
617
653
//000 //header word
@@ -626,67 +662,83 @@ write_file (FILE *f, char *name)
626
662
fdb [013 ] = tops20_timestamp (st .st_ctime ); //timestamp: creation
627
663
fdb [014 ] = tops20_timestamp (st .st_mtime ); //timestamp: last user write
628
664
fdb [015 ] = tops20_timestamp (st .st_atime ); //timestamp: last nonwrite access
629
-
630
- write_asciz (file_name , block + 6 );
631
- memcpy (block + 0206 , fdb , sizeof fdb );
665
+ write_asciz (file_name , data );
666
+ memcpy (data + 0200 , fdb , sizeof fdb );
632
667
page_number = 0 ;
633
- write_record (f , FLHD , 0 );
668
+ write_record (f , FLHD );
634
669
635
670
while (get_page (input ))
636
671
{
637
- write_record (f , DATA , 0 );
672
+ write_record (f , DATA );
638
673
page_number ++ ;
639
674
}
640
675
fclose (input );
641
676
642
- memcpy (block + 6 , fdb , sizeof fdb );
677
+ memcpy (data , fdb , sizeof fdb );
643
678
page_number = 0 ;
644
- write_record (f , FLTR , 0 );
679
+ write_record (f , FLTR );
680
+ if (format == 0 )
681
+ write_mark ();
645
682
}
646
683
647
684
static void
648
685
write_usr (FILE * f )
649
686
{
650
- write_record (f , USR , 0 );
687
+ write_record (f , USR );
651
688
}
652
689
653
690
static void
654
691
write_tape (FILE * f )
655
692
{
656
- int i ;
657
693
struct word_format * tmp = input_word_format ;
658
694
input_word_format = output_word_format ;
659
695
output_word_format = tmp ;
696
+ int i , bfmsg = 0 ;
660
697
661
698
if (f == NULL )
662
699
f = stdout ;
663
700
664
701
saveset_number = 0 ;
665
702
tape_number = 1 ;
666
703
file_number = 1 ;
667
- record_number = 1 ;
668
704
669
- block [6 ] = format ;
670
- block [7 ] = bfmsg ;
671
- block [8 ] = tops20_timestamp (time (NULL ));
672
- write_asciz ("Saveset name" , block + 6 + bfmsg );
673
- write_record (f , TPHD , START_FILE );
705
+ if (format == 0 )
706
+ {
707
+ record_number = 2 ;
708
+ }
709
+ else
710
+ {
711
+ record_number = 1 ;
712
+ data [bfmsg ++ ] = format ;
713
+ bfmsg ++ ;
714
+ data [bfmsg ++ ] = tops20_timestamp (time (NULL ));
715
+ data [1 ] = bfmsg ;
716
+ }
717
+ write_asciz ("Saveset name" , data + bfmsg );
718
+
719
+ write_record (f , TPHD );
720
+ if (format == 0 )
721
+ {
722
+ write_mark ();
723
+ record_number ++ ;
724
+ }
674
725
675
726
for (i = 0 ; i < file_argc ; i ++ )
676
727
{
677
728
write_file (f , file_argv [i ]);
678
729
file_number ++ ;
679
730
}
680
731
681
- write_record (f , TPTR , 0 );
732
+ write_record (f , TPTR );
733
+ write_mark ();
682
734
flush_word (f );
683
735
}
684
736
685
737
static void
686
738
usage (const char * x )
687
739
{
688
740
fprintf (stderr ,
689
- "Usage: %s -c|-t|-x [-v789 ] [-Wformat] [-Cdir] [-f file]\n" , x );
741
+ "Usage: %s -c|-t|-x [-v0123456 ] [-Wformat] [-Cdir] [-f file]\n" , x );
690
742
usage_word_format ();
691
743
exit (1 );
692
744
}
@@ -716,6 +768,14 @@ main (int argc, char **argv)
716
768
list = stdout ;
717
769
info = debug = stderr ;
718
770
771
+ /* If the program is called mini-something, default to mini-dumper
772
+ format. Otherwise go with format 4 which is acceptable to a wide
773
+ range of DUMPER versions. */
774
+ if (strncasecmp (argv [0 ], "mini" , 4 ) == 0 )
775
+ format = 0 ;
776
+ else
777
+ format = 4 ;
778
+
719
779
while ((opt = getopt (argc , argv , "ctvx012379f:W:C:" )) != -1 )
720
780
{
721
781
switch (opt )
0 commit comments