dbraun@cadavr.intel.com (Doug Braun ~) (12/22/88)
This and the following posting contain a set of UZI utility programs. These programs run under CP/M, and allow you to build, check, and manipulate a UZI filesystem. They must be linked with the device drivers you must write for your disks. This is also the best way to get device drivers working in the first place. See the .DOC file for more info. #!/bin/sh # #Run this file through sh to get: # xmachdep.c # ucp.c # fsck.c # xdevtty.c # bd.c # mkfs.c # unix.azm # loadutil.sub # filflop.sub # uzi_util.doc # filfs.sub # filelist # read.me echo -n 'Extracting xmachdep.c ... ' sed 's/^X//' > xmachdep.c << 'EOF_xmachdep.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: xmachdep.c X***************************************************/ X X X#include "unix.h" X#include "extern.h" X X X/* This is called at the very beginning to initialize everything. */ X/* It is the equivalent of main() */ X Xfs_init() X{ X inint = 0; X udata.u_euid = 0; X udata.u_insys = 1; X} X X X/* This checks to see if a user-suppled address is legitimate */ Xvaladr(base,size) Xchar *base; Xuint16 size; X{ X return(1); X} X X X/* This adds two tick counts together. XThe t_time field holds up to one second of ticks, Xwhile the t_date field counts minutes */ X Xaddtick(t1,t2) Xtime_t *t1, *t2; X{ X X t1->t_time += t2->t_time; X t1->t_date += t2->t_date; X if (t1->t_time >= 60*TICKSPERSEC) X { X t1->t_time -= 60*TICKSPERSEC; X ++t1->t_date; X } X} X Xincrtick(t) Xtime_t *t; X{ X if (++t->t_time == 60*TICKSPERSEC) X { X t->t_time = 0; X ++t->t_date; X } X} X X X Xstkreset() X{ X#asm 8080 X POP H X LXI SP,udata?-2 X PCHL X#endasm X} X X X/* Port addresses of clock chip registers. */ X X#define SECS 0xe2 X#define MINS 0xe3 X#define HRS 0xe4 X#define DAY 0xe6 X#define MON 0xe7 X#define YEAR 86 X Xsttime() X{ X panic("Calling sttime"); X} X X Xrdtime(tloc) Xtime_t *tloc; X{ X tloc->t_time = (tread(SECS)>>1) | (tread(MINS)<<5) | (tread(HRS)<<11); X tloc->t_date = tread(DAY) | (tread(MON)<<5) | (YEAR<<9); X} X X X/* Update global time of day */ Xrdtod() X{ X tod.t_time = (tread(SECS)>>1) | (tread(MINS)<<5) | (tread(HRS)<<11); X tod.t_date = tread(DAY) | (tread(MON)<<5) | (YEAR<<9); X} X X X/* Read BCD clock register, convert to binary. */ Xtread(port) Xuint16 port; X{ X int n; X X n = in(port); X return ( 10*((n>>4)&0x0f) + (n&0x0f) ); X} X X X/* Disable interrupts */ Xdi() X{ X#asm 8080 X DI ;disable interrupts X#endasm X} X X/* Enable interrupts if we are not in service routine */ Xei() X{ X if (inint) X return; X ; /* Empty statement necessary to fool compiler */ X X#asm 8080 X EI ;disable interrupts X#endasm X} X X X X/* This shifts an unsigned int right 8 places. */ X Xshift8() X{ X#asm 8080 X POP D ;ret addr X POP H X MOV L,H X MVI H,0 X MOV A,L X ANA A ;set Z flag on result X PUSH H X PUSH D ;restore stack X#endasm X} X X X/* This prints an error message and dies. */ X Xpanic(s) Xchar *s; X{ X inint = 1; X kprintf("PANIC: %s\n",s); X idump(); X abort(); X} X X Xwarning(s) Xchar *s; X{ X kprintf("WARNING: %s\n",s); X} X X Xkputs(s) Xchar *s; X{ X while (*s) X kputchar(*(s++)); X} X Xkputchar(c) Xint c; X{ X if (c == '\n') X _putc('\r'); X _putc(c); X} X X X Xidump() X{ X inoptr ip; X ptptr pp; X extern struct cinode i_tab[]; X bufptr j; X X kprintf( X " MAGIC DEV NUM MODE NLINK (DEV) REFS DIRTY err %d root %d\n", X udata.u_error, root - i_tab); X X for (ip=i_tab; ip < i_tab+ITABSIZE; ++ip) X { X kprintf("%d %d %d %u 0%o %d %d %d %d\n", X ip-i_tab, ip->c_magic,ip->c_dev, ip->c_num, X ip->c_node.i_mode,ip->c_node.i_nlink,ip->c_node.i_addr[0], X ip->c_refs,ip->c_dirty); X ifnot (ip->c_magic) X break; X } X X kprintf("\n STAT WAIT PID PPTR ALARM PENDING IGNORED\n"); X for (pp=ptab; pp < ptab+PTABSIZE; ++pp) X { X kprintf("%d %d 0x%x %d %d %d 0x%x 0x%x\n", X pp-ptab, pp->p_status, pp->p_wait, pp->p_pid, X pp->p_pptr-ptab, pp->p_alarm, pp->p_pending, X pp->p_ignored); X ifnot(pp->p_pptr) X break; X } X X kprintf("\ndev blk drty bsy\n"); X for (j=bufpool; j < bufpool+NBUFS; ++j) X kprintf("%d %u %d %d\n",j->bf_dev,j->bf_blk,j->bf_dirty,j->bf_busy); X X kprintf("\ninsys %d ptab %d call %d cwd %d sp 0x%x\n", X udata.u_insys,udata.u_ptab-ptab, udata.u_callno, udata.u_cwd-i_tab, X udata.u_sp); X} X X X X/* Short version of printf to save space */ Xkprintf(nargs) X { X register char **arg, *fmt; X register c, base; X char s[7], *itob(); X X arg = (char **)&nargs + nargs; X fmt = *arg; X while (c = *fmt++) { X if (c != '%') { X kputchar(c); X continue; X } X switch (c = *fmt++) { X case 'c': X kputchar(*--arg); X continue; X case 'd': X base = -10; X goto prt; X case 'o': X base = 8; X goto prt; X case 'u': X base = 10; X goto prt; X case 'x': X base = 16; X prt: X kputs(itob(*--arg, s, base)); X continue; X case 's': X kputs(*--arg); X continue; X default: X kputchar(c); X continue; X } X } X } EOF_xmachdep.c echo 'Done' echo -n 'Extracting ucp.c ... ' sed 's/^X//' > ucp.c << 'EOF_ucp.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: ucp.c X***************************************************/ X X X#include <stdio.h> X#include "unix.h"; X#include "extern.h" X Xint16 *syserror = &udata.u_error; Xstatic char cwd[100]; Xstatic char line[128]; X X#ifndef CPM Xextern char *sys_errlist[]; X#endif X X Xmain(argc,argval) Xint argc; Xchar *argval[]; X{ X int rdev; X char cmd[30], arg1[30], arg2[30], arg3[30]; X int count; X struct filesys fsys; X int j; X char *argv[5]; X X if (argc < 2) X rdev = 0; X else X rdev = atoi(argval[1]); X X xfs_init(rdev); X strcpy(cwd,"/"); X X for(;;) X { X printf("unix: "); X if (gets(line) == NULL) X { X xfs_end(); X exit(); X } X cmd[0] = '\0'; X *arg1 = '\0'; X arg2[0] = '\0'; X arg3[0] = '\0'; X count = sscanf(line,"%s %s %s %s",cmd, arg1, arg2, arg3); X if (count == 0 || cmd[0] == '\0') X continue; X X _sync(); X X if (strcmp(cmd,"\n") == 0) X continue; X else if (strcmp(cmd,"exit") == 0) X { X xfs_end(); X exit(); X } X else if (strcmp(cmd,"ls") == 0) X { X if (*arg1 ) X ls(arg1); X else X ls("."); X } X else if (strcmp(cmd,"cd") == 0) X { X if (*arg1 ) X { X strcpy(cwd,arg1); X if (_chdir(arg1) != 0) X { X printf("cd: error number %d\n",*syserror); X } X } X } X else if (strcmp(cmd,"mkdir") == 0) X { X if (*arg1 ) X mkdir(arg1); X } X else if (strcmp(cmd,"mknod") == 0) X { X if (*arg1 && *arg2 && *arg3 ) X mknod(arg1,arg2, arg3); X } X else if (strcmp(cmd,"chmod") == 0) X { X if (*arg1 && *arg2 ) X chmod(arg1,arg2); X } X else if (strcmp(cmd,"get") == 0) X { X if (*arg1 ) X get(arg1,0); X } X else if (strcmp(cmd,"bget") == 0) X { X if (*arg1 ) X get(arg1,1); X } X else if (strcmp(cmd,"put") == 0) X { X if (*arg1 ) X put(arg1,0); X } X else if (strcmp(cmd,"bput") == 0) X { X if (*arg1 ) X put(arg1,1); X } X else if (strcmp(cmd,"type") == 0) X { X if (*arg1 ) X type(arg1); X } X else if (strcmp(cmd,"dump") == 0) X { X if (*arg1 ) X fdump(arg1); X } X else if (strcmp(cmd,"rm") == 0) X { X if (*arg1 ) X unlink(arg1); X } X else if (strcmp(cmd,"df") == 0) X { X for (j=0; j < 4; ++j) X { X _getfsys(j,&fsys); X if (fsys.s_mounted) X { X printf("%d: %u blks used %u blks free %u inodes used %u inodes free\n", X j,(fsys.s_fsize - fsys.s_isize)-fsys.s_tfree, fsys.s_tfree, X (8*(fsys.s_isize-2)-fsys.s_tinode), fsys.s_tinode); X } X } X } X else if (strcmp(cmd,"rmdir") == 0) X { X if (*arg1 ) X rmdir(arg1); X } X else if (strcmp(cmd,"mount") == 0) X { X if (*arg1 && *arg2) X if (_mount(arg1,arg2,0) != 0) X { X printf("Mount error.%d\n", *syserror); X } X } X else if (strcmp(cmd,"umount") == 0) X { X if (*arg1) X if (_umount(arg1) != 0) X { X printf("Umount error.%d\n", *syserror); X } X } X else X { X printf("Unknown command\n"); X } X } X} X X X Xls(path) Xchar *path; X{ X struct direct buf; X struct stat statbuf; X char dname[128]; X int d; X X d = _open(path,0); X if (d < 0) X { X printf("ls: can't open %s\n",path); X return; X } X X while (_read(d,(char *)&buf,16) == 16) X { X if (buf.d_name[0] == '\0') X continue; X X if (path[0] != '.' || path[1] ) X { X strcpy(dname,path); X strcat(dname,"/"); X } X else X dname[0] = '\0'; X strcat(dname,buf.d_name); X X if (_stat(dname,&statbuf) != 0) X { X printf("ls: can't stat %s\n",dname); X continue; X } X X if ((statbuf.st_mode & F_MASK) == F_DIR) X strcat(dname,"/"); X X printf("%-6d %-15s", X (statbuf.st_mode & F_CDEV) ? X statbuf.st_rdev : X 512*statbuf.st_size.o_blkno + statbuf.st_size.o_offset, X dname); X X printf(" 0%-6o %-2d %-5d\n", statbuf.st_mode, statbuf.st_nlink, X statbuf.st_ino); X } X _close(d); X} X X Xchmod(path,modes) Xchar *path; Xchar *modes; X{ X int mode; X int dev; X X mode = -1; X sscanf(modes,"%o",&mode); X if (mode == -1 ) X { X printf("chmod: bad mode\n"); X return(-1); X } X X if (_chmod(path,mode)) X { X printf("_chmod: error %d\n",*syserror); X return(-1); X } X X} X X Xmknod(path,modes, devs) Xchar *path; Xchar *modes; Xchar *devs; X{ X int mode; X int dev; X X mode = -1; X sscanf(modes,"%o",&mode); X if (mode == -1 ) X { X printf("mknod: bad mode\n"); X return(-1); X } X X if ((mode & F_MASK) != F_BDEV && (mode & F_MASK) != F_CDEV) X { X printf("mknod: mode is not device\n"); X return(-1); X } X X dev = -1; X sscanf(devs,"%d",&dev); X if (dev == -1 ) X { X printf("mknod: bad device\n"); X return(-1); X } X X if (_mknod(path,mode,dev) != 0) X { X printf("_mknod: error %d\n",*syserror); X return(-1); X } X X return(0); X} X X X Xmkdir(path) Xchar *path; X{ X X char dot[100]; X X if ( _mknod(path, 040000 | 0777, 0) != 0) X { X printf("mkdir: mknod error %d\n",*syserror); X return(-1); X } X X strcpy(dot,path); X strcat(dot,"/."); X if ( _link(path,dot) != 0) X { X printf("mkdir: link dot error %d\n",*syserror); X return(-1); X } X X strcpy(dot,path); X strcat(dot,"/.."); X if ( _link(".",dot) != 0) X { X printf("mkdir: link dotdot error %d\n",*syserror); X return(-1); X } X X return(0); X} X X X X Xget(arg,binflag) Xchar *arg; Xint binflag; X{ X FILE *fp; X int d; X char cbuf[512]; X int nread; X X fp = fopen(arg,binflag ? "rb" : "r"); X if (fp == NULL) X { X printf("Source file not found\n"); X return(-1); X } X X d = _creat(arg,0666); X if (d < 0) X { X printf("Cant open unix file error %d\n",*syserror); X return(-1); X } X X for (;;) X { X nread = fread(cbuf,1,512,fp); X if (nread == 0) X break; X if (_write(d,cbuf,nread) != nread) X { X printf("_write error %d\n",*syserror); X fclose(fp); X _close(d); X return(-1); X } X } X fclose(fp); X _close(d); X return(0); X} X X Xput(arg,binflag) Xchar *arg; Xint binflag; X{ X FILE *fp; X int d; X char cbuf[512]; X int nread; X X fp = fopen(arg,binflag ? "wb" : "w"); X if (fp == NULL) X { X printf("Cant open destination file.\n"); X return(-1); X } X X d = _open(arg,0); X if (d < 0) X { X printf("Cant open unix file error %d\n",*syserror); X return(-1); X } X X for (;;) X { X if ((nread =_read(d,cbuf,512)) == 0) X break; X if (fwrite(cbuf,1,nread,fp) != nread) X { X printf("fwrite error"); X fclose(fp); X _close(d); X return(-1); X } X } X fclose(fp); X _close(d); X return(0); X} X X Xtype(arg) Xchar *arg; X{ X int d; X char cbuf[512]; X int nread; X X d = _open(arg,0); X if (d < 0) X { X printf("Cant open unix file error %d\n",*syserror); X return(-1); X } X X for (;;) X { X if( (nread = _read(d,cbuf,512)) == 0) X break; X X fwrite(cbuf, 1, nread, stdout); X } X _close(d); X return(0); X} X X Xfdump(arg) Xchar *arg; X{ X int d; X char cbuf[512]; X int nread; X X printf("Dump starting.\n"); X d = _open(arg,0); X if (d < 0) X { X printf("Cant open unix file error %d\n",*syserror); X return(-1); X } X X for (;;) X { X if( (nread = _read(d,cbuf,512)) == 0) X break; X } X _close(d); X printf("Dump done.\n"); X return(0); X} X X X X Xunlink(path) Xchar *path; X{ X struct stat statbuf; X X if (_stat(path,&statbuf) != 0) X { X printf("unlink: can't stat %s\n",path); X return(-1); X } X X if ((statbuf.st_mode & F_MASK) == F_DIR) X { X printf("unlink: %s directory\n",path); X return(-1); X } X X if (_unlink(path) != 0) X { X printf("unlink: _unlink errn=or %d\n",*syserror); X return(-1); X } X X return(0); X} X X Xrmdir(path) Xchar *path; X{ X struct stat statbuf; X char newpath[100]; X struct direct dir; X int fd; X X if (_stat(path,&statbuf) != 0) X { X printf("rmdir: can't stat %s\n",path); X return(-1); X } X X if (statbuf.st_mode & F_DIR == 0) X { X printf("rmdir: %s not directory\n",path); X return(-1); X } X X if((fd = _open(path,0)) < 0) { X printf("rmdir: %s unreadable\n", path); X return(-1); X } X while(_read(fd, (char *)&dir, sizeof (dir)) == sizeof (dir)) { X if(dir.d_ino == 0) continue; X if(!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, "..")) X continue; X printf("rmdir: %s not empty\n", path); X _close(fd); X return(-1); X } X _close(fd); X X strcpy(newpath,path); X strcat(newpath,"/."); X if (_unlink(newpath) != 0) X { X printf("rmdir: can't unlink \".\" error %d\n",*syserror); X return(-1); X } X X strcat(newpath,"."); X if (_unlink(newpath) != 0) X { X printf("rmdir: can't unlink \"..\" error %d\n",*syserror); X return(-1); X } X X if (_unlink(path) != 0) X { X printf("rmdir: _unlink error %d\n",*syserror); X return(-1); X } X X return(0); X} X EOF_ucp.c echo 'Done' echo -n 'Extracting fsck.c ... ' sed 's/^X//' > fsck.c << 'EOF_fsck.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: fsck.c X***************************************************/ X X X#include <stdio.h> X X#include "unix.h" X#include "extern.h" X X#define MAXDEPTH 20 /* Maximum depth of directory tree to search */ X X/* This checks a filesystem */ X Xint dev; Xstruct filesys filsys; X Xchar *bitmap; Xint16 *linkmap; X X Xchar *strcpy(), *strcat(), *sprintf(); Xchar *daread(); Xchar *calloc(); Xchar *da_read(); X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X X char *buf; X X if (argc != 2 || argv[1][0] < '0' || argv[1][0] > '9') X { X fprintf(stderr,"Usage: fsck device#\n"); X exit(-1); X } X X dev = atoi(argv[1]); X X bufinit(); X if (d_open(dev)) X { X fprintf(stderr,"Can't open device number %d\n",dev); X exit(-1); X } X X /* Read in the super block. */ X X buf = daread(1); X bcopy(buf, (char *)&filsys, sizeof(struct filesys)); X X /* Verify the fsize and isize parameters */ X X if (filsys.s_mounted != SMOUNTED) X { X printf("Device %d has invalid magic number %d. Fix? ", X dev, filsys.s_mounted); X if (!yes()) X exit(-1); X filsys.s_mounted = SMOUNTED; X dwrite((blkno_t)1,(char *)&filsys); X } X X printf("Device %d has fsize = %d and isize = %d. Continue? ", X dev, filsys.s_fsize, filsys.s_isize); X if (!yes()) X exit(-1); X X bitmap = calloc(filsys.s_fsize,sizeof(char)); X linkmap = (int16 *)calloc(8 * filsys.s_isize, sizeof(int16)); X X if (!bitmap || !linkmap) X { X fprintf(stderr,"Not enough memory.\n"); X exit(-1); X } X X printf("Pass 1: Checking inodes.\n"); X pass1(); X X printf("Pass 2: Rebuilding free list.\n"); X pass2(); X X printf("Pass 3: Checking block allocation.\n"); X pass3(); X X printf("Pass 4: Checking directory entries.\n"); X pass4(); X X printf("Pass 5: Checking link counts.\n"); X pass5(); X X bufsync(); X printf("Done.\n"); X X exit(0); X} X X X X/* Pass 1 checks each inode independently for validity, zaps bad block Xnumbers in the inodes, and builds the block allocation map. */ X Xpass1() X{ X uint16 n; X struct dinode ino; X uint16 mode; X blkno_t b; X blkno_t bno; X uint16 icount; X blkno_t *buf; X X blkno_t getblkno(); X X icount = 0; X X for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n) X { X iread(n, &ino); X linkmap[n] = -1; X X if (ino.i_mode == 0) X continue; X X mode = ino.i_mode & F_MASK; X X /* Check mode */ X if (mode != F_REG && mode != F_DIR && mode != F_BDEV && mode != F_CDEV) X { X printf("Inode %d with mode 0%o is not of correct type. Zap? ", X n, ino.i_mode); X if (yes()) X { X ino.i_mode = 0; X ino.i_nlink = 0; X iwrite(n, &ino); X continue; X } X } X X linkmap[n] = 0; X ++icount; X /* Check size */ X X if (ino.i_size.o_offset >= 512) X { X printf("Inode %d offset is too big with value of %d. Fix? ", X n,ino.i_size.o_offset); X if (yes()) X { X while (ino.i_size.o_offset >= 512) X { X ino.i_size.o_offset -= 512; X ++ino.i_size.o_blkno; X } X iwrite(n,&ino); X } X } X X X if (ino.i_size.o_offset < 0) X { X printf("Inode %d offset is negative with value of %d. Fix? ", X n,ino.i_size.o_offset); X if (yes()) X { X ino.i_size.o_offset = 0; X iwrite(n,&ino); X } X } X X X /* Check blocks and build free block map */ X if (mode == F_REG || mode == F_DIR) X { X /* Check singly indirect blocks */ X X for (b=18; b < 20; ++b) X { X if (ino.i_addr[b] != 0 && (ino.i_addr[b] < filsys.s_isize || X ino.i_addr[b] >= filsys.s_fsize)) X { X printf("Inode %d singly indirect block %d is out of range with value of %u. Zap? ", X n, b, ino.i_addr[b]); X if (yes()) X { X ino.i_addr[b] = 0; X iwrite(n, &ino); X } X } X X if (ino.i_addr[b] != 0 && ino.i_size.o_blkno < 18) X { X printf("Inode %d singly indirect block %d is past end of file with value of %u. Zap? ", X n, b, ino.i_addr[b]); X if (yes()) X { X ino.i_addr[b] = 0; X iwrite(n, &ino); X } X } X if (ino.i_addr[b] != 0) X bitmap[ino.i_addr[b]] = 1; X } X X /* Check the double indirect blocks */ X if (ino.i_addr[19] != 0) X { X buf = (blkno_t *)daread(ino.i_addr[19]); X for (b=0; b < 256; ++b) X { X if (buf[b] != 0 && (buf[b] < filsys.s_isize || X buf[b] >= filsys.s_fsize)) X { X printf("Inode %d doubly indirect block %d is out of range with value of %u. Zap? ", X n, b, buf[b]); X if (yes()) X { X buf[b] = 0; X dwrite(b, (char *)buf); X } X } X if (buf[b] != 0) X bitmap[buf[b]] = 1; X X } X } X X X /* Check the rest */ X for (bno=0; bno <= ino.i_size.o_blkno; ++bno) X { X b = getblkno(&ino, bno); X X if (b != 0 && (b < filsys.s_isize || X b >= filsys.s_fsize)) X { X printf("Inode %d block %d is out of range with value of %u. Zap? ", X n, bno, b); X if (yes()) X { X setblkno(&ino, bno,0); X iwrite(n, &ino); X } X } X X if (b != 0) X bitmap[b] = 1; X } X X } X } X X /* Fix free inode count in super block */ X if (filsys.s_tinode != 8*(filsys.s_isize-2) - ROOTINODE - icount) X { X printf("Free inode count in super block is %u should be %u. Fix? ", X filsys.s_tinode, 8*(filsys.s_isize-2) - ROOTINODE - icount); X X if (yes()) X { X filsys.s_tinode = 8*(filsys.s_isize-2) - ROOTINODE - icount; X dwrite((blkno_t)1,(char *)&filsys); X } X } X} X X X X/* Clear inode free list, rebuild block free list using bit map. */ X Xpass2() X{ X blkno_t j; X blkno_t oldtfree; X X printf("Rebuild free list? "); X if (!yes()) X return; X X oldtfree = filsys.s_tfree; X X /* Initialize the super-block */ X X filsys.s_ninode = 0; X filsys.s_nfree = 1; X filsys.s_free[0] = 0; X filsys.s_tfree = 0; X X /* Free each block, building the free list */ X X for (j= filsys.s_fsize-1; j >= filsys.s_isize; --j) X { X if (bitmap[j] == 0) X { X if (filsys.s_nfree == 50) X { X dwrite(j, (char *)&filsys.s_nfree); X filsys.s_nfree = 0; X } X X ++filsys.s_tfree; X filsys.s_free[(filsys.s_nfree)++] = j; X } X } X X dwrite((blkno_t)1,(char *)&filsys); X X if (oldtfree != filsys.s_tfree) X printf("During free list regeneration s_tfree was changed to %d from %d.\n", X filsys.s_tfree, oldtfree); X X} X X X X/* Pass 3 finds and fixes multiply allocated blocks. */ Xpass3() X{ X uint16 n; X struct dinode ino; X uint16 mode; X blkno_t b; X blkno_t bno; X blkno_t newno; X blkno_t blk_alloc(); X blkno_t getblkno(); X X for (b = filsys.s_isize; b < filsys.s_fsize; ++b) X bitmap[b] = 0; X X for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n) X { X iread(n, &ino); X X mode = ino.i_mode & F_MASK; X if (mode != F_REG && mode != F_DIR) X continue; X X /* Check singly indirect blocks */ X X for (b=18; b < 20; ++b) X { X if (ino.i_addr[b] != 0) X { X if (bitmap[ino.i_addr[b]] != 0) X { X printf("Indirect block %d in inode %u value %u multiply allocated. Fix? ", b, n, ino.i_addr[b]); X if (yes()) X { X newno = blk_alloc(&filsys); X if (newno == 0) X printf("Sorry... No more free blocks.\n"); X else X { X dwrite(newno,daread(ino.i_addr[b])); X ino.i_addr[b] = newno; X iwrite(n, &ino); X } X } X } X else X bitmap[ino.i_addr[b]] = 1; X } X } X X /* Check the rest */ X for (bno=0; bno <= ino.i_size.o_blkno; ++bno) X { X b = getblkno(&ino, bno); X X if (b != 0) X { X if (bitmap[b] != 0) X { X printf("Block %d in inode %u value %u multiply allocated. Fix? ", X bno, n, b); X if (yes()) X { X newno = blk_alloc(&filsys); X if (newno == 0) X printf("Sorry... No more free blocks.\n"); X else X { X dwrite(newno,daread(b)); X setblkno(&ino, bno, newno); X iwrite(n, &ino); X } X } X } X else X bitmap[b] = 1; X } X } X X } X X} X Xint depth; X X/* Pass 4 traverses the directory tree, fixing bad directory entries Xand finding the actual number of references to each inode. */ X Xpass4() X{ X depth = 0; X linkmap[ROOTINODE] = 1; X ckdir(ROOTINODE,ROOTINODE,"/"); X if (depth != 0) X panic("Inconsistent depth"); X} X X X X/* This recursively checks the directories */ Xckdir(inum, pnum, name) Xuint16 inum; Xuint16 pnum; Xchar *name; X{ X struct dinode ino; X struct direct dentry; X uint16 j; X int c; X int nentries; X char ename[150]; X X iread(inum, &ino); X if ((ino.i_mode & F_MASK) != F_DIR) X return; X ++depth; X X if (ino.i_size.o_offset % 16 != 0) X { X printf("Directory inode %d has improper length. Fix? "); X if (yes()) X { X ino.i_size.o_offset &= (~0x0f); X ++ino.i_size.o_offset; X iwrite(inum, &ino); X } X } X X nentries = 8*ino.i_size.o_blkno + ino.i_size.o_offset/16; X X for (j=0; j < nentries; ++j) X { X dirread(&ino, j, &dentry); X X if (dentry.d_ino == 0) X continue; X X if (dentry.d_ino < ROOTINODE || dentry.d_ino >= 8*filsys.s_isize) X { X printf("Directory entry %s%-1.14s has out-of-range inode %u. Zap? ", X name, dentry.d_name, dentry.d_ino); X if (yes()) X { X dentry.d_ino = 0; X dentry.d_name[0] = '\0'; X dirwrite(&ino, j, &dentry); X continue; X } X } X X if (dentry.d_ino && linkmap[dentry.d_ino] == -1) X { X printf("Directory entry %s%-1.14s points to bogus inode %u. Zap? ", X name, dentry.d_name, dentry.d_ino); X if (yes()) X { X dentry.d_ino = 0; X dentry.d_name[0] = '\0'; X dirwrite(&ino, j, &dentry); X continue; X } X } X X ++linkmap[dentry.d_ino]; X X for (c=0; c<14 && dentry.d_name[c]; ++c) X { X if (dentry.d_name[c] == '/') X { X printf("Directory entry %s%-1.14s contains slash. Fix? ", X name, dentry.d_name); X if (yes()) X { X dentry.d_name[c] = 'X'; X dirwrite(&ino, j, &dentry); X } X } X } X X if (strncmp(dentry.d_name,".",14) == 0 && dentry.d_ino != inum) X { X printf("Dot entry %s%-1.14s points to wrong place. Fix? ", X name, dentry.d_name); X if (yes()) X { X dentry.d_ino = inum; X dirwrite(&ino, j, &dentry); X } X } X X if (strncmp(dentry.d_name,"..",14) == 0 && dentry.d_ino != pnum) X { X printf("DotDot entry %s%-1.14s points to wrong place. Fix? ", X name, dentry.d_name); X if (yes()) X { X dentry.d_ino = pnum; X dirwrite(&ino, j, &dentry); X } X } X X if (dentry.d_ino != pnum && dentry.d_ino != inum && depth < MAXDEPTH) X { X strcpy(ename,name); X strcat(ename,dentry.d_name); X strcat(ename,"/"); X ckdir(dentry.d_ino,inum,ename); X } X } X --depth; X} X X X/* Pass 5 compares the link counts found in pass 4 with the inodes. */ X Xpass5() X{ X uint16 n; X struct dinode ino; X X for (n = ROOTINODE; n < 8*(filsys.s_isize-2); ++n) X { X iread(n, &ino); X X if (ino.i_mode == 0) X { X if (linkmap[n] != -1) X panic("Inconsistent linkmap"); X continue; X } X X if (linkmap[n] == -1 && ino.i_mode != 0) X panic("Inconsistent linkmap"); X X if (linkmap[n] > 0 && ino.i_nlink != linkmap[n]) X { X printf("Inode %d has link count %d should be %d. Fix? ", X n, ino.i_nlink, linkmap[n]); X if (yes()) X { X ino.i_nlink = linkmap[n]; X iwrite(n, &ino); X } X } X X if (linkmap[n] == 0) X { X if ((ino.i_mode&F_MASK) == F_BDEV || X (ino.i_mode&F_MASK) == F_CDEV || X (ino.i_size.o_blkno == 0 && ino.i_size.o_offset == 0)) X { X printf("Useless inode %d with mode 0%o has become detached. Link count is %d. Zap? ", X n, ino.i_mode, ino.i_nlink); X if (yes()) X { X ino.i_nlink = 0; X ino.i_mode = 0; X iwrite(n, &ino); X ++filsys.s_tinode; X dwrite((blkno_t)1,(char *)&filsys); X } X } X else X { X printf("Inode %d has become detached. Link count is %d. Fix? ", X n, ino.i_nlink); X if (yes()) X { X ino.i_nlink = 1; X iwrite(n, &ino); X mkentry(n); X } X } X } X } X} X X X/* This makes an entry in "lost+found" for inode n */ X Xmkentry(inum) Xuint16 inum; X{ X struct dinode rootino; X struct direct dentry; X uint16 d; X X iread(ROOTINODE,&rootino); X for (d=0; d < 32*rootino.i_size.o_blkno + rootino.i_size.o_offset/16; ++d) X { X dirread(&rootino,d,&dentry); X if (dentry.d_ino == 0 && dentry.d_name[0] == '\0') X { X dentry.d_ino = inum; X sprintf(dentry.d_name,"l+f%d",inum); X dirwrite(&rootino,d,&dentry); X return; X } X } X printf("Sorry... No empty slots in root directory.\n"); X} X X/* Beginning of fsck1.c */ X X/* Getblkno gets a pointer index, and a number of a block in the file. XIt returns the number of the block on the disk. A value of zero Xmeans an unallocated block. */ X Xchar *daread(); X Xblkno_t Xgetblkno(ino,num) Xstruct dinode *ino; Xblkno_t num; X{ X X blkno_t indb; X blkno_t dindb; X blkno_t *buf; X X if (num < 18) /* Direct block */ X { X return(ino->i_addr[num]); X } X X if (num < 256+18) /* Single indirect */ X { X indb = ino->i_addr[18]; X if (indb==0) X return(0); X buf = (blkno_t *)daread(indb); X return(buf[num - 18]); X } X X /* Double indirect */ X indb = ino->i_addr[19]; X if(indb==0) X return(0); X X buf = (blkno_t *)daread(indb); X X dindb = buf[ (num-(18+256)) >> 8]; X buf = (blkno_t *)daread(dindb); X X return(buf[ (num-(18+256)) & 0x00ff]); X} X X X/* Setblkno sets the given block number of the given file to the given Xdisk block number, possibly creating or modifiying the indirect blocks. XA return of zero means there were no blocks available to create an Xindirect block. This should never happen in fsck. */ X X Xsetblkno(ino,num,dnum) Xstruct dinode *ino; Xblkno_t num; Xblkno_t dnum; X{ X X blkno_t indb; X blkno_t dindb; X blkno_t *buf; X char *zerobuf(); X X X if (num < 18) /* Direct block */ X { X ino->i_addr[num] = dnum; X } X else if (num < 256+18) /* Single indirect */ X { X indb = ino->i_addr[18]; X if (indb==0) X panic("Missing indirect block"); X X buf = (blkno_t *)daread(indb); X buf[num - 18] = dnum; X dwrite(indb,(char *)buf); X } X else /* Double indirect */ X { X indb = ino->i_addr[19]; X if (indb == 0) X panic("Missing indirect block"); X X buf = (blkno_t *)daread(indb); X dindb = buf[ (num-(18+256)) >> 8]; X if (dindb==0) X panic("Missing indirect block"); X X buf = (blkno_t *)daread(dindb); X buf[ (num-(18+256)) & 0x00ff] = num; X dwrite(indb,(char *)buf); X } X X} X X X/* Blk_alloc allocates an unused block. XA returned block number of zero means no more blocks. */ X Xblkno_t Xblk_alloc(filsys) Xstruct filesys *filsys; X{ X X blkno_t newno; X blkno_t *buf; X int16 j; X X newno = filsys->s_free[--filsys->s_nfree]; X ifnot (newno) X { X ++filsys->s_nfree; X return(0); X } X X /* See if we must refill the s_free array */ X X ifnot (filsys->s_nfree) X { X buf = (blkno_t *)daread(newno); X filsys->s_nfree = buf[0]; X for (j=0; j < 50; j++) X { X filsys->s_free[j] = buf[j+1]; X } X } X X --filsys->s_tfree; X X if (newno < filsys->s_isize || newno >= filsys->s_fsize) X { X printf("Free list is corrupt. Did you rebuild it?\n"); X return(0); X } X X dwrite((blkno_t)1,(char *)filsys); X return(newno); X} X X X Xchar * Xdaread(blk) Xuint16 blk; X{ X char *buf; X if (da_read(dev,blk,&buf) != 512) X { X fprintf(stderr,"Read of block %d failed.\n",blk); X abort(); X } X return(buf); X} X X X Xdwrite(blk, addr) Xuint16 blk; Xchar *addr; X{ X if (d_write(dev,blk,addr) != 512) X { X fprintf(stderr,"Write of block %d failed.\n",blk); X abort(); X } X} X X X Xiread(ino, buf) Xuint16 ino; Xstruct dinode *buf; X{ X struct dinode *addr; X X addr = (struct dinode *) daread((ino>>3) + 2); X bcopy((char *)&addr[ino & 7], (char *)buf, sizeof(struct dinode)); X} X X Xiwrite(ino, buf) Xuint16 ino; Xstruct dinode *buf; X{ X struct dinode *addr; X X addr = (struct dinode *) daread((ino>>3) + 2); X bcopy((char *)buf, (char *)&addr[ino & 7], sizeof(struct dinode)); X dwrite((ino>>3) + 2,(char *)addr); X} X X Xdirread(ino, j, dentry) Xstruct dinode *ino; Xuint16 j; Xstruct direct *dentry; X{ X blkno_t blkno; X char *buf; X X blkno = getblkno(ino,(blkno_t)j/32); X if (blkno == 0) X panic("Missing block in directory"); X buf = daread(blkno); X bcopy(buf+(16*j), (char *)dentry, 16); X} X X Xdirwrite(ino, j, dentry) Xstruct dinode *ino; Xuint16 j; Xstruct direct *dentry; X{ X blkno_t blkno; X char *buf; X X blkno = getblkno(ino,(blkno_t)j/32); X if (blkno == 0) X panic("Missing block in directory"); X buf = daread(blkno); X bcopy((char *)dentry, buf+(16*j), 16); X dwrite(blkno,buf); X} X X Xyes() X{ X char line[20]; X X if (!fgets(line,sizeof(line),stdin) || (*line != 'y' && *line != 'Y')) X return(0); X X return(1); X} X X EOF_fsck.c echo 'Done' echo -n 'Extracting xdevtty.c ... ' sed 's/^X//' > xdevtty.c << 'EOF_xdevtty.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: xdevtty.c X***************************************************/ X X X#include "unix.h" X#include "extern.h" X X#define LINESIZ 128 X Xstatic char line[LINESIZ]; X Xtty_read(minor, rawflag) Xint16 minor; Xint rawflag; X{ X int nread; X X line[0] = udata.u_count; X line[1] = 0; X bdos(10,line); /* Read console buffer */ X bdos(2,'\n'); X nread = line[1]; X line[nread+2] = '\n'; X bcopy(line+2,udata.u_base,nread+1); X return(nread+1); X} X X Xtty_write(minor, rawflag) Xint16 minor; Xint rawflag; X{ X while (udata.u_count-- != 0) X { X if (*udata.u_base=='\n') X bdos(2,'\r'); X bdos(2,*udata.u_base); X ++udata.u_base; X } X} X X X_putc(c) Xint c; X{ X bdos(2,c); X} X X Xtty_open(minor) Xint minor; X{ X return(0); X} X X Xtty_close(minor) Xint minor; X{ X return(0); X} X X Xtty_ioctl(minor) Xint minor; X{ X return(-1); X} EOF_xdevtty.c echo 'Done' echo -n 'Extracting bd.c ... ' sed 's/^X//' > bd.c << 'EOF_bd.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: bd.c X***************************************************/ X X X#include <stdio.h> X#include "unix.h" X#include "extern.h" X X/* Block dump: to examine hard disk. X XUsage: bd dev blkno X X************************************************** */ X Xchar buf[512]; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int i,j; X unsigned blkno; X int dev; X X if (argc != 3 || !isdigit(argv[1][0])) X { X fprintf(stderr,"Usage: bd device blkno\n"); X exit(1); X } X X dev = atoi(argv[1]); X blkno = atoi(argv[2]); X bufinit(); X d_open(dev); X X dread(dev,blkno,buf); X X for (i=0; i < 512/24; ++i) X { X printf("%4x ",24*i); X for (j=0; j < 24; ++j) X { X if (( buf[24*i+j]&0x00ff) < 16) X printf("0%1x ",buf[24*i + j] & 0x00ff); X else X printf("%2x ",buf[24*i + j] & 0x00ff); X } X printf("\n"); X } X X exit(0); X} X X X Xdread(dev, blk, addr) Xint dev; Xuint16 blk; Xchar *addr; X{ X char *buf; X char *bread(); X X buf = bread(dev, blk, 0); X bcopy(buf, addr, 512); X bfree(buf, 0); X} EOF_bd.c echo 'Done' echo -n 'Extracting mkfs.c ... ' sed 's/^X//' > mkfs.c << 'EOF_mkfs.c' X X/************************************************** XUZI (Unix Z80 Implementation) Utilities: mkfs.c X***************************************************/ X X X#include <stdio.h> X#include "unix.h"; X#include "extern.h" X X/* This makes a filesystem */ X Xint dev; X Xextern char zerobuf(); Xdirect dirbuf[32] = { ROOTINODE,".",ROOTINODE,".." }; Xstruct dinode inode[8]; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X uint16 fsize, isize; X X if (argc != 4) X { X printf("Usage: mkfs device isize fsize\n"); X exit(-1); X } X X dev = atoi(argv[1]); X isize = (uint16)atoi(argv[2]); X fsize = (uint16)atoi(argv[3]); X X if (dev == 0 && argv[1][0] != '0') X { X printf("Invalid device\n"); X exit(-1); X } X if (dev < 0 || dev >= NDEVS) X { X printf("Invalid device\n"); X exit(-1); X } X X if (fsize < 3 || isize < 2 || isize >= fsize) X { X printf("Bad parameter values\n"); X exit(-1); X } X X X printf("Making filesystem on device %d with isize %u fsize %u. Confirm? ", X dev,isize,fsize); X if (!yes()) X exit(-1); X X bufinit(); X if (d_open(dev)) X { X printf("Can't open device"); X exit(-1); X } X X mkfs(fsize,isize); X bufsync(); X exit(0); X} X X X X Xmkfs(fsize, isize) Xuint16 fsize, isize; X{ X uint16 j; X X /* Zero out the blocks */ X X#ifdef CPM X for (j=0; j < isize; ++j) /* Don't waste time in CPM */ X dwrite(j,zerobuf()); X#else X for (j=0; j < fsize; ++j) X dwrite(j,zerobuf()); X#endif X X /* Initialize the super-block */ X X fs_tab[dev].s_mounted = SMOUNTED; /* Magic number */ X fs_tab[dev].s_isize = isize; X fs_tab[dev].s_fsize = fsize; X fs_tab[dev].s_nfree = 1; X fs_tab[dev].s_free[0] = 0; X fs_tab[dev].s_tfree = 0; X fs_tab[dev].s_ninode = 0; X fs_tab[dev].s_tinode = 8 * (isize-2) - 2; X X /* Free each block, building the free list */ X X for (j= fsize-1; j >= isize+1; --j) X { X if (fs_tab[dev].s_nfree == 50) X { X dwrite(j, (char *)&fs_tab[dev].s_nfree); X fs_tab[dev].s_nfree = 0; X } X X ++fs_tab[dev].s_tfree; X fs_tab[dev].s_free[(fs_tab[dev].s_nfree)++] = j; X } X X /* The inodes are already zeroed out */ X /* create the root dir */ X X X inode[ROOTINODE].i_mode = F_DIR | (0777 & MODE_MASK); X inode[ROOTINODE].i_nlink = 3; X inode[ROOTINODE].i_size.o_blkno = 0; X inode[ROOTINODE].i_size.o_offset = 32; X inode[ROOTINODE].i_addr[0] = isize; X X /* Reserve reserved inode */ X inode[0].i_nlink = 1; X inode[0].i_mode = ~0; X X dwrite(2,(char *)inode); X X dwrite(isize,(char *)dirbuf); X X /* Write out super block */ X dwrite(1,(char *)&fs_tab[dev]); X} X X X Xdwrite(blk, addr) Xuint16 blk; Xchar *addr; X{ X char *buf; X char *bread(); X X buf = bread(dev, blk, 1); X bcopy(addr, buf, 512); X bfree(buf, 1); X} X X Xyes() X{ X char line[20]; X X if (!fgets(line,sizeof(line),stdin) || (*line != 'y' && *line != 'Y')) X return(0); X X return(1); X} X EOF_mkfs.c echo 'Done' echo -n 'Extracting unix.azm ... ' sed 's/^X//' > unix.azm << 'EOF_unix.azm' X; Loader program for UZI image X X.pabs X.loc 100h X Xlxi sp,0100h Xlxi d,fcb Xmvi c,0fh Xcall 5 Xcpi 0ffh Xjz 0000 ;open file X Xloop: Xlhld addr Xxchg Xmvi c,1ah Xcall 5 ;set dma addr X Xlxi d,fcb Xmvi c,14h Xcall 5 ;read Xana a Xjnz move Xlhld addr Xlxi d,128 Xdad d Xshld addr Xjmp loop X X Xmove: Xlxi h,8202h Xlxi d,0ffffh Xlxi b,8010h Xlddr X Xjmp 8000h-3 X Xaddr: .word 01f8h ;initial address Xfcb: .byte 0 X .ascii 'UNIX BIN' X .byte 0,0,0,0,0 X .blkb 16 X X X X.end X X11A> EOF_unix.azm echo 'Done' echo -n 'Extracting loadutil.sub ... ' sed 's/^X//' > loadutil.sub << 'EOF_loadutil.sub' Xb:l80 $1,a:devio,xdevtty,xmachdep,a:devwd,a:devflop,a:devmisc,a:data,a:extras,xfs/s,b:libqcc/s,$1/n/y/e X EOF_loadutil.sub echo 'Done' echo -n 'Extracting filflop.sub ... ' sed 's/^X//' > filflop.sub << 'EOF_filflop.sub' Xxsub Xmkfs 1 30 500 Xy Xpip d:=e:sh[ov] Xxsub Xucp 1 Xmkdir /dev Xcd /dev Xmknod wd0 060644 0 Xmknod wd1 060644 2 Xmknod wd2 060644 3 Xmknod fd0 060644 1 Xmknod rwd0 020444 0 Xmknod rwd1 020444 2 Xmknod rwd2 020444 3 Xmknod rfd0 020444 1 Xmknod lpr 020222 4 Xmknod null 020666 6 Xmknod mem 020444 7 Xmknod kmem 020444 7 Xmknod rmt 020444 8 Xmknod swap 060644 3 Xcd / Xmkdir /tmp Xmkdir /bin Xbget init Xchmod init 0755 Xcd bin Xbget sh Xchmod sh 0755 Xbget minish Xchmod minish 0755 Xbget l Xchmod l 0755 Xbget ls Xchmod ls 0755 Xbget ps Xchmod ps 0755 Xbget ed Xchmod ed 0755 Xbget reboot Xchmod reboot 0755 Xbget dd Xchmod dd 0755 Xbget mvdir Xchmod mvdir 0755 Xbget mv Xchmod mv 0755 Xbget cat Xchmod cat 0755 Xbget chmod Xchmod chmod 0755 Xbget echo Xchmod echo 0755 Xbget fsck Xchmod fsck 0755 Xbget kill Xchmod kill 0755 Xbget lpr Xchmod lpr 0755 Xbget pwd Xchmod pwd 0755 Xbget wc Xchmod wc 0755 Xbget mkdir Xchmod mkdir 4755 Xbget rm Xchmod rm 0755 Xbget rmdir Xchmod rmdir 4755 Xbget printenv Xchmod printenv 0755 Xbget date Xchmod date 0755 Xbget ls Xchmod ls 0755 Xbget sync Xchmod sync 0755 Xexit Xunxsub EOF_filflop.sub echo 'Done' echo -n 'Extracting uzi_util.doc ... ' sed 's/^X//' > uzi_util.doc << 'EOF_uzi_util.doc' X UZI UTILITIES X XThis package contains several utilities to Xmanage UZI filesystems from a different host operating Xsystem. They have been compiled and used under CP/M Xto build and repair UZI filesystems, and debug device drivers. XThis has been useful because UZI was developed Xand compiled under CP/M. They have also Xbeen used under SYS V Unix to debug the UZI filesystem Xcode (using a Unix file to serve as a virtual UZI device). X XThere are four programs, each contained in the C file of the same name: X XMKFS: This makes a file system. It takes three arguments: a device Xnumber, the total number of blocks, and the number of inodes. X XFSCK: This checks file system consistency. It takes a single argument, Xthe device number to check. X XBD: This dumps (in hex) a block of a device. It takes two arguments: Xthe device number, and the block number to dump. X XUCP: This is an interactive program taht performs a number of operations. XIt can be used to make and delete directories and device files, Xupload and download files between the host OS and the UZI filesystem, Xlist directories, and print files. It takes a single argument, the Xdevice number. It then prompts for commands. Look at the code for a Xcomplete list of commands. X XEach program is linked with the device drivers for your system, Xsome files from UZI itself, and some modified versions of other XUZI files (the ones beginning with "x"). The file "loadutil.sub" Xshows what needs to be linked. The files "filfs.sub" and "filflop.sub" Xare examples of how these utilities are used to build and populate XUZI filesystems. X XThe file UNIX.AZM is the source (in a obscure Z80 assembly language) for Xa little program that opens the UZI binary image file, loads it Xinto memory, and starts it running from CP/M. X XIf you are trying to get UZI running on a new system, these programs Xwill be very helpful in getting your device drivers working, and Xwill allow UZI to have something on its disks when it finally runs. EOF_uzi_util.doc echo 'Done' echo -n 'Extracting filfs.sub ... ' sed 's/^X//' > filfs.sub << 'EOF_filfs.sub' Xxsub Xmkfs 0$1 200 3072 Xy Xpip d:=e:sh[ov] Xxsub Xucp 0$1 Xmkdir /dev Xcd /dev Xmknod tty 020666 5 Xmknod wd0 060644 0 Xmknod wd1 060644 2 Xmknod wd2 060644 3 Xmknod fd0 060644 1 Xmknod rwd0 020444 0 Xmknod rwd1 020444 2 Xmknod rwd2 020444 3 Xmknod rfd0 020444 1 Xmknod lpr 020222 4 Xmknod null 020666 6 Xmknod mem 020444 7 Xmknod kmem 020444 7 Xmknod rmt 020444 8 Xmknod swap 060644 3 Xcd / Xmkdir /tmp Xmkdir /bin Xbget init Xchmod init 0755 Xcd bin Xbget sh Xchmod sh 0755 Xbget minish Xchmod minish 0755 Xbget l Xchmod l 0755 Xbget ls Xchmod ls 0755 Xbget ps Xchmod ps 0755 Xbget ed Xchmod ed 0755 Xbget reboot Xchmod reboot 0755 Xbget dd Xchmod dd 0755 Xbget mvdir Xchmod mvdir 0755 Xbget mv Xchmod mv 0755 Xbget cat Xchmod cat 0755 Xbget chmod Xchmod chmod 0755 Xbget echo Xchmod echo 0755 Xbget fork Xchmod fork 0755 Xbget fsck Xchmod fsck 0755 Xbget head Xchmod head 0755 Xbget kill Xchmod kill 0755 Xbget lpr Xchmod lpr 0755 Xbget pwd Xchmod pwd 0755 Xbget mkfs Xchmod mkfs 0755 Xbget wc Xchmod wc 0755 Xbget mkdir Xchmod mkdir 4755 Xbget rm Xchmod rm 0755 Xbget rmdir Xchmod rmdir 4755 Xbget tar Xchmod tar 0755 Xbget printenv Xchmod printenv 0755 Xbget date Xchmod date 0755 Xbget ls Xchmod ls 0755 Xbget sync Xchmod sync 0755 Xbget mount Xchmod mount 0755 Xbget time Xchmod time 0755 Xbget diff Xchmod diff 0755 Xexit Xunxsub EOF_filfs.sub echo 'Done' echo -n 'Extracting filelist ... ' sed 's/^X//' > filelist << 'EOF_filelist' Xxfs.c Xxmachdep.c Xucp.c Xfsck.c Xxdevtty.c Xbd.c Xmkfs.c Xunix.azm Xloadutil.sub Xfilflop.sub Xuzi_util.doc Xfilfs.sub Xfilelist Xread.me EOF_filelist echo 'Done' echo -n 'Extracting read.me ... ' sed 's/^X//' > read.me << 'EOF_read.me' XUZI is a UNIX kernel clone written for Z-80 systems. XAll code is public domain, not being based on any AT&T code. X XThis archive is a supplement to the main archive, Xand contains programs to manipulate UZI file systems Xfrom a different host operating system. XThe file UZI_UTILS.DOC contains more information. X XThe author, Douglas Braun, can be reached at: X X7696 West Zayante Rd. XFelton, CA 95018 X Xoliveb!intelca!mipos3!cadev4!dbraun EOF_read.me echo 'Done' exit 0 Doug Braun Intel Corp CAD 408 765-4279 / decwrl \ | hplabs | -| oliveb |- !intelca!mipos3!cadev4!dbraun | amd | \ qantel /
sme@computing-maths.cardiff.ac.uk (Simon Elliott) (01/13/89)
Did anyone get the UZI utilities part 2/2? If so, please could someone mail it? Thank you in advance. -- -------------------------------------------------------------------------- Simon Elliott Internet: sme%v1.cm.cf.ac.uk@cunyvm.cuny.edu UWCC Computer Centre JANET: sme@uk.ac.cf.cm.v1 40/41 Park Place UUCP: {backbones}!mcvax!ukc!reading!cf-cm!sme Cardiff, Wales PHONE: +44 222 874300