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