* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
static char sccsid
[] = "@(#)arff.c 5.4 (Berkeley) %G%";
u_short rt_yr
:5; /* year-1972 */
u_short rt_dy
:5; /* day */
u_short rt_mo
:5; /* month */
char rt_pad
; /* unusued */
u_char rt_stat
; /* type of entry, or end of seg */
u_short rt_name
[3]; /* name, 3 words in rad50 form */
u_short rt_len
; /* length of file */
u_char rt_chan
; /* only used in temporary files */
char rt_job
; /* only used in temporary files */
struct rt_dat rt_date
; /* creation date */
#define RT_PFILE (0200|RT_FILE) /* protected file */
#define RT_BLOCK 512 /* block size */
#define RT_DIRSIZE 31 /* max # of directory segments */
short rt_numseg
; /* # of segments available */
short rt_nxtseg
; /* # of next logical segment */
short rt_lstseg
; /* highest seg currently open */
u_short rt_entpad
; /* extra words/directory entry */
short rt_stfile
; /* block # where files begin */
struct rt_head rt_axhead
;
struct rt_ent rt_ents
[72];
#define rd_numseg rt_axhead.rt_numseg
#define rd_nxtseg rt_axhead.rt_nxtseg
#define rd_lstseg rt_axhead.rt_lstseg
#define rd_entpad rt_axhead.rt_entpad
#define rd_stfile rt_axhead.rt_stfile
#define rt(p) ((struct rt_ent *) p )
#define flag(c) (flg[('c') - 'a'])
struct rt_dir rt_dir
[RT_DIRSIZE
] = {
{ { 0, RT_NULL
, { 0, 0, 0 }, 486, 0 },
struct rt_dir rt_nulldir
= {
{ { 0, RT_NULL
, { 0, 0, 0 }, 0, 0 },
struct rt_ent
*rt_curend
[RT_DIRSIZE
];
char *defdev
= "/dev/floppy";
int rcmd(), dcmd(), xcmd(), tcmd();
for (cp
= argv
[1]; *cp
; cp
++)
fprintf(stderr
, "arff: bad option `%c'\n", *cp
);
fprintf(stderr
, "arff: one of [%s] must be specified\n",
fprintf(stderr
, "arff: only one of [%s] allowed\n", man
);
fprintf(stderr
, "usage: ar [%s][%s] archive files ...\n", opt
, man
);
for (i
= 0; i
< namc
; i
++)
fprintf(stderr
, "arff: %s not found\n", namv
[i
]);
register char *de
, *last
;
register struct rt_ent
*rde
;
for (i
= 0; i
< namc
; i
++)
if (dope
= lookup(namv
[i
])) {
for (segnum
= 0; segnum
!= -1;
segnum
= rt_dir
[segnum
].rd_nxtseg
- 1) {
last
= rt_last
+ segnum
*2*RT_BLOCK
;
for (de
= ((char *)&rt_dir
[segnum
])+10; de
<= last
;
nleft
= (last
-de
)/rt_entsiz
;
#define ENTRIES "\n%d entries remaining in directory segment %d.\n"
printf(ENTRIES
, nleft
, segnum
+1);
register struct rt_ent
*de
;
sunrad50(name
, de
->rt_name
);
unrad50(2, de
->rt_name
, name
);
unrad50(1, &(de
->rt_name
[2]), ext
);
year
= de
->rt_date
.rt_yr
+72;
month
= de
->rt_date
.rt_mo
;
printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name
,
ext
, month
, day
, year
, de
->rt_len
);
printf("%-25.9s %d\n","<UNUSED>", de
->rt_len
);
register char *de
, *last
;
for (i
= 0; i
< namc
; i
++)
for (segnum
= 0; segnum
!= -1;
segnum
= rt_dir
[segnum
].rd_nxtseg
-1)
for (last
= rt_last
+(segnum
*2*RT_BLOCK
),
de
= ((char *)&rt_dir
[segnum
])+10; de
<= last
;
switch (rt(de
)->rt_stat
) {
break; /* exit loop and try next segment */
sunrad50(name
,rt(de
)->rt_name
);
if (dope
= lookup(name
)) {
(void) rtls(dope
->rtdope
);
if ((file
= creat(name
, 0666)) < 0)
for( ; count
> 0 ; count
-= 512) {
(void) lread(startad
, 512, buff
);
(void) write(file
, buff
, 512);
register char *de
, *last
;
if (stat(defdev
, &sb
) >= 0 && (sb
.st_mode
& S_IFMT
) == S_IFREG
)
tty
= open("/dev/tty", O_RDWR
);
#define SURE "Are you sure you want to clobber the floppy? "
(void) write(tty
, SURE
, sizeof (SURE
));
(void) read(tty
, response
, sizeof (response
));
if (flag(c
) || flag(d
) || flag(r
))
if ((temp_floppydes
= fopen(defdev
, mode
)) == NULL
) {
floppydes
= fileno(temp_floppydes
);
if (lread(6*RT_BLOCK
, 2*RT_BLOCK
, (char *)&rt_dir
[0]))
dirnum
= rt_dir
[0].rd_numseg
;
/* check for blank/uninitialized diskette */
fprintf(stderr
,"arff: bad directory format\n");
if (dirnum
> RT_DIRSIZE
) {
fprintf(stderr
,"arff: too many directory segments\n");
for (i
= 1; i
< dirnum
; i
++)
if (lread((6+2*i
)*RT_BLOCK
, 2*RT_BLOCK
, (char *)&rt_dir
[i
]))
rt_dir
[0].rd_numseg
= 31;
rt_dir
[0].rd_stfile
= 68;
rt_dir
[0].rt_ents
[0].rt_len
= 20480 - 68;
rt_entsiz
= 2*rt_dir
[0].rd_entpad
+ 14;
* We assume that the directory entries have no padding. This
* may not be a valid assumption, but there are numerous point
* in the code where it assumes it is an rt_ent structure and
* not an rt_entsiz sized structure.
rt_last
= ((char *) &rt_dir
[0]) + 10 + 1014/rt_entsiz
*rt_entsiz
;
for (i
= 0; i
< dirnum
; i
++) {
last
= rt_last
+ i
*2*RT_BLOCK
;
for (de
= ((char *)&rt_dir
[i
])+10; de
<= last
; de
+= rt_entsiz
)
if (rt(de
)->rt_stat
== RT_ESEG
)
rt_nleft
+= (last
-de
)/rt_entsiz
;
* Search for name, accumulate blocks in index
for (segnum
= 0; segnum
!= -1;
segnum
= rt_dir
[segnum
].rd_nxtseg
- 1)
for (de
=((char *)&rt_dir
[segnum
])+10;
rt(de
)->rt_stat
!= RT_ESEG
; de
+= rt_entsiz
)
switch(rt(de
)->rt_stat
) {
if(samename(rname
,rt(de
)->rt_name
)) {
result
.count
= rt(de
)->rt_len
* 512;
(rt_dir
[segnum
].rd_stfile
+ index
);
result
.rtdope
= (struct rt_ent
*) de
;
return (*a
== *b
&& a
[1] == b
[1] && a
[2] == b
[2] );
for (index
= 0; *cp
; index
++) {
temp
= Ain1
* table
[*cp
++];
temp
+= Ain2
* table
[*cp
++];
#define reduce(x, p, q) (x = v[p/q], p %= q);
register u_char
*v
= (u_char
*) val
;
for (i
= 0; i
< count
; i
++) {
reduce(*cp
++, temp
, Ain1
);
reduce(*cp
++, temp
, Ain2
);
while (cp
>= name
&& *--cp
!= '/')
if (*cp
== '.' || index
>= 3)
rname
[0] = rname
[1] = rname
[2] = 0;
rad50((u_char
*)file
, rname
);
rad50((u_char
*)ext
, rname
+2);
unrad50(1, rname
+ 2, ext
);
* Jam name and extension together with a dot
while (*--cp
== ' ' && cp
>= name
)
for (cp2
= ext
; *cp2
!= ' ' && cp2
< ext
+3;)
static char *val
= " abcdefghijklmnopqrstuvwxyz$.@0123456789";
static char table
[256] = {
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
29, 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, 29, 29, 29, 29, 29,
29, 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, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
29, 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, 29, 29, 29, 29, 29,
29, 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, 29, 29, 29, 29 };
* Logical to physical adress translation
register int sector
, bytes
, track
;
sector
+= 26 + ((track
= (logical
/26))-1)*6;
return ((((track
*26)+sector
) << 7) + bytes
);
lread(startad
, count
, obuff
)
register int size
= flag(m
) ? 512 : 128;
while ((count
-= size
) >= 0) {
(void) lseek(floppydes
, flag(m
) ?
(long)startad
: trans(startad
), 0);
if (read(floppydes
, obuff
, size
) != size
) {
fprintf(stderr
, "arff: read error block %d: ",
lwrite(startad
, count
, obuff
)
register int size
= flag(m
) ? 512 : 128;
while ((count
-= size
) >= 0) {
(void) lseek(floppydes
, flag(m
) ?
(long)startad
: trans(startad
), 0);
if (write(floppydes
, obuff
, size
) != size
)
fprintf(stderr
, "arff: write error block %d\n",
for (i
= 0; i
< namc
; i
++)
register struct rt_ent
*de
;
register struct stat
*bufp
= &buf
;
if (stat(name
, bufp
) < 0) {
if (dope
= lookup(name
)) {
/* can replace, no problem */
if (bufp
->st_size
<= (de
->rt_len
* 512)) {
toflop(name
, bufp
->st_size
, dope
);
*((u_short
*)&(de
->rt_date
)) = 0;
for (segnum
= 0; segnum
!= -1;
segnum
= rt_dir
[segnum
].rd_nxtseg
- 1)
for (de
= rt_dir
[segnum
].rt_ents
;
rt(de
)->rt_stat
!= RT_ESEG
; de
++)
if ((de
)->rt_stat
== RT_NULL
) {
if (bufp
->st_size
<= (de
->rt_len
*512)) {
printf("%c - %s\n", type
, name
),
mkent(de
, segnum
, bufp
,name
);
printf("%s: no slot for file, file deleted\n",name
);
printf("%s: no slot for file\n", name
);
if (dope
= lookup(name
)) {
toflop(name
, bufp
->st_size
, dope
);
printf("%s: internal error, added then not found\n", name
);
mkent(de
, segnum
, bufp
, name
)
register struct rt_ent
*de
;
register struct stat
*bufp
;
register struct tm
*timp
;
register struct rt_ent
*workp
;
count
= (((bufp
->st_size
-1) >>9) + 1);
/* make sure there is room */
if ((char *)rt_curend
[segnum
] == (rt_last
+ (segnum
*2*RT_BLOCK
))) {
/* no entries left on segment, trying adding new segment */
if (rt_dir
[0].rd_numseg
> rt_dir
[0].rd_lstseg
) {
newseg
= rt_dir
[0].rd_lstseg
++;
rt_dir
[newseg
] = rt_nulldir
;
rt_dir
[newseg
].rd_nxtseg
= rt_dir
[segnum
].rd_nxtseg
;
rt_dir
[segnum
].rd_nxtseg
= newseg
+ 1;
rt_dir
[newseg
].rd_entpad
= rt_dir
[0].rd_entpad
;
rt_dir
[newseg
].rd_numseg
= rt_dir
[0].rd_numseg
;
for(i
= newseg
- 1; i
>= 0; i
--) {
workp
= rt_curend
[i
] - 1;
if (workp
->rt_stat
!= RT_NULL
)
if (workp
->rt_len
< size
)
for (workp
= &rt_dir
[maxseg
].rt_ents
[0];
workp
->rt_stat
!= RT_ESEG
; workp
++) {
rt_dir
[newseg
].rt_ents
[0].rt_len
= workp
->rt_len
;
rt_dir
[newseg
].rd_stfile
=
rt_dir
[maxseg
].rd_stfile
+ size
- workp
->rt_len
;
rt_curend
[newseg
] = &rt_dir
[newseg
].rt_ents
[1];
lwrite(6*RT_BLOCK
, 2*RT_BLOCK
, (char *)&rt_dir
[0]);
lwrite((6+segnum
*2)*RT_BLOCK
, 2*RT_BLOCK
,
(char *)&rt_dir
[segnum
]);
lwrite((6+newseg
*2)*RT_BLOCK
, 2*RT_BLOCK
,
(char *)&rt_dir
[newseg
]);
de
= &rt_dir
[newseg
].rt_ents
[0];
fprintf(stderr
, "All directory segments full on %s\n",
/* copy directory entries up */
for (workp
= rt_curend
[segnum
]+1; workp
> de
; workp
--)
srad50(name
,de
->rt_name
);
timp
= localtime(&bufp
->st_mtime
);
de
->rt_date
.rt_dy
= timp
->tm_mday
;
de
->rt_date
.rt_mo
= timp
->tm_mon
+ 1;
de
->rt_date
.rt_yr
= timp
->tm_year
- 72;
lwrite((6+segnum
*2)*RT_BLOCK
, 2*RT_BLOCK
, (char *)&rt_dir
[segnum
]);
toflop(name
, ocount
, dope
)
register file
, n
, startad
= dope
->startad
, count
= ocount
;
fprintf(stderr
, "arff: couldn't open %s\n",name
);
for( ; count
>= 512; count
-= 512) {
(void) read(file
, buff
, 512);
lwrite(startad
, 512, buff
);
(void) read(file
, buff
, count
);
for (n
= count
; n
< 512; n
++)
lwrite(startad
, 512, buff
);
count
= (dope
->rtdope
->rt_len
*512-ocount
)/512 ;
for ( ; count
> 0 ; count
--) {
lwrite(startad
, 512, zeroes
);
for (i
= 0; i
< namc
; i
++)
register struct rt_ent
*de
;
if (dope
= lookup(name
)) {
*((u_short
*)&(de
->rt_date
)) = 0;
register struct rt_ent
*de
, *workp
;
for (segnum
= 0; segnum
!= -1;
segnum
= rt_dir
[segnum
].rd_nxtseg
- 1) {
for (de
= rt_dir
[segnum
].rt_ents
; de
<= rt_curend
[segnum
]; de
++)
if (de
->rt_stat
== RT_NULL
&&
(de
+1)->rt_stat
== RT_NULL
) {
(de
+1)->rt_len
+= de
->rt_len
;
for (workp
=de
; workp
<rt_curend
[segnum
]; workp
++)
lwrite((6+segnum
*2)*RT_BLOCK
, 2*RT_BLOCK
,
(char *)&rt_dir
[segnum
]);