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


Пример 14



Пример 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.




- Начало -  - Назад -  - Вперед -