Added --version option to get dabbad version info.
[dabba.git] / dabbad / misc.c
blob318b13fab363915ae110d65d8329d75bf8ba8a6f
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 <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
39 #include <libdabba/strlcpy.h>
41 /**
42 * \brief Path to current process open file descriptor information
45 #define PROC_FD_PATH "/proc/self/fd/"
47 /**
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
56 * to correlate them.
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;
63 DIR *dir;
64 struct dirent *dir_entry;
65 char *resolved_path;
66 int rc = 0;
68 assert(fd > 0);
69 assert(path);
70 assert(path_len);
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)
79 return errno;
81 dir = opendir(PROC_FD_PATH);
83 if (!dir)
84 return errno;
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)
89 break;
92 if (!dir_entry) {
93 rc = ENOENT;
94 goto out;
97 if (snprintf
98 (proc_path, sizeof(proc_path), "%s%s", PROC_FD_PATH, dir_entry->d_name) <= 0) {
99 rc = errno;
100 goto out;
103 if (fstat(fd, &fd_stat) < 0 || stat(proc_path, &path_stat) < 0) {
104 rc = errno;
105 goto out;
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) {
111 rc = EINVAL;
112 goto out;
115 /* resolve /proc/self/fd/<fdstr> symlink now */
116 resolved_path = realpath(proc_path, NULL);
118 if (!resolved_path) {
119 rc = errno;
120 goto out;
123 strlcpy(path, resolved_path, path_len);
125 free(resolved_path);
127 out:
128 closedir(dir);
129 return rc;