Системное программное обеспечение персональных ЭВМ

         

static union REGS rr; static



Пример 14

/*== ПРИМЕР 10.7 == файл 10_7_F.C == */ /*================= Работа с библиотекой =================*/ /* Функции FCB-ориентированного ввода-вывода */ #include <dos.h> #include <10_7.h> static struct { /* FCB для библиотеки */ unsigned char drive; /* идентификатор диска */ char fname[11]; /* имя и расширение */ unsigned curblk; /* текущий блок */ unsigned recsize; /* размер записи */ unsigned long fsize; /* размер файла */ unsigned date; /* дата */ unsigned time; /* время */ char reserved[8]; unsigned char currec; /* текущий номер записи */ unsigned long randrec; /* относительный номер записи */ } lib; extern int SIZE; /* размер эл-та оглавления */ extern int memb_max; /* число мест в оглавлении */ extern char libname[80]; /* имя файла-библиотеки */ extern unsigned long fptr; /* текущая позиция в файле */ static struct lib_dir a; /* буфер эл-та */ static union REGS rr; static struct SREGS sr; static struct { /* формат структуры, возвращаемой при поиске по FCB */ char drive; char fname[8]; /* имя файла */ unsigned char attr; /* атрибут */ char v[10]; /* резерв */ unsigned time; /* время */ unsigned date; /* дата */ unsigned cl; /* номер 1-го кластера */ unsigned long sz; /* размер файла */ } find; /*==== формирование неоткрытого FCB ====*/ make_fcb(void *n, /* адрес ASCIIZ-строки */ void *f) /* адрес FCB */ { rr.h.ah=0x29; /* функция ParseFnam */ sr.ds=FP_SEG(n); /* адрес ASCIIZ-строки */ rr.x.si=FP_OFF(n); sr.es=FP_SEG(f); /* адрес FCB */ rr.x.di=FP_OFF(f); intdosx(&rr,&rr,&sr); iferror("преобразования имени"); } /*==== индикация ошибки ввода-вывода ====*/ iferror(char *s) { if (rr.h.al) { printf("Ошибка %s: %x\n",s,rr.h.al); exit(); } } /*==== создание библиотеки ====*/ creat_lib() { int f; make_fcb(libname,&lib); rr.h.ah=0x0f; /* функция OpenFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); if (!rr.h.al) { close_lib(); printf("Файл %s уже существует\n",libname); do { printf("Создать файл заново (y/n)?"); if ((f=getche())=='n') { prt("\nБиблиотека не создана"); return; } } while (f!='y'); } rr.h.ah=0x16; /* функция CreatFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); iferror("создания"); printf("\nЧисло разделов MAX >"); scanf("%d",&memb_max); form_lib(); /* формирование пустого оглавления */ close_lib(); prt("Библиотека создана"); } /*==== открытие файла ====*/ int open_lib() { make_fcb(libname,&lib); rr.h.ah=0x0f; /* функция OpenFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); if (rr.h.al!=0) { printf("Файл не открыт\n"); return (0); } fptr=0; seek_dir(0); /* чтение 0-го элемента и */ read_dir(&a); /* установка memb_max */ memb_max=a.memb_size; return (1); } /*==== закрытие файла ====*/ close_lib() { rr.h.ah=0x10; /* функция CloseFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); iferror("закрытия"); } /*==== запись элемента в оглавление ====*/ write_dir(void *a) { f_rdwr(0x15,"записи",SIZE,a); } /*==== чтение элемента из оглавления ====*/ read_dir(void *a) { f_rdwr(0x14,"чтения",SIZE,a); } /*==== запись в раздел строки текста ====*/ write_memb(char *s) { fb_rdwr(0x28,"записи",strlen(s)+1,s); } /*==== чтение из раздела строки текста ====*/ read_memb(char *s) { unsigned long p; p=fptr; fb_rdwr(0x27,"чтения",200,s); fptr=p+strlen(s)+1; } /*==== ввод/вывод записи ====*/ f_rdwr(unsigned char op,char *m,int s,void *a) { /* op - функция DOS, m - сообщение на случай ошибки, s - кол.байт; a - адрес */ /* назначение DTA */ rr.h.ah=0x1a; /* функция SetDTA */ sr.ds=FP_SEG(a); /* адрес данных */ rr.x.dx=FP_OFF(a); intdosx(&rr,&rr,&sr); rr.h.ah=op; /* ф-ция ReadSeqFCB(0x14)/WriteSeqFCB(0x15) */ lib.recsize=s; /* размер записи */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); iferror(m); } /*==== блочный вывод/вывод ====*/ fb_rdwr(unsigned char op,char *m,int s,void *a) { rr.h.ah=0x1a; /* функция SetDTA */ sr.ds=FP_SEG(a); rr.x.dx=FP_OFF(a); intdosx(&rr,&rr,&sr); rr.h.ah=op; /* ф-ция ReadRdmBlk(0x27)/WriteRdmBlk(0x28) */ lib.recsize=1; /* размер записи = 1 */ lib.randrec=fptr; /* номер байта */ rr.x.cx=s; /* размер блока */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); /* для чтения ситуация EOF не аварийная */ if (!((op==0x27)&&(rr.h.al==1))) iferror(m); fptr+=s; } /*=== позиционирование указателя на элемент оглавления ===*/ seek_dir(int n) { lib.curblk=n/128; lib.currec=n%128; lib.recsize=SIZE; rr.h.ah=0x24; /* функция SetRdmBlk */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); iferror("позиционирования"); } /*==== установка указателя на конец файла ====*/ seek_eof() { lib.curblk=lib.fsize/128; lib.currec=lib.fsize%128; lib.recsize=1; rr.h.ah=0x24; /* функция SetRdmBlk */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); fptr=lib.fsize; } /*==== установка указателя на начало раздела ====*/ seek_memb(unsigned long ptr) { lib.curblk=ptr/128; lib.currec=ptr%128; lib.recsize=1; rr.h.ah=0x24; /* функция SetRdmBlk */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); iferror("позиционирования"); fptr=ptr; } /*==== поиск первого файла .LBR ====*/ int first_f(char *c) { char *s; int i; /* подготовка маски для поиска */ lib.drive=0; for(i=0;i<8;lib.fname[i++]='?'); lib.fname[i++]='L'; lib.fname[i++]='B'; lib.fname[i]='R'; rr.h.ah=0x1a; /* функция SetDTA */ sr.ds=FP_SEG(&find); /* адрес области результатов */ rr.x.dx=FP_OFF(&find); intdosx(&rr,&rr,&sr); rr.h.ah=0x11; /* функция Find1stFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); if (rr.h.al) return(0); /* перевод результата в ASCIIZ-строку */ for(s=c,i=0; (i<8)&&(find.fname[i]!=' '); *(s++)=find.fname[i++]); *(s++)='.'; for(i=8; (i<11)&&(find.fname[i]!=' '); *(s++)=find.fname[i++]); *s=0; return(1); } /*==== поиск следующего файла .LBR ====*/ int next_f(char *c) { char *s; int i; rr.h.ah=0x12; /* функция FindNxtFCB */ sr.ds=FP_SEG(&lib); /* адрес FCB */ rr.x.dx=FP_OFF(&lib); intdosx(&rr,&rr,&sr); if (rr.h.al) return(0); for(s=c,i=0; (i<8)&&(find.fname[i]!=' '); *(s++)=find.fname[i++]); *(s++)='.'; for(i=8; (i<11)&&(find.fname[i]!=' '); *(s++)=find.fname[i++]); *s=0; return(1); } /*==== переименование файла ====*/ int ren_f(char *old, char *new) { make_fcb(old,&lib); /* формир.

