dabbad: give group pidfile read access.
[dabba.git] / dabbad / misc.c
bloba3c06445132301ad9680bd99cd0510f695d9e54e
1 /**
2 * \file misc.c
3 * \author written by Emmanuel Roullit emmanuel.roullit@gmail.com (c) 2012
4 * \date 2012
5 */
7 /* __LICENSE_HEADER_BEGIN__ */
9 /*
10 * Copyright (C) 2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
28 /* __LICENSE_HEADER_END__ */
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <dirent.h>
40 #include <libdabba/strlcpy.h>
41 #include <unistd.h>
43 /**
44 * \brief Path to current process open file descriptor information
47 #ifndef PROC_FD_PATH
48 #define PROC_FD_PATH "/proc/self/fd/"
49 #endif /* PROC_FD_PATH */
51 /**
52 * \brief Get file path from an open file descriptor
53 * \param[in] fd File descriptor
54 * \param[out] path Pointer to the path string buffer
55 * \param[in] path_len Path string buffer size in bytes
56 * \return 0 on success, else on failure.
58 * This function retrieves the absolute path of a file from its file descriptor.
59 * It mainly checks the device/inode numbers of the file descriptor and the file
60 * to correlate them.
63 int fd_to_path(const int fd, char *path, const size_t path_len)
65 char proc_path[PATH_MAX], fdstr[16];
66 struct stat fd_stat, path_stat;
67 DIR *dir;
68 struct dirent *dir_entry;
69 char *resolved_path;
70 int rc = 0;
72 assert(fd > 0);
73 assert(path);
74 assert(path_len);
76 memset(proc_path, 0, sizeof(proc_path));
77 memset(fdstr, 0, sizeof(fdstr));
78 memset(&fd_stat, 0, sizeof(fd_stat));
79 memset(&resolved_path, 0, sizeof(resolved_path));
80 memset(&path_stat, 0, sizeof(path_stat));
82 if (snprintf(fdstr, sizeof(fdstr), "%i", fd) <= 0)
83 return errno;
85 dir = opendir(PROC_FD_PATH);
87 if (!dir)
88 return errno;
90 /* /proc/self/fd/<fdstr> is a symlink to the actual file */
91 for (dir_entry = readdir(dir); dir_entry; dir_entry = readdir(dir)) {
92 if (strcmp(dir_entry->d_name, fdstr) == 0)
93 break;
96 if (!dir_entry) {
97 rc = ENOENT;
98 goto out;
101 if (snprintf
102 (proc_path, sizeof(proc_path), "%s%s", PROC_FD_PATH,
103 dir_entry->d_name) <= 0) {
104 rc = errno;
105 goto out;
108 if (fstat(fd, &fd_stat) < 0 || stat(proc_path, &path_stat) < 0) {
109 rc = errno;
110 goto out;
113 /* filenames are not accurate, interface and inode ID need to checked too */
114 if (fd_stat.st_dev != path_stat.st_dev
115 || fd_stat.st_ino != path_stat.st_ino) {
116 rc = EINVAL;
117 goto out;
120 /* resolve /proc/self/fd/<fdstr> symlink now */
121 resolved_path = realpath(proc_path, NULL);
123 if (!resolved_path) {
124 rc = errno;
125 goto out;
128 strlcpy(path, resolved_path, path_len);
130 free(resolved_path);
132 out:
133 closedir(dir);
134 return rc;
138 * \brief Create text where the current pid is written in
139 * \param[in]           pidfile                PID file path
140 * \return 0 on success, \c errno on failure.
141 * \note if no file exists at the indicated path, a file is created.
142 * \note if a file already exists at the indicated path, it is overwritten.
145 int create_pidfile(const char *const pidfile)
147 int pidfd, len, rc = 0;
148 char pidstr[8];
150 assert(pidfile);
152 pidfd = open(pidfile, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP);
154 if (pidfd < 0)
155 return errno;
157 len = snprintf(pidstr, sizeof(pidstr), "%u", getpid());
159 if (write(pidfd, pidstr, len) != len)
160 rc = errno;
162 close(pidfd);
164 return rc;