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/stdio.h> 00021 #include <libexplain/ac/string.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/fileinfo.h> 00025 #include <libexplain/lsof.h> 00026 00027 00028 #if defined(PROC_PID_PATH_CWD) || defined(PROC_PID_CWD) 00029 00030 static int 00031 proc_pid_cwd(pid_t pid, char *data, size_t data_size) 00032 { 00033 int n; 00034 char path[100]; 00035 00036 if (data_size < 2) 00037 return 0; 00038 #if defined(PROC_PID_PATH_CWD) 00039 snprintf(path, sizeof(path), "/proc/%ld/path/cwd", (long)pid); 00040 #else 00041 snprintf(path, sizeof(path), "/proc/%ld/cwd", (long)pid); 00042 #endif 00043 n = readlink(path, data, data_size - 1); 00044 if (n <= 0) 00045 return 0; 00046 data[n] = '\0'; 00047 return (data[0] == '/'); 00048 } 00049 00050 #endif 00051 00052 00053 typedef struct adapter adapter; 00054 struct adapter 00055 { 00056 explain_lsof_t inherited; 00057 char *data; 00058 size_t data_size; 00059 int count; 00060 }; 00061 00062 00063 static void 00064 n_callback(explain_lsof_t *context, const char *name) 00065 { 00066 /* 00067 * Sometimes lsof(1) is less than helpful, and says "cwd (readlink: 00068 * Permission denied)" which is effectively no answer at all. 00069 */ 00070 if (0 != memcmp(name, "cwd (readlink:", 14)) 00071 { 00072 adapter *a; 00073 00074 a = (adapter *)context; 00075 explain_strendcpy(a->data, name, a->data + a->data_size); 00076 a->count++; 00077 } 00078 } 00079 00080 00081 int 00082 explain_fileinfo_pid_cwd(pid_t pid, char *data, size_t data_size) 00083 { 00084 /* 00085 * First, we try to do it the easy way. 00086 */ 00087 #if defined(PROC_PID_PATH_CWD) || defined(PROC_PID_CWD) 00088 if (proc_pid_cwd(pid, data, data_size)) 00089 return 1; 00090 #endif 00091 00092 /* 00093 * It is possible that /proc didn't work. Maybe ./configure 00094 * was fooled, or it could be that /proc worked in the build 00095 * environment, but it isn't available or doesn't work in the 00096 * runtime environment (e.g. chroot jails). 00097 * 00098 * Try lsof(1) instead. 00099 */ 00100 { 00101 adapter obj; 00102 char options[40]; 00103 00104 snprintf(options, sizeof(options), "-p%ld -dcwd", (long)pid); 00105 obj.inherited.n_callback = n_callback; 00106 obj.data = data; 00107 obj.data_size = data_size; 00108 obj.count = 0; 00109 explain_lsof(options, &obj.inherited); 00110 if (obj.count > 0) 00111 return 1; 00112 } 00113 00114 /* 00115 * Sorry, can't help you. 00116 */ 00117 return 0; 00118 } 00119 00120 00121 /* vim: set ts=8 sw=4 et : */