2
libparted - a library for manipulating disk partitions
3
Copyright (C) 1999-2001, 2007-2012 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/>.
19
/** \file filesys.c */
22
* \addtogroup PedFileSystem
24
* \note File systems exist on a PedGeometry - NOT a PedPartition.
31
#include <parted/parted.h>
32
#include <parted/debug.h>
36
# define _(String) dgettext (PACKAGE, String)
38
# define _(String) (String)
39
#endif /* ENABLE_NLS */
41
#define BUFFER_SIZE 4096 /* in sectors */
43
static PedFileSystemType* fs_types = NULL;
44
static PedFileSystemAlias* fs_aliases = NULL;
47
ped_file_system_type_register (PedFileSystemType* fs_type)
49
PED_ASSERT (fs_type != NULL);
50
PED_ASSERT (fs_type->ops != NULL);
51
PED_ASSERT (fs_type->name != NULL);
53
fs_type->next = fs_types;
58
ped_file_system_type_unregister (PedFileSystemType* fs_type)
60
PedFileSystemType* walk;
61
PedFileSystemType* last = NULL;
63
PED_ASSERT (fs_types != NULL);
64
PED_ASSERT (fs_type != NULL);
66
for (walk = fs_types; walk && walk != fs_type;
67
last = walk, walk = walk->next);
69
PED_ASSERT (walk != NULL);
71
((struct _PedFileSystemType*) last)->next = fs_type->next;
73
fs_types = fs_type->next;
77
ped_file_system_alias_register (PedFileSystemType* fs_type, const char* alias,
80
PedFileSystemAlias* fs_alias;
82
PED_ASSERT (fs_type != NULL);
83
PED_ASSERT (alias != NULL);
85
fs_alias = ped_malloc (sizeof *fs_alias);
89
fs_alias->next = fs_aliases;
90
fs_alias->fs_type = fs_type;
91
fs_alias->alias = alias;
92
fs_alias->deprecated = deprecated;
93
fs_aliases = fs_alias;
97
ped_file_system_alias_unregister (PedFileSystemType* fs_type,
100
PedFileSystemAlias* walk;
101
PedFileSystemAlias* last = NULL;
103
PED_ASSERT (fs_aliases != NULL);
104
PED_ASSERT (fs_type != NULL);
105
PED_ASSERT (alias != NULL);
107
for (walk = fs_aliases; walk; last = walk, walk = walk->next) {
108
if (walk->fs_type == fs_type && !strcmp (walk->alias, alias))
112
PED_ASSERT (walk != NULL);
114
last->next = walk->next;
116
fs_aliases = walk->next;
121
* Get a PedFileSystemType by its @p name.
123
* @return @c NULL if none found.
126
ped_file_system_type_get (const char* name)
128
PedFileSystemType* walk;
129
PedFileSystemAlias* alias_walk;
131
PED_ASSERT (name != NULL);
133
for (walk = fs_types; walk != NULL; walk = walk->next) {
134
if (!strcasecmp (walk->name, name))
140
for (alias_walk = fs_aliases; alias_walk != NULL;
141
alias_walk = alias_walk->next) {
142
if (!strcasecmp (alias_walk->alias, name))
145
if (alias_walk != NULL) {
146
if (alias_walk->deprecated)
147
PED_DEBUG (0, "File system alias %s is deprecated",
149
return alias_walk->fs_type;
156
* Get the next PedFileSystemType after @p fs_type.
158
* @return @c NULL if @p fs_type is the last item in the list.
161
ped_file_system_type_get_next (const PedFileSystemType* fs_type)
164
return fs_type->next;
170
* Get the next PedFileSystemAlias after @p fs_alias.
172
* @return @c NULL if @p fs_alias is the last item in the list.
175
ped_file_system_alias_get_next (const PedFileSystemAlias* fs_alias)
178
return fs_alias->next;
184
* Attempt to find a file system and return the region it occupies.
186
* @param fs_type The file system type to probe for.
187
* @param geom The region to be searched.
189
* @return @p NULL if @p fs_type file system wasn't detected
192
ped_file_system_probe_specific (
193
const PedFileSystemType* fs_type, PedGeometry* geom)
197
PED_ASSERT (fs_type != NULL);
198
PED_ASSERT (fs_type->ops->probe != NULL);
199
PED_ASSERT (geom != NULL);
201
/* Fail all fs-specific probe-related tests when sector size
202
is not the default. */
203
if (geom->dev->sector_size != PED_SECTOR_SIZE_DEFAULT)
206
if (!ped_device_open (geom->dev))
208
result = fs_type->ops->probe (geom);
209
ped_device_close (geom->dev);
214
_geometry_error (const PedGeometry* a, const PedGeometry* b)
216
PedSector start_delta = a->start - b->start;
217
PedSector end_delta = a->end - b->end;
219
return abs (start_delta) + abs (end_delta);
222
static PedFileSystemType*
223
_best_match (const PedGeometry* geom, PedFileSystemType* detected [],
224
const int detected_error [], int detected_count)
230
min_error = PED_MAX (4096, geom->length / 100);
232
for (i = 1; i < detected_count; i++) {
233
if (detected_error [i] < detected_error [best_match])
237
/* make sure the best match is significantly better than all the
240
for (i = 0; i < detected_count; i++) {
244
if (abs (detected_error [best_match] - detected_error [i])
249
return detected [best_match];
254
* Attempt to detect a file system in region \p geom.
255
* This function tries to be clever at dealing with ambiguous
256
* situations, such as when one file system was not completely erased before a
257
* new file system was created on top of it.
259
* \return a new PedFileSystem on success, \c NULL on failure
262
ped_file_system_probe (PedGeometry* geom)
264
PedFileSystemType* detected[32];
265
int detected_error[32];
266
int detected_count = 0;
267
PedFileSystemType* walk = NULL;
269
PED_ASSERT (geom != NULL);
271
if (!ped_device_open (geom->dev))
274
ped_exception_fetch_all ();
275
while ( (walk = ped_file_system_type_get_next (walk)) ) {
278
probed = ped_file_system_probe_specific (walk, geom);
280
detected [detected_count] = walk;
281
detected_error [detected_count]
282
= _geometry_error (geom, probed);
284
ped_geometry_destroy (probed);
286
ped_exception_catch ();
289
ped_exception_leave_all ();
291
ped_device_close (geom->dev);
295
walk = _best_match (geom, detected, detected_error, detected_count);