~ubuntu-branches/ubuntu/precise/util-linux/precise

« back to all changes in this revision

Viewing changes to misc-utils/uuidd.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2011-12-16 22:53:42 UTC
  • mfrom: (1.6.4) (4.5.5 sid)
  • Revision ID: package-import@ubuntu.com-20111216225342-206wz4bhvutyvx0d
Tags: 2.20.1-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
  - Use canonicalize_spec in getmntdevbackward. proc should not be
    interpreted as a non-canonical-path.
* Dropped changes, superseded upstream:
  - shlibs/mount/src/tab_update.c: don't refuse to update mtab when source
    is 'none'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include <unistd.h>
16
16
#include <inttypes.h>
17
17
#include <errno.h>
 
18
#include <err.h>
18
19
#include <sys/types.h>
19
20
#include <sys/stat.h>
20
21
#include <sys/socket.h>
48
49
/* length of binary representation of UUID */
49
50
#define UUID_LEN        (sizeof(uuid_t))
50
51
 
51
 
static void usage(const char *progname)
52
 
{
53
 
        fprintf(stderr, _("Usage: %s [-d] [-p pidfile] [-s socketpath] "
54
 
                          "[-T timeout]\n"), progname);
55
 
        fprintf(stderr, _("       %s [-r|t] [-n num] [-s socketpath]\n"),
56
 
                progname);
57
 
        fprintf(stderr, _("       %s -k\n"), progname);
58
 
        exit(1);
59
 
}
60
 
 
61
 
static void die(const char *msg)
62
 
{
63
 
        perror(msg);
64
 
        exit(1);
 
52
static void __attribute__ ((__noreturn__)) usage(FILE * out)
 
53
{
 
54
        fputs(_("\nUsage:\n"), out);
 
55
        fprintf(out,
 
56
              _(" %s [options]\n"), program_invocation_short_name);
 
57
 
 
58
        fputs(_("\nOptions:\n"), out);
 
59
        fputs(_(" -p, --pid <path>    path to pid file\n"
 
60
                " -s, --socket <path> path to socket\n"
 
61
                " -T, --timeout <sec> specify inactivity timeout\n"
 
62
                " -k, --kill          kill running daemon\n"
 
63
                " -r, --random        test random-based generation\n"
 
64
                " -t, --time          test time-based generation\n"
 
65
                " -n, --uuids <num>   request number of uuids\n"
 
66
                " -d, --debug         run in debugging mode\n"
 
67
                " -q, --quiet         turn on quiet mode\n"
 
68
                " -V, --version       output version information and exit\n"
 
69
                " -h, --help          display this help and exit\n\n"), out);
 
70
 
 
71
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
65
72
}
66
73
 
67
74
static void create_daemon(void)
68
75
{
69
76
        uid_t euid;
70
77
 
71
 
        if (daemon(0,0))
72
 
                die("daemon");
 
78
        if (daemon(0, 0))
 
79
                err(EXIT_FAILURE, "daemon");
73
80
 
74
81
        euid = geteuid();
75
82
        if (setreuid(euid, euid) < 0)
76
 
                die("setreuid");
 
83
                err(EXIT_FAILURE, "setreuid");
77
84
}
78
85
 
79
86
static ssize_t read_all(int fd, char *buf, size_t count)
104
111
 
105
112
static void terminate_intr(int signo CODE_ATTR((unused)))
106
113
{
107
 
        (void) unlink(cleanup_pidfile);
 
114
        unlink(cleanup_pidfile);
108
115
        if (cleanup_socket)
109
 
                (void) unlink(cleanup_socket);
110
 
        exit(0);
 
116
                unlink(cleanup_socket);
 
117
        exit(EXIT_SUCCESS);
111
118
}
112
119
 
113
120
static int call_daemon(const char *socket_path, int op, char *buf,
114
 
                       int buflen, int *num, const char **err_context)
 
121
                       size_t buflen, int *num, const char **err_context)
