struct stat st; char *s; int code; if( !*path) return 0; /* kornevoj katalog "/" */ if( stat(path, &st) >= 0 ){ /* sushchestvuet */ if((st.st_mode & S_IFMT) == S_IFDIR) return 0; /* OK */ printf( "%s - ne katalog\n", path ); return 1; /* FAIL */ } if( s = strrchr(path, '/')){ *s = '\0'; code = md(path); *s = '/'; if( code ) return code; /* Oblom */ } sprintf(command, "mkdir \"%s\"", path ); return system(command); /* 0 esli OK */ } /* Skonstruirovat' imya fajla v stile UNIX. * V MS DOS vse bukvy v imenah - bol'shie */ void mkname( res, n, e ) char *res, *n, *e; { /* res - rezul'tat, n - imya, e - suffiks */ register i; char *start = res; if( n[0] == 0x05 ) n[0] = 0xE5; /* podstavnoj simvol */ for(i=0; i < 8 && n[i] && n[i] != ' ' ; i++) *res++ = n[i]; if( e[0] != ' ') *res++ = '.'; for(i=0; i < 3 && e[i] && e[i] != ' ' ; i++) *res++ = e[i]; *res = '\0'; while( *start ){ if( isalpha(*start) && isupper(*start)) *start = tolower(*start); start++; } } /* ------------------------------------------------------- */ /* Poluchit' zapis' iz FAT dlya klastera clu */ ushort numCluster(clu) ushort clu; { ushort n; if( clu >= MAXCLU ) printf( "Slishkom bol'shoj nomer klastera %03X >= %03X\n", clu, MAXCLU ); if( bit16 ){ /* 16 bit na nomer klastera */ n = INT( &FAT1[ 2*clu ]); n &= 0xFFFF; return n; } /* inache 12 bit na nomer klastera */ n = clu + clu/2 ; n = INT( &FAT1[n] ); if( clu % 2 ){ /* nechetnyj */ n >>= 4; } n &= 0xFFF; return n; } /* Uznat' sleduyushchij klaster fajla. 0 esli poslednij */ ushort nextCluster(clu) ushort clu; { clu = numCluster(clu); if( clu >= (bit16 ? 0xFFF8 : 0xFF8 )) return 0; /* EOF */ return clu; } /* Prochest' klaster i sohranit' ego v fajle i bufere */ getCluster(clu, fp, size, buffer) ushort clu; /* logicheskij klaster (2..) */ FILE *fp; /* fajl dlya spaseniya */ long size; /* ostalos' dopisat' */ char *buffer; /* bufer dlya klastera */ { long offset; int rd, howmuchtoread; if( size <= 0L ){ printf( "CLUSTER %03X lishnij\n", clu ); exit(3); } /* Vychislit' smeshchenie. Klastery numeruyutsya nachinaya s #2 */ offset = (clu - 2 + DATACLU) * (long) CLU; Lseek(fd, offset, 0); /* Skol'ko bajt prochest' ? */ howmuchtoread = (size > CLU) ? CLU : size; rd = Read(fd, buffer, howmuchtoread); if( fp != NULL ) fwrite(buffer, 1, rd, fp); return ( rd < 0 ) ? 0 : rd; } /* ------------------------------------------------------------------ * dosfs -rPATH fajly skidyvayutsya v katalog PATH, a ne v /tmp * dosfs ... "shablon" sbrasyvayutsya tol'ko fajly s podhodyashchimi * imenami, naprimer: * dosfs 1.2 "/*.c" *.c iz kornya diskety * dosfs 1.2 "/dir1/*.c" *.c iz kataloga /dir1 * dosfs 1.2 "*.c" *.c iz vseh katalogov * dosfs -d tol'ko prosmotr katalogov, bez sbrosa fajlov * Primer: dosfs -qr. 360 */ void main(argc, argv) char *argv[]; { if( argc < 2 ) goto usage; if( *argv[1] == '-' ){ /* razbor klyuchej */ char *keys = &argv[1][1]; while(*keys){ switch(*keys){ case 't': /* vklyuchit' trassirovku */ trace++; if((mapfp = fopen( ".Map", "w" )) == NULL ) trace = 0; break; case 'q': /* bez zaprosov (quiet) */ ask = 0; break; case 'r': /* perenaznachit' root */ root = keys+1; goto breakwhile; case 'd': /* dosfs -d == komanda dir */ dironly++; break; } keys++; } breakwhile: argc--; argv++; } if( argc < 2 ) goto usage; if( pattern = argv[2] ){ /* mozhet byt' NULL */ char *s = strrchr(pattern, '/'); if(s){ /* PATH/PATTERN */ dirpattern = pattern; /* PATH */ *s = '\0'; pattern = s+1; /* PATTERN */ }else{ /* prosto PATTERN */ dirpattern = NULL; } } setbuf(stdout, NULL); /* otmenit' buferizaciyu */ readBoot(drive(argv[1])); readFAT(); countFree(); readRootDir(); exit(0); usage: printf( "Vyzov: dosfs [-dqtrDIR] ustrojstvo [\"shablon\"]\n" ); exit(4); } /* Prochest' boot-sector, vychislit' raznye parametry diskety */ void readBoot(dsk) char *dsk; { char BOOT[SECTOR]; int skips, sides; if((fd = open( dsk, O_RDONLY)) < 0 ){ fprintf(stderr, "Ne mogu chitat' %s\n", dsk); exit(5); } /* nulevoj sektor diskety - boot */ Read(fd, BOOT, SECTOR); boot = (struct boot *) BOOT; line('-'); printf( "Sformatirovano \"%8.8s\"\n", boot->label ); printf( "Razmer boot-sektora %d bajt\n", INT(boot->bfs)); printf( "Klaster soderzhit %d sektorov\n", SPC = boot->sectorsPerCluster ); printf( "Disketa soderzhit %d sektorov ", SECT = INT(boot->sectors)); capacity = SECT * (long) SECTOR; printf( "(%ld KB)\n", capacity / 1024L ); printf( "Na treke %d sektorov\n", INT(boot->sectorsPerTrack)); sides = INT(boot->sides); printf( "Disk imeet %d storon%c\n\n", sides, sides==1? 'u':'y'); printf( "Smeshchenie do FAT %d sektor\n", skips = INT(boot->fatoff)); printf( "Imeetsya %d kopii FAT\n", NFAT = boot->copies ); printf( "FAT zanimaet %d sektorov\n\n", SPF = INT(boot->FATsize)); printf( "Kornevoj katalog soderzhit %d zapisej\n\n", NDIR = INT(boot->dirsize)); printf( "Opisatel' diskety = %02X\t(", DESC = boot->desc ); switch( DESC ){ case 0xFF: printf( "double sided, 8 sectors per track" ); break; case 0xFE: printf( "single sided, 8 sectors per track" ); break; case 0xFD: printf( "double sided, 9 sectors per track" ); break; case 0xFC: printf( "single sided, 9 sectors per track" ); break; case 0xF9: printf( "double sided, 15 sectors per track"); break; case 0xF8: printf( "Winchester" ); bit16++; break; default: printf( "neizvestnyj tip" ); break; } printf( ")\n"); printf( "Na diske %d spryatannyh sektorov\n", INT(boot->hidden)); /* Vychislit' harakteristiki */ CLU = SECTOR * SPC; /* razmer klastera v bajtah */ FATSIZE = SECTOR * SPF; /* dlina FAT v bajtah */ FATSTART = SECTOR * skips; /* smeshchenie v bajtah do FAT */ /* dlina kornevogo kataloga v bajtah */ DIRSIZE = NDIR * sizeof(struct dir); /* fizicheskij nomer pervogo klastera dannyh */ DATACLU = ((long) FATSTART + (long) FATSIZE * NFAT + (long) DIRSIZE ) / CLU; printf( "Pervyj klaster dannyh (fiz.) = %d\n", DATACLU ); /* chislo zapisej kataloga v klastere */ ENTRperCLUSTER = CLU / sizeof(struct dir); /* chislo sektorov dlya dannyh */ MAXCLU = (SECT - DATACLU * SPC); /* chislo klasterov dlya dannyh */ MAXCLU = MAXCLU / SPC; /* logicheskie nomera klasterov idut s #2 */ MAXCLU += 2; } /* Prochest' File Allocation Table (tablicu razmeshcheniya fajlov) */ void readFAT(){ register int i; FAT1 = Malloc(FATSIZE); Lseek(fd, (long) FATSTART, 0); Read(fd, FAT1, FATSIZE); if(NFAT > 1){ FAT2 = Malloc(FATSIZE); Read(fd, FAT2, FATSIZE); /* Sravnit' kopii FAT */ for(i=0; i < FATSIZE; i++ ) if(FAT1[i] != FAT2[i]){ printf( "kopii FAT razlichayutsya v %d/%d\n", i, FATSIZE ); break; } free( FAT2 ); } if( DESC != FAT1[0] ) printf( "U FAT drugoj opisatel': %02X\n", FAT1[0] & 0xFF ); } /* Prochest' kornevoj katalog diskety. * On raspolozhen srazu zhe posle kopij FAT */ void readRootDir(){ if( DIRSIZE % SECTOR ) printf( "Razmer kataloga ne kraten sektoru\n" ); Lseek(fd, (long)FATSTART + (long)FATSIZE * NFAT, 0); droot = (struct dir *) Malloc(DIRSIZE); Read(fd, droot, DIRSIZE ); /* NDIR dolzhno byt' 112 dlya 360K i 720K * 224 dlya 1.2 Mb */ if( !dironly ) mkdir( root, 0755 ); line('-'); doDirectory(0, NDIR, droot); } /* Obrabotat' katalog (napechatat', spasti fajly, obojti podkatalogi) */ #define PRINT \ for(j=0; j < level; j++ ) printf( " " ); /* otstup */ \ printf( "%02d\t%s/%-14s %12ld %s\n", \ strt + i, \ cwd, \ basename, \ size, \ isdir(dd[i].attrib) ? "<DIR>" : \ islabel(dd[i].attrib) ? "<LAB>" : "" ) void doDirectory(strt, entries, dd) struct dir dd[]; { register i, j; char basename[40]; static int level = 0; int need_to_get; /* nado li sbrasyvat' */ /* line('-'); */ for(i=0; i < entries; i++ ){ uchar c; long size; if((c = *dd[i].name) == 0xE5 || !c) continue; /* fajl stert (dyra) */ mkname(basename, dd[i].name, dd[i].ext); size = LONG(dd[i].size); /* razmer fajla */ /* proverit' shablon imeni, esli nuzhno */ if( !pattern || /* pattern zadan i */ ( (!dirpattern || eq(cwd, dirpattern)) && match(basename, pattern) ) ){ PRINT; need_to_get = !dironly; } else need_to_get = 0; if(isdir(dd[i].attrib)){ /* sebya i roditelya proignorirovat' */ if( eq(basename, "." ) || eq(basename, "..")) continue; level++; /* U katalogov pochemu-to size == 0 */ enterDir( basename, INT(dd[i].firstCluster), need_to_get); level--; } else if( islabel(dd[i].attrib)){ printf( "Volume label:%11.11s\n", dd[i].name ); } else if( need_to_get ) getFile ( basename, INT(dd[i].firstCluster), size); } /* line('#'); */ } /* Prochest' fajl v UNIX-nuyu fajlovuyu sistemu */ void getFile(name, clu, size) char *name; /* imya fajla */ ushort clu; /* nachal'nyj klaster */ long size; /* razmer */ { FILE *fp; /* fajl kuda sohranyat' */ struct stat st; ushort nclu = 0;/* poryadkovyj nomer klastera */ sprintf(newname, "%s%s/%s", root, cwd, name ); if( ask && stat(newname, &st) >= 0 ){ char answer[30]; fprintf(stderr, "%s uzhe sushchestvuet, perezapisat'? ", newname); gets(answer); if( *answer != 'y' ) return; fprintf( stderr, "\tOK\n" ); } if((fp = fmdopen( newname, "w" )) == NULL){ printf( "Ne mogu sozdat' %s\n", newname ); return; } if( trace ) fprintf( mapfp, "\n%s/%s:", cwd, name ); while( clu ){ if( trace ) traceclu(nclu++, clu); size -= getCluster(clu, fp, size, cluster); clu = nextCluster(clu); } fclose(fp); } /* Obrabotat' podkatalog */ void enterDir(name, clu, create) char *name; /* imya */ ushort clu; /* nachal'nyj klaster */ { char *tail, *myCluster; struct dir *dsub; ushort nclu; int nentries; /* chislo zapisej v kataloge */ /* Korrekciya cwd */ tail = cwd + strlen(cwd); *tail = '/'; strcpy(tail+1, name); if( create ){ /* sozdat' */ sprintf( newname, "%s%s", root, cwd ); mkdir ( newname, 0755); } if( trace ) fprintf( mapfp, "\nDIR %s:", cwd); myCluster = Malloc( sizeof cluster ); dsub = (struct dir *) myCluster; nentries = nclu = 0; while( clu ){ if( trace ) traceclu(nclu++, clu); /* Prochest' ocherednoj klaster kataloga */ getCluster(clu, NULL,(long) CLU, myCluster); /* Obrabotat' imena v etom klastere */ doDirectory(nentries, ENTRperCLUSTER, dsub); nentries += ENTRperCLUSTER; /* Vzyat' sleduyushchij klaster */ clu = nextCluster(clu); } *tail = '\0'; free(myCluster); } /* Podschet svobodnyh i plohih klasterov. */ void countFree(){ int isFree = 0; /* svobodnye klastery */ int isBad = 0; /* sbojnye klastery */ int isReserved = 0; /* spryatannye klastery */ register ushort n = 0; register ushort clu; /* tekushchij analiziruemyj klaster */ int nline = 300; if( trace ) fprintf(mapfp, "\t\tFAT chart\n"); for(clu=0; clu < MAXCLU; clu++){ if( clu >= 2 ){ n = numCluster(clu); if( n == 0 ) isFree++; if( n == (bit16 ? 0xFFF7 : 0xFF7)) isBad++; if( n >= (bit16 ? 0xFFF0 : 0xFF0 ) && n < (bit16 ? 0xFFF7 : 0xFF7 )) isReserved++; } if( trace ){ if( nline >= 8){ nline = 0; fprintf( mapfp, "\n%03X:\t", clu ); } else nline++; fprintf( mapfp, "%03X ", n ); } } line('='); printf( "Svobodno %ld, isporcheno %ld, rezerv %d klasterov\n", (long)isFree * CLU, /* v bajtah */ (long)isBad * CLU, isReserved ); } void traceclu(nclu, clu) ushort nclu, clu; { if( nclu % 16 == 0 ) fprintf( mapfp, "\n\t" ); fprintf( mapfp, "%03X ", clu ); } #ifdef LOCAL_MALLOC /* Obratite vnimanie, chto v etoj programme pamyat' otvoditsya malloc() i osvobozhdaetsya free() po principu steka (LIFO). My mogli by pereopredelit' standartnye funkcii malloc() i free(), zastaviv ih rabotat' so staticheskoj pamyat'yu! (Esli my napishem svoyu funkciyu s imenem, kak u standartnoj, to budet ispol'zovat'sya NASHA funkciya). */ static char allocArena[32 * 1024]; static char *top = allocArena; char *malloc(n){ char *ptr; /* okruglit' do celogo chisla slov */ /* delenie s ostatkom */ /* chislo int-ov: */ n = (n + (sizeof(int)-1)) / sizeof(int); /* chislo char-ov:*/ n *= sizeof(int); ptr = top; top += n; return ptr; } free(ptr) char *ptr; { top = ptr; } #endif /*LOCAL_MALLOC*/ /* Primer 31 */ /* Introspektivnaya programma: pechataet sama sebya */ #include <stdio.h> char *text[] = { "#include <stdio.h>", "char *text[] = {", " NULL};", "/* Programma, pechatayushchaya svoj sobstvennyj tekst */", "main(){ int i;", " puts(text[0]); puts(text[1]);", " for(i=0; text[i]; i++) putq(text[i]);", " for(i=2; text[i]; i++) puts(text[i]);", "}", "putq(s) char *s; {", " printf(\"\\t\\\"\");", " while(*s){", " if(*s == '\"') printf(\"\\\\\\\"\");", " else if(*s == '\\\\') printf(\"\\\\\\\\\");", " else putchar(*s);", " s++;", " }", " printf(\"\\\",\\n\");", "}", NULL}; /* Programma, pechatayushchaya svoj sobstvennyj tekst */ main(){ int i; puts(text[0]); puts(text[1]); for(i=0; text[i]; i++) putq(text[i]); for(i=2; text[i]; i++) puts(text[i]); } putq(s) char *s; { printf("\t\""); while(*s){ if(*s == '"') printf("\\\""); else if(*s == '\\') printf("\\\\"); else putchar(*s); s++; } printf("\",\n"); } /* Primer 32 */ /* C beautify: programma cb.c, formatiruyushchaya ishodnyj * tekst programmy na Si. Tekst vzyat iz distributiva UNIX */ #include <stdio.h> #include <stdlib.h> #define gets getlex #define puts putlex /* prototipy */ void main(int argc, char *argv[]); void ptabs( void ); int getch( void ); void puts( void ); int lookup( char *tab[] ); int gets( void ); void gotelse( void ); int getnl( void ); void comment( void ); int slevel[10]; int clevel = 0; int spflg[20][10]; int sind [20][10]; int siflev[10]; int sifflg[10]; int iflev = 0; int ifflg = -1; int level = 0; int ind[10] = { 0,0,0,0,0,0,0,0,0,0 }; int eflg = 0; int paren = 0; int pflg[10] = { 0,0,0,0,0,0,0,0,0,0 }; char lchar; char pchar; int aflg = 0; int ct; int stabs[20][10]; int qflg = 0; char *wif[] = { "if",NULL}; char *welse[] = { "else", NULL}; char *wfor[] = { "for" , NULL}; char *wds[] = { "case","default", NULL}; int j = 0; char string[200]; char cc; int sflg = 1; int peek = -1; int tabs = 0; int lastchar; int c; void main(int argc, char *argv[]) { if( argc > 1 ){ if( freopen( argv[1], "r", stdin ) == NULL ){ fprintf(stderr, "Can't open %s\n", argv[1] ); exit(1); } } if( argc > 2 ){ if( freopen( argv[2], "w", stdout ) == NULL ){ fprintf(stderr, "Can't create %s\n", argv[2] ); exit(1); } } while((c = getch()) != EOF){ switch(c){ case ' ': case '\t': if(lookup(welse) == 1){ gotelse(); if(sflg == 0 || j > 0) string[j++] = c; puts(); sflg = 0; if(getnl() == 1){ puts(); printf("\n"); sflg = 1; pflg[level]++; tabs++; } continue; } if(sflg == 0 || j > 0) string[j++] = c; continue; case '\n': if((eflg = lookup(welse)) == 1) gotelse(); puts(); printf("\n"); sflg = 1; if(eflg == 1){ pflg[level]++; tabs++; } else if(pchar == lchar) aflg = 1; continue; case '{': if(lookup(welse) == 1) gotelse(); siflev[clevel] = iflev; sifflg[clevel] = ifflg; iflev = ifflg = 0; clevel++; if(sflg == 1 && pflg[level] != 0){ pflg[level]--; tabs--; } string[j++] = c; puts(); getnl(); puts(); printf("\n"); tabs++; sflg = 1; if(pflg[level] > 0){ ind[level] = 1; level++; slevel[level] = clevel; } continue; case '}': clevel--; if((iflev = siflev[clevel]-1) < 0) iflev = 0; ifflg = sifflg[clevel]; if(pflg[level] >0 && ind[level] == 0){ tabs -= pflg[level]; pflg[level] = 0; } puts(); tabs--; ptabs(); if((peek = getch()) == ';'){ printf("%c;", c); peek = -1; } else printf("%c", c); getnl(); puts(); printf("\n"); sflg = 1; if(clevel < slevel[level])if(level > 0) level--; if(ind[level] != 0){ tabs -= pflg[level]; pflg[level] = 0; ind[level] = 0; } continue; case '"': case '\'': string[j++] = c; while((cc = getch()) != c){ string[j++] = cc; if(cc == '\\'){ string[j++] = getch(); } if(cc == '\n'){ puts(); sflg = 1; } } string[j++] = cc; if(getnl() == 1){ lchar = cc; peek = '\n'; } continue; case ';': string[j++] = c; puts(); if(pflg[level] > 0 && ind[level] == 0){ tabs -= pflg[level]; pflg[level] = 0; } getnl(); puts(); printf("\n"); sflg = 1; if(iflev > 0) if(ifflg == 1){ iflev--; ifflg = 0; } else iflev = 0; continue; case '\\': string[j++] = c; string[j++] = getch(); continue; case '?': qflg = 1; string[j++] = c; continue; case ':': string[j++] = c; if(qflg == 1){ qflg = 0; continue; } if(lookup(wds) == 0){ sflg = 0; puts(); } else{ tabs--; puts(); tabs++; } if((peek = getch()) == ';'){ printf(";"); peek = -1; } getnl(); puts(); printf("\n"); sflg = 1; continue; case '/': string[j++] = c; if((peek = getch()) != '*') continue; string[j++] = peek; peek = -1; comment(); continue; case ')': paren--; string[j++] = c; puts(); if(getnl() == 1){ peek = '\n'; if(paren != 0) aflg = 1; else if(tabs > 0){ pflg[level]++; tabs++; ind[level] = 0; } } continue; case '#': string[j++] = c; while((cc = getch()) != '\n') string[j++] = cc; string[j++] = cc; sflg = 0; puts(); sflg = 1; continue; case '(': string[j++] = c; paren++; if(lookup(wfor) == 1){ while((c = gets()) != ';'); ct=0; cont: while((c = gets()) != ')'){ if(c == '(') ct++; } if(ct != 0){ ct--; goto cont; } paren--; puts(); if(getnl() == 1){ peek = '\n'; pflg[level]++; tabs++; ind[level] = 0; } continue; } if(lookup(wif) == 1){ puts(); stabs[clevel][iflev] = tabs; spflg[clevel][iflev] = pflg[level]; sind[clevel][iflev] = ind[level]; iflev++; ifflg = 1; } continue; default: string[j++] = c; if(c != ',') lchar = c; } } } void ptabs( void ){ int i; for(i=0; i < tabs; i++) printf("\t"); } int getch( void ){ if(peek < 0 && lastchar != ' ' && lastchar != '\t') pchar = lastchar; lastchar = (peek<0) ? getc(stdin) : peek; peek = -1; return(lastchar); } void puts( void ){ if(j > 0){ if(sflg != 0){ ptabs(); sflg = 0; if(aflg == 1){ aflg = 0; if(tabs > 0) printf(" "); } } string[j] = '\0'; printf("%s",string); j = 0; } else{ if(sflg != 0){ sflg = 0; aflg = 0; } } } int lookup( char *tab[] ) { char r; int l,kk,k,i; if(j < 1) return(0); kk=0; while(string[kk] == ' ') kk++; for(i=0; tab[i] != 0; i++){ l=0; for(k=kk;(r = tab[i][l++]) == string[k] && r != '\0';k++); if(r == '\0' && (string[k] < 'a' || string[k] > 'z' || k >= j)) return(1); } return(0); } int gets( void ){ char ch; beg: if((ch = string[j++] = getch()) == '\\'){ string[j++] = getch(); goto beg; } if(ch == '\'' || ch == '"'){ while((cc = string[j++] = getch()) != ch) if(cc == '\\') string[j++] = getch(); goto beg; } if(ch == '\n'){ puts(); aflg = 1; goto beg; } else return(ch); } void gotelse( void ){ tabs = stabs[clevel][iflev]; pflg[level] = spflg[clevel][iflev]; ind[level] = sind [clevel][iflev]; ifflg = 1; } int getnl( void ){ while((peek = getch()) == '\t' || peek == ' '){ string[j++] = peek; peek = -1; } if((peek = getch()) == '/'){ peek = -1; if((peek = getch()) == '*'){ string[j++] = '/'; string[j++] = '*'; peek = -1; comment(); } else string[j++] = '/'; } if((peek = getch()) == '\n'){ peek = -1; return(1); } return(0); } void comment( void ){ rep: while((c = string[j++] = getch()) != '*') if(c == '\n'){ puts(); sflg = 1; } gotstar: if((c = string[j++] = getch()) != '/'){ if(c == '*') goto gotstar; goto rep; } }