libexplain  1.4.D001
libexplain/buffer/efbig.c
Go to the documentation of this file.
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 : */