115
122
{
116
123
        char op_buf[8];
117
124
        int op_len;
136
143
 
137
144
        srv_addr.sun_family = AF_UNIX;
138
145
        strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
139
 
        srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';
 
146
        srv_addr.sun_path[sizeof(srv_addr.sun_path) - 1] = '\0';
140
147
 
141
148
        if (connect(s, (const struct sockaddr *) &srv_addr,
142
149
                    sizeof(struct sockaddr_un)) < 0) {
147
154
        }
148
155
 
149
156
        if (op == UUIDD_OP_BULK_RANDOM_UUID) {
150
 
                if ((*num)*UUID_LEN > buflen-4)
151
 
                        *num = (buflen-4) / UUID_LEN;
 
157
                if ((*num) * UUID_LEN > buflen - 4)
 
158
                        *num = (buflen - 4) / UUID_LEN;
152
159
        }
153
160
        op_buf[0] = op;
154
161
        op_len = 1;
155
162
        if ((op == UUIDD_OP_BULK_TIME_UUID) ||
156
163
            (op == UUIDD_OP_BULK_RANDOM_UUID)) {
157
 
                memcpy(op_buf+1, num, sizeof(int));
 
164
                memcpy(op_buf + 1, num, sizeof(int));
158
165
                op_len += sizeof(int);
159
166
        }
160
167
 
173
180
                close(s);
174
181
                return -1;
175
182
        }
176
 
        if (reply_len < 0 || reply_len > buflen) {
 
183
        if (reply_len < 0 || (size_t) reply_len > buflen) {
177
184
                if (err_context)
178
185
                        *err_context = _("bad response length");
179
186
                close(s);
218
225
                if (!quiet)
219
226
                        fprintf(stderr, _("Failed to open/create %s: %s\n"),
220
227
                                pidfile_path, strerror(errno));
221
 
                exit(1);
 
228
                exit(EXIT_FAILURE);
222
229
        }
223
230
        cleanup_pidfile = pidfile_path;
224
231
        cleanup_socket = 0;
235
242
                if (!quiet)
236
243
                        fprintf(stderr, _("Failed to lock %s: %s\n"),
237
244
                                pidfile_path, strerror(errno));
238
 
                exit(1);
 
245
                exit(EXIT_FAILURE);
239
246
        }
240
247
        ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
241
248
        if (ret > 0) {
242
249
                if (!quiet)
243
250
                        printf(_("uuidd daemon already running at pid %s\n"),
244
251
                               reply_buf);
245
 
                exit(1);
 
252
                exit(EXIT_FAILURE);
246
253
        }
247
254
        alarm(0);
248
255
 
250
257
                if (!quiet)
251
258
                        fprintf(stderr, _("Couldn't create unix stream "
252
259
                                          "socket: %s"), strerror(errno));
253
 
                exit(1);
 
260
                exit(EXIT_FAILURE);
254
261
        }
255
262
 
256
263
        /*
260
267
        while (!debug && s <= 2) {
261
268
                s = dup(s);
262
269
                if (s < 0)
263
 
                        die("dup");
 
270
                        err(EXIT_FAILURE, "dup");
264
271
        }
265
272
 
266
273
        /*
268
275
         */
269
276
        my_addr.sun_family = AF_UNIX;
270
277
        strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
271
 
        my_addr.sun_path[sizeof(my_addr.sun_path)-1] = '\0';
272
 
        (void) unlink(socket_path);
 
278
        my_addr.sun_path[sizeof(my_addr.sun_path) - 1] = '\0';
 
279
        unlink(socket_path);
273
280
        save_umask = umask(0);
274
281
        if (bind(s, (const struct sockaddr *) &my_addr,
275
282
                 sizeof(struct sockaddr_un)) < 0) {
277
284
                        fprintf(stderr,
278
285
                                _("Couldn't bind unix socket %s: %s\n"),
279
286
                                socket_path, strerror(errno));
280
 
                exit(1);
 
287
                exit(EXIT_FAILURE);
281
288
        }
282
 
        (void) umask(save_umask);
 
289
        umask(save_umask);
283
290
 
284
291
        if (listen(s, SOMAXCONN) < 0) {
285
292
                if (!quiet)
286
293
                        fprintf(stderr, _("Couldn't listen on unix "
287
294
                                          "socket %s: %s\n"), socket_path,
288
295
                                strerror(errno));
289
 
                exit(1);
 
296
                exit(EXIT_FAILURE);
290
297
        }
291
298
 
292
299
        cleanup_socket = socket_path;
299
306
        signal(SIGPIPE, SIG_IGN);
300
307
 
