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 ||
218 error = CM_ERROR_RETRY;
219 else if (error == RX_CALL_IDLE)
222 error = CM_ERROR_UNKNOWN;
223 else if (error == EINVAL)
224 error = CM_ERROR_INVAL;
225 else if (error == EROFS)
226 error = CM_ERROR_READONLY;
227 else if (error == EACCES)
228 error = CM_ERROR_NOACCESS;
229 else if (error == EXDEV)
230 error = CM_ERROR_CROSSDEVLINK;
231 else if (error == EEXIST)
232 error = CM_ERROR_EXISTS;
233 else if (error == ENOTDIR)
234 error = CM_ERROR_NOTDIR;
235 else if (error == ENOENT)
236 error = CM_ERROR_NOSUCHFILE;
237 else if (error == EAGAIN
238 || error == 35 /* EAGAIN, Digital UNIX */
239 || error == WSAEWOULDBLOCK)
240 error = CM_ERROR_WOULDBLOCK;
241 else if (error == VDISKFULL
243 error = CM_ERROR_SPACE;
244 else if (error == VOVERQUOTA
246 || error == 49 /* EDQUOT on Solaris */
247 || error == 88 /* EDQUOT on AIX */
248 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
249 || error == 122 /* EDQUOT on Linux */
250 || error == 1133) /* EDQUOT on Irix */
251 error = CM_ERROR_QUOTA;
252 else if (error == VNOVNODE)
253 error = CM_ERROR_BADFD;
254 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
255 error = CM_ERROR_ALLOFFLINE;
256 else if (error == VBUSY || error == VRESTARTING)
257 error = CM_ERROR_ALLBUSY;
258 else if (error == EISDIR)
259 return CM_ERROR_ISDIR;
263 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
268 /* If we had to stop retrying, report our saved error code. */
269 if (reqp && error == CM_ERROR_TIMEDOUT) {
270 if (reqp->accessError)
271 return reqp->accessError;
272 if (reqp->volumeError)
273 return reqp->volumeError;
275 return reqp->rpcError;
279 error = et_to_sys_error(error);
281 if (error == RX_CALL_DEAD ||
282 error == RX_CALL_TIMEOUT ||
283 error == RX_CALL_BUSY ||
284 error == RX_CALL_IDLE ||
286 error = CM_ERROR_RETRY;
287 else if (error == VNOVNODE)
288 error = CM_ERROR_BADFD;
289 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
290 error = CM_ERROR_ALLOFFLINE;
291 else if (error == VBUSY || error == VRESTARTING)
292 error = CM_ERROR_ALLBUSY;
294 error = CM_ERROR_UNKNOWN;
295 else if (error == EROFS)
296 error = CM_ERROR_READONLY;
297 else if (error == ENOTDIR)
298 error = CM_ERROR_NOTDIR;
299 else if (error == EACCES)
300 error = CM_ERROR_NOACCESS;
301 else if (error == ENOENT)
302 error = CM_ERROR_NOSUCHFILE;
303 else if (error == EINVAL)
304 error = CM_ERROR_INVAL;
305 else if (error == ENOTEMPTY
306 || error == 17 /* AIX */
307 || error == 66 /* SunOS 4, Digital UNIX */
308 || error == 93 /* Solaris 2, IRIX */
309 || error == 247) /* HP/UX */
310 error = CM_ERROR_NOTEMPTY;
314 long cm_MapVLRPCError(long error, cm_req_t *reqp)
316 if (error == 0) return 0;
318 /* If we had to stop retrying, report our saved error code. */
319 if (reqp && error == CM_ERROR_TIMEDOUT) {
320 if (reqp->accessError)
321 return reqp->accessError;
322 if (reqp->volumeError)
323 return reqp->volumeError;
325 return reqp->rpcError;
329 error = et_to_sys_error(error);
331 if (error == RX_CALL_DEAD ||
332 error == RX_CALL_TIMEOUT ||
333 error == RX_CALL_BUSY ||
334 error == RX_CALL_IDLE ||
336 error = CM_ERROR_RETRY;
337 else if (error == RX_RESTARTING)
338 error = CM_ERROR_ALLBUSY;
340 error = CM_ERROR_UNKNOWN;
341 else if (error == EINVAL)
342 error = CM_ERROR_INVAL;
343 else if (error == VL_NOENT || error == VL_BADNAME)
344 error = CM_ERROR_NOSUCHVOLUME;
348 cm_space_t *cm_GetSpace(void)
354 lock_ObtainWrite(&cm_utilsLock);
355 if (tsp = cm_spaceListp) {
356 cm_spaceListp = tsp->nextp;
358 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
359 (void) memset(tsp, 0, sizeof(cm_space_t));
360 lock_ReleaseWrite(&cm_utilsLock);
365 void cm_FreeSpace(cm_space_t *tsp)
367 lock_ObtainWrite(&cm_utilsLock);
368 tsp->nextp = cm_spaceListp;
370 lock_ReleaseWrite(&cm_utilsLock);
373 /* characters that are legal in an 8.3 name */
375 * We used to have 1's for all characters from 128 to 254. But
376 * the NT client behaves better if we create an 8.3 name for any
377 * name that has a character with the high bit on, and if we
378 * delete those characters from 8.3 names. In particular, see
379 * Sybase defect 10859.
381 char cm_LegalChars[256] = {
382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
384 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
385 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
386 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
387 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
388 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
390 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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
400 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
402 /* return true iff component is a valid 8.3 name */
403 int cm_Is8Dot3(clientchar_t *namep)
409 if (namep == NULL || !namep[0])
413 * can't have a leading dot;
414 * special case for . and ..
416 if (namep[0] == '.') {
419 if (namep[1] == '.' && namep[2] == 0)
423 while (tc = *namep++) {
425 /* saw another dot */
426 if (sawDot) return 0; /* second dot */
431 if (!ISLEGALCHAR(tc))
434 if (!sawDot && charCount > 8)
435 /* more than 8 chars in name */
437 if (sawDot && charCount > 3)
438 /* more than 3 chars in extension */
445 * Number unparsing map for generating 8.3 names;
446 * The version taken from DFS was on drugs.
447 * You can't include '&' and '@' in a file name.
449 char cm_8Dot3Mapping[42] =
450 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
451 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
452 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
453 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
455 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
457 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
458 clientchar_t *shortName, clientchar_t **shortNameEndp)
462 int vnode = ntohl(pfid->vnode);
464 int validExtension = 0;
468 /* Unparse the file's vnode number to get a "uniquifier" */
470 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
472 vnode /= cm_8Dot3MapSize;
476 * Look for valid extension. There has to be a dot, and
477 * at least one of the characters following has to be legal.
479 lastDot = strrchr(longname, '.');
481 temp = lastDot; temp++;
489 /* Copy name characters */
490 for (i = 0, name = longname;
491 i < (7 - nsize) && name != lastDot; ) {
496 if (!ISLEGALCHAR(tc))
499 *shortName++ = toupper(tc);
505 /* Copy uniquifier characters */
506 for (i=0; i < nsize; i++) {
507 *shortName++ = number[i];
510 if (validExtension) {
511 /* Copy extension characters */
512 *shortName++ = *lastDot++; /* copy dot */
513 for (i = 0, tc = *lastDot++;
516 if (ISLEGALCHAR(tc)) {
518 *shortName++ = toupper(tc);
527 *shortNameEndp = shortName;
530 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
531 clientchar_t *shortName, clientchar_t **shortNameEndp)
533 clientchar_t number[12];
535 int vnode = ntohl(pfid->vnode);
536 clientchar_t *lastDot;
537 int validExtension = 0;
538 clientchar_t tc, *temp;
539 const clientchar_t *name;
541 /* Unparse the file's vnode number to get a "uniquifier" */
543 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
545 vnode /= cm_8Dot3MapSize;
549 * Look for valid extension. There has to be a dot, and
550 * at least one of the characters following has to be legal.
552 lastDot = cm_ClientStrRChr(longname, '.');
554 temp = lastDot; temp++;
562 /* Copy name characters */
563 for (i = 0, name = longname;
564 i < (7 - nsize) && name != lastDot; ) {
569 if (!ISLEGALCHAR(tc))
572 *shortName++ = toupper((char) tc);
578 /* Copy uniquifier characters */
579 for (i=0; i < nsize; i++) {
580 *shortName++ = number[i];
583 if (validExtension) {
584 /* Copy extension characters */
585 *shortName++ = *lastDot++; /* copy dot */
586 for (i = 0, tc = *lastDot++;
589 if (ISLEGALCHAR(tc)) {
591 *shortName++ = toupper(tc);
600 *shortNameEndp = shortName;
603 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
604 clientchar_t *shortName, clientchar_t **shortNameEndp)
606 clientchar_t number[12];
608 int validExtension = 0;
610 /* Unparse the file's cell and volume numbers */
612 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
614 cell /= cm_8Dot3MapSize;
617 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
619 volume /= cm_8Dot3MapSize;
620 } while (volume && nsize < 8);
622 /* Copy uniquifier characters */
623 for (i=0; i < nsize; i++) {
624 *shortName++ = number[i];
627 /* Add extension characters */
628 *shortName++ = '.'; /* copy dot */
637 *shortNameEndp = shortName;
640 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
642 \note This procedure works recursively calling itself.
644 \param[in] pattern string containing metacharacters.
645 \param[in] name File name to be compared with 'pattern'.
647 \return BOOL : TRUE/FALSE (match/mistmatch)
650 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
652 clientchar_t upattern[MAX_PATH];
653 clientchar_t uname[MAX_PATH];
655 clientchar_t * pename; // points to the last 'name' character
657 clientchar_t * pattern_next;
660 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
661 cm_ClientStrUpr(upattern);
664 cm_ClientStrCpy(uname, lengthof(uname), name);
665 cm_ClientStrUpr(uname);
668 /* The following translations all work on single byte
670 for (p=upattern; *p; p++) {
671 if (*p == '"') *p = '.'; continue;
672 if (*p == '<') *p = '*'; continue;
673 if (*p == '>') *p = '?'; continue;
676 for (p=uname; *p; p++) {
677 if (*p == '"') *p = '.'; continue;
678 if (*p == '<') *p = '*'; continue;
679 if (*p == '>') *p = '?'; continue;
683 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
688 pattern = cm_ClientCharNext(pattern);
691 name = cm_ClientCharNext(name);
695 pattern = cm_ClientCharNext(pattern);
696 if (*pattern == '\0')
699 pattern_next = cm_ClientCharNext(pattern);
701 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
702 if (*p == *pattern &&
703 szWildCardMatchFileName(pattern_next,
704 cm_ClientCharNext(p), FALSE))
707 if (*pattern == '.' && *pattern_next == '\0') {
708 for (p = name; p && *p; p = cm_ClientCharNext(p))
718 if (*name != *pattern)
720 pattern = cm_ClientCharNext(pattern);
721 name = cm_ClientCharNext(name);
726 /* if all we have left are wildcards, then we match */
727 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
728 if (*pattern != '*' && *pattern != '?')
734 /* do a case-folding search of the star name mask with the name in namep.
735 * Return 1 if we match, otherwise 0.
737 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
739 clientchar_t *newmask, lastchar = _C('\0');
740 int i, j, casefold, retval;
741 int star = 0, qmark = 0, dot = 0;
743 /* make sure we only match 8.3 names, if requested */
744 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
747 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
749 /* optimize the pattern:
750 * if there is a mixture of '?' and '*',
751 * for example the sequence "*?*?*?*"
752 * must be turned into the form "*"
754 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
755 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
757 switch ( maskp[i] ) {
772 } else if ( qmark ) {
776 newmask[j++] = maskp[i];
783 } else if ( qmark ) {
787 if (dot == 0 && lastchar == '<')
791 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
798 cm_TargetPerceivedAsDirectory(const fschar_t *target)
802 ext = PathFindExtension(target);
810 cm_LoadAfsdHookLib(void)
816 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
819 p = strrchr(dllname, '\\');
822 strcpy(p, AFSD_HOOK_DLL);
823 hLib = LoadLibrary(dllname);
825 hLib = LoadLibrary(AFSD_HOOK_DLL);
832 * Obtain the file info structure for the specified file.
833 * If a full path is not specified, the search order is the
834 * same as that used by LoadLibrary().
837 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
845 VS_FIXEDFILEINFO vsf;
847 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
852 pInfo = (char*)malloc(dwSize);
857 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
860 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
863 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
865 liVer->LowPart = vsf.dwFileVersionLS;
866 liVer->HighPart = vsf.dwFileVersionMS;
875 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
876 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
877 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
879 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
881 static BOOL fChecked = FALSE;
882 static BOOL fSupportsExtendedTimeouts = FALSE;
886 BOOL isWow64 = FALSE;
887 OSVERSIONINFOEX Version;
889 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
890 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
891 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
892 PVOID Wow64RedirectionState;
893 LARGE_INTEGER fvFile, fvHotFixMin;
895 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
897 * If we don't find the fnIsWow64Process function then we
898 * are not running in a Wow64 environment
901 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
903 memset (&Version, 0x00, sizeof(Version));
904 Version.dwOSVersionInfoSize = sizeof(Version);
905 GetVersionEx((OSVERSIONINFO *) &Version);
908 * Support is available as hot fixes / service packs on:
915 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
916 Version.dwMajorVersion >= 5) {
919 if (Version.dwMajorVersion == 5 &&
920 Version.dwMinorVersion == 1) {
922 fvHotFixMin.HighPart = (5 << 16) | 1;
924 switch (Version.wServicePackMajor) {
926 fvHotFixMin.LowPart = (2600 << 16) | 5815;
929 fvHotFixMin.LowPart = (2600 << 16) | 3572;
932 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
937 /* 64-bit XP and Server 2003 */
938 else if (Version.dwMajorVersion == 5 &&
939 Version.dwMinorVersion == 2) {
941 fvHotFixMin.HighPart = (5 << 16) | 2;
943 switch (Version.wServicePackMajor) {
945 fvHotFixMin.LowPart = (3790 << 16) | 4479;
948 fvHotFixMin.LowPart = (3790 << 16) | 3310;
951 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
956 /* Vista and Server 2008 */
957 else if (Version.dwMajorVersion == 6 &&
958 Version.dwMinorVersion == 0) {
960 fvHotFixMin.HighPart = (6 << 16) | 0;
962 switch (Version.wServicePackMajor) {
964 fvHotFixMin.LowPart = (6002 << 16) | 18005;
967 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
972 /* Windows 7 and Server 2008 R2 and beyond */
973 else if (Version.dwMajorVersion > 6 ||
974 Version.dwMajorVersion == 6 &&
975 Version.dwMinorVersion >= 1) {
976 fSupportsExtendedTimeouts = TRUE;
980 /* If wow64, disable wow64 redirection and preserve the existing state */
981 if (fnIsWow64Process &&
982 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
984 fnDisableWow64FsRedirection =
985 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
986 fnRevertWow64FsRedirection =
987 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
988 fnDisableWow64FsRedirection(&Wow64RedirectionState);
991 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
992 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
993 fSupportsExtendedTimeouts = TRUE;
995 /* If wow64, restore the previous redirection state */
996 if (fnIsWow64Process && isWow64) {
997 fnRevertWow64FsRedirection(Wow64RedirectionState);
1004 return fSupportsExtendedTimeouts;
1007 void cm_ResetServerPriority()
1009 void * p = TlsGetValue(cm_TlsRequestSlot);
1012 TlsSetValue(cm_TlsRequestSlot, NULL);
1013 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1017 void cm_SetRequestStartTime()
1019 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1021 tp = malloc(sizeof(time_t));
1025 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1030 void cm_UpdateServerPriority()
1032 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1035 time_t now = osi_Time();
1037 /* Give one priority boost for each 15 seconds */
1038 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1043 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1045 // Note that LONGLONG is a 64-bit value
1048 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1049 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1050 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1053 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1055 // Note that LONGLONG is a 64-bit value
1058 ll = largeTimep->dwHighDateTime;
1060 ll += largeTimep->dwLowDateTime;
1062 ll -= 116444736000000000;
1065 *unixTimep = (DWORD)ll;
1068 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1073 struct tm localJunk;
1074 time_t t = unixTime;
1076 ltp = localtime(&t);
1078 /* if we fail, make up something */
1081 localJunk.tm_year = 89 - 20;
1082 localJunk.tm_mon = 4;
1083 localJunk.tm_mday = 12;
1084 localJunk.tm_hour = 0;
1085 localJunk.tm_min = 0;
1086 localJunk.tm_sec = 0;
1089 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1090 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1091 *searchTimep = (dosDate<<16) | dosTime;
1094 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1096 unsigned short dosDate;
1097 unsigned short dosTime;
1100 dosDate = (unsigned short) (searchTime & 0xffff);
1101 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1103 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1104 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1105 localTm.tm_mday = (dosDate) & 0x1f;
1106 localTm.tm_hour = (dosTime>>11) & 0x1f;
1107 localTm.tm_min = (dosTime >> 5) & 0x3f;
1108 localTm.tm_sec = (dosTime & 0x1f) * 2;
1109 localTm.tm_isdst = -1; /* compute whether DST in effect */
1111 *unixTimep = mktime(&localTm);
1115 cm_NextHighestPowerOf2(afs_uint32 n)