libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-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/sys/stat.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/ebadf.h> 00025 #include <libexplain/buffer/efbig.h> 00026 #include <libexplain/buffer/eintr.h> 00027 #include <libexplain/buffer/eio.h> 00028 #include <libexplain/buffer/erofs.h> 00029 #include <libexplain/buffer/errno/ftruncate.h> 00030 #include <libexplain/buffer/errno/generic.h> 00031 #include <libexplain/buffer/etxtbsy.h> 00032 #include <libexplain/buffer/fildes_to_pathname.h> 00033 #include <libexplain/buffer/fildes_not_open_for_writing.h> 00034 #include <libexplain/buffer/file_type.h> 00035 #include <libexplain/buffer/mount_point.h> 00036 #include <libexplain/buffer/off_t.h> 00037 #include <libexplain/buffer/open_flags.h> 00038 #include <libexplain/explanation.h> 00039 00040 00041 static void 00042 explain_buffer_errno_ftruncate_system_call(explain_string_buffer_t *sb, 00043 int errnum, int fildes, off_t length) 00044 { 00045 (void)errnum; 00046 explain_string_buffer_printf(sb, "ftruncate(fildes = %d", fildes); 00047 explain_buffer_fildes_to_pathname(sb, fildes); 00048 explain_string_buffer_puts(sb, ", length = "); 00049 explain_buffer_off_t(sb, length); 00050 explain_string_buffer_putc(sb, ')'); 00051 } 00052 00053 00054 static void 00055 explain_buffer_errno_ftruncate_explanation(explain_string_buffer_t *sb, 00056 int errnum, int fildes, off_t length) 00057 { 00058 switch (errnum) 00059 { 00060 case EACCES: 00061 case EBADF: 00062 if (explain_buffer_fildes_not_open_for_writing(sb, fildes, "fildes")) 00063 explain_buffer_ebadf(sb, fildes, "fildes"); 00064 break; 00065 00066 case EFBIG: 00067 explain_buffer_efbig_fildes(sb, fildes, length, "length"); 00068 break; 00069 00070 case EINTR: 00071 explain_buffer_eintr(sb, "ftruncate"); 00072 break; 00073 00074 case EINVAL: 00075 if (length < 0) 00076 { 00077 /* FIXME: i18n */ 00078 explain_string_buffer_puts(sb, "'length' is negative"); 00079 } 00080 else 00081 { 00082 #ifdef _PC_FILESIZEBITS 00083 long file_size_bits; 00084 00085 /* 00086 * FIXME: also use getrlimit(RLIMIT_FSIZE) 00087 * 00088 * RLIMIT_FSIZE 00089 * The maximum size of files that the process may 00090 * create. Attempts to extend a file beyond this limit 00091 * result in delivery of a SIGXFSZ signal. By default, 00092 * this signal terminates a process, but a process can 00093 * catch this signal instead, in which case the relevant 00094 * system call (e.g., write(2), truncate(2)) fails with 00095 * the error EFBIG. 00096 */ 00097 file_size_bits = fpathconf(fildes, _PC_FILESIZEBITS); 00098 if 00099 ( 00100 file_size_bits > 0 00101 && 00102 (size_t)file_size_bits < 8 * sizeof(off_t) 00103 && 00104 length > (1LL << file_size_bits) 00105 ) 00106 { 00107 explain_string_buffer_printf 00108 ( 00109 sb, 00110 /* FIXME: i18n */ 00111 "'length' is larger than the maximum file size (2 ** %ld)", 00112 file_size_bits 00113 ); 00114 } 00115 else 00116 #endif 00117 { 00118 int flags; 00119 00120 /* FIXME: i18n */ 00121 flags = fcntl(fildes, F_GETFL); 00122 if (flags >= 0 && (flags & O_ACCMODE) == O_RDONLY) 00123 { 00124 explain_string_buffer_puts 00125 ( 00126 sb, 00127 "the file is not open for writing (" 00128 ); 00129 explain_buffer_open_flags(sb, flags); 00130 explain_string_buffer_putc(sb, ')'); 00131 } 00132 else 00133 { 00134 struct stat st; 00135 00136 if (fstat(fildes, &st) >= 0 && !S_ISREG(st.st_mode)) 00137 { 00138 explain_string_buffer_puts 00139 ( 00140 sb, 00141 "fildes refers to a " 00142 ); 00143 explain_buffer_file_type_st(sb, &st); 00144 explain_string_buffer_puts 00145 ( 00146 sb, 00147 ", it is only possible to truncate a " 00148 ); 00149 explain_buffer_file_type(sb, S_IFREG); 00150 } 00151 else 00152 { 00153 explain_string_buffer_puts 00154 ( 00155 sb, 00156 "the file is not open for writing; or, the file is " 00157 "not a " 00158 ); 00159 explain_buffer_file_type(sb, S_IFREG); 00160 } 00161 } 00162 } 00163 } 00164 break; 00165 00166 case EIO: 00167 explain_buffer_eio_fildes(sb, fildes); 00168 break; 00169 00170 case EISDIR: 00171 /* FIXME: i18n */ 00172 explain_string_buffer_puts 00173 ( 00174 sb, 00175 "fildes refers to a " 00176 ); 00177 explain_buffer_file_type(sb, S_IFDIR); 00178 explain_string_buffer_puts 00179 ( 00180 sb, 00181 ", it is only possible to truncate a " 00182 ); 00183 explain_buffer_file_type(sb, S_IFREG); 00184 break; 00185 00186 case EPERM: 00187 explain_string_buffer_puts 00188 ( 00189 sb, 00190 /* FIXME: i18n */ 00191 "the underlying file system does not support extending a " 00192 "file beyond its current size" 00193 ); 00194 explain_buffer_mount_point_fd(sb, fildes); 00195 break; 00196 00197 case EROFS: 00198 explain_buffer_erofs_fildes(sb, fildes, "fildes"); 00199 break; 00200 00201 case ETXTBSY: 00202 explain_buffer_etxtbsy_fildes(sb, fildes); 00203 break; 00204 00205 default: 00206 explain_buffer_errno_generic(sb, errnum, "ftruncate"); 00207 break; 00208 } 00209 } 00210 00211 00212 void 00213 explain_buffer_errno_ftruncate(explain_string_buffer_t *sb, int errnum, 00214 int fildes, off_t length) 00215 { 00216 explain_explanation_t exp; 00217 00218 explain_explanation_init(&exp, errnum); 00219 explain_buffer_errno_ftruncate_system_call 00220 ( 00221 &exp.system_call_sb, 00222 errnum, 00223 fildes, 00224 length 00225 ); 00226 explain_buffer_errno_ftruncate_explanation 00227 ( 00228 &exp.explanation_sb, 00229 errnum, 00230 fildes, 00231 length 00232 ); 00233 explain_explanation_assemble(&exp, sb); 00234 } 00235 00236 00237 /* vim: set ts=8 sw=4 et : */