1
/* libparted - a library for manipulating disk partitions
2
Copyright (C) 1999-2001, 2007-2012 Free Software Foundation, Inc.
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 3 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program. If not, see <http://www.gnu.org/licenses/>.
18
/** \file filesys.c */
21
* \addtogroup PedFileSystem
23
* \note File systems exist on a PedGeometry - NOT a PedPartition.
30
#include <parted/parted.h>
31
#include <parted/debug.h>
36
# define _(String) dgettext (PACKAGE, String)
38
# define _(String) (String)
39
#endif /* ENABLE_NLS */
41
#define STREQ(a, b) (strcmp (a, b) == 0)
44
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
47
typedef PedFileSystem * (*open_fn_t) (PedGeometry *);
48
extern PedFileSystem *hfsplus_open (PedGeometry *);
49
extern PedFileSystem *hfs_open (PedGeometry *);
50
extern PedFileSystem *fat_open (PedGeometry *);
52
typedef int (*close_fn_t) (PedFileSystem *);
53
extern int hfsplus_close (PedFileSystem *);
54
extern int hfs_close (PedFileSystem *);
55
extern int fat_close (PedFileSystem *);
57
typedef int (*resize_fn_t) (PedFileSystem *fs, PedGeometry *geom,
59
extern int hfsplus_resize (PedFileSystem *fs, PedGeometry *geom,
61
extern int hfs_resize (PedFileSystem *fs, PedGeometry *geom,
63
extern int fat_resize (PedFileSystem *fs, PedGeometry *geom,
66
typedef PedConstraint * (*resize_constraint_fn_t) (PedFileSystem const *fs);
67
extern PedConstraint *hfsplus_get_resize_constraint (PedFileSystem const *fs);
68
extern PedConstraint *hfs_get_resize_constraint (PedFileSystem const *fs);
69
extern PedConstraint *fat_get_resize_constraint (PedFileSystem const *fs);
72
is_hfs_plus (char const *fs_type_name)
74
return STREQ (fs_type_name, "hfsx") || STREQ (fs_type_name, "hfs+");
78
open_fn (char const *fs_type_name)
80
if (is_hfs_plus (fs_type_name))
82
if (STREQ (fs_type_name, "hfs"))
84
if (strncmp (fs_type_name, "fat", 3) == 0)
90
close_fn (char const *fs_type_name)
92
if (is_hfs_plus (fs_type_name))
94
if (STREQ (fs_type_name, "hfs"))
96
if (strncmp (fs_type_name, "fat", 3) == 0)
102
resize_fn (char const *fs_type_name)
104
if (is_hfs_plus (fs_type_name))
105
return hfsplus_resize;
106
if (STREQ (fs_type_name, "hfs"))
108
if (strncmp (fs_type_name, "fat", 3) == 0)
113
static resize_constraint_fn_t
114
resize_constraint_fn (char const *fs_type_name)
116
if (is_hfs_plus (fs_type_name))
117
return hfsplus_get_resize_constraint;
118
if (STREQ (fs_type_name, "hfs"))
119
return hfs_get_resize_constraint;
120
if (strncmp (fs_type_name, "fat", 3) == 0)
121
return fat_get_resize_constraint;
126
* This function opens the file system stored on \p geom, if it
128
* It is often called in the following manner:
130
* fs = ped_file_system_open (&part.geom)
133
* \throws PED_EXCEPTION_ERROR if file system could not be detected
134
* \throws PED_EXCEPTION_ERROR if the file system is bigger than its volume
135
* \throws PED_EXCEPTION_NO_FEATURE if opening of a file system stored on
136
* \p geom is not implemented
138
* \return a PedFileSystem on success, \c NULL on failure.
141
ped_file_system_open (PedGeometry* geom)
143
PED_ASSERT (geom != NULL);
145
if (!ped_device_open (geom->dev))
148
PedFileSystemType *type = ped_file_system_probe (geom);
150
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
151
_("Could not detect file system."));
152
goto error_close_dev;
155
open_fn_t open_f = open_fn (type->name);
156
if (open_f == NULL) {
157
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
158
_("resizing %s file systems is not supported"),
160
goto error_close_dev;
163
PedGeometry *probed_geom = ped_file_system_probe_specific (type, geom);
165
goto error_close_dev;
166
if (!ped_geometry_test_inside (geom, probed_geom)) {
167
if (ped_exception_throw (
169
PED_EXCEPTION_IGNORE_CANCEL,
170
_("The file system is bigger than its volume!"))
171
!= PED_EXCEPTION_IGNORE)
172
goto error_destroy_probed_geom;
175
PedFileSystem *fs = (*open_f) (probed_geom);
177
goto error_destroy_probed_geom;
178
ped_geometry_destroy (probed_geom);
182
error_destroy_probed_geom:
183
ped_geometry_destroy (probed_geom);
185
ped_device_close (geom->dev);
191
* Close file system \p fs.
193
* \return \c 1 on success, \c 0 on failure
196
ped_file_system_close (PedFileSystem* fs)
198
PED_ASSERT (fs != NULL);
199
PedDevice *dev = fs->geom->dev;
201
if (!(close_fn (fs->type->name) (fs)))
202
goto error_close_dev;
203
ped_device_close (dev);
207
ped_device_close (dev);
212
* This function erases all file system signatures that indicate that a
213
* file system occupies a given region described by \p geom.
214
* After this operation ped_file_system_probe() won't detect any file system.
216
* \note ped_file_system_create() calls this before creating a new file system.
218
* \return \c 1 on success, \c 0 on failure
221
ped_file_system_clobber (PedGeometry* geom)
223
PED_ASSERT (geom != NULL);
225
if (!ped_device_open (geom->dev))
228
/* Clear the first three and the last two sectors, albeit fewer
229
when GEOM is too small. */
230
PedSector len = MIN (geom->length, geom->dev->length);
233
? ptt_geom_clear_sectors (geom, 0, len)
234
: (ptt_geom_clear_sectors (geom, 0, 3)
235
&& ptt_geom_clear_sectors (geom, geom->dev->length - 2, 2)));
237
ped_device_close (geom->dev);
241
/* This function erases all signatures that indicate the presence of
242
* a file system in a particular region, without erasing any data
243
* contained inside the "exclude" region.
246
ped_file_system_clobber_exclude (PedGeometry* geom,
247
const PedGeometry* exclude)
249
PedGeometry* clobber_geom;
252
if (ped_geometry_test_sector_inside (exclude, geom->start))
255
clobber_geom = ped_geometry_duplicate (geom);
256
if (ped_geometry_test_overlap (clobber_geom, exclude))
257
ped_geometry_set_end (clobber_geom, exclude->start - 1);
259
status = ped_file_system_clobber (clobber_geom);
260
ped_geometry_destroy (clobber_geom);
265
* Resize \p fs to new geometry \p geom.
267
* \p geom should satisfy the ped_file_system_get_resize_constraint().
268
* (This isn't asserted, so it's not a bug not to... just it's likely
269
* to fail ;) If \p timer is non-NULL, it is used as the progress meter.
271
* \throws PED_EXCEPTION_NO_FEATURE if resizing of file system \p fs
272
* is not implemented yet
274
* \return \c 0 on failure
277
ped_file_system_resize (PedFileSystem *fs, PedGeometry *geom, PedTimer *timer)
279
PED_ASSERT (fs != NULL);
280
PED_ASSERT (geom != NULL);
282
resize_fn_t resize_f = resize_fn (fs->type->name);
283
if (resize_f == NULL) {
284
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
285
_("resizing %s file systems is not supported"),
290
if (!ped_file_system_clobber_exclude (geom, fs->geom))
293
return resize_f (fs, geom, timer);
297
* Return a constraint that represents all of the possible ways the
298
* file system \p fs can be resized with ped_file_system_resize().
299
* This takes into account the amount of used space on
300
* the filesystem \p fs and the capabilities of the resize algorithm.
302
* -# if constraint->start_align->grain_size == 0, or
303
* constraint->start_geom->length == 1, then the start cannot be moved
304
* -# constraint->min_size is the minimum size you can resize the partition
305
* to. You might want to tell the user this ;-).
307
* \return a PedConstraint on success, \c NULL on failure
310
ped_file_system_get_resize_constraint (const PedFileSystem *fs)
312
PED_ASSERT (fs != NULL);
314
resize_constraint_fn_t resize_constraint_f =
315
resize_constraint_fn (fs->type->name);
316
if (resize_constraint_f == NULL)
319
return resize_constraint_f (fs);