]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mount/error.c
Fix more 'prototype' warnings and other warnings.
[nfs-utils.git] / utils / mount / error.c
1 /*
2  * error.c -- Common error handling functions
3  *
4  * Copyright (C) 2007 Oracle.  All rights reserved.
5  * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 021110-1307, USA.
21  *
22  * To Do:
23  *  + Proper support for internationalization
24  */
25
26 #include "config.h"
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <syslog.h>
34 #include <rpc/rpc.h>
35 #include <rpc/pmap_prot.h>
36 #include <rpc/pmap_clnt.h>
37
38 #include "xcommon.h"
39 #include "nls.h"
40 #include "mount.h"
41 #include "error.h"
42
43 #ifdef HAVE_RPCSVC_NFS_PROT_H
44 #include <rpcsvc/nfs_prot.h>
45 #else
46 #include <linux/nfs.h>
47 #define nfsstat nfs_stat
48 #endif
49
50 extern char *progname;
51
52 static char errbuf[BUFSIZ];
53 static char *erreob = &errbuf[BUFSIZ];
54
55 /* Convert RPC errors into strings */
56 static int rpc_strerror(int spos)
57 {
58         int cf_stat = rpc_createerr.cf_stat;
59         int pos = 0, cf_errno = rpc_createerr.cf_error.re_errno;
60         char *ptr, *estr = clnt_sperrno(cf_stat);
61         char *tmp;
62
63         if (estr) {
64                 if ((ptr = index(estr, ':')))
65                         estr = ++ptr;
66
67                 tmp = &errbuf[spos];
68                 if (cf_stat == RPC_SYSTEMERROR)
69                         pos = snprintf(tmp, (erreob - tmp),
70                                 "System Error: %s", strerror(cf_errno));
71                 else
72                         pos = snprintf(tmp, (erreob - tmp), "RPC Error:%s", estr);
73         }
74         return pos;
75 }
76
77 void mount_errors(char *server, int will_retry, int bg)
78 {
79         int pos = 0;
80         char *tmp;
81         static int onlyonce = 0;
82
83         tmp = &errbuf[pos];
84         if (bg)
85                 pos = snprintf(tmp, (erreob - tmp),
86                         "mount to NFS server '%s' failed: ", server);
87         else
88                 pos = snprintf(tmp, (erreob - tmp),
89                                "%s: mount to NFS server '%s' failed: ",
90                                progname, server);
91
92         tmp = &errbuf[pos];
93         if (rpc_createerr.cf_stat == RPC_TIMEDOUT) {
94                 pos = snprintf(tmp, (erreob - tmp), "timed out %s",
95                         will_retry ? "(retrying)" : "(giving up)");
96         } else {
97                 pos += rpc_strerror(pos);
98                 tmp = &errbuf[pos];
99                 if (bg) {
100                         pos = snprintf(tmp, (erreob - tmp), " %s",
101                                 will_retry ? "(retrying)" : "(giving up)");
102                 }
103         }
104         if (bg) {
105                 if (onlyonce++ < 1)
106                         openlog("mount", LOG_CONS|LOG_PID, LOG_AUTH);
107                 syslog(LOG_ERR, "%s.", errbuf);
108         } else
109                 fprintf(stderr, "%s.\n", errbuf);
110 }
111
112 void mount_error(const char *spec, const char *mount_point, int error)
113 {
114         switch(error) {
115         case ENOTDIR:
116                 nfs_error(_("%s: mount point %s is not a directory"),
117                                 progname, mount_point);
118                 break;
119         case EBUSY:
120                 nfs_error(_("%s: %s is already mounted or busy"),
121                         progname, mount_point);
122                 break;
123         case ENOENT:
124                 if (spec)
125                         nfs_error(_("%s: mounting %s failed, "
126                                 "reason given by server:\n  %s"),
127                                 progname, spec, strerror(error));
128                 else
129                         nfs_error(_("%s: mount point %s does not exist"),
130                                 progname, mount_point);
131                 break;
132         default:
133                 nfs_error(_("%s: %s"),
134                         progname, strerror(error));
135         }
136 }
137
138 /*
139  * Report a failed umount
140  */
141 void umount_error(int err, const char *dev)
142 {
143         switch (err) {
144         case ENXIO:
145                 nfs_error(_("%s: %s: invalid block device"),
146                         progname, dev);
147                 break;
148         case EINVAL:
149                 nfs_error(_("%s: %s: not mounted"),
150                         progname, dev);
151                 break;
152         case EIO:
153                 nfs_error(_("%s: %s: can't write superblock"),
154                         progname, dev);
155                 break;
156         case EBUSY:
157                 nfs_error(_("%s: %s: device is busy"),
158                         progname, dev);
159                 break;
160         case ENOENT:
161                 nfs_error(_("%s: %s: not found"),
162                         progname, dev);
163                 break;
164         case EPERM:
165                 nfs_error(_("%s: %s: must be superuser to umount"),
166                         progname, dev);
167                 break;
168         case EACCES:
169                 nfs_error(_("%s: %s: block devices not permitted on fs"),
170                         progname, dev);
171                 break;
172         default:
173                 nfs_error(_("%s: %s: %s"),
174                         progname, dev, strerror(err));
175                 break;
176         }
177 }
178
179 /*
180  * We need to translate between nfs status return values and
181  * the local errno values which may not be the same.
182  *
183  * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
184  * "after #include <errno.h> the symbol errno is reserved for any use,
185  *  it cannot even be used as a struct tag or field name".
186  */
187
188 #ifndef EDQUOT
189 #define EDQUOT  ENOSPC
190 #endif
191
192 static struct {
193         enum nfsstat stat;
194         int errnum;
195 } nfs_errtbl[] = {
196         { NFS_OK,               0               },
197         { NFSERR_PERM,          EPERM           },
198         { NFSERR_NOENT,         ENOENT          },
199         { NFSERR_IO,            EIO             },
200         { NFSERR_NXIO,          ENXIO           },
201         { NFSERR_ACCES,         EACCES          },
202         { NFSERR_EXIST,         EEXIST          },
203         { NFSERR_NODEV,         ENODEV          },
204         { NFSERR_NOTDIR,        ENOTDIR         },
205         { NFSERR_ISDIR,         EISDIR          },
206 #ifdef NFSERR_INVAL
207         { NFSERR_INVAL,         EINVAL          },      /* that Sun forgot */
208 #endif
209         { NFSERR_FBIG,          EFBIG           },
210         { NFSERR_NOSPC,         ENOSPC          },
211         { NFSERR_ROFS,          EROFS           },
212         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
213         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
214         { NFSERR_DQUOT,         EDQUOT          },
215         { NFSERR_STALE,         ESTALE          },
216 #ifdef EWFLUSH
217         { NFSERR_WFLUSH,        EWFLUSH         },
218 #endif
219         /* Throw in some NFSv3 values for even more fun (HP returns these) */
220         { 71,                   EREMOTE         },
221
222         { -1,                   EIO             }
223 };
224
225 char *nfs_strerror(int stat)
226 {
227         int i;
228         static char buf[256];
229
230         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
231                 if (nfs_errtbl[i].stat == stat)
232                         return strerror(nfs_errtbl[i].errnum);
233         }
234         sprintf(buf, _("unknown nfs status return value: %d"), stat);
235         return buf;
236 }