~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to libparted/fs/linux_swap/linux_swap.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    libparted - a library for manipulating disk partitions
 
3
    Copyright (C) 1999-2000, 2002, 2007-2012 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
/* It's a bit silly calling a swap partition a file system.  Oh well...  */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#include <parted/parted.h>
 
24
#include <parted/endian.h>
 
25
 
 
26
#if ENABLE_NLS
 
27
#  include <libintl.h>
 
28
#  define _(String) dgettext (PACKAGE, String)
 
29
#else
 
30
#  define _(String) (String)
 
31
#endif /* ENABLE_NLS */
 
32
 
 
33
#include <unistd.h>
 
34
#include <uuid/uuid.h>
 
35
 
 
36
#define SWAP_SPECIFIC(fs) ((SwapSpecific*) (fs->type_specific))
 
37
#define BUFFER_SIZE 128
 
38
 
 
39
#define LINUXSWAP_BLOCK_SIZES       ((int[2]){512, 0})
 
40
 
 
41
typedef struct {
 
42
        char            page_map[1];
 
43
} SwapOldHeader;
 
44
 
 
45
/* ripped from mkswap */
 
46
typedef struct {
 
47
        char            bootbits[1024];    /* Space for disklabel etc. */
 
48
        uint32_t        version;
 
49
        uint32_t        last_page;
 
50
        uint32_t        nr_badpages;
 
51
        unsigned char   sws_uuid[16];
 
52
        unsigned char   sws_volume[16];
 
53
        uint32_t        padding[117];
 
54
        uint32_t        badpages[1];
 
55
} SwapNewHeader;
 
56
 
 
57
typedef struct {
 
58
        union {
 
59
                SwapNewHeader   new;
 
60
                SwapOldHeader   old;
 
61
        }* header;
 
62
 
 
63
        void*           buffer;
 
64
        int             buffer_size;
 
65
 
 
66
        PedSector       page_sectors;
 
67
        unsigned int    page_count;
 
68
        unsigned int    version;
 
69
        unsigned int    max_bad_pages;
 
70
} SwapSpecific;
 
71
 
 
72
static PedFileSystemType _swap_v0_type;
 
73
static PedFileSystemType _swap_v1_type;
 
74
static PedFileSystemType _swap_swsusp_type;
 
75
 
 
76
static PedFileSystem* _swap_v0_open (PedGeometry* geom);
 
77
static PedFileSystem* _swap_v1_open (PedGeometry* geom);
 
78
static PedFileSystem* _swap_swsusp_open (PedGeometry* geom);
 
79
static int swap_close (PedFileSystem* fs);
 
80
 
 
81
static PedGeometry*
 
82
_generic_swap_probe (PedGeometry* geom, int kind)
 
83
{
 
84
        PedFileSystem*  fs;
 
85
        SwapSpecific*   fs_info;
 
86
        PedGeometry*    probed_geom;
 
87
        PedSector       length;
 
88
 
 
89
        /* Fail the swap-file-system-recognizing test when sector size
 
90
           is not the default.  */
 
91
        if (geom->dev->sector_size != PED_SECTOR_SIZE_DEFAULT)
 
92
                return NULL;
 
93
 
 
94
        switch (kind) {
 
95
        /* Check for old style swap partitions. */
 
96
                case 0:
 
97
                        fs = _swap_v0_open(geom);
 
98
                        break;
 
99
        /* Check for new style swap partitions. */
 
100
                case 1:
 
101
                        fs = _swap_v1_open(geom);
 
102
                        break;
 
103
        /* Check for swap partitions containing swsusp data. */
 
104
                case -1:
 
105
                        fs = _swap_swsusp_open(geom);
 
106
                        break;
 
107
        /* Not reached. */
 
108
                default:
 
109
                        goto error;
 
110
        }
 
111
 
 
112
        if (!fs)
 
113
                goto error;
 
114
        fs_info = SWAP_SPECIFIC (fs);
 
115
 
 
116
        if (fs_info->version)
 
117
                length = fs_info->page_sectors * fs_info->page_count;
 
118
        else
 
119
                length = geom->length;
 
120
 
 
121
        probed_geom = ped_geometry_new (geom->dev, geom->start, length);
 
122
        if (!probed_geom)
 
123
                goto error_close_fs;
 
124
        swap_close (fs);
 
125
        return probed_geom;
 
126
 
 
127
error_close_fs:
 
128
        swap_close (fs);
 
129
error:
 
130
        return NULL;
 
131
}
 
132
 
 
133
 
 
134
static int
 
135
swap_init (PedFileSystem* fs, int fresh)
 
136
{
 
137
        SwapSpecific*   fs_info = SWAP_SPECIFIC (fs);
 
138
 
 
139
        fs_info->page_sectors = getpagesize () / 512;
 
140
        fs_info->page_count = fs->geom->length / fs_info->page_sectors;
 
141
        fs_info->version = 1;
 
142
        fs_info->max_bad_pages = (getpagesize()
 
143
                                        - sizeof (SwapNewHeader)) / 4;
 
144
 
 
145
        if (fresh) {
 
146
                uuid_t uuid_dat;
 
147
 
 
148
                memset (fs_info->header, 0, getpagesize());
 
149
 
 
150
                /* version is always 1 here */
 
151
                uuid_generate (uuid_dat);
 
152
                memcpy (fs_info->header->new.sws_uuid, uuid_dat,
 
153
                        sizeof (fs_info->header->new.sws_uuid));
 
154
                return 1;
 
155
        }
 
156
        else
 
157
                return ped_geometry_read (fs->geom, fs_info->header,
 
158
                                          0, fs_info->page_sectors);
 
159
}
 
160
 
 
161
 
 
162
static PedFileSystem*
 
163
swap_alloc (PedGeometry* geom)
 
164
{
 
165
        PedFileSystem*  fs;
 
166
        SwapSpecific*   fs_info;
 
167
 
 
168
        fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
 
169
        if (!fs)
 
170
                goto error;
 
171
 
 
172
        fs->type_specific = (SwapSpecific*) ped_malloc (sizeof (SwapSpecific));
 
173
        if (!fs->type_specific)
 
174
                goto error_free_fs;
 
175
 
 
176
        fs_info = SWAP_SPECIFIC (fs);
 
177
        fs_info->header = ped_malloc (getpagesize());
 
178
        if (!fs_info->header)
 
179
                goto error_free_type_specific;
 
180
 
 
181
        fs_info = SWAP_SPECIFIC (fs);
 
182
        fs_info->buffer_size = getpagesize() * BUFFER_SIZE;
 
183
        fs_info->buffer = ped_malloc (fs_info->buffer_size);
 
184
        if (!fs_info->buffer)
 
185
                goto error_free_header;
 
186
 
 
187
        fs->geom = ped_geometry_duplicate (geom);
 
188
        if (!fs->geom)
 
189
                goto error_free_buffer;
 
190
        fs->type = &_swap_v1_type;
 
191
        return fs;
 
192
 
 
193
error_free_buffer:
 
194
        free (fs_info->buffer);
 
195
error_free_header:
 
196
        free (fs_info->header);
 
197
error_free_type_specific:
 
198
        free (fs->type_specific);
 
199
error_free_fs:
 
200
        free (fs);
 
201
error:
 
202
        return NULL;
 
203
}
 
204
 
 
205
static void
 
206
swap_free (PedFileSystem* fs)
 
207
{
 
208
        SwapSpecific*   fs_info = SWAP_SPECIFIC (fs);
 
209
 
 
210
        free (fs_info->buffer);
 
211
        free (fs_info->header);
 
212
        free (fs->type_specific);
 
213
 
 
214
        ped_geometry_destroy (fs->geom);
 
215
        free (fs);
 
216
}
 
217
 
 
218
static PedFileSystem*
 
219
_swap_v0_open (PedGeometry* geom)
 
220
{
 
221
        PedFileSystem*          fs;
 
222
        SwapSpecific*           fs_info;
 
223
        const char*             sig;
 
224
 
 
225
        fs = swap_alloc (geom);
 
226
        if (!fs)
 
227
                goto error;
 
228
        swap_init (fs, 0);
 
229
 
 
230
        fs_info = SWAP_SPECIFIC (fs);
 
231
        if (!ped_geometry_read (fs->geom, fs_info->header, 0,
 
232
                                fs_info->page_sectors))
 
233
                goto error_free_fs;
 
234
 
 
235
        sig = ((char*) fs_info->header) + getpagesize() - 10;
 
236
        if (strncmp (sig, "SWAP-SPACE", 10) == 0) {
 
237
                fs_info->version = 0;
 
238
                fs_info->page_count
 
239
                        = PED_MIN (fs->geom->length / fs_info->page_sectors,
 
240
                                   8 * (getpagesize() - 10));
 
241
        } else {
 
242
                char    _sig [11];
 
243
 
 
244
                memcpy (_sig, sig, 10);
 
245
                _sig [10] = 0;
 
246
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
247
                        _("Unrecognised old style linux swap signature '%10s'."), _sig);
 
248
                goto error_free_fs;
 
249
        }
 
250
 
 
251
        fs->checked = 1;
 
252
        return fs;
 
253
 
 
254
error_free_fs:
 
255
        swap_free (fs);
 
256
error:
 
257
        return NULL;
 
258
}
 
259
 
 
260
static PedFileSystem*
 
261
_swap_v1_open (PedGeometry* geom)
 
262
{
 
263
        PedFileSystem*          fs;
 
264
        SwapSpecific*           fs_info;
 
265
        const char*             sig;
 
266
 
 
267
        fs = swap_alloc (geom);
 
268
        if (!fs)
 
269
                goto error;
 
270
/*      swap_init (fs, 0); */
 
271
 
 
272
/*      fs_info = SWAP_SPECIFIC (fs); */
 
273
/*      if (!ped_geometry_read (fs->geom, fs_info->header, 0, */
 
274
/*                              fs_info->page_sectors)) */
 
275
        if (!swap_init(fs, 0))
 
276
                goto error_free_fs;
 
277
 
 
278
        fs_info = SWAP_SPECIFIC (fs);
 
279
 
 
280
        sig = ((char*) fs_info->header) + getpagesize() - 10;
 
281
        if (strncmp (sig, "SWAPSPACE2", 10) == 0) {
 
282
                fs_info->version = 1;
 
283
                fs_info->page_count = fs_info->header->new.last_page;
 
284
        } else {
 
285
                char    _sig [11];
 
286
 
 
287
                memcpy (_sig, sig, 10);
 
288
                _sig [10] = 0;
 
289
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
290
                        _("Unrecognised new style linux swap signature '%10s'."), _sig);
 
291
                goto error_free_fs;
 
292
        }
 
293
 
 
294
        fs->checked = 1;
 
295
        return fs;
 
296
 
 
297
error_free_fs:
 
298
        swap_free (fs);
 
299
error:
 
300
        return NULL;
 
301
}
 
302
 
 
303
static PedFileSystem*
 
304
_swap_swsusp_open (PedGeometry* geom)
 
305
{
 
306
        PedFileSystem*          fs;
 
307
        SwapSpecific*           fs_info;
 
308
        const char*             sig;
 
309
 
 
310
        fs = swap_alloc (geom);
 
311
        if (!fs)
 
312
                goto error;
 
313
        fs->type = &_swap_swsusp_type;
 
314
        swap_init (fs, 0);
 
315
 
 
316
        fs_info = SWAP_SPECIFIC (fs);
 
317
        if (!ped_geometry_read (fs->geom, fs_info->header, 0,
 
318
                                fs_info->page_sectors))
 
319
                goto error_free_fs;
 
320
 
 
321
        sig = ((char*) fs_info->header) + getpagesize() - 10;
 
322
        if (strncmp (sig, "S1SUSPEND", 9) == 0) {
 
323
                fs_info->version = -1;
 
324
        } else {
 
325
                char    _sig [10];
 
326
 
 
327
                memcpy (_sig, sig, 9);
 
328
                _sig [9] = 0;
 
329
                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 
330
                        _("Unrecognised swsusp linux swap signature '%9s'."), _sig);
 
331
                goto error_free_fs;
 
332
        }
 
