1*9663SMark.Logan@Sun.COM /*
2*9663SMark.Logan@Sun.COM libparted
3*9663SMark.Logan@Sun.COM Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
4*9663SMark.Logan@Sun.COM
5*9663SMark.Logan@Sun.COM This program is free software; you can redistribute it and/or modify
6*9663SMark.Logan@Sun.COM it under the terms of the GNU General Public License as published by
7*9663SMark.Logan@Sun.COM the Free Software Foundation; either version 3 of the License, or
8*9663SMark.Logan@Sun.COM (at your option) any later version.
9*9663SMark.Logan@Sun.COM
10*9663SMark.Logan@Sun.COM This program is distributed in the hope that it will be useful,
11*9663SMark.Logan@Sun.COM but WITHOUT ANY WARRANTY; without even the implied warranty of
12*9663SMark.Logan@Sun.COM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*9663SMark.Logan@Sun.COM GNU General Public License for more details.
14*9663SMark.Logan@Sun.COM
15*9663SMark.Logan@Sun.COM You should have received a copy of the GNU General Public License
16*9663SMark.Logan@Sun.COM along with this program. If not, see <http://www.gnu.org/licenses/>.
17*9663SMark.Logan@Sun.COM */
18*9663SMark.Logan@Sun.COM
19*9663SMark.Logan@Sun.COM #include <config.h>
20*9663SMark.Logan@Sun.COM #include <string.h>
21*9663SMark.Logan@Sun.COM #include <uuid/uuid.h>
22*9663SMark.Logan@Sun.COM
23*9663SMark.Logan@Sun.COM #include "fat.h"
24*9663SMark.Logan@Sun.COM #include "calc.h"
25*9663SMark.Logan@Sun.COM
26*9663SMark.Logan@Sun.COM PedFileSystem*
fat_alloc(const PedGeometry * geom)27*9663SMark.Logan@Sun.COM fat_alloc (const PedGeometry* geom)
28*9663SMark.Logan@Sun.COM {
29*9663SMark.Logan@Sun.COM PedFileSystem* fs;
30*9663SMark.Logan@Sun.COM
31*9663SMark.Logan@Sun.COM fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
32*9663SMark.Logan@Sun.COM if (!fs)
33*9663SMark.Logan@Sun.COM goto error;
34*9663SMark.Logan@Sun.COM
35*9663SMark.Logan@Sun.COM fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific));
36*9663SMark.Logan@Sun.COM if (!fs->type_specific)
37*9663SMark.Logan@Sun.COM goto error_free_fs;
38*9663SMark.Logan@Sun.COM
39*9663SMark.Logan@Sun.COM fs->geom = ped_geometry_duplicate (geom);
40*9663SMark.Logan@Sun.COM if (!fs->geom)
41*9663SMark.Logan@Sun.COM goto error_free_type_specific;
42*9663SMark.Logan@Sun.COM
43*9663SMark.Logan@Sun.COM fs->checked = 0;
44*9663SMark.Logan@Sun.COM return fs;
45*9663SMark.Logan@Sun.COM
46*9663SMark.Logan@Sun.COM error_free_type_specific:
47*9663SMark.Logan@Sun.COM ped_free (fs->type_specific);
48*9663SMark.Logan@Sun.COM error_free_fs:
49*9663SMark.Logan@Sun.COM ped_free (fs);
50*9663SMark.Logan@Sun.COM error:
51*9663SMark.Logan@Sun.COM return NULL;
52*9663SMark.Logan@Sun.COM }
53*9663SMark.Logan@Sun.COM
54*9663SMark.Logan@Sun.COM /* Requires the boot sector to be analysed */
55*9663SMark.Logan@Sun.COM int
fat_alloc_buffers(PedFileSystem * fs)56*9663SMark.Logan@Sun.COM fat_alloc_buffers (PedFileSystem* fs)
57*9663SMark.Logan@Sun.COM {
58*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
59*9663SMark.Logan@Sun.COM
60*9663SMark.Logan@Sun.COM fs_info->buffer_sectors = BUFFER_SIZE;
61*9663SMark.Logan@Sun.COM fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512);
62*9663SMark.Logan@Sun.COM if (!fs_info->buffer)
63*9663SMark.Logan@Sun.COM goto error;
64*9663SMark.Logan@Sun.COM
65*9663SMark.Logan@Sun.COM fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2);
66*9663SMark.Logan@Sun.COM if (!fs_info->cluster_info)
67*9663SMark.Logan@Sun.COM goto error_free_buffer;
68*9663SMark.Logan@Sun.COM
69*9663SMark.Logan@Sun.COM return 1;
70*9663SMark.Logan@Sun.COM
71*9663SMark.Logan@Sun.COM error_free_buffer:
72*9663SMark.Logan@Sun.COM ped_free (fs_info->buffer);
73*9663SMark.Logan@Sun.COM error:
74*9663SMark.Logan@Sun.COM return 0;
75*9663SMark.Logan@Sun.COM }
76*9663SMark.Logan@Sun.COM
77*9663SMark.Logan@Sun.COM void
fat_free_buffers(PedFileSystem * fs)78*9663SMark.Logan@Sun.COM fat_free_buffers (PedFileSystem* fs)
79*9663SMark.Logan@Sun.COM {
80*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
81*9663SMark.Logan@Sun.COM
82*9663SMark.Logan@Sun.COM ped_free (fs_info->cluster_info);
83*9663SMark.Logan@Sun.COM ped_free (fs_info->buffer);
84*9663SMark.Logan@Sun.COM }
85*9663SMark.Logan@Sun.COM
86*9663SMark.Logan@Sun.COM void
fat_free(PedFileSystem * fs)87*9663SMark.Logan@Sun.COM fat_free (PedFileSystem* fs)
88*9663SMark.Logan@Sun.COM {
89*9663SMark.Logan@Sun.COM ped_geometry_destroy (fs->geom);
90*9663SMark.Logan@Sun.COM ped_free (fs->type_specific);
91*9663SMark.Logan@Sun.COM ped_free (fs);
92*9663SMark.Logan@Sun.COM }
93*9663SMark.Logan@Sun.COM
94*9663SMark.Logan@Sun.COM int
fat_set_frag_sectors(PedFileSystem * fs,PedSector frag_sectors)95*9663SMark.Logan@Sun.COM fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors)
96*9663SMark.Logan@Sun.COM {
97*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
98*9663SMark.Logan@Sun.COM
99*9663SMark.Logan@Sun.COM PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0
100*9663SMark.Logan@Sun.COM && frag_sectors <= fs_info->cluster_sectors,
101*9663SMark.Logan@Sun.COM return 0);
102*9663SMark.Logan@Sun.COM
103*9663SMark.Logan@Sun.COM fs_info->frag_size = frag_sectors * 512;
104*9663SMark.Logan@Sun.COM fs_info->frag_sectors = frag_sectors;
105*9663SMark.Logan@Sun.COM fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors;
106*9663SMark.Logan@Sun.COM fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors;
107*9663SMark.Logan@Sun.COM fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags;
108*9663SMark.Logan@Sun.COM
109*9663SMark.Logan@Sun.COM return 1;
110*9663SMark.Logan@Sun.COM }
111*9663SMark.Logan@Sun.COM
112*9663SMark.Logan@Sun.COM PedGeometry*
fat_probe(PedGeometry * geom,FatType * fat_type)113*9663SMark.Logan@Sun.COM fat_probe (PedGeometry* geom, FatType* fat_type)
114*9663SMark.Logan@Sun.COM {
115*9663SMark.Logan@Sun.COM PedFileSystem* fs;
116*9663SMark.Logan@Sun.COM FatSpecific* fs_info;
117*9663SMark.Logan@Sun.COM PedGeometry* result;
118*9663SMark.Logan@Sun.COM
119*9663SMark.Logan@Sun.COM fs = fat_alloc (geom);
120*9663SMark.Logan@Sun.COM if (!fs)
121*9663SMark.Logan@Sun.COM goto error;
122*9663SMark.Logan@Sun.COM fs_info = (FatSpecific*) fs->type_specific;
123*9663SMark.Logan@Sun.COM
124*9663SMark.Logan@Sun.COM if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
125*9663SMark.Logan@Sun.COM goto error_free_fs;
126*9663SMark.Logan@Sun.COM if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
127*9663SMark.Logan@Sun.COM goto error_free_fs;
128*9663SMark.Logan@Sun.COM
129*9663SMark.Logan@Sun.COM *fat_type = fs_info->fat_type;
130*9663SMark.Logan@Sun.COM result = ped_geometry_new (geom->dev, geom->start,
131*9663SMark.Logan@Sun.COM fs_info->sector_count);
132*9663SMark.Logan@Sun.COM
133*9663SMark.Logan@Sun.COM fat_free (fs);
134*9663SMark.Logan@Sun.COM return result;
135*9663SMark.Logan@Sun.COM
136*9663SMark.Logan@Sun.COM error_free_fs:
137*9663SMark.Logan@Sun.COM fat_free (fs);
138*9663SMark.Logan@Sun.COM error:
139*9663SMark.Logan@Sun.COM return NULL;
140*9663SMark.Logan@Sun.COM }
141*9663SMark.Logan@Sun.COM
142*9663SMark.Logan@Sun.COM PedGeometry*
fat_probe_fat16(PedGeometry * geom)143*9663SMark.Logan@Sun.COM fat_probe_fat16 (PedGeometry* geom)
144*9663SMark.Logan@Sun.COM {
145*9663SMark.Logan@Sun.COM FatType fat_type;
146*9663SMark.Logan@Sun.COM PedGeometry* probed_geom = fat_probe (geom, &fat_type);
147*9663SMark.Logan@Sun.COM
148*9663SMark.Logan@Sun.COM if (probed_geom) {
149*9663SMark.Logan@Sun.COM if (fat_type == FAT_TYPE_FAT16)
150*9663SMark.Logan@Sun.COM return probed_geom;
151*9663SMark.Logan@Sun.COM ped_geometry_destroy (probed_geom);
152*9663SMark.Logan@Sun.COM }
153*9663SMark.Logan@Sun.COM return NULL;
154*9663SMark.Logan@Sun.COM }
155*9663SMark.Logan@Sun.COM
156*9663SMark.Logan@Sun.COM PedGeometry*
fat_probe_fat32(PedGeometry * geom)157*9663SMark.Logan@Sun.COM fat_probe_fat32 (PedGeometry* geom)
158*9663SMark.Logan@Sun.COM {
159*9663SMark.Logan@Sun.COM FatType fat_type;
160*9663SMark.Logan@Sun.COM PedGeometry* probed_geom = fat_probe (geom, &fat_type);
161*9663SMark.Logan@Sun.COM
162*9663SMark.Logan@Sun.COM if (probed_geom) {
163*9663SMark.Logan@Sun.COM if (fat_type == FAT_TYPE_FAT32)
164*9663SMark.Logan@Sun.COM return probed_geom;
165*9663SMark.Logan@Sun.COM ped_geometry_destroy (probed_geom);
166*9663SMark.Logan@Sun.COM }
167*9663SMark.Logan@Sun.COM return NULL;
168*9663SMark.Logan@Sun.COM }
169*9663SMark.Logan@Sun.COM
170*9663SMark.Logan@Sun.COM #ifndef DISCOVER_ONLY
171*9663SMark.Logan@Sun.COM int
fat_clobber(PedGeometry * geom)172*9663SMark.Logan@Sun.COM fat_clobber (PedGeometry* geom)
173*9663SMark.Logan@Sun.COM {
174*9663SMark.Logan@Sun.COM FatBootSector boot_sector;
175*9663SMark.Logan@Sun.COM
176*9663SMark.Logan@Sun.COM if (!fat_boot_sector_read (&boot_sector, geom))
177*9663SMark.Logan@Sun.COM return 1;
178*9663SMark.Logan@Sun.COM
179*9663SMark.Logan@Sun.COM boot_sector.system_id[0] = 0;
180*9663SMark.Logan@Sun.COM boot_sector.boot_sign = 0;
181*9663SMark.Logan@Sun.COM if (boot_sector.u.fat16.fat_name[0] == 'F')
182*9663SMark.Logan@Sun.COM boot_sector.u.fat16.fat_name[0] = 0;
183*9663SMark.Logan@Sun.COM if (boot_sector.u.fat32.fat_name[0] == 'F')
184*9663SMark.Logan@Sun.COM boot_sector.u.fat32.fat_name[0] = 0;
185*9663SMark.Logan@Sun.COM
186*9663SMark.Logan@Sun.COM return ped_geometry_write (geom, &boot_sector, 0, 1);
187*9663SMark.Logan@Sun.COM }
188*9663SMark.Logan@Sun.COM
189*9663SMark.Logan@Sun.COM static int
_init_fats(PedFileSystem * fs)190*9663SMark.Logan@Sun.COM _init_fats (PedFileSystem* fs)
191*9663SMark.Logan@Sun.COM {
192*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
193*9663SMark.Logan@Sun.COM FatCluster table_size;
194*9663SMark.Logan@Sun.COM
195*9663SMark.Logan@Sun.COM table_size = fs_info->fat_sectors * 512
196*9663SMark.Logan@Sun.COM / fat_table_entry_size (fs_info->fat_type);
197*9663SMark.Logan@Sun.COM fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
198*9663SMark.Logan@Sun.COM if (!fs_info->fat)
199*9663SMark.Logan@Sun.COM goto error;
200*9663SMark.Logan@Sun.COM
201*9663SMark.Logan@Sun.COM if (!fat_table_read (fs_info->fat, fs, 0))
202*9663SMark.Logan@Sun.COM goto error_free_fat;
203*9663SMark.Logan@Sun.COM
204*9663SMark.Logan@Sun.COM return 1;
205*9663SMark.Logan@Sun.COM
206*9663SMark.Logan@Sun.COM error_free_fat:
207*9663SMark.Logan@Sun.COM fat_table_destroy (fs_info->fat);
208*9663SMark.Logan@Sun.COM error:
209*9663SMark.Logan@Sun.COM return 0;
210*9663SMark.Logan@Sun.COM }
211*9663SMark.Logan@Sun.COM
212*9663SMark.Logan@Sun.COM PedFileSystem*
fat_open(PedGeometry * geom)213*9663SMark.Logan@Sun.COM fat_open (PedGeometry* geom)
214*9663SMark.Logan@Sun.COM {
215*9663SMark.Logan@Sun.COM PedFileSystem* fs;
216*9663SMark.Logan@Sun.COM FatSpecific* fs_info;
217*9663SMark.Logan@Sun.COM
218*9663SMark.Logan@Sun.COM fs = fat_alloc (geom);
219*9663SMark.Logan@Sun.COM if (!fs)
220*9663SMark.Logan@Sun.COM goto error;
221*9663SMark.Logan@Sun.COM fs_info = (FatSpecific*) fs->type_specific;
222*9663SMark.Logan@Sun.COM
223*9663SMark.Logan@Sun.COM if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
224*9663SMark.Logan@Sun.COM goto error_free_fs;
225*9663SMark.Logan@Sun.COM if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
226*9663SMark.Logan@Sun.COM goto error_free_fs;
227*9663SMark.Logan@Sun.COM fs->type = (fs_info->fat_type == FAT_TYPE_FAT16)
228*9663SMark.Logan@Sun.COM ? &fat16_type
229*9663SMark.Logan@Sun.COM : &fat32_type;
230*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT32) {
231*9663SMark.Logan@Sun.COM if (!fat_info_sector_read (&fs_info->info_sector, fs))
232*9663SMark.Logan@Sun.COM goto error_free_fs;
233*9663SMark.Logan@Sun.COM }
234*9663SMark.Logan@Sun.COM
235*9663SMark.Logan@Sun.COM if (!_init_fats (fs))
236*9663SMark.Logan@Sun.COM goto error_free_fs;
237*9663SMark.Logan@Sun.COM if (!fat_alloc_buffers (fs))
238*9663SMark.Logan@Sun.COM goto error_free_fat_table;
239*9663SMark.Logan@Sun.COM if (!fat_collect_cluster_info (fs))
240*9663SMark.Logan@Sun.COM goto error_free_buffers;
241*9663SMark.Logan@Sun.COM
242*9663SMark.Logan@Sun.COM return fs;
243*9663SMark.Logan@Sun.COM
244*9663SMark.Logan@Sun.COM error_free_buffers:
245*9663SMark.Logan@Sun.COM fat_free_buffers (fs);
246*9663SMark.Logan@Sun.COM error_free_fat_table:
247*9663SMark.Logan@Sun.COM fat_table_destroy (fs_info->fat);
248*9663SMark.Logan@Sun.COM error_free_fs:
249*9663SMark.Logan@Sun.COM fat_free (fs);
250*9663SMark.Logan@Sun.COM error:
251*9663SMark.Logan@Sun.COM return NULL;
252*9663SMark.Logan@Sun.COM }
253*9663SMark.Logan@Sun.COM
254*9663SMark.Logan@Sun.COM static int
fat_root_dir_clear(PedFileSystem * fs)255*9663SMark.Logan@Sun.COM fat_root_dir_clear (PedFileSystem* fs)
256*9663SMark.Logan@Sun.COM {
257*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
258*9663SMark.Logan@Sun.COM memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count);
259*9663SMark.Logan@Sun.COM return ped_geometry_write (fs->geom, fs_info->buffer,
260*9663SMark.Logan@Sun.COM fs_info->root_dir_offset,
261*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count);
262*9663SMark.Logan@Sun.COM }
263*9663SMark.Logan@Sun.COM
264*9663SMark.Logan@Sun.COM /* hack: use the ext2 uuid library to generate a reasonably random (hopefully
265*9663SMark.Logan@Sun.COM * with /dev/random) number. Unfortunately, we can only use 4 bytes of it
266*9663SMark.Logan@Sun.COM */
267*9663SMark.Logan@Sun.COM static uint32_t
_gen_new_serial_number()268*9663SMark.Logan@Sun.COM _gen_new_serial_number ()
269*9663SMark.Logan@Sun.COM {
270*9663SMark.Logan@Sun.COM uuid_t uuid;
271*9663SMark.Logan@Sun.COM
272*9663SMark.Logan@Sun.COM uuid_generate (uuid);
273*9663SMark.Logan@Sun.COM return * (uint32_t*) &uuid [0];
274*9663SMark.Logan@Sun.COM }
275*9663SMark.Logan@Sun.COM
276*9663SMark.Logan@Sun.COM PedFileSystem*
fat_create(PedGeometry * geom,FatType fat_type,PedTimer * timer)277*9663SMark.Logan@Sun.COM fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer)
278*9663SMark.Logan@Sun.COM {
279*9663SMark.Logan@Sun.COM PedFileSystem* fs;
280*9663SMark.Logan@Sun.COM FatSpecific* fs_info;
281*9663SMark.Logan@Sun.COM FatCluster table_size;
282*9663SMark.Logan@Sun.COM
283*9663SMark.Logan@Sun.COM fs = fat_alloc (geom);
284*9663SMark.Logan@Sun.COM if (!fs)
285*9663SMark.Logan@Sun.COM goto error;
286*9663SMark.Logan@Sun.COM fs_info = (FatSpecific*) fs->type_specific;
287*9663SMark.Logan@Sun.COM
288*9663SMark.Logan@Sun.COM fs_info->logical_sector_size = 1;
289*9663SMark.Logan@Sun.COM fs_info->sectors_per_track = geom->dev->bios_geom.sectors;
290*9663SMark.Logan@Sun.COM fs_info->heads = geom->dev->bios_geom.heads;
291*9663SMark.Logan@Sun.COM fs_info->sector_count = fs->geom->length;
292*9663SMark.Logan@Sun.COM fs_info->fat_table_count = 2;
293*9663SMark.Logan@Sun.COM /* some initial values, to be changed later */
294*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
295*9663SMark.Logan@Sun.COM / (512 / sizeof (FatDirEntry));
296*9663SMark.Logan@Sun.COM fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
297*9663SMark.Logan@Sun.COM
298*9663SMark.Logan@Sun.COM fs_info->fat_type = fat_type;
299*9663SMark.Logan@Sun.COM if (!fat_calc_sizes (fs->geom->length, 0,
300*9663SMark.Logan@Sun.COM fs_info->fat_type,
301*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count,
302*9663SMark.Logan@Sun.COM &fs_info->cluster_sectors,
303*9663SMark.Logan@Sun.COM &fs_info->cluster_count,
304*9663SMark.Logan@Sun.COM &fs_info->fat_sectors)) {
305*9663SMark.Logan@Sun.COM ped_exception_throw (PED_EXCEPTION_ERROR,
306*9663SMark.Logan@Sun.COM PED_EXCEPTION_CANCEL,
307*9663SMark.Logan@Sun.COM _("Partition too big/small for a %s file system."),
308*9663SMark.Logan@Sun.COM (fat_type == FAT_TYPE_FAT16)
309*9663SMark.Logan@Sun.COM ? fat16_type.name
310*9663SMark.Logan@Sun.COM : fat32_type.name);
311*9663SMark.Logan@Sun.COM goto error_free_fs;
312*9663SMark.Logan@Sun.COM }
313*9663SMark.Logan@Sun.COM
314*9663SMark.Logan@Sun.COM fs_info->cluster_size = fs_info->cluster_sectors * 512;
315*9663SMark.Logan@Sun.COM
316*9663SMark.Logan@Sun.COM fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type);
317*9663SMark.Logan@Sun.COM fs_info->dir_entries_per_cluster
318*9663SMark.Logan@Sun.COM = fs_info->cluster_size / sizeof (FatDirEntry);
319*9663SMark.Logan@Sun.COM
320*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT16) {
321*9663SMark.Logan@Sun.COM /* FAT16 */
322*9663SMark.Logan@Sun.COM fs->type = &fat16_type;
323*9663SMark.Logan@Sun.COM
324*9663SMark.Logan@Sun.COM if (fs_info->cluster_count
325*9663SMark.Logan@Sun.COM > fat_max_cluster_count (fs_info->fat_type)) {
326*9663SMark.Logan@Sun.COM fs_info->cluster_count
327*9663SMark.Logan@Sun.COM = fat_max_cluster_count (fs_info->fat_type);
328*9663SMark.Logan@Sun.COM }
329*9663SMark.Logan@Sun.COM
330*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count
331*9663SMark.Logan@Sun.COM = FAT_ROOT_DIR_ENTRY_COUNT
332*9663SMark.Logan@Sun.COM / (512 / sizeof (FatDirEntry));
333*9663SMark.Logan@Sun.COM fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
334*9663SMark.Logan@Sun.COM fs_info->root_dir_offset
335*9663SMark.Logan@Sun.COM = fs_info->fat_offset
336*9663SMark.Logan@Sun.COM + fs_info->fat_sectors * fs_info->fat_table_count;
337*9663SMark.Logan@Sun.COM fs_info->cluster_offset
338*9663SMark.Logan@Sun.COM = fs_info->root_dir_offset
339*9663SMark.Logan@Sun.COM + fs_info->root_dir_sector_count;
340*9663SMark.Logan@Sun.COM } else {
341*9663SMark.Logan@Sun.COM /* FAT32 */
342*9663SMark.Logan@Sun.COM fs->type = &fat32_type;
343*9663SMark.Logan@Sun.COM
344*9663SMark.Logan@Sun.COM fs_info->info_sector_offset = 1;
345*9663SMark.Logan@Sun.COM fs_info->boot_sector_backup_offset = 6;
346*9663SMark.Logan@Sun.COM
347*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count = 0;
348*9663SMark.Logan@Sun.COM fs_info->root_dir_entry_count = 0;
349*9663SMark.Logan@Sun.COM fs_info->root_dir_offset = 0;
350*9663SMark.Logan@Sun.COM
351*9663SMark.Logan@Sun.COM fs_info->cluster_offset
352*9663SMark.Logan@Sun.COM = fs_info->fat_offset
353*9663SMark.Logan@Sun.COM + fs_info->fat_sectors * fs_info->fat_table_count;
354*9663SMark.Logan@Sun.COM }
355*9663SMark.Logan@Sun.COM
356*9663SMark.Logan@Sun.COM table_size = fs_info->fat_sectors * 512
357*9663SMark.Logan@Sun.COM / fat_table_entry_size (fs_info->fat_type);
358*9663SMark.Logan@Sun.COM fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
359*9663SMark.Logan@Sun.COM if (!fs_info->fat)
360*9663SMark.Logan@Sun.COM goto error_free_fs;
361*9663SMark.Logan@Sun.COM fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count);
362*9663SMark.Logan@Sun.COM if (!fat_alloc_buffers (fs))
363*9663SMark.Logan@Sun.COM goto error_free_fat_table;
364*9663SMark.Logan@Sun.COM
365*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT32) {
366*9663SMark.Logan@Sun.COM fs_info->root_cluster
367*9663SMark.Logan@Sun.COM = fat_table_alloc_cluster (fs_info->fat);
368*9663SMark.Logan@Sun.COM fat_table_set_eof (fs_info->fat, fs_info->root_cluster);
369*9663SMark.Logan@Sun.COM memset (fs_info->buffer, 0, fs_info->cluster_size);
370*9663SMark.Logan@Sun.COM if (!fat_write_cluster (fs, fs_info->buffer,
371*9663SMark.Logan@Sun.COM fs_info->root_cluster))
372*9663SMark.Logan@Sun.COM return 0;
373*9663SMark.Logan@Sun.COM }
374*9663SMark.Logan@Sun.COM
375*9663SMark.Logan@Sun.COM fs_info->serial_number = _gen_new_serial_number ();
376*9663SMark.Logan@Sun.COM
377*9663SMark.Logan@Sun.COM if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector))
378*9663SMark.Logan@Sun.COM goto error_free_buffers;
379*9663SMark.Logan@Sun.COM if (!fat_boot_sector_generate (&fs_info->boot_sector, fs))
380*9663SMark.Logan@Sun.COM goto error_free_buffers;
381*9663SMark.Logan@Sun.COM if (!fat_boot_sector_write (&fs_info->boot_sector, fs))
382*9663SMark.Logan@Sun.COM goto error_free_buffers;
383*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT32) {
384*9663SMark.Logan@Sun.COM if (!fat_info_sector_generate (&fs_info->info_sector, fs))
385*9663SMark.Logan@Sun.COM goto error_free_buffers;
386*9663SMark.Logan@Sun.COM if (!fat_info_sector_write (&fs_info->info_sector, fs))
387*9663SMark.Logan@Sun.COM goto error_free_buffers;
388*9663SMark.Logan@Sun.COM }
389*9663SMark.Logan@Sun.COM
390*9663SMark.Logan@Sun.COM if (!fat_table_write_all (fs_info->fat, fs))
391*9663SMark.Logan@Sun.COM goto error_free_buffers;
392*9663SMark.Logan@Sun.COM
393*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT16) {
394*9663SMark.Logan@Sun.COM if (!fat_root_dir_clear (fs))
395*9663SMark.Logan@Sun.COM goto error_free_buffers;
396*9663SMark.Logan@Sun.COM }
397*9663SMark.Logan@Sun.COM
398*9663SMark.Logan@Sun.COM return fs;
399*9663SMark.Logan@Sun.COM
400*9663SMark.Logan@Sun.COM error_free_buffers:
401*9663SMark.Logan@Sun.COM fat_free_buffers (fs);
402*9663SMark.Logan@Sun.COM error_free_fat_table:
403*9663SMark.Logan@Sun.COM fat_table_destroy (fs_info->fat);
404*9663SMark.Logan@Sun.COM error_free_fs:
405*9663SMark.Logan@Sun.COM fat_free (fs);
406*9663SMark.Logan@Sun.COM error:
407*9663SMark.Logan@Sun.COM return NULL;
408*9663SMark.Logan@Sun.COM }
409*9663SMark.Logan@Sun.COM
410*9663SMark.Logan@Sun.COM PedFileSystem*
fat_create_fat16(PedGeometry * geom,PedTimer * timer)411*9663SMark.Logan@Sun.COM fat_create_fat16 (PedGeometry* geom, PedTimer* timer)
412*9663SMark.Logan@Sun.COM {
413*9663SMark.Logan@Sun.COM return fat_create (geom, FAT_TYPE_FAT16, timer);
414*9663SMark.Logan@Sun.COM }
415*9663SMark.Logan@Sun.COM
416*9663SMark.Logan@Sun.COM PedFileSystem*
fat_create_fat32(PedGeometry * geom,PedTimer * timer)417*9663SMark.Logan@Sun.COM fat_create_fat32 (PedGeometry* geom, PedTimer* timer)
418*9663SMark.Logan@Sun.COM {
419*9663SMark.Logan@Sun.COM return fat_create (geom, FAT_TYPE_FAT32, timer);
420*9663SMark.Logan@Sun.COM }
421*9663SMark.Logan@Sun.COM
422*9663SMark.Logan@Sun.COM int
fat_close(PedFileSystem * fs)423*9663SMark.Logan@Sun.COM fat_close (PedFileSystem* fs)
424*9663SMark.Logan@Sun.COM {
425*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
426*9663SMark.Logan@Sun.COM
427*9663SMark.Logan@Sun.COM fat_free_buffers (fs);
428*9663SMark.Logan@Sun.COM fat_table_destroy (fs_info->fat);
429*9663SMark.Logan@Sun.COM fat_free (fs);
430*9663SMark.Logan@Sun.COM return 1;
431*9663SMark.Logan@Sun.COM }
432*9663SMark.Logan@Sun.COM
433*9663SMark.Logan@Sun.COM /* Hack: just resize the file system outside of its boundaries! */
434*9663SMark.Logan@Sun.COM PedFileSystem*
fat_copy(const PedFileSystem * fs,PedGeometry * geom,PedTimer * timer)435*9663SMark.Logan@Sun.COM fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
436*9663SMark.Logan@Sun.COM {
437*9663SMark.Logan@Sun.COM PedFileSystem* new_fs;
438*9663SMark.Logan@Sun.COM
439*9663SMark.Logan@Sun.COM new_fs = ped_file_system_open (fs->geom);
440*9663SMark.Logan@Sun.COM if (!new_fs)
441*9663SMark.Logan@Sun.COM goto error;
442*9663SMark.Logan@Sun.COM if (!ped_file_system_resize (new_fs, geom, timer))
443*9663SMark.Logan@Sun.COM goto error_close_new_fs;
444*9663SMark.Logan@Sun.COM return new_fs;
445*9663SMark.Logan@Sun.COM
446*9663SMark.Logan@Sun.COM error_close_new_fs:
447*9663SMark.Logan@Sun.COM ped_file_system_close (new_fs);
448*9663SMark.Logan@Sun.COM error:
449*9663SMark.Logan@Sun.COM return 0;
450*9663SMark.Logan@Sun.COM }
451*9663SMark.Logan@Sun.COM
452*9663SMark.Logan@Sun.COM static int
_compare_fats(PedFileSystem * fs)453*9663SMark.Logan@Sun.COM _compare_fats (PedFileSystem* fs)
454*9663SMark.Logan@Sun.COM {
455*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
456*9663SMark.Logan@Sun.COM FatTable* table_copy;
457*9663SMark.Logan@Sun.COM FatCluster table_size;
458*9663SMark.Logan@Sun.COM int i;
459*9663SMark.Logan@Sun.COM
460*9663SMark.Logan@Sun.COM table_size = fs_info->fat_sectors * 512
461*9663SMark.Logan@Sun.COM / fat_table_entry_size (fs_info->fat_type);
462*9663SMark.Logan@Sun.COM
463*9663SMark.Logan@Sun.COM table_copy = fat_table_new (fs_info->fat_type, table_size);
464*9663SMark.Logan@Sun.COM if (!table_copy)
465*9663SMark.Logan@Sun.COM goto error;
466*9663SMark.Logan@Sun.COM
467*9663SMark.Logan@Sun.COM for (i = 1; i < fs_info->fat_table_count; i++) {
468*9663SMark.Logan@Sun.COM if (!fat_table_read (table_copy, fs, i))
469*9663SMark.Logan@Sun.COM goto error_free_table_copy;
470*9663SMark.Logan@Sun.COM if (!fat_table_compare (fs_info->fat, table_copy)) {
471*9663SMark.Logan@Sun.COM if (ped_exception_throw (PED_EXCEPTION_ERROR,
472*9663SMark.Logan@Sun.COM PED_EXCEPTION_IGNORE_CANCEL,
473*9663SMark.Logan@Sun.COM _("The FATs don't match. If you don't know "
474*9663SMark.Logan@Sun.COM "what this means, then select cancel, run "
475*9663SMark.Logan@Sun.COM "scandisk on the file system, and then come "
476*9663SMark.Logan@Sun.COM "back."))
477*9663SMark.Logan@Sun.COM != PED_EXCEPTION_IGNORE)
478*9663SMark.Logan@Sun.COM goto error_free_table_copy;
479*9663SMark.Logan@Sun.COM }
480*9663SMark.Logan@Sun.COM }
481*9663SMark.Logan@Sun.COM
482*9663SMark.Logan@Sun.COM fat_table_destroy (table_copy);
483*9663SMark.Logan@Sun.COM return 1;
484*9663SMark.Logan@Sun.COM
485*9663SMark.Logan@Sun.COM error_free_table_copy:
486*9663SMark.Logan@Sun.COM fat_table_destroy (table_copy);
487*9663SMark.Logan@Sun.COM error:
488*9663SMark.Logan@Sun.COM return 0;
489*9663SMark.Logan@Sun.COM }
490*9663SMark.Logan@Sun.COM
491*9663SMark.Logan@Sun.COM int
fat_check(PedFileSystem * fs,PedTimer * timer)492*9663SMark.Logan@Sun.COM fat_check (PedFileSystem* fs, PedTimer* timer)
493*9663SMark.Logan@Sun.COM {
494*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
495*9663SMark.Logan@Sun.COM PedSector cluster_sectors;
496*9663SMark.Logan@Sun.COM FatCluster cluster_count;
497*9663SMark.Logan@Sun.COM PedSector fat_sectors;
498*9663SMark.Logan@Sun.COM PedSector align_sectors;
499*9663SMark.Logan@Sun.COM FatCluster info_free_clusters;
500*9663SMark.Logan@Sun.COM
501*9663SMark.Logan@Sun.COM align_sectors = fs_info->fat_offset
502*9663SMark.Logan@Sun.COM - fat_min_reserved_sector_count (fs_info->fat_type);
503*9663SMark.Logan@Sun.COM
504*9663SMark.Logan@Sun.COM if (!fat_calc_sizes (fs->geom->length,
505*9663SMark.Logan@Sun.COM align_sectors,
506*9663SMark.Logan@Sun.COM fs_info->fat_type,
507*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count,
508*9663SMark.Logan@Sun.COM &cluster_sectors,
509*9663SMark.Logan@Sun.COM &cluster_count,
510*9663SMark.Logan@Sun.COM &fat_sectors)) {
511*9663SMark.Logan@Sun.COM if (ped_exception_throw (PED_EXCEPTION_BUG,
512*9663SMark.Logan@Sun.COM PED_EXCEPTION_IGNORE_CANCEL,
513*9663SMark.Logan@Sun.COM _("There are no possible configurations for this FAT "
514*9663SMark.Logan@Sun.COM "type."))
515*9663SMark.Logan@Sun.COM != PED_EXCEPTION_IGNORE)
516*9663SMark.Logan@Sun.COM goto error;
517*9663SMark.Logan@Sun.COM }
518*9663SMark.Logan@Sun.COM
519*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT16) {
520*9663SMark.Logan@Sun.COM if (cluster_sectors != fs_info->cluster_sectors
521*9663SMark.Logan@Sun.COM || cluster_count != fs_info->cluster_count
522*9663SMark.Logan@Sun.COM || fat_sectors != fs_info->fat_sectors) {
523*9663SMark.Logan@Sun.COM if (ped_exception_throw (PED_EXCEPTION_WARNING,
524*9663SMark.Logan@Sun.COM PED_EXCEPTION_IGNORE_CANCEL,
525*9663SMark.Logan@Sun.COM _("File system doesn't have expected sizes for "
526*9663SMark.Logan@Sun.COM "Windows to like it. "
527*9663SMark.Logan@Sun.COM "Cluster size is %dk (%dk expected); "
528*9663SMark.Logan@Sun.COM "number of clusters is %d (%d expected); "
529*9663SMark.Logan@Sun.COM "size of FATs is %d sectors (%d expected)."),
530*9663SMark.Logan@Sun.COM (int) fs_info->cluster_sectors / 2,
531*9663SMark.Logan@Sun.COM (int) cluster_sectors / 2,
532*9663SMark.Logan@Sun.COM (int) fs_info->cluster_count,
533*9663SMark.Logan@Sun.COM (int) cluster_count,
534*9663SMark.Logan@Sun.COM (int) fs_info->fat_sectors,
535*9663SMark.Logan@Sun.COM (int) fat_sectors)
536*9663SMark.Logan@Sun.COM != PED_EXCEPTION_IGNORE)
537*9663SMark.Logan@Sun.COM goto error;
538*9663SMark.Logan@Sun.COM }
539*9663SMark.Logan@Sun.COM }
540*9663SMark.Logan@Sun.COM
541*9663SMark.Logan@Sun.COM if (fs_info->fat_type == FAT_TYPE_FAT32) {
542*9663SMark.Logan@Sun.COM info_free_clusters
543*9663SMark.Logan@Sun.COM = PED_LE32_TO_CPU (fs_info->info_sector.free_clusters);
544*9663SMark.Logan@Sun.COM if (info_free_clusters != (FatCluster) -1
545*9663SMark.Logan@Sun.COM && info_free_clusters != fs_info->fat->free_cluster_count) {
546*9663SMark.Logan@Sun.COM if (ped_exception_throw (PED_EXCEPTION_WARNING,
547*9663SMark.Logan@Sun.COM PED_EXCEPTION_IGNORE_CANCEL,
548*9663SMark.Logan@Sun.COM _("File system is reporting the free space as "
549*9663SMark.Logan@Sun.COM "%d clusters, not %d clusters."),
550*9663SMark.Logan@Sun.COM info_free_clusters,
551*9663SMark.Logan@Sun.COM fs_info->fat->free_cluster_count)
552*9663SMark.Logan@Sun.COM != PED_EXCEPTION_IGNORE)
553*9663SMark.Logan@Sun.COM goto error;
554*9663SMark.Logan@Sun.COM }
555*9663SMark.Logan@Sun.COM }
556*9663SMark.Logan@Sun.COM
557*9663SMark.Logan@Sun.COM if (!_compare_fats (fs))
558*9663SMark.Logan@Sun.COM goto error;
559*9663SMark.Logan@Sun.COM
560*9663SMark.Logan@Sun.COM fs->checked = 1;
561*9663SMark.Logan@Sun.COM return 1; /* existence of fs implies consistency ;-) */
562*9663SMark.Logan@Sun.COM
563*9663SMark.Logan@Sun.COM error:
564*9663SMark.Logan@Sun.COM return 0;
565*9663SMark.Logan@Sun.COM }
566*9663SMark.Logan@Sun.COM
567*9663SMark.Logan@Sun.COM /* Calculates how much space there will be in clusters in:
568*9663SMark.Logan@Sun.COM * old_fs intersect the-new-fs
569*9663SMark.Logan@Sun.COM */
570*9663SMark.Logan@Sun.COM static PedSector
_calc_resize_data_size(const PedFileSystem * old_fs,PedSector new_cluster_sectors,FatCluster new_cluster_count,PedSector new_fat_size)571*9663SMark.Logan@Sun.COM _calc_resize_data_size (
572*9663SMark.Logan@Sun.COM const PedFileSystem* old_fs,
573*9663SMark.Logan@Sun.COM PedSector new_cluster_sectors,
574*9663SMark.Logan@Sun.COM FatCluster new_cluster_count,
575*9663SMark.Logan@Sun.COM PedSector new_fat_size)
576*9663SMark.Logan@Sun.COM {
577*9663SMark.Logan@Sun.COM FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
578*9663SMark.Logan@Sun.COM PedSector fat_size_delta;
579*9663SMark.Logan@Sun.COM
580*9663SMark.Logan@Sun.COM fat_size_delta = old_fs_info->fat_sectors - new_fat_size;
581*9663SMark.Logan@Sun.COM return new_cluster_sectors * new_cluster_count - fat_size_delta * 2;
582*9663SMark.Logan@Sun.COM }
583*9663SMark.Logan@Sun.COM
584*9663SMark.Logan@Sun.COM static int
_test_resize_size(const PedFileSystem * fs,PedSector length,PedSector min_data_size)585*9663SMark.Logan@Sun.COM _test_resize_size (const PedFileSystem* fs,
586*9663SMark.Logan@Sun.COM PedSector length, PedSector min_data_size)
587*9663SMark.Logan@Sun.COM {
588*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
589*9663SMark.Logan@Sun.COM PedGeometry geom;
590*9663SMark.Logan@Sun.COM PedSector _cluster_sectors;
591*9663SMark.Logan@Sun.COM FatCluster _cluster_count;
592*9663SMark.Logan@Sun.COM PedSector _fat_size;
593*9663SMark.Logan@Sun.COM
594*9663SMark.Logan@Sun.COM ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length);
595*9663SMark.Logan@Sun.COM
596*9663SMark.Logan@Sun.COM if (fat_calc_resize_sizes (
597*9663SMark.Logan@Sun.COM &geom,
598*9663SMark.Logan@Sun.COM fs_info->cluster_sectors,
599*9663SMark.Logan@Sun.COM FAT_TYPE_FAT16,
600*9663SMark.Logan@Sun.COM fs_info->root_dir_sector_count,
601*9663SMark.Logan@Sun.COM fs_info->cluster_sectors,
602*9663SMark.Logan@Sun.COM &_cluster_sectors,
603*9663SMark.Logan@Sun.COM &_cluster_count,
604*9663SMark.Logan@Sun.COM &_fat_size)
605*9663SMark.Logan@Sun.COM && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
606*9663SMark.Logan@Sun.COM _fat_size)
607*9663SMark.Logan@Sun.COM >= min_data_size)
608*9663SMark.Logan@Sun.COM return 1;
609*9663SMark.Logan@Sun.COM
610*9663SMark.Logan@Sun.COM if (fat_calc_resize_sizes (
611*9663SMark.Logan@Sun.COM &geom,
612*9663SMark.Logan@Sun.COM fs_info->cluster_sectors,
613*9663SMark.Logan@Sun.COM FAT_TYPE_FAT32,
614*9663SMark.Logan@Sun.COM 0,
615*9663SMark.Logan@Sun.COM fs_info->cluster_sectors,
616*9663SMark.Logan@Sun.COM &_cluster_sectors,
617*9663SMark.Logan@Sun.COM &_cluster_count,
618*9663SMark.Logan@Sun.COM &_fat_size)
619*9663SMark.Logan@Sun.COM && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
620*9663SMark.Logan@Sun.COM _fat_size)
621*9663SMark.Logan@Sun.COM >= min_data_size)
622*9663SMark.Logan@Sun.COM return 1;
623*9663SMark.Logan@Sun.COM
624*9663SMark.Logan@Sun.COM return 0;
625*9663SMark.Logan@Sun.COM }
626*9663SMark.Logan@Sun.COM
627*9663SMark.Logan@Sun.COM /* does a binary search (!) for the mininum size. Too hard to compute directly
628*9663SMark.Logan@Sun.COM * (see calc_sizes() for why!)
629*9663SMark.Logan@Sun.COM */
630*9663SMark.Logan@Sun.COM static PedSector
_get_min_resize_size(const PedFileSystem * fs,PedSector min_data_size)631*9663SMark.Logan@Sun.COM _get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size)
632*9663SMark.Logan@Sun.COM {
633*9663SMark.Logan@Sun.COM PedSector min_length = 0;
634*9663SMark.Logan@Sun.COM PedSector max_length = fs->geom->length;
635*9663SMark.Logan@Sun.COM PedSector length;
636*9663SMark.Logan@Sun.COM
637*9663SMark.Logan@Sun.COM while (min_length < max_length - 1) {
638*9663SMark.Logan@Sun.COM length = (min_length + max_length) / 2;
639*9663SMark.Logan@Sun.COM if (_test_resize_size (fs, length, min_data_size))
640*9663SMark.Logan@Sun.COM max_length = length;
641*9663SMark.Logan@Sun.COM else
642*9663SMark.Logan@Sun.COM min_length = length;
643*9663SMark.Logan@Sun.COM }
644*9663SMark.Logan@Sun.COM
645*9663SMark.Logan@Sun.COM /* adds a bit of leeway (64 sectors), for resolving extra issues, like root
646*9663SMark.Logan@Sun.COM * directory allocation, that aren't covered here.
647*9663SMark.Logan@Sun.COM */
648*9663SMark.Logan@Sun.COM return max_length + 64;
649*9663SMark.Logan@Sun.COM }
650*9663SMark.Logan@Sun.COM
651*9663SMark.Logan@Sun.COM PedConstraint*
fat_get_copy_constraint(const PedFileSystem * fs,const PedDevice * dev)652*9663SMark.Logan@Sun.COM fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev)
653*9663SMark.Logan@Sun.COM {
654*9663SMark.Logan@Sun.COM FatSpecific* fs_info = FAT_SPECIFIC (fs);
655*9663SMark.Logan@Sun.COM PedGeometry full_dev;
656*9663SMark.Logan@Sun.COM PedSector min_cluster_count;
657*9663SMark.Logan@Sun.COM FatCluster used_clusters;
658*9663SMark.Logan@Sun.COM PedSector min_data_size;
659*9663SMark.Logan@Sun.COM
660*9663SMark.Logan@Sun.COM if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
661*9663SMark.Logan@Sun.COM return NULL;
662*9663SMark.Logan@Sun.COM
663*9663SMark.Logan@Sun.COM used_clusters = fs_info->fat->cluster_count
664*9663SMark.Logan@Sun.COM - fs_info->fat->free_cluster_count;
665*9663SMark.Logan@Sun.COM min_cluster_count = used_clusters + fs_info->total_dir_clusters;
666*9663SMark.Logan@Sun.COM min_data_size = min_cluster_count * fs_info->cluster_sectors;
667*9663SMark.Logan@Sun.COM
668*9663SMark.Logan@Sun.COM return ped_constraint_new (ped_alignment_any, ped_alignment_any,
669*9663SMark.Logan@Sun.COM &full_dev, &full_dev,
670*9663SMark.Logan@Sun.COM _get_min_resize_size (fs, min_data_size),
671*9663SMark.Logan@Sun.COM dev->length);
672*9663SMark.Logan@Sun.COM }
673*9663SMark.Logan@Sun.COM
674*9663SMark.Logan@Sun.COM PedConstraint*
fat_get_resize_constraint(const PedFileSystem * fs)675*9663SMark.Logan@Sun.COM fat_get_resize_constraint (const PedFileSystem* fs)
676*9663SMark.Logan@Sun.COM {
677*9663SMark.Logan@Sun.COM return fat_get_copy_constraint (fs, fs->geom->dev);
678*9663SMark.Logan@Sun.COM }
679*9663SMark.Logan@Sun.COM
680*9663SMark.Logan@Sun.COM /* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or
681*9663SMark.Logan@Sun.COM * something. This is a really difficult (maths) problem to do
682*9663SMark.Logan@Sun.COM * nicely...
683*9663SMark.Logan@Sun.COM * So, this algorithm works if dev->length / 2 is a valid fat_type
684*9663SMark.Logan@Sun.COM * size. (Which is how I got the magic numbers below)
685*9663SMark.Logan@Sun.COM */
686*9663SMark.Logan@Sun.COM #if 0
687*9663SMark.Logan@Sun.COM /* returns: -1 too small, 0 ok, 1 too big */
688*9663SMark.Logan@Sun.COM static int
689*9663SMark.Logan@Sun.COM _test_create_size (PedSector length, FatType fat_type,
690*9663SMark.Logan@Sun.COM PedSector cluster_sectors, PedSector cluster_count)
691*9663SMark.Logan@Sun.COM {
692*9663SMark.Logan@Sun.COM PedSector rootdir_sectors;
693*9663SMark.Logan@Sun.COM PedSector _cluster_sectors;
694*9663SMark.Logan@Sun.COM FatCluster _cluster_count;
695*9663SMark.Logan@Sun.COM PedSector _fat_size;
696*9663SMark.Logan@Sun.COM
697*9663SMark.Logan@Sun.COM rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0;
698*9663SMark.Logan@Sun.COM
699*9663SMark.Logan@Sun.COM if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors,
700*9663SMark.Logan@Sun.COM &_cluster_sectors, &_cluster_count, &_fat_size))
701*9663SMark.Logan@Sun.COM return -1; // XXX: doesn't work... can't see a better way!
702*9663SMark.Logan@Sun.COM
703*9663SMark.Logan@Sun.COM if (_cluster_sectors < cluster_sectors)
704*9663SMark.Logan@Sun.COM return -1;
705*9663SMark.Logan@Sun.COM if (_cluster_sectors > cluster_sectors)
706*9663SMark.Logan@Sun.COM return 1;
707*9663SMark.Logan@Sun.COM
708*9663SMark.Logan@Sun.COM if (_cluster_count < cluster_count)
709*9663SMark.Logan@Sun.COM return -1;
710*9663SMark.Logan@Sun.COM if (_cluster_count > cluster_count)
711*9663SMark.Logan@Sun.COM return 1;
712*9663SMark.Logan@Sun.COM
713*9663SMark.Logan@Sun.COM return 0;
714*9663SMark.Logan@Sun.COM }
715*9663SMark.Logan@Sun.COM
716*9663SMark.Logan@Sun.COM static PedSector
717*9663SMark.Logan@Sun.COM _get_create_size (PedSector upper_bound, FatType fat_type,
718*9663SMark.Logan@Sun.COM PedSector cluster_sectors, FatCluster cluster_count)
719*9663SMark.Logan@Sun.COM {
720*9663SMark.Logan@Sun.COM PedSector min_length = 0;
721*9663SMark.Logan@Sun.COM PedSector max_length = upper_bound;
722*9663SMark.Logan@Sun.COM PedSector length;
723*9663SMark.Logan@Sun.COM
724*9663SMark.Logan@Sun.COM while (1) {
725*9663SMark.Logan@Sun.COM length = (min_length + max_length) / 2;
726*9663SMark.Logan@Sun.COM switch (_test_create_size (length, fat_type, cluster_sectors,
727*9663SMark.Logan@Sun.COM cluster_count)) {
728*9663SMark.Logan@Sun.COM case -1: min_length = length; break;
729*9663SMark.Logan@Sun.COM case 0: return length;
730*9663SMark.Logan@Sun.COM case 1: max_length = length; break;
731*9663SMark.Logan@Sun.COM }
732*9663SMark.Logan@Sun.COM /* hack... won't always be able to get max cluster count
733*9663SMark.Logan@Sun.COM * with max cluster size, etc. */
734*9663SMark.Logan@Sun.COM if (max_length - min_length == 1)
735*9663SMark.Logan@Sun.COM return min_length;
736*9663SMark.Logan@Sun.COM }
737*9663SMark.Logan@Sun.COM
738*9663SMark.Logan@Sun.COM return 0; /* shut gcc up */
739*9663SMark.Logan@Sun.COM }
740*9663SMark.Logan@Sun.COM #endif
741*9663SMark.Logan@Sun.COM
742*9663SMark.Logan@Sun.COM PedConstraint*
fat_get_create_constraint_fat16(const PedDevice * dev)743*9663SMark.Logan@Sun.COM fat_get_create_constraint_fat16 (const PedDevice* dev)
744*9663SMark.Logan@Sun.COM {
745*9663SMark.Logan@Sun.COM PedGeometry full_dev;
746*9663SMark.Logan@Sun.COM PedSector min_size;
747*9663SMark.Logan@Sun.COM PedSector max_size;
748*9663SMark.Logan@Sun.COM
749*9663SMark.Logan@Sun.COM if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
750*9663SMark.Logan@Sun.COM return NULL;
751*9663SMark.Logan@Sun.COM
752*9663SMark.Logan@Sun.COM #if 0
753*9663SMark.Logan@Sun.COM min_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
754*9663SMark.Logan@Sun.COM fat_min_cluster_size (FAT_TYPE_FAT16),
755*9663SMark.Logan@Sun.COM fat_min_cluster_count (FAT_TYPE_FAT16));
756*9663SMark.Logan@Sun.COM max_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
757*9663SMark.Logan@Sun.COM fat_max_cluster_size (FAT_TYPE_FAT16),
758*9663SMark.Logan@Sun.COM fat_max_cluster_count (FAT_TYPE_FAT16));
759*9663SMark.Logan@Sun.COM if (!min_size)
760*9663SMark.Logan@Sun.COM return NULL;
761*9663SMark.Logan@Sun.COM #else
762*9663SMark.Logan@Sun.COM min_size = 65794;
763*9663SMark.Logan@Sun.COM max_size = 2097153;
764*9663SMark.Logan@Sun.COM #endif
765*9663SMark.Logan@Sun.COM
766*9663SMark.Logan@Sun.COM return ped_constraint_new (
767*9663SMark.Logan@Sun.COM ped_alignment_any, ped_alignment_any,
768*9663SMark.Logan@Sun.COM &full_dev, &full_dev,
769*9663SMark.Logan@Sun.COM min_size, max_size);
770*9663SMark.Logan@Sun.COM }
771*9663SMark.Logan@Sun.COM
772*9663SMark.Logan@Sun.COM PedConstraint*
fat_get_create_constraint_fat32(const PedDevice * dev)773*9663SMark.Logan@Sun.COM fat_get_create_constraint_fat32 (const PedDevice* dev)
774*9663SMark.Logan@Sun.COM {
775*9663SMark.Logan@Sun.COM PedGeometry full_dev;
776*9663SMark.Logan@Sun.COM PedSector min_size;
777*9663SMark.Logan@Sun.COM
778*9663SMark.Logan@Sun.COM if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
779*9663SMark.Logan@Sun.COM return NULL;
780*9663SMark.Logan@Sun.COM
781*9663SMark.Logan@Sun.COM #if 0
782*9663SMark.Logan@Sun.COM min_size = _get_create_size (dev->length, FAT_TYPE_FAT32,
783*9663SMark.Logan@Sun.COM fat_min_cluster_size (FAT_TYPE_FAT32),
784*9663SMark.Logan@Sun.COM fat_min_cluster_count (FAT_TYPE_FAT32));
785*9663SMark.Logan@Sun.COM if (!min_size)
786*9663SMark.Logan@Sun.COM return NULL;
787*9663SMark.Logan@Sun.COM #else
788*9663SMark.Logan@Sun.COM min_size = 525224;
789*9663SMark.Logan@Sun.COM #endif
790*9663SMark.Logan@Sun.COM
791*9663SMark.Logan@Sun.COM return ped_constraint_new (
792*9663SMark.Logan@Sun.COM ped_alignment_any, ped_alignment_any,
793*9663SMark.Logan@Sun.COM &full_dev, &full_dev,
794*9663SMark.Logan@Sun.COM min_size, dev->length);
795*9663SMark.Logan@Sun.COM }
796*9663SMark.Logan@Sun.COM #endif /* !DISCOVER_ONLY */
797*9663SMark.Logan@Sun.COM
798*9663SMark.Logan@Sun.COM static PedFileSystemOps fat16_ops = {
799*9663SMark.Logan@Sun.COM .probe = fat_probe_fat16,
800*9663SMark.Logan@Sun.COM #ifndef DISCOVER_ONLY
801*9663SMark.Logan@Sun.COM .clobber = fat_clobber,
802*9663SMark.Logan@Sun.COM .open = fat_open,
803*9663SMark.Logan@Sun.COM .create = fat_create_fat16,
804*9663SMark.Logan@Sun.COM .close = fat_close,
805*9663SMark.Logan@Sun.COM .check = fat_check,
806*9663SMark.Logan@Sun.COM .resize = fat_resize,
807*9663SMark.Logan@Sun.COM .copy = fat_copy,
808*9663SMark.Logan@Sun.COM .get_create_constraint = fat_get_create_constraint_fat16,
809*9663SMark.Logan@Sun.COM .get_resize_constraint = fat_get_resize_constraint,
810*9663SMark.Logan@Sun.COM .get_copy_constraint = fat_get_copy_constraint,
811*9663SMark.Logan@Sun.COM #else /* !DISCOVER_ONLY */
812*9663SMark.Logan@Sun.COM .clobber = NULL,
813*9663SMark.Logan@Sun.COM .open = NULL,
814*9663SMark.Logan@Sun.COM .create = NULL,
815*9663SMark.Logan@Sun.COM .close = NULL,
816*9663SMark.Logan@Sun.COM .check = NULL,
817*9663SMark.Logan@Sun.COM .resize = NULL,
818*9663SMark.Logan@Sun.COM .copy = NULL,
819*9663SMark.Logan@Sun.COM .get_create_constraint = NULL,
820*9663SMark.Logan@Sun.COM .get_resize_constraint = NULL,
821*9663SMark.Logan@Sun.COM .get_copy_constraint = NULL,
822*9663SMark.Logan@Sun.COM #endif /* !DISCOVER_ONLY */
823*9663SMark.Logan@Sun.COM };
824*9663SMark.Logan@Sun.COM
825*9663SMark.Logan@Sun.COM static PedFileSystemOps fat32_ops = {
826*9663SMark.Logan@Sun.COM .probe = fat_probe_fat32,
827*9663SMark.Logan@Sun.COM #ifndef DISCOVER_ONLY
828*9663SMark.Logan@Sun.COM .clobber = fat_clobber,
829*9663SMark.Logan@Sun.COM .open = fat_open,
830*9663SMark.Logan@Sun.COM .create = fat_create_fat32,
831*9663SMark.Logan@Sun.COM .close = fat_close,
832*9663SMark.Logan@Sun.COM .check = fat_check,
833*9663SMark.Logan@Sun.COM .resize = fat_resize,
834*9663SMark.Logan@Sun.COM .copy = fat_copy,
835*9663SMark.Logan@Sun.COM .get_create_constraint = fat_get_create_constraint_fat32,
836*9663SMark.Logan@Sun.COM .get_resize_constraint = fat_get_resize_constraint,
837*9663SMark.Logan@Sun.COM .get_copy_constraint = fat_get_copy_constraint,
838*9663SMark.Logan@Sun.COM #else /* !DISCOVER_ONLY */
839*9663SMark.Logan@Sun.COM .clobber = NULL,
840*9663SMark.Logan@Sun.COM .open = NULL,
841*9663SMark.Logan@Sun.COM .create = NULL,
842*9663SMark.Logan@Sun.COM .close = NULL,
843*9663SMark.Logan@Sun.COM .check = NULL,
844*9663SMark.Logan@Sun.COM .resize = NULL,
845*9663SMark.Logan@Sun.COM .copy = NULL,
846*9663SMark.Logan@Sun.COM .get_create_constraint = NULL,
847*9663SMark.Logan@Sun.COM .get_resize_constraint = NULL,
848*9663SMark.Logan@Sun.COM .get_copy_constraint = NULL,
849*9663SMark.Logan@Sun.COM #endif /* !DISCOVER_ONLY */
850*9663SMark.Logan@Sun.COM };
851*9663SMark.Logan@Sun.COM
852*9663SMark.Logan@Sun.COM #define FAT_BLOCK_SIZES ((int[2]){512, 0})
853*9663SMark.Logan@Sun.COM
854*9663SMark.Logan@Sun.COM PedFileSystemType fat16_type = {
855*9663SMark.Logan@Sun.COM .next = NULL,
856*9663SMark.Logan@Sun.COM .ops = &fat16_ops,
857*9663SMark.Logan@Sun.COM .name = "fat16",
858*9663SMark.Logan@Sun.COM .block_sizes = FAT_BLOCK_SIZES
859*9663SMark.Logan@Sun.COM };
860*9663SMark.Logan@Sun.COM
861*9663SMark.Logan@Sun.COM PedFileSystemType fat32_type = {
862*9663SMark.Logan@Sun.COM .next = NULL,
863*9663SMark.Logan@Sun.COM .ops = &fat32_ops,
864*9663SMark.Logan@Sun.COM .name = "fat32",
865*9663SMark.Logan@Sun.COM .block_sizes = FAT_BLOCK_SIZES
866*9663SMark.Logan@Sun.COM };
867*9663SMark.Logan@Sun.COM
868*9663SMark.Logan@Sun.COM void
ped_file_system_fat_init()869*9663SMark.Logan@Sun.COM ped_file_system_fat_init ()
870*9663SMark.Logan@Sun.COM {
871*9663SMark.Logan@Sun.COM if (sizeof (FatBootSector) != 512) {
872*9663SMark.Logan@Sun.COM ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
873*9663SMark.Logan@Sun.COM _("GNU Parted was miscompiled: the FAT boot sector "
874*9663SMark.Logan@Sun.COM "should be 512 bytes. FAT support will be disabled."));
875*9663SMark.Logan@Sun.COM } else {
876*9663SMark.Logan@Sun.COM ped_file_system_type_register (&fat16_type);
877*9663SMark.Logan@Sun.COM ped_file_system_type_register (&fat32_type);
878*9663SMark.Logan@Sun.COM }
879*9663SMark.Logan@Sun.COM }
880*9663SMark.Logan@Sun.COM
881*9663SMark.Logan@Sun.COM void
ped_file_system_fat_done()882*9663SMark.Logan@Sun.COM ped_file_system_fat_done ()
883*9663SMark.Logan@Sun.COM {
884*9663SMark.Logan@Sun.COM ped_file_system_type_unregister (&fat16_type);
885*9663SMark.Logan@Sun.COM ped_file_system_type_unregister (&fat32_type);
886*9663SMark.Logan@Sun.COM }
887*9663SMark.Logan@Sun.COM
888