rx: Remove RX_CALL_BUSY
[openafs.git] / src / WINNT / afsreg / vptab.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Functions and definitions for accessing the vice partition table */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14 #include <afs/stds.h>
15
16 #include <roken.h>
17
18 #include <windows.h>
19
20 #include <afs/errmap_nt.h>
21
22 #include "afsreg.h"
23 #include "vptab.h"
24
25 #define PARTITION_NAME_PREFIX  "/vicep"
26
27
28 /*
29  * vpt_PartitionNameValid() -- Check partition name syntax.
30  *
31  * RETURN CODES: 1 valid, 0 not valid
32  */
33 int
34 vpt_PartitionNameValid(const char *vpname)
35 {
36     int rc = 0;
37
38     /* Only allowing full name, not any of the standard shorthands.
39      * Assumes C locale.
40      * NOTE: yet another incarnation of parsing code; should be consolidated.
41      */
42     if (!strncmp(vpname,
43                  PARTITION_NAME_PREFIX, sizeof(PARTITION_NAME_PREFIX) - 1)) {
44         /* prefix is correct; check suffix */
45         const char *vpsuffix = vpname + (sizeof(PARTITION_NAME_PREFIX) - 1);
46         size_t vpsuffixLen = strlen(vpsuffix);
47
48         if (vpsuffixLen == 1) {
49             /* must be 'a' - 'z' (0 .. 25) */
50             if (islower(vpsuffix[0])) {
51                 rc = 1;
52             }
53         } else if (vpsuffixLen == 2) {
54             /* must be 'aa' - 'zz' and in range (26 .. 255) */
55             if (islower(vpsuffix[0]) && islower(vpsuffix[1])) {
56                 int vpsuffixVal = ((vpsuffix[0] - 'a') * 26 +
57                                    (vpsuffix[1] - 'a') + 26);
58                 if (vpsuffixVal <= 255) {
59                     rc = 1;
60                 }
61             }
62         }
63     }
64     return rc;
65 }
66
67
68 /*
69  * vpt_DeviceNameValid() -- Check device name syntax.
70  *
71  * RETURN CODES: 1 valid, 0 not valid
72  */
73 int
74 vpt_DeviceNameValid(const char *devname)
75 {
76     /* assuming C locale */
77     if (isupper(devname[0]) && devname[1] == ':' && devname[2] == '\0') {
78         return 1;
79     } else {
80         return 0;
81     }
82 }
83
84
85 /*
86  * vpt_Start() -- Initialize iteration for reading vice partition table.
87  *
88  * RETURN CODES: 0 success, -1 failed (errno set)
89  */
90
91 int
92 vpt_Start(struct vpt_iter *iterp)  /* [out] iteration handle to initialize */
93 {
94     long status;
95     HKEY key;
96
97     memset(iterp, 0, sizeof(*iterp));
98
99     /* open canonical Afstab key */
100     status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY,
101                            KEY_READ, 0, &key, NULL);
102
103     if (status == ERROR_SUCCESS) {
104         /* enumerate subkeys, each of which represents a vice partition */
105         status = RegEnumKeyAlt(key, &iterp->vpenum);
106         (void)RegCloseKey(key);
107     }
108
109     if (status) {
110         errno = nterr_nt2unix(status, EIO);
111         return -1;
112     }
113     return 0;
114 }
115
116
117 /*
118  * vpt_NextEntry() -- Return next vice partition table entry.
119  *
120  * RETURN CODES: 0 success, -1 no more entries (ENOENT) or failed (errno set).
121  */
122
123 int
124 vpt_NextEntry(struct vpt_iter *iterp,   /* [in] valid iteration handle */
125               struct vptab *vptabp)    /* [out] next partiton table entry */
126 {
127     long status;
128     HKEY tabKey, vpKey;
129     char *nextNamep;
130
131     if (iterp->vpenum == NULL) {
132         /* no partition entries (or invalid iteration handle) */
133         errno = ENOENT;
134         return -1;
135     }
136
137     /* find name of next partition entry to examine in multistring enum */
138     if (iterp->last == NULL) {
139         /* first call */
140         nextNamep = iterp->last = iterp->vpenum;
141     } else {
142         /* subsequent call */
143         if (*iterp->last != '\0') {
144             /* not at end of multistring; advance to next name */
145             iterp->last += strlen(iterp->last) + 1;
146         }
147         nextNamep = iterp->last;
148     }
149
150     if (*nextNamep == '\0') {
151         /* end of multistring; no more entries */
152         errno = ENOENT;
153         return -1;
154     }
155
156     if (strlen(nextNamep) >= VPTABSIZE_NAME) {
157         /* invalid partition name entry */
158         errno = EINVAL;
159         return -1;
160     }
161     strcpy(vptabp->vp_name, nextNamep);
162
163     /* open canonical Afstab key */
164     status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY,
165                            KEY_READ, 0, &tabKey, NULL);
166
167     if (status == ERROR_SUCCESS) {
168         /* open key representing vice partition */
169         status = RegOpenKeyAlt(tabKey, nextNamep,
170                                KEY_READ, 0, &vpKey, NULL);
171
172         if (status == ERROR_SUCCESS) {
173             /* read partition attributes */
174             DWORD dataType, dataSize = VPTABSIZE_DEV;
175
176             status = RegQueryValueEx(vpKey,
177                                      AFSREG_SVR_SVC_AFSTAB_DEVNAME_VALUE,
178                                      NULL, &dataType, vptabp->vp_dev,
179                                      &dataSize);
180
181             if (status == ERROR_SUCCESS && dataType != REG_SZ) {
182                 /* invalid device name type */
183                 status = ERROR_INVALID_PARAMETER;
184             }
185             (void)RegCloseKey(vpKey);
186         }
187         (void)RegCloseKey(tabKey);
188     }
189
190     if (status) {
191         errno = nterr_nt2unix(status, EIO);
192         return -1;
193     }
194     return 0;
195 }
196
197
198 /*
199  * vpt_Finish() -- Terminate iteration for vice partition table.
200  *
201  * RETURN CODES: 0 success, -1 failed (errno set)
202  */
203 int
204 vpt_Finish(struct vpt_iter *iterp)    /* [in] iteration handle to terminate */
205 {
206     if (iterp->vpenum) {
207         free(iterp->vpenum);
208     }
209     memset(iterp, 0, sizeof(*iterp));
210     return 0;
211 }
212
213
214 /*
215  * vpt_AddEntry() -- Add or update vice partition table entry.
216  *
217  * RETURN CODES: 0 success, -1 failed (errno set)
218  */
219 int
220 vpt_AddEntry(const struct vptab *vptabp)
221 {
222     long status;
223     HKEY tabKey, vpKey;
224     const char *vpName, *vpDev;
225
226     vpName = vptabp->vp_name;
227     vpDev = vptabp->vp_dev;
228
229     if (!vpt_PartitionNameValid(vpName) || !vpt_DeviceNameValid(vpDev)) {
230         errno = EINVAL;
231         return -1;
232     }
233
234     /* open canonical Afstab key; create if doesn't exist */
235     status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY,
236                            KEY_WRITE, 1 /* create */, &tabKey, NULL);
237
238     if (status == ERROR_SUCCESS) {
239         /* open key representing vice partition; create if doesn't exist */
240         status = RegOpenKeyAlt(tabKey, vpName,
241                                KEY_WRITE, 1 /* create */, &vpKey, NULL);
242
243         if (status == ERROR_SUCCESS) {
244             /* write partition attributes */
245             status = RegSetValueEx(vpKey, AFSREG_SVR_SVC_AFSTAB_DEVNAME_VALUE,
246                                    0, REG_SZ, vpDev, (DWORD)strlen(vpDev) + 1);
247
248             RegCloseKey(vpKey);
249         }
250
251         RegCloseKey(tabKey);
252     }
253
254     if (status) {
255         errno = nterr_nt2unix(status, EIO);
256         return -1;
257     }
258     return 0;
259 }
260
261
262 /*
263  * vpt_RemoveEntry() -- Remove vice partition table entry.
264  *
265  * RETURN CODES: 0 success, -1 failed (errno set)
266  */
267 int
268 vpt_RemoveEntry(const char *vpname)
269 {
270     long status;
271     HKEY tabKey;
272
273     if (!vpt_PartitionNameValid(vpname)) {
274         errno = EINVAL;
275         return -1;
276     }
277
278     /* open canonical Afstab key */
279     status = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_SVR_SVC_AFSTAB_KEY,
280                            KEY_WRITE, 0, &tabKey, NULL);
281
282     if (status == ERROR_SUCCESS) {
283         /* delete key representing vice partition */
284         status = RegDeleteKey(tabKey, vpname);
285     }
286
287     if (status) {
288         errno = nterr_nt2unix(status, EIO);
289         return -1;
290     }
291     return 0;
292 }