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__ */
35 #include <sys/types.h>
39 #include <libdabba/strlcpy.h>
42 * \brief Path to current process open file descriptor information
45 #define PROC_FD_PATH "/proc/self/fd/"
48 * \brief Get file path from an open file descriptor
49 * \param[in] fd File descriptor
50 * \param[out] path Pointer to the path string buffer
51 * \param[in] path_len Path string buffer size in bytes
52 * \return 0 on success, else on failure.
54 * This function retrieves the absolute path of a file from its file descriptor.
55 * It mainly checks the device/inode numbers of the file descriptor and the file
59 int fd_to_path(const int fd
, char *path
, const size_t path_len
)
61 char proc_path
[PATH_MAX
], fdstr
[16];
62 struct stat fd_stat
, path_stat
;
64 struct dirent
*dir_entry
;
72 memset(proc_path
, 0, sizeof(proc_path
));
73 memset(fdstr
, 0, sizeof(fdstr
));
74 memset(&fd_stat
, 0, sizeof(fd_stat
));
75 memset(&resolved_path
, 0, sizeof(resolved_path
));
76 memset(&path_stat
, 0, sizeof(path_stat
));
78 if (snprintf(fdstr
, sizeof(fdstr
), "%i", fd
) <= 0)
81 dir
= opendir(PROC_FD_PATH
);
86 /* /proc/self/fd/<fdstr> is a symlink to the actual file */
87 for (dir_entry
= readdir(dir
); dir_entry
; dir_entry
= readdir(dir
)) {
88 if (strcmp(dir_entry
->d_name
, fdstr
) == 0)
98 (proc_path
, sizeof(proc_path
), "%s%s", PROC_FD_PATH
, dir_entry
->d_name
) <= 0) {
103 if (fstat(fd
, &fd_stat
) < 0 || stat(proc_path
, &path_stat
) < 0) {
108 /* filenames are not accurate, interface and inode ID need to checked too */
109 if (fd_stat
.st_dev
!= path_stat
.st_dev
110 || fd_stat
.st_ino
!= path_stat
.st_ino
) {
115 /* resolve /proc/self/fd/<fdstr> symlink now */
116 resolved_path
= realpath(proc_path
, NULL
);
118 if (!resolved_path
) {
123 strlcpy(path
, resolved_path
, path_len
);