2 clear_fat - a tool to clear unused space (for testing purposes)
3 Copyright (C) 2000, 2007-2011 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "configmake.h"
29 #include "long-options.h"
33 #include "../../libparted/fs/fat/fat.h"
37 /* Take care of NLS matters. */
42 # define textdomain(Domainname) /* empty */
43 # undef bindtextdomain
44 # define bindtextdomain(Domainname, Dirname) /* empty */
48 #define _(msgid) gettext (msgid)
52 /* The official name of this program (e.g., no `g' prefix). */
53 #define PROGRAM_NAME "clearfat"
56 "<http://git.debian.org/?p=parted/parted.git;a=blob_plain;f=AUTHORS>"
61 if (status != EXIT_SUCCESS)
62 fprintf (stderr, _("Try `%s --help' for more information.\n"),
68 or: %s DEVICE MINOR\n"), PROGRAM_NAME, PROGRAM_NAME);
70 Clear unused space on a FAT partition (a GNU Parted testing tool).\n\
73 fputs (_(" --help display this help and exit\n"), stdout);
74 fputs (_(" --version output version information and exit\n"),
76 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
81 #define CLEAR_BUFFER_SIZE (1024 * 1024)
82 #define CLEAR_BUFFER_SECTORS (CLEAR_BUFFER_SIZE/512)
84 static char buffer [CLEAR_BUFFER_SIZE];
86 /* generic clearing code ***************************************************/
89 _clear_sectors (PedGeometry* geom, PedSector start, PedSector count)
92 PedSector to_go = count;
96 pos += CLEAR_BUFFER_SECTORS, to_go -= CLEAR_BUFFER_SECTORS) {
97 if (!ped_geometry_write (geom, buffer, start,
98 PED_MIN (CLEAR_BUFFER_SECTORS, to_go)))
106 _clear_sector_range (PedGeometry* geom, PedSector start, PedSector end)
108 return _clear_sectors (geom, start, end - start + 1);
112 _clear_sector (PedGeometry* geom, PedSector sector)
114 return _clear_sectors (geom, sector, 1);
118 _clear_partial_sector (PedGeometry* geom, PedSector sector,
119 int offset, int count)
121 if (!ped_geometry_read (geom, buffer, sector, 1))
123 memset (buffer + offset, 0, count);
124 if (!ped_geometry_write (geom, buffer, sector, 1))
127 memset (buffer, 0, 512);
131 memset (buffer, 0, 512);
136 _clear_partial_range (PedGeometry* geom, PedSector sector, int start, int end)
138 return _clear_partial_sector (geom, sector, start, end - start + 1);
142 _clear_clusters (PedFileSystem* fs, FatCluster start, FatCluster count)
144 FatSpecific* fs_info = FAT_SPECIFIC (fs);
145 return _clear_sectors (fs->geom, fat_cluster_to_sector(fs, start),
146 count * fs_info->cluster_sectors);
149 /* FAT code ******************************************************************/
152 _clear_before_fat (PedFileSystem* fs)
154 FatSpecific* fs_info = FAT_SPECIFIC (fs);
157 for (sector = 1; sector < fs_info->fat_offset; sector++) {
158 if (sector == fs_info->info_sector_offset)
160 if (sector == fs_info->boot_sector_backup_offset)
162 _clear_sector (fs->geom, sector);
167 _calc_fat_entry_offset (PedFileSystem* fs, FatCluster cluster)
169 FatSpecific* fs_info = FAT_SPECIFIC (fs);
171 switch (fs_info->fat_type) {
173 PED_ASSERT (0, (void) 0);
186 _clear_unused_fats (PedFileSystem* fs)
188 FatSpecific* fs_info = FAT_SPECIFIC (fs);
189 PedSector table_start;
191 int last_active_offset;
192 PedSector last_active_sector;
193 int last_active_sector_offset;
196 = _calc_fat_entry_offset (fs, fs_info->fat->cluster_count);
197 last_active_sector = last_active_offset / 512;
198 last_active_sector_offset = last_active_offset % 512 + 4;
200 for (table_num = 0; table_num < fs_info->fat_table_count; table_num++) {
201 table_start = fs_info->fat_offset
202 + table_num * fs_info->fat_sectors;
204 if (last_active_sector_offset < 512) {
205 _clear_partial_range (
207 table_start + last_active_sector,
208 last_active_sector_offset,
212 if (last_active_sector < fs_info->fat_sectors - 2) {
213 _clear_sector_range (
215 table_start + last_active_sector + 1,
216 table_start + fs_info->fat_sectors - 1);
222 _clear_unused_clusters (PedFileSystem* fs)
224 FatSpecific* fs_info = FAT_SPECIFIC (fs);
226 FatCluster run_start = 0; /* shut gcc up! */
227 FatCluster run_length = 0;
229 for (cluster = 2; cluster < fs_info->cluster_count + 2; cluster++) {
230 if (fat_table_is_available (fs_info->fat, cluster)) {
239 _clear_clusters (fs, run_start, run_length);
245 _clear_clusters (fs, run_start, run_length);
251 _clear_unused_fat (PedFileSystem* fs)
253 memset (buffer, 0, CLEAR_BUFFER_SIZE);
255 _clear_before_fat (fs);
256 _clear_unused_fats (fs);
257 _clear_unused_clusters (fs);
260 /* bureaucracy ***************************************************************/
263 main (int argc, char* argv[])
270 set_program_name (argv[0]);
271 setlocale (LC_ALL, "");
272 bindtextdomain (PACKAGE, LOCALEDIR);
273 textdomain (PACKAGE);
275 atexit (close_stdout);
277 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
278 usage, AUTHORS, (char const *) NULL);
279 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
280 usage (EXIT_FAILURE);
282 if (argc - optind < 2)
284 error (0, 0, _("too few arguments"));
285 usage (EXIT_FAILURE);
287 if (2 < argc - optind)
289 error (0, 0, _("too many arguments"));
290 usage (EXIT_FAILURE);
293 unsigned long minor_dev_number;
294 if (xstrtoul (argv[2], NULL, 10, &minor_dev_number, NULL)
295 || INT_MAX < minor_dev_number)
297 error (0, 0, _("invalid minor device number: %s"), argv[2]);
298 usage (EXIT_FAILURE);
301 dev = ped_device_get (argv [1]);
304 if (!ped_device_open (dev))
307 disk = ped_disk_new (dev);
309 goto error_close_dev;
311 part = ped_disk_get_partition (disk, minor_dev_number);
313 printf ("Couldn't find partition `%s'\n", argv[2]);
314 goto error_destroy_disk;
317 fs = ped_file_system_open (&part->geom);
319 goto error_destroy_disk;
321 if (strncmp (fs->type->name, "fat", 3)) {
322 printf ("Not a FAT file system!\n");
326 _clear_unused_fat (fs);
328 ped_file_system_close (fs);
329 ped_disk_destroy (disk);
330 ped_device_close (dev);
334 ped_file_system_close (fs);
336 ped_disk_destroy (disk);
338 ped_device_close (dev);
343 #else /* DISCOVER_ONLY */
349 printf ("You must compile libparted with full read/write support\n");
353 #endif /* DISCOVER_ONLY */