⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat32.c

📁 c语言编的网络操作系统。具备网络操作系统基本功能。
💻 C
字号:
/*
nexOS: nexos generic ata driver - generic ata driver FAT32 dir reader
Copyright 2004 nexOS development team

This file is part of nexOS.

nexOS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

nexOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with nexOS; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ 

/* this file just contains a test and gets removed after devfs is done */

#include "ata.h"
#include "fat32.h"
#include <libnexos-module/nexos-module.h>

extern const char *ata_map_sysid(BYTE);
extern const char ata_cmderr[][15];

DWORD fat32_firstsecofcluster(DWORD cluster, FAT32BS *bs);
void fat32_fatentry_from_cluster(DWORD cluster, FAT32BS *bs, DWORD *sector, DWORD *offset);
int fat32_buildclusterchain(ATA_DRIVE *drv, DWORD startsector, FAT32BS *bs,
                            DWORD startcluster, DWORD clusterbuf[], DWORD bufelems);
void fat32_printbs(FAT32BS *bs);

int fat32_readdir(int argc, char *argv[])
{
    if( argc < 4 )
    {
        kprintf("usage: %s <controller> <drive> <partition>\n",argv[0]);
        kprintf("Controller: 0-1\tDrive: 0-1\tPartition: 0-3\n");
        kprintf("example: %s 0 0 2\nreads fat32 dir on primary master partition 2\n",argv[0]);
        return 0;
    }
    if( argv[1][0] < '0' || argv[1][0] > '1' || argv[2][0] < '0' || 
        argv[2][0] > '1' || argv[3][0] < '0' || argv[3][0] > '3' )
    {
        kprintf("usage: %s <controller> <drive> <partition>\n",argv[0]);
        kprintf("Controller: 0-1\tDrive: 0-1\tPartition: 0-3\n");
        kprintf("example: %s 0 0 2\nreads fat32 dir on primary master partition 2\n",argv[0]);
        return 0;
    }
    ATA_DRIVE drv;
    BLOCK blk;
    int status;
    char sector[512];
    MBR *mbr = (MBR*)sector;
    int partition = argv[3][0]-0x30;

    /* load data into struct */
    drv.controller = argv[1][0] - 0x30;
    drv.drive      = argv[2][0] - 0x30;
       
    /* read MBR first to determine if the chosen partition is fat32 actually */
    
    /* the blk struct uses 64-bit LBA adresses (for future use) */
    blk.lownum = 0;
    blk.highnum = 0;
    blk.len = 1;
    blk.buf = sector;
    
    /* select drive and identify it */
    ata_select(&drv);
    ata_identify(&drv,sector);
    /* read MBR */
    if( (status = ata_readblocks(&drv,blk)) == ATA_ERR_NONE )
    {
        if( mbr->partitions[partition].systid != 0x0B )
        {
            kprintf("Selected partition type is not FAT32, but %s.\n",
                    ata_map_sysid(mbr->partitions[partition].systid));
            return 0;
        }
    }
    else
    {
        kprintf("(%s:%d)ERROR %X: %s\n",__FILE__,__LINE__,status,ata_cmderr[status]);
        return 0;
    }
    DWORD partstartsec = mbr->partitions[partition].relsect;
    FAT32BS *fat32bs = (FAT32BS*)sector;
    FAT32DIRENT direntrys[16];
    DWORD clchain[256];
    DWORD clchainlen;
    int i,j,k;
    char fname[13];
    char attrstr[7];
    BYTE namefirstbyte;
        
    /* selected partition is valid, so load the 1st sector in the partition */
    blk.lownum = partstartsec;
    blk.highnum = 0;
    blk.len = 1;
    blk.buf = fat32bs;
    if( (status = ata_readblocks(&drv,blk)) != ATA_ERR_NONE )
    {
        kprintf("(%s:%d)ERROR %X: %s\n",__FILE__,__LINE__,status,ata_cmderr[status]);
        return 0;
    }
    
    /* build the clusterchain */
    clchainlen = fat32_buildclusterchain(&drv,partstartsec,fat32bs,fat32bs->rootcluster,clchain,256);
  
    /* we use the filename buffer to hold the volume label */
    kmemset(fname,0,13);
    kmemcpy(fname,fat32bs->vollabel,11);
    /* print header */
    kprintf("Root directory on \"%s\" (%X):\n",fname,fat32bs->volid);
    kprintf("      Filename      |   Attributes   |     Size\n");
    kprintf("--------------------+----------------+-------------\n");
    
    /* cycle through all clusters and print the dir entrys */
    for( i=0; i<clchainlen; i++)
    {
        for( k=0; k<fat32bs->secpercluster; k++ )
        {
            /* load next sector of cluster */
            blk.lownum = fat32_firstsecofcluster(clchain[i],fat32bs) + partstartsec + k;
            blk.buf = direntrys;
            ata_readblocks(&drv,blk);
            for( j=0; j<16; j++ )
            {
                /* check if this is the last entry/ a valid entry */
                namefirstbyte = direntrys[j].name[0];
                if( namefirstbyte == 0x00 )
                    break;
                if( namefirstbyte != 0xE5 && namefirstbyte != 0x05 )
                {
                    /* "valid" (normal file/dir) entry, copy filename */
                    kmemset(fname,0,13);                  
                    kmemcpy(fname,direntrys[j].name,11);
                    
                    /* build attr string  */
                    kmemset(attrstr,0,7);
                    if( direntrys[j].attr & FAT32_ATTR_READ_ONLY )
                        attrstr[0] = 'r';
                    else
                        attrstr[0] = '-';
                    if( direntrys[j].attr & FAT32_ATTR_HIDDEN )
                        attrstr[1] = 'h';
                    else
                        attrstr[1] = '-';
                    if( direntrys[j].attr & FAT32_ATTR_SYSTEM )
                        attrstr[2] = 's';
                    else
                        attrstr[2] = '-';
                    if( direntrys[j].attr & FAT32_ATTR_VOLUME_ID )
                        attrstr[3] = 'v';
                    else
                        attrstr[3] = '-';
                    if( direntrys[j].attr & FAT32_ATTR_DIRECTORY )
                        attrstr[4] = 'd';
                    else
                        attrstr[4] = '-';
                    if( direntrys[j].attr & FAT32_ATTR_ARCHIVE )
                        attrstr[5] = 'a';
                    else
                        attrstr[5] = '-';
                    
                    /* ignore volume id "files" */
                    if( !(direntrys[j].attr & FAT32_ATTR_VOLUME_ID) )
                    {
                        kprintf("    %s     |     %s     |  ",fname,attrstr);
                        if( direntrys[j].size > 1<<20 ) /* megabytes */
                            kprintf("%d mb",direntrys[j].size>>20);
                        else if( direntrys[j].size > 1<<10 ) /* kilobytes */
                            kprintf("%d kb",direntrys[j].size>>10);
                        else /* bytes */
                            kprintf("%d b",direntrys[j].size);
                        
                        kprintf("\n");
                    }    
                }    
            }
        }     
    }    
    
    return 0;
}    

