通过$Bitmap元文件计算NTFS分区的使用空间大小
2010-05-10 11:26
316 查看
原创文章,转载请注明出处,谢谢!
作者:清林,博客名:飞空静渡
在我之前的一篇文章《如何获取NTFS卷的使用空间大小
》里说明了两张方式来获取NTFS文件系统下的分区的使用空间的大小的原理,这里,我将通过第一种方法即通过NTFS中的Bitmap元文件来计算整个分区使用空间的大小。
在《如何获取
NTFS卷的使用空间大小
》里说,在通过NTFS中的Bitmap元文件来计算整个分区使用空间的大小时,由于Bitmap不能完全表示到整个分区大小,因此有必要截取Bitmap文件,但我们可以通过Bitmap来计算自由空间大小就不需要截取Bitmap文件了,因为Bitmap中表示的超出分区的比特位都设置成1,这样分区就不会使用超出分区部分的空间,这样我们计算自由空间的大小就只计算0的部分就可以了。
下面,我通过一个程序来获取NTFS分区的自由空间大小,并把这个大小和XP系统下看到的分区的自由空间大小进行对比。
首先,我们读取分区的DBR,DBR位于分区的第一个扇区,这样我们就可以得到这个分区的信息,包括整个分区的大小。这个DBR结构是这样的(DBR结构来源于NTFS-3g代码并有修改):
这样我们就可以知道MFT的偏移位置了(mft_lcn变量)。
这样我们就可以读取第6个元文件(索引从0开始)也就是$Bitmap文件。我们获取$Bitmap文件的数据属性并获得其大小.
通过它的大小,我们可以读取整个$Bitmap文件的内容。
我们先初始化整个分区的自由空间大小为整个磁盘的大小,整个磁盘空间大小可以通过DRB来获得。
long long nr_free = m_dwlTotalClusters;
然后我们检测我们的$Bitmap内容,如果为1,我们的nr_free就相应的减1,直到我们检测完$Bitmap的所有内容。
我通过ntfs_get_attribute_value(attr, buf)函数把$Bitmap的数据的非常驻属性的内容读取到buf中,然后通过一个for循环来计算整个分区的自由空间的大小。
下面是获取一个20G左右的NTFS分区的大小的情况,并和在XP下获得的大小进行对比。如下:
程序获得大小:
the partition total size is: 20974463488
the partition free size is: 20906041344
XP下:
下面是一个200M左右的NTFS分区大小的对比情况:
程序获得大小情况:
the partition total size is: 205599232
the partition free size is: 202801152
XP下获得大小情况:
我们看到,通过$Bitmap元文件获得的分区的自由空间大小和XP下获得的自由空间的大小是非常接近的,因此,我们在没有通过windows下的API的情况,通过计算NTFS文件系统中的$Bitmap就可以获得整个分区的自由空间的大小的了,这在Linux下,在不加载分区的情况下也可以通过这样的方式来获得分区的大小。
下次说明一下如何计算FAT32和FAT16分区的自由空间大小,这个的计算要比NTFS麻烦一些了。
作者:清林,博客名:飞空静渡
在我之前的一篇文章《如何获取NTFS卷的使用空间大小
》里说明了两张方式来获取NTFS文件系统下的分区的使用空间的大小的原理,这里,我将通过第一种方法即通过NTFS中的Bitmap元文件来计算整个分区使用空间的大小。
在《如何获取
NTFS卷的使用空间大小
》里说,在通过NTFS中的Bitmap元文件来计算整个分区使用空间的大小时,由于Bitmap不能完全表示到整个分区大小,因此有必要截取Bitmap文件,但我们可以通过Bitmap来计算自由空间大小就不需要截取Bitmap文件了,因为Bitmap中表示的超出分区的比特位都设置成1,这样分区就不会使用超出分区部分的空间,这样我们计算自由空间的大小就只计算0的部分就可以了。
下面,我通过一个程序来获取NTFS分区的自由空间大小,并把这个大小和XP系统下看到的分区的自由空间大小进行对比。
首先,我们读取分区的DBR,DBR位于分区的第一个扇区,这样我们就可以得到这个分区的信息,包括整个分区的大小。这个DBR结构是这样的(DBR结构来源于NTFS-3g代码并有修改):
typedef struct { WORD bytes_per_sector; /* Size of a sector in bytes. */ BYTE sectors_per_cluster; /* Size of a cluster in sectors. */ WORD reserved_sectors; /* zero */ BYTE fats; /* zero */ WORD root_entries; /* zero */ WORD sectors; /* zero */ BYTE media_type; /* 0xf8 = hard disk */ WORD sectors_per_fat; /* zero */ /*0x0d*/WORD sectors_per_track; /* Required to boot Windows. */ /*0x0f*/WORD heads; /* Required to boot Windows. */ /*0x11*/DWORD hidden_sectors; /* Offset to the start of the partition relative to the disk in sectors. Required to boot Windows. */ /*0x15*/DWORD large_sectors; /* zero */ /* sizeof() = 25 (0x19) bytes */ }BIOS_PARAMETER_BLOCK; typedef struct { BYTE jump[3]; /* Irrelevant (jump to boot up code).*/ DWORDLONG oem_id; /* Magic "NTFS ". */ /*0x0b*/BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. */ BYTE physical_drive; /* 0x00 floppy, 0x80 hard disk */ BYTE current_head; /* zero */ BYTE extended_boot_signature; /* 0x80 */ BYTE reserved2; /* zero */ /*0x28*/DWORDLONG number_of_sectors; /* Number of sectors in volume. Gives maximum volume size of 2^63 sectors. Assuming standard sector size of 512 bytes, the maximum byte size is approx. 4.7x10^21 bytes. (-; */ DWORDLONG mft_lcn; /* Cluster location of mft data. */ DWORDLONG mftmirr_lcn; /* Cluster location of copy of mft. */ CHAR clusters_per_mft_record; /* Mft record size in clusters. */ BYTE reserved0[3]; /* zero */ CHAR clusters_per_index_record; /* Index block size in clusters. */ BYTE reserved1[3]; /* zero */ DWORDLONG volume_serial_number; /* Irrelevant (serial number). */ DWORD checksum; /* Boot sector checksum. */ /*0x54*/BYTE bootstrap[426]; /* Irrelevant (boot up code). */ WORD end_of_sector_marker; /* End of boot sector magic. Always is 0xaa55 in little endian. */ /* sizeof() = 512 (0x200) bytes */ }NTFS_BOOT_SECTOR;
这样我们就可以知道MFT的偏移位置了(mft_lcn变量)。
这样我们就可以读取第6个元文件(索引从0开始)也就是$Bitmap文件。我们获取$Bitmap文件的数据属性并获得其大小.
if (read_mft_file($Bitmap, pMftFile)) { log_error("get mft file failed"); goto error; } if (look_up_attr(AT_DATA, &pMftFile, &attr)) { log_error("can't get the bitmap data attribute!"); goto error; } l = ntfs_get_attribute_value_length(attr);
通过它的大小,我们可以读取整个$Bitmap文件的内容。
我们先初始化整个分区的自由空间大小为整个磁盘的大小,整个磁盘空间大小可以通过DRB来获得。
long long nr_free = m_dwlTotalClusters;
然后我们检测我们的$Bitmap内容,如果为1,我们的nr_free就相应的减1,直到我们检测完$Bitmap的所有内容。
if (ntfs_get_attribute_value(attr, buf) == 0) { log_error("get partition free space failed!"); goto error_buf; } { int i, j; for (i = 0; i < l; i++) for (j = 0; j < 8; j++) if ((buf[i] >> j) & 1) nr_free--; } free_size = nr_free * m_dwClusterSize;
我通过ntfs_get_attribute_value(attr, buf)函数把$Bitmap的数据的非常驻属性的内容读取到buf中,然后通过一个for循环来计算整个分区的自由空间的大小。
下面是获取一个20G左右的NTFS分区的大小的情况,并和在XP下获得的大小进行对比。如下:
程序获得大小:
the partition total size is: 20974463488
the partition free size is: 20906041344
XP下:
下面是一个200M左右的NTFS分区大小的对比情况:
程序获得大小情况:
the partition total size is: 205599232
the partition free size is: 202801152
XP下获得大小情况:
我们看到,通过$Bitmap元文件获得的分区的自由空间大小和XP下获得的自由空间的大小是非常接近的,因此,我们在没有通过windows下的API的情况,通过计算NTFS文件系统中的$Bitmap就可以获得整个分区的自由空间的大小的了,这在Linux下,在不加载分区的情况下也可以通过这样的方式来获得分区的大小。
下次说明一下如何计算FAT32和FAT16分区的自由空间大小,这个的计算要比NTFS麻烦一些了。
相关文章推荐
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- Oracle 查看表空间、数据文件的大小及使用情况
- linux下使用fstat来计算文件的大小
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- linux下使用 du查看某个文件或目录占用磁盘空间的大小方法
- c# 磁盘空间计算 和 目录空间 、 文件大小 计算
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- Oracle调整表空间大小——ORA-03297: 文件包含在请求的 RESIZE 值以外使用的数据
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- linux下使用 du查看某个文件或目录占用磁盘空间的大小
- 文件内存空间大小计算
- 查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- 使用sizeof计算普通变量所占空间大小