printf( "\nEND-------------------------------------\n" ); } disconnect(); /* */ exit(0); } /* P_server.c ---------------------------------------------------------*/ /* * -, . */ #include <stdio.h> #include <signal.h> #include <fcntl.h> #include "P_packet.h" int datapipe, ctrlpipe, datafile, got_sig; char *dataname = "/etc/passwd"; /* waiting for signal */ #define WAITSIG while( !got_sig ) void handler(nsig){ signal( SIGUSR1, handler ); /* reset trap */ got_sig++; } /* : */ void die(nsig){ unlink( CNAME ); unlink( DNAME ); exit(0); /* , * , ! */ } main(){ struct packet pk; struct packet sendpk; /* */ setbuf( stdout, NULL ); /* make unbuffered */ /* */ mknod( DNAME, S_IFIFO | 0666, 0 ); /* create FIFO */ mknod( CNAME, S_IFIFO | 0666, 0 ); /* create FIFO */ /* die() */ signal( SIGINT, die ); signal( SIGQUIT, die ); signal( SIGTERM, die ); /* . O_NDELAY , * " ", * .. ( ), * read() "", , * 0 ( 0 ). * . */ ctrlpipe = open( CNAME, O_RDONLY | O_NDELAY ); if( ctrlpipe < 0 ){ printf( "Can't open %s\n", CNAME ); die(0); } datafile = open( dataname, O_RDONLY ); if( datafile < 0 ){ printf( "Can't open %s\n", dataname ); die(0); } /* */ sendpk.pk_code = SENDPID; sendpk.pk_pid = getpid(); /* server's pid */ sendpk.pk_blk = (-1); printf( "Server pid=%d\n", getpid()); handler(0); for(;;){ int n; static long i = 0L; /* active spin loop */ printf( "%20ld\r", i++ ); /* */ while((n = read( ctrlpipe, &pk, sizeof(pk))) > 0 ){ putchar( '\n' ); if( n != sizeof pk ){ printf( "Wrong packet size\n" ); continue; } /* */ process( &pk, &sendpk ); } } die(0); } process( pkp, spkp ) struct packet *pkp, *spkp; { char pbuf[ PBUFSIZE ]; /* FIFO- * */ datapipe = open( DNAME, O_WRONLY | O_NDELAY ); printf( "REQUEST TYPE_%d from pid=%d blk=%d\n", pkp->pk_code, pkp->pk_pid, pkp->pk_blk ); switch( pkp -> pk_code ){ case CONNECT: /* */ write( datapipe, spkp, sizeof( struct packet )); break; case RQ_READ: /* */ /* read block # pk_blk */ lseek( datafile, pkp -> pk_blk * (long)PBUFSIZE, 0 ); read( datafile, pbuf, PBUFSIZE ); write( datapipe, pbuf, PBUFSIZE ); break; case DISCONNECT: /* */ printf( "Client pid=%d finished\n", pkp -> pk_pid ); write ( datapipe, spkp, sizeof( struct packet )); break; case BYE: /* */ printf( "Server terminated.\n" ); kill( pkp-> pk_pid, SIGKILL ); die(0); default: printf( "Unknown packet type %d\n", pkp -> pk_code ); break; } close( datapipe ); /* "" */ got_sig = 0; kill( pkp -> pk_pid , SIGUSR1 ); printf( "Waiting for reply... " ); /* - */ WAITSIG; printf( "server continued\n" ); } /* 26 */ /* . * : shms & * shmc a & shmc b & shmc c & */ /* --------------------------- shm.h ----------------------- */ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <signal.h> #include <errno.h> extern errno; /* */ struct connect { /* */ int pid; int msgnum; int max; char message[128]; /* */ }; #define NSEMS 3 /* */ /* */ #define EMPTY 0 /* 1 - ; 0 - */ #define NOTEMPTY 1 /* EMPTY */ #define ACCESS 2 /* 1 - (); * 0 - - */ /* */ #define YES 1 #define NO 0 /* */ #define OPEN 1 #define CLOSE (-1) #define TEST_NO 0 #ifdef COMMENT : semop : : : nsems : : sem_op[i] : sem_id: sem[i] : again: ( ); for(i=0; i<nsems; i++) /* OPEN */ if( sem_op[i] > 0 ){ sem[i] += sem_op[i]; ( "sem[i]++" ); /* CLOSE */ }else if( sem_op[i] < 0 ){ if((newsm = sem[i] + sem_op[i]) >= 0 ){ sem[i] = newsm; if( sem[i] == 0 ) ( "sem[i]==0" ); }else{ ; ( "sem[i]++" ); goto again; } /* TEST0 */ }else{ /* sem_op[i] == 0 */ if( sem[i] != 0 ){ ; ( "sem[i]==0" ); goto again; } } -: |----------------------------------------------------------------| |: EMPTY ACCESS | |----------------------------------------------------------------| | : YES YES | |----------------------------------------------------------------| |================================================================| |loop: | |----------------------------------------------------------------| |: NO YES | |: NO(test0) NO(close) | |----------------------------------------------------------------| | ; | |----------------------------------------------------------------| |: NO NO | |: YES(open) YES(open) | |----------------------------------------------------------------| | goto loop; | |================================================================| |================================================================| |loop: | |----------------------------------------------------------------| |: YES YES | |: YES(test!=0) NO(close) | |----------------------------------------------------------------| | ; | |----------------------------------------------------------------| |: YES NO | |: NO(close) YES(open) | |----------------------------------------------------------------| | goto loop; | |================================================================| , test!=0 - NOTEMPTY, EMPTY: |----------------------------------------------------------------| |: EMPTY NOTEMPTY ACCESS | |----------------------------------------------------------------| | : YES NO YES | |----------------------------------------------------------------| |================================================================| |loop: | |----------------------------------------------------------------| |: NO - YES | |: NO(test0) - NO(close) | |----------------------------------------------------------------| | ; | |----------------------------------------------------------------| |: NO YES NO | |: YES(open) NO(close) YES(open) | |----------------------------------------------------------------| | goto loop; | |================================================================| |================================================================| |loop: | |----------------------------------------------------------------| |: - NO YES | |: - NO(test0) NO(close) | |----------------------------------------------------------------| | ; | |----------------------------------------------------------------| |: YES NO NO | |: NO(close) YES(open) YES(open) | |----------------------------------------------------------------| | goto loop; | |================================================================| #endif /*COMMENT*/ /* ------------------------------- */ key_t key = 1917; /* */ int shm_id; /* */ int sem_id; /* */ char name[40]; /* */ char far *addr; struct connect far *caddr; struct sembuf ops[NSEMS]; /* EMPTY NOTEMPTY ACCESS */ short values[NSEMS] = { YES, NO, YES }; void semtell(msg, name) char *msg, *name; { int i; semctl(sem_id, NSEMS, GETALL, values); printf( "%s %-10s: :", name, msg); for(i=0; i < NSEMS; i++) printf( " %d", values[i]); putchar('\n'); } void inisem(){ register i; for(i=0; i < NSEMS; i++ ) ops[i].sem_flg = 0; } /* --------------------------- shms.c ----------------------- */ /* Shared memory server */ #include "shm.h" int npack; /* */ void cleanup(sig){ /* ( ) */ shmctl( shm_id, IPC_RMID, NULL ); /* */ semctl( sem_id, NSEMS, IPC_RMID, NULL ); if( npack ) printf( "\t** %d **\n", npack+1); exit(0); } void main(){ register i; int pid = getpid(); FILE *fout; sprintf( name, "Server-%03d", pid ); for( i = 1; i <= SIGTERM; i++ ) signal( i, cleanup ); /* */ if((shm_id = shmget( key, sizeof(struct connect), 0644 | IPC_CREAT )) < 0 ){ perror( "shmget" ) ; exit(1); } /* */ if((addr = (char far *) shmat( shm_id, NULL, 0 )) == NULL ){ perror( "shmat" ); cleanup(); } caddr = (struct connect far *) addr; /* NSEMS */ if((sem_id = semget( key, NSEMS, 0644 |IPC_CREAT |IPC_EXCL)) < 0){ if(errno == EEXIST){ printf( " \n");exit(2); } else{ perror( "semget" ); cleanup(); } } /* */ semctl( sem_id, NSEMS, SETALL, values ); setbuf(stdout, NULL); inisem(); printf( "Server is up now. MESSAGES.\n"); fout = fopen( "MESSAGES", "w"); for(;;npack++){ printf( "%s: \n", name ); semtell("", name); ops[0].sem_num = EMPTY; ops[0].sem_op = TEST_NO; ops[1].sem_num = ACCESS; ops[1].sem_op = CLOSE; semop( sem_id, ops, 2 /* */); printf( "%s: GOT-%02d/%02d %d \"%s\"\n", name, caddr->msgnum, caddr->max, caddr->pid, caddr->message); fprintf( fout, "#%03d %02d/%02d %d \"%s\"\n", npack, caddr->msgnum, caddr->max, caddr->pid, caddr->message); if( ! strcmp(caddr->message, "-exit" )){ printf( "%s: .\n", name ); cleanup(); } semtell("", name); ops[0].sem_num = EMPTY ; ops[0].sem_op = OPEN; ops[1].sem_num = NOTEMPTY; ops[1].sem_op = CLOSE; ops[2].sem_num = ACCESS ; ops[2].sem_op = OPEN; semop( sem_id, ops, 3 /* */); } /*NOTREACHED*/ } /* --------------------------- shmc.c ----------------------- */ /* Shared memory client */ #include "shm.h" void ignsigs(sig){ register i; for( i = 1; i <= SIGTERM; i++ ) signal( i, ignsigs ); printf( " ,\n\ .\n" ); } void main(argc, argv) char **argv; { int pid = getpid(); int i, ntimes = 60; if( argc < 2 ){ fprintf( stderr, ": %s []\n", argv[0] ); fprintf( stderr, " \"-exit\" \n"); fprintf( stderr, " \"-info\" \n"); exit(1); } if( argc > 2 ) ntimes = atoi(argv[2]); sprintf( name, "Client-%03d", pid); ignsigs(); srand( pid ); /* */ if((shm_id = shmget( key, sizeof(struct connect), 0644)) < 0 ){ perror( "shmget" ); exit(2); } /* */ if((addr = (char far *) shmat( shm_id, NULL, 0 )) == NULL ){ perror( "shmat" ); exit(3); } caddr = (struct connect far *) addr; /* */ if((sem_id = semget( key, NSEMS, 0644)) < 0 ){ perror( "semget" ); exit(4); } setbuf(stdout, NULL); inisem(); if( !strcmp(argv[1], "-info")){ semtell("", name); exit(0); } for( i=0; i < ntimes; i++ ){ printf( "%s: \n", name); semtell("", name); ops[0].sem_num = NOTEMPTY; ops[0].sem_op = TEST_NO; ops[1].sem_num = ACCESS ; ops[1].sem_op = CLOSE; if( semop( sem_id, ops, 2 /* */) < 0) goto err; caddr->pid = pid; caddr->msgnum = i; caddr->max = ntimes; strncpy( caddr->message, argv[1], sizeof(caddr->message) - 1); printf( "%s: PUT-%02d \"%s\"\n", name, i, argv[1]); semtell("", name); ops[0].sem_num = EMPTY ; ops[0].sem_op = CLOSE; ops[1].sem_num = NOTEMPTY; ops[1].sem_op = OPEN; ops[2].sem_num = ACCESS ; ops[2].sem_op = OPEN; if( semop( sem_id, ops, 3 /* */) < 0) goto err; if( rand()%2 ) sleep(2); /* */ } shmdt( addr ); /* */ exit(0); err: perror("semop"); exit(5); } /* 27 */ /* -. * * . * , * "" . * * * select() . * * "" 5 . * UNIX System V. * TRACE__ * \ \ master slave * |<======\(Reader)=======!~!<====( ) * / <==\ | ! !====>() * \ | !P! | * | | !T! | * . . . . | | !Y! (Slave)--> * =|===|=>(Writer)=>!_! | \ * | | | | \ * | #####starter################## \ * |...................................| * ftty */ #include <stdio.h> #include <sys/types.h> #include <sys/signal.h> #include <termio.h> #include <sys/stat.h> #include <fcntl.h> extern int exit (); extern char *ttyname (); extern FILE * fopen (); extern errno; #define SEMAPHORE "/tmp/+++" /* */ #define TRACE "./TRACE" /* */ /* */ /* master - , * ioctl()- */ #define PTY "/dev/ptyp0" /* master */ /* slave - , */ #define TTYP "/dev/ttyp0" /* slave */ int ptyfd; FILE * ftrace = NULL; /* "" */ onintr () { closeVisual (); fprintf (stderr, "\rwriter finished\r\n"); exit (0); } /* -"" */ bye () { if (ftrace) fclose (ftrace); fprintf (stderr, "\rreader finished\r\n"); exit (0); } int visual = 0; struct termio old, new; /* "" */ initVisual () { ioctl (0, TCGETA, &old); new = old; new.c_iflag &= ~ICRNL; new.c_lflag &= ~(ECHO | ICANON); new.c_oflag &= ~(TAB3 | ONLCR); new.c_cc[VMIN] = 1; new.c_cc[VTIME] = 0; /* new.c_cc[VINTR] = ctrl('C'); */ new.c_cc[VQUIT] = 0; new.c_cc[VERASE] = 0; new.c_cc[VKILL] = 0; } /* */ openVisual () { if (visual) return; visual = 1; ioctl (0, TCSETAW, &new); } /* */ closeVisual () { if (!visual) return; visual = 0; ioctl (0, TCSETAW, &old); } struct stat st; main (argc, argv) char **argv; { int r, /* pid -"" */ w; /* pid -"" */ if (argc == 1) { fprintf (stderr, "pty CMD ...\n"); exit (1); } initVisual (); if((ptyfd = open ( PTY , O_RDWR)) < 0){ fprintf(stderr, "Cannot open pty\n"); exit(2); } /* */ r = startReader (); /* */ w = startWriter (); sleep (2); /* */ startSlave (argv + 1, r, w); /* */ while (wait (NULL) > 0); exit (0); } /* */ startSlave (argv, r, w) char **argv; { FILE * ftty; int pid; int tfd; char *tty = ttyname (1); /* */ if (!(pid = fork ())) { /* PTY SLAVE process */ ftty = fopen (tty, "w"); /* */ setpgrp (); /* ; * */ /* , , */ close (0); close (1); close (2); /* , * . * (slave) * , */ open ( TTYP, O_RDWR); open ( TTYP, O_RDWR); tfd = open ( TTYP, O_RDWR); if (tfd < 0) { fprintf (ftty, "\rSlave: can't read/write pty\r\n"); kill(r, SIGKILL); kill(w, SIGKILL); exit (1); } /* */ if (!(pid = fork ())) { fprintf (ftty, "\rCreating %s\r\n", SEMAPHORE); fflush (ftty); /* */ close (creat (SEMAPHORE, 0644)); fprintf (ftty, "\rStart %s\r\n", argv[0]); fclose(ftty); /* , * */ execvp (argv[0], argv); exit (errno); } /* */ while (wait (NULL) != pid); /* , * */ unlink (SEMAPHORE); fprintf (ftty, "\rDied.\r\n"); fflush (ftty); /* */ /* terminate reader & writer */ kill (r, SIGINT); kill (w, SIGINT); exit (0); } return pid; } /* master- */ /* ( master-) */ startReader () { char c[512]; int pid; int n; if (!(pid = fork ())) { /* ptyp */ signal (SIGINT, bye); /* */ while (stat (SEMAPHORE, &st) < 0); fprintf (stderr, "\rReader: Hello\r\n"); ftrace = fopen (TRACE, "w"); /* , */ while (stat (SEMAPHORE, &st) >= 0) { /* */ n = read (ptyfd, c, 512); if( n > 0 ) { /* */ fwrite( c, sizeof(char), n, stdout ); /* */ fwrite( c, sizeof(char), n, ftrace ); fflush (stdout); } } bye (); } return pid; } /* * "". , * - */ startWriter () { char c; int pid; if (!(pid = fork ())) { /* ptyp */ openVisual (); /* - */ signal (SIGINT, onintr); while (stat (SEMAPHORE, &st) < 0); fprintf (stderr, "\rWriter: Hello\r\n"); /* , */ while (stat (SEMAPHORE, &st) >= 0) { read (0, &c, 1); /* */ write (ptyfd, &c, 1); /* master-pty */ } onintr (); /* */ } return pid; } /* 28 */ /* * ( ). * UNIX , * . * !!! * "" () . * V7 * (""), , BSD/4.2 * . * * UNIX-. * . .. */ #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/param.h> #include <sys/ino.h> /* struct dinode: disk inode */ #include <sys/stat.h> /* struct stat */ #include <sys/dir.h> /* struct direct */ char blkflag; /* */ /* , */ char *MyAlloc( n ){ extern char *malloc(); char *ptr; ptr = malloc( n ); if( ptr == NULL ){ fprintf( stderr, "Cannot allocate %d bytes\n", n ); exit(77); } return ptr; } char DEV[] = "/dev" ; /* , */ /* st_dev . * - /dev */ char *whichdev( dev ) dev_t dev; { struct stat s; struct direct d; long i; int fd; /* */ long dsize; /* */ char *devname; if( stat( DEV, &s ) < 0 ){ fprintf( stderr, "Cannot stat %s\n", DEV ); exit(1); } if((fd = open( DEV, O_RDONLY )) < 0 ){ fprintf( stderr, "Cannot read %s\n", DEV ); exit(2); } dsize = s.st_size / sizeof( struct direct ); /* */ for( i = 0 ; i < dsize ; i++ ){ char leaf[ DIRSIZ + 1 ]; if( read( fd, &d, sizeof d ) != sizeof d ){ fprintf( stderr, "Cannot read %s\n", DEV ); exit(14); } if( ! d.d_ino ) continue; /* */ strncpy( leaf, d.d_name, DIRSIZ ); leaf[ DIRSIZ ] = '\0'; devname = MyAlloc( strlen( DEV ) + 1 + strlen( leaf ) + 1 ); /* /dev / xxxx \0 */ sprintf( devname, "%s/%s", DEV, leaf ); if( stat( devname, &s ) < 0 ){ fprintf( stderr, "Cannot stat %s\n", devname ); exit(3); } if( (s.st_mode & S_IFMT ) == S_IFBLK && s.st_rdev == dev ){ close(fd); return devname; } else free( devname ); } close( fd ); return NULL; } /* UNIX: 2.2 */ /* */ #define BLOCK 1024 /* . BSIZE <sys/param.h> */ /* */ #define NAPB (BLOCK/sizeof(daddr_t)) #define LNAPB ((long) NAPB ) /* I- I- */ #ifndef INOPB # define INOPB (BLOCK/sizeof(struct dinode)) #endif /* I- - "" . I- , , I-. I- : , , , ... - di_addr: 0 : ... DIR0 IX1: 1 , NAPB IX2: 1 . , NAPB . IX3: 1 . , NAPB . , NAPB . stat() I-. d_ino I- . */ /* 3 I- */ #define NADDR 7 /* */ #define DIR0 ((long)(NADDR-3)) /* */ #define DIR1 (DIR0 + LNAPB) /* , */ #define DIR2 (DIR0 + LNAPB + LNAPB*LNAPB) /* , */ #define DIR3 (DIR0 + LNAPB + LNAPB*LNAPB + LNAPB*LNAPB*LNAPB) /* */ #define IX1 (NADDR-3) /* */ #define IX2 (NADDR-2) /* */ #define IX3 (NADDR-1) /* , * */ daddr_t bmap( fd, ip, lb ) int fd; /* raw */ daddr_t lb; /* */ struct dinode *ip; /* I- */ { long di_map[ NADDR ]; long dd_map[ NAPB ]; /* 3 daddr_t */ l3tol( di_map, ip->di_addr, NADDR ); if( lb < DIR0 ) return di_map[ lb ]; if( lb < DIR1 ){ lb -= DIR0; lseek( fd, di_map[ IX1 ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); return dd_map[ lb % LNAPB ]; } if( lb < DIR2 ){ lb -= DIR1; lseek( fd, di_map[ IX2 ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); lseek( fd, dd_map[ lb / LNAPB ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); return dd_map[ lb % LNAPB ]; } if( lb < DIR2 ){ lb -= DIR2; lseek( fd, di_map[ IX3 ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); lseek( fd, dd_map[ lb / (LNAPB*LNAPB) ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); lseek( fd, dd_map[ lb % (LNAPB*LNAPB) ] * BLOCK, 0 ); read( fd, dd_map, BLOCK ); return dd_map[ lb % LNAPB ]; } fprintf( stderr, "Strange block %ld\n", lb ); exit(4); } /* , . . N SUM | p(j) - p(j-1) | j = 2 F = ---------------------------------- N p(j) - . , . j : 1) I- 1 ( 0), 0 - (d_ino == 0). 2) I- 2- (0-boot, 1-superblock) 3) - , N = 0, F = 0 4) (""), 0L */ double xabs( l ) daddr_t l; { return ( l < (daddr_t) 0 ? -l : l ); } double getfrag( dev, ino ) char *dev; /* */ ino_t ino; /* I- */ { struct dinode db; int fd; /* */ daddr_t i; /* . */ daddr_t op; /* . */ daddr_t ip; daddr_t nb; /* () */ long ni = 0L; /* */ double ifrag = 0.0; if((fd = open( dev, O_RDONLY )) < 0 ){ fprintf( stderr, "Cannot read %s\n", dev ); perror( "open" ); exit(5); } /* I- ino. * I- 2 * INOPB . */ lseek( fd, (( 2 + ((ino-1)/INOPB)) * (long)BLOCK ) + ( sizeof(struct dinode) * ((ino-1) % INOPB)), 0 ); if( read( fd, &db, sizeof db ) != sizeof db ){ fprintf( stderr, "Cannot read %s\n", dev ); perror( "read" ); exit(6); } /* */ nb = ((long) db.di_size + BLOCK - 1) / BLOCK; printf( "%4ld blk%s\t" , nb, nb > 1 ? "s" : " " ); /* */ if( nb == 0L ){ close(fd); return 0.0; } /* */ op = bmap( fd, &db, 0L ); /* 0-block */ if( blkflag ) printf( "%ld ", op ); for( i = 1 ; i < nb ; i++ ){ ip = bmap( fd, &db, i ); if( blkflag ) printf( "%ld ", ip ); /* , 0, ("") */ if( ip && op ){ ni++; ifrag += xabs( ip - op ); } if( ip ) op = ip; } close ( fd ); if( blkflag ) putchar( '\n' ); return ni ? (ifrag/ni) : 0.0 ; } double process( name ) char *name; { struct stat ss; char *dn; double f; /* , * name */ if( stat( name, &ss ) < 0 ){ fprintf( stderr, "Cannot stat %s\n", name ); exit(8); } /* printf( "major %d minor %d", major(ss.st_dev), minor(ss.st_dev)); */ if((dn = whichdev( ss.st_dev )) == NULL){ fprintf( stderr, "Cannot determine device\n" ); exit(9); } printf( "%-14s on %-12s %12.3f\n", name, dn, f = getfrag(dn, ss.st_ino )); free( dn ); return f; } usage( name ) char *name; { fprintf( stderr, "Usage: %s [-b] file ...\n" , name ); exit(7); } main(ac, av) char *av[]; { double fr = 0.0; int n = 0; if( ac < 2 ) usage( av[0] ); if( !strcmp( av[1], "-b" )){ blkflag = 1; av++; ac--; } while( av[1] ){ fr += process( av[1] ); n++; av++; } if( n > 1 ) printf( "\nAverage %12.3f\n", fr / n ); exit(0); } /* 29 */ /* * . * UNIX (). * . * * . * , * . * , , . */ #include <stdio.h> #include <sys/types.h> #include <sys/param.h> /* BSIZE */ #include <sys/filsys.h> /* struct filsys */ #include <sys/fblk.h> /* struct fblk */ #include <fcntl.h> #include <ctype.h> /* #define BSIZE 1024 */ int fd; /* raw disk */ int fdout; /* */ char blk[ BSIZE ], /* */ sublk[ BSIZE ]; /* */ /* */ struct filsys *super = (struct filsys *) sublk; /* */ long n = 0L; main( ac, av ) char *av[]; { daddr_t bno; /* */ extern daddr_t alloc(); if( ac < 2 ){ fprintf( stderr, "Usage: %s disk\n", av[0] ); exit(1); } if((fd = open( av[1], O_RDONLY )) < 0 ){ fprintf( stderr, "Can't read %s\n", av[1] ); exit(2); } sync(); /* syncronize */ printf( " , %s,\n", av[1] ); printf( " , \n"); printf( ", \n" ); printf( " %s\n\n", av[1] ); fflush( stdout ); sleep(2); /* */ lseek( fd, (long) BSIZE, 0 ); read( fd, sublk, BSIZE ); fprintf( stderr, "%ld free blocks at %s (%6.6s)\n" , super->s_tfree, av[1], super->s_fpack ); /* . * LIFO (), * , * . , * , , * ! */ while((bno = alloc()) >= 0L ){ save( bno ); } printf( "total %ld\n", n ); exit(0); } /* */ daddr_t alloc(){ daddr_t bno; if( super -> s_nfree <= 0 ) /* . , * */ goto nospace; /* */ bno = super -> s_free[ --super -> s_nfree ]; if( bno == (daddr_t) 0 ) goto nospace; if( super -> s_nfree <= 0 ){ /* - , * . */ printf( "Indirect block %ld\n", bno ); lseek( fd, (long) BSIZE * bno , 0 ); read ( fd, blk, BSIZE ); super -> s_nfree = ((struct fblk *)blk) -> df_nfree ; memcpy( (char *) (super -> s_free), (char *) (((struct fblk *) blk) -> df_free ), sizeof( super->s_free)); } if( super -> s_nfree <= 0 || super -> s_nfree > NICFREE ){ fprintf( stderr, "Bad free count %d\n", super->s_nfree ); goto nospace; } if( super -> s_tfree ) /* - */ super -> s_tfree --; return bno; nospace: super -> s_nfree = 0; super -> s_tfree = 0; return (-1L); /* */ } /* n */ memcpy( to, from, n ) register char *to, *from; register n; { while( n > 0 ){ *to++ = *from++; n--; } } save( bno ) daddr_t bno; { register i; char answer[ 20 ]; printf( "block %ld-------------------\n", bno ); lseek( fd, bno * BSIZE , 0 ); read ( fd, blk, BSIZE ); for( i=0; i < BSIZE; i++ ) putchar(isprint(blk[i]) || isspace(blk[i]) ? blk[i] : '.' ); printf( "\n\7===> save block %ld ? ", bno ); fflush( stdout ); gets( answer ); if( *answer == 'y' || *answer == 'Y' ){ sprintf( answer, "#%012ld", n ); fdout = creat( answer, 0644 ); if( fdout < 0 ){ fprintf( stderr, "Can't create %s\n", answer ); exit(3); } write( fdout, blk, BSIZE ); close( fdout ); } n++; } /* 30 */ /* /bin/cc -M2 -Ml -DMATCHONLY -LARGE dosfs.c match.c -o dosfs * , MS DOS, UNIX. * , UNIX- * , IBM PC. * match.c - , match(). */ #include <stdio.h> #include <fcntl.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> extern char *malloc(); /* */ extern char *strrchr(); /* */ extern long lseek(); void readBoot(), readFAT(), readRootDir(), main(), line(), getFile(), doDirectory(), mkname(), enterDir(), countFree(), traceclu(); int fd; /* - */ FILE *mapfp; /* */ int trace = 0; /* */ int ask = 1; /* */ int dironly = 0; /* 1: , */ typedef unsigned char uchar; /*typedef unsigned short ushort; sys/types.h */ /* */ struct boot { char jmp[3]; /* jmp */ char label[8]; /* */ char bfs[2]; /* boot- */ uchar sectorsPerCluster; /* */ char fatoff[2]; /* FAT */ uchar copies; /* FAT */ char dirsize[2]; /* */ char sectors[2]; /* */ uchar desc; /* */ char FATsize[2]; /* FAT */ char sectorsPerTrack[2]; /* */ char sides[2]; /* (1, 2) */ char hidden[2]; /* */ } *boot; #define SECTOR 512 /* */ int CLU; /* */ int SPC; /* */ int SECT; /* */ long capacity; /* */ ushort MAXCLU; /* + 1 */ int NDIR; /* */ int DIRSIZE; /* */ int ENTRperCLUSTER; /* */ int SPF; /* FAT */ int FATSIZE; /* FAT */ int FATSTART; /* FAT */ int NFAT; /* FAT */ uchar DESC; /* */ int DATACLU; /* ( . ) */ int bit16 = 0; /* 1 FAT 16- , 12 */ /* char[] integer */ #define INT(s) ( * (short *)s) #define LONG(s) ( * (long *)s) /* . */ struct dir{ char name[8]; /* */ char ext[3]; /* () */ uchar attrib; /* */ char unused[10]; char creat_time[2]; /* */ char creat_date[2]; /* */ char firstCluster[2]; /* */ char size[4]; /* */ }; #define isdir(attr) (attr & 0x10) /* ? */ #define islabel(attr) (attr & 0x08) /* ? */ #define eq(s1, s2) (!strcmp(s1, s2)) /* == */ struct dir *droot; /* */ char *FAT1; /* File Allocation Table, 1 */ char *FAT2; /* 2 */ char cwd[256] = ""; /* DOS. "" - */ char *root = "/tmp"; /* UNIX, */ char *pattern = NULL; /* */ char *dirpattern; /* ( ) */ char newname[256]; /* */ char cluster[4098]; /* */ /* n s */ Read(fd, s, n) char *s; { int nn = read(fd, s, n); if(nn != n ){ fprintf(stderr, " : %d %d\n", nn, n); perror( "read" ); exit(1); } return nn; } /* */ long Lseek(fd, off, how) long off; { long offf; if((offf = lseek(fd, off, how)) < 0){ fprintf(stderr, " lseek(%ld,%d)\n", off, how); } return offf; } /* */ char *Malloc(n) unsigned n;{ char *ptr = malloc(n); register unsigned i; if( !ptr){ fprintf(stderr, " malloc(%u)\n", n ); exit(2); } for(i=0; i < n ; i++ ) ptr[i] = 0; /* ptr = calloc(1,n); * */ return ptr; } /* */ void line(c) char c;{ register i; for(i=0; i < 78; i++) putchar(c); putchar('\n'); } /* - . XENIX */ char *drive(name) char *name; { if( eq(name, "360")) return "/dev/fd048ds9"; if( eq(name, "720")) return "/dev/fd096ds9"; if( eq(name, "1.2")) return "/dev/fd096ds15"; return name; } /* */ char command[512]; /* */ mkdir(name, mode) char *name; { int retcode; struct stat st; if( stat(name, &st) >= 0 && (st.st_mode & S_IFMT) == S_IFDIR ) return 0; /* */ sprintf(command, "mkdir \"%s\"", name ); retcode = system(command); /* , command */ chmod(name, mode & 0777); /* */ return retcode; /* 0 - */ } /* , ( ) */ FILE *fmdopen(name, mode) char *name, *mode; { extern errno; char *s; FILE *fp; if( fp = fopen(name, mode)) return fp; /* OK */ /* */ /* if( errno != ENOENT ) return NULL; /* - */ /* */ if((s = strrchr(name, '/' )) == NULL ) return NULL; *s = '\0'; md(name); *s = '/'; return fopen(name, mode); } /* mkdir */ md(path) char *path; {