libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2010, 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 00007 * it 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 00009 * your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public 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/errno.h> 00021 #include <libexplain/ac/string.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/enfile.h> 00025 #include <libexplain/buffer/gettext.h> 00026 #include <libexplain/option.h> 00027 #include <libexplain/sizeof.h> 00028 #include <libexplain/string_buffer.h> 00029 00030 #ifdef __linux__ 00031 #include <sys/syscall.h> 00032 #include <linux/sysctl.h> 00033 #endif 00034 00035 00036 static long 00037 get_maxfile(void) 00038 { 00039 if (explain_option_dialect_specific()) 00040 { 00041 #ifdef __linux__ 00042 /* 00043 * In the linux kernel, if get_empty_filp() returns NULL, the open 00044 * system call (and others) will return ENFILE. 00045 */ 00046 struct __sysctl_args args; 00047 int32_t maxfile; 00048 size_t maxfile_size = sizeof(maxfile); 00049 int name[] = { CTL_FS, FS_MAXFILE }; 00050 00051 /* 00052 * The Linux sysctl(2) man page has this to say: 00053 * 00054 * Glibc does not provide a wrapper for this system call; call it 00055 * using syscall(2). 00056 * 00057 * Or rather... don't call it: use of this system call has long 00058 * been discouraged, and it is so unloved that it is likely 00059 * to disappear in a future kernel version. Remove it from your 00060 * programs now; use the /proc/sys interface instead. 00061 * 00062 * The object names vary between kernel versions, making this system 00063 * call worthless for applications. 00064 * 00065 * Catch 22: you have to open a file to discover the limit of 00066 * open files AFTER you have hit the limit of open files. Sigh. 00067 */ 00068 memset(&args, 0, sizeof(struct __sysctl_args)); 00069 args.name = name; 00070 args.nlen = SIZEOF(name); 00071 args.oldval = &maxfile; 00072 args.oldlenp = &maxfile_size; 00073 00074 if (syscall(SYS__sysctl, &args) >= 0) 00075 return maxfile; 00076 #endif 00077 } 00078 return -1; 00079 } 00080 00081 00082 void 00083 explain_buffer_enfile(explain_string_buffer_t *sb) 00084 { 00085 long maxfile; 00086 00087 /* 00088 * FIXME: say the limit -- except that there doesn't seem to be 00089 * a sysconf() name for this. The _SC_OPEN_MAX name is for the 00090 * EMFILE error, which is different. 00091 */ 00092 explain_buffer_gettext 00093 ( 00094 sb, 00095 /* 00096 * xgettext: This message is used when explaining an ENFILE error. 00097 * 00098 * Note that it could be followed by the actual limit in 00099 * preentheses (if it can be determined) so it helps of the last 00100 * phrase in the message can sensably be followed by it. 00101 */ 00102 i18n("the system limit on the total number of open files " 00103 "has been reached") 00104 ); 00105 00106 /* 00107 * Some systems provide a way to discover the actual limit. 00108 */ 00109 maxfile = get_maxfile(); 00110 if (maxfile > 0) 00111 explain_string_buffer_printf(sb, " (%ld)", maxfile); 00112 } 00113 00114 00115 /* vim: set ts=8 sw=4 et : */