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 <afs/param.h>
19 #define STRSAFE_NO_DEPRECATE
26 #include <afs/unified_afs.h>
28 static osi_once_t cm_utilsOnce;
30 osi_rwlock_t cm_utilsLock;
32 cm_space_t *cm_spaceListp;
34 static int et2sys[512];
36 static DWORD cm_TlsRequestSlot = -1;
38 void cm_utilsInit(void)
40 if (osi_Once(&cm_utilsOnce)) {
41 lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock", LOCK_HIERARCHY_UTILS_GLOBAL);
43 cm_TlsRequestSlot = TlsAlloc();
45 osi_EndOnce(&cm_utilsOnce);
49 void cm_utilsCleanup(void)
51 TlsFree(cm_TlsRequestSlot);
55 init_et_to_sys_error(void)
57 memset(&et2sys, 0, sizeof(et2sys));
58 et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
59 et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
60 et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
61 et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
62 et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
63 et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
64 et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
65 et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
66 et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
67 et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
68 et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
69 et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
70 et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
71 et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
72 et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
73 et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
74 et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
75 et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
76 et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
77 et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
78 et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
79 et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
80 et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
81 et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
82 et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
83 et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
84 et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
85 et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
86 et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
87 et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
88 et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
89 et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
90 et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
91 et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
92 et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
93 et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
94 et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
95 et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
96 et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
97 et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
98 et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
99 et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
100 et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
101 et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
102 et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
103 et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
104 et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
105 et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
106 et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
107 et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
108 et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
109 et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
110 et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
111 et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
112 et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
113 et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
114 et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
115 et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
116 et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
117 et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
118 et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
119 et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
120 et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
121 et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
122 et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
123 et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
124 et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
125 et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
126 et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
127 et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
128 et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
129 et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
130 et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
131 et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
132 et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
133 et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
134 et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
135 et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
136 et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
137 et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
138 et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
139 et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
140 et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
141 et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
142 et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
143 et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
144 et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
145 et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
146 et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
147 et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
148 et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
149 et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
150 et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
151 et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
152 et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
153 et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
154 et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
155 et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
156 et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
157 et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
158 et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
159 et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
160 et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
161 et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
162 et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
163 et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
164 et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
165 et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
166 et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
167 et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
168 et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
169 et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
170 et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
171 et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
172 et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
173 et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
174 et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
175 et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
176 et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
177 et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
178 et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
179 et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
180 et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
184 et_to_sys_error(afs_int32 in)
186 if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
188 if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
189 return et2sys[in - ERROR_TABLE_BASE_uae];
193 long cm_MapRPCError(long error, cm_req_t *reqp)
198 /* If we had to stop retrying, report our saved error code. */
199 if (reqp && error == CM_ERROR_TIMEDOUT) {
200 if (reqp->accessError)
201 return reqp->accessError;
202 if (reqp->volumeError)
203 return reqp->volumeError;
205 return reqp->rpcError;
209 error = et_to_sys_error(error);
211 if (error == RX_CALL_DEAD ||
212 error == RX_CALL_TIMEOUT ||
214 error = CM_ERROR_RETRY;
216 error = CM_ERROR_UNKNOWN;
217 else if (error == EINVAL)
218 error = CM_ERROR_INVAL;
219 else if (error == EROFS)
220 error = CM_ERROR_READONLY;
221 else if (error == EACCES)
222 error = CM_ERROR_NOACCESS;
223 else if (error == EXDEV)
224 error = CM_ERROR_CROSSDEVLINK;
225 else if (error == EEXIST)
226 error = CM_ERROR_EXISTS;
227 else if (error == ENOTDIR)
228 error = CM_ERROR_NOTDIR;
229 else if (error == ENOENT)
230 error = CM_ERROR_NOSUCHFILE;
231 else if (error == EAGAIN
232 || error == 35 /* EAGAIN, Digital UNIX */
233 || error == WSAEWOULDBLOCK)
234 error = CM_ERROR_WOULDBLOCK;
235 else if (error == VDISKFULL
237 error = CM_ERROR_SPACE;
238 else if (error == VOVERQUOTA
240 || error == 49 /* EDQUOT on Solaris */
241 || error == 88 /* EDQUOT on AIX */
242 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
243 || error == 122 /* EDQUOT on Linux */
244 || error == 1133) /* EDQUOT on Irix */
245 error = CM_ERROR_QUOTA;
246 else if (error == VNOVNODE)
247 error = CM_ERROR_BADFD;
248 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
249 error = CM_ERROR_ALLOFFLINE;
250 else if (error == VBUSY || error == VRESTARTING)
251 error = CM_ERROR_ALLBUSY;
252 else if (error == EISDIR)
253 return CM_ERROR_ISDIR;
257 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
262 /* If we had to stop retrying, report our saved error code. */
263 if (reqp && error == CM_ERROR_TIMEDOUT) {
264 if (reqp->accessError)
265 return reqp->accessError;
266 if (reqp->volumeError)
267 return reqp->volumeError;
269 return reqp->rpcError;
273 error = et_to_sys_error(error);
275 if (error == RX_CALL_DEAD ||
276 error == RX_CALL_TIMEOUT ||
278 error = CM_ERROR_RETRY;
279 else if (error == VNOVNODE)
280 error = CM_ERROR_BADFD;
281 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
282 error = CM_ERROR_ALLOFFLINE;
283 else if (error == VBUSY || error == VRESTARTING)
284 error = CM_ERROR_ALLBUSY;
286 error = CM_ERROR_UNKNOWN;
287 else if (error == EROFS)
288 error = CM_ERROR_READONLY;
289 else if (error == ENOTDIR)
290 error = CM_ERROR_NOTDIR;
291 else if (error == EACCES)
292 error = CM_ERROR_NOACCESS;
293 else if (error == ENOENT)
294 error = CM_ERROR_NOSUCHFILE;
295 else if (error == EINVAL)
296 error = CM_ERROR_INVAL;
297 else if (error == ENOTEMPTY
298 || error == 17 /* AIX */
299 || error == 66 /* SunOS 4, Digital UNIX */
300 || error == 93 /* Solaris 2, IRIX */
301 || error == 247) /* HP/UX */
302 error = CM_ERROR_NOTEMPTY;
306 long cm_MapVLRPCError(long error, cm_req_t *reqp)
308 if (error == 0) return 0;
310 /* If we had to stop retrying, report our saved error code. */
311 if (reqp && error == CM_ERROR_TIMEDOUT) {
312 if (reqp->accessError)
313 return reqp->accessError;
314 if (reqp->volumeError)
315 return reqp->volumeError;
317 return reqp->rpcError;
321 error = et_to_sys_error(error);
323 if (error == RX_CALL_DEAD ||
324 error == RX_CALL_TIMEOUT ||
326 error = CM_ERROR_RETRY;
327 else if (error == RX_RESTARTING)
328 error = CM_ERROR_ALLBUSY;
330 error = CM_ERROR_UNKNOWN;
331 else if (error == EINVAL)
332 error = CM_ERROR_INVAL;
333 else if (error == VL_NOENT || error == VL_BADNAME)
334 error = CM_ERROR_NOSUCHVOLUME;
338 cm_space_t *cm_GetSpace(void)
344 lock_ObtainWrite(&cm_utilsLock);
345 if (tsp = cm_spaceListp) {
346 cm_spaceListp = tsp->nextp;
348 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
349 (void) memset(tsp, 0, sizeof(cm_space_t));
350 lock_ReleaseWrite(&cm_utilsLock);
355 void cm_FreeSpace(cm_space_t *tsp)
357 lock_ObtainWrite(&cm_utilsLock);
358 tsp->nextp = cm_spaceListp;
360 lock_ReleaseWrite(&cm_utilsLock);
363 /* characters that are legal in an 8.3 name */
365 * We used to have 1's for all characters from 128 to 254. But
366 * the NT client behaves better if we create an 8.3 name for any
367 * name that has a character with the high bit on, and if we
368 * delete those characters from 8.3 names. In particular, see
369 * Sybase defect 10859.
371 char cm_LegalChars[256] = {
372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
375 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
376 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
377 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
378 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
379 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
380 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 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
390 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
392 /* return true iff component is a valid 8.3 name */
393 int cm_Is8Dot3(clientchar_t *namep)
399 if (namep == NULL || !namep[0])
403 * can't have a leading dot;
404 * special case for . and ..
406 if (namep[0] == '.') {
409 if (namep[1] == '.' && namep[2] == 0)
413 while (tc = *namep++) {
415 /* saw another dot */
416 if (sawDot) return 0; /* second dot */
421 if (!ISLEGALCHAR(tc))
424 if (!sawDot && charCount > 8)
425 /* more than 8 chars in name */
427 if (sawDot && charCount > 3)
428 /* more than 3 chars in extension */
435 * Number unparsing map for generating 8.3 names;
436 * The version taken from DFS was on drugs.
437 * You can't include '&' and '@' in a file name.
439 char cm_8Dot3Mapping[42] =
440 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
441 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
442 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
443 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
445 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
447 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
448 clientchar_t *shortName, clientchar_t **shortNameEndp)
452 int vnode = ntohl(pfid->vnode);
454 int validExtension = 0;
458 /* Unparse the file's vnode number to get a "uniquifier" */
460 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
462 vnode /= cm_8Dot3MapSize;
466 * Look for valid extension. There has to be a dot, and
467 * at least one of the characters following has to be legal.
469 lastDot = strrchr(longname, '.');
471 temp = lastDot; temp++;
479 /* Copy name characters */
480 for (i = 0, name = longname;
481 i < (7 - nsize) && name != lastDot; ) {
486 if (!ISLEGALCHAR(tc))
489 *shortName++ = toupper(tc);
495 /* Copy uniquifier characters */
496 for (i=0; i < nsize; i++) {
497 *shortName++ = number[i];
500 if (validExtension) {
501 /* Copy extension characters */
502 *shortName++ = *lastDot++; /* copy dot */
503 for (i = 0, tc = *lastDot++;
506 if (ISLEGALCHAR(tc)) {
508 *shortName++ = toupper(tc);
517 *shortNameEndp = shortName;
520 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
521 clientchar_t *shortName, clientchar_t **shortNameEndp)
523 clientchar_t number[12];
525 int vnode = ntohl(pfid->vnode);
526 clientchar_t *lastDot;
527 int validExtension = 0;
528 clientchar_t tc, *temp;
529 const clientchar_t *name;
531 /* Unparse the file's vnode number to get a "uniquifier" */
533 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
535 vnode /= cm_8Dot3MapSize;
539 * Look for valid extension. There has to be a dot, and
540 * at least one of the characters following has to be legal.
542 lastDot = cm_ClientStrRChr(longname, '.');
544 temp = lastDot; temp++;
552 /* Copy name characters */
553 for (i = 0, name = longname;
554 i < (7 - nsize) && name != lastDot; ) {
559 if (!ISLEGALCHAR(tc))
562 *shortName++ = toupper((char) tc);
568 /* Copy uniquifier characters */
569 for (i=0; i < nsize; i++) {
570 *shortName++ = number[i];
573 if (validExtension) {
574 /* Copy extension characters */
575 *shortName++ = *lastDot++; /* copy dot */
576 for (i = 0, tc = *lastDot++;
579 if (ISLEGALCHAR(tc)) {
581 *shortName++ = toupper(tc);
590 *shortNameEndp = shortName;
593 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
595 \note This procedure works recursively calling itself.
597 \param[in] pattern string containing metacharacters.
598 \param[in] name File name to be compared with 'pattern'.
600 \return BOOL : TRUE/FALSE (match/mistmatch)
603 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
605 clientchar_t upattern[MAX_PATH];
606 clientchar_t uname[MAX_PATH];
608 clientchar_t * pename; // points to the last 'name' character
610 clientchar_t * pattern_next;
613 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
614 cm_ClientStrUpr(upattern);
617 cm_ClientStrCpy(uname, lengthof(uname), name);
618 cm_ClientStrUpr(uname);
621 /* The following translations all work on single byte
623 for (p=upattern; *p; p++) {
624 if (*p == '"') *p = '.'; continue;
625 if (*p == '<') *p = '*'; continue;
626 if (*p == '>') *p = '?'; continue;
629 for (p=uname; *p; p++) {
630 if (*p == '"') *p = '.'; continue;
631 if (*p == '<') *p = '*'; continue;
632 if (*p == '>') *p = '?'; continue;
636 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
641 pattern = cm_ClientCharNext(pattern);
644 name = cm_ClientCharNext(name);
648 pattern = cm_ClientCharNext(pattern);
649 if (*pattern == '\0')
652 pattern_next = cm_ClientCharNext(pattern);
654 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
655 if (*p == *pattern &&
656 szWildCardMatchFileName(pattern_next,
657 cm_ClientCharNext(p), FALSE))
660 if (*pattern == '.' && *pattern_next == '\0') {
661 for (p = name; p && *p; p = cm_ClientCharNext(p))
671 if (*name != *pattern)
673 pattern = cm_ClientCharNext(pattern);
674 name = cm_ClientCharNext(name);
679 /* if all we have left are wildcards, then we match */
680 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
681 if (*pattern != '*' && *pattern != '?')
687 /* do a case-folding search of the star name mask with the name in namep.
688 * Return 1 if we match, otherwise 0.
690 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
692 clientchar_t *newmask, lastchar = _C('\0');
693 int i, j, casefold, retval;
694 int star = 0, qmark = 0, dot = 0;
696 /* make sure we only match 8.3 names, if requested */
697 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
700 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
702 /* optimize the pattern:
703 * if there is a mixture of '?' and '*',
704 * for example the sequence "*?*?*?*"
705 * must be turned into the form "*"
707 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
708 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
710 switch ( maskp[i] ) {
725 } else if ( qmark ) {
729 newmask[j++] = maskp[i];
736 } else if ( qmark ) {
740 if (dot == 0 && lastchar == '<')
744 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
751 cm_TargetPerceivedAsDirectory(const fschar_t *target)
755 ext = PathFindExtension(target);
763 cm_LoadAfsdHookLib(void)
769 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
772 p = strrchr(dllname, '\\');
775 strcpy(p, AFSD_HOOK_DLL);
776 hLib = LoadLibrary(dllname);
778 hLib = LoadLibrary(AFSD_HOOK_DLL);
785 * Obtain the file info structure for the specified file.
786 * If a full path is not specified, the search order is the
787 * same as that used by LoadLibrary().
790 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
798 VS_FIXEDFILEINFO vsf;
800 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
805 pInfo = (char*)malloc(dwSize);
810 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
813 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
816 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
818 liVer->LowPart = vsf.dwFileVersionLS;
819 liVer->HighPart = vsf.dwFileVersionMS;
828 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
829 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
830 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
832 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
834 static BOOL fChecked = FALSE;
835 static BOOL fSupportsExtendedTimeouts = FALSE;
839 BOOL isWow64 = FALSE;
840 OSVERSIONINFOEX Version;
842 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
843 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
844 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
845 PVOID Wow64RedirectionState;
846 LARGE_INTEGER fvFile, fvHotFixMin;
848 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
850 * If we don't find the fnIsWow64Process function then we
851 * are not running in a Wow64 environment
854 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
856 memset (&Version, 0x00, sizeof(Version));
857 Version.dwOSVersionInfoSize = sizeof(Version);
858 GetVersionEx((OSVERSIONINFO *) &Version);
861 * Support is available as hot fixes / service packs on:
868 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
869 Version.dwMajorVersion >= 5) {
872 if (Version.dwMajorVersion == 5 &&
873 Version.dwMinorVersion == 1) {
875 fvHotFixMin.HighPart = (5 << 16) | 1;
877 switch (Version.wServicePackMajor) {
879 fvHotFixMin.LowPart = (2600 << 16) | 5815;
882 fvHotFixMin.LowPart = (2600 << 16) | 3572;
885 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
890 /* 64-bit XP and Server 2003 */
891 else if (Version.dwMajorVersion == 5 &&
892 Version.dwMinorVersion == 2) {
894 fvHotFixMin.HighPart = (5 << 16) | 2;
896 switch (Version.wServicePackMajor) {
898 fvHotFixMin.LowPart = (3790 << 16) | 4479;
901 fvHotFixMin.LowPart = (3790 << 16) | 3310;
904 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
909 /* Vista and Server 2008 */
910 else if (Version.dwMajorVersion == 6 &&
911 Version.dwMinorVersion == 0) {
913 fvHotFixMin.HighPart = (6 << 16) | 0;
915 switch (Version.wServicePackMajor) {
917 fvHotFixMin.LowPart = (6002 << 16) | 18005;
920 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
925 /* Windows 7 and Server 2008 R2 and beyond */
926 else if (Version.dwMajorVersion > 6 ||
927 Version.dwMajorVersion == 6 &&
928 Version.dwMinorVersion >= 1) {
929 fSupportsExtendedTimeouts = TRUE;
933 /* If wow64, disable wow64 redirection and preserve the existing state */
934 if (fnIsWow64Process &&
935 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
937 fnDisableWow64FsRedirection =
938 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
939 fnRevertWow64FsRedirection =
940 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
941 fnDisableWow64FsRedirection(&Wow64RedirectionState);
944 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
945 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
946 fSupportsExtendedTimeouts = TRUE;
948 /* If wow64, restore the previous redirection state */
949 if (fnIsWow64Process && isWow64) {
950 fnRevertWow64FsRedirection(Wow64RedirectionState);
957 return fSupportsExtendedTimeouts;
960 void cm_ResetServerPriority()
962 void * p = TlsGetValue(cm_TlsRequestSlot);
965 TlsSetValue(cm_TlsRequestSlot, NULL);
966 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
970 void cm_SetRequestStartTime()
972 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
974 tp = malloc(sizeof(time_t));
978 if (!TlsSetValue(cm_TlsRequestSlot, tp))
983 void cm_UpdateServerPriority()
985 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
988 time_t now = osi_Time();
990 /* Give one priority boost for each 15 seconds */
991 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
996 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
998 // Note that LONGLONG is a 64-bit value
1001 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1002 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1003 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1006 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1008 // Note that LONGLONG is a 64-bit value
1011 ll = largeTimep->dwHighDateTime;
1013 ll += largeTimep->dwLowDateTime;
1015 ll -= 116444736000000000;
1018 *unixTimep = (DWORD)ll;
1021 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1026 struct tm localJunk;
1027 time_t t = unixTime;
1029 ltp = localtime(&t);
1031 /* if we fail, make up something */
1034 localJunk.tm_year = 89 - 20;
1035 localJunk.tm_mon = 4;
1036 localJunk.tm_mday = 12;
1037 localJunk.tm_hour = 0;
1038 localJunk.tm_min = 0;
1039 localJunk.tm_sec = 0;
1042 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1043 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1044 *searchTimep = (dosDate<<16) | dosTime;
1047 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1049 unsigned short dosDate;
1050 unsigned short dosTime;
1053 dosDate = (unsigned short) (searchTime & 0xffff);
1054 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1056 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1057 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1058 localTm.tm_mday = (dosDate) & 0x1f;
1059 localTm.tm_hour = (dosTime>>11) & 0x1f;
1060 localTm.tm_min = (dosTime >> 5) & 0x3f;
1061 localTm.tm_sec = (dosTime & 0x1f) * 2;
1062 localTm.tm_isdst = -1; /* compute whether DST in effect */
1064 *unixTimep = mktime(&localTm);