| 1446 | } |
| 1447 | |
| 1448 | static void create_pid_file(void) |
| 1449 | { |
| 1450 | char *pid_file = lp_pid_file(); |
| 1451 | char pidbuf[32]; |
| 1452 | STRUCT_STAT st1, st2; |
| 1453 | char *fail = NULL; |
| 1454 | |
| 1455 | if (!pid_file || !*pid_file) |
| 1456 | return; |
| 1457 | |
| 1458 | #ifdef O_NOFOLLOW |
| 1459 | #define SAFE_OPEN_FLAGS (O_CREAT|O_NOFOLLOW) |
| 1460 | #else |
| 1461 | #define SAFE_OPEN_FLAGS (O_CREAT) |
| 1462 | #endif |
| 1463 | |
| 1464 | /* These tests make sure that a temp-style lock dir is handled safely. */ |
| 1465 | st1.st_mode = 0; |
| 1466 | if (do_lstat(pid_file, &st1) == 0 && !S_ISREG(st1.st_mode) && unlink(pid_file) < 0) |
| 1467 | fail = "unlink"; |
| 1468 | else if ((pid_file_fd = do_open(pid_file, O_RDWR|SAFE_OPEN_FLAGS, 0664)) < 0) |
| 1469 | fail = S_ISREG(st1.st_mode) ? "open" : "create"; |
| 1470 | else if (!lock_range(pid_file_fd, 0, 4)) |
| 1471 | fail = "lock"; |
| 1472 | else if (do_fstat(pid_file_fd, &st1) < 0) |
| 1473 | fail = "fstat opened"; |
| 1474 | else if (st1.st_size > (int)sizeof pidbuf) |
| 1475 | fail = "find small"; |
| 1476 | else if (do_lstat(pid_file, &st2) < 0) |
| 1477 | fail = "lstat"; |
| 1478 | else if (!S_ISREG(st1.st_mode)) |
| 1479 | fail = "avoid file overwrite race for"; |
| 1480 | else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) |
| 1481 | fail = "verify stat info for"; |
| 1482 | #ifdef HAVE_FTRUNCATE |
| 1483 | else if (do_ftruncate(pid_file_fd, 0) < 0) |
| 1484 | fail = "truncate"; |
| 1485 | #endif |
| 1486 | else { |
| 1487 | pid_t pid = getpid(); |
| 1488 | int len = snprintf(pidbuf, sizeof pidbuf, "%d\n", (int)pid); |
| 1489 | #ifndef HAVE_FTRUNCATE |
| 1490 | /* What can we do with a too-long file and no truncate? I guess we'll add extra newlines. */ |
| 1491 | while (len < st1.st_size) /* We already verified that st_size chars fits in the buffer. */ |
| 1492 | pidbuf[len++] = '\n'; |
| 1493 | /* We don't need the buffer to end in a '\0' (and we may not have room to add it). */ |
| 1494 | #endif |
| 1495 | if (write(pid_file_fd, pidbuf, len) != len) |
| 1496 | fail = "write"; |
| 1497 | cleanup_set_pid(pid); /* Mark the file for removal on exit, even if the write failed. */ |
| 1498 | } |
| 1499 | |
| 1500 | if (fail) { |
| 1501 | char msg[1024]; |
no test coverage detected