OSDN Git Service

17cdf4eaca611dfa210d7f8beb6fc6a1e49c56b5
[android-x86/external-parted.git] / libparted / labels / loop.c
1 /*
2     libparted - a library for manipulating disk partitions
3     Copyright (C) 1999-2000, 2007-2010 Free Software Foundation, Inc.
4
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.
9
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.
14
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/>.
17 */
18
19 #include <config.h>
20
21 #include <parted/parted.h>
22 #include <parted/debug.h>
23 #include <parted/endian.h>
24 #include <stdbool.h>
25
26 #include "pt-tools.h"
27
28 #if ENABLE_NLS
29 #  include <libintl.h>
30 #  define _(String) dgettext (PACKAGE, String)
31 #else
32 #  define _(String) (String)
33 #endif /* ENABLE_NLS */
34
35 #define LOOP_SIGNATURE          "GNU Parted Loopback 0"
36
37 static PedDiskType loop_disk_type;
38
39 static PedDisk* loop_alloc (const PedDevice* dev);
40 static void loop_free (PedDisk* disk);
41
42 static int
43 loop_probe (const PedDevice* dev)
44 {
45         PedDisk *disk = loop_alloc (dev);
46         if (!disk)
47                 goto error;
48
49         void *buf;
50         if (!ptt_read_sector (dev, 0, &buf))
51                 goto error_destroy_disk;
52         int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
53         free (buf);
54
55         int result;
56         if (found_sig) {
57                 result = 1;
58         } else {
59                 PedGeometry*    geom;
60
61                 geom = ped_geometry_new (dev, 0, disk->dev->length);
62                 if (!geom)
63                         goto error_destroy_disk;
64                 result = ped_file_system_probe (geom) != NULL;
65                 ped_geometry_destroy (geom);
66         }
67         loop_free (disk);
68         return result;
69
70 error_destroy_disk:
71         loop_free (disk);
72 error:
73         return 0;
74 }
75
76 static PedDisk*
77 loop_alloc (const PedDevice* dev)
78 {
79         PED_ASSERT (dev != NULL, return 0);
80
81         if (dev->length < 256)
82                 return NULL;
83         return _ped_disk_alloc ((PedDevice*)dev, &loop_disk_type);
84 }
85
86 static PedDisk*
87 loop_duplicate (const PedDisk* disk)
88 {
89         return ped_disk_new_fresh (disk->dev, &loop_disk_type);
90 }
91
92 static void
93 loop_free (PedDisk* disk)
94 {
95         PED_ASSERT (disk != NULL, return);
96
97         _ped_disk_free (disk);
98 }
99
100 static int
101 loop_read (PedDisk* disk)
102 {
103         PedDevice*              dev = NULL;
104         PedGeometry*            geom;
105         PedFileSystemType*      fs_type;
106         PedPartition*           part;
107         PedConstraint*          constraint_any;
108
109         PED_ASSERT (disk != NULL, return 0);
110         dev = disk->dev;
111         constraint_any = ped_constraint_any (dev);
112
113         ped_disk_delete_all (disk);
114
115         void *buf;
116         if (!ptt_read_sector (dev, 0, &buf))
117                 goto error;
118
119         int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
120         free (buf);
121
122         if (found_sig) {
123                 ped_constraint_destroy (constraint_any);
124                 return 1;
125         }
126
127         geom = ped_geometry_new (dev, 0, dev->length);
128         if (!geom)
129                 goto error;
130
131         fs_type = ped_file_system_probe (geom);
132         if (!fs_type)
133                 goto error_free_geom;
134
135         part = ped_partition_new (disk, PED_PARTITION_NORMAL,
136                                   fs_type, geom->start, geom->end);
137         ped_geometry_destroy (geom);
138         if (!part)
139                 goto error;
140         part->fs_type = fs_type;
141
142         if (!ped_disk_add_partition (disk, part, constraint_any))
143                 goto error;
144         ped_constraint_destroy (constraint_any);
145         return 1;
146
147 error_free_geom:
148         ped_geometry_destroy (geom);
149 error:
150         ped_constraint_destroy (constraint_any);
151         return 0;
152 }
153
154 #ifndef DISCOVER_ONLY
155 static int
156 loop_write (const PedDisk* disk)
157 {
158         size_t buflen = disk->dev->sector_size;
159         char *buf = ped_malloc (buflen);
160         if (buf == NULL)
161                 return 0;
162
163         if (ped_disk_get_partition (disk, 1)) {
164                 if (!ped_device_read (disk->dev, buf, 0, 1)) {
165                         free (buf);
166                         return 0;
167                 }
168                 if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0) {
169                         free (buf);
170                         return 1;
171                 }
172                 memset (buf, 0, strlen (LOOP_SIGNATURE));
173                 return ped_device_write (disk->dev, buf, 0, 1);
174         }
175
176         memset (buf, 0, buflen);
177         strcpy (buf, LOOP_SIGNATURE);
178
179         int write_ok = ped_device_write (disk->dev, buf, 0, 1);
180         free (buf);
181         return write_ok;
182 }
183 #endif /* !DISCOVER_ONLY */
184
185 static PedPartition*
186 loop_partition_new (const PedDisk* disk, PedPartitionType part_type,
187                     const PedFileSystemType* fs_type,
188                     PedSector start, PedSector end)
189 {
190         PedPartition*   part;
191
192         part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
193         if (!part)
194                 return NULL;
195         part->disk_specific = NULL;
196         return part;
197 }
198
199 static PedPartition*
200 loop_partition_duplicate (const PedPartition* part)
201 {
202         PedPartition* result;
203
204         result = ped_partition_new (part->disk, part->type, part->fs_type,
205                                     part->geom.start, part->geom.end);
206         result->num = part->num;
207         return result;
208 }
209
210 static void
211 loop_partition_destroy (PedPartition* part)
212 {
213         free (part);
214 }
215
216 static int
217 loop_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
218 {
219         part->fs_type = fs_type;
220         return 1;
221 }
222
223 static int
224 loop_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
225 {
226         return 0;
227 }
228
229 static int
230 loop_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
231 {
232         return 0;
233 }
234
235 static int
236 loop_partition_align (PedPartition* part, const PedConstraint* constraint)
237 {
238         PedGeometry*    new_geom;
239
240         new_geom = ped_constraint_solve_nearest (constraint, &part->geom);
241         if (!new_geom) {
242                 ped_exception_throw (
243                         PED_EXCEPTION_ERROR,
244                         PED_EXCEPTION_CANCEL,
245                         _("Unable to satisfy all constraints on the "
246                           "partition."));
247                 return 0;
248         }
249         ped_geometry_set (&part->geom, new_geom->start, new_geom->length);
250         ped_geometry_destroy (new_geom);
251         return 1;
252 }
253
254 static int
255 loop_partition_is_flag_available (const PedPartition* part,
256                                   PedPartitionFlag flag)
257 {
258         return 0;
259 }
260
261 static int
262 loop_partition_enumerate (PedPartition* part)
263 {
264         part->num = 1;
265         return 1;
266 }
267
268 static int
269 loop_alloc_metadata (PedDisk* disk)
270 {
271         return 1;
272 }
273
274 static int
275 loop_get_max_primary_partition_count (const PedDisk* disk)
276 {
277         return 1;
278 }
279
280 static bool
281 loop_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
282 {
283         *max_n = 1;
284         return true;
285 }
286
287 #include "pt-common.h"
288 PT_define_limit_functions (loop)
289
290 static PedDiskOps loop_disk_ops = {
291         clobber:                NULL,
292         write:                  NULL_IF_DISCOVER_ONLY (loop_write),
293
294         partition_set_name:     NULL,
295         partition_get_name:     NULL,
296
297         PT_op_function_initializers (loop)
298 };
299
300 static PedDiskType loop_disk_type = {
301         next:           NULL,
302         name:           "loop",
303         ops:            &loop_disk_ops,
304         features:       0
305 };
306
307 void
308 ped_disk_loop_init ()
309 {
310         ped_disk_type_register (&loop_disk_type);
311 }
312
313 void
314 ped_disk_loop_done ()
315 {
316         ped_disk_type_unregister (&loop_disk_type);
317 }