libexplain  1.4.D001
libexplain/buffer/errno/symlink.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  * 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 published by
00008  * the Free Software Foundation; either version 3 of the License, or (at
00009  * 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/limits.h> /* for PATH_MAX on Solaris */
00022 #include <libexplain/ac/string.h>
00023 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */
00024 #include <libexplain/ac/sys/stat.h>
00025 #include <libexplain/ac/unistd.h>
00026 
00027 #include <libexplain/buffer/eacces.h>
00028 #include <libexplain/buffer/eexist.h>
00029 #include <libexplain/buffer/efault.h>
00030 #include <libexplain/buffer/eio.h>
00031 #include <libexplain/buffer/eloop.h>
00032 #include <libexplain/buffer/enametoolong.h>
00033 #include <libexplain/buffer/enoent.h>
00034 #include <libexplain/buffer/enomem.h>
00035 #include <libexplain/buffer/enospc.h>
00036 #include <libexplain/buffer/enotdir.h>
00037 #include <libexplain/buffer/erofs.h>
00038 #include <libexplain/buffer/errno/generic.h>
00039 #include <libexplain/buffer/errno/path_resolution.h>
00040 #include <libexplain/buffer/errno/symlink.h>
00041 #include <libexplain/buffer/file_type.h>
00042 #include <libexplain/buffer/mount_point.h>
00043 #include <libexplain/buffer/pathname.h>
00044 #include <libexplain/explanation.h>
00045 #include <libexplain/is_efault.h>
00046 #include <libexplain/string_buffer.h>
00047 
00048 
00049 static void
00050 explain_buffer_errno_symlink_system_call(explain_string_buffer_t *sb,
00051     int errnum, const char *oldpath, const char *newpath)
00052 {
00053     (void)errnum;
00054     explain_string_buffer_printf(sb, "symlink(oldpath = ");
00055     explain_buffer_pathname(sb, oldpath);
00056     explain_string_buffer_puts(sb, ", newpath = ");
00057     explain_buffer_pathname(sb, newpath);
00058     explain_string_buffer_putc(sb, ')');
00059 }
00060 
00061 
00062 static void
00063 explain_buffer_errno_symlink_explanation(explain_string_buffer_t *sb,
00064     int errnum, const char *oldpath, const char *newpath)
00065 {
00066     explain_final_t final_component;
00067 
00068     explain_final_init(&final_component);
00069     final_component.must_exist = 0;
00070     final_component.must_not_exist = 1;
00071     final_component.want_to_create = 1;
00072     final_component.st_mode = S_IFLNK;
00073 
00074     switch (errnum)
00075     {
00076     case EACCES:
00077         explain_buffer_eacces(sb, newpath, "newpath", &final_component);
00078         break;
00079 
00080     case EEXIST:
00081         explain_buffer_eexist(sb, newpath);
00082         break;
00083 
00084     case EFAULT:
00085         if (explain_is_efault_path(oldpath))
00086         {
00087             explain_buffer_efault(sb, "oldpath");
00088             break;
00089         }
00090         if (explain_is_efault_path(newpath))
00091         {
00092             explain_buffer_efault(sb, "newpath");
00093             break;
00094         }
00095         explain_buffer_efault(sb, "oldpath or newpath");
00096         break;
00097 
00098     case EIO:
00099         explain_buffer_eio_path_dirname(sb, newpath);
00100         break;
00101 
00102     case ELOOP:
00103     case EMLINK: /* BSD */
00104         explain_buffer_eloop(sb, newpath, "newpath", &final_component);
00105         break;
00106 
00107     case ENAMETOOLONG:
00108         {
00109             size_t          oldpath_len;
00110             long            path_max;
00111 
00112             oldpath_len = strlen(oldpath);
00113             path_max = pathconf(newpath, _PC_PATH_MAX);
00114             if (path_max <= 0)
00115                 path_max = PATH_MAX;
00116             if (oldpath_len > (size_t)path_max)
00117             {
00118                 /* FIXME: i18n */
00119                 explain_string_buffer_puts(sb, "oldpath is too long");
00120                 explain_string_buffer_printf
00121                 (
00122                     sb,
00123                     " (%ld > %ld)",
00124                     (long)oldpath_len,
00125                     path_max
00126                 );
00127             }
00128             else
00129             {
00130                 explain_buffer_enametoolong
00131                 (
00132                     sb,
00133                     newpath,
00134                     "newpath",
00135                     &final_component
00136                 );
00137             }
00138         }
00139         break;
00140 
00141     case ENOENT:
00142         if (!*oldpath)
00143         {
00144             explain_string_buffer_puts
00145             (
00146                 sb,
00147                 /* FIXME: i18n */
00148                 "oldpath is the empty string; if you meant the current "
00149                 "directory, use \".\" instead"
00150             );
00151             break;
00152         }
00153         explain_buffer_enoent(sb, newpath, "newpath", &final_component);
00154         break;
00155 
00156     case ENOMEM:
00157         explain_buffer_enomem_kernel(sb);
00158         break;
00159 
00160     case ENOSPC:
00161         explain_buffer_enospc(sb, newpath, "newpath");
00162         break;
00163 
00164     case ENOTDIR:
00165         explain_buffer_enotdir(sb, newpath, "newpath", &final_component);
00166         break;
00167 
00168     case EPERM:
00169         /* FIXME: i18n */
00170         explain_string_buffer_puts
00171         (
00172             sb,
00173             "the file system containing newpath"
00174         );
00175         explain_buffer_mount_point_dirname(sb, newpath);
00176         explain_string_buffer_puts
00177         (
00178             sb,
00179             " does not support the creation of symbolic links"
00180         );
00181         break;
00182 
00183     case EROFS:
00184         explain_buffer_erofs(sb, newpath, "newpath");
00185         break;
00186 
00187     default:
00188         explain_buffer_errno_generic(sb, errnum, "symlink");
00189         break;
00190     }
00191 }
00192 
00193 
00194 void
00195 explain_buffer_errno_symlink(explain_string_buffer_t *sb, int errnum,
00196     const char *oldpath, const char *newpath)
00197 {
00198     explain_explanation_t exp;
00199 
00200     explain_explanation_init(&exp, errnum);
00201     explain_buffer_errno_symlink_system_call
00202     (
00203         &exp.system_call_sb,
00204         errnum,
00205         oldpath,
00206         newpath
00207     );
00208     explain_buffer_errno_symlink_explanation
00209     (
00210         &exp.explanation_sb,
00211         errnum,
00212         oldpath,
00213         newpath
00214     );
00215     explain_explanation_assemble(&exp, sb);
00216 }
00217 
00218 
00219 /* vim: set ts=8 sw=4 et : */