1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
3
* Copyright (C) 2008 David Zeuthen <david@fubar.dk>
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.
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, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
#define _LARGEFILE64_SOURCE
33
#include <sys/types.h>
37
#include <sys/mount.h>
41
#include "job-shared.h"
59
gboolean is_kernel_partitioned;
60
GIOChannel *stdin_channel;
61
GPtrArray *options_array;
65
uid_t take_ownership_uid;
66
gid_t take_ownership_gid;
70
standard_error = NULL;
71
take_ownership_uid = 0;
72
take_ownership_gid = 0;
77
g_printerr ("wrong usage\n");
82
is_kernel_partitioned = (strcmp (argv[3], "1") == 0);
84
options_array = g_ptr_array_new ();
85
stdin_channel = g_io_channel_unix_new (0);
86
if (stdin_channel == NULL)
88
g_printerr ("cannot open stdin\n");
91
while (g_io_channel_read_line (stdin_channel, &option, &option_len, NULL, NULL) == G_IO_STATUS_NORMAL)
93
option[option_len - 1] = '\0';
94
if (strlen (option) == 0)
96
g_ptr_array_add (options_array, option);
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);
102
if (strcmp (fstype, "vfat") == 0)
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++)
109
if (g_str_has_prefix (options[n], "label="))
111
label = strdup (options[n] + sizeof("label=") - 1);
112
if (!validate_and_escape_label (&label, 254))
114
g_string_free (s, TRUE);
117
if (strlen (label) <= 11)
119
g_string_append_printf (s, " -n \"%s\"", label);
126
g_printerr ("option %s not supported\n", options[n]);
130
g_string_append_printf (s, " %s", device);
131
command_line = g_string_free (s, FALSE);
134
else if (strcmp (fstype, "ext2") == 0 || strcmp (fstype, "ext3") == 0 || strcmp (fstype, "ext4") == 0)
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++)
142
if (g_str_has_prefix (options[n], "label="))
144
label = strdup (options[n] + sizeof("label=") - 1);
145
if (!validate_and_escape_label (&label, 16))
147
g_string_free (s, TRUE);
150
g_string_append_printf (s, " -L \"%s\"", label);
154
else if (g_str_has_prefix (options[n], "take_ownership_uid="))
156
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
157
if (endp == NULL || *endp != '\0')
159
g_printerr ("option %s is malformed\n", options[n]);
163
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
165
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
166
if (endp == NULL || *endp != '\0')
168
g_printerr ("option %s is malformed\n", options[n]);
174
g_printerr ("option %s not supported\n", options[n]);
178
g_string_append_printf (s, " %s", device);
179
command_line = g_string_free (s, FALSE);
182
else if (strcmp (fstype, "btrfs") == 0)
185
s = g_string_new ("mkfs.btrfs");
186
for (n = 0; options[n] != NULL; n++)
188
if (g_str_has_prefix (options[n], "label="))
190
label = strdup (options[n] + sizeof("label=") - 1);
191
if (!validate_and_escape_label (&label, 12))
193
g_string_free (s, TRUE);
196
g_string_append_printf (s, " -L \"%s\"", label);
200
else if (g_str_has_prefix (options[n], "take_ownership_uid="))
202
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
203
if (endp == NULL || *endp != '\0')
205
g_printerr ("option %s is malformed\n", options[n]);
209
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
211
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
212
if (endp == NULL || *endp != '\0')
214
g_printerr ("option %s is malformed\n", options[n]);
220
g_printerr ("option %s not supported\n", options[n]);
224
g_string_append_printf (s, " %s", device);
225
command_line = g_string_free (s, FALSE);
228
else if (strcmp (fstype, "xfs") == 0)
231
s = g_string_new ("mkfs.xfs");
232
for (n = 0; options[n] != NULL; n++)
234
if (g_str_has_prefix (options[n], "label="))
236
label = strdup (options[n] + sizeof("label=") - 1);
237
if (!validate_and_escape_label (&label, 12))
239
g_string_free (s, TRUE);
242
g_string_append_printf (s, " -L \"%s\"", label);
246
else if (g_str_has_prefix (options[n], "take_ownership_uid="))
248
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
249
if (endp == NULL || *endp != '\0')
251
g_printerr ("option %s is malformed\n", options[n]);
255
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
257
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
258
if (endp == NULL || *endp != '\0')
260
g_printerr ("option %s is malformed\n", options[n]);
266
g_printerr ("option %s not supported\n", options[n]);
270
g_string_append_printf (s, " %s", device);
271
command_line = g_string_free (s, FALSE);
274
else if (strcmp (fstype, "ntfs") == 0)
277
/* skip zeroing (we do that ourselves) and bad sector checking (will
278
* eventually be handled on a higher level)
280
s = g_string_new ("mkntfs -f -F");
281
for (n = 0; options[n] != NULL; n++)
283
if (g_str_has_prefix (options[n], "label="))
285
label = strdup (options[n] + sizeof("label=") - 1);
286
if (!validate_and_escape_label (&label, 255))
288
g_string_free (s, TRUE);
291
g_string_append_printf (s, " -L \"%s\"", label);
297
g_printerr ("option %s not supported\n", options[n]);
301
g_string_append_printf (s, " %s", device);
302
command_line = g_string_free (s, FALSE);
305
else if (strcmp (fstype, "reiserfs") == 0)
308
s = g_string_new ("mkfs.reiserfs -q");
309
for (n = 0; options[n] != NULL; n++)
311
if (g_str_has_prefix (options[n], "label="))
313
label = strdup (options[n] + sizeof("label=") - 1);
314
if (!validate_and_escape_label (&label, 16))
316
g_string_free (s, TRUE);
319
g_string_append_printf (s, " -l \"%s\"", label);
323
else if (g_str_has_prefix (options[n], "take_ownership_uid="))
325
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
326
if (endp == NULL || *endp != '\0')
328
g_printerr ("option %s is malformed\n", options[n]);
332
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
334
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
335
if (endp == NULL || *endp != '\0')
337
g_printerr ("option %s is malformed\n", options[n]);
343
g_printerr ("option %s not supported\n", options[n]);
347
g_string_append_printf (s, " %s", device);
348
command_line = g_string_free (s, FALSE);
351
else if (strcmp (fstype, "minix") == 0)
354
s = g_string_new ("mkfs.minix");
355
/* minix does not support labels */
356
for (n = 0; options[n] != NULL; n++)
358
if (g_str_has_prefix (options[n], "take_ownership_uid="))
360
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
361
if (endp == NULL || *endp != '\0')
363
g_printerr ("option %s is malformed\n", options[n]);
367
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
369
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
370
if (endp == NULL || *endp != '\0')
372
g_printerr ("option %s is malformed\n", options[n]);
378
g_printerr ("option %s not supported\n", options[n]);
382
g_string_append_printf (s, " %s", device);
383
command_line = g_string_free (s, FALSE);
386
else if (strcmp (fstype, "nilfs2") == 0)
389
s = g_string_new ("mkfs.nilfs2");
390
for (n = 0; options[n] != NULL; n++)
392
if (g_str_has_prefix (options[n], "label="))
394
label = strdup (options[n] + sizeof("label=") - 1);
395
if (!validate_and_escape_label (&label, 80))
397
g_string_free (s, TRUE);
400
g_string_append_printf (s, " -L \"%s\"", label);
404
else if (g_str_has_prefix (options[n], "take_ownership_uid="))
406
take_ownership_uid = strtol (options[n] + sizeof("take_ownership_uid=") - 1, &endp, 10);
407
if (endp == NULL || *endp != '\0')
409
g_printerr ("option %s is malformed\n", options[n]);
413
else if (g_str_has_prefix (options[n], "take_ownership_gid="))
415
take_ownership_gid = strtol (options[n] + sizeof("take_ownership_gid=") - 1, &endp, 10);
416
if (endp == NULL || *endp != '\0')
418
g_printerr ("option %s is malformed\n", options[n]);
424
g_printerr ("option %s not supported\n", options[n]);
428
g_string_append_printf (s, " %s", device);
429
command_line = g_string_free (s, FALSE);
431
else if (strcmp (fstype, "swap") == 0)
434
s = g_string_new ("mkswap");
435
for (n = 0; options[n] != NULL; n++)
437
if (g_str_has_prefix (options[n], "label="))
439
label = strdup (options[n] + sizeof("label=") - 1);
440
if (!validate_and_escape_label (&label, 15))
442
g_string_free (s, TRUE);
445
g_string_append_printf (s, " -L \"%s\"", label);
451
g_printerr ("option %s not supported\n", options[n]);
455
g_string_append_printf (s, " %s", device);
456
command_line = g_string_free (s, FALSE);
459
else if (strcmp (fstype, "empty") == 0)
462
for (n = 0; options[n] != NULL; n++)
464
g_printerr ("option %s not supported\n", options[n]);
470
g_printerr ("fstype %s not supported\n", fstype);
474
/* scrub signatures */
475
if (!scrub_signatures (device, 0, 0))
478
if (command_line != NULL)
481
if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
483
g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
484
ret = 3; /* indicate FilesystemToolsMissing error */
485
g_error_free (error);
488
if (WEXITSTATUS (exit_status) != 0)
490
g_printerr ("helper failed with:\n%s", standard_error);
497
g_free (command_line);
499
if (strcmp (fstype, "vfat") == 0)
501
command_line = g_strdup_printf ("mlabel -i %s \"::%s\"", device, label);
505
g_printerr ("label change for fstype '%s' requested but not implemented", fstype);
510
if (!g_spawn_command_line_sync (command_line, NULL, &standard_error, &exit_status, &error))
512
g_printerr ("cannot spawn '%s': %s\n", command_line, error->message);
513
g_error_free (error);
514
ret = 3; /* indicate FilesystemToolsMissing error */
517
if (WEXITSTATUS (exit_status) != 0)
519
g_printerr ("helper failed with:\n%s", standard_error);
526
/* If we've created an fs on a partitioned device, then signal the
527
* kernel to reread the (now missing) partition table.
529
if (is_kernel_partitioned)
531
fd = open (device, O_RDONLY);
534
g_printerr ("cannot open %s (for BLKRRPART): %m\n", device);
537
if (ioctl (fd, BLKRRPART) != 0)
540
g_printerr ("BLKRRPART ioctl failed for %s: %m\n", device);
546
/* take ownership of the device if requested */
547
if (take_ownership_uid != 0 || take_ownership_gid != 0)
549
char dir[256] = PACKAGE_LOCALSTATE_DIR "/run/udisks/job-mkfs-XXXXXX";
551
if (mkdtemp (dir) == NULL)
553
g_printerr ("cannot create directory %s: %m\n", dir);
557
if (mount (device, dir, fstype, 0, NULL) != 0)
559
g_printerr ("cannot mount %s at %s: %m\n", device, dir);
564
if (chown (dir, take_ownership_uid, take_ownership_gid) != 0)
566
g_printerr ("cannot chown %s to uid=%d and gid=%d: %m\n", dir, take_ownership_uid, take_ownership_gid);
570
if (chmod (dir, 0700) != 0)
572
g_printerr ("cannot chmod %s to mode 0700: %m\n", dir);
576
if (umount (dir) != 0)
578
g_printerr ("cannot unmount %s: %m\n", dir);
584
if (rmdir (dir) != 0)
586
g_printerr ("cannot remove directory %s: %m\n", dir);
597
g_free (standard_error);
598
g_free (command_line);