libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008, 2009, 2011, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 3 of the License, or (at 00008 * your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/errno.h> 00020 #include <libexplain/ac/fcntl.h> 00021 #include <libexplain/ac/stdio.h> 00022 00023 #include <libexplain/buffer/ebadf.h> 00024 #include <libexplain/buffer/efault.h> 00025 #include <libexplain/buffer/eintr.h> 00026 #include <libexplain/buffer/enomem.h> 00027 #include <libexplain/buffer/errno/generic.h> 00028 #include <libexplain/buffer/errno/select.h> 00029 #include <libexplain/buffer/fd_set.h> 00030 #include <libexplain/buffer/timeval.h> 00031 #include <libexplain/explanation.h> 00032 #include <libexplain/option.h> 00033 #include <libexplain/is_efault.h> 00034 00035 00036 static void 00037 explain_buffer_errno_select_system_call(explain_string_buffer_t *sb, 00038 int errnum, int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 00039 struct timeval *timeout) 00040 { 00041 (void)errnum; 00042 explain_string_buffer_printf(sb, "select(nfds = %d", nfds); 00043 explain_string_buffer_puts(sb, ", readfds = "); 00044 explain_buffer_fd_set(sb, nfds, readfds); 00045 explain_string_buffer_puts(sb, ", writefds = "); 00046 explain_buffer_fd_set(sb, nfds, writefds); 00047 explain_string_buffer_puts(sb, ", exceptfds = "); 00048 explain_buffer_fd_set(sb, nfds, exceptfds); 00049 explain_string_buffer_puts(sb, ", timeout = "); 00050 explain_buffer_timeval(sb, timeout); 00051 explain_string_buffer_putc(sb, ')'); 00052 } 00053 00054 00055 static int 00056 file_descriptor_is_open(int fildes) 00057 { 00058 int err; 00059 00060 err = fcntl(fildes, F_GETFL); 00061 return (err >= 0); 00062 } 00063 00064 00065 static void 00066 explain_buffer_errno_select_explanation(explain_string_buffer_t *sb, 00067 int errnum, const char *syscall_name, int nfds, fd_set *readfds, 00068 fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) 00069 { 00070 /* 00071 * http://www.opengroup.org/onlinepubs/009695399/functions/select.html 00072 */ 00073 switch (errnum) 00074 { 00075 case EBADF: 00076 { 00077 int fildes; 00078 00079 for (fildes = 0; fildes < nfds; ++fildes) 00080 { 00081 if 00082 ( 00083 ( 00084 (readfds && FD_ISSET(fildes, readfds)) 00085 || 00086 (writefds && FD_ISSET(fildes, writefds)) 00087 || 00088 (exceptfds && FD_ISSET(fildes, exceptfds)) 00089 ) 00090 && 00091 !file_descriptor_is_open(fildes) 00092 ) 00093 break; 00094 } 00095 if (fildes < nfds) 00096 { 00097 char caption[40]; 00098 00099 snprintf(caption, sizeof(caption), "fildes %d", fildes); 00100 explain_buffer_ebadf(sb, fildes, caption); 00101 } 00102 else 00103 { 00104 explain_string_buffer_puts 00105 ( 00106 sb, 00107 "an invalid file descriptor was given in one of the sets; " 00108 "perhaps a file descriptor that was already closed, or one " 00109 "on which an error has occurred" 00110 ); 00111 } 00112 } 00113 break; 00114 00115 case EFAULT: 00116 if (readfds && explain_is_efault_pointer(readfds, sizeof(*readfds))) 00117 { 00118 explain_buffer_efault(sb, "readfds"); 00119 break; 00120 } 00121 if 00122 ( 00123 writefds 00124 && 00125 explain_is_efault_pointer(writefds, sizeof(*writefds)) 00126 ) 00127 { 00128 explain_buffer_efault(sb, "writefds"); 00129 break; 00130 } 00131 if 00132 ( 00133 exceptfds 00134 && 00135 explain_is_efault_pointer(exceptfds, sizeof(*exceptfds)) 00136 ) 00137 { 00138 explain_buffer_efault(sb, "exceptfds"); 00139 break; 00140 } 00141 if (timeout && explain_is_efault_pointer(timeout, sizeof(*timeout))) 00142 { 00143 explain_buffer_efault(sb, "timeout"); 00144 break; 00145 } 00146 break; 00147 00148 case EINTR: 00149 explain_buffer_eintr(sb, syscall_name); 00150 break; 00151 00152 case EINVAL: 00153 if (nfds < 0) 00154 { 00155 explain_string_buffer_puts(sb, "nfds is negative"); 00156 break; 00157 } 00158 if ((unsigned)nfds > (unsigned)FD_SETSIZE) 00159 { 00160 explain_string_buffer_puts 00161 ( 00162 sb, 00163 "nfds is greater than FD_SETSIZE" 00164 ); 00165 if (explain_option_dialect_specific()) 00166 explain_string_buffer_printf(sb, " (%d)", FD_SETSIZE); 00167 break; 00168 } 00169 if (timeout && (timeout->tv_sec < 0 || timeout->tv_usec < 0)) 00170 { 00171 explain_string_buffer_puts(sb, "timeout is invalid"); 00172 break; 00173 } 00174 break; 00175 00176 case ENOMEM: 00177 explain_buffer_enomem_kernel(sb); 00178 break; 00179 00180 default: 00181 explain_buffer_errno_generic(sb, errnum, syscall_name); 00182 break; 00183 } 00184 } 00185 00186 00187 void 00188 explain_buffer_errno_select(explain_string_buffer_t *sb, int errnum, 00189 int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 00190 struct timeval *timeout) 00191 { 00192 explain_explanation_t exp; 00193 00194 explain_explanation_init(&exp, errnum); 00195 explain_buffer_errno_select_system_call 00196 ( 00197 &exp.system_call_sb, 00198 errnum, 00199 nfds, 00200 readfds, 00201 writefds, 00202 exceptfds, 00203 timeout 00204 ); 00205 explain_buffer_errno_select_explanation 00206 ( 00207 &exp.explanation_sb, 00208 errnum, 00209 "select", 00210 nfds, 00211 readfds, 00212 writefds, 00213 exceptfds, 00214 timeout 00215 ); 00216 explain_explanation_assemble(&exp, sb); 00217 } 00218 00219 00220 /* vim: set ts=8 sw=4 et : */