3 * \author written by Emmanuel Roullit emmanuel.roullit@gmail.com (c) 2012
7 /* __LICENSE_HEADER_BEGIN__ */
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
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__ */
36 #include <sys/types.h>
40 #include <libdabba/strlcpy.h>
44 * \brief Path to current process open file descriptor information
48 #define PROC_FD_PATH "/proc/self/fd/"
49 #endif /* PROC_FD_PATH */
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
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
;
68 struct dirent
*dir_entry
;
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)
85 dir
= opendir(PROC_FD_PATH
);
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)
102 (proc_path
, sizeof(proc_path
), "%s%s", PROC_FD_PATH
,
103 dir_entry
->d_name
) <= 0) {
108 if (fstat(fd
, &fd_stat
) < 0 || stat(proc_path
, &path_stat
) < 0) {
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
) {
120 /* resolve /proc/self/fd/<fdstr> symlink now */
121 resolved_path
= realpath(proc_path
, NULL
);
123 if (!resolved_path
) {
128 strlcpy(path
, resolved_path
, path_len
);
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;
152 pidfd
= open(pidfile
, O_WRONLY
| O_CREAT
, S_IWUSR
| S_IRUSR
| S_IRGRP
);
157 len
= snprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
159 if (write(pidfd
, pidstr
, len
) != len
)