301
308
        sprintf(reply_buf, "%8d\n", getpid());
302
 
        if (ftruncate(fd_pidfile, 0)) {} /* Silence warn_unused_result */
 
309
        if (ftruncate(fd_pidfile, 0)) {
 
310
                /* Silence warn_unused_result */
 
311
        }
303
312
        write_all(fd_pidfile, reply_buf, strlen(reply_buf));
304
313
        if (fd_pidfile > 1)
305
314
                close(fd_pidfile); /* Unlock the pid file */
314
323
                        if ((errno == EAGAIN) || (errno == EINTR))
315
324
                                continue;
316
325
                        else
317
 
                                die("accept");
 
326
                                err(EXIT_FAILURE, "accept");
318
327
                }
319
328
                len = read(ns, &op, 1);
320
329
                if (len != 1) {
335
344
                } else if (debug)
336
345
                        printf(_("operation %d\n"), op);
337
346
 
338
 
                switch(op) {
 
347
                switch (op) {
339
348
                case UUIDD_OP_GETPID:
340
349
                        sprintf(reply_buf, "%d", getpid());
341
 
                        reply_len = strlen(reply_buf)+1;
 
350
                        reply_len = strlen(reply_buf) + 1;
342
351
                        break;
343
352
                case UUIDD_OP_GET_MAXOP:
344
353
                        sprintf(reply_buf, "%d", UUIDD_MAX_OP);
345
 
                        reply_len = strlen(reply_buf)+1;
 
354
                        reply_len = strlen(reply_buf) + 1;
346
355
                        break;
347
356
                case UUIDD_OP_TIME_UUID:
348
357
                        num = 1;
349
 
                        uuid__generate_time(uu, &num);
 
358
                        __uuid_generate_time(uu, &num);
350
359
                        if (debug) {
351
360
                                uuid_unparse(uu, str);
352
361
                                printf(_("Generated time UUID: %s\n"), str);
356
365
                        break;
357
366
                case UUIDD_OP_RANDOM_UUID:
358
367
                        num = 1;
359
 
                        uuid__generate_random(uu, &num);
 
368
                        __uuid_generate_random(uu, &num);
360
369
                        if (debug) {
361
370
                                uuid_unparse(uu, str);
362
371
                                printf(_("Generated random UUID: %s\n"), str);
365
374
                        reply_len = sizeof(uu);
366
375
                        break;
367
376
                case UUIDD_OP_BULK_TIME_UUID:
368
 
                        uuid__generate_time(uu, &num);
 
377
                        __uuid_generate_time(uu, &num);
369
378
                        if (debug) {
370
379
                                uuid_unparse(uu, str);
371
 
                                printf(_("Generated time UUID %s and %d "
372
 
                                         "following\n"), str, num - 1);
 
380
                                printf(P_("Generated time UUID %s "
 
381
                                          "and %d following\n",
 
382
                                          "Generated time UUID %s "
 
383
                                          "and %d following\n", num - 1),
 
384
                                       str, num - 1);
373
385
                        }
374
386
                        memcpy(reply_buf, uu, sizeof(uu));
375
387
                        reply_len = sizeof(uu);
376
 
                        memcpy(reply_buf+reply_len, &num, sizeof(num));
 
388
                        memcpy(reply_buf + reply_len, &num, sizeof(num));
377
389
                        reply_len += sizeof(num);
378
390
                        break;
379
391
                case UUIDD_OP_BULK_RANDOM_UUID:
381
393
                                num = 1;
382
394
                        if (num > 1000)
383
395
                                num = 1000;
384
 
                        if (num * UUID_LEN > (int) (sizeof(reply_buf)-sizeof(num)))
385
 
                                num = (sizeof(reply_buf)-sizeof(num)) / UUID_LEN;
386
 
                        uuid__generate_random((unsigned char *) reply_buf +
 
396
                        if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
 
397
                                num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
 
398
                        __uuid_generate_random((unsigned char *) reply_buf +
387
399
                                              sizeof(num), &num);
388
400
                        if (debug) {
389
 
                                printf(_("Generated %d UUIDs:\n"), num);
390
 
                                for (i=0, cp=reply_buf+sizeof(num);
391
 
                                     i < num; i++, cp+=UUID_LEN) {
 
401
                                printf(P_("Generated %d UUID:\n",
 
402
                                          "Generated %d UUIDs:\n", num), num);
 
403
                                for (i = 0, cp = reply_buf + sizeof(num);
 
404
                                     i < num;
 
405
                                     i++, cp += UUID_LEN) {
392
406
                                        uuid_unparse((unsigned char *)cp, str);
393
407
                                        printf("\t%s\n", str);
394
408
                                }
408
422
        }
409
423
}
410
424
 
 
425
static void __attribute__ ((__noreturn__)) unexpected_size(int size)
 
426
{
 
427
        errx(EXIT_FAILURE, _("Unexpected reply length from server %d"), size);
 
428
}
 
429
 
411
430
int main(int argc, char **argv)
412
431
{
413
432
        const char      *socket_path = UUIDD_SOCKET_PATH;
422
441
        int             debug = 0, do_type = 0, do_kill = 0, num = 0;
423
442
        int             timeout = 0, quiet = 0, drop_privs = 0;
424
443
 
 
444
        static const struct option longopts[] = {
 
445
                {"pid", required_argument, NULL, 'p'},
 
446
                {"socket", required_argument, NULL, 's'},
 
447
                {"timeout", required_argument, NULL, 'T'},
 
448
                {"kill", no_argument, NULL, 'k'},
 
449
                {"random", no_argument, NULL, 'r'},
 
450
                {"time", no_argument, NULL, 't'},
 
451
                {"uuids", required_argument, NULL, 'n'},
 
452
                {"debug", no_argument, NULL, 'd'},
 
453
                {"quiet", no_argument, NULL, 'q'},
 
454
                {"version", no_argument, NULL, 'V'},
 
455
                {"help", no_argument, NULL, 'h'},
 
456
                {NULL, 0, NULL, 0}
 
457
        };
 
458
 
425
459
        setlocale(LC_ALL, "");
426
460
        bindtextdomain(PACKAGE, LOCALEDIR);
427
461
        textdomain(PACKAGE);
428
462
 
429
 
        while ((c = getopt (argc, argv, "dkn:qp:s:tT:r")) != EOF) {
 
463
        while ((c =
 
464
                getopt_long(argc, argv, "p:s:T:krtn:dqVh", longopts,
 
465
                            NULL)) != -1) {
430
466
                switch (c) {
431
467
                case 'd':
432
468
                        debug++;
440
476
                        num = strtol(optarg, &tmp, 0);
441
477
                        if ((num < 1) || *tmp) {
442
478
                                fprintf(stderr, _("Bad number: %s\n"), optarg);
443
 
                                exit(1);
 
479
                                return EXIT_FAILURE;
444
480
                        }
 
481
                        break;
445
482
                case 'p':
446
483
                        pidfile_path = optarg;
447
484
                        drop_privs = 1;
449
486
                case 'q':
450
487
                        quiet++;
451
488
                        break;
 
489
                case 'r':
 
490
                        do_type = UUIDD_OP_RANDOM_UUID;
 
491
                        drop_privs = 1;
 
492
                        break;
452
493
                case 's':
453
494
                        socket_path = optarg;
454
495
                        drop_privs = 1;
461
502
                        timeout = strtol(optarg, &tmp, 0);
462
503
                        if ((timeout < 0) || *tmp) {
463
504
                                fprintf(stderr, _("Bad number: %s\n"), optarg);
464
 
                                exit(1);
 
505
                                return EXIT_FAILURE;
465
506
                        }
466
507
                        break;
467
 
                case 'r':
468
 
                        do_type = UUIDD_OP_RANDOM_UUID;
469
 
                        drop_privs = 1;
470
 
                        break;
 
508
                case 'V':
 
509
                        printf(_("%s from %s\n"),
 
510
                               program_invocation_short_name,
 
511
                               PACKAGE_STRING);
 
512
                        return EXIT_SUCCESS;
 
513
                case 'h':
 
514
                        usage(stdout);
471
515
                default:
472
 
                        usage(argv[0]);
 
516
                        usage(stderr);
473
517
                }
474
518
        }
475
519
        uid = getuid();
477
521
                gid = getgid();
478
522
#ifdef HAVE_SETRESGID
479
523
                if (setresgid(gid, gid, gid) < 0)
480
 
                        die("setresgid");
 
524
                        err(EXIT_FAILURE, "setresgid");
481
525
#else
482
526
                if (setregid(gid, gid) < 0)
483
 
                        die("setregid");
 
527
                        err(EXIT_FAILURE, "setregid");
484
528
#endif
485
529
 
486
530
#ifdef HAVE_SETRESUID
487
531
                if (setresuid(uid, uid, uid) < 0)
488
 
                        die("setresuid");
 
532
                        err(EXIT_FAILURE, "setresuid");
489
533
#else
490
534
                if (setreuid(uid, uid) < 0)
491
 
                        die("setreuid");
 
535
                        err(EXIT_FAILURE, "setreuid");
492
536
#endif
493
537
        }
494
538
        if (num && do_type) {
495
 
                ret = call_daemon(socket_path, do_type+2, buf,
 
539
                ret = call_daemon(socket_path, do_type + 2, buf,
496
540
                                  sizeof(buf), &num, &err_context);
497
541
                if (ret < 0) {
498
542
                        printf(_("Error calling uuidd daemon (%s): %s\n"),
499
543
                               err_context, strerror(errno));
500
 
                        exit(1);
 
544
                        return EXIT_FAILURE;
501
545
                }
502
546
                if (do_type == UUIDD_OP_TIME_UUID) {
503
547
                        if (ret != sizeof(uu) + sizeof(num))
504
 
                                goto unexpected_size;
 
548
                                unexpected_size(ret);
505
549
 
506
550
                        uuid_unparse((unsigned char *) buf, str);
507
551
 
508
 
                        printf(_("%s and subsequent %d UUIDs\n"), str, num - 1);
 
552
                        printf(P_("%s and %d subsequent UUID\n",
 
553
                                  "%s and %d subsequent UUIDs\n", num - 1),
 
554
                               str, num - 1);
509
555
                } else {
510
556
                        printf(_("List of UUIDs:\n"));
511
557
                        cp = buf + 4;
512
 
                        if (ret != (int) (sizeof(num) + num*sizeof(uu)))
513
 
                                goto unexpected_size;
514
 
                        for (i=0; i < num; i++, cp+=UUID_LEN) {
 
558
                        if (ret != (int) (sizeof(num) + num * sizeof(uu)))
 
559
                                unexpected_size(ret);
 
560
                        for (i = 0; i < num; i++, cp += UUID_LEN) {
515
561
                                uuid_unparse((unsigned char *) cp, str);
516
562
                                printf("\t%s\n", str);
517
563
                        }
518
564
                }
519
 
                exit(0);
 
565
                return EXIT_SUCCESS;
520
566
        }
521
567
        if (do_type) {
522
568
                ret = call_daemon(socket_path, do_type, (char *) &uu,
524
570
                if (ret < 0) {
525
571
                        printf(_("Error calling uuidd daemon (%s): %s\n"),
526
572
                               err_context, strerror(errno));
527
 
                        exit(1);
528
 
                }
529
 
                if (ret != sizeof(uu)) {
530
 
                unexpected_size:
531
 
                        printf(_("Unexpected reply length from server %d\n"),
532
 
                               ret);
533
 
                        exit(1);
534
 
                }
 
573
                        return EXIT_FAILURE;
 
574
                }
 
575
                if (ret != sizeof(uu))
 
576
                        unexpected_size(ret);
 
577
 
535
578
                uuid_unparse(uu, str);
536
579
 
537
580
                printf("%s\n", str);
538
 
                exit(0);
 
581
                return EXIT_SUCCESS;
539
582
        }
540
583
 
541
584
        if (do_kill) {
548
591
                                                _("Couldn't kill uuidd running "
549
592
                                                  "at pid %d: %s\n"), do_kill,
550
593
                                                strerror(errno));
551
 
                                exit(1);
 
594
                                return EXIT_FAILURE;
552
595
                        }
553
596
                        if (!quiet)
554
597
                                printf(_("Killed uuidd running at pid %d\n"),
555
598
                                       do_kill);
556
599
                }
557
 
                exit(0);
 
600
                return EXIT_SUCCESS;
558
601
        }
559
602
 
560
603
        server_loop(socket_path, pidfile_path, debug, timeout, quiet);
561
 
        return 0;
 
604
        return EXIT_SUCCESS;
562
605
}