2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
22 #define STRSAFE_NO_DEPRECATE
29 #include <afs/unified_afs.h>
31 static osi_once_t cm_utilsOnce;
33 osi_rwlock_t cm_utilsLock;
35 cm_space_t *cm_spaceListp;
37 static int et2sys[512];
39 static DWORD cm_TlsRequestSlot = -1;
41 void cm_utilsInit(void)
43 if (osi_Once(&cm_utilsOnce)) {
44 lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock", LOCK_HIERARCHY_UTILS_GLOBAL);
46 cm_TlsRequestSlot = TlsAlloc();
48 osi_EndOnce(&cm_utilsOnce);
52 void cm_utilsCleanup(void)
54 TlsFree(cm_TlsRequestSlot);
58 init_et_to_sys_error(void)
60 memset(&et2sys, 0, sizeof(et2sys));
61 et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
62 et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
63 et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
64 et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
65 et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
66 et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
67 et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
68 et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
69 et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
70 et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
71 et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
72 et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
73 et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
74 et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
75 et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
76 et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
77 et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
78 et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
79 et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
80 et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
81 et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
82 et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
83 et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
84 et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
85 et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
86 et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
87 et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
88 et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
89 et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
90 et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
91 et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
92 et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
93 et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
94 et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
95 et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
96 et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
97 et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
98 et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
99 et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
100 et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
101 et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
102 et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
103 et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
104 et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
105 et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
106 et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
107 et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
108 et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
109 et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
110 et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
111 et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
112 et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
113 et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
114 et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
115 et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
116 et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
117 et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
118 et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
119 et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
120 et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
121 et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
122 et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
123 et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
124 et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
125 et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
126 et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
127 et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
128 et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
129 et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
130 et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
131 et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
132 et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
133 et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
134 et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
135 et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
136 et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
137 et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
138 et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
139 et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
140 et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
141 et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
142 et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
143 et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
144 et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
145 et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
146 et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
147 et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
148 et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
149 et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
150 et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
151 et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
152 et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
153 et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
154 et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
155 et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
156 et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
157 et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
158 et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
159 et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
160 et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
161 et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
162 et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
163 et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
164 et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
165 et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
166 et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
167 et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
168 et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
169 et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
170 et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
171 et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
172 et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
173 et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
174 et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
175 et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
176 et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
177 et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
178 et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
179 et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
180 et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
181 et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
182 et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
183 et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
187 et_to_sys_error(afs_int32 in)
189 if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
191 if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
192 return et2sys[in - ERROR_TABLE_BASE_uae];
196 long cm_MapRPCError(long error, cm_req_t *reqp)
201 /* If we had to stop retrying, report our saved error code. */
202 if (reqp && error == CM_ERROR_TIMEDOUT) {
203 if (reqp->accessError)
204 return reqp->accessError;
205 if (reqp->volumeError)
206 return reqp->volumeError;
208 return reqp->rpcError;
212 error = et_to_sys_error(error);
214 if (error == RX_CALL_DEAD ||
215 error == RX_CALL_TIMEOUT ||
217 error = CM_ERROR_RETRY;
219 error = CM_ERROR_UNKNOWN;
220 else if (error == EINVAL)
221 error = CM_ERROR_INVAL;
222 else if (error == EROFS)
223 error = CM_ERROR_READONLY;
224 else if (error == EACCES)
225 error = CM_ERROR_NOACCESS;
226 else if (error == EXDEV)
227 error = CM_ERROR_CROSSDEVLINK;
228 else if (error == EEXIST)
229 error = CM_ERROR_EXISTS;
230 else if (error == ENOTDIR)
231 error = CM_ERROR_NOTDIR;
232 else if (error == ENOENT)
233 error = CM_ERROR_NOSUCHFILE;
234 else if (error == EAGAIN
235 || error == 35 /* EAGAIN, Digital UNIX */
236 || error == WSAEWOULDBLOCK)
237 error = CM_ERROR_WOULDBLOCK;
238 else if (error == VDISKFULL
240 error = CM_ERROR_SPACE;
241 else if (error == VOVERQUOTA
243 || error == 49 /* EDQUOT on Solaris */
244 || error == 88 /* EDQUOT on AIX */
245 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
246 || error == 122 /* EDQUOT on Linux */
247 || error == 1133) /* EDQUOT on Irix */
248 error = CM_ERROR_QUOTA;
249 else if (error == VNOVNODE)
250 error = CM_ERROR_BADFD;
251 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
252 error = CM_ERROR_ALLOFFLINE;
253 else if (error == VBUSY || error == VRESTARTING)
254 error = CM_ERROR_ALLBUSY;
255 else if (error == EISDIR)
256 return CM_ERROR_ISDIR;
260 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
265 /* If we had to stop retrying, report our saved error code. */
266 if (reqp && error == CM_ERROR_TIMEDOUT) {
267 if (reqp->accessError)
268 return reqp->accessError;
269 if (reqp->volumeError)
270 return reqp->volumeError;
272 return reqp->rpcError;
276 error = et_to_sys_error(error);
278 if (error == RX_CALL_DEAD ||
279 error == RX_CALL_TIMEOUT ||
281 error = CM_ERROR_RETRY;
282 else if (error == VNOVNODE)
283 error = CM_ERROR_BADFD;
284 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
285 error = CM_ERROR_ALLOFFLINE;
286 else if (error == VBUSY || error == VRESTARTING)
287 error = CM_ERROR_ALLBUSY;
289 error = CM_ERROR_UNKNOWN;
290 else if (error == EROFS)
291 error = CM_ERROR_READONLY;
292 else if (error == ENOTDIR)
293 error = CM_ERROR_NOTDIR;
294 else if (error == EACCES)
295 error = CM_ERROR_NOACCESS;
296 else if (error == ENOENT)
297 error = CM_ERROR_NOSUCHFILE;
298 else if (error == EINVAL)
299 error = CM_ERROR_INVAL;
300 else if (error == ENOTEMPTY
301 || error == 17 /* AIX */
302 || error == 66 /* SunOS 4, Digital UNIX */
303 || error == 93 /* Solaris 2, IRIX */
304 || error == 247) /* HP/UX */
305 error = CM_ERROR_NOTEMPTY;
309 long cm_MapVLRPCError(long error, cm_req_t *reqp)
311 if (error == 0) return 0;
313 /* If we had to stop retrying, report our saved error code. */
314 if (reqp && error == CM_ERROR_TIMEDOUT) {
315 if (reqp->accessError)
316 return reqp->accessError;
317 if (reqp->volumeError)
318 return reqp->volumeError;
320 return reqp->rpcError;
324 error = et_to_sys_error(error);
326 if (error == RX_CALL_DEAD ||
327 error == RX_CALL_TIMEOUT ||
329 error = CM_ERROR_RETRY;
330 else if (error == RX_RESTARTING)
331 error = CM_ERROR_ALLBUSY;
333 error = CM_ERROR_UNKNOWN;
334 else if (error == EINVAL)
335 error = CM_ERROR_INVAL;
336 else if (error == VL_NOENT || error == VL_BADNAME)
337 error = CM_ERROR_NOSUCHVOLUME;
341 cm_space_t *cm_GetSpace(void)
347 lock_ObtainWrite(&cm_utilsLock);
348 if (tsp = cm_spaceListp) {
349 cm_spaceListp = tsp->nextp;
351 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
352 (void) memset(tsp, 0, sizeof(cm_space_t));
353 lock_ReleaseWrite(&cm_utilsLock);
358 void cm_FreeSpace(cm_space_t *tsp)
360 lock_ObtainWrite(&cm_utilsLock);
361 tsp->nextp = cm_spaceListp;
363 lock_ReleaseWrite(&cm_utilsLock);
366 /* characters that are legal in an 8.3 name */
368 * We used to have 1's for all characters from 128 to 254. But
369 * the NT client behaves better if we create an 8.3 name for any
370 * name that has a character with the high bit on, and if we
371 * delete those characters from 8.3 names. In particular, see
372 * Sybase defect 10859.
374 char cm_LegalChars[256] = {
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
377 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
378 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
379 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
380 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
381 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
382 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
384 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
387 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
388 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
390 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
393 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
395 /* return true iff component is a valid 8.3 name */
396 int cm_Is8Dot3(clientchar_t *namep)
402 if (namep == NULL || !namep[0])
406 * can't have a leading dot;
407 * special case for . and ..
409 if (namep[0] == '.') {
412 if (namep[1] == '.' && namep[2] == 0)
416 while (tc = *namep++) {
418 /* saw another dot */
419 if (sawDot) return 0; /* second dot */
424 if (!ISLEGALCHAR(tc))
427 if (!sawDot && charCount > 8)
428 /* more than 8 chars in name */
430 if (sawDot && charCount > 3)
431 /* more than 3 chars in extension */
438 * Number unparsing map for generating 8.3 names;
439 * The version taken from DFS was on drugs.
440 * You can't include '&' and '@' in a file name.
442 char cm_8Dot3Mapping[42] =
443 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
444 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
445 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
446 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
448 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
450 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
451 clientchar_t *shortName, clientchar_t **shortNameEndp)
455 int vnode = ntohl(pfid->vnode);
457 int validExtension = 0;
461 /* Unparse the file's vnode number to get a "uniquifier" */
463 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
465 vnode /= cm_8Dot3MapSize;
469 * Look for valid extension. There has to be a dot, and
470 * at least one of the characters following has to be legal.
472 lastDot = strrchr(longname, '.');
474 temp = lastDot; temp++;
482 /* Copy name characters */
483 for (i = 0, name = longname;
484 i < (7 - nsize) && name != lastDot; ) {
489 if (!ISLEGALCHAR(tc))
492 *shortName++ = toupper(tc);
498 /* Copy uniquifier characters */
499 for (i=0; i < nsize; i++) {
500 *shortName++ = number[i];
503 if (validExtension) {
504 /* Copy extension characters */
505 *shortName++ = *lastDot++; /* copy dot */
506 for (i = 0, tc = *lastDot++;
509 if (ISLEGALCHAR(tc)) {
511 *shortName++ = toupper(tc);
520 *shortNameEndp = shortName;
523 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
524 clientchar_t *shortName, clientchar_t **shortNameEndp)
526 clientchar_t number[12];
528 int vnode = ntohl(pfid->vnode);
529 clientchar_t *lastDot;
530 int validExtension = 0;
531 clientchar_t tc, *temp;
532 const clientchar_t *name;
534 /* Unparse the file's vnode number to get a "uniquifier" */
536 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
538 vnode /= cm_8Dot3MapSize;
542 * Look for valid extension. There has to be a dot, and
543 * at least one of the characters following has to be legal.
545 lastDot = cm_ClientStrRChr(longname, '.');
547 temp = lastDot; temp++;
555 /* Copy name characters */
556 for (i = 0, name = longname;
557 i < (7 - nsize) && name != lastDot; ) {
562 if (!ISLEGALCHAR(tc))
565 *shortName++ = toupper((char) tc);
571 /* Copy uniquifier characters */
572 for (i=0; i < nsize; i++) {
573 *shortName++ = number[i];
576 if (validExtension) {
577 /* Copy extension characters */
578 *shortName++ = *lastDot++; /* copy dot */
579 for (i = 0, tc = *lastDot++;
582 if (ISLEGALCHAR(tc)) {
584 *shortName++ = toupper(tc);
593 *shortNameEndp = shortName;
596 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
598 \note This procedure works recursively calling itself.
600 \param[in] pattern string containing metacharacters.
601 \param[in] name File name to be compared with 'pattern'.
603 \return BOOL : TRUE/FALSE (match/mistmatch)
606 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
608 clientchar_t upattern[MAX_PATH];
609 clientchar_t uname[MAX_PATH];
611 clientchar_t * pename; // points to the last 'name' character
613 clientchar_t * pattern_next;
616 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
617 cm_ClientStrUpr(upattern);
620 cm_ClientStrCpy(uname, lengthof(uname), name);
621 cm_ClientStrUpr(uname);
624 /* The following translations all work on single byte
626 for (p=upattern; *p; p++) {
627 if (*p == '"') *p = '.'; continue;
628 if (*p == '<') *p = '*'; continue;
629 if (*p == '>') *p = '?'; continue;
632 for (p=uname; *p; p++) {
633 if (*p == '"') *p = '.'; continue;
634 if (*p == '<') *p = '*'; continue;
635 if (*p == '>') *p = '?'; continue;
639 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
644 pattern = cm_ClientCharNext(pattern);
647 name = cm_ClientCharNext(name);
651 pattern = cm_ClientCharNext(pattern);
652 if (*pattern == '\0')
655 pattern_next = cm_ClientCharNext(pattern);
657 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
658 if (*p == *pattern &&
659 szWildCardMatchFileName(pattern_next,
660 cm_ClientCharNext(p), FALSE))
663 if (*pattern == '.' && *pattern_next == '\0') {
664 for (p = name; p && *p; p = cm_ClientCharNext(p))
674 if (*name != *pattern)
676 pattern = cm_ClientCharNext(pattern);
677 name = cm_ClientCharNext(name);
682 /* if all we have left are wildcards, then we match */
683 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
684 if (*pattern != '*' && *pattern != '?')
690 /* do a case-folding search of the star name mask with the name in namep.
691 * Return 1 if we match, otherwise 0.
693 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
695 clientchar_t *newmask, lastchar = _C('\0');
696 int i, j, casefold, retval;
697 int star = 0, qmark = 0, dot = 0;
699 /* make sure we only match 8.3 names, if requested */
700 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
703 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
705 /* optimize the pattern:
706 * if there is a mixture of '?' and '*',
707 * for example the sequence "*?*?*?*"
708 * must be turned into the form "*"
710 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
711 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
713 switch ( maskp[i] ) {
728 } else if ( qmark ) {
732 newmask[j++] = maskp[i];
739 } else if ( qmark ) {
743 if (dot == 0 && lastchar == '<')
747 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
754 cm_TargetPerceivedAsDirectory(const fschar_t *target)
758 ext = PathFindExtension(target);
766 cm_LoadAfsdHookLib(void)
772 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
775 p = strrchr(dllname, '\\');
778 strcpy(p, AFSD_HOOK_DLL);
779 hLib = LoadLibrary(dllname);
781 hLib = LoadLibrary(AFSD_HOOK_DLL);
788 * Obtain the file info structure for the specified file.
789 * If a full path is not specified, the search order is the
790 * same as that used by LoadLibrary().
793 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
801 VS_FIXEDFILEINFO vsf;
803 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
808 pInfo = (char*)malloc(dwSize);
813 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
816 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
819 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
821 liVer->LowPart = vsf.dwFileVersionLS;
822 liVer->HighPart = vsf.dwFileVersionMS;
831 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
832 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
833 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
835 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
837 static BOOL fChecked = FALSE;
838 static BOOL fSupportsExtendedTimeouts = FALSE;
842 BOOL isWow64 = FALSE;
843 OSVERSIONINFOEX Version;
845 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
846 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
847 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
848 PVOID Wow64RedirectionState;
849 LARGE_INTEGER fvFile, fvHotFixMin;
851 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
853 * If we don't find the fnIsWow64Process function then we
854 * are not running in a Wow64 environment
857 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
859 memset (&Version, 0x00, sizeof(Version));
860 Version.dwOSVersionInfoSize = sizeof(Version);
861 GetVersionEx((OSVERSIONINFO *) &Version);
864 * Support is available as hot fixes / service packs on:
871 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
872 Version.dwMajorVersion >= 5) {
875 if (Version.dwMajorVersion == 5 &&
876 Version.dwMinorVersion == 1) {
878 fvHotFixMin.HighPart = (5 << 16) | 1;
880 switch (Version.wServicePackMajor) {
882 fvHotFixMin.LowPart = (2600 << 16) | 5815;
885 fvHotFixMin.LowPart = (2600 << 16) | 3572;
888 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
893 /* 64-bit XP and Server 2003 */
894 else if (Version.dwMajorVersion == 5 &&
895 Version.dwMinorVersion == 2) {
897 fvHotFixMin.HighPart = (5 << 16) | 2;
899 switch (Version.wServicePackMajor) {
901 fvHotFixMin.LowPart = (3790 << 16) | 4479;
904 fvHotFixMin.LowPart = (3790 << 16) | 3310;
907 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
912 /* Vista and Server 2008 */
913 else if (Version.dwMajorVersion == 6 &&
914 Version.dwMinorVersion == 0) {
916 fvHotFixMin.HighPart = (6 << 16) | 0;
918 switch (Version.wServicePackMajor) {
920 fvHotFixMin.LowPart = (6002 << 16) | 18005;
923 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
928 /* Windows 7 and Server 2008 R2 and beyond */
929 else if (Version.dwMajorVersion > 6 ||
930 Version.dwMajorVersion == 6 &&
931 Version.dwMinorVersion >= 1) {
932 fSupportsExtendedTimeouts = TRUE;
936 /* If wow64, disable wow64 redirection and preserve the existing state */
937 if (fnIsWow64Process &&
938 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
940 fnDisableWow64FsRedirection =
941 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
942 fnRevertWow64FsRedirection =
943 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
944 fnDisableWow64FsRedirection(&Wow64RedirectionState);
947 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
948 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
949 fSupportsExtendedTimeouts = TRUE;
951 /* If wow64, restore the previous redirection state */
952 if (fnIsWow64Process && isWow64) {
953 fnRevertWow64FsRedirection(Wow64RedirectionState);
960 return fSupportsExtendedTimeouts;
963 void cm_ResetServerPriority()
965 void * p = TlsGetValue(cm_TlsRequestSlot);
968 TlsSetValue(cm_TlsRequestSlot, NULL);
969 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
973 void cm_SetRequestStartTime()
975 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
977 tp = malloc(sizeof(time_t));
981 if (!TlsSetValue(cm_TlsRequestSlot, tp))
986 void cm_UpdateServerPriority()
988 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
991 time_t now = osi_Time();
993 /* Give one priority boost for each 15 seconds */
994 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
999 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1001 // Note that LONGLONG is a 64-bit value
1004 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1005 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1006 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1009 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1011 // Note that LONGLONG is a 64-bit value
1014 ll = largeTimep->dwHighDateTime;
1016 ll += largeTimep->dwLowDateTime;
1018 ll -= 116444736000000000;
1021 *unixTimep = (DWORD)ll;
1024 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1029 struct tm localJunk;
1030 time_t t = unixTime;
1032 ltp = localtime(&t);
1034 /* if we fail, make up something */
1037 localJunk.tm_year = 89 - 20;
1038 localJunk.tm_mon = 4;
1039 localJunk.tm_mday = 12;
1040 localJunk.tm_hour = 0;
1041 localJunk.tm_min = 0;
1042 localJunk.tm_sec = 0;
1045 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1046 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1047 *searchTimep = (dosDate<<16) | dosTime;
1050 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1052 unsigned short dosDate;
1053 unsigned short dosTime;
1056 dosDate = (unsigned short) (searchTime & 0xffff);
1057 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1059 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1060 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1061 localTm.tm_mday = (dosDate) & 0x1f;
1062 localTm.tm_hour = (dosTime>>11) & 0x1f;
1063 localTm.tm_min = (dosTime >> 5) & 0x3f;
1064 localTm.tm_sec = (dosTime & 0x1f) * 2;
1065 localTm.tm_isdst = -1; /* compute whether DST in effect */
1067 *unixTimep = mktime(&localTm);