1*73af9334Sbostic /*-
2*73af9334Sbostic * Copyright (c) 1980 The Regents of the University of California.
3*73af9334Sbostic * All rights reserved.
4*73af9334Sbostic *
5*73af9334Sbostic * %sccs.include.proprietary.c%
62e57d5edSdist */
72e57d5edSdist
8b74381a6Ssam #ifndef lint
92e57d5edSdist char copyright[] =
10*73af9334Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
112e57d5edSdist All rights reserved.\n";
12*73af9334Sbostic #endif /* not lint */
132e57d5edSdist
142e57d5edSdist #ifndef lint
15*73af9334Sbostic static char sccsid[] = "@(#)arff.c 5.8 (Berkeley) 04/18/91";
16*73af9334Sbostic #endif /* not lint */
17c09a6a34Ssam
181437cf11Sbill #include <sys/types.h>
191437cf11Sbill #include <sys/stat.h>
201bbff716Ssam #include <sys/time.h>
21e01a7c91Sbostic #include <sys/signal.h>
2219251218Ssam #include <sys/file.h>
23e01a7c91Sbostic #include <stdio.h>
24e01a7c91Sbostic #include "pathnames.h"
25c09a6a34Ssam
261437cf11Sbill #define dbprintf printf
27c09a6a34Ssam
281437cf11Sbill struct rt_dat {
29c09a6a34Ssam u_short rt_yr:5; /* year-1972 */
30c09a6a34Ssam u_short rt_dy:5; /* day */
31c09a6a34Ssam u_short rt_mo:5; /* month */
321437cf11Sbill };
33c09a6a34Ssam
341437cf11Sbill struct rt_axent {
351437cf11Sbill char rt_sent[14];
361437cf11Sbill };
371437cf11Sbill
381437cf11Sbill struct rt_ent {
391437cf11Sbill char rt_pad; /* unusued */
400a8e9d21Sbostic u_char rt_stat; /* type of entry, or end of seg */
41c09a6a34Ssam u_short rt_name[3]; /* name, 3 words in rad50 form */
422ef99505Swnj u_short rt_len; /* length of file */
430a8e9d21Sbostic u_char rt_chan; /* only used in temporary files */
44c09a6a34Ssam char rt_job; /* only used in temporary files */
45c09a6a34Ssam struct rt_dat rt_date; /* creation date */
461437cf11Sbill };
47c09a6a34Ssam
481437cf11Sbill #define RT_TEMP 1
491437cf11Sbill #define RT_NULL 2
501437cf11Sbill #define RT_FILE 4
510a8e9d21Sbostic #define RT_PFILE (0200|RT_FILE) /* protected file */
521437cf11Sbill #define RT_ESEG 8
53c09a6a34Ssam
54c09a6a34Ssam #define RT_BLOCK 512 /* block size */
55d0b9e33eSwnj #define RT_DIRSIZE 31 /* max # of directory segments */
56c09a6a34Ssam
571437cf11Sbill struct rt_head {
58c09a6a34Ssam short rt_numseg; /* # of segments available */
59c09a6a34Ssam short rt_nxtseg; /* # of next logical segment */
60c09a6a34Ssam short rt_lstseg; /* highest seg currently open */
61c09a6a34Ssam u_short rt_entpad; /* extra words/directory entry */
62c09a6a34Ssam short rt_stfile; /* block # where files begin */
631437cf11Sbill };
64c09a6a34Ssam
651437cf11Sbill struct rt_dir {
661437cf11Sbill struct rt_head rt_axhead;
671437cf11Sbill struct rt_ent rt_ents[72];
681437cf11Sbill char _dirpad[6];
691437cf11Sbill };
70c09a6a34Ssam
712e5d0128Sbloom #define rd_numseg rt_axhead.rt_numseg
722e5d0128Sbloom #define rd_nxtseg rt_axhead.rt_nxtseg
732e5d0128Sbloom #define rd_lstseg rt_axhead.rt_lstseg
742e5d0128Sbloom #define rd_entpad rt_axhead.rt_entpad
752e5d0128Sbloom #define rd_stfile rt_axhead.rt_stfile
762e5d0128Sbloom
771437cf11Sbill typedef struct fldope {
781437cf11Sbill int startad;
791437cf11Sbill int count;
801437cf11Sbill struct rt_ent *rtdope;
811437cf11Sbill } FLDOPE;
82c09a6a34Ssam
831437cf11Sbill FLDOPE *lookup();
84c09a6a34Ssam
851437cf11Sbill #define rt(p) ((struct rt_ent *) p )
861437cf11Sbill #define Ain1 03100
871437cf11Sbill #define Ain2 050
88c09a6a34Ssam #define flag(c) (flg[('c') - 'a'])
891437cf11Sbill
90c09a6a34Ssam char *man = "rxtd";
911437cf11Sbill char zeroes[512];
92c09a6a34Ssam
931437cf11Sbill extern char *val;
941437cf11Sbill extern char table[256];
95c09a6a34Ssam struct rt_dir rt_dir[RT_DIRSIZE] = {
96b5239b99Sbostic {
97c09a6a34Ssam { 4, 0, 1, 0, 14 },
982e5d0128Sbloom { { 0, RT_NULL, { 0, 0, 0 }, 486, 0 },
992e5d0128Sbloom { 0, RT_ESEG } }
100b5239b99Sbostic }
1012e5d0128Sbloom };
1022e5d0128Sbloom
1032e5d0128Sbloom struct rt_dir rt_nulldir = {
1042e5d0128Sbloom { 0, 0, 0, 0, 0 },
1052e5d0128Sbloom { { 0, RT_NULL, { 0, 0, 0 }, 0, 0 },
106b74381a6Ssam { 0, RT_ESEG } }
107c09a6a34Ssam };
108c09a6a34Ssam
1091437cf11Sbill int rt_entsiz;
1101437cf11Sbill int rt_nleft;
111d0b9e33eSwnj struct rt_ent *rt_curend[RT_DIRSIZE];
1121437cf11Sbill int floppydes;
1131437cf11Sbill int dirdirty;
1141437cf11Sbill char *rt_last;
115e01a7c91Sbostic char *defdev = _PATH_FLOPPY;
1161437cf11Sbill
1172e5d0128Sbloom char *opt = "vfbcm";
1181437cf11Sbill
119c09a6a34Ssam extern long lseek();
120c09a6a34Ssam int rcmd(), dcmd(), xcmd(), tcmd();
121c09a6a34Ssam
1221437cf11Sbill int (*comfun)();
1231437cf11Sbill char flg[26];
1241437cf11Sbill char **namv;
1251437cf11Sbill int namc;
1261437cf11Sbill
main(argc,argv)1271437cf11Sbill main(argc, argv)
1281437cf11Sbill char *argv[];
1291437cf11Sbill {
1301437cf11Sbill register char *cp;
1311437cf11Sbill
1321437cf11Sbill if (argc < 2)
1331437cf11Sbill usage();
1341437cf11Sbill for (cp = argv[1]; *cp; cp++)
1351437cf11Sbill switch (*cp) {
136c09a6a34Ssam
1371437cf11Sbill case 'm':
1381437cf11Sbill case 'v':
1391437cf11Sbill case 'u':
1401437cf11Sbill case 'w':
1412e5d0128Sbloom case 'b':
1421437cf11Sbill flg[*cp-'a']++;
1431437cf11Sbill continue;
1441437cf11Sbill case 'c':
145c09a6a34Ssam flag(c)++;
1461437cf11Sbill dirdirty++;
1471437cf11Sbill continue;
1481437cf11Sbill
1491437cf11Sbill case 'r':
1501437cf11Sbill setcom(rcmd);
151c09a6a34Ssam flag(r)++;
1521437cf11Sbill continue;
1531437cf11Sbill
1541437cf11Sbill case 'd':
1551437cf11Sbill setcom(dcmd);
156c09a6a34Ssam flag(d)++;
1571437cf11Sbill continue;
1581437cf11Sbill
1591437cf11Sbill case 'x':
1601437cf11Sbill setcom(xcmd);
1611437cf11Sbill continue;
1621437cf11Sbill
1631437cf11Sbill case 't':
1641437cf11Sbill setcom(tcmd);
1651437cf11Sbill continue;
1661437cf11Sbill
1671437cf11Sbill case 'f':
1681437cf11Sbill defdev = argv[2];
1691437cf11Sbill argv++;
1701437cf11Sbill argc--;
1711437cf11Sbill continue;
1721437cf11Sbill
1731437cf11Sbill default:
1741437cf11Sbill fprintf(stderr, "arff: bad option `%c'\n", *cp);
1751437cf11Sbill exit(1);
1761437cf11Sbill }
177c09a6a34Ssam
1781437cf11Sbill namv = argv+2;
1791437cf11Sbill namc = argc-2;
1801437cf11Sbill if (comfun == 0) {
181c09a6a34Ssam if (flag(u) == 0) {
182c09a6a34Ssam fprintf(stderr, "arff: one of [%s] must be specified\n",
183c09a6a34Ssam man);
1841437cf11Sbill exit(1);
1851437cf11Sbill }
1861437cf11Sbill setcom(rcmd);
1871437cf11Sbill }
1881437cf11Sbill (*comfun)();
1891437cf11Sbill exit(notfound());
1901437cf11Sbill }
1911437cf11Sbill
1921437cf11Sbill setcom(fun)
1931437cf11Sbill int (*fun)();
1941437cf11Sbill {
1951437cf11Sbill if (comfun != 0) {
1961437cf11Sbill fprintf(stderr, "arff: only one of [%s] allowed\n", man);
1971437cf11Sbill exit(1);
1981437cf11Sbill }
1991437cf11Sbill comfun = fun;
2001437cf11Sbill }
2011437cf11Sbill
usage()2021437cf11Sbill usage()
2031437cf11Sbill {
204296c7c8aSwnj fprintf(stderr, "usage: ar [%s][%s] archive files ...\n", opt, man);
2051437cf11Sbill exit(1);
2061437cf11Sbill }
2071437cf11Sbill
notfound()2081437cf11Sbill notfound()
2091437cf11Sbill {
210c09a6a34Ssam register i, n = 0;
2111437cf11Sbill
2121437cf11Sbill for (i = 0; i < namc; i++)
2131437cf11Sbill if (namv[i]) {
2141437cf11Sbill fprintf(stderr, "arff: %s not found\n", namv[i]);
2151437cf11Sbill n++;
2161437cf11Sbill }
2171437cf11Sbill return (n);
2181437cf11Sbill }
2191437cf11Sbill
tcmd()2201437cf11Sbill tcmd()
2211437cf11Sbill {
222c09a6a34Ssam register char *de, *last;
2231437cf11Sbill FLDOPE *lookup(), *dope;
224c09a6a34Ssam int segnum, nleft;
225c09a6a34Ssam register i;
2261437cf11Sbill register struct rt_ent *rde;
2271437cf11Sbill
2281437cf11Sbill rt_init();
229b74381a6Ssam if (namc != 0) {
230b74381a6Ssam for (i = 0; i < namc; i++)
231b74381a6Ssam if (dope = lookup(namv[i])) {
232b74381a6Ssam rde = dope->rtdope;
2332e5d0128Sbloom (void) rtls(rde);
234b74381a6Ssam namv[i] = 0;
235b74381a6Ssam }
236b74381a6Ssam return;
237b74381a6Ssam }
238c09a6a34Ssam for (segnum = 0; segnum != -1;
2392e5d0128Sbloom segnum = rt_dir[segnum].rd_nxtseg - 1) {
240d0b9e33eSwnj last = rt_last + segnum*2*RT_BLOCK;
241d0b9e33eSwnj for (de = ((char *)&rt_dir[segnum])+10; de <= last;
242c09a6a34Ssam de += rt_entsiz)
2431437cf11Sbill if (rtls(rt(de))) {
244d0b9e33eSwnj nleft = (last-de)/rt_entsiz;
245c09a6a34Ssam #define ENTRIES "\n%d entries remaining in directory segment %d.\n"
246c09a6a34Ssam printf(ENTRIES, nleft, segnum+1);
2471437cf11Sbill break;
2481437cf11Sbill }
2491437cf11Sbill }
2501437cf11Sbill }
251c09a6a34Ssam
rtls(de)2521437cf11Sbill rtls(de)
2531437cf11Sbill register struct rt_ent *de;
2541437cf11Sbill {
2551437cf11Sbill int month, day, year;
2561437cf11Sbill char name[12], ext[4];
2571437cf11Sbill
2581437cf11Sbill switch (de->rt_stat) {
259c09a6a34Ssam
2601437cf11Sbill case RT_TEMP:
261c09a6a34Ssam if (flag(v))
2621437cf11Sbill printf("Tempfile:\n");
263c09a6a34Ssam /* fall thru...*/
264c09a6a34Ssam
2651437cf11Sbill case RT_FILE:
2660a8e9d21Sbostic case RT_PFILE:
267c09a6a34Ssam if (!flag(v)) {
268c09a6a34Ssam sunrad50(name, de->rt_name);
269c09a6a34Ssam printf("%s\n", name);
270c09a6a34Ssam break;
271c09a6a34Ssam }
2721437cf11Sbill unrad50(2, de->rt_name, name);
2731437cf11Sbill unrad50(1, &(de->rt_name[2]), ext);
2741437cf11Sbill day = de->rt_date.rt_dy;
2751437cf11Sbill year = de->rt_date.rt_yr+72;
2761437cf11Sbill month = de->rt_date.rt_mo;
2771437cf11Sbill printf("%6.6s %3.3s %02d/%02d/%02d %d\n",name,
2781437cf11Sbill ext, month, day, year, de->rt_len);
2791437cf11Sbill break;
2801437cf11Sbill
2811437cf11Sbill case RT_NULL:
2821437cf11Sbill printf("%-25.9s %d\n","<UNUSED>", de->rt_len);
2831437cf11Sbill break;
2841437cf11Sbill
2851437cf11Sbill case RT_ESEG:
2861437cf11Sbill return (1);
2871437cf11Sbill }
2881437cf11Sbill return (0);
2891437cf11Sbill }
290c09a6a34Ssam
xcmd()2911437cf11Sbill xcmd()
2921437cf11Sbill {
293c09a6a34Ssam register char *de, *last;
294d0b9e33eSwnj int segnum;
2951437cf11Sbill char name[12];
2961437cf11Sbill register int i;
2971437cf11Sbill
2981437cf11Sbill rt_init();
299b74381a6Ssam if (namc != 0) {
300b74381a6Ssam for (i = 0; i < namc; i++)
301b74381a6Ssam if (rtx(namv[i]) == 0)
302b74381a6Ssam namv[i] = 0;
303b74381a6Ssam return;
304b74381a6Ssam }
305c09a6a34Ssam for (segnum = 0; segnum != -1;
3062e5d0128Sbloom segnum = rt_dir[segnum].rd_nxtseg-1)
307c09a6a34Ssam for (last = rt_last+(segnum*2*RT_BLOCK),
308c09a6a34Ssam de = ((char *)&rt_dir[segnum])+10; de <= last;
30967f39843Sralph de += rt_entsiz) {
3100200ad53Swnj switch (rt(de)->rt_stat) {
311b74381a6Ssam
3120200ad53Swnj case RT_ESEG:
31367f39843Sralph break; /* exit loop and try next segment */
314b74381a6Ssam
3150200ad53Swnj case RT_TEMP:
3160200ad53Swnj case RT_FILE:
3170a8e9d21Sbostic case RT_PFILE:
3180200ad53Swnj sunrad50(name,rt(de)->rt_name);
3192e5d0128Sbloom (void) rtx(name);
320b74381a6Ssam
3210200ad53Swnj case RT_NULL:
32267f39843Sralph default:
32367f39843Sralph continue;
32467f39843Sralph }
325b74381a6Ssam break;
3260200ad53Swnj }
3271437cf11Sbill }
328c09a6a34Ssam
rtx(name)3291437cf11Sbill rtx(name)
3301437cf11Sbill char *name;
3311437cf11Sbill {
3321437cf11Sbill register FLDOPE *dope;
3331437cf11Sbill FLDOPE *lookup();
3341437cf11Sbill register startad, count;
335c09a6a34Ssam int file;
336c09a6a34Ssam char buff[512];
3371437cf11Sbill
3381437cf11Sbill
3391437cf11Sbill if (dope = lookup(name)) {
340c09a6a34Ssam if (flag(v))
3412e5d0128Sbloom (void) rtls(dope->rtdope);
3421437cf11Sbill else
3431437cf11Sbill printf("x - %s\n",name);
3441437cf11Sbill
345c09a6a34Ssam if ((file = creat(name, 0666)) < 0)
346c09a6a34Ssam return (1);
3471437cf11Sbill count = dope->count;
3481437cf11Sbill startad = dope->startad;
3491437cf11Sbill for( ; count > 0 ; count -= 512) {
350b1b6657eSkarels (void) lread(startad, 512, buff);
3512e5d0128Sbloom (void) write(file, buff, 512);
3521437cf11Sbill startad += 512;
3531437cf11Sbill }
3542e5d0128Sbloom (void) close(file);
3551437cf11Sbill return (0);
3561437cf11Sbill }
3571437cf11Sbill return (1);
3581437cf11Sbill }
359c09a6a34Ssam
rt_init()3601437cf11Sbill rt_init()
3611437cf11Sbill {
3621437cf11Sbill static initized = 0;
363c09a6a34Ssam register char *de, *last;
364d0b9e33eSwnj register i;
365a11ea3b6Shickman int dirnum;
366a11ea3b6Shickman char *mode;
367a11ea3b6Shickman FILE *temp_floppydes;
3681437cf11Sbill
369c09a6a34Ssam if (initized)
370c09a6a34Ssam return;
3711437cf11Sbill initized = 1;
37219251218Ssam if (flag(c)) {
37319251218Ssam struct stat sb;
37419251218Ssam char response[128];
37519251218Ssam int tty;
37619251218Ssam
37719251218Ssam if (stat(defdev, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFREG)
37819251218Ssam goto ignore;
379e01a7c91Sbostic tty = open(_PATH_TTY, O_RDWR);
38019251218Ssam #define SURE "Are you sure you want to clobber the floppy? "
3812e5d0128Sbloom (void) write(tty, SURE, sizeof (SURE));
3822e5d0128Sbloom (void) read(tty, response, sizeof (response));
38319251218Ssam if (*response != 'y')
38419251218Ssam exit(50);
3852e5d0128Sbloom (void) close(tty);
38619251218Ssam ignore:
38719251218Ssam ;
38819251218Ssam }
389c09a6a34Ssam if (flag(c) || flag(d) || flag(r))
390a11ea3b6Shickman mode = "r+";
3911437cf11Sbill else
392a11ea3b6Shickman mode = "r";
393a11ea3b6Shickman if ((temp_floppydes = fopen(defdev, mode)) == NULL) {
394a11ea3b6Shickman perror(defdev);
395296c7c8aSwnj exit(1);
396a11ea3b6Shickman } else
397a11ea3b6Shickman floppydes = fileno(temp_floppydes);
398c09a6a34Ssam if (!flag(c)) {
399b1b6657eSkarels if (lread(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]))
400b1b6657eSkarels exit(2);
4012e5d0128Sbloom dirnum = rt_dir[0].rd_numseg;
402254d8466Shelge /* check for blank/uninitialized diskette */
403254d8466Shelge if (dirnum <= 0) {
404254d8466Shelge fprintf(stderr,"arff: bad directory format\n");
405254d8466Shelge exit(1);
406254d8466Shelge }
407d0b9e33eSwnj if (dirnum > RT_DIRSIZE) {
408d0b9e33eSwnj fprintf(stderr,"arff: too many directory segments\n");
409d0b9e33eSwnj exit(1);
410d0b9e33eSwnj }
411d0b9e33eSwnj for (i = 1; i < dirnum; i++)
412b1b6657eSkarels if (lread((6+2*i)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[i]))
413b1b6657eSkarels exit(1);
4142e5d0128Sbloom } else {
41519ec2be6Sroot dirnum = 1;
4162e5d0128Sbloom if (flag(b)) {
4172e5d0128Sbloom rt_dir[0].rd_numseg = 31;
4182e5d0128Sbloom rt_dir[0].rd_stfile = 68;
4192e5d0128Sbloom rt_dir[0].rt_ents[0].rt_len = 20480 - 68;
4202e5d0128Sbloom }
4212e5d0128Sbloom }
4221437cf11Sbill
4232e5d0128Sbloom rt_entsiz = 2*rt_dir[0].rd_entpad + 14;
4242e5d0128Sbloom /*
4252e5d0128Sbloom * We assume that the directory entries have no padding. This
4262e5d0128Sbloom * may not be a valid assumption, but there are numerous point
4272e5d0128Sbloom * in the code where it assumes it is an rt_ent structure and
4282e5d0128Sbloom * not an rt_entsiz sized structure.
4292e5d0128Sbloom */
4302e5d0128Sbloom rt_entsiz = 14;
431d0b9e33eSwnj rt_last = ((char *) &rt_dir[0]) + 10 + 1014/rt_entsiz*rt_entsiz;
432d0b9e33eSwnj rt_nleft = 0;
433d0b9e33eSwnj
434d0b9e33eSwnj for (i = 0; i < dirnum; i++) {
435d0b9e33eSwnj last = rt_last + i*2*RT_BLOCK;
436c09a6a34Ssam for (de = ((char *)&rt_dir[i])+10; de <= last; de += rt_entsiz)
437c09a6a34Ssam if (rt(de)->rt_stat == RT_ESEG)
438c09a6a34Ssam break;
439d0b9e33eSwnj rt_curend[i] = rt(de);
440d0b9e33eSwnj rt_nleft += (last-de)/rt_entsiz;
441d0b9e33eSwnj }
4421437cf11Sbill }
4431437cf11Sbill
4441437cf11Sbill static FLDOPE result;
445c09a6a34Ssam
4461437cf11Sbill FLDOPE *
lookup(name)4471437cf11Sbill lookup(name)
4481437cf11Sbill char *name;
4491437cf11Sbill {
4501437cf11Sbill unsigned short rname[3];
4512e5d0128Sbloom register char *de;
452d0b9e33eSwnj int segnum;
4531437cf11Sbill register index;
4541437cf11Sbill
4551437cf11Sbill srad50(name,rname);
4561437cf11Sbill
4571437cf11Sbill /*
4581437cf11Sbill * Search for name, accumulate blocks in index
4591437cf11Sbill */
4601437cf11Sbill rt_init();
461c09a6a34Ssam for (segnum = 0; segnum != -1;
4622e5d0128Sbloom segnum = rt_dir[segnum].rd_nxtseg - 1)
463c09a6a34Ssam {
4641437cf11Sbill index = 0;
465d0b9e33eSwnj for (de=((char *)&rt_dir[segnum])+10;
466c09a6a34Ssam rt(de)->rt_stat != RT_ESEG; de += rt_entsiz)
4671437cf11Sbill switch(rt(de)->rt_stat) {
468c09a6a34Ssam
4691437cf11Sbill case RT_FILE:
4700a8e9d21Sbostic case RT_PFILE:
4711437cf11Sbill case RT_TEMP:
472c09a6a34Ssam if(samename(rname,rt(de)->rt_name)) {
473c09a6a34Ssam result.count = rt(de)->rt_len * 512;
474c09a6a34Ssam result.startad = 512*
4752e5d0128Sbloom (rt_dir[segnum].rd_stfile + index);
476c09a6a34Ssam result.rtdope = (struct rt_ent *) de;
477c09a6a34Ssam return (&result);
478c09a6a34Ssam }
479c09a6a34Ssam
4801437cf11Sbill case RT_NULL:
4811437cf11Sbill index += rt(de)->rt_len;
4821437cf11Sbill }
4831437cf11Sbill }
4841437cf11Sbill return ((FLDOPE *) 0);
485c09a6a34Ssam
4861437cf11Sbill }
487c09a6a34Ssam
4881437cf11Sbill static
samename(a,b)4891437cf11Sbill samename(a, b)
490c09a6a34Ssam u_short a[], b[];
4911437cf11Sbill {
492c09a6a34Ssam return (*a == *b && a[1] == b[1] && a[2] == b[2] );
4931437cf11Sbill }
4941437cf11Sbill
rad50(cp,out)4951437cf11Sbill rad50(cp, out)
496c09a6a34Ssam register u_char *cp;
497c09a6a34Ssam u_short *out;
4981437cf11Sbill {
499c09a6a34Ssam register index, temp;
5001437cf11Sbill
5011437cf11Sbill for (index = 0; *cp; index++) {
5021437cf11Sbill temp = Ain1 * table[*cp++];
5031437cf11Sbill if (*cp!=0) {
5041437cf11Sbill temp += Ain2 * table[*cp++];
5051437cf11Sbill if(*cp!=0)
5061437cf11Sbill temp += table[*cp++];
5071437cf11Sbill }
5081437cf11Sbill out[index] = temp;
5091437cf11Sbill }
5101437cf11Sbill }
511c09a6a34Ssam
512c09a6a34Ssam #define reduce(x, p, q) (x = v[p/q], p %= q);
5131437cf11Sbill
unrad50(count,in,cp)5141437cf11Sbill unrad50(count, in, cp)
515c09a6a34Ssam u_short *in;
5161437cf11Sbill register char *cp;
5171437cf11Sbill {
518c09a6a34Ssam register i, temp;
519c09a6a34Ssam register u_char *v = (u_char *) val;
5201437cf11Sbill
5211437cf11Sbill for (i = 0; i < count; i++) {
5221437cf11Sbill temp = in[i];
5231437cf11Sbill reduce(*cp++, temp, Ain1);
5241437cf11Sbill reduce(*cp++, temp, Ain2);
5251437cf11Sbill reduce(*cp++, temp, 1);
5261437cf11Sbill }
5271437cf11Sbill *cp=0;
5281437cf11Sbill }
5291437cf11Sbill
srad50(name,rname)5301437cf11Sbill srad50(name, rname)
5311437cf11Sbill register char *name;
532c09a6a34Ssam register u_short *rname;
5331437cf11Sbill {
534c09a6a34Ssam register index;
535c09a6a34Ssam register char *cp;
5361437cf11Sbill char file[7], ext[4];
537c09a6a34Ssam
5381437cf11Sbill /*
5391437cf11Sbill * Find end of pathname
5401437cf11Sbill */
541c09a6a34Ssam for (cp = name; *cp++; )
542c09a6a34Ssam ;
543c09a6a34Ssam while (cp >= name && *--cp != '/')
544c09a6a34Ssam ;
5451437cf11Sbill cp++;
5461437cf11Sbill /*
5471437cf11Sbill * Change to rad50
5481437cf11Sbill */
5491437cf11Sbill for (index = 0; *cp; ) {
5501437cf11Sbill file[index++] = *cp++;
5511437cf11Sbill if (*cp == '.') {
5521437cf11Sbill cp++;
5531437cf11Sbill break;
5541437cf11Sbill }
5551437cf11Sbill if (index >= 6) {
5561437cf11Sbill break;
5571437cf11Sbill }
5581437cf11Sbill }
5591437cf11Sbill file[index] = 0;
5601437cf11Sbill for (index = 0; *cp; ) {
5611437cf11Sbill ext[index++] = *cp++;
562c09a6a34Ssam if (*cp == '.' || index >= 3)
5631437cf11Sbill break;
5641437cf11Sbill }
5651437cf11Sbill ext[index]=0;
566c09a6a34Ssam rname[0] = rname[1] = rname[2] = 0;
567c09a6a34Ssam rad50((u_char *)file, rname);
568c09a6a34Ssam rad50((u_char *)ext, rname+2);
5691437cf11Sbill }
570c09a6a34Ssam
sunrad50(name,rname)5711437cf11Sbill sunrad50(name, rname)
572c09a6a34Ssam u_short rname[];
5731437cf11Sbill register char *name;
5741437cf11Sbill {
5751437cf11Sbill register char *cp, *cp2;
5761437cf11Sbill char ext[4];
5771437cf11Sbill
5781437cf11Sbill unrad50(2, rname, name);
5791437cf11Sbill unrad50(1, rname + 2, ext);
580c09a6a34Ssam /*
581c09a6a34Ssam * Jam name and extension together with a dot
582c09a6a34Ssam * deleting white space
583c09a6a34Ssam */
584c09a6a34Ssam for (cp = name; *cp++;)
585c09a6a34Ssam ;
586c09a6a34Ssam --cp;
587c09a6a34Ssam while (*--cp == ' ' && cp >= name)
588c09a6a34Ssam ;
589c09a6a34Ssam *++cp = '.';
590c09a6a34Ssam cp++;
591c09a6a34Ssam for (cp2 = ext; *cp2 != ' ' && cp2 < ext+3;)
5921437cf11Sbill *cp++ = *cp2++;
5931437cf11Sbill *cp=0;
594c09a6a34Ssam if (cp[-1] == '.')
595c09a6a34Ssam cp[-1] = 0;
5961437cf11Sbill }
5971437cf11Sbill
5981437cf11Sbill static char *val = " abcdefghijklmnopqrstuvwxyz$.@0123456789";
599c09a6a34Ssam
6001437cf11Sbill static char table[256] = {
6011437cf11Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
6021437cf11Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
6031437cf11Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
6041437cf11Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
6051437cf11Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6061437cf11Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
6071437cf11Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6081437cf11Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
6091437cf11Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
6101437cf11Sbill 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
6111437cf11Sbill 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
6121437cf11Sbill 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
6131437cf11Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6141437cf11Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
6151437cf11Sbill 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6161437cf11Sbill 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
6171437cf11Sbill
618c09a6a34Ssam /*
619c09a6a34Ssam * Logical to physical adress translation
620c09a6a34Ssam */
621c09a6a34Ssam long
trans(logical)622c09a6a34Ssam trans(logical)
6231437cf11Sbill register int logical;
6241437cf11Sbill {
6251437cf11Sbill register int sector, bytes, track;
6261437cf11Sbill
6271437cf11Sbill logical += 26*128;
6281437cf11Sbill bytes = (logical&127);
6291437cf11Sbill logical >>= 7;
6301437cf11Sbill sector = logical%26;
6311437cf11Sbill if(sector >= 13)
6321437cf11Sbill sector = sector*2+1;
6331437cf11Sbill else
6341437cf11Sbill sector *= 2;
6351437cf11Sbill sector += 26 + ((track = (logical/26))-1)*6;
6361437cf11Sbill sector %= 26;
6371437cf11Sbill return ((((track*26)+sector) << 7) + bytes);
6381437cf11Sbill }
639c09a6a34Ssam
lread(startad,count,obuff)6401437cf11Sbill lread(startad, count, obuff)
6411437cf11Sbill register startad, count;
6421437cf11Sbill register char *obuff;
6431437cf11Sbill {
6441437cf11Sbill long trans();
6451437cf11Sbill extern floppydes;
646c09a6a34Ssam register int size = flag(m) ? 512 : 128;
647b1b6657eSkarels int error = 0;
648b1b6657eSkarels extern int errno;
649c09a6a34Ssam
6501437cf11Sbill rt_init();
651c09a6a34Ssam while ((count -= size) >= 0) {
6522e5d0128Sbloom (void) lseek(floppydes, flag(m) ?
653c09a6a34Ssam (long)startad : trans(startad), 0);
654b1b6657eSkarels if (read(floppydes, obuff, size) != size) {
655b1b6657eSkarels error = errno;
656b1b6657eSkarels fprintf(stderr, "arff: read error block %d: ",
657c09a6a34Ssam startad/size);
658b1b6657eSkarels errno = error;
659b1b6657eSkarels perror("");
660b1b6657eSkarels }
661c09a6a34Ssam obuff += size;
662c09a6a34Ssam startad += size;
6631437cf11Sbill }
664b1b6657eSkarels return (error);
6651437cf11Sbill }
666c09a6a34Ssam
lwrite(startad,count,obuff)6671437cf11Sbill lwrite(startad, count, obuff)
6681437cf11Sbill register startad, count;
6691437cf11Sbill register char *obuff;
6701437cf11Sbill {
6711437cf11Sbill long trans();
6721437cf11Sbill extern floppydes;
673c09a6a34Ssam register int size = flag(m) ? 512 : 128;
674c09a6a34Ssam
6751437cf11Sbill rt_init();
676c09a6a34Ssam while ((count -= size) >= 0) {
6772e5d0128Sbloom (void) lseek(floppydes, flag(m) ?
678c09a6a34Ssam (long)startad : trans(startad), 0);
679c09a6a34Ssam if (write(floppydes, obuff, size) != size)
680c09a6a34Ssam fprintf(stderr, "arff: write error block %d\n",
681c09a6a34Ssam startad/size);
682c09a6a34Ssam obuff += size;
683c09a6a34Ssam startad += size;
6841437cf11Sbill }
6851437cf11Sbill }
6861437cf11Sbill
rcmd()6871437cf11Sbill rcmd()
6881437cf11Sbill {
6891437cf11Sbill register int i;
6901437cf11Sbill
6911437cf11Sbill rt_init();
6921437cf11Sbill if (namc > 0)
6931437cf11Sbill for (i = 0; i < namc; i++)
694c09a6a34Ssam if (rtr(namv[i]) == 0)
695c09a6a34Ssam namv[i] = 0;
6961437cf11Sbill }
6971437cf11Sbill
rtr(name)6981437cf11Sbill rtr(name)
6991437cf11Sbill char *name;
7001437cf11Sbill {
701c09a6a34Ssam register FLDOPE *dope;
702c09a6a34Ssam register struct rt_ent *de;
703c09a6a34Ssam struct stat buf;
704c09a6a34Ssam register struct stat *bufp = &buf;
705d0b9e33eSwnj int segnum;
7062e5d0128Sbloom char type;
7071437cf11Sbill
70819ec2be6Sroot if (stat(name, bufp) < 0) {
70919ec2be6Sroot perror(name);
71019ec2be6Sroot return (-1);
71119ec2be6Sroot }
7122e5d0128Sbloom type = 'a';
7131437cf11Sbill if (dope = lookup(name)) {
7141437cf11Sbill /* can replace, no problem */
7151437cf11Sbill de = dope->rtdope;
7162e5d0128Sbloom if (bufp->st_size <= (de->rt_len * 512)) {
7172e5d0128Sbloom printf("r - %s\n",name);
7181437cf11Sbill toflop(name, bufp->st_size, dope);
719b74381a6Ssam goto found;
7202e5d0128Sbloom } else {
7212e5d0128Sbloom de = dope->rtdope;
7222e5d0128Sbloom type = 'r';
7232e5d0128Sbloom de->rt_stat = RT_NULL;
7242e5d0128Sbloom de->rt_name[0] = 0;
7252e5d0128Sbloom de->rt_name[1] = 0;
7262e5d0128Sbloom de->rt_name[2] = 0;
7272e5d0128Sbloom *((u_short *)&(de->rt_date)) = 0;
7282e5d0128Sbloom scrunch();
7292e5d0128Sbloom }
730b74381a6Ssam }
731b74381a6Ssam /*
732b74381a6Ssam * Search for vacant spot
733b74381a6Ssam */
734c09a6a34Ssam for (segnum = 0; segnum != -1;
7352e5d0128Sbloom segnum = rt_dir[segnum].rd_nxtseg - 1)
736c09a6a34Ssam {
737d0b9e33eSwnj for (de = rt_dir[segnum].rt_ents;
738c09a6a34Ssam rt(de)->rt_stat != RT_ESEG; de++)
739c09a6a34Ssam if ((de)->rt_stat == RT_NULL) {
7401437cf11Sbill if (bufp->st_size <= (de->rt_len*512)) {
7412e5d0128Sbloom printf("%c - %s\n", type, name),
742d0b9e33eSwnj mkent(de, segnum, bufp,name);
7431437cf11Sbill goto found;
7441437cf11Sbill }
7451437cf11Sbill continue;
746d0b9e33eSwnj }
747d0b9e33eSwnj }
748852ee85bSbostic if (type == 'r')
7492e5d0128Sbloom printf("%s: no slot for file, file deleted\n",name);
7502e5d0128Sbloom else
75119ec2be6Sroot printf("%s: no slot for file\n", name);
75219ec2be6Sroot return (-1);
753c09a6a34Ssam
754c09a6a34Ssam found:
755c09a6a34Ssam if (dope = lookup(name)) {
7561437cf11Sbill toflop(name, bufp->st_size, dope);
7571437cf11Sbill return (0);
7581437cf11Sbill }
75919ec2be6Sroot printf("%s: internal error, added then not found\n", name);
76019ec2be6Sroot return (-1);
7611437cf11Sbill }
762c09a6a34Ssam
mkent(de,segnum,bufp,name)763d0b9e33eSwnj mkent(de, segnum, bufp, name)
7641437cf11Sbill register struct rt_ent *de;
765d0b9e33eSwnj int segnum;
7661437cf11Sbill register struct stat *bufp;
7671437cf11Sbill char *name;
7681437cf11Sbill {
769c09a6a34Ssam struct tm *localtime();
770c09a6a34Ssam register struct tm *timp;
771c09a6a34Ssam register struct rt_ent *workp;
772c09a6a34Ssam int count;
7731437cf11Sbill
7741437cf11Sbill count = (((bufp->st_size -1) >>9) + 1);
775c09a6a34Ssam /* make sure there is room */
7761437cf11Sbill if (de->rt_len == count)
7771437cf11Sbill goto overwrite;
778c09a6a34Ssam if ((char *)rt_curend[segnum] == (rt_last + (segnum*2*RT_BLOCK))) {
7792e5d0128Sbloom /* no entries left on segment, trying adding new segment */
7802e5d0128Sbloom if (rt_dir[0].rd_numseg > rt_dir[0].rd_lstseg) {
7812e5d0128Sbloom short newseg;
7822e5d0128Sbloom register int i;
7832e5d0128Sbloom int maxseg;
7842e5d0128Sbloom short size;
7852e5d0128Sbloom
7862e5d0128Sbloom newseg = rt_dir[0].rd_lstseg++;
7872e5d0128Sbloom rt_dir[newseg] = rt_nulldir;
7882e5d0128Sbloom rt_dir[newseg].rd_nxtseg = rt_dir[segnum].rd_nxtseg;
7892e5d0128Sbloom rt_dir[segnum].rd_nxtseg = newseg + 1;
7902e5d0128Sbloom rt_dir[newseg].rd_entpad = rt_dir[0].rd_entpad;
7912e5d0128Sbloom rt_dir[newseg].rd_numseg = rt_dir[0].rd_numseg;
7922e5d0128Sbloom size = 0;
7932e5d0128Sbloom maxseg = 0;
7942e5d0128Sbloom for(i = newseg - 1; i >= 0; i--) {
7952e5d0128Sbloom workp = rt_curend[i] - 1;
7962e5d0128Sbloom if (workp->rt_stat != RT_NULL)
7972e5d0128Sbloom continue;
7982e5d0128Sbloom if (workp->rt_len < size)
7992e5d0128Sbloom continue;
8002e5d0128Sbloom size = workp->rt_len;
8012e5d0128Sbloom maxseg = i;
8022e5d0128Sbloom }
8032e5d0128Sbloom size = 0;
8042e5d0128Sbloom for (workp = &rt_dir[maxseg].rt_ents[0];
8052e5d0128Sbloom workp->rt_stat != RT_ESEG; workp++) {
8062e5d0128Sbloom size += workp->rt_len;
8072e5d0128Sbloom }
8082e5d0128Sbloom workp--;
8092e5d0128Sbloom rt_dir[newseg].rt_ents[0].rt_len = workp->rt_len;
8102e5d0128Sbloom rt_dir[newseg].rd_stfile =
8112e5d0128Sbloom rt_dir[maxseg].rd_stfile + size - workp->rt_len;
8122e5d0128Sbloom workp->rt_len = 0;
8132e5d0128Sbloom rt_curend[newseg] = &rt_dir[newseg].rt_ents[1];
8142e5d0128Sbloom lwrite(6*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[0]);
8152e5d0128Sbloom if (segnum != 0)
8162e5d0128Sbloom lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
8172e5d0128Sbloom (char *)&rt_dir[segnum]);
8182e5d0128Sbloom lwrite((6+newseg*2)*RT_BLOCK, 2*RT_BLOCK,
8192e5d0128Sbloom (char *)&rt_dir[newseg]);
8202e5d0128Sbloom segnum = newseg;
8212e5d0128Sbloom de = &rt_dir[newseg].rt_ents[0];
8222e5d0128Sbloom } else {
8232e5d0128Sbloom fprintf(stderr, "All directory segments full on %s\n",
8242e5d0128Sbloom defdev);
8251437cf11Sbill exit(1);
8261437cf11Sbill }
8272e5d0128Sbloom }
8281437cf11Sbill /* copy directory entries up */
829d0b9e33eSwnj for (workp = rt_curend[segnum]+1; workp > de; workp--)
8301437cf11Sbill *workp = workp[-1];
8311437cf11Sbill de[1].rt_len -= count;
8321437cf11Sbill de->rt_len = count;
833d0b9e33eSwnj rt_curend[segnum]++;
8341437cf11Sbill rt_nleft--;
835c09a6a34Ssam
8361437cf11Sbill overwrite:
8371437cf11Sbill srad50(name,de->rt_name);
8381437cf11Sbill timp = localtime(&bufp->st_mtime);
839b566105aSwnj de->rt_date.rt_dy = timp->tm_mday;
8401437cf11Sbill de->rt_date.rt_mo = timp->tm_mon + 1;
8411437cf11Sbill de->rt_date.rt_yr = timp->tm_year - 72;
8421437cf11Sbill de->rt_stat = RT_FILE;
8431437cf11Sbill de->rt_pad = 0;
8441437cf11Sbill de->rt_chan = 0;
8451437cf11Sbill de->rt_job = 0;
846d0b9e33eSwnj lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK, (char *)&rt_dir[segnum]);
8471437cf11Sbill }
8481437cf11Sbill
toflop(name,ocount,dope)8491437cf11Sbill toflop(name, ocount, dope)
8501437cf11Sbill char *name;
8511437cf11Sbill register FLDOPE *dope;
8521437cf11Sbill long ocount;
8531437cf11Sbill {
8541437cf11Sbill register file, n, startad = dope->startad, count = ocount;
8551437cf11Sbill char buff[512];
8561437cf11Sbill
8571437cf11Sbill file = open(name, 0);
8581437cf11Sbill if (file < 0) {
859c09a6a34Ssam fprintf(stderr, "arff: couldn't open %s\n",name);
860c09a6a34Ssam exit(1);
861c09a6a34Ssam }
8621437cf11Sbill for( ; count >= 512; count -= 512) {
8632e5d0128Sbloom (void) read(file, buff, 512);
8641437cf11Sbill lwrite(startad, 512, buff);
8651437cf11Sbill startad += 512;
8661437cf11Sbill }
8672e5d0128Sbloom (void) read(file, buff, count);
8682e5d0128Sbloom (void) close(file);
869c09a6a34Ssam if (count <= 0)
870c09a6a34Ssam return;
871c09a6a34Ssam for (n = count; n < 512; n ++)
872c09a6a34Ssam buff[n] = 0;
8731437cf11Sbill lwrite(startad, 512, buff);
8741437cf11Sbill count = (dope->rtdope->rt_len*512-ocount)/512 ;
875c09a6a34Ssam if (count <= 0)
876c09a6a34Ssam return;
8771437cf11Sbill for ( ; count > 0 ; count--) {
8781437cf11Sbill startad += 512;
8791437cf11Sbill lwrite(startad, 512, zeroes);
8801437cf11Sbill }
8811437cf11Sbill }
882c09a6a34Ssam
dcmd()8831437cf11Sbill dcmd()
8841437cf11Sbill {
8851437cf11Sbill register int i;
8861437cf11Sbill
8871437cf11Sbill rt_init();
8881437cf11Sbill if (namc)
8891437cf11Sbill for (i = 0; i < namc; i++)
890c09a6a34Ssam if (rtk(namv[i])==0)
891c09a6a34Ssam namv[i]=0;
8921437cf11Sbill if (dirdirty)
8931437cf11Sbill scrunch();
8941437cf11Sbill }
895c09a6a34Ssam
rtk(name)8961437cf11Sbill rtk(name)
8971437cf11Sbill char *name;
8981437cf11Sbill {
8991437cf11Sbill register FLDOPE *dope;
9001437cf11Sbill register struct rt_ent *de;
9011437cf11Sbill FLDOPE *lookup();
9021437cf11Sbill
9031437cf11Sbill if (dope = lookup(name)) {
9041437cf11Sbill printf("d - %s\n",name);
9051437cf11Sbill de = dope->rtdope;
9061437cf11Sbill de->rt_stat = RT_NULL;
9071437cf11Sbill de->rt_name[0] = 0;
9081437cf11Sbill de->rt_name[1] = 0;
9091437cf11Sbill de->rt_name[2] = 0;
910c09a6a34Ssam *((u_short *)&(de->rt_date)) = 0;
9111437cf11Sbill dirdirty = 1;
9121437cf11Sbill return (0);
9131437cf11Sbill }
9141437cf11Sbill return (1);
9151437cf11Sbill }
916c09a6a34Ssam
scrunch()917c09a6a34Ssam scrunch()
918c09a6a34Ssam {
919d0b9e33eSwnj register struct rt_ent *de , *workp;
920d0b9e33eSwnj register segnum;
921c09a6a34Ssam
922c09a6a34Ssam for (segnum = 0; segnum != -1;
9232e5d0128Sbloom segnum = rt_dir[segnum].rd_nxtseg - 1) {
924c09a6a34Ssam for (de = rt_dir[segnum].rt_ents; de <= rt_curend[segnum]; de++)
925b74381a6Ssam if (de->rt_stat == RT_NULL &&
926254d8466Shelge (de+1)->rt_stat == RT_NULL) {
9271437cf11Sbill (de+1)->rt_len += de->rt_len;
928d0b9e33eSwnj for (workp=de; workp<rt_curend[segnum]; workp++)
9291437cf11Sbill *workp = workp[1];
9301437cf11Sbill de--;
931d0b9e33eSwnj rt_curend[segnum]--;
9321437cf11Sbill rt_nleft++;
9331437cf11Sbill }
934c09a6a34Ssam lwrite((6+segnum*2)*RT_BLOCK, 2*RT_BLOCK,
935c09a6a34Ssam (char *)&rt_dir[segnum]);
936d0b9e33eSwnj }
937254d8466Shelge dirdirty = 0;
9381437cf11Sbill }
939