libexplain  1.4.D001
libexplain/buffer/errno/gethostname.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2009, 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/stdlib.h>
00021 #include <libexplain/ac/string.h>
00022 #include <libexplain/ac/unistd.h>
00023 
00024 #include <libexplain/buffer/efault.h>
00025 #include <libexplain/buffer/einval.h>
00026 #include <libexplain/buffer/enametoolong.h>
00027 #include <libexplain/buffer/enosys.h>
00028 #include <libexplain/buffer/errno/generic.h>
00029 #include <libexplain/buffer/errno/gethostname.h>
00030 #include <libexplain/buffer/is_the_null_pointer.h>
00031 #include <libexplain/buffer/pointer.h>
00032 #include <libexplain/buffer/size_t.h>
00033 #include <libexplain/buffer/software_error.h>
00034 #include <libexplain/explanation.h>
00035 #include <libexplain/host_name_max.h>
00036 
00037 
00038 static void
00039 explain_buffer_errno_gethostname_system_call(explain_string_buffer_t *sb,
00040     int errnum, char *data, size_t data_size)
00041 {
00042     (void)errnum;
00043     explain_string_buffer_puts(sb, "gethostname(data = ");
00044     explain_buffer_pointer(sb, data);
00045     explain_string_buffer_puts(sb, ", data_size = ");
00046     explain_buffer_size_t(sb, data_size);
00047     explain_string_buffer_putc(sb, ')');
00048 }
00049 
00050 
00051 static size_t
00052 get_actual_hostname_size(void)
00053 {
00054 #ifdef HAVE_GETHOSTNAME
00055     size_t name_size = explain_get_host_name_max();
00056     char *name = malloc(name_size + 1);
00057     if (name)
00058     {
00059         if (gethostname(name, name_size) == 0)
00060         {
00061             size_t          result;
00062 
00063             /* paranoia */
00064             name[name_size] = '\0';
00065 
00066             result = strlen(name);
00067             free(name);
00068             return result;
00069         }
00070         free(name);
00071     }
00072 #endif
00073 
00074     /*
00075      * no idea what the length is
00076      */
00077     return 0;
00078 }
00079 
00080 
00081 static void
00082 explain_buffer_errno_gethostname_explanation(explain_string_buffer_t *sb,
00083     int errnum, char *data, size_t data_size)
00084 {
00085     /*
00086      * http://www.opengroup.org/onlinepubs/009695399/functions/gethostname.html
00087      */
00088     (void)data;
00089     switch (errnum)
00090     {
00091     case EFAULT:
00092         explain_buffer_efault(sb, "data");
00093         break;
00094 
00095     case EINVAL:
00096         if (data && data_size + 1 < get_actual_hostname_size())
00097         {
00098           /* OSX/Darwin does this when the buffer is not large enough */
00099           goto bad_size;
00100         }
00101 
00102         if (!data)
00103         {
00104             explain_buffer_is_the_null_pointer(sb, "data");
00105             break;
00106         }
00107         if ((int)data_size <= 0)
00108         {
00109             explain_buffer_einval_too_small(sb, "data_size", data_size);
00110             break;
00111         }
00112         /* fall through... */
00113 
00114     case ENAMETOOLONG:
00115         /* data_size is smaller than the actual size.  */
00116         {
00117             size_t actual_size;
00118             bad_size:
00119             /* OSX/Darwin does this when the buffer is not large enough */
00120             actual_size = get_actual_hostname_size();
00121             if (actual_size > 0 && data_size < actual_size + 1)
00122             {
00123                 explain_buffer_enametoolong_gethostname
00124                 (
00125                     sb,
00126                     actual_size,
00127                     "data_size"
00128                 );
00129             }
00130             else
00131             {
00132                 explain_buffer_einval_too_small(sb, "data_size", data_size);
00133             }
00134             explain_buffer_software_error(sb);
00135         }
00136         break;
00137 
00138     case ENOSYS:
00139         explain_buffer_enosys_vague(sb, "gethostname");
00140         break;
00141 
00142     default:
00143         explain_buffer_errno_generic(sb, errnum, "gethostname");
00144         break;
00145     }
00146 }
00147 
00148 
00149 void
00150 explain_buffer_errno_gethostname(explain_string_buffer_t *sb, int errnum,
00151     char *data, size_t data_size)
00152 {
00153     explain_explanation_t exp;
00154 
00155     explain_explanation_init(&exp, errnum);
00156     explain_buffer_errno_gethostname_system_call
00157     (
00158         &exp.system_call_sb,
00159         errnum,
00160         data,
00161         data_size
00162     );
00163     explain_buffer_errno_gethostname_explanation
00164     (
00165         &exp.explanation_sb,
00166         errnum,
00167         data,
00168         data_size
00169     );
00170     explain_explanation_assemble(&exp, sb);
00171 }
00172 
00173 /* vim: set ts=8 sw=4 et : */