| 100 | } |
| 101 | |
| 102 | struct pidfh * |
| 103 | pidfile_open(const char *pathp, mode_t mode, pid_t *pidptr) |
| 104 | { |
| 105 | char path[MAXPATHLEN]; |
| 106 | struct pidfh *pfh; |
| 107 | struct stat sb; |
| 108 | int error, fd, dirfd, dirlen, filenamelen, count; |
| 109 | struct timespec rqtp; |
| 110 | cap_rights_t caprights; |
| 111 | |
| 112 | pfh = malloc(sizeof(*pfh)); |
| 113 | if (pfh == NULL) |
| 114 | return (NULL); |
| 115 | |
| 116 | if (pathp == NULL) { |
| 117 | dirlen = snprintf(pfh->pf_dir, sizeof(pfh->pf_dir), |
| 118 | "/var/run/"); |
| 119 | filenamelen = snprintf(pfh->pf_filename, |
| 120 | sizeof(pfh->pf_filename), "%s.pid", getprogname()); |
| 121 | } else { |
| 122 | if (strlcpy(path, pathp, sizeof(path)) >= sizeof(path)) { |
| 123 | free(pfh); |
| 124 | errno = ENAMETOOLONG; |
| 125 | return (NULL); |
| 126 | } |
| 127 | dirlen = strlcpy(pfh->pf_dir, dirname(path), |
| 128 | sizeof(pfh->pf_dir)); |
| 129 | (void)strlcpy(path, pathp, sizeof(path)); |
| 130 | filenamelen = strlcpy(pfh->pf_filename, basename(path), |
| 131 | sizeof(pfh->pf_filename)); |
| 132 | } |
| 133 | |
| 134 | if (dirlen >= (int)sizeof(pfh->pf_dir) || |
| 135 | filenamelen >= (int)sizeof(pfh->pf_filename)) { |
| 136 | free(pfh); |
| 137 | errno = ENAMETOOLONG; |
| 138 | return (NULL); |
| 139 | } |
| 140 | |
| 141 | dirfd = open(pfh->pf_dir, O_CLOEXEC | O_DIRECTORY | O_NONBLOCK); |
| 142 | if (dirfd == -1) { |
| 143 | error = errno; |
| 144 | free(pfh); |
| 145 | errno = error; |
| 146 | return (NULL); |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | * Open the PID file and obtain exclusive lock. |
| 151 | * We truncate PID file here only to remove old PID immediately, |
| 152 | * PID file will be truncated again in pidfile_write(), so |
| 153 | * pidfile_write() can be called multiple times. |
| 154 | */ |
| 155 | fd = flopenat(dirfd, pfh->pf_filename, |
| 156 | O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode); |
| 157 | if (fd == -1) { |
| 158 | if (errno == EWOULDBLOCK) { |
| 159 | if (pidptr == NULL) { |