2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
22 #define STRSAFE_NO_DEPRECATE
29 #include <afs/unified_afs.h>
31 static osi_once_t cm_utilsOnce;
33 osi_rwlock_t cm_utilsLock;
35 cm_space_t *cm_spaceListp;
37 static int et2sys[512];
39 static DWORD cm_TlsRequestSlot = -1;
41 void cm_utilsInit(void)
43 if (osi_Once(&cm_utilsOnce)) {
44 lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock", LOCK_HIERARCHY_UTILS_GLOBAL);
46 cm_TlsRequestSlot = TlsAlloc();
48 osi_EndOnce(&cm_utilsOnce);
52 void cm_utilsCleanup(void)
54 TlsFree(cm_TlsRequestSlot);
58 init_et_to_sys_error(void)
60 memset(&et2sys, 0, sizeof(et2sys));
61 et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
62 et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
63 et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
64 et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
65 et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
66 et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
67 et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
68 et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
69 et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
70 et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
71 et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
72 et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
73 et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
74 et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
75 et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
76 et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
77 et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
78 et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
79 et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
80 et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
81 et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
82 et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
83 et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
84 et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
85 et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
86 et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
87 et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
88 et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
89 et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
90 et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
91 et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
92 et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
93 et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
94 et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
95 et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
96 et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
97 et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
98 et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
99 et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
100 et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
101 et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
102 et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
103 et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
104 et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
105 et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
106 et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
107 et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
108 et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
109 et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
110 et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
111 et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
112 et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
113 et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
114 et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
115 et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
116 et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
117 et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
118 et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
119 et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
120 et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
121 et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
122 et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
123 et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
124 et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
125 et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
126 et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
127 et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
128 et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
129 et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
130 et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
131 et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
132 et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
133 et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
134 et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
135 et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
136 et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
137 et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
138 et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
139 et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
140 et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
141 et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
142 et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
143 et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
144 et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
145 et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
146 et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
147 et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
148 et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
149 et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
150 et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
151 et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
152 et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
153 et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
154 et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
155 et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
156 et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
157 et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
158 et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
159 et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
160 et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
161 et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
162 et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
163 et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
164 et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
165 et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
166 et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
167 et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
168 et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
169 et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
170 et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
171 et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
172 et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
173 et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
174 et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
175 et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
176 et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
177 et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
178 et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
179 et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
180 et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
181 et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
182 et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
183 et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
187 et_to_sys_error(afs_int32 in)
189 if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
191 if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
192 return et2sys[in - ERROR_TABLE_BASE_uae];
196 long cm_MapRPCError(long error, cm_req_t *reqp)
201 /* If we had to stop retrying, report our saved error code. */
202 if (reqp && error == CM_ERROR_TIMEDOUT) {
203 if (reqp->accessError)
204 return reqp->accessError;
205 if (reqp->volumeError)
206 return reqp->volumeError;
208 return reqp->rpcError;
212 error = et_to_sys_error(error);
214 if (error == RX_CALL_DEAD ||
215 error == RX_CALL_TIMEOUT ||
216 error == RX_CALL_BUSY ||
217 error == RX_MSGSIZE ||
219 error = CM_ERROR_TIMEDOUT;
220 else if (error == RX_INVALID_OPERATION)
221 error = CM_ERROR_INVAL_NET_RESP;
223 error = CM_ERROR_UNKNOWN;
224 else if (error == EINVAL)
225 error = CM_ERROR_INVAL;
226 else if (error == EROFS)
227 error = CM_ERROR_READONLY;
228 else if (error == EACCES)
229 error = CM_ERROR_NOACCESS;
230 else if (error == EXDEV)
231 error = CM_ERROR_CROSSDEVLINK;
232 else if (error == EEXIST)
233 error = CM_ERROR_EXISTS;
234 else if (error == ENOTDIR)
235 error = CM_ERROR_NOTDIR;
236 else if (error == ENOENT)
237 error = CM_ERROR_NOSUCHFILE;
238 else if (error == EAGAIN
239 || error == 35 /* EAGAIN, Digital UNIX */
240 || error == WSAEWOULDBLOCK)
241 error = CM_ERROR_WOULDBLOCK;
242 else if (error == VDISKFULL
244 error = CM_ERROR_SPACE;
245 else if (error == VOVERQUOTA
247 || error == 49 /* EDQUOT on Solaris */
248 || error == 88 /* EDQUOT on AIX */
249 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
250 || error == 122 /* EDQUOT on Linux */
251 || error == 1133) /* EDQUOT on Irix */
252 error = CM_ERROR_QUOTA;
253 else if (error == VNOVNODE)
254 error = CM_ERROR_BADFD;
255 else if (error == VSALVAGE || error == VOFFLINE)
256 error = CM_ERROR_ALLOFFLINE;
257 else if (error == VBUSY || error == VRESTARTING)
258 error = CM_ERROR_ALLBUSY;
259 else if (error == EISDIR)
260 return CM_ERROR_ISDIR;
264 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
269 /* If we had to stop retrying, report our saved error code. */
270 if (reqp && error == CM_ERROR_TIMEDOUT) {
271 if (reqp->accessError)
272 return reqp->accessError;
273 if (reqp->volumeError)
274 return reqp->volumeError;
276 return reqp->rpcError;
280 error = et_to_sys_error(error);
282 if (error == RX_CALL_DEAD ||
283 error == RX_CALL_TIMEOUT ||
284 error == RX_CALL_BUSY ||
285 error == RX_MSGSIZE ||
287 error = CM_ERROR_TIMEDOUT;
288 else if (error == VNOVNODE)
289 error = CM_ERROR_BADFD;
290 else if (error == VSALVAGE || error == VOFFLINE)
291 error = CM_ERROR_ALLOFFLINE;
292 else if (error == VBUSY || error == VRESTARTING)
293 error = CM_ERROR_ALLBUSY;
294 else if (error == RX_INVALID_OPERATION)
295 error = CM_ERROR_INVAL_NET_RESP;
297 error = CM_ERROR_UNKNOWN;
298 else if (error == EROFS)
299 error = CM_ERROR_READONLY;
300 else if (error == ENOTDIR)
301 error = CM_ERROR_NOTDIR;
302 else if (error == EACCES)
303 error = CM_ERROR_NOACCESS;
304 else if (error == ENOENT)
305 error = CM_ERROR_NOSUCHFILE;
306 else if (error == EINVAL)
307 error = CM_ERROR_INVAL;
308 else if (error == ENOTEMPTY
310 || error == 17 /* AIX */
311 || error == 66 /* SunOS 4, Digital UNIX */
312 || error == 93 /* Solaris 2, IRIX */
313 || error == 247) /* HP/UX */
314 error = CM_ERROR_NOTEMPTY;
318 long cm_MapVLRPCError(long error, cm_req_t *reqp)
320 if (error == 0) return 0;
322 /* If we had to stop retrying, report our saved error code. */
323 if (reqp && error == CM_ERROR_TIMEDOUT) {
324 if (reqp->accessError)
325 return reqp->accessError;
326 if (reqp->volumeError)
327 return reqp->volumeError;
329 return reqp->rpcError;
333 error = et_to_sys_error(error);
335 if (error == RX_CALL_DEAD ||
336 error == RX_CALL_TIMEOUT ||
337 error == RX_CALL_BUSY ||
338 error == RX_MSGSIZE ||
340 error = CM_ERROR_TIMEDOUT;
341 else if (error == RX_INVALID_OPERATION)
342 error = CM_ERROR_INVAL_NET_RESP;
343 else if (error == RX_RESTARTING)
344 error = CM_ERROR_ALLBUSY;
346 error = CM_ERROR_UNKNOWN;
347 else if (error == EINVAL)
348 error = CM_ERROR_INVAL;
349 else if (error == VL_NOENT || error == VL_BADNAME)
350 error = CM_ERROR_NOSUCHVOLUME;
354 cm_space_t *cm_GetSpace(void)
360 lock_ObtainWrite(&cm_utilsLock);
361 if (tsp = cm_spaceListp) {
362 cm_spaceListp = tsp->nextp;
364 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
365 (void) memset(tsp, 0, sizeof(cm_space_t));
366 lock_ReleaseWrite(&cm_utilsLock);
371 void cm_FreeSpace(cm_space_t *tsp)
373 lock_ObtainWrite(&cm_utilsLock);
374 tsp->nextp = cm_spaceListp;
376 lock_ReleaseWrite(&cm_utilsLock);
379 /* characters that are legal in an 8.3 name */
381 * We used to have 1's for all characters from 128 to 254. But
382 * the NT client behaves better if we create an 8.3 name for any
383 * name that has a character with the high bit on, and if we
384 * delete those characters from 8.3 names. In particular, see
385 * Sybase defect 10859.
387 char cm_LegalChars[256] = {
388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
390 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
391 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
406 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
408 /* return true iff component is a valid 8.3 name */
409 int cm_Is8Dot3(clientchar_t *namep)
415 if (namep == NULL || !namep[0])
419 * can't have a leading dot;
420 * special case for . and ..
422 if (namep[0] == '.') {
425 if (namep[1] == '.' && namep[2] == 0)
429 while (tc = *namep++) {
431 /* saw another dot */
432 if (sawDot) return 0; /* second dot */
437 if (!ISLEGALCHAR(tc))
440 if (!sawDot && charCount > 8)
441 /* more than 8 chars in name */
443 if (sawDot && charCount > 3)
444 /* more than 3 chars in extension */
451 * Number unparsing map for generating 8.3 names;
452 * The version taken from DFS was on drugs.
453 * You can't include '&' and '@' in a file name.
455 char cm_8Dot3Mapping[42] =
456 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
457 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
458 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
459 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
461 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
463 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
464 clientchar_t *shortName, clientchar_t **shortNameEndp)
468 int vnode = ntohl(pfid->vnode);
470 int validExtension = 0;
474 /* Unparse the file's vnode number to get a "uniquifier" */
476 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
478 vnode /= cm_8Dot3MapSize;
482 * Look for valid extension. There has to be a dot, and
483 * at least one of the characters following has to be legal.
485 lastDot = strrchr(longname, '.');
487 temp = lastDot; temp++;
495 /* Copy name characters */
496 for (i = 0, name = longname;
497 i < (7 - nsize) && name != lastDot; ) {
502 if (!ISLEGALCHAR(tc))
505 *shortName++ = toupper(tc);
511 /* Copy uniquifier characters */
512 for (i=0; i < nsize; i++) {
513 *shortName++ = number[i];
516 if (validExtension) {
517 /* Copy extension characters */
518 *shortName++ = *lastDot++; /* copy dot */
519 for (i = 0, tc = *lastDot++;
522 if (ISLEGALCHAR(tc)) {
524 *shortName++ = toupper(tc);
533 *shortNameEndp = shortName;
536 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
537 clientchar_t *shortName, clientchar_t **shortNameEndp)
539 clientchar_t number[12];
541 int vnode = ntohl(pfid->vnode);
542 clientchar_t *lastDot;
543 int validExtension = 0;
544 clientchar_t tc, *temp;
545 const clientchar_t *name;
547 /* Unparse the file's vnode number to get a "uniquifier" */
549 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
551 vnode /= cm_8Dot3MapSize;
555 * Look for valid extension. There has to be a dot, and
556 * at least one of the characters following has to be legal.
558 lastDot = cm_ClientStrRChr(longname, '.');
560 temp = lastDot; temp++;
568 /* Copy name characters */
569 for (i = 0, name = longname;
570 i < (7 - nsize) && name != lastDot; ) {
575 if (!ISLEGALCHAR(tc))
578 *shortName++ = toupper((char) tc);
584 /* Copy uniquifier characters */
585 for (i=0; i < nsize; i++) {
586 *shortName++ = number[i];
589 if (validExtension) {
590 /* Copy extension characters */
591 *shortName++ = *lastDot++; /* copy dot */
592 for (i = 0, tc = *lastDot++;
595 if (ISLEGALCHAR(tc)) {
597 *shortName++ = toupper(tc);
606 *shortNameEndp = shortName;
609 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
610 clientchar_t *shortName, clientchar_t **shortNameEndp)
612 clientchar_t number[12];
614 int validExtension = 0;
616 /* Unparse the file's cell and volume numbers */
618 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
620 cell /= cm_8Dot3MapSize;
623 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
625 volume /= cm_8Dot3MapSize;
626 } while (volume && nsize < 8);
628 /* Copy uniquifier characters */
629 for (i=0; i < nsize; i++) {
630 *shortName++ = number[i];
633 /* Add extension characters */
634 *shortName++ = '.'; /* copy dot */
643 *shortNameEndp = shortName;
646 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
648 \note This procedure works recursively calling itself.
650 \param[in] pattern string containing metacharacters.
651 \param[in] name File name to be compared with 'pattern'.
653 \return BOOL : TRUE/FALSE (match/mistmatch)
656 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
658 clientchar_t upattern[MAX_PATH];
659 clientchar_t uname[MAX_PATH];
661 clientchar_t * pename; // points to the last 'name' character
663 clientchar_t * pattern_next;
666 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
667 cm_ClientStrUpr(upattern);
670 cm_ClientStrCpy(uname, lengthof(uname), name);
671 cm_ClientStrUpr(uname);
674 /* The following translations all work on single byte
676 for (p=upattern; *p; p++) {
677 if (*p == '"') *p = '.'; continue;
678 if (*p == '<') *p = '*'; continue;
679 if (*p == '>') *p = '?'; continue;
682 for (p=uname; *p; p++) {
683 if (*p == '"') *p = '.'; continue;
684 if (*p == '<') *p = '*'; continue;
685 if (*p == '>') *p = '?'; continue;
689 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
694 pattern = cm_ClientCharNext(pattern);
697 name = cm_ClientCharNext(name);
701 pattern = cm_ClientCharNext(pattern);
702 if (*pattern == '\0')
705 pattern_next = cm_ClientCharNext(pattern);
707 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
708 if (*p == *pattern &&
709 szWildCardMatchFileName(pattern_next,
710 cm_ClientCharNext(p), FALSE))
713 if (*pattern == '.' && *pattern_next == '\0') {
714 for (p = name; p && *p; p = cm_ClientCharNext(p))
724 if (*name != *pattern)
726 pattern = cm_ClientCharNext(pattern);
727 name = cm_ClientCharNext(name);
732 /* if all we have left are wildcards, then we match */
733 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
734 if (*pattern != '*' && *pattern != '?')
740 /* do a case-folding search of the star name mask with the name in namep.
741 * Return 1 if we match, otherwise 0.
743 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
745 clientchar_t *newmask, lastchar = _C('\0');
746 int i, j, casefold, retval;
747 int star = 0, qmark = 0, dot = 0;
749 /* make sure we only match 8.3 names, if requested */
750 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
753 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
755 /* optimize the pattern:
756 * if there is a mixture of '?' and '*',
757 * for example the sequence "*?*?*?*"
758 * must be turned into the form "*"
760 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
761 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
763 switch ( maskp[i] ) {
778 } else if ( qmark ) {
782 newmask[j++] = maskp[i];
789 } else if ( qmark ) {
793 if (dot == 0 && lastchar == '<')
797 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
804 cm_TargetPerceivedAsDirectory(const fschar_t *target)
808 ext = PathFindExtension(target);
816 cm_LoadAfsdHookLib(void)
822 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
825 p = strrchr(dllname, '\\');
828 strcpy(p, AFSD_HOOK_DLL);
829 hLib = LoadLibrary(dllname);
831 hLib = LoadLibrary(AFSD_HOOK_DLL);
838 * Obtain the file info structure for the specified file.
839 * If a full path is not specified, the search order is the
840 * same as that used by LoadLibrary().
843 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
851 VS_FIXEDFILEINFO vsf;
853 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
858 pInfo = (char*)malloc(dwSize);
863 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
866 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
869 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
871 liVer->LowPart = vsf.dwFileVersionLS;
872 liVer->HighPart = vsf.dwFileVersionMS;
881 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
882 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
883 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
885 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
887 static BOOL fChecked = FALSE;
888 static BOOL fSupportsExtendedTimeouts = FALSE;
892 BOOL isWow64 = FALSE;
893 OSVERSIONINFOEX Version;
895 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
896 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
897 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
898 PVOID Wow64RedirectionState;
899 LARGE_INTEGER fvFile, fvHotFixMin;
901 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
903 * If we don't find the fnIsWow64Process function then we
904 * are not running in a Wow64 environment
907 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
909 memset (&Version, 0x00, sizeof(Version));
910 Version.dwOSVersionInfoSize = sizeof(Version);
911 GetVersionEx((OSVERSIONINFO *) &Version);
914 * Support is available as hot fixes / service packs on:
921 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
922 Version.dwMajorVersion >= 5) {
925 if (Version.dwMajorVersion == 5 &&
926 Version.dwMinorVersion == 1) {
928 fvHotFixMin.HighPart = (5 << 16) | 1;
930 switch (Version.wServicePackMajor) {
932 fvHotFixMin.LowPart = (2600 << 16) | 5815;
935 fvHotFixMin.LowPart = (2600 << 16) | 3572;
938 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
943 /* 64-bit XP and Server 2003 */
944 else if (Version.dwMajorVersion == 5 &&
945 Version.dwMinorVersion == 2) {
947 fvHotFixMin.HighPart = (5 << 16) | 2;
949 switch (Version.wServicePackMajor) {
951 fvHotFixMin.LowPart = (3790 << 16) | 4479;
954 fvHotFixMin.LowPart = (3790 << 16) | 3310;
957 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
962 /* Vista and Server 2008 */
963 else if (Version.dwMajorVersion == 6 &&
964 Version.dwMinorVersion == 0) {
966 fvHotFixMin.HighPart = (6 << 16) | 0;
968 switch (Version.wServicePackMajor) {
970 fvHotFixMin.LowPart = (6002 << 16) | 18005;
973 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
978 /* Windows 7 and Server 2008 R2 and beyond */
979 else if (Version.dwMajorVersion > 6 ||
980 Version.dwMajorVersion == 6 &&
981 Version.dwMinorVersion >= 1) {
982 fSupportsExtendedTimeouts = TRUE;
986 /* If wow64, disable wow64 redirection and preserve the existing state */
987 if (fnIsWow64Process &&
988 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
990 fnDisableWow64FsRedirection =
991 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
992 fnRevertWow64FsRedirection =
993 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
994 fnDisableWow64FsRedirection(&Wow64RedirectionState);
997 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
998 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
999 fSupportsExtendedTimeouts = TRUE;
1001 /* If wow64, restore the previous redirection state */
1002 if (fnIsWow64Process && isWow64) {
1003 fnRevertWow64FsRedirection(Wow64RedirectionState);
1010 return fSupportsExtendedTimeouts;
1013 void cm_ResetServerPriority()
1015 void * p = TlsGetValue(cm_TlsRequestSlot);
1018 TlsSetValue(cm_TlsRequestSlot, NULL);
1019 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1023 void cm_SetRequestStartTime()
1025 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1027 tp = malloc(sizeof(time_t));
1031 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1036 void cm_UpdateServerPriority()
1038 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1041 time_t now = osi_Time();
1043 /* Give one priority boost for each 15 seconds */
1044 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1049 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1051 // Note that LONGLONG is a 64-bit value
1054 #ifdef _USE_32BIT_TIME_T
1055 ll.QuadPart = UInt32x32To64(unixTime, 10000000) + 116444736000000000;
1057 ll.QuadPart = unixTime * 10000000 + 116444736000000000;
1059 largeTimep->dwLowDateTime = ll.LowPart;
1060 largeTimep->dwHighDateTime = ll.HighPart;
1063 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1065 // Note that LONGLONG is a 64-bit value
1068 ll.HighPart = largeTimep->dwHighDateTime;
1069 ll.LowPart = largeTimep->dwLowDateTime;
1071 ll.QuadPart -= 116444736000000000;
1072 ll.QuadPart /= 10000000;
1074 *unixTimep = (time_t)ll.QuadPart;
1077 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1082 struct tm localJunk;
1083 time_t t = unixTime;
1085 ltp = localtime(&t);
1087 /* if we fail, make up something */
1090 localJunk.tm_year = 89 - 20;
1091 localJunk.tm_mon = 4;
1092 localJunk.tm_mday = 12;
1093 localJunk.tm_hour = 0;
1094 localJunk.tm_min = 0;
1095 localJunk.tm_sec = 0;
1098 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1099 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1100 *searchTimep = (dosDate<<16) | dosTime;
1103 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1105 unsigned short dosDate;
1106 unsigned short dosTime;
1109 dosDate = (unsigned short) (searchTime & 0xffff);
1110 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1112 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1113 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1114 localTm.tm_mday = (dosDate) & 0x1f;
1115 localTm.tm_hour = (dosTime>>11) & 0x1f;
1116 localTm.tm_min = (dosTime >> 5) & 0x3f;
1117 localTm.tm_sec = (dosTime & 0x1f) * 2;
1118 localTm.tm_isdst = -1; /* compute whether DST in effect */
1120 *unixTimep = mktime(&localTm);
1124 cm_NextHighestPowerOf2(afs_uint32 n)