libexplain  1.4.D001
libexplain/buffer/errno/truncate.c
Go to the documentation of this file.
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/unistd.h>
00021 #include <libexplain/ac/sys/stat.h>
00022 
00023 #include <libexplain/buffer/eacces.h>
00024 #include <libexplain/buffer/efault.h>
00025 #include <libexplain/buffer/efbig.h>
00026 #include <libexplain/buffer/eintr.h>
00027 #include <libexplain/buffer/eio.h>
00028 #include <libexplain/buffer/eloop.h>
00029 #include <libexplain/buffer/enametoolong.h>
00030 #include <libexplain/buffer/enoent.h>
00031 #include <libexplain/buffer/enotdir.h>
00032 #include <libexplain/buffer/erofs.h>
00033 #include <libexplain/buffer/errno/generic.h>
00034 #include <libexplain/buffer/errno/path_resolution.h>
00035 #include <libexplain/buffer/errno/truncate.h>
00036 #include <libexplain/buffer/etxtbsy.h>
00037 #include <libexplain/buffer/file_type.h>
00038 #include <libexplain/buffer/mount_point.h>
00039 #include <libexplain/buffer/off_t.h>
00040 #include <libexplain/buffer/pathname.h>
00041 #include <libexplain/explanation.h>
00042 #include <libexplain/option.h>
00043 
00044 
00045 static void
00046 explain_buffer_errno_truncate_system_call(explain_string_buffer_t *sb,
00047     int errnum, const char *pathname, off_t length)
00048 {
00049     (void)errnum;
00050     explain_string_buffer_puts(sb, "truncate(pathname = ");
00051     explain_buffer_pathname(sb, pathname);
00052     explain_string_buffer_puts(sb, ", length = ");
00053     explain_buffer_off_t(sb, length);
00054     explain_string_buffer_putc(sb, ')');
00055 }
00056 
00057 
00058 static void
00059 explain_buffer_errno_truncate_explanation(explain_string_buffer_t *sb,
00060     int errnum, const char *syscall_name, const char *pathname, off_t length)
00061 {
00062     explain_final_t final_component;
00063 
00064     explain_final_init(&final_component);
00065     final_component.want_to_write = 1;
00066 
00067     switch (errnum)
00068     {
00069     case EACCES:
00070         explain_buffer_eacces(sb, pathname, "pathname", &final_component);
00071         break;
00072 
00073     case EFAULT:
00074         explain_buffer_efault(sb, "pathname");
00075         break;
00076 
00077     case EFBIG:
00078         explain_buffer_efbig(sb, pathname, length, "length");
00079         break;
00080 
00081     case EINTR:
00082         explain_buffer_eintr(sb, syscall_name);
00083         break;
00084 
00085     case EINVAL:
00086         if (length < 0)
00087         {
00088             /* FIXME: i18n */
00089             explain_string_buffer_puts(sb, "length is negative");
00090             break;
00091         }
00092 
00093         {
00094             struct stat     st;
00095 
00096             /* FIXME: explain_buffer_wrong_file_type */
00097             if (stat(pathname, &st) >= 0 && !S_ISREG(st.st_mode))
00098             {
00099                 explain_string_buffer_puts(sb, "pathname is a ");
00100                 explain_buffer_file_type_st(sb, &st);
00101                 explain_string_buffer_puts(sb, ", not a ");
00102                 explain_buffer_file_type(sb, S_IFREG);
00103                 break;
00104             }
00105         }
00106 
00107         explain_buffer_efbig(sb, pathname, length, "length");
00108         break;
00109 
00110     case EIO:
00111         explain_buffer_eio_path(sb, pathname);
00112         break;
00113 
00114     case EISDIR:
00115         explain_string_buffer_puts
00116         (
00117             sb,
00118             /*
00119              * xgettext:  This message is used to explain an EISDIR error
00120              * reported by the truncate(2) system call, in the case where the
00121              * named file is a directory.
00122              */
00123             i18n("the named file is a directory; directories may not be "
00124             "truncated, use rmdir(2) or remove(3) instead")
00125         );
00126         break;
00127 
00128     case ELOOP:
00129     case EMLINK: /* BSD */
00130         explain_buffer_eloop(sb, pathname, "pathname", &final_component);
00131         break;
00132 
00133     case ENAMETOOLONG:
00134         explain_buffer_enametoolong
00135         (
00136             sb,
00137             pathname,
00138             "pathname",
00139             &final_component
00140         );
00141         break;
00142 
00143     case ENOENT:
00144         explain_buffer_enoent(sb, pathname, "pathname", &final_component);
00145         break;
00146 
00147     case ENOTDIR:
00148         explain_buffer_enotdir(sb, pathname, "pathname", &final_component);
00149         break;
00150 
00151     case EPERM:
00152         explain_string_buffer_puts
00153         (
00154             sb,
00155             /* FIXME: i18n */
00156             "the underlying file system does not support extending a "
00157             "file beyond its current size"
00158         );
00159         explain_buffer_mount_point(sb, pathname);
00160         break;
00161 
00162     case EROFS:
00163         explain_buffer_erofs(sb, pathname, "pathname");
00164         break;
00165 
00166     case ETXTBSY:
00167         explain_buffer_etxtbsy(sb, pathname);
00168         break;
00169 
00170     default:
00171         explain_buffer_errno_generic(sb, errnum, syscall_name);
00172         break;
00173     }
00174 }
00175 
00176 
00177 void
00178 explain_buffer_errno_truncate(explain_string_buffer_t *sb, int errnum,
00179     const char *pathname, off_t length)
00180 {
00181     explain_explanation_t exp;
00182 
00183     explain_explanation_init(&exp, errnum);
00184     explain_buffer_errno_truncate_system_call
00185     (
00186         &exp.system_call_sb,
00187         errnum,
00188         pathname,
00189         length
00190     );
00191     explain_buffer_errno_truncate_explanation
00192     (
00193         &exp.explanation_sb,
00194         errnum,
00195         "truncate",
00196         pathname,
00197         length
00198     );
00199     explain_explanation_assemble(&exp, sb);
00200 }
00201 
00202 
00203 /* vim: set ts=8 sw=4 et : */