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 00008 * published by the Free Software Foundation; either version 3 of the 00009 * License, or (at 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/fcntl.h> 00022 00023 #include <libexplain/buffer/ebadf.h> 00024 #include <libexplain/buffer/errno/close.h> 00025 #include <libexplain/buffer/errno/fclose.h> 00026 #include <libexplain/buffer/errno/write.h> 00027 #include <libexplain/buffer/gettext.h> 00028 #include <libexplain/buffer/is_the_null_pointer.h> 00029 #include <libexplain/buffer/stream.h> 00030 #include <libexplain/buffer/note/underlying_fildes_open.h> 00031 #include <libexplain/explanation.h> 00032 #include <libexplain/stream_to_fildes.h> 00033 00034 00035 static void 00036 explain_buffer_errno_fclose_system_call(explain_string_buffer_t *sb, 00037 int errnum, FILE *fp) 00038 { 00039 (void)errnum; 00040 explain_string_buffer_puts(sb, "fclose(fp = "); 00041 explain_buffer_stream(sb, fp); 00042 explain_string_buffer_putc(sb, ')'); 00043 } 00044 00045 00046 void 00047 explain_buffer_errno_fclose_explanation(explain_string_buffer_t *sb, 00048 int errnum, const char *syscall_name, FILE *fp) 00049 { 00050 int fildes; 00051 00052 if (!fp) 00053 { 00054 explain_buffer_is_the_null_pointer(sb, "fp"); 00055 return; 00056 } 00057 00058 /* 00059 * The Linux fclose(3) man page says 00060 * 00061 * "RETURN VALUE: Upon successful completion 0 is returned. 00062 * Otherwise, EOF is returned and the global variable errno is 00063 * set to indicate the error. In either case any further access 00064 * (including another call to fclose()) to the stream results in 00065 * undefined behavior." 00066 * 00067 * which is interesting because if close(2) fails, the file 00068 * descriptor is usually still open. Thus, we make an attempt 00069 * to recover the file descriptor, to see if we can produce some 00070 * additional information. 00071 * 00072 * If you are using glibc you are plain out of luck, because 00073 * it very carefully assigns -1 to the file descriptor member. 00074 * Other implementations may not be so careful, indeed other 00075 * implementations may keep the FILE pointer valid if the underlying 00076 * file descriptor is still valid. 00077 */ 00078 fildes = explain_stream_to_fildes(fp); 00079 00080 switch (errnum) 00081 { 00082 case EFAULT: 00083 case EFBIG: 00084 case EINVAL: 00085 case ENOSPC: 00086 case EPIPE: 00087 explain_buffer_errno_write_explanation 00088 ( 00089 sb, 00090 errnum, 00091 syscall_name, 00092 fildes, 00093 NULL, 00094 0 00095 ); 00096 break; 00097 00098 case EBADF: 00099 explain_buffer_ebadf(sb, fildes, "fp"); 00100 break; 00101 00102 case EINTR: 00103 case EIO: 00104 default: 00105 explain_buffer_errno_close_explanation 00106 ( 00107 sb, 00108 errnum, 00109 syscall_name, 00110 fildes 00111 ); 00112 break; 00113 } 00114 if (errnum != EBADF) 00115 { 00116 explain_buffer_note_underlying_fildes_open(sb); 00117 } 00118 } 00119 00120 00121 void 00122 explain_buffer_errno_fclose(explain_string_buffer_t *sb, int errnum, 00123 FILE *fp) 00124 { 00125 explain_explanation_t exp; 00126 00127 explain_explanation_init(&exp, errnum); 00128 explain_buffer_errno_fclose_system_call(&exp.system_call_sb, errnum, fp); 00129 explain_buffer_errno_fclose_explanation 00130 ( 00131 &exp.explanation_sb, 00132 errnum, 00133 "fclose", 00134 fp 00135 ); 00136 explain_explanation_assemble(&exp, sb); 00137 } 00138 00139 00140 /* vim: set ts=8 sw=4 et : */