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 ||
217 error = CM_ERROR_RETRY;
219 error = CM_ERROR_UNKNOWN;
220 else if (error == EINVAL)
221 error = CM_ERROR_INVAL;
222 else if (error == EROFS)
223 error = CM_ERROR_READONLY;
224 else if (error == EACCES)
225 error = CM_ERROR_NOACCESS;
226 else if (error == EXDEV)
227 error = CM_ERROR_CROSSDEVLINK;
228 else if (error == EEXIST)
229 error = CM_ERROR_EXISTS;
230 else if (error == ENOTDIR)
231 error = CM_ERROR_NOTDIR;
232 else if (error == ENOENT)
233 error = CM_ERROR_NOSUCHFILE;
234 else if (error == EAGAIN
235 || error == 35 /* EAGAIN, Digital UNIX */
236 || error == WSAEWOULDBLOCK)
237 error = CM_ERROR_WOULDBLOCK;
238 else if (error == VDISKFULL
240 error = CM_ERROR_SPACE;
241 else if (error == VOVERQUOTA
243 || error == 49 /* EDQUOT on Solaris */
244 || error == 88 /* EDQUOT on AIX */
245 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
246 || error == 122 /* EDQUOT on Linux */
247 || error == 1133) /* EDQUOT on Irix */
248 error = CM_ERROR_QUOTA;
249 else if (error == VNOVNODE)
250 error = CM_ERROR_BADFD;
251 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
252 error = CM_ERROR_ALLOFFLINE;
253 else if (error == VBUSY || error == VRESTARTING)
254 error = CM_ERROR_ALLBUSY;
255 else if (error == EISDIR)
256 return CM_ERROR_ISDIR;
260 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
265 /* If we had to stop retrying, report our saved error code. */
266 if (reqp && error == CM_ERROR_TIMEDOUT) {
267 if (reqp->accessError)
268 return reqp->accessError;
269 if (reqp->volumeError)
270 return reqp->volumeError;
272 return reqp->rpcError;
276 error = et_to_sys_error(error);
278 if (error == RX_CALL_DEAD ||
279 error == RX_CALL_TIMEOUT ||
281 error = CM_ERROR_RETRY;
282 else if (error == VNOVNODE)
283 error = CM_ERROR_BADFD;
284 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
285 error = CM_ERROR_ALLOFFLINE;
286 else if (error == VBUSY || error == VRESTARTING)
287 error = CM_ERROR_ALLBUSY;
289 error = CM_ERROR_UNKNOWN;
290 else if (error == EROFS)
291 error = CM_ERROR_READONLY;
292 else if (error == ENOTDIR)
293 error = CM_ERROR_NOTDIR;
294 else if (error == EACCES)
295 error = CM_ERROR_NOACCESS;
296 else if (error == ENOENT)
297 error = CM_ERROR_NOSUCHFILE;
298 else if (error == EINVAL)
299 error = CM_ERROR_INVAL;
300 else if (error == ENOTEMPTY
301 || error == 17 /* AIX */
302 || error == 66 /* SunOS 4, Digital UNIX */
303 || error == 93 /* Solaris 2, IRIX */
304 || error == 247) /* HP/UX */
305 error = CM_ERROR_NOTEMPTY;
309 long cm_MapVLRPCError(long error, cm_req_t *reqp)
311 if (error == 0) return 0;
313 /* If we had to stop retrying, report our saved error code. */
314 if (reqp && error == CM_ERROR_TIMEDOUT) {
315 if (reqp->accessError)
316 return reqp->accessError;
317 if (reqp->volumeError)
318 return reqp->volumeError;
320 return reqp->rpcError;
324 error = et_to_sys_error(error);
326 if (error == RX_CALL_DEAD ||
327 error == RX_CALL_TIMEOUT ||
329 error = CM_ERROR_RETRY;
330 else if (error == RX_RESTARTING)
331 error = CM_ERROR_ALLBUSY;
333 error = CM_ERROR_UNKNOWN;
334 else if (error == EINVAL)
335 error = CM_ERROR_INVAL;
336 else if (error == VL_NOENT || error == VL_BADNAME)
337 error = CM_ERROR_NOSUCHVOLUME;
341 cm_space_t *cm_GetSpace(void)
347 lock_ObtainWrite(&cm_utilsLock);
348 if (tsp = cm_spaceListp) {
349 cm_spaceListp = tsp->nextp;
351 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
352 (void) memset(tsp, 0, sizeof(cm_space_t));
353 lock_ReleaseWrite(&cm_utilsLock);
358 void cm_FreeSpace(cm_space_t *tsp)
360 lock_ObtainWrite(&cm_utilsLock);
361 tsp->nextp = cm_spaceListp;
363 lock_ReleaseWrite(&cm_utilsLock);
366 /* characters that are legal in an 8.3 name */
368 * We used to have 1's for all characters from 128 to 254. But
369 * the NT client behaves better if we create an 8.3 name for any
370 * name that has a character with the high bit on, and if we
371 * delete those characters from 8.3 names. In particular, see
372 * Sybase defect 10859.
374 char cm_LegalChars[256] = {
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
378 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
379 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
380 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
381 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
382 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
393 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
395 /* return true iff component is a valid 8.3 name */
396 int cm_Is8Dot3(clientchar_t *namep)
402 if (namep == NULL || !namep[0])
406 * can't have a leading dot;
407 * special case for . and ..
409 if (namep[0] == '.') {
412 if (namep[1] == '.' && namep[2] == 0)
416 while (tc = *namep++) {
418 /* saw another dot */
419 if (sawDot) return 0; /* second dot */
424 if (!ISLEGALCHAR(tc))
427 if (!sawDot && charCount > 8)
428 /* more than 8 chars in name */
430 if (sawDot && charCount > 3)
431 /* more than 3 chars in extension */
438 * Number unparsing map for generating 8.3 names;
439 * The version taken from DFS was on drugs.
440 * You can't include '&' and '@' in a file name.
442 char cm_8Dot3Mapping[42] =
443 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
444 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
445 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
446 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
448 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
450 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
451 clientchar_t *shortName, clientchar_t **shortNameEndp)
455 int vnode = ntohl(pfid->vnode);
457 int validExtension = 0;
461 /* Unparse the file's vnode number to get a "uniquifier" */
463 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
465 vnode /= cm_8Dot3MapSize;
469 * Look for valid extension. There has to be a dot, and
470 * at least one of the characters following has to be legal.
472 lastDot = strrchr(longname, '.');
474 temp = lastDot; temp++;
482 /* Copy name characters */
483 for (i = 0, name = longname;
484 i < (7 - nsize) && name != lastDot; ) {
489 if (!ISLEGALCHAR(tc))
492 *shortName++ = toupper(tc);
498 /* Copy uniquifier characters */
499 for (i=0; i < nsize; i++) {
500 *shortName++ = number[i];
503 if (validExtension) {
504 /* Copy extension characters */
505 *shortName++ = *lastDot++; /* copy dot */
506 for (i = 0, tc = *lastDot++;
509 if (ISLEGALCHAR(tc)) {
511 *shortName++ = toupper(tc);
520 *shortNameEndp = shortName;
523 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
524 clientchar_t *shortName, clientchar_t **shortNameEndp)
526 clientchar_t number[12];
528 int vnode = ntohl(pfid->vnode);
529 clientchar_t *lastDot;
530 int validExtension = 0;
531 clientchar_t tc, *temp;
532 const clientchar_t *name;
534 /* Unparse the file's vnode number to get a "uniquifier" */
536 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
538 vnode /= cm_8Dot3MapSize;
542 * Look for valid extension. There has to be a dot, and
543 * at least one of the characters following has to be legal.
545 lastDot = cm_ClientStrRChr(longname, '.');
547 temp = lastDot; temp++;
555 /* Copy name characters */
556 for (i = 0, name = longname;
557 i < (7 - nsize) && name != lastDot; ) {
562 if (!ISLEGALCHAR(tc))
565 *shortName++ = toupper((char) tc);
571 /* Copy uniquifier characters */
572 for (i=0; i < nsize; i++) {
573 *shortName++ = number[i];
576 if (validExtension) {
577 /* Copy extension characters */
578 *shortName++ = *lastDot++; /* copy dot */
579 for (i = 0, tc = *lastDot++;
582 if (ISLEGALCHAR(tc)) {
584 *shortName++ = toupper(tc);
593 *shortNameEndp = shortName;
596 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
597 clientchar_t *shortName, clientchar_t **shortNameEndp)
599 clientchar_t number[12];
601 int validExtension = 0;
603 /* Unparse the file's cell and volume numbers */
605 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
607 cell /= cm_8Dot3MapSize;
610 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
612 volume /= cm_8Dot3MapSize;
613 } while (volume && nsize < 8);
615 /* Copy uniquifier characters */
616 for (i=0; i < nsize; i++) {
617 *shortName++ = number[i];
620 /* Add extension characters */
621 *shortName++ = '.'; /* copy dot */
630 *shortNameEndp = shortName;
633 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
635 \note This procedure works recursively calling itself.
637 \param[in] pattern string containing metacharacters.
638 \param[in] name File name to be compared with 'pattern'.
640 \return BOOL : TRUE/FALSE (match/mistmatch)
643 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
645 clientchar_t upattern[MAX_PATH];
646 clientchar_t uname[MAX_PATH];
648 clientchar_t * pename; // points to the last 'name' character
650 clientchar_t * pattern_next;
653 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
654 cm_ClientStrUpr(upattern);
657 cm_ClientStrCpy(uname, lengthof(uname), name);
658 cm_ClientStrUpr(uname);
661 /* The following translations all work on single byte
663 for (p=upattern; *p; p++) {
664 if (*p == '"') *p = '.'; continue;
665 if (*p == '<') *p = '*'; continue;
666 if (*p == '>') *p = '?'; continue;
669 for (p=uname; *p; p++) {
670 if (*p == '"') *p = '.'; continue;
671 if (*p == '<') *p = '*'; continue;
672 if (*p == '>') *p = '?'; continue;
676 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
681 pattern = cm_ClientCharNext(pattern);
684 name = cm_ClientCharNext(name);
688 pattern = cm_ClientCharNext(pattern);
689 if (*pattern == '\0')
692 pattern_next = cm_ClientCharNext(pattern);
694 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
695 if (*p == *pattern &&
696 szWildCardMatchFileName(pattern_next,
697 cm_ClientCharNext(p), FALSE))
700 if (*pattern == '.' && *pattern_next == '\0') {
701 for (p = name; p && *p; p = cm_ClientCharNext(p))
711 if (*name != *pattern)
713 pattern = cm_ClientCharNext(pattern);
714 name = cm_ClientCharNext(name);
719 /* if all we have left are wildcards, then we match */
720 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
721 if (*pattern != '*' && *pattern != '?')
727 /* do a case-folding search of the star name mask with the name in namep.
728 * Return 1 if we match, otherwise 0.
730 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
732 clientchar_t *newmask, lastchar = _C('\0');
733 int i, j, casefold, retval;
734 int star = 0, qmark = 0, dot = 0;
736 /* make sure we only match 8.3 names, if requested */
737 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
740 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
742 /* optimize the pattern:
743 * if there is a mixture of '?' and '*',
744 * for example the sequence "*?*?*?*"
745 * must be turned into the form "*"
747 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
748 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
750 switch ( maskp[i] ) {
765 } else if ( qmark ) {
769 newmask[j++] = maskp[i];
776 } else if ( qmark ) {
780 if (dot == 0 && lastchar == '<')
784 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
791 cm_TargetPerceivedAsDirectory(const fschar_t *target)
795 ext = PathFindExtension(target);
803 cm_LoadAfsdHookLib(void)
809 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
812 p = strrchr(dllname, '\\');
815 strcpy(p, AFSD_HOOK_DLL);
816 hLib = LoadLibrary(dllname);
818 hLib = LoadLibrary(AFSD_HOOK_DLL);
825 * Obtain the file info structure for the specified file.
826 * If a full path is not specified, the search order is the
827 * same as that used by LoadLibrary().
830 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
838 VS_FIXEDFILEINFO vsf;
840 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
845 pInfo = (char*)malloc(dwSize);
850 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
853 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
856 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
858 liVer->LowPart = vsf.dwFileVersionLS;
859 liVer->HighPart = vsf.dwFileVersionMS;
868 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
869 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
870 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
872 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
874 static BOOL fChecked = FALSE;
875 static BOOL fSupportsExtendedTimeouts = FALSE;
879 BOOL isWow64 = FALSE;
880 OSVERSIONINFOEX Version;
882 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
883 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
884 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
885 PVOID Wow64RedirectionState;
886 LARGE_INTEGER fvFile, fvHotFixMin;
888 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
890 * If we don't find the fnIsWow64Process function then we
891 * are not running in a Wow64 environment
894 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
896 memset (&Version, 0x00, sizeof(Version));
897 Version.dwOSVersionInfoSize = sizeof(Version);
898 GetVersionEx((OSVERSIONINFO *) &Version);
901 * Support is available as hot fixes / service packs on:
908 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
909 Version.dwMajorVersion >= 5) {
912 if (Version.dwMajorVersion == 5 &&
913 Version.dwMinorVersion == 1) {
915 fvHotFixMin.HighPart = (5 << 16) | 1;
917 switch (Version.wServicePackMajor) {
919 fvHotFixMin.LowPart = (2600 << 16) | 5815;
922 fvHotFixMin.LowPart = (2600 << 16) | 3572;
925 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
930 /* 64-bit XP and Server 2003 */
931 else if (Version.dwMajorVersion == 5 &&
932 Version.dwMinorVersion == 2) {
934 fvHotFixMin.HighPart = (5 << 16) | 2;
936 switch (Version.wServicePackMajor) {
938 fvHotFixMin.LowPart = (3790 << 16) | 4479;
941 fvHotFixMin.LowPart = (3790 << 16) | 3310;
944 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
949 /* Vista and Server 2008 */
950 else if (Version.dwMajorVersion == 6 &&
951 Version.dwMinorVersion == 0) {
953 fvHotFixMin.HighPart = (6 << 16) | 0;
955 switch (Version.wServicePackMajor) {
957 fvHotFixMin.LowPart = (6002 << 16) | 18005;
960 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
965 /* Windows 7 and Server 2008 R2 and beyond */
966 else if (Version.dwMajorVersion > 6 ||
967 Version.dwMajorVersion == 6 &&
968 Version.dwMinorVersion >= 1) {
969 fSupportsExtendedTimeouts = TRUE;
973 /* If wow64, disable wow64 redirection and preserve the existing state */
974 if (fnIsWow64Process &&
975 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
977 fnDisableWow64FsRedirection =
978 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
979 fnRevertWow64FsRedirection =
980 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
981 fnDisableWow64FsRedirection(&Wow64RedirectionState);
984 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
985 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
986 fSupportsExtendedTimeouts = TRUE;
988 /* If wow64, restore the previous redirection state */
989 if (fnIsWow64Process && isWow64) {
990 fnRevertWow64FsRedirection(Wow64RedirectionState);
997 return fSupportsExtendedTimeouts;
1000 void cm_ResetServerPriority()
1002 void * p = TlsGetValue(cm_TlsRequestSlot);
1005 TlsSetValue(cm_TlsRequestSlot, NULL);
1006 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1010 void cm_SetRequestStartTime()
1012 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1014 tp = malloc(sizeof(time_t));
1018 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1023 void cm_UpdateServerPriority()
1025 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1028 time_t now = osi_Time();
1030 /* Give one priority boost for each 15 seconds */
1031 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1036 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1038 // Note that LONGLONG is a 64-bit value
1041 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1042 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1043 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1046 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1048 // Note that LONGLONG is a 64-bit value
1051 ll = largeTimep->dwHighDateTime;
1053 ll += largeTimep->dwLowDateTime;
1055 ll -= 116444736000000000;
1058 *unixTimep = (DWORD)ll;
1061 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1066 struct tm localJunk;
1067 time_t t = unixTime;
1069 ltp = localtime(&t);
1071 /* if we fail, make up something */
1074 localJunk.tm_year = 89 - 20;
1075 localJunk.tm_mon = 4;
1076 localJunk.tm_mday = 12;
1077 localJunk.tm_hour = 0;
1078 localJunk.tm_min = 0;
1079 localJunk.tm_sec = 0;
1082 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1083 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1084 *searchTimep = (dosDate<<16) | dosTime;
1087 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1089 unsigned short dosDate;
1090 unsigned short dosTime;
1093 dosDate = (unsigned short) (searchTime & 0xffff);
1094 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1096 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1097 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1098 localTm.tm_mday = (dosDate) & 0x1f;
1099 localTm.tm_hour = (dosTime>>11) & 0x1f;
1100 localTm.tm_min = (dosTime >> 5) & 0x3f;
1101 localTm.tm_sec = (dosTime & 0x1f) * 2;
1102 localTm.tm_isdst = -1; /* compute whether DST in effect */
1104 *unixTimep = mktime(&localTm);
1108 cm_NextHighestPowerOf2(afs_uint32 n)