2 * uuidd.c --- UUID-generation daemon
4 * Copyright (C) 2007 Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
17 #include <sys/types.h>
19 #include <sys/socket.h>
25 #include <sys/signalfd.h>
32 #include "closestream.h"
35 #include "monotonic.h"
38 #ifdef HAVE_LIBSYSTEMD
39 # include <systemd/sd-daemon.h>
45 #define CODE_ATTR(x) __attribute__(x)
50 /* length of textual representation of UUID, including trailing \0 */
51 #define UUID_STR_LEN 37
53 /* length of binary representation of UUID */
54 #define UUID_LEN (sizeof(uuid_t))
56 /* server loop control structure */
58 const char *cleanup_pidfile
;
59 const char *cleanup_socket
;
61 unsigned int debug
: 1,
67 static void __attribute__ ((__noreturn__
)) usage(FILE * out
)
69 fputs(USAGE_HEADER
, out
);
70 fprintf(out
, _(" %s [options]\n"), program_invocation_short_name
);
71 fputs(USAGE_SEPARATOR
, out
);
72 fputs(_("A daemon for generating UUIDs.\n"), out
);
73 fputs(USAGE_OPTIONS
, out
);
74 fputs(_(" -p, --pid <path> path to pid file\n"), out
);
75 fputs(_(" -s, --socket <path> path to socket\n"), out
);
76 fputs(_(" -T, --timeout <sec> specify inactivity timeout\n"), out
);
77 fputs(_(" -k, --kill kill running daemon\n"), out
);
78 fputs(_(" -r, --random test random-based generation\n"), out
);
79 fputs(_(" -t, --time test time-based generation\n"), out
);
80 fputs(_(" -n, --uuids <num> request number of uuids\n"), out
);
81 fputs(_(" -P, --no-pid do not create pid file\n"), out
);
82 fputs(_(" -F, --no-fork do not daemonize using double-fork\n"), out
);
83 fputs(_(" -S, --socket-activation do not create listening socket\n"), out
);
84 fputs(_(" -d, --debug run in debugging mode\n"), out
);
85 fputs(_(" -q, --quiet turn on quiet mode\n"), out
);
86 fputs(USAGE_SEPARATOR
, out
);
87 fputs(USAGE_HELP
, out
);
88 fputs(USAGE_VERSION
, out
);
89 fprintf(out
, USAGE_MAN_TAIL("uuidd(8)"));
90 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
93 static void create_daemon(void)
98 err(EXIT_FAILURE
, "daemon");
101 if (setreuid(euid
, euid
) < 0)
102 err(EXIT_FAILURE
, "setreuid");
105 static int call_daemon(const char *socket_path
, int op
, char *buf
,
106 size_t buflen
, int *num
, const char **err_context
)
112 int32_t reply_len
= 0;
113 struct sockaddr_un srv_addr
;
115 if (((op
== UUIDD_OP_BULK_TIME_UUID
) ||
116 (op
== UUIDD_OP_BULK_RANDOM_UUID
)) && !num
) {
118 *err_context
= _("bad arguments");
123 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
125 *err_context
= _("socket");
129 srv_addr
.sun_family
= AF_UNIX
;
130 strncpy(srv_addr
.sun_path
, socket_path
, sizeof(srv_addr
.sun_path
));
131 srv_addr
.sun_path
[sizeof(srv_addr
.sun_path
) - 1] = '\0';
133 if (connect(s
, (const struct sockaddr
*) &srv_addr
,
134 sizeof(struct sockaddr_un
)) < 0) {
136 *err_context
= _("connect");
141 if (op
== UUIDD_OP_BULK_RANDOM_UUID
) {
142 if ((*num
) * UUID_LEN
> buflen
- 4)
143 *num
= (buflen
- 4) / UUID_LEN
;
147 if ((op
== UUIDD_OP_BULK_TIME_UUID
) ||
148 (op
== UUIDD_OP_BULK_RANDOM_UUID
)) {
149 memcpy(op_buf
+ 1, num
, sizeof(int));
150 op_len
+= sizeof(int);
153 ret
= write_all(s
, op_buf
, op_len
);
156 *err_context
= _("write");
161 ret
= read_all(s
, (char *) &reply_len
, sizeof(reply_len
));
164 *err_context
= _("read count");
168 if (reply_len
< 0 || (size_t) reply_len
> buflen
) {
170 *err_context
= _("bad response length");
174 ret
= read_all(s
, (char *) buf
, reply_len
);
176 if ((ret
> 0) && (op
== UUIDD_OP_BULK_TIME_UUID
)) {
177 if (reply_len
>= (int) (UUID_LEN
+ sizeof(int)))
178 memcpy(buf
+ UUID_LEN
, num
, sizeof(int));
182 if ((ret
> 0) && (op
== UUIDD_OP_BULK_RANDOM_UUID
)) {
183 if (reply_len
>= (int) sizeof(int))
184 memcpy(buf
, num
, sizeof(int));
195 * Exclusively create and open a pid file with path @pidfile_path
197 * Return file descriptor of the created pid_file.
199 static int create_pidfile(struct uuidd_cxt_t
*cxt
, const char *pidfile_path
)
204 fd_pidfile
= open(pidfile_path
, O_CREAT
| O_RDWR
, 0664);
205 if (fd_pidfile
< 0) {
207 warn(_("cannot open %s"), pidfile_path
);
210 cxt
->cleanup_pidfile
= pidfile_path
;
213 fl
.l_whence
= SEEK_SET
;
217 while (fcntl(fd_pidfile
, F_SETLKW
, &fl
) < 0) {
218 if ((errno
== EAGAIN
) || (errno
== EINTR
))
221 warn(_("cannot lock %s"), pidfile_path
);
229 * Create AF_UNIX, SOCK_STREAM socket and bind to @socket_path
231 * If @will_fork is true, then make sure the descriptor
232 * of the socket is >2, so that it won't be later closed
233 * during create_daemon().
235 * Return file descriptor corresponding to created socket.
237 static int create_socket(struct uuidd_cxt_t
*uuidd_cxt
,
238 const char *socket_path
, int will_fork
)
240 struct sockaddr_un my_addr
;
244 if ((s
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
245 if (!uuidd_cxt
->quiet
)
246 warn(_("couldn't create unix stream socket"));
251 * Make sure the socket isn't using fd numbers 0-2 to avoid it
252 * getting closed by create_daemon()
254 while (will_fork
&& s
<= 2) {
257 err(EXIT_FAILURE
, "dup");
261 * Create the address we will be binding to.
263 my_addr
.sun_family
= AF_UNIX
;
264 strncpy(my_addr
.sun_path
, socket_path
, sizeof(my_addr
.sun_path
));
265 my_addr
.sun_path
[sizeof(my_addr
.sun_path
) - 1] = '\0';
267 save_umask
= umask(0);
268 if (bind(s
, (const struct sockaddr
*) &my_addr
,
269 sizeof(struct sockaddr_un
)) < 0) {
270 if (!uuidd_cxt
->quiet
)
271 warn(_("couldn't bind unix socket %s"), socket_path
);
275 uuidd_cxt
->cleanup_socket
= socket_path
;
280 static void __attribute__((__noreturn__
)) all_done(const struct uuidd_cxt_t
*uuidd_cxt
, int ret
)
282 if (uuidd_cxt
->cleanup_pidfile
)
283 unlink(uuidd_cxt
->cleanup_pidfile
);
284 if (uuidd_cxt
->cleanup_socket
)
285 unlink(uuidd_cxt
->cleanup_socket
);
289 static void handle_signal(const struct uuidd_cxt_t
*uuidd_cxt
, int fd
)
291 struct signalfd_siginfo info
;
294 bytes
= read(fd
, &info
, sizeof(info
));
295 if (bytes
!= sizeof(info
)) {
298 warn(_("receiving signal failed"));
301 if (info
.ssi_signo
== SIGPIPE
)
302 return; /* ignored */
303 all_done(uuidd_cxt
, EXIT_SUCCESS
);
306 static void timeout_handler(int sig
__attribute__((__unused__
)),
308 void *context
__attribute__((__unused__
)))
310 if (info
->si_code
== SI_TIMER
)
311 errx(EXIT_FAILURE
, _("timed out"));
314 static void server_loop(const char *socket_path
, const char *pidfile_path
,
315 struct uuidd_cxt_t
*uuidd_cxt
)
317 struct sockaddr_un from_addr
;
319 int32_t reply_len
= 0;
321 char reply_buf
[1024], *cp
;
322 char op
, str
[UUID_STR_LEN
];
327 struct pollfd pfd
[2];
335 #ifdef HAVE_LIBSYSTEMD
336 if (!uuidd_cxt
->no_sock
) /* no_sock implies no_fork and no_pid */
340 struct itimerval timeout
;
342 memset(&timeout
, 0, sizeof timeout
);
343 timeout
.it_value
.tv_sec
= 30;
344 if (setup_timer(&t_id
, &timeout
, &timeout_handler
))
345 err(EXIT_FAILURE
, _("cannot set up timer"));
347 fd_pidfile
= create_pidfile(uuidd_cxt
, pidfile_path
);
348 ret
= call_daemon(socket_path
, UUIDD_OP_GETPID
, reply_buf
,
349 sizeof(reply_buf
), 0, NULL
);
352 if (!uuidd_cxt
->quiet
)
353 warnx(_("uuidd daemon is already running at pid %s"),
358 s
= create_socket(uuidd_cxt
, socket_path
,
359 (!uuidd_cxt
->debug
|| !uuidd_cxt
->no_fork
));
360 if (listen(s
, SOMAXCONN
) < 0) {
361 if (!uuidd_cxt
->quiet
)
362 warn(_("couldn't listen on unix socket %s"), socket_path
);
366 if (!uuidd_cxt
->debug
&& !uuidd_cxt
->no_fork
)
370 sprintf(reply_buf
, "%8d\n", getpid());
371 if (ftruncate(fd_pidfile
, 0))
372 err(EXIT_FAILURE
, _("could not truncate file: %s"), pidfile_path
);
373 write_all(fd_pidfile
, reply_buf
, strlen(reply_buf
));
375 if (close_fd(fd_pidfile
) != 0) /* Unlock the pid file */
376 err(EXIT_FAILURE
, _("write failed: %s"), pidfile_path
);
381 #ifdef HAVE_LIBSYSTEMD
382 if (uuidd_cxt
->no_sock
) {
383 const int r
= sd_listen_fds(0);
387 err(EXIT_FAILURE
, _("sd_listen_fds() failed"));
390 _("no file descriptors received, check systemctl status uuidd.socket"));
393 _("too many file descriptors received, check uuidd.socket"));
394 s
= SD_LISTEN_FDS_START
+ 0;
398 sigemptyset(&sigmask
);
399 sigaddset(&sigmask
, SIGHUP
);
400 sigaddset(&sigmask
, SIGINT
);
401 sigaddset(&sigmask
, SIGTERM
);
402 sigaddset(&sigmask
, SIGALRM
);
403 sigaddset(&sigmask
, SIGPIPE
);
404 /* Block signals so that they aren't handled according to their
405 * default dispositions */
406 sigprocmask(SIG_BLOCK
, &sigmask
, NULL
);
407 if ((sigfd
= signalfd(-1, &sigmask
, 0)) < 0)
408 err(EXIT_FAILURE
, _("cannot set signal handler"));
410 pfd
[POLLFD_SIGNAL
].fd
= sigfd
;
411 pfd
[POLLFD_SOCKET
].fd
= s
;
412 pfd
[POLLFD_SIGNAL
].events
= pfd
[POLLFD_SOCKET
].events
= POLLIN
| POLLERR
| POLLHUP
;
415 ret
= poll(pfd
, ARRAY_SIZE(pfd
),
417 (int) uuidd_cxt
->timeout
* 1000 : -1);
421 warn(_("poll failed"));
422 all_done(uuidd_cxt
, EXIT_FAILURE
);
424 if (ret
== 0) { /* truen when poll() times out */
425 if (uuidd_cxt
->debug
)
426 fprintf(stderr
, _("timeout [%d sec]\n"), uuidd_cxt
->timeout
),
427 all_done(uuidd_cxt
, EXIT_SUCCESS
);
429 if (pfd
[POLLFD_SIGNAL
].revents
!= 0)
430 handle_signal(uuidd_cxt
, sigfd
);
431 if (pfd
[POLLFD_SOCKET
].revents
== 0)
433 fromlen
= sizeof(from_addr
);
434 ns
= accept(s
, (struct sockaddr
*) &from_addr
, &fromlen
);
436 if ((errno
== EAGAIN
) || (errno
== EINTR
))
439 err(EXIT_FAILURE
, "accept");
441 len
= read(ns
, &op
, 1);
444 warn(_("read failed"));
446 warnx(_("error reading from client, len = %d"),
448 goto shutdown_socket
;
450 if ((op
== UUIDD_OP_BULK_TIME_UUID
) ||
451 (op
== UUIDD_OP_BULK_RANDOM_UUID
)) {
452 if (read_all(ns
, (char *) &num
, sizeof(num
)) != 4)
453 goto shutdown_socket
;
454 if (uuidd_cxt
->debug
)
455 fprintf(stderr
, _("operation %d, incoming num = %d\n"),
457 } else if (uuidd_cxt
->debug
)
458 fprintf(stderr
, _("operation %d\n"), op
);
461 case UUIDD_OP_GETPID
:
462 sprintf(reply_buf
, "%d", getpid());
463 reply_len
= strlen(reply_buf
) + 1;
465 case UUIDD_OP_GET_MAXOP
:
466 sprintf(reply_buf
, "%d", UUIDD_MAX_OP
);
467 reply_len
= strlen(reply_buf
) + 1;
469 case UUIDD_OP_TIME_UUID
:
471 __uuid_generate_time(uu
, &num
);
472 if (uuidd_cxt
->debug
) {
473 uuid_unparse(uu
, str
);
474 fprintf(stderr
, _("Generated time UUID: %s\n"), str
);
476 memcpy(reply_buf
, uu
, sizeof(uu
));
477 reply_len
= sizeof(uu
);
479 case UUIDD_OP_RANDOM_UUID
:
481 __uuid_generate_random(uu
, &num
);
482 if (uuidd_cxt
->debug
) {
483 uuid_unparse(uu
, str
);
484 fprintf(stderr
, _("Generated random UUID: %s\n"), str
);
486 memcpy(reply_buf
, uu
, sizeof(uu
));
487 reply_len
= sizeof(uu
);
489 case UUIDD_OP_BULK_TIME_UUID
:
490 __uuid_generate_time(uu
, &num
);
491 if (uuidd_cxt
->debug
) {
492 uuid_unparse(uu
, str
);
493 fprintf(stderr
, P_("Generated time UUID %s "
494 "and %d following\n",
495 "Generated time UUID %s "
496 "and %d following\n", num
- 1),
499 memcpy(reply_buf
, uu
, sizeof(uu
));
500 reply_len
= sizeof(uu
);
501 memcpy(reply_buf
+ reply_len
, &num
, sizeof(num
));
502 reply_len
+= sizeof(num
);
504 case UUIDD_OP_BULK_RANDOM_UUID
:
509 if (num
* UUID_LEN
> (int) (sizeof(reply_buf
) - sizeof(num
)))
510 num
= (sizeof(reply_buf
) - sizeof(num
)) / UUID_LEN
;
511 __uuid_generate_random((unsigned char *) reply_buf
+
513 if (uuidd_cxt
->debug
) {
514 fprintf(stderr
, P_("Generated %d UUID:\n",
515 "Generated %d UUIDs:\n", num
), num
);
516 for (i
= 0, cp
= reply_buf
+ sizeof(num
);
518 i
++, cp
+= UUID_LEN
) {
519 uuid_unparse((unsigned char *)cp
, str
);
520 fprintf(stderr
, "\t%s\n", str
);
523 reply_len
= (num
* UUID_LEN
) + sizeof(num
);
524 memcpy(reply_buf
, &num
, sizeof(num
));
527 if (uuidd_cxt
->debug
)
528 fprintf(stderr
, _("Invalid operation %d\n"), op
);
529 goto shutdown_socket
;
531 write_all(ns
, (char *) &reply_len
, sizeof(reply_len
));
532 write_all(ns
, reply_buf
, reply_len
);
538 static void __attribute__ ((__noreturn__
)) unexpected_size(int size
)
540 errx(EXIT_FAILURE
, _("Unexpected reply length from server %d"), size
);
543 int main(int argc
, char **argv
)
545 const char *socket_path
= UUIDD_SOCKET_PATH
;
546 const char *pidfile_path
= NULL
;
547 const char *pidfile_path_param
= NULL
;
548 const char *err_context
= NULL
;
550 char str
[UUID_STR_LEN
];
553 int do_type
= 0, do_kill
= 0, num
= 0;
557 struct uuidd_cxt_t uuidd_cxt
= { .timeout
= 0 };
559 static const struct option longopts
[] = {
560 {"pid", required_argument
, NULL
, 'p'},
561 {"socket", required_argument
, NULL
, 's'},
562 {"timeout", required_argument
, NULL
, 'T'},
563 {"kill", no_argument
, NULL
, 'k'},
564 {"random", no_argument
, NULL
, 'r'},
565 {"time", no_argument
, NULL
, 't'},
566 {"uuids", required_argument
, NULL
, 'n'},
567 {"no-pid", no_argument
, NULL
, 'P'},
568 {"no-fork", no_argument
, NULL
, 'F'},
569 {"socket-activation", no_argument
, NULL
, 'S'},
570 {"debug", no_argument
, NULL
, 'd'},
571 {"quiet", no_argument
, NULL
, 'q'},
572 {"version", no_argument
, NULL
, 'V'},
573 {"help", no_argument
, NULL
, 'h'},
576 static const ul_excl_t excl
[] = {
582 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
584 setlocale(LC_ALL
, "");
585 bindtextdomain(PACKAGE
, LOCALEDIR
);
587 atexit(close_stdout
);
590 getopt_long(argc
, argv
, "p:s:T:krtn:PFSdqVh", longopts
,
592 err_exclusive_options(c
, longopts
, excl
, excl_st
);
601 num
= strtou32_or_err(optarg
,
602 _("failed to parse --uuids"));
605 pidfile_path_param
= optarg
;
611 uuidd_cxt
.no_fork
= 1;
614 #ifdef HAVE_LIBSYSTEMD
615 uuidd_cxt
.no_sock
= 1;
616 uuidd_cxt
.no_fork
= 1;
619 errx(EXIT_FAILURE
, _("uuidd has been built without "
620 "support for socket activation"));
627 do_type
= UUIDD_OP_RANDOM_UUID
;
630 socket_path
= optarg
;
634 do_type
= UUIDD_OP_TIME_UUID
;
637 uuidd_cxt
.timeout
= strtou32_or_err(optarg
,
638 _("failed to parse --timeout"));
641 printf(UTIL_LINUX_VERSION
);
650 if (!no_pid
&& !pidfile_path_param
)
651 pidfile_path
= UUIDD_PIDFILE_PATH
;
652 else if (pidfile_path_param
)
653 pidfile_path
= pidfile_path_param
;
655 /* custom socket path and socket-activation make no sense */
656 if (s_flag
&& uuidd_cxt
.no_sock
&& !uuidd_cxt
.quiet
)
657 warnx(_("Both --socket-activation and --socket specified. "
658 "Ignoring --socket."));
660 if (num
&& do_type
) {
661 ret
= call_daemon(socket_path
, do_type
+ 2, buf
,
662 sizeof(buf
), &num
, &err_context
);
664 err(EXIT_FAILURE
, _("error calling uuidd daemon (%s)"),
665 err_context
? : _("unexpected error"));
667 if (do_type
== UUIDD_OP_TIME_UUID
) {
668 if (ret
!= sizeof(uu
) + sizeof(num
))
669 unexpected_size(ret
);
671 uuid_unparse((unsigned char *) buf
, str
);
673 printf(P_("%s and %d subsequent UUID\n",
674 "%s and %d subsequent UUIDs\n", num
- 1),
677 printf(_("List of UUIDs:\n"));
679 if (ret
!= (int) (sizeof(num
) + num
* sizeof(uu
)))
680 unexpected_size(ret
);
681 for (i
= 0; i
< num
; i
++, cp
+= UUID_LEN
) {
682 uuid_unparse((unsigned char *) cp
, str
);
683 printf("\t%s\n", str
);
689 ret
= call_daemon(socket_path
, do_type
, (char *) &uu
,
690 sizeof(uu
), 0, &err_context
);
692 err(EXIT_FAILURE
, _("error calling uuidd daemon (%s)"),
693 err_context
? : _("unexpected error"));
694 if (ret
!= sizeof(uu
))
695 unexpected_size(ret
);
697 uuid_unparse(uu
, str
);
704 ret
= call_daemon(socket_path
, UUIDD_OP_GETPID
, buf
, sizeof(buf
), 0, NULL
);
705 if ((ret
> 0) && ((do_kill
= atoi((char *) buf
)) > 0)) {
706 ret
= kill(do_kill
, SIGTERM
);
708 if (!uuidd_cxt
.quiet
)
709 warn(_("couldn't kill uuidd running "
710 "at pid %d"), do_kill
);
713 if (!uuidd_cxt
.quiet
)
714 printf(_("Killed uuidd running at pid %d.\n"),
720 server_loop(socket_path
, pidfile_path
, &uuidd_cxt
);