Fixed up copyright year mention.
[dabba.git] / dabbad / misc.c
blob37d4e873366a633680138a577f1faeb533cf9986
1 /* __LICENSE_HEADER_BEGIN__ */
3 /*
4 * Copyright (C) 2012 Emmanuel Roullit <emmanuel.roullit@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
22 /* __LICENSE_HEADER_END__ */
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <dirent.h>
33 #include <dabbacore/strlcpy.h>
35 #define PROC_FD_PATH "/proc/self/fd/"
37 int fd_to_path(const int fd, char *path, const size_t path_len)
39 char proc_path[PATH_MAX], fdstr[16];
40 struct stat fd_stat, path_stat;
41 DIR *dir;
42 struct dirent *dir_entry;
43 char *resolved_path;
44 int rc = 0;
46 assert(fd > 0);
47 assert(path);
48 assert(path_len);
50 memset(&proc_path, 0, sizeof(proc_path));
51 memset(&fd_stat, 0, sizeof(fd_stat));
52 memset(&resolved_path, 0, sizeof(resolved_path));
53 memset(&path_stat, 0, sizeof(path_stat));
54 memset(&fdstr, 0, sizeof(fdstr));
56 if (snprintf(fdstr, sizeof(fdstr), "%i", fd) <= 0)
57 return errno;
59 dir = opendir(PROC_FD_PATH);
61 if (!dir)
62 return errno;
64 /* /proc/self/fd/<fdstr> is a symlink to the actual file */
65 for (dir_entry = readdir(dir); dir_entry; dir_entry = readdir(dir)) {
66 if (strcmp(dir_entry->d_name, fdstr) == 0)
67 break;
70 if (!dir_entry) {
71 rc = ENOENT;
72 goto out;
75 if (snprintf
76 (proc_path, sizeof(proc_path), PROC_FD_PATH "%s",
77 dir_entry->d_name) <= 0) {
78 rc = errno;
79 goto out;
82 if (fstat(fd, &fd_stat) < 0 || stat(proc_path, &path_stat) < 0) {
83 rc = errno;
84 goto out;
87 /* filenames are not accurate, interface and inode ID need to checked too */
88 if (fd_stat.st_dev != path_stat.st_dev
89 || fd_stat.st_ino != path_stat.st_ino) {
90 rc = EINVAL;
91 goto out;
94 /* resolve /proc/self/fd/<fdstr> symlink now */
95 resolved_path = realpath(proc_path, NULL);
97 if (!resolved_path) {
98 rc = errno;
99 goto out;
102 strlcpy(path, resolved_path, path_len);
104 free(resolved_path);
106 out:
107 closedir(dir);
108 return rc;