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_CALL_IDLE ||
219 error = CM_ERROR_RETRY;
221 error = CM_ERROR_UNKNOWN;
222 else if (error == EINVAL)
223 error = CM_ERROR_INVAL;
224 else if (error == EROFS)
225 error = CM_ERROR_READONLY;
226 else if (error == EACCES)
227 error = CM_ERROR_NOACCESS;
228 else if (error == EXDEV)
229 error = CM_ERROR_CROSSDEVLINK;
230 else if (error == EEXIST)
231 error = CM_ERROR_EXISTS;
232 else if (error == ENOTDIR)
233 error = CM_ERROR_NOTDIR;
234 else if (error == ENOENT)
235 error = CM_ERROR_NOSUCHFILE;
236 else if (error == EAGAIN
237 || error == 35 /* EAGAIN, Digital UNIX */
238 || error == WSAEWOULDBLOCK)
239 error = CM_ERROR_WOULDBLOCK;
240 else if (error == VDISKFULL
242 error = CM_ERROR_SPACE;
243 else if (error == VOVERQUOTA
245 || error == 49 /* EDQUOT on Solaris */
246 || error == 88 /* EDQUOT on AIX */
247 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
248 || error == 122 /* EDQUOT on Linux */
249 || error == 1133) /* EDQUOT on Irix */
250 error = CM_ERROR_QUOTA;
251 else if (error == VNOVNODE)
252 error = CM_ERROR_BADFD;
253 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
254 error = CM_ERROR_ALLOFFLINE;
255 else if (error == VBUSY || error == VRESTARTING)
256 error = CM_ERROR_ALLBUSY;
257 else if (error == EISDIR)
258 return CM_ERROR_ISDIR;
262 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
267 /* If we had to stop retrying, report our saved error code. */
268 if (reqp && error == CM_ERROR_TIMEDOUT) {
269 if (reqp->accessError)
270 return reqp->accessError;
271 if (reqp->volumeError)
272 return reqp->volumeError;
274 return reqp->rpcError;
278 error = et_to_sys_error(error);
280 if (error == RX_CALL_DEAD ||
281 error == RX_CALL_TIMEOUT ||
282 error == RX_CALL_BUSY ||
283 error == RX_CALL_IDLE ||
285 error = CM_ERROR_RETRY;
286 else if (error == VNOVNODE)
287 error = CM_ERROR_BADFD;
288 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
289 error = CM_ERROR_ALLOFFLINE;
290 else if (error == VBUSY || error == VRESTARTING)
291 error = CM_ERROR_ALLBUSY;
293 error = CM_ERROR_UNKNOWN;
294 else if (error == EROFS)
295 error = CM_ERROR_READONLY;
296 else if (error == ENOTDIR)
297 error = CM_ERROR_NOTDIR;
298 else if (error == EACCES)
299 error = CM_ERROR_NOACCESS;
300 else if (error == ENOENT)
301 error = CM_ERROR_NOSUCHFILE;
302 else if (error == EINVAL)
303 error = CM_ERROR_INVAL;
304 else if (error == ENOTEMPTY
305 || error == 17 /* AIX */
306 || error == 66 /* SunOS 4, Digital UNIX */
307 || error == 93 /* Solaris 2, IRIX */
308 || error == 247) /* HP/UX */
309 error = CM_ERROR_NOTEMPTY;
313 long cm_MapVLRPCError(long error, cm_req_t *reqp)
315 if (error == 0) return 0;
317 /* If we had to stop retrying, report our saved error code. */
318 if (reqp && error == CM_ERROR_TIMEDOUT) {
319 if (reqp->accessError)
320 return reqp->accessError;
321 if (reqp->volumeError)
322 return reqp->volumeError;
324 return reqp->rpcError;
328 error = et_to_sys_error(error);
330 if (error == RX_CALL_DEAD ||
331 error == RX_CALL_TIMEOUT ||
332 error == RX_CALL_BUSY ||
333 error == RX_CALL_IDLE ||
335 error = CM_ERROR_RETRY;
336 else if (error == RX_RESTARTING)
337 error = CM_ERROR_ALLBUSY;
339 error = CM_ERROR_UNKNOWN;
340 else if (error == EINVAL)
341 error = CM_ERROR_INVAL;
342 else if (error == VL_NOENT || error == VL_BADNAME)
343 error = CM_ERROR_NOSUCHVOLUME;
347 cm_space_t *cm_GetSpace(void)
353 lock_ObtainWrite(&cm_utilsLock);
354 if (tsp = cm_spaceListp) {
355 cm_spaceListp = tsp->nextp;
357 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
358 (void) memset(tsp, 0, sizeof(cm_space_t));
359 lock_ReleaseWrite(&cm_utilsLock);
364 void cm_FreeSpace(cm_space_t *tsp)
366 lock_ObtainWrite(&cm_utilsLock);
367 tsp->nextp = cm_spaceListp;
369 lock_ReleaseWrite(&cm_utilsLock);
372 /* characters that are legal in an 8.3 name */
374 * We used to have 1's for all characters from 128 to 254. But
375 * the NT client behaves better if we create an 8.3 name for any
376 * name that has a character with the high bit on, and if we
377 * delete those characters from 8.3 names. In particular, see
378 * Sybase defect 10859.
380 char cm_LegalChars[256] = {
381 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
383 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
384 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
385 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
386 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
387 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
388 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
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,
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
399 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
401 /* return true iff component is a valid 8.3 name */
402 int cm_Is8Dot3(clientchar_t *namep)
408 if (namep == NULL || !namep[0])
412 * can't have a leading dot;
413 * special case for . and ..
415 if (namep[0] == '.') {
418 if (namep[1] == '.' && namep[2] == 0)
422 while (tc = *namep++) {
424 /* saw another dot */
425 if (sawDot) return 0; /* second dot */
430 if (!ISLEGALCHAR(tc))
433 if (!sawDot && charCount > 8)
434 /* more than 8 chars in name */
436 if (sawDot && charCount > 3)
437 /* more than 3 chars in extension */
444 * Number unparsing map for generating 8.3 names;
445 * The version taken from DFS was on drugs.
446 * You can't include '&' and '@' in a file name.
448 char cm_8Dot3Mapping[42] =
449 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
450 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
451 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
452 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
454 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
456 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
457 clientchar_t *shortName, clientchar_t **shortNameEndp)
461 int vnode = ntohl(pfid->vnode);
463 int validExtension = 0;
467 /* Unparse the file's vnode number to get a "uniquifier" */
469 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
471 vnode /= cm_8Dot3MapSize;
475 * Look for valid extension. There has to be a dot, and
476 * at least one of the characters following has to be legal.
478 lastDot = strrchr(longname, '.');
480 temp = lastDot; temp++;
488 /* Copy name characters */
489 for (i = 0, name = longname;
490 i < (7 - nsize) && name != lastDot; ) {
495 if (!ISLEGALCHAR(tc))
498 *shortName++ = toupper(tc);
504 /* Copy uniquifier characters */
505 for (i=0; i < nsize; i++) {
506 *shortName++ = number[i];
509 if (validExtension) {
510 /* Copy extension characters */
511 *shortName++ = *lastDot++; /* copy dot */
512 for (i = 0, tc = *lastDot++;
515 if (ISLEGALCHAR(tc)) {
517 *shortName++ = toupper(tc);
526 *shortNameEndp = shortName;
529 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
530 clientchar_t *shortName, clientchar_t **shortNameEndp)
532 clientchar_t number[12];
534 int vnode = ntohl(pfid->vnode);
535 clientchar_t *lastDot;
536 int validExtension = 0;
537 clientchar_t tc, *temp;
538 const clientchar_t *name;
540 /* Unparse the file's vnode number to get a "uniquifier" */
542 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
544 vnode /= cm_8Dot3MapSize;
548 * Look for valid extension. There has to be a dot, and
549 * at least one of the characters following has to be legal.
551 lastDot = cm_ClientStrRChr(longname, '.');
553 temp = lastDot; temp++;
561 /* Copy name characters */
562 for (i = 0, name = longname;
563 i < (7 - nsize) && name != lastDot; ) {
568 if (!ISLEGALCHAR(tc))
571 *shortName++ = toupper((char) tc);
577 /* Copy uniquifier characters */
578 for (i=0; i < nsize; i++) {
579 *shortName++ = number[i];
582 if (validExtension) {
583 /* Copy extension characters */
584 *shortName++ = *lastDot++; /* copy dot */
585 for (i = 0, tc = *lastDot++;
588 if (ISLEGALCHAR(tc)) {
590 *shortName++ = toupper(tc);
599 *shortNameEndp = shortName;
602 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
603 clientchar_t *shortName, clientchar_t **shortNameEndp)
605 clientchar_t number[12];
607 int validExtension = 0;
609 /* Unparse the file's cell and volume numbers */
611 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
613 cell /= cm_8Dot3MapSize;
616 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
618 volume /= cm_8Dot3MapSize;
619 } while (volume && nsize < 8);
621 /* Copy uniquifier characters */
622 for (i=0; i < nsize; i++) {
623 *shortName++ = number[i];
626 /* Add extension characters */
627 *shortName++ = '.'; /* copy dot */
636 *shortNameEndp = shortName;
639 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
641 \note This procedure works recursively calling itself.
643 \param[in] pattern string containing metacharacters.
644 \param[in] name File name to be compared with 'pattern'.
646 \return BOOL : TRUE/FALSE (match/mistmatch)
649 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
651 clientchar_t upattern[MAX_PATH];
652 clientchar_t uname[MAX_PATH];
654 clientchar_t * pename; // points to the last 'name' character
656 clientchar_t * pattern_next;
659 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
660 cm_ClientStrUpr(upattern);
663 cm_ClientStrCpy(uname, lengthof(uname), name);
664 cm_ClientStrUpr(uname);
667 /* The following translations all work on single byte
669 for (p=upattern; *p; p++) {
670 if (*p == '"') *p = '.'; continue;
671 if (*p == '<') *p = '*'; continue;
672 if (*p == '>') *p = '?'; continue;
675 for (p=uname; *p; p++) {
676 if (*p == '"') *p = '.'; continue;
677 if (*p == '<') *p = '*'; continue;
678 if (*p == '>') *p = '?'; continue;
682 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
687 pattern = cm_ClientCharNext(pattern);
690 name = cm_ClientCharNext(name);
694 pattern = cm_ClientCharNext(pattern);
695 if (*pattern == '\0')
698 pattern_next = cm_ClientCharNext(pattern);
700 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
701 if (*p == *pattern &&
702 szWildCardMatchFileName(pattern_next,
703 cm_ClientCharNext(p), FALSE))
706 if (*pattern == '.' && *pattern_next == '\0') {
707 for (p = name; p && *p; p = cm_ClientCharNext(p))
717 if (*name != *pattern)
719 pattern = cm_ClientCharNext(pattern);
720 name = cm_ClientCharNext(name);
725 /* if all we have left are wildcards, then we match */
726 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
727 if (*pattern != '*' && *pattern != '?')
733 /* do a case-folding search of the star name mask with the name in namep.
734 * Return 1 if we match, otherwise 0.
736 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
738 clientchar_t *newmask, lastchar = _C('\0');
739 int i, j, casefold, retval;
740 int star = 0, qmark = 0, dot = 0;
742 /* make sure we only match 8.3 names, if requested */
743 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
746 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
748 /* optimize the pattern:
749 * if there is a mixture of '?' and '*',
750 * for example the sequence "*?*?*?*"
751 * must be turned into the form "*"
753 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
754 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
756 switch ( maskp[i] ) {
771 } else if ( qmark ) {
775 newmask[j++] = maskp[i];
782 } else if ( qmark ) {
786 if (dot == 0 && lastchar == '<')
790 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
797 cm_TargetPerceivedAsDirectory(const fschar_t *target)
801 ext = PathFindExtension(target);
809 cm_LoadAfsdHookLib(void)
815 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
818 p = strrchr(dllname, '\\');
821 strcpy(p, AFSD_HOOK_DLL);
822 hLib = LoadLibrary(dllname);
824 hLib = LoadLibrary(AFSD_HOOK_DLL);
831 * Obtain the file info structure for the specified file.
832 * If a full path is not specified, the search order is the
833 * same as that used by LoadLibrary().
836 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
844 VS_FIXEDFILEINFO vsf;
846 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
851 pInfo = (char*)malloc(dwSize);
856 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
859 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
862 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
864 liVer->LowPart = vsf.dwFileVersionLS;
865 liVer->HighPart = vsf.dwFileVersionMS;
874 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
875 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
876 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
878 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
880 static BOOL fChecked = FALSE;
881 static BOOL fSupportsExtendedTimeouts = FALSE;
885 BOOL isWow64 = FALSE;
886 OSVERSIONINFOEX Version;
888 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
889 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
890 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
891 PVOID Wow64RedirectionState;
892 LARGE_INTEGER fvFile, fvHotFixMin;
894 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
896 * If we don't find the fnIsWow64Process function then we
897 * are not running in a Wow64 environment
900 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
902 memset (&Version, 0x00, sizeof(Version));
903 Version.dwOSVersionInfoSize = sizeof(Version);
904 GetVersionEx((OSVERSIONINFO *) &Version);
907 * Support is available as hot fixes / service packs on:
914 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
915 Version.dwMajorVersion >= 5) {
918 if (Version.dwMajorVersion == 5 &&
919 Version.dwMinorVersion == 1) {
921 fvHotFixMin.HighPart = (5 << 16) | 1;
923 switch (Version.wServicePackMajor) {
925 fvHotFixMin.LowPart = (2600 << 16) | 5815;
928 fvHotFixMin.LowPart = (2600 << 16) | 3572;
931 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
936 /* 64-bit XP and Server 2003 */
937 else if (Version.dwMajorVersion == 5 &&
938 Version.dwMinorVersion == 2) {
940 fvHotFixMin.HighPart = (5 << 16) | 2;
942 switch (Version.wServicePackMajor) {
944 fvHotFixMin.LowPart = (3790 << 16) | 4479;
947 fvHotFixMin.LowPart = (3790 << 16) | 3310;
950 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
955 /* Vista and Server 2008 */
956 else if (Version.dwMajorVersion == 6 &&
957 Version.dwMinorVersion == 0) {
959 fvHotFixMin.HighPart = (6 << 16) | 0;
961 switch (Version.wServicePackMajor) {
963 fvHotFixMin.LowPart = (6002 << 16) | 18005;
966 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
971 /* Windows 7 and Server 2008 R2 and beyond */
972 else if (Version.dwMajorVersion > 6 ||
973 Version.dwMajorVersion == 6 &&
974 Version.dwMinorVersion >= 1) {
975 fSupportsExtendedTimeouts = TRUE;
979 /* If wow64, disable wow64 redirection and preserve the existing state */
980 if (fnIsWow64Process &&
981 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
983 fnDisableWow64FsRedirection =
984 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
985 fnRevertWow64FsRedirection =
986 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
987 fnDisableWow64FsRedirection(&Wow64RedirectionState);
990 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
991 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
992 fSupportsExtendedTimeouts = TRUE;
994 /* If wow64, restore the previous redirection state */
995 if (fnIsWow64Process && isWow64) {
996 fnRevertWow64FsRedirection(Wow64RedirectionState);
1003 return fSupportsExtendedTimeouts;
1006 void cm_ResetServerPriority()
1008 void * p = TlsGetValue(cm_TlsRequestSlot);
1011 TlsSetValue(cm_TlsRequestSlot, NULL);
1012 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1016 void cm_SetRequestStartTime()
1018 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1020 tp = malloc(sizeof(time_t));
1024 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1029 void cm_UpdateServerPriority()
1031 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1034 time_t now = osi_Time();
1036 /* Give one priority boost for each 15 seconds */
1037 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1042 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1044 // Note that LONGLONG is a 64-bit value
1047 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1048 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1049 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1052 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1054 // Note that LONGLONG is a 64-bit value
1057 ll = largeTimep->dwHighDateTime;
1059 ll += largeTimep->dwLowDateTime;
1061 ll -= 116444736000000000;
1064 *unixTimep = (DWORD)ll;
1067 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1072 struct tm localJunk;
1073 time_t t = unixTime;
1075 ltp = localtime(&t);
1077 /* if we fail, make up something */
1080 localJunk.tm_year = 89 - 20;
1081 localJunk.tm_mon = 4;
1082 localJunk.tm_mday = 12;
1083 localJunk.tm_hour = 0;
1084 localJunk.tm_min = 0;
1085 localJunk.tm_sec = 0;
1088 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1089 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1090 *searchTimep = (dosDate<<16) | dosTime;
1093 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1095 unsigned short dosDate;
1096 unsigned short dosTime;
1099 dosDate = (unsigned short) (searchTime & 0xffff);
1100 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1102 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1103 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1104 localTm.tm_mday = (dosDate) & 0x1f;
1105 localTm.tm_hour = (dosTime>>11) & 0x1f;
1106 localTm.tm_min = (dosTime >> 5) & 0x3f;
1107 localTm.tm_sec = (dosTime & 0x1f) * 2;
1108 localTm.tm_isdst = -1; /* compute whether DST in effect */
1110 *unixTimep = mktime(&localTm);
1114 cm_NextHighestPowerOf2(afs_uint32 n)