Пример 14

/*== ПРИМЕР 13.4 ==*/ /*================ Системные таблицы файлов ==============*/ #define byte unsigned char #define word unsigned int #define dword unsigned long #define P(x) (dos>3)?dfcb->var.dos4.x:dfcb->var.dos3.x #include <dos.h> /* Заголовок таблицы файлов */ struct SFT { struct SFT *next; word n_files; } *sft; /* Элемент таблицы файлов */ struct DFCB { /* инвариантная часть */ word n_handles; byte open_mode, reserv1, attr; word info; char *drv_ptr; word First_clust, F_time, F_date; dword F_size, F_seek; word lst_cl_n; union VAR { struct { /* для DOS 3.x */ word lst_clust, dir_sect; byte dir_num; char fname[11]; byte reserved2[6]; word owner; byte reserved4[2]; } dos3; struct { /* для DOS 4.0 и выше */ word dir_sect; byte reserved2[2], dir_num; char fname[11]; byte reserved3[6]; word owner, lst_clust; byte reserved4[6]; } dos4; } var; } *dfcb; byte dos; /* номер версии DOS */ int dfcb_size; /* размер DFCB */ word sft_seg, sft_off; /* сегм.,смещ. начала */ int files; /* счетчик файлов */ byte file; /* признак файл/устройство */ union REGS rr; struct SREGS sr; word i, j, u; char *s; main() { /* получение номера версии DOS */ rr.h.ah=0x30; intdos(&rr,&rr); dos=rr.h.al; /* установка размера DFCB */ dfcb_size= (dos>3) ? 59 : 53; /* получение адреса системных блоков */ rr.h.ah=0x52; intdosx(&rr,&rr,&sr); /* получение адреса 1-й таблицы файлов */ sft_off=peek(sr.es,rr.x.bx+4); sft_seg=peek(sr.es,rr.x.bx+6); sft=(struct SFT *)MK_FP(sft_seg,sft_off); files=0; /* счетчик файлов */ while(FP_OFF(sft)!=0xffff) { /* смещение FFFF - признак конца списка */ printf("\n\STF по адресу - %Fp (%u файлов)\n", sft,sft->n_files); dfcb=(struct DFCB *)((byte *)(sft+1)); /* 1-й DFCB */ for (i=0; i<sft->n_files; i++) { /* перебор таблицы */ printf("\nФайл %d - ",files++); if (dfcb->n_handles) { /* файл открыт */ for (j=0;j<11;j++) printf("%c",P(fname[j])); if (file=!(dfcb->info&0x0080)) printf(" (дисковый)"); else printf(" (устройство)"); printf(" \"хозяин\" - %04X ",P(owner)); if (dos>3) { /* определяется для DOS-4 и выше */ s=(char *)MK_FP(P(owner)-1,8); for(j=0;j<8;printf("%c",s[j++])); } printf("\n дескрипторов - %u;",dfcb->n_handles); printf(" режим доступа - %02X (",dfcb->open_mode); switch (dfcb->open_mode) { case 0: printf("Только чтение)");break; case 1: printf("Только запись)");break; case 2: printf("Чтение/Запись)");break; } if (file) /* только для дисковых файлов */ printf(";\n DRIVE = %c:;", 'A'+(dfcb->info&0x007)); if (!file) { printf("\n драйвер "); for(s=dfcb->drv_ptr+10,j=0; j<8; printf("%c",s[j++])); } else printf(" адр.DPB"); printf(" - %Fp;",dfcb->drv_ptr); printf(" состояние устр-ва - %04X\n",dfcb->info); if (file) { /* только для дисковых файлов */ printf(" КАТАЛОГ: нач.сектор - "); /* выбирается в зависимости от версии DOS */ if (dos<4) printf("%04X",P(dir_sect)); else printf("%04X",P(lst_clust)); printf(", номер в секторе - %u\n",P(dir_num)); printf(" ЭЛЕМЕНТ КАТАЛОГА: атрибут - %02X, ", dfcb->attr); /* время и дата - упакованном формате */ printf("время - "); u=dfcb->F_time; printf("%02d:%02d:%02d, ", u>>11,(u>>5)&0x3f,(u&0x1f)<<1); printf("дата - "); u=dfcb->F_date; printf("%d:%02d:%02d\n", u&0x1f,(u>>5)&0x0f,(u>>9)+1980); printf(" размер - %lu", dfcb->F_size); printf(", нач.класт - %04X\n",dfcb->First_clust); printf (" ТЕКУЩЕЕ СОСТОЯНИЕ: последн.кластер - "); /* выбирается в зависимости от версии DOS */ if (dos<4) printf("%04X",P(lst_clust)); else printf("%04X",P(lst_clust)); printf(" (%d), ",dfcb->lst_cl_n); printf("смещение - %lu\n",dfcb->F_seek); } } else printf("не используется\n"); if(getch()==27) exit(); /* размер элемента зависит от версии DOS */ dfcb=(struct DFCB *)((byte *)dfcb+dfcb_size); } sft=sft->next; } }
Выполнение программы в том виде, в каком она приведена здесь, не даст сколько-нибудь интересных результатов: программа "покажет" только три постоянно открытых файла - AUX, CON, PRN. Для получения более наглядного представления о функционировании STF рекомендуем читателю оформить программу в виде функции и вставить многочисленные обращения к этой функции в какую-либо программу, выполняющую интенсивную работу с файлами (например, пример 10.7).
Для файлов, открытых при помощи метода FCB в режиме разделения, создается собственная таблица, адрес и размер которой содержатся в CVT. Размер элементов этой таблицы равен размеру DFCB, формат их практически совпадает с форматом DFCB.

Содержание раздела