void fat32_printbs(FAT32BS *bs)
{
    char text[12];
    
    kmemset(text,0,12);kmemcpy(text,bs->oemname,8);kprintf("OEM name: %s\t",text);
    kmemset(text,0,12);kmemcpy(text,bs->fstype,8);kprintf("FS type: %s\t",text);
    kmemset(text,0,12);kmemcpy(text,bs->vollabel,11);kprintf("Vol.label: %s\t",text);
    kprintf("Vol.ID: %X\n",bs->volid);
    kprintf("FAT size (16/32): %d/%d\tNum FATs: %d\n",bs->fatsize16,bs->fatsize32,bs->numfats);
    kprintf("Total sectors (16/32): %d/%d\tReserved sectors: %d\n",bs->totsec16,bs->totsec32,bs->resseccnt);
    kprintf("Bytes per Sector: %X\tSectors per cluster: %d\tRootcluster: %d\n",bs->bytespersec,bs->secpercluster,bs->rootcluster);
    kprintf("Bootsector signature (must be 0xAA55): %X\n",bs->signature);
}    

void fat32_fatentry_from_cluster(DWORD cluster, FAT32BS *bs, DWORD *sector, DWORD *offset)
{
    *sector = bs->resseccnt + ((cluster*4) / bs->bytespersec);
    *offset = (cluster*4) % bs->bytespersec;
}    

DWORD fat32_firstsecofcluster(DWORD cluster, FAT32BS *bs)
{
    return ((cluster-2)*bs->secpercluster)+bs->resseccnt+(bs->fatsize32 * bs->numfats);
}

int fat32_buildclusterchain(ATA_DRIVE *drv, DWORD startsector, FAT32BS *bs,
                            DWORD startcluster, DWORD clusterbuf[], DWORD bufelems)
{
    DWORD sectorbuf[128];
    BLOCK blk;
    blk.highnum = 0;
    blk.lownum = startsector;
    blk.len = 1;
    blk.buf = sectorbuf;
    DWORD lastsector, sector, offset;
    DWORD curcluster;
    DWORD nextcluster = startcluster;
    DWORD i = 0;
    lastsector = 0;
    ata_readblocks(drv,blk);
    
    for( curcluster=startcluster; curcluster > 1 && curcluster <= 0x0FFFFFF7 && i<bufelems; i++ )
    {
        clusterbuf[i] = curcluster;
        fat32_fatentry_from_cluster(nextcluster,bs,&sector,&offset);
        if( sector != lastsector )
        {
            blk.lownum = startsector + sector;
            ata_readblocks(drv,blk);
            lastsector = sector;
        }
        curcluster = sectorbuf[offset/4];        
    }
    return i;
}    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -