~ubuntu-branches/ubuntu/utopic/udisks/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/13-dosfslabel.patch/src/helpers/job-mkfs.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2012-07-20 11:39:01 UTC
  • Revision ID: package-import@ubuntu.com-20120720113901-v00iwjwwykpn124u
Tags: 1.0.4-7
debian/patches/13-dosfslabel.patch: The original reasons why mlabel was
preferred over dosfslabel are no longer true. So switch back to dosfslabel
which is part of dosfstools which we already require for mkfs.vfat and
drop the Recommends on mtools. Fix the maximum length for FAT labels while
at it. (Closes: #680683)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
 
2
 *
 
3
 * Copyright (C) 2008 David Zeuthen <david@fubar.dk>
 
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 2 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, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#  include "config.h"
 
23
#endif
 
24
 
 
25
#define _LARGEFILE64_SOURCE
 
26
 
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <unistd.h>
 
30
#include <signal.h>
 
31
#include <errno.h>
 
32
#include <string.h>
 
33
#include <sys/types.h>
 
34
#include <sys/stat.h>
 
35
#include <fcntl.h>
 
36
#include <sys/wait.h>
 
37
#include <sys/mount.h>
 
38
 
 
39
#include <glib.h>
 
40
 
 
41
#include "job-shared.h"
 
42
 
 
43
int
 
44
main (int argc,
 
45
      char **argv)
 
46
{
 
47
  int fd;
 
48
  int ret;
 
49
  int exit_status;
 
50
  GError *error;
 
51
  const char *fstype;
 
52
  const char *device;
 
53
  char *command_line;
 
54
  char *standard_error;
 
55
  char **options;
 
56
  GString *s;
 
57
  char *label;
 
58
  int n;
 
59
  gboolean is_kernel_partitioned;
 
60
  GIOChannel *stdin_channel;
 
61
  GPtrArray *options_array;
 
62
  char *option;
 
63
  gsize option_len;
 
64
  char *endp;
 
65
  uid_t take_ownership_uid;
 
66
  gid_t take_ownership_gid;
 
67
 
 
68
  ret = 1;
 
69
  command_line = NULL;
 
70
  standard_error = NULL;
 
71
  take_ownership_uid = 0;
 
72
  take_ownership_gid = 0;
 
73
  label = NULL;
 
74
 
 
75
  if (argc != 4)
 
76
    {
 
77
      g_printerr ("wrong usage\n");
 
78
      goto out;
 
79
    }
 
80
  fstype = argv[1];
 
81
  device = argv[2];
 
82
  is_kernel_partitioned = (strcmp (argv[3], "1") == 0);
 
83
 
 
84
  options_array = g_ptr_array_new ();
 
85
  stdin_channel = g_io_channel_unix_new (0);
 
86
  if (stdin_channel == NULL)
 
87
    {
 
88
      g_printerr ("cannot open stdin\n");
 
89
      goto out;
 
90
    }
 
91
  while (g_io_channel_read_line (stdin_channel, &option, &option_len, NULL, NULL) == G_IO_STATUS_NORMAL)
 
92
    {
 
93
      option[option_len - 1] = '\0';
 
94
      if (strlen (option) == 0)
 
95
        break;
 
96
      g_ptr_array_add (options_array, option);
 
97
    }
 
98
  g_io_channel_unref (stdin_channel);
 
99
  g_ptr_array_add (options_array, NULL);
 
100
  options = (char **) g_ptr_array_free (options_array, FALSE);
 
101
 
 
102
  if (strcmp (fstype, "vfat") == 0)
 
103
    {
 
104
 
 
105
      /* allow to create an fs on the main block device */
 
106
      s = g_string_new ("mkfs.vfat -I");
 
107
      for (n = 0; options[n] != NULL; n++)
 
108
        {
 
109
          if (g_str_has_prefix (options[n], "label="))
 
110
            {
 
111
              label = strdup (options[n] + sizeof("label=") - 1);
 
112
              if (!validate_and_escape_label (&label, 254))
 
113
                {
 
114
                  g_string_free (s, TRUE);
 
115
                  goto out;
 
116
                }
 
117
              if (strlen (label) <= 11)
 
118
                {
 
119
                  g_string_append_printf (s, " -n \"%s\"", label);
 
120
                  g_free (label);
 
121
                  label = NULL;
 
122
                }
 
123
            }
 
124
          else
 
125
            {
 
126
              g_printerr ("option %s not supported\n", options[n]);
 
127
              goto out;
 
128
            }
 
129
        }
 
130
      g_string_append_printf (s, " %s", device);
 
131
      command_line = g_string_free (s, FALSE);
 
132
 
 
133
    }
 
134
  else if (strcmp (fstype, "ext2") == 0 || strcmp (fstype, "ext3") == 0 || strcmp (fstype, "ext4") == 0)
 
135
    {
 
136
 
 
137
      s = g_string_new ("mkfs.");
 
138
      g_string_append (s, fstype);
 
139
      g_string_append (s, " -F ");
 
140
      for (n = 0; options[n] != NULL; n++)
 
141
        {
 
142
          if (g_str_has_prefix (options[n], "label="))
 
143
            {
 
144
              label = strdup (options[n] + sizeof("label=") - 1);
 
145
              if (!validate_and_escape_label (&label, 16))
 
146
                {
 
147
                  g_string_free (s, TRUE);
 
148
                  goto out;
 
149
                }
 
150
              g_string_append_printf (s, " -L \"%s\"", label);
 
151
              g_free (label);
 
152
              label = NULL;
 
153
            }
 
154
          else if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
155
            {
 
156
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
157
              if (endp == NULL || *endp != '\0')
 
158
                {
 
159
                  g_printerr ("option %s is malformed\n", options[n]);
 
160
                  goto out;
 
161
                }
 
162
            }
 
163
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
164
            {
 
165
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
166
              if (endp == NULL || *endp != '\0')
 
167
                {
 
168
                  g_printerr ("option %s is malformed\n", options[n]);
 
169
                  goto out;
 
170
                }
 
171
            }
 
172
          else
 
173
            {
 
174
              g_printerr ("option %s not supported\n", options[n]);
 
175
              goto out;
 
176
            }
 
177
        }
 
178
      g_string_append_printf (s, " %s", device);
 
179
      command_line = g_string_free (s, FALSE);
 
180
 
 
181
    }
 
182
  else if (strcmp (fstype, "btrfs") == 0)
 
183
    {
 
184
 
 
185
      s = g_string_new ("mkfs.btrfs");
 
186
      for (n = 0; options[n] != NULL; n++)
 
187
        {
 
188
          if (g_str_has_prefix (options[n], "label="))
 
189
            {
 
190
              label = strdup (options[n] + sizeof("label=") - 1);
 
191
              if (!validate_and_escape_label (&label, 12))
 
192
                {
 
193
                  g_string_free (s, TRUE);
 
194
                  goto out;
 
195
                }
 
196
              g_string_append_printf (s, " -L \"%s\"", label);
 
197
              g_free (label);
 
198
              label = NULL;
 
199
            }
 
200
          else if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
201
            {
 
202
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
203
              if (endp == NULL || *endp != '\0')
 
204
                {
 
205
                  g_printerr ("option %s is malformed\n", options[n]);
 
206
                  goto out;
 
207
                }
 
208
            }
 
209
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
210
            {
 
211
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
212
              if (endp == NULL || *endp != '\0')
 
213
                {
 
214
                  g_printerr ("option %s is malformed\n", options[n]);
 
215
                  goto out;
 
216
                }
 
217
            }
 
218
          else
 
219
            {
 
220
              g_printerr ("option %s not supported\n", options[n]);
 
221
              goto out;
 
222
            }
 
223
        }
 
224
      g_string_append_printf (s, " %s", device);
 
225
      command_line = g_string_free (s, FALSE);
 
226
 
 
227
    }
 
228
  else if (strcmp (fstype, "xfs") == 0)
 
229
    {
 
230
 
 
231
      s = g_string_new ("mkfs.xfs");
 
232
      for (n = 0; options[n] != NULL; n++)
 
233
        {
 
234
          if (g_str_has_prefix (options[n], "label="))
 
235
            {
 
236
              label = strdup (options[n] + sizeof("label=") - 1);
 
237
              if (!validate_and_escape_label (&label, 12))
 
238
                {
 
239
                  g_string_free (s, TRUE);
 
240
                  goto out;
 
241
                }
 
242
              g_string_append_printf (s, " -L \"%s\"", label);
 
243
              g_free (label);
 
244
              label = NULL;
 
245
            }
 
246
          else if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
247
            {
 
248
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
249
              if (endp == NULL || *endp != '\0')
 
250
                {
 
251
                  g_printerr ("option %s is malformed\n", options[n]);
 
252
                  goto out;
 
253
                }
 
254
            }
 
255
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
256
            {
 
257
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
258
              if (endp == NULL || *endp != '\0')
 
259
                {
 
260
                  g_printerr ("option %s is malformed\n", options[n]);
 
261
                  goto out;
 
262
                }
 
263
            }
 
264
          else
 
265
            {
 
266
              g_printerr ("option %s not supported\n", options[n]);
 
267
              goto out;
 
268
            }
 
269
        }
 
270
      g_string_append_printf (s, " %s", device);
 
271
      command_line = g_string_free (s, FALSE);
 
272
 
 
273
    }
 
274
  else if (strcmp (fstype, "ntfs") == 0)
 
275
    {
 
276
 
 
277
      /* skip zeroing (we do that ourselves) and bad sector checking (will 
 
278
       * eventually be handled on a higher level)
 
279
       */
 
280
      s = g_string_new ("mkntfs -f -F");
 
281
      for (n = 0; options[n] != NULL; n++)
 
282
        {
 
283
          if (g_str_has_prefix (options[n], "label="))
 
284
            {
 
285
              label = strdup (options[n] + sizeof("label=") - 1);
 
286
              if (!validate_and_escape_label (&label, 255))
 
287
                {
 
288
                  g_string_free (s, TRUE);
 
289
                  goto out;
 
290
                }
 
291
              g_string_append_printf (s, " -L \"%s\"", label);
 
292
              g_free (label);
 
293
              label = NULL;
 
294
            }
 
295
          else
 
296
            {
 
297
              g_printerr ("option %s not supported\n", options[n]);
 
298
              goto out;
 
299
            }
 
300
        }
 
301
      g_string_append_printf (s, " %s", device);
 
302
      command_line = g_string_free (s, FALSE);
 
303
 
 
304
    }
 
305
  else if (strcmp (fstype, "reiserfs") == 0)
 
306
    {
 
307
 
 
308
      s = g_string_new ("mkfs.reiserfs -q");
 
309
      for (n = 0; options[n] != NULL; n++)
 
310
        {
 
311
          if (g_str_has_prefix (options[n], "label="))
 
312
            {
 
313
              label = strdup (options[n] + sizeof("label=") - 1);
 
314
              if (!validate_and_escape_label (&label, 16))
 
315
                {
 
316
                  g_string_free (s, TRUE);
 
317
                  goto out;
 
318
                }
 
319
              g_string_append_printf (s, " -l \"%s\"", label);
 
320
              g_free (label);
 
321
              label = NULL;
 
322
            }
 
323
          else if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
324
            {
 
325
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
326
              if (endp == NULL || *endp != '\0')
 
327
                {
 
328
                  g_printerr ("option %s is malformed\n", options[n]);
 
329
                  goto out;
 
330
                }
 
331
            }
 
332
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
333
            {
 
334
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
335
              if (endp == NULL || *endp != '\0')
 
336
                {
 
337
                  g_printerr ("option %s is malformed\n", options[n]);
 
338
                  goto out;
 
339
                }
 
340
            }
 
341
          else
 
342
            {
 
343
              g_printerr ("option %s not supported\n", options[n]);
 
344
              goto out;
 
345
            }
 
346
        }
 
347
      g_string_append_printf (s, " %s", device);
 
348
      command_line = g_string_free (s, FALSE);
 
349
 
 
350
    }
 
351
  else if (strcmp (fstype, "minix") == 0)
 
352
    {
 
353
 
 
354
      s = g_string_new ("mkfs.minix");
 
355
      /* minix does not support labels */
 
356
      for (n = 0; options[n] != NULL; n++)
 
357
        {
 
358
          if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
359
            {
 
360
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
361
              if (endp == NULL || *endp != '\0')
 
362
                {
 
363
                  g_printerr ("option %s is malformed\n", options[n]);
 
364
                  goto out;
 
365
                }
 
366
            }
 
367
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
368
            {
 
369
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
370
              if (endp == NULL || *endp != '\0')
 
371
                {
 
372
                  g_printerr ("option %s is malformed\n", options[n]);
 
373
                  goto out;
 
374
                }
 
375
            }
 
376
          else
 
377
            {
 
378
              g_printerr ("option %s not supported\n", options[n]);
 
379
              goto out;
 
380
            }
 
381
        }
 
382
      g_string_append_printf (s, " %s", device);
 
383
      command_line = g_string_free (s, FALSE);
 
384
 
 
385
    }
 
386
  else if (strcmp (fstype, "nilfs2") == 0)
 
387
    {
 
388
 
 
389
      s = g_string_new ("mkfs.nilfs2");
 
390
      for (n = 0; options[n] != NULL; n++)
 
391
        {
 
392
          if (g_str_has_prefix (options[n], "label="))
 
393
            {
 
394
              label = strdup (options[n] + sizeof("label=") - 1);
 
395
              if (!validate_and_escape_label (&label, 80))
 
396
                {
 
397
                  g_string_free (s, TRUE);
 
398
                  goto out;
 
399
                }
 
400
              g_string_append_printf (s, " -L \"%s\"", label);
 
401
              g_free (label);
 
402
              label = NULL;
 
403
            }
 
404
          else if (g_str_has_prefix (options[n], "take_ownership_uid="))
 
405
            {
 
406
              take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
 
407
              if (endp == NULL || *endp != '\0')
 
408
                {
 
409
                  g_printerr ("option %s is malformed\n", options[n]);
 
410
                  goto out;
 
411
                }
 
412
            }
 
413
          else if (g_str_has_prefix (options[n], "take_ownership_gid="))
 
414
            {
 
415
              take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
 
416
              if (endp == NULL || *endp != '\0')
 
417
                {
 
418
                  g_printerr ("option %s is malformed\n", options[n]);
 
419
                  goto out;
 
420
                }
 
421
            }
 
422
          else
 
423
            {
 
424
              g_printerr ("option %s not supported\n", options[n]);
 
425
              goto out;
 
426
            }
 
427
        }
 
428
      g_string_append_printf (s, " %s", device);
 
429
      command_line = g_string_free (s, FALSE);
 
430
    }
 
431
  else if (strcmp (fstype, "swap") == 0)
 
432
    {
 
433
 
 
434
      s = g_string_new ("mkswap");
 
435
      for (n = 0; options[n] != NULL; n++)
 
436
        {
 
437
          if (g_str_has_prefix (options[n], "label="))
 
438
            {
 
439
              label = strdup (options[n] + sizeof("label=") - 1);
 
440
              if (!validate_and_escape_label (&label, 15))
 
441
                {
 
442
                  g_string_free (s, TRUE);
 
443
                  goto out;
 
444
                }
 
445
              g_string_append_printf (s, " -L \"%s\"", label);
 
446
              g_free (label);
 
447
              label = NULL;
 
448
            }
 
449
          else
 
450
            {
 
451
              g_printerr ("option %s not supported\n", options[n]);
 
452
              goto out;
 
453
            }
 
454
        }
 
455
      g_string_append_printf (s, " %s", device);
 
456
      command_line = g_string_free (s, FALSE);
 
457
 
 
458
    }
 
459
  else if (strcmp (fstype, "empty") == 0)
 
460
    {
 
461
      command_line = NULL;
 
462
      for (n = 0; options[n] != NULL; n++)
 
463
        {
 
464
          g_printerr ("option %s not supported\n", options[n]);
 
465
          goto out;
 
466
        }
 
467
    }
 
468
  else
 
469
    {
 
470
      g_printerr ("fstype %s not supported\n", fstype);
 
471
      goto out;
 
472
    }
 
473
 
 
474
  /* scrub signatures */
 
475
  if (!scrub_signatures (device, 0, 0))
 
476
    goto out;
 
477
 
 
478
  if (command_line != NULL)
 
479
    {
 
480
      error = NULL;
 
481
      if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
 
482
        {
 
483
          g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
 
484
          ret = 3; /* indicate FilesystemToolsMissing error */
 
485
          g_error_free (error);
 
486
          goto out;
 
487
        }
 
488
      if (WEXITSTATUS (exit_status) != 0)
 
489
        {
 
490
          g_printerr ("helper failed with:\n%s", standard_error);
 
491
          goto out;
 
492
        }
 
493
    }
 
494
 
 
495
  if (label != NULL)
 
496
    {
 
497
      g_free (command_line);
 
498
 
 
499
      if (strcmp (fstype, "vfat") == 0)
 
500
        {
 
501
          command_line = g_strdup_printf ("mlabel -i %s \"::%s\"", device, label);
 
502
        }
 
503
      else
 
504
        {
 
505
          g_printerr ("label change for fstype '%s' requested but not implemented", fstype);
 
506
          goto out;
 
507
        }
 
508
 
 
509
      error = NULL;
 
510
      if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
 
511
        {
 
512
          g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
 
513
          g_error_free (error);
 
514
          ret = 3; /* indicate FilesystemToolsMissing error */
 
515
          goto out;
 
516
        }
 
517
      if (WEXITSTATUS (exit_status) != 0)
 
518
        {
 
519
          g_printerr ("helper failed with:\n%s", standard_error);
 
520
          goto out;
 
521
        }
 
522
 
 
523
      g_free (label);
 
524
    }
 
525
 
 
526
  /* If we've created an fs on a partitioned device, then signal the
 
527
   * kernel to reread the (now missing) partition table.
 
528
   */
 
529
  if (is_kernel_partitioned)
 
530
    {
 
531
      fd = open (device, O_RDONLY);
 
532
      if (fd < 0)
 
533
        {
 
534
          g_printerr ("cannot open %s (for BLKRRPART): %m\n", device);
 
535
          goto out;
 
536
        }
 
537
      if (ioctl (fd, BLKRRPART) != 0)
 
538
        {
 
539
          close (fd);
 
540
          g_printerr ("BLKRRPART ioctl failed for %s: %m\n", device);
 
541
          goto out;
 
542
        }
 
543
      close (fd);
 
544
    }
 
545
 
 
546
  /* take ownership of the device if requested */
 
547
  if (take_ownership_uid != 0 || take_ownership_gid != 0)
 
548
    {
 
549
      char dir[256] = PACKAGE_LOCALSTATE_DIR "/run/udisks/job-mkfs-XXXXXX";
 
550
 
 
551
      if (mkdtemp (dir) == NULL)
 
552
        {
 
553
          g_printerr ("cannot create directory %s: %m\n", dir);
 
554
          goto out;
 
555
        }
 
556
 
 
557
      if (mount (device, dir, fstype, 0, NULL) != 0)
 
558
        {
 
559
          g_printerr ("cannot mount %s at %s: %m\n", device, dir);
 
560
          ret = 2;
 
561
          goto tos_err0;
 
562
        }
 
563
 
 
564
      if (chown (dir, take_ownership_uid, take_ownership_gid) != 0)
 
565
        {
 
566
          g_printerr ("cannot chown %s to uid=%d and gid=%d: %m\n", dir, take_ownership_uid, take_ownership_gid);
 
567
          ret = 2;
 
568
        }
 
569
 
 
570
      if (chmod (dir, 0700) != 0)
 
571
        {
 
572
          g_printerr ("cannot chmod %s to mode 0700: %m\n", dir);
 
573
          ret = 2;
 
574
        }
 
575
 
 
576
      if (umount (dir) != 0)
 
577
        {
 
578
          g_printerr ("cannot unmount %s: %m\n", dir);
 
579
          ret = 2;
 
580
          goto tos_err0;
 
581
        }
 
582
 
 
583
    tos_err0:
 
584
      if (rmdir (dir) != 0)
 
585
        {
 
586
          g_printerr ("cannot remove directory %s: %m\n", dir);
 
587
          goto out;
 
588
        }
 
589
    }
 
590
 
 
591
  if (ret == 2)
 
592
    ret = 1;
 
593
  else
 
594
    ret = 0;
 
595
 
 
596
 out:
 
597
  g_free (standard_error);
 
598
  g_free (command_line);
 
599
  return ret;
 
600
}