pmt: revert 7f8090b
This commit is contained in:
@@ -1,433 +0,0 @@
|
||||
/*
|
||||
libparted
|
||||
Copyright (C) 1998-2000, 2002, 2007, 2009-2014, 2019-2023 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "fat.h"
|
||||
|
||||
#ifndef DISCOVER_ONLY
|
||||
|
||||
/* returns the minimum size of clusters for a given file system type */
|
||||
PedSector _GL_ATTRIBUTE_CONST
|
||||
fat_min_cluster_size (FatType fat_type) {
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12: return 1;
|
||||
case FAT_TYPE_FAT16: return 1024/512;
|
||||
case FAT_TYPE_FAT32: return 4096/512;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PedSector _GL_ATTRIBUTE_CONST
|
||||
_smallest_power2_over (PedSector ceiling)
|
||||
{
|
||||
PedSector result = 1;
|
||||
|
||||
while (result < ceiling)
|
||||
result *= 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* returns the minimum size of clusters for a given file system type */
|
||||
PedSector _GL_ATTRIBUTE_CONST
|
||||
fat_recommend_min_cluster_size (FatType fat_type, PedSector size) {
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12: return 1;
|
||||
case FAT_TYPE_FAT16: return fat_min_cluster_size(fat_type);
|
||||
case FAT_TYPE_FAT32:
|
||||
return PED_MAX(_smallest_power2_over(size
|
||||
/ MAX_FAT32_CLUSTERS),
|
||||
fat_min_cluster_size (fat_type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns the maxmimum size of clusters for a given file system type */
|
||||
PedSector _GL_ATTRIBUTE_CONST
|
||||
fat_max_cluster_size (FatType fat_type) {
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12: return 1; /* dunno... who cares? */
|
||||
case FAT_TYPE_FAT16: return 65536/512;
|
||||
case FAT_TYPE_FAT32: return 65536/512;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns the minimum number of clusters for a given file system type */
|
||||
FatCluster _GL_ATTRIBUTE_CONST
|
||||
fat_min_cluster_count (FatType fat_type) {
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12:
|
||||
case FAT_TYPE_FAT16:
|
||||
return fat_max_cluster_count (fat_type) / 2;
|
||||
|
||||
case FAT_TYPE_FAT32: return 0xfff0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns the maximum number of clusters for a given file system type */
|
||||
FatCluster _GL_ATTRIBUTE_CONST
|
||||
fat_max_cluster_count (FatType fat_type) {
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12: return 0xff0;
|
||||
case FAT_TYPE_FAT16: return 0xfff0;
|
||||
case FAT_TYPE_FAT32: return 0x0ffffff0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* what is this supposed to be? What drugs are M$ on? (Can I have some? :-) */
|
||||
PedSector _GL_ATTRIBUTE_CONST
|
||||
fat_min_reserved_sector_count (FatType fat_type)
|
||||
{
|
||||
return (fat_type == FAT_TYPE_FAT32) ? 32 : 1;
|
||||
}
|
||||
|
||||
int
|
||||
fat_check_resize_geometry (const PedFileSystem* fs,
|
||||
const PedGeometry* geom,
|
||||
PedSector new_cluster_sectors,
|
||||
FatCluster new_cluster_count)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
PedSector free_space;
|
||||
PedSector min_free_space;
|
||||
PedSector total_space;
|
||||
PedSector new_total_space;
|
||||
PedSector dir_space;
|
||||
|
||||
PED_ASSERT (geom != NULL);
|
||||
|
||||
dir_space = fs_info->total_dir_clusters * fs_info->cluster_sectors;
|
||||
free_space = fs_info->fat->free_cluster_count
|
||||
* fs_info->cluster_sectors;
|
||||
total_space = fs_info->fat->cluster_count * fs_info->cluster_sectors;
|
||||
new_total_space = new_cluster_count * new_cluster_sectors;
|
||||
min_free_space = total_space - new_total_space + dir_space;
|
||||
|
||||
PED_ASSERT (new_cluster_count
|
||||
<= fat_max_cluster_count (FAT_TYPE_FAT32));
|
||||
|
||||
if (free_space < min_free_space) {
|
||||
char* needed = ped_unit_format (geom->dev, min_free_space);
|
||||
char* have = ped_unit_format (geom->dev, free_space);
|
||||
ped_exception_throw (
|
||||
PED_EXCEPTION_ERROR,
|
||||
PED_EXCEPTION_CANCEL,
|
||||
_("You need %s of free disk space to shrink this "
|
||||
"partition to this size. Currently, only %s is "
|
||||
"free."),
|
||||
needed, have);
|
||||
free (needed);
|
||||
free (have);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* DO NOT EDIT THIS ALGORITHM!
|
||||
* As far as I can tell, this is the same algorithm used by Microsoft to
|
||||
* calculate the size of the file allocaion tables, and the number of clusters.
|
||||
* I have not verified this by dissassembling Microsoft code - I came to this
|
||||
* conclusion by empirical analysis (i.e. trial and error - this was HORRIBLE).
|
||||
*
|
||||
* If you think this code makes no sense, then you are right. I will restrain
|
||||
* the urge to inflict serious bodily harm on Microsoft people.
|
||||
*/
|
||||
|
||||
static int
|
||||
entries_per_sector (FatType fat_type)
|
||||
{
|
||||
switch (fat_type) {
|
||||
case FAT_TYPE_FAT12:
|
||||
return 512 * 3 / 2;
|
||||
case FAT_TYPE_FAT16:
|
||||
return 512 / 2;
|
||||
case FAT_TYPE_FAT32:
|
||||
return 512 / 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
calc_sizes (PedSector size, PedSector align, FatType fat_type,
|
||||
PedSector root_dir_sectors, PedSector cluster_sectors,
|
||||
FatCluster* out_cluster_count, PedSector* out_fat_size)
|
||||
{
|
||||
PedSector data_fat_space; /* space available to clusters + FAT */
|
||||
PedSector fat_space; /* space taken by each FAT */
|
||||
PedSector cluster_space; /* space taken by clusters */
|
||||
FatCluster cluster_count;
|
||||
int i;
|
||||
|
||||
PED_ASSERT (out_cluster_count != NULL);
|
||||
PED_ASSERT (out_fat_size != NULL);
|
||||
|
||||
data_fat_space = size - fat_min_reserved_sector_count (fat_type)
|
||||
- align;
|
||||
if (fat_type == FAT_TYPE_FAT16)
|
||||
data_fat_space -= root_dir_sectors;
|
||||
|
||||
fat_space = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (fat_type == FAT_TYPE_FAT32)
|
||||
cluster_space = data_fat_space - fat_space;
|
||||
else
|
||||
cluster_space = data_fat_space - 2 * fat_space;
|
||||
|
||||
cluster_count = cluster_space / cluster_sectors;
|
||||
fat_space = ped_div_round_up (cluster_count + 2,
|
||||
entries_per_sector (fat_type));
|
||||
}
|
||||
|
||||
cluster_space = data_fat_space - 2 * fat_space;
|
||||
cluster_count = cluster_space / cluster_sectors;
|
||||
|
||||
/* looks like this should be part of the loop condition?
|
||||
* Need to build the Big Table TM again to check
|
||||
*/
|
||||
if (fat_space < ped_div_round_up (cluster_count + 2,
|
||||
entries_per_sector (fat_type))) {
|
||||
fat_space = ped_div_round_up (cluster_count + 2,
|
||||
entries_per_sector (fat_type));
|
||||
}
|
||||
|
||||
if (cluster_count > fat_max_cluster_count (fat_type)
|
||||
|| cluster_count < fat_min_cluster_count (fat_type))
|
||||
return 0;
|
||||
|
||||
*out_cluster_count = cluster_count;
|
||||
*out_fat_size = fat_space;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int
|
||||
fat_calc_sizes (PedSector size, PedSector align, FatType fat_type,
|
||||
PedSector root_dir_sectors,
|
||||
PedSector* out_cluster_sectors, FatCluster* out_cluster_count,
|
||||
PedSector* out_fat_size)
|
||||
{
|
||||
PedSector cluster_sectors;
|
||||
|
||||
PED_ASSERT (out_cluster_sectors != NULL);
|
||||
PED_ASSERT (out_cluster_count != NULL);
|
||||
PED_ASSERT (out_fat_size != NULL);
|
||||
|
||||
for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size);
|
||||
cluster_sectors <= fat_max_cluster_size (fat_type);
|
||||
cluster_sectors *= 2) {
|
||||
if (calc_sizes (size, align, fat_type, root_dir_sectors,
|
||||
cluster_sectors,
|
||||
out_cluster_count, out_fat_size)) {
|
||||
*out_cluster_sectors = cluster_sectors;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size);
|
||||
cluster_sectors >= fat_min_cluster_size (fat_type);
|
||||
cluster_sectors /= 2) {
|
||||
if (calc_sizes (size, align, fat_type, root_dir_sectors,
|
||||
cluster_sectors,
|
||||
out_cluster_count, out_fat_size)) {
|
||||
*out_cluster_sectors = cluster_sectors;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* only make the cluster size really small (<4k) if a bigger one is
|
||||
* isn't possible. Windows never makes FS's like this, but it
|
||||
* seems to work... (do more tests!)
|
||||
*/
|
||||
for (cluster_sectors = 4; cluster_sectors > 0; cluster_sectors /= 2) {
|
||||
if (calc_sizes (size, align, fat_type, root_dir_sectors,
|
||||
cluster_sectors,
|
||||
out_cluster_count, out_fat_size)) {
|
||||
*out_cluster_sectors = cluster_sectors;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Same as fat_calc_sizes, except it only attempts to match a particular
|
||||
* cluster size. This is useful, because the FAT resizer can only shrink the
|
||||
* cluster size.
|
||||
*/
|
||||
int
|
||||
fat_calc_resize_sizes (
|
||||
const PedGeometry* geom,
|
||||
PedSector align,
|
||||
FatType fat_type,
|
||||
PedSector root_dir_sectors,
|
||||
PedSector cluster_sectors,
|
||||
PedSector* out_cluster_sectors,
|
||||
FatCluster* out_cluster_count,
|
||||
PedSector* out_fat_size)
|
||||
{
|
||||
PED_ASSERT (geom != NULL);
|
||||
PED_ASSERT (out_cluster_sectors != NULL);
|
||||
PED_ASSERT (out_cluster_count != NULL);
|
||||
PED_ASSERT (out_fat_size != NULL);
|
||||
|
||||
/* libparted can only reduce the cluster size at this point */
|
||||
for (*out_cluster_sectors = cluster_sectors;
|
||||
*out_cluster_sectors >= fat_min_cluster_size (fat_type);
|
||||
*out_cluster_sectors /= 2) {
|
||||
if (calc_sizes (geom->length, align, fat_type, root_dir_sectors,
|
||||
*out_cluster_sectors,
|
||||
out_cluster_count, out_fat_size))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculates the number of sectors needed to be added to cluster_offset,
|
||||
to make the cluster on the new file system match up with the ones
|
||||
on the old file system.
|
||||
However, some space is reserved by fat_calc_resize_sizes() and
|
||||
friends, to allow room for this space. If too much of this space is left
|
||||
over, everyone will complain, so we have to be greedy, and use it all up...
|
||||
*/
|
||||
PedSector _GL_ATTRIBUTE_PURE
|
||||
fat_calc_align_sectors (const PedFileSystem* new_fs,
|
||||
const PedFileSystem* old_fs)
|
||||
{
|
||||
FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
|
||||
FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs);
|
||||
PedSector raw_old_meta_data_end;
|
||||
PedSector new_meta_data_size;
|
||||
PedSector min_new_meta_data_end;
|
||||
PedSector new_data_size;
|
||||
PedSector new_clusters_size;
|
||||
PedSector align;
|
||||
|
||||
new_meta_data_size
|
||||
= fat_min_reserved_sector_count (new_fs_info->fat_type)
|
||||
+ new_fs_info->fat_sectors * 2;
|
||||
|
||||
if (new_fs_info->fat_type == FAT_TYPE_FAT16)
|
||||
new_meta_data_size += new_fs_info->root_dir_sector_count;
|
||||
|
||||
raw_old_meta_data_end = old_fs->geom->start
|
||||
+ old_fs_info->cluster_offset;
|
||||
|
||||
min_new_meta_data_end = new_fs->geom->start + new_meta_data_size;
|
||||
|
||||
if (raw_old_meta_data_end > min_new_meta_data_end)
|
||||
align = (raw_old_meta_data_end - min_new_meta_data_end)
|
||||
% new_fs_info->cluster_sectors;
|
||||
else
|
||||
align = (new_fs_info->cluster_sectors
|
||||
- ( (min_new_meta_data_end - raw_old_meta_data_end)
|
||||
% new_fs_info->cluster_sectors ))
|
||||
% new_fs_info->cluster_sectors;
|
||||
|
||||
new_data_size = new_fs->geom->length - new_meta_data_size;
|
||||
new_clusters_size = new_fs_info->cluster_count
|
||||
* new_fs_info->cluster_sectors;
|
||||
|
||||
while (new_clusters_size + align + new_fs_info->cluster_sectors
|
||||
<= new_data_size)
|
||||
align += new_fs_info->cluster_sectors;
|
||||
|
||||
return align;
|
||||
}
|
||||
|
||||
int _GL_ATTRIBUTE_PURE
|
||||
fat_is_sector_in_clusters (const PedFileSystem* fs, PedSector sector)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
return sector >= fs_info->cluster_offset
|
||||
&& sector < fs_info->cluster_offset
|
||||
+ fs_info->cluster_sectors * fs_info->cluster_count;
|
||||
}
|
||||
|
||||
FatFragment _GL_ATTRIBUTE_PURE
|
||||
fat_cluster_to_frag (const PedFileSystem* fs, FatCluster cluster)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2);
|
||||
|
||||
return (cluster - 2) * fs_info->cluster_frags;
|
||||
}
|
||||
|
||||
FatCluster _GL_ATTRIBUTE_PURE
|
||||
fat_frag_to_cluster (const PedFileSystem* fs, FatFragment frag)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);
|
||||
|
||||
return frag / fs_info->cluster_frags + 2;
|
||||
}
|
||||
|
||||
PedSector _GL_ATTRIBUTE_PURE
|
||||
fat_frag_to_sector (const PedFileSystem* fs, FatFragment frag)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);
|
||||
|
||||
return frag * fs_info->frag_sectors + fs_info->cluster_offset;
|
||||
}
|
||||
|
||||
FatFragment _GL_ATTRIBUTE_PURE
|
||||
fat_sector_to_frag (const PedFileSystem* fs, PedSector sector)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (sector >= fs_info->cluster_offset);
|
||||
|
||||
return (sector - fs_info->cluster_offset) / fs_info->frag_sectors;
|
||||
}
|
||||
|
||||
PedSector _GL_ATTRIBUTE_PURE
|
||||
fat_cluster_to_sector (const PedFileSystem* fs, FatCluster cluster)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2);
|
||||
|
||||
return (cluster - 2) * fs_info->cluster_sectors
|
||||
+ fs_info->cluster_offset;
|
||||
}
|
||||
|
||||
FatCluster _GL_ATTRIBUTE_PURE
|
||||
fat_sector_to_cluster (const PedFileSystem* fs, PedSector sector)
|
||||
{
|
||||
FatSpecific* fs_info = FAT_SPECIFIC (fs);
|
||||
|
||||
PED_ASSERT (sector >= fs_info->cluster_offset);
|
||||
|
||||
return (sector - fs_info->cluster_offset) / fs_info->cluster_sectors
|
||||
+ 2;
|
||||
}
|
||||
#endif /* !DISCOVER_ONLY */
|
||||
Reference in New Issue
Block a user