Warning cleanups for kernel module build
[openafs.git] / src / comerr / error_msg.c
1 /*
2  * $Locker$
3  *
4  * Copyright 1987 by the Student Information Processing Board
5  * of the Massachusetts Institute of Technology
6  *
7  * For copyright info, see "mit-sipb-cr.h".
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #include "internal.h"
15 #include <stdio.h>
16 #include "error_table.h"
17 #include "mit-sipb-cr.h"
18 #include <afs/errors.h>
19 #include <afs/afsutil.h>
20 #include <string.h>
21 #include "com_err.h"
22
23 static const char copyright[] =
24     "Copyright 1986, 1987, 1988 by the Student Information Processing Board\nand the department of Information Systems\nof the Massachusetts Institute of Technology";
25
26 static char buffer[64];
27
28 static struct et_list *_et_list = (struct et_list *)NULL;
29
30 #ifdef AFS_PTHREAD_ENV
31 #include <pthread.h>
32 #include <assert.h>
33
34 /*
35  * This mutex protects the following variables:
36  * _et_list
37  */
38
39 static pthread_mutex_t et_list_mutex;
40 static int et_list_done = 0;
41 static pthread_once_t et_list_once = PTHREAD_ONCE_INIT;
42
43 /*
44  * Function to initialize the et_list_mutex
45  */
46
47 static void
48 et_mutex_once(void)
49 {
50     assert(!pthread_mutex_init
51            (&et_list_mutex, (const pthread_mutexattr_t *)0));
52     et_list_done = 1;
53 }
54
55 #define LOCK_ET_LIST \
56         do { \
57             (et_list_done || pthread_once(&et_list_once, et_mutex_once)); \
58             assert(pthread_mutex_lock(&et_list_mutex)==0); \
59         } while (0)
60 #define UNLOCK_ET_LIST assert(pthread_mutex_unlock(&et_list_mutex)==0)
61 #else
62 #define LOCK_ET_LIST
63 #define UNLOCK_ET_LIST
64 #endif /* AFS_PTHREAD_ENV */
65
66
67 static char *vmsgs[] = {
68     "volume needs to be salvaged",      /* 101, in Pittsburghese */
69     "no such entry (vnode)",    /* 102 */
70     "volume does not exist / did not salvage",  /* 103 */
71     "volume already exists",    /* 104 */
72     "volume out of service",    /* 105 */
73     "volume offline (utility running)", /* 106 */
74     "volume already online",    /* 107 */
75     "unknown volume error 108", /* 108 */
76     "unknown volume error 109", /* 109 */
77     "volume temporarily busy",  /* 110 */
78     "volume moved",             /* 111 */
79     (char *)0
80 };
81
82 static char *
83 negative_message(int code)
84 {
85     if (code == -1)
86         return "server or network not responding";
87     else if (code == -2)
88         return "invalid RPC (RX) operation";
89     else if (code == -3)
90         return "server not responding promptly";
91     else if (code == -7)
92         return "port address already in use";
93     else if (code <= -450 && code > -500) {
94         sprintf(buffer, "RPC interface mismatch (%d)", code);
95         return buffer;
96     } else {
97         sprintf(buffer, "unknown RPC error (%d)", code);
98         return buffer;
99     }
100 }
101
102 static char *
103 volume_message(int code)
104 {
105     if (code >= 101 && code <= 111)
106         return vmsgs[code - 101];
107     else
108         return "unknown volume error";
109 }
110
111 const char *
112 afs_error_message(afs_int32 code)
113 {
114     int offset;
115     struct et_list *et;
116     int table_num;
117     int started = 0;
118     char *cp;
119     char *err_msg;
120
121     /* check for rpc errors first */
122     if (code < 0)
123         return negative_message(code);
124
125     offset = code & ((1 << ERRCODE_RANGE) - 1);
126     table_num = code - offset;
127     if (!table_num) {
128         if ((err_msg = strerror(offset)) != NULL)
129             return (err_msg);
130         else if (offset < 140)
131             return volume_message(code);
132         else
133             goto oops;
134     }
135     LOCK_ET_LIST;
136     for (et = _et_list; et; et = et->next) {
137         if (et->table->base == table_num) {
138             /* This is the right table */
139             if (et->table->n_msgs <= offset)
140                 goto oops;
141             UNLOCK_ET_LIST;
142             return (et->table->msgs[offset]);
143         }
144     }
145   oops:
146     UNLOCK_ET_LIST;
147     strlcpy(buffer, "Unknown code ", sizeof buffer);
148     if (table_num) {
149         strlcat(buffer, afs_error_table_name(table_num), sizeof buffer);
150         strlcat(buffer, " ", sizeof buffer);
151     }
152     for (cp = buffer; *cp; cp++);
153     if (offset >= 100) {
154         *cp++ = '0' + offset / 100;
155         offset %= 100;
156         started++;
157     }
158     if (started || offset >= 10) {
159         *cp++ = '0' + offset / 10;
160         offset %= 10;
161     }
162     *cp++ = '0' + offset;
163     if (code > -10000)
164         sprintf(cp, " (%d)", code);
165     else
166         *cp = '\0';
167     return (buffer);
168 }
169
170 void
171 afs_add_to_error_table(struct et_list *new_table)
172 {
173     struct et_list *et;
174
175     LOCK_ET_LIST;
176     /*
177      * Protect against adding the same error table twice
178      */
179     for (et = _et_list; et; et = et->next) {
180         if (et->table->base == new_table->table->base) {
181             UNLOCK_ET_LIST;
182             return;
183         }
184     }
185
186     new_table->next = _et_list;
187     _et_list = new_table;
188     UNLOCK_ET_LIST;
189 }