1: /* v6-- accesses version 6 filesystems and copies files to */ 2: /* version 7 filesystems */ 3: /* Mike Karels, University of California Berkeley */ 4: /* Molecular Biology Department */ 5: /* (mail to virus.mike @BERKELEY) */ 6: /* (415) 642-7359 */ 7: 8: #include "inode.h" 9: #include "filsys.h" 10: #include <signal.h> 11: #include <stdio.h> 12: 13: #define BLKSIZE 512 14: #define MAXLINE 80 /* maximum input line length */ 15: #define NARG 3 /* maximum number of arguments */ 16: #define MAXARG 30 /* maximum size of input args */ 17: #define MAXSIZE BLKSIZE/sizeof(struct direct)*8 /* max number of 18: * directory entries */ 19: #define DIRSIZE 14 20: 21: struct filsys sb; /* superblock */ 22: struct inode dinode, finode; /* current dir, file inodes */ 23: struct direct 24: { 25: int d_ino; 26: char d_name[DIRSIZE]; 27: } dir[MAXSIZE], cur_dir, root = { 1, "/" }; 28: int dir_sz, fd, fo, imax; 29: char *cmd[] = { "ls", "cd", "cp", "cat", "?", "", "q", "cpdir" }; 30: 31: 32: 33: 34: main(argc,argv) 35: int argc; 36: char *argv[]; 37: { 38: extern struct direct dir[], root, cur_dir; 39: extern struct inode dinode; 40: extern int fd; 41: extern char *cmd[]; 42: char linein[MAXLINE], arg[NARG][MAXARG]; 43: int i, count, null(); 44: 45: if (argc != 2) { 46: fprintf(stderr,"Usage: v6 file, where file is block special\n"); 47: exit(1); 48: } 49: if ((fd=open(argv[1],0)) < 0) { 50: fprintf(stderr,"can't open %s\n",argv[1]); 51: exit(1); 52: } 53: if ((lseek(fd,(long)BLKSIZE,0) < 0) || 54: (read(fd,&sb,BLKSIZE) < BLKSIZE)) { 55: fprintf(stderr,"can't read superblock\n"); 56: exit(1); 57: } 58: imax = BLKSIZE / sizeof(struct inode) * (sb.isize-1); 59: if (readdir(&root) < 0) exit(1); 60: cur_dir.d_ino = root.d_ino; 61: strcpy(cur_dir.d_name,root.d_name); 62: signal(SIGINT,SIG_IGN); 63: 64: while(1) { 65: printf("* "); 66: if (getline(linein) == EOF) exit(0); 67: for (i=0; i<NARG; i++) arg[i][0] = '\0'; 68: sscanf(linein,"%s %s %s",arg[0],arg[1],arg[2]); 69: for (i = 0; (i<8) && (strcmp(arg[0],cmd[i])); i++) ; 70: switch(i) { 71: case 0: ls(arg[1]); 72: break; 73: case 1: cd(arg[1]); 74: break; 75: case 2: cp(arg[1],arg[2],1); 76: break; 77: case 3: cat(arg[1]); 78: break; 79: case 4: msg(); 80: break; 81: case 5: break; 82: case 6: exit(0); 83: case 7: cpdir(arg[1]); 84: break; 85: case 8: if (*arg[0] == '!') { 86: signal(SIGINT,null); 87: system(linein+1); 88: signal(SIGINT,SIG_IGN); 89: } 90: else fprintf(stderr,"invalid command\n"); 91: break; 92: } 93: } 94: } 95: 96: getline(linein) /* reads input line into linein */ 97: char linein[]; { 98: int i, c; 99: 100: for (i=0; i<MAXLINE-1 && (c=getchar()) != '\n' && c != EOF; 101: i++) linein[i] = c; 102: if (c == '\n') { 103: linein[i] = '\0'; 104: return(i); 105: } 106: else if (c == EOF) return(EOF); 107: else { 108: fprintf(stderr,"input line too long\n"); 109: fflush(stdin); 110: linein[0] = '\0'; 111: return(0); 112: } 113: } 114: 115: null() {} /* trap here on interrupt during system() */ 116: 117: ls(name) /* list directory 'name', current dir if no name */ 118: char *name; { 119: int i, j, flag; 120: extern struct direct dir[], cur_dir; 121: extern int dir_sz; 122: struct direct save_dir; 123: 124: flag = 0; 125: if (name[0] != '\0') { 126: flag = 1; 127: save_dir.d_ino = cur_dir.d_ino; 128: strcpy(save_dir.d_name,cur_dir.d_name); 129: if (cd(name) < 0) return; 130: } 131: j=0; 132: for (i=0; i<dir_sz; i++) 133: if (dir[i].d_ino != 0 ) 134: printf("%-14s%c", dir[i].d_name, 135: ++j%4 ? '\t':'\n'); 136: if (j%4) putchar('\n'); 137: if (flag) { 138: readdir(&save_dir); 139: cur_dir.d_ino = save_dir.d_ino; 140: strcpy(cur_dir.d_name,save_dir.d_name); 141: } 142: } 143: cpdir(arg) /* copy contents of current directory */ 144: char *arg; { 145: int i; 146: extern struct direct dir[]; 147: extern int dir_sz; 148: 149: if (arg[0] != '\0') { 150: fprintf(stderr,"no arguments allowed for cpdir\n"); 151: return(-1); 152: } 153: for (i=0; i<dir_sz; i++) 154: if ((dir[i].d_ino != 0) && (dir[i].d_name[0] != '.')) 155: cp(dir[i].d_name,dir[i].d_name,1); 156: return(0); 157: } 158: 159: cd(name) /* returns 0 if successful, else -1 */ 160: char *name; { /* returns to previous directory if unsuccesssful */ 161: extern struct inode dinode; 162: extern struct direct dir[], cur_dir, root; 163: extern int dir_sz; 164: int i, ino; 165: char *c, *rindex(); 166: struct direct *pdir, *find(), save_dir; 167: 168: if ((i=iindex(name,'/')) >= 0) { 169: if (i==0) { 170: readdir(&root); 171: name++; 172: } 173: if (name[0]=='\0') { 174: cur_dir.d_ino = root.d_ino; 175: strcpy(cur_dir.d_name,root.d_name); 176: return(0); 177: } 178: if (*((c=rindex(name,'/'))+1) == '\0') *c = '\0'; 179: /* removes trailing '/' if present */ 180: while ((i=iindex(name,'/')) != -1) { 181: name[i] = '\0'; 182: if ((pdir=find(name)) == NULL) { 183: fprintf(stderr,"can't find %s\n",name); 184: readdir(&cur_dir); 185: return(-1); 186: } 187: if (readdir(pdir) < 0) return(-1); 188: name += i+1; 189: } 190: } 191: if ((pdir=find(name))==NULL) { 192: fprintf(stderr,"can't find %s\n",name); 193: readdir(&cur_dir); 194: return(-1); 195: } 196: ino = pdir->d_ino; 197: if (readdir(pdir) >= 0) { 198: cur_dir.d_ino = ino; 199: strcpy(cur_dir.d_name,name); 200: return(0); 201: } 202: else return(-1); 203: } 204: 205: iindex(s,c) 206: char *s, c; { 207: int i; 208: 209: for (i=0; ; i++) { 210: if (s[i] == c) return(i); 211: if (s[i] == NULL) return(-1); 212: } 213: } 214: 215: struct direct *find(name) /* returns pointer to "name" entry */ 216: char *name; { /* in dir[], NULL if not found */ 217: extern struct direct dir[]; 218: int i; 219: extern int dir_sz; 220: 221: for (i=0; i<dir_sz; i++) 222: if ((strcmp(dir[i].d_name,name) == 0) && 223: (dir[i].d_ino != 0)) 224: break; 225: if (i==dir_sz) return(NULL); 226: return(&(dir[i])); 227: } 228: 229: #define MODE 0644 230: #define STDOUT 1 231: 232: cp(ifile,ofile,mode) /* copies v6 ifile to v7 ofile if mode 1 */ 233: char *ifile, *ofile; /* cats ifile if mode 0 */ 234: int mode; { 235: 236: extern struct inode finode; 237: extern struct direct dir[], cur_dir; 238: extern int fd,fo; 239: int n, i, j, blk, flag, indir[BLKSIZE/2]; 240: long size; 241: char buf[BLKSIZE], *tname; 242: struct direct *pdir, save_dir; 243: 244: flag = 0; 245: if (ofile[0] == '\0' && mode == 1) { 246: fprintf(stderr,"Usage: cp v6file v7file\n"); 247: goto quit; 248: } 249: if ((mode==1) && ((fo=open(ofile,0) != -1))) { 250: fprintf(stderr,"%s already exists\n",ofile); 251: goto quit; 252: } 253: if (mode == 1) { 254: if ((fo= creat(ofile,MODE)) < 0) { 255: fprintf(stderr,"can't create %s\n",ofile); 256: goto quit; 257: } 258: } 259: else fo = dup(STDOUT); 260: if (iindex(ifile,'/') != -1) { 261: flag = 1; 262: save_dir.d_ino = cur_dir.d_ino; 263: strcpy(save_dir.d_name,cur_dir.d_name); 264: tname = rindex(ifile,'/'); 265: *tname = '\0'; 266: if (cd(ifile) < 0) return; 267: ifile = tname + 1; 268: } 269: if ((pdir = find(ifile)) == NULL) { 270: fprintf(stderr,"can't find %s\n",ifile); 271: goto quit; 272: } 273: if (readi(pdir->d_ino,&finode) < 0) goto quit; 274: if (finode.flags & (IFCHR | IFBLK)) { 275: /* is special file or directory */ 276: fprintf(stderr,"cp: %s not a regular file\n"); 277: goto quit; 278: } 279: size = finode.size1 + ((long)(finode.size0 & 0377) << 8); 280: if (finode.flags & IFLRG) /* file is large */ 281: for (blk=0; size>0; blk++) { 282: if (blk == 7) { 283: fprintf(stderr,"%s is huge file, cp incomplete\n", 284: ifile); 285: goto quit; 286: } 287: if (readblk(finode.addr[blk],indir) < BLKSIZE) 288: goto quit; 289: for (i=0; ((i<BLKSIZE/2) && (size > 0)); i++) { 290: if (indir[i]==0) 291: for (j=0; j<BLKSIZE/2; j++) 292: buf[j] = 0; 293: else if (readblk(indir[i],buf) < BLKSIZE) 294: goto quit; 295: n = (size < BLKSIZE) ? size : BLKSIZE; 296: if (write(fo,buf,n) != n) { 297: if (mode == 1) 298: fprintf(stderr,"write error\n"); 299: else putchar('\n'); 300: goto quit; 301: } 302: size -= BLKSIZE; 303: } 304: } 305: else for (blk=0; size>0 && blk<8; blk++) { 306: if (finode.addr[blk]==0) 307: for (j=0; j<BLKSIZE/2; j++) 308: buf[j] = 0; 309: else if (readblk(finode.addr[blk],buf) < BLKSIZE) 310: goto quit; 311: n = (size<BLKSIZE) ? size : BLKSIZE; 312: if (write(fo,buf,n) != n) { 313: if (mode == 1) fprintf(stderr,"write error\n"); 314: else putchar('\n'); 315: goto quit; 316: } 317: size -= BLKSIZE; 318: } 319: quit: if (fo != STDOUT) close(fo); 320: if (flag) { 321: readdir(&save_dir); 322: cur_dir.d_ino = save_dir.d_ino; 323: strcpy(cur_dir.d_name,save_dir.d_name); 324: } 325: } 326: 327: readdir(pdir) /* reads pdir->d_inode into dinode, then */ 328: struct direct *pdir; /* reads corresponding directory into dir */ 329: { /* reads cur_dir on error, then returns -1 */ 330: extern struct inode dinode; 331: extern struct direct dir[], cur_dir; 332: extern int dir_sz, fd; 333: char buf[BLKSIZE]; 334: int blk, sz, i, n; 335: long size; 336: 337: if (pdir->d_ino == 0) return(-1); 338: if (readi(pdir->d_ino,&dinode) < 0) return(-1); 339: if (!(dinode.flags & IFDIR)) { /* not a directory */ 340: fprintf(stderr,"%s not a directory\n",pdir->d_name); 341: readdir(&cur_dir); 342: return(-1); 343: } 344: if (dinode.flags & IFLRG) { /* file is large */ 345: fprintf(stderr,"Ouch, %s is large\n",pdir->d_name); 346: readdir(&cur_dir); 347: return(-1); 348: } 349: size = dinode.size1 + (long)(dinode.size0 & 0377) << 8; 350: sz = 0; 351: n = BLKSIZE/sizeof(struct direct); 352: for (blk=0; size>0 && blk<8; blk++) 353: if (dinode.addr[blk] > 0) { 354: if (readblk(dinode.addr[blk],&dir[sz])<BLKSIZE) 355: return(-1); 356: sz += (size<BLKSIZE ? size : BLKSIZE) 357: /sizeof(struct direct); 358: size -= BLKSIZE; 359: } 360: dir_sz = sz; 361: return(dir_sz); 362: } 363: 364: readi(inum,pinode) /* reads inode inum into *pinode */ 365: int inum; 366: struct inode *pinode; { 367: extern int fd, imax; 368: 369: if (inum < 1 || inum > imax) { 370: fprintf(stderr,"bad inode number, %d\n",inum); 371: return(-1); 372: } 373: if ((lseek(fd,((long)2*BLKSIZE + 374: (long)(inum-1)*(sizeof(struct inode))),0) < 0) || 375: (read(fd,pinode,sizeof(struct inode)) < 0)) { 376: fprintf(stderr,"can't read inode %d\n",inum); 377: return(-1); 378: } 379: return(0); 380: } 381: 382: readblk(blk,buf) /* reads block blk into buf */ 383: int blk; 384: char *buf; { 385: extern struct filsys sb; 386: extern int fd; 387: int n; 388: 389: if ((blk < sb.isize-1) || (blk >= sb.fsize)) { 390: fprintf(stderr,"bad block number %d\n",blk); 391: return(-1); 392: } 393: if (lseek(fd,(long)(BLKSIZE)*(long)(blk),0) < 0) { 394: fprintf(stderr,"seek error, block %d\n",blk); 395: return(-1); 396: } 397: if ((n=read(fd,buf,BLKSIZE)) != BLKSIZE) 398: fprintf(stderr,"read error, block %d\n",blk); 399: return(n); 400: } 401: 402: cat(ifile) /* prints ifile on terminal, using cp */ 403: char *ifile; { 404: 405: int flush(); 406: signal(SIGINT,flush); 407: cp(ifile,NULL,0); /* mode 0 signals print on tty */ 408: signal(SIGINT,SIG_IGN); 409: } 410: 411: flush() { /* closes fo to terminate a cat() */ 412: extern int fo; 413: close(fo); 414: return; 415: } 416: 417: msg() { 418: printf("commands:\n"); 419: printf("\t ls [dir]: list directory contents, current dir default\n"); 420: printf("\t cd name: change to (v6) directory 'name'\n"); 421: printf("\t cat name: print (v6) file 'name' on terminal\n"); 422: printf("\t cp name1 name2: copy (v6) 'name1' to (v7) file 'name2'\n"); 423: printf("\t cpdir: copy all files in current v6 directory\n"); 424: printf("\t\tto current v7 directory\n"); 425: printf("\t q or ^d: quit\n"); 426: }