333
 
 
334
        fs->checked = 1;
 
335
        return fs;
 
336
 
 
337
error_free_fs:
 
338
        swap_free (fs);
 
339
error:
 
340
        return NULL;
 
341
}
 
342
 
 
343
static int
 
344
swap_close (PedFileSystem* fs)
 
345
{
 
346
        swap_free (fs);
 
347
        return 1;
 
348
}
 
349
 
 
350
static PedGeometry*
 
351
_swap_v0_probe (PedGeometry* geom) {
 
352
        return _generic_swap_probe (geom, 0);
 
353
}
 
354
 
 
355
static PedGeometry*
 
356
_swap_v1_probe (PedGeometry* geom) {
 
357
        return _generic_swap_probe (geom, 1);
 
358
}
 
359
 
 
360
static PedGeometry*
 
361
_swap_swsusp_probe (PedGeometry* geom) {
 
362
        return _generic_swap_probe (geom, -1);
 
363
}
 
364
 
 
365
static PedFileSystemOps _swap_v0_ops = {
 
366
        probe:          _swap_v0_probe,
 
367
};
 
368
 
 
369
static PedFileSystemOps _swap_v1_ops = {
 
370
        probe:          _swap_v1_probe,
 
371
};
 
372
 
 
373
static PedFileSystemOps _swap_swsusp_ops = {
 
374
  probe:                _swap_swsusp_probe,
 
375
};
 
376
 
 
377
static PedFileSystemType _swap_v0_type = {
 
378
        next:   NULL,
 
379
        ops:    &_swap_v0_ops,
 
380
        name:   "linux-swap(v0)",
 
381
        block_sizes: LINUXSWAP_BLOCK_SIZES
 
382
};
 
383
 
 
384
static PedFileSystemType _swap_v1_type = {
 
385
        next:   NULL,
 
386
        ops:    &_swap_v1_ops,
 
387
        name:   "linux-swap(v1)",
 
388
        block_sizes: LINUXSWAP_BLOCK_SIZES
 
389
};
 
390
 
 
391
static PedFileSystemType _swap_swsusp_type = {
 
392
        next:   NULL,
 
393
        ops:    &_swap_swsusp_ops,
 
394
        name:   "swsusp",
 
395
        block_sizes: LINUXSWAP_BLOCK_SIZES
 
396
};
 
397
 
 
398
void
 
399
ped_file_system_linux_swap_init ()
 
400
{
 
401
        ped_file_system_type_register (&_swap_v0_type);
 
402
        ped_file_system_type_register (&_swap_v1_type);
 
403
        ped_file_system_type_register (&_swap_swsusp_type);
 
404
 
 
405
        ped_file_system_alias_register (&_swap_v0_type, "linux-swap(old)", 1);
 
406
        ped_file_system_alias_register (&_swap_v1_type, "linux-swap(new)", 1);
 
407
        ped_file_system_alias_register (&_swap_v1_type, "linux-swap", 0);
 
408
}
 
409
 
 
410
void
 
411
ped_file_system_linux_swap_done ()
 
412
{
 
413
        ped_file_system_alias_unregister (&_swap_v0_type, "linux-swap(old)");
 
414
        ped_file_system_alias_unregister (&_swap_v1_type, "linux-swap(new)");
 
415
        ped_file_system_alias_unregister (&_swap_v1_type, "linux-swap");
 
416
 
 
417
        ped_file_system_type_unregister (&_swap_v0_type);
 
418
        ped_file_system_type_unregister (&_swap_v1_type);
 
419
        ped_file_system_type_unregister (&_swap_swsusp_type);
 
420
}