libexplain
1.4.D001
|
00001 /* 00002 * libexplain - a library of system-call-specific strerror replacements 00003 * Copyright (C) 2011, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 3 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, but WITHOUT 00012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00014 * License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/fcntl.h> 00021 #include <libexplain/ac/limits.h> /* for PATH_MAX on Solaris */ 00022 #include <libexplain/ac/stdio.h> 00023 #include <libexplain/ac/string.h> 00024 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */ 00025 #include <libexplain/ac/unistd.h> 00026 00027 #include <libexplain/fileinfo.h> 00028 #include <libexplain/lsof.h> 00029 00030 00031 typedef struct adapter adapter; 00032 struct adapter 00033 { 00034 explain_lsof_t inherited; 00035 char *data; 00036 size_t data_size; 00037 int found; 00038 }; 00039 00040 00041 static void 00042 n_callback(explain_lsof_t *context, const char *name) 00043 { 00044 /* 00045 * Sometimes lsof(1) is less than helpful, and says "n (readlink: 00046 * Permission denied)" which is effectively no answer at all. 00047 * 00048 * There is a very small chance of discarding a valid result. 00049 * Get fussier if it proves to be an actual problem. 00050 */ 00051 if (!strstr(name, " (readlink: ")) 00052 { 00053 adapter *a; 00054 00055 a = (adapter *)context; 00056 a->found = 1; 00057 explain_strendcpy(a->data, name, a->data + a->data_size); 00058 } 00059 } 00060 00061 00062 int 00063 explain_fileinfo_pid_fd_n(pid_t pid, int fildes, char *data, size_t data_size) 00064 { 00065 if (fildes == AT_FDCWD) 00066 { 00067 return explain_fileinfo_self_cwd(data, data_size); 00068 } 00069 if (data_size < 2) 00070 return 0; 00071 #if defined(PROC_PID_PATH_N) 00072 { 00073 int n; 00074 char path[PATH_MAX + 1]; 00075 00076 /* Solaris */ 00077 snprintf(path, sizeof(path), "/proc/%ld/path/%d", (long)pid, fildes); 00078 n = readlink(path, data, data_size - 1); 00079 if (n > 0 && data[0] == '/') 00080 { 00081 data[n] = '\0'; 00082 return 1; 00083 } 00084 } 00085 #elif defined(PROC_PID_FD_N) 00086 { 00087 int n; 00088 char path[PATH_MAX + 1]; 00089 00090 /* Linux (The Solaris files at the same path aren't useful). */ 00091 snprintf(path, sizeof(path), "/proc/%ld/fd/%d", (long)pid, fildes); 00092 n = readlink(path, data, data_size - 1); 00093 if (n > 0 && data[0] == '/') 00094 { 00095 data[n] = '\0'; 00096 return 1; 00097 } 00098 } 00099 #endif 00100 00101 /* 00102 * It is possible that /proc didn't work. Maybe ./configure 00103 * was fooled, or it could be that /proc worked in the build 00104 * environment, but it isn't available or doesn't work in the 00105 * runtime environment (e.g. chroot jails). 00106 * 00107 * Try lsof(1) instead. 00108 */ 00109 { 00110 adapter obj; 00111 char options[40]; 00112 00113 obj.inherited.n_callback = n_callback; 00114 obj.data = data; 00115 obj.data_size = data_size; 00116 obj.found = 0; 00117 snprintf(options, sizeof(options), "-p %ld -d %d", (long)pid, fildes); 00118 explain_lsof(options, &obj.inherited); 00119 if (obj.found) 00120 return 1; 00121 } 00122 00123 /* 00124 * Sorry, can't help you. 00125 */ 00126 return 0; 00127 } 00128 00129 00130 /* vim: set ts=8 sw=4 et : */