libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008, 2009, 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/limits.h> 00021 #include <libexplain/ac/sys/resource.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/efbig.h> 00025 #include <libexplain/buffer/gettext.h> 00026 #include <libexplain/buffer/pretty_size.h> 00027 #include <libexplain/option.h> 00028 00029 00030 static unsigned long long 00031 get_max_file_size(int file_size_bits) 00032 { 00033 int long_long_bits; 00034 struct rlimit szlim; 00035 unsigned long long max_file_size; 00036 00037 long_long_bits = sizeof(unsigned long long) * CHAR_BIT; 00038 if (file_size_bits > long_long_bits || file_size_bits <= 0) 00039 file_size_bits = long_long_bits; 00040 if (file_size_bits >= long_long_bits) 00041 max_file_size = ~(unsigned long long)0; 00042 else 00043 max_file_size = (unsigned long long)1 << file_size_bits; 00044 if (getrlimit(RLIMIT_FSIZE, &szlim) < 0 || szlim.rlim_cur == RLIM_INFINITY) 00045 return max_file_size; 00046 if ((unsigned long long)szlim.rlim_cur < max_file_size) 00047 max_file_size = szlim.rlim_cur; 00048 return max_file_size; 00049 } 00050 00051 00052 unsigned long long 00053 explain_get_max_file_size_by_pathname(const char *pathname) 00054 { 00055 long nbits; 00056 00057 #ifdef _PC_FILESIZEBITS 00058 nbits = pathconf(pathname, _PC_FILESIZEBITS); 00059 #else 00060 (void)pathname; 00061 nbits = sizeof(off_t) * CHAR_BIT; 00062 #endif 00063 return get_max_file_size(nbits); 00064 } 00065 00066 00067 static void 00068 report_error(explain_string_buffer_t *sb, const char *caption, 00069 unsigned long long actual, unsigned long long maximum) 00070 { 00071 explain_string_buffer_printf_gettext 00072 ( 00073 sb, 00074 /* 00075 * xgettext: This message is used when a path given in a path is 00076 * larger that the (dialect specific) maximum path length. 00077 * 00078 * %1$s => the name of the offending system call argument. 00079 */ 00080 i18n("%s is larger than the maximum file size"), 00081 caption 00082 ); 00083 00084 if (explain_option_dialect_specific()) 00085 { 00086 explain_string_buffer_puts(sb, " ("); 00087 explain_buffer_pretty_size(sb, actual); 00088 explain_string_buffer_puts(sb, " > "); 00089 explain_buffer_pretty_size(sb, maximum); 00090 explain_string_buffer_putc(sb, ')'); 00091 } 00092 } 00093 00094 00095 void 00096 explain_buffer_efbig(explain_string_buffer_t *sb, const char *pathname, 00097 unsigned long long length, const char *length_caption) 00098 { 00099 unsigned long long maximum; 00100 00101 maximum = explain_get_max_file_size_by_pathname(pathname); 00102 report_error(sb, length_caption, length, maximum); 00103 } 00104 00105 00106 unsigned long long 00107 explain_get_max_file_size_by_fildes(int fildes) 00108 { 00109 long nbits; 00110 00111 #ifdef _PC_FILESIZEBITS 00112 nbits = fpathconf(fildes, _PC_FILESIZEBITS); 00113 #else 00114 (void)fildes; 00115 nbits = sizeof(off_t) * CHAR_BIT; 00116 #endif 00117 return get_max_file_size(nbits); 00118 } 00119 00120 00121 void 00122 explain_buffer_efbig_fildes(explain_string_buffer_t *sb, int fildes, 00123 unsigned long long length, const char *length_caption) 00124 { 00125 unsigned long long maximum; 00126 00127 maximum = explain_get_max_file_size_by_fildes(fildes); 00128 report_error(sb, length_caption, length, maximum); 00129 } 00130 00131 00132 /* vim: set ts=8 sw=4 et : */