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_RETRY;
220 else if (error == RX_CALL_IDLE)
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_CALL_IDLE ||
286 error == RX_MSGSIZE ||
288 error = CM_ERROR_RETRY;
289 else if (error == VNOVNODE)
290 error = CM_ERROR_BADFD;
291 else if (error == VSALVAGE || error == VOFFLINE)
292 error = CM_ERROR_ALLOFFLINE;
293 else if (error == VBUSY || error == VRESTARTING)
294 error = CM_ERROR_ALLBUSY;
296 error = CM_ERROR_UNKNOWN;
297 else if (error == EROFS)
298 error = CM_ERROR_READONLY;
299 else if (error == ENOTDIR)
300 error = CM_ERROR_NOTDIR;
301 else if (error == EACCES)
302 error = CM_ERROR_NOACCESS;
303 else if (error == ENOENT)
304 error = CM_ERROR_NOSUCHFILE;
305 else if (error == EINVAL)
306 error = CM_ERROR_INVAL;
307 else if (error == ENOTEMPTY
308 || error == 17 /* AIX */
309 || error == 66 /* SunOS 4, Digital UNIX */
310 || error == 93 /* Solaris 2, IRIX */
311 || error == 247) /* HP/UX */
312 error = CM_ERROR_NOTEMPTY;
316 long cm_MapVLRPCError(long error, cm_req_t *reqp)
318 if (error == 0) return 0;
320 /* If we had to stop retrying, report our saved error code. */
321 if (reqp && error == CM_ERROR_TIMEDOUT) {
322 if (reqp->accessError)
323 return reqp->accessError;
324 if (reqp->volumeError)
325 return reqp->volumeError;
327 return reqp->rpcError;
331 error = et_to_sys_error(error);
333 if (error == RX_CALL_DEAD ||
334 error == RX_CALL_TIMEOUT ||
335 error == RX_CALL_BUSY ||
336 error == RX_CALL_IDLE ||
337 error == RX_MSGSIZE ||
339 error = CM_ERROR_RETRY;
340 else if (error == RX_RESTARTING)
341 error = CM_ERROR_ALLBUSY;
343 error = CM_ERROR_UNKNOWN;
344 else if (error == EINVAL)
345 error = CM_ERROR_INVAL;
346 else if (error == VL_NOENT || error == VL_BADNAME)
347 error = CM_ERROR_NOSUCHVOLUME;
351 cm_space_t *cm_GetSpace(void)
357 lock_ObtainWrite(&cm_utilsLock);
358 if (tsp = cm_spaceListp) {
359 cm_spaceListp = tsp->nextp;
361 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
362 (void) memset(tsp, 0, sizeof(cm_space_t));
363 lock_ReleaseWrite(&cm_utilsLock);
368 void cm_FreeSpace(cm_space_t *tsp)
370 lock_ObtainWrite(&cm_utilsLock);
371 tsp->nextp = cm_spaceListp;
373 lock_ReleaseWrite(&cm_utilsLock);
376 /* characters that are legal in an 8.3 name */
378 * We used to have 1's for all characters from 128 to 254. But
379 * the NT client behaves better if we create an 8.3 name for any
380 * name that has a character with the high bit on, and if we
381 * delete those characters from 8.3 names. In particular, see
382 * Sybase defect 10859.
384 char cm_LegalChars[256] = {
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, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
388 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
391 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
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,
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
403 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
405 /* return true iff component is a valid 8.3 name */
406 int cm_Is8Dot3(clientchar_t *namep)
412 if (namep == NULL || !namep[0])
416 * can't have a leading dot;
417 * special case for . and ..
419 if (namep[0] == '.') {
422 if (namep[1] == '.' && namep[2] == 0)
426 while (tc = *namep++) {
428 /* saw another dot */
429 if (sawDot) return 0; /* second dot */
434 if (!ISLEGALCHAR(tc))
437 if (!sawDot && charCount > 8)
438 /* more than 8 chars in name */
440 if (sawDot && charCount > 3)
441 /* more than 3 chars in extension */
448 * Number unparsing map for generating 8.3 names;
449 * The version taken from DFS was on drugs.
450 * You can't include '&' and '@' in a file name.
452 char cm_8Dot3Mapping[42] =
453 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
454 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
455 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
456 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
458 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
460 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
461 clientchar_t *shortName, clientchar_t **shortNameEndp)
465 int vnode = ntohl(pfid->vnode);
467 int validExtension = 0;
471 /* Unparse the file's vnode number to get a "uniquifier" */
473 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
475 vnode /= cm_8Dot3MapSize;
479 * Look for valid extension. There has to be a dot, and
480 * at least one of the characters following has to be legal.
482 lastDot = strrchr(longname, '.');
484 temp = lastDot; temp++;
492 /* Copy name characters */
493 for (i = 0, name = longname;
494 i < (7 - nsize) && name != lastDot; ) {
499 if (!ISLEGALCHAR(tc))
502 *shortName++ = toupper(tc);
508 /* Copy uniquifier characters */
509 for (i=0; i < nsize; i++) {
510 *shortName++ = number[i];
513 if (validExtension) {
514 /* Copy extension characters */
515 *shortName++ = *lastDot++; /* copy dot */
516 for (i = 0, tc = *lastDot++;
519 if (ISLEGALCHAR(tc)) {
521 *shortName++ = toupper(tc);
530 *shortNameEndp = shortName;
533 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
534 clientchar_t *shortName, clientchar_t **shortNameEndp)
536 clientchar_t number[12];
538 int vnode = ntohl(pfid->vnode);
539 clientchar_t *lastDot;
540 int validExtension = 0;
541 clientchar_t tc, *temp;
542 const clientchar_t *name;
544 /* Unparse the file's vnode number to get a "uniquifier" */
546 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
548 vnode /= cm_8Dot3MapSize;
552 * Look for valid extension. There has to be a dot, and
553 * at least one of the characters following has to be legal.
555 lastDot = cm_ClientStrRChr(longname, '.');
557 temp = lastDot; temp++;
565 /* Copy name characters */
566 for (i = 0, name = longname;
567 i < (7 - nsize) && name != lastDot; ) {
572 if (!ISLEGALCHAR(tc))
575 *shortName++ = toupper((char) tc);
581 /* Copy uniquifier characters */
582 for (i=0; i < nsize; i++) {
583 *shortName++ = number[i];
586 if (validExtension) {
587 /* Copy extension characters */
588 *shortName++ = *lastDot++; /* copy dot */
589 for (i = 0, tc = *lastDot++;
592 if (ISLEGALCHAR(tc)) {
594 *shortName++ = toupper(tc);
603 *shortNameEndp = shortName;
606 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
607 clientchar_t *shortName, clientchar_t **shortNameEndp)
609 clientchar_t number[12];
611 int validExtension = 0;
613 /* Unparse the file's cell and volume numbers */
615 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
617 cell /= cm_8Dot3MapSize;
620 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
622 volume /= cm_8Dot3MapSize;
623 } while (volume && nsize < 8);
625 /* Copy uniquifier characters */
626 for (i=0; i < nsize; i++) {
627 *shortName++ = number[i];
630 /* Add extension characters */
631 *shortName++ = '.'; /* copy dot */
640 *shortNameEndp = shortName;
643 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
645 \note This procedure works recursively calling itself.
647 \param[in] pattern string containing metacharacters.
648 \param[in] name File name to be compared with 'pattern'.
650 \return BOOL : TRUE/FALSE (match/mistmatch)
653 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
655 clientchar_t upattern[MAX_PATH];
656 clientchar_t uname[MAX_PATH];
658 clientchar_t * pename; // points to the last 'name' character
660 clientchar_t * pattern_next;
663 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
664 cm_ClientStrUpr(upattern);
667 cm_ClientStrCpy(uname, lengthof(uname), name);
668 cm_ClientStrUpr(uname);
671 /* The following translations all work on single byte
673 for (p=upattern; *p; p++) {
674 if (*p == '"') *p = '.'; continue;
675 if (*p == '<') *p = '*'; continue;
676 if (*p == '>') *p = '?'; continue;
679 for (p=uname; *p; p++) {
680 if (*p == '"') *p = '.'; continue;
681 if (*p == '<') *p = '*'; continue;
682 if (*p == '>') *p = '?'; continue;
686 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
691 pattern = cm_ClientCharNext(pattern);
694 name = cm_ClientCharNext(name);
698 pattern = cm_ClientCharNext(pattern);
699 if (*pattern == '\0')
702 pattern_next = cm_ClientCharNext(pattern);
704 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
705 if (*p == *pattern &&
706 szWildCardMatchFileName(pattern_next,
707 cm_ClientCharNext(p), FALSE))
710 if (*pattern == '.' && *pattern_next == '\0') {
711 for (p = name; p && *p; p = cm_ClientCharNext(p))
721 if (*name != *pattern)
723 pattern = cm_ClientCharNext(pattern);
724 name = cm_ClientCharNext(name);
729 /* if all we have left are wildcards, then we match */
730 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
731 if (*pattern != '*' && *pattern != '?')
737 /* do a case-folding search of the star name mask with the name in namep.
738 * Return 1 if we match, otherwise 0.
740 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
742 clientchar_t *newmask, lastchar = _C('\0');
743 int i, j, casefold, retval;
744 int star = 0, qmark = 0, dot = 0;
746 /* make sure we only match 8.3 names, if requested */
747 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
750 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
752 /* optimize the pattern:
753 * if there is a mixture of '?' and '*',
754 * for example the sequence "*?*?*?*"
755 * must be turned into the form "*"
757 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
758 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
760 switch ( maskp[i] ) {
775 } else if ( qmark ) {
779 newmask[j++] = maskp[i];
786 } else if ( qmark ) {
790 if (dot == 0 && lastchar == '<')
794 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
801 cm_TargetPerceivedAsDirectory(const fschar_t *target)
805 ext = PathFindExtension(target);
813 cm_LoadAfsdHookLib(void)
819 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
822 p = strrchr(dllname, '\\');
825 strcpy(p, AFSD_HOOK_DLL);
826 hLib = LoadLibrary(dllname);
828 hLib = LoadLibrary(AFSD_HOOK_DLL);
835 * Obtain the file info structure for the specified file.
836 * If a full path is not specified, the search order is the
837 * same as that used by LoadLibrary().
840 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
848 VS_FIXEDFILEINFO vsf;
850 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
855 pInfo = (char*)malloc(dwSize);
860 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
863 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
866 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
868 liVer->LowPart = vsf.dwFileVersionLS;
869 liVer->HighPart = vsf.dwFileVersionMS;
878 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
879 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
880 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
882 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
884 static BOOL fChecked = FALSE;
885 static BOOL fSupportsExtendedTimeouts = FALSE;
889 BOOL isWow64 = FALSE;
890 OSVERSIONINFOEX Version;
892 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
893 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
894 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
895 PVOID Wow64RedirectionState;
896 LARGE_INTEGER fvFile, fvHotFixMin;
898 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
900 * If we don't find the fnIsWow64Process function then we
901 * are not running in a Wow64 environment
904 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
906 memset (&Version, 0x00, sizeof(Version));
907 Version.dwOSVersionInfoSize = sizeof(Version);
908 GetVersionEx((OSVERSIONINFO *) &Version);
911 * Support is available as hot fixes / service packs on:
918 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
919 Version.dwMajorVersion >= 5) {
922 if (Version.dwMajorVersion == 5 &&
923 Version.dwMinorVersion == 1) {
925 fvHotFixMin.HighPart = (5 << 16) | 1;
927 switch (Version.wServicePackMajor) {
929 fvHotFixMin.LowPart = (2600 << 16) | 5815;
932 fvHotFixMin.LowPart = (2600 << 16) | 3572;
935 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
940 /* 64-bit XP and Server 2003 */
941 else if (Version.dwMajorVersion == 5 &&
942 Version.dwMinorVersion == 2) {
944 fvHotFixMin.HighPart = (5 << 16) | 2;
946 switch (Version.wServicePackMajor) {
948 fvHotFixMin.LowPart = (3790 << 16) | 4479;
951 fvHotFixMin.LowPart = (3790 << 16) | 3310;
954 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
959 /* Vista and Server 2008 */
960 else if (Version.dwMajorVersion == 6 &&
961 Version.dwMinorVersion == 0) {
963 fvHotFixMin.HighPart = (6 << 16) | 0;
965 switch (Version.wServicePackMajor) {
967 fvHotFixMin.LowPart = (6002 << 16) | 18005;
970 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
975 /* Windows 7 and Server 2008 R2 and beyond */
976 else if (Version.dwMajorVersion > 6 ||
977 Version.dwMajorVersion == 6 &&
978 Version.dwMinorVersion >= 1) {
979 fSupportsExtendedTimeouts = TRUE;
983 /* If wow64, disable wow64 redirection and preserve the existing state */
984 if (fnIsWow64Process &&
985 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
987 fnDisableWow64FsRedirection =
988 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
989 fnRevertWow64FsRedirection =
990 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
991 fnDisableWow64FsRedirection(&Wow64RedirectionState);
994 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
995 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
996 fSupportsExtendedTimeouts = TRUE;
998 /* If wow64, restore the previous redirection state */
999 if (fnIsWow64Process && isWow64) {
1000 fnRevertWow64FsRedirection(Wow64RedirectionState);
1007 return fSupportsExtendedTimeouts;
1010 void cm_ResetServerPriority()
1012 void * p = TlsGetValue(cm_TlsRequestSlot);
1015 TlsSetValue(cm_TlsRequestSlot, NULL);
1016 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1020 void cm_SetRequestStartTime()
1022 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1024 tp = malloc(sizeof(time_t));
1028 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1033 void cm_UpdateServerPriority()
1035 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1038 time_t now = osi_Time();
1040 /* Give one priority boost for each 15 seconds */
1041 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1046 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1048 // Note that LONGLONG is a 64-bit value
1051 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1052 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1053 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1056 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1058 // Note that LONGLONG is a 64-bit value
1061 ll = largeTimep->dwHighDateTime;
1063 ll += largeTimep->dwLowDateTime;
1065 ll -= 116444736000000000;
1068 *unixTimep = (DWORD)ll;
1071 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1076 struct tm localJunk;
1077 time_t t = unixTime;
1079 ltp = localtime(&t);
1081 /* if we fail, make up something */
1084 localJunk.tm_year = 89 - 20;
1085 localJunk.tm_mon = 4;
1086 localJunk.tm_mday = 12;
1087 localJunk.tm_hour = 0;
1088 localJunk.tm_min = 0;
1089 localJunk.tm_sec = 0;
1092 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1093 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1094 *searchTimep = (dosDate<<16) | dosTime;
1097 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1099 unsigned short dosDate;
1100 unsigned short dosTime;
1103 dosDate = (unsigned short) (searchTime & 0xffff);
1104 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1106 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1107 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1108 localTm.tm_mday = (dosDate) & 0x1f;
1109 localTm.tm_hour = (dosTime>>11) & 0x1f;
1110 localTm.tm_min = (dosTime >> 5) & 0x3f;
1111 localTm.tm_sec = (dosTime & 0x1f) * 2;
1112 localTm.tm_isdst = -1; /* compute whether DST in effect */
1114 *unixTimep = mktime(&localTm);
1118 cm_NextHighestPowerOf2(afs_uint32 n)