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)
213 error = CM_ERROR_RETRY;
215 error = CM_ERROR_UNKNOWN;
216 else if (error == EROFS)
217 error = CM_ERROR_READONLY;
218 else if (error == EACCES)
219 error = CM_ERROR_NOACCESS;
220 else if (error == EXDEV)
221 error = CM_ERROR_CROSSDEVLINK;
222 else if (error == EEXIST)
223 error = CM_ERROR_EXISTS;
224 else if (error == ENOTDIR)
225 error = CM_ERROR_NOTDIR;
226 else if (error == ENOENT)
227 error = CM_ERROR_NOSUCHFILE;
228 else if (error == EAGAIN
229 || error == 35 /* EAGAIN, Digital UNIX */
230 || error == WSAEWOULDBLOCK)
231 error = CM_ERROR_WOULDBLOCK;
232 else if (error == VDISKFULL
234 error = CM_ERROR_SPACE;
235 else if (error == VOVERQUOTA
237 || error == 49 /* EDQUOT on Solaris */
238 || error == 88 /* EDQUOT on AIX */
239 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
240 || error == 122 /* EDQUOT on Linux */
241 || error == 1133) /* EDQUOT on Irix */
242 error = CM_ERROR_QUOTA;
243 else if (error == VNOVNODE)
244 error = CM_ERROR_BADFD;
245 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
246 error = CM_ERROR_ALLOFFLINE;
247 else if (error == VBUSY || error == VRESTARTING)
248 error = CM_ERROR_ALLBUSY;
249 else if (error == EISDIR)
250 return CM_ERROR_ISDIR;
254 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
259 /* If we had to stop retrying, report our saved error code. */
260 if (reqp && error == CM_ERROR_TIMEDOUT) {
261 if (reqp->accessError)
262 return reqp->accessError;
263 if (reqp->volumeError)
264 return reqp->volumeError;
266 return reqp->rpcError;
270 error = et_to_sys_error(error);
272 if (error == RX_CALL_DEAD ||
273 error == RX_CALL_TIMEOUT)
274 error = CM_ERROR_RETRY;
275 else if (error == VNOVNODE)
276 error = CM_ERROR_BADFD;
277 else if (error == VNOSERVICE || error == VSALVAGE || error == VOFFLINE)
278 error = CM_ERROR_ALLOFFLINE;
279 else if (error == VBUSY || error == VRESTARTING)
280 error = CM_ERROR_ALLBUSY;
282 error = CM_ERROR_UNKNOWN;
283 else if (error == EROFS)
284 error = CM_ERROR_READONLY;
285 else if (error == ENOTDIR)
286 error = CM_ERROR_NOTDIR;
287 else if (error == EACCES)
288 error = CM_ERROR_NOACCESS;
289 else if (error == ENOENT)
290 error = CM_ERROR_NOSUCHFILE;
291 else if (error == ENOTEMPTY
292 || error == 17 /* AIX */
293 || error == 66 /* SunOS 4, Digital UNIX */
294 || error == 93 /* Solaris 2, IRIX */
295 || error == 247) /* HP/UX */
296 error = CM_ERROR_NOTEMPTY;
300 long cm_MapVLRPCError(long error, cm_req_t *reqp)
302 if (error == 0) return 0;
304 /* If we had to stop retrying, report our saved error code. */
305 if (reqp && error == CM_ERROR_TIMEDOUT) {
306 if (reqp->accessError)
307 return reqp->accessError;
308 if (reqp->volumeError)
309 return reqp->volumeError;
311 return reqp->rpcError;
315 error = et_to_sys_error(error);
317 if (error == RX_CALL_DEAD ||
318 error == RX_CALL_TIMEOUT)
319 error = CM_ERROR_RETRY;
320 else if (error == RX_RESTARTING)
321 error = CM_ERROR_ALLBUSY;
323 error = CM_ERROR_UNKNOWN;
324 else if (error == VL_NOENT || error == VL_BADNAME)
325 error = CM_ERROR_NOSUCHVOLUME;
329 cm_space_t *cm_GetSpace(void)
335 lock_ObtainWrite(&cm_utilsLock);
336 if (tsp = cm_spaceListp) {
337 cm_spaceListp = tsp->nextp;
339 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
340 (void) memset(tsp, 0, sizeof(cm_space_t));
341 lock_ReleaseWrite(&cm_utilsLock);
346 void cm_FreeSpace(cm_space_t *tsp)
348 lock_ObtainWrite(&cm_utilsLock);
349 tsp->nextp = cm_spaceListp;
351 lock_ReleaseWrite(&cm_utilsLock);
354 /* characters that are legal in an 8.3 name */
356 * We used to have 1's for all characters from 128 to 254. But
357 * the NT client behaves better if we create an 8.3 name for any
358 * name that has a character with the high bit on, and if we
359 * delete those characters from 8.3 names. In particular, see
360 * Sybase defect 10859.
362 char cm_LegalChars[256] = {
363 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
364 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
365 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
366 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
367 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
368 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
369 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
370 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
381 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
383 /* return true iff component is a valid 8.3 name */
384 int cm_Is8Dot3(clientchar_t *namep)
390 if (namep == NULL || !namep[0])
394 * can't have a leading dot;
395 * special case for . and ..
397 if (namep[0] == '.') {
400 if (namep[1] == '.' && namep[2] == 0)
404 while (tc = *namep++) {
406 /* saw another dot */
407 if (sawDot) return 0; /* second dot */
412 if (!ISLEGALCHAR(tc))
415 if (!sawDot && charCount > 8)
416 /* more than 8 chars in name */
418 if (sawDot && charCount > 3)
419 /* more than 3 chars in extension */
426 * Number unparsing map for generating 8.3 names;
427 * The version taken from DFS was on drugs.
428 * You can't include '&' and '@' in a file name.
430 char cm_8Dot3Mapping[42] =
431 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
432 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
433 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
434 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
436 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
438 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
439 clientchar_t *shortName, clientchar_t **shortNameEndp)
443 int vnode = ntohl(pfid->vnode);
445 int validExtension = 0;
449 /* Unparse the file's vnode number to get a "uniquifier" */
451 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
453 vnode /= cm_8Dot3MapSize;
457 * Look for valid extension. There has to be a dot, and
458 * at least one of the characters following has to be legal.
460 lastDot = strrchr(longname, '.');
462 temp = lastDot; temp++;
470 /* Copy name characters */
471 for (i = 0, name = longname;
472 i < (7 - nsize) && name != lastDot; ) {
477 if (!ISLEGALCHAR(tc))
480 *shortName++ = toupper(tc);
486 /* Copy uniquifier characters */
487 for (i=0; i < nsize; i++) {
488 *shortName++ = number[i];
491 if (validExtension) {
492 /* Copy extension characters */
493 *shortName++ = *lastDot++; /* copy dot */
494 for (i = 0, tc = *lastDot++;
497 if (ISLEGALCHAR(tc)) {
499 *shortName++ = toupper(tc);
508 *shortNameEndp = shortName;
511 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
512 clientchar_t *shortName, clientchar_t **shortNameEndp)
514 clientchar_t number[12];
516 int vnode = ntohl(pfid->vnode);
517 clientchar_t *lastDot;
518 int validExtension = 0;
519 clientchar_t tc, *temp;
520 const clientchar_t *name;
522 /* Unparse the file's vnode number to get a "uniquifier" */
524 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
526 vnode /= cm_8Dot3MapSize;
530 * Look for valid extension. There has to be a dot, and
531 * at least one of the characters following has to be legal.
533 lastDot = cm_ClientStrRChr(longname, '.');
535 temp = lastDot; temp++;
543 /* Copy name characters */
544 for (i = 0, name = longname;
545 i < (7 - nsize) && name != lastDot; ) {
550 if (!ISLEGALCHAR(tc))
553 *shortName++ = toupper((char) tc);
559 /* Copy uniquifier characters */
560 for (i=0; i < nsize; i++) {
561 *shortName++ = number[i];
564 if (validExtension) {
565 /* Copy extension characters */
566 *shortName++ = *lastDot++; /* copy dot */
567 for (i = 0, tc = *lastDot++;
570 if (ISLEGALCHAR(tc)) {
572 *shortName++ = toupper(tc);
581 *shortNameEndp = shortName;
584 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
586 \note This procedure works recursively calling itself.
588 \param[in] pattern string containing metacharacters.
589 \param[in] name File name to be compared with 'pattern'.
591 \return BOOL : TRUE/FALSE (match/mistmatch)
594 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
596 clientchar_t upattern[MAX_PATH];
597 clientchar_t uname[MAX_PATH];
599 clientchar_t * pename; // points to the last 'name' character
601 clientchar_t * pattern_next;
604 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
605 cm_ClientStrUpr(upattern);
608 cm_ClientStrCpy(uname, lengthof(uname), name);
609 cm_ClientStrUpr(uname);
612 /* The following translations all work on single byte
614 for (p=upattern; *p; p++) {
615 if (*p == '"') *p = '.'; continue;
616 if (*p == '<') *p = '*'; continue;
617 if (*p == '>') *p = '?'; continue;
620 for (p=uname; *p; p++) {
621 if (*p == '"') *p = '.'; continue;
622 if (*p == '<') *p = '*'; continue;
623 if (*p == '>') *p = '?'; continue;
627 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
632 pattern = cm_ClientCharNext(pattern);
635 name = cm_ClientCharNext(name);
639 pattern = cm_ClientCharNext(pattern);
640 if (*pattern == '\0')
643 pattern_next = cm_ClientCharNext(pattern);
645 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
646 if (*p == *pattern &&
647 szWildCardMatchFileName(pattern_next,
648 cm_ClientCharNext(p), FALSE))
651 if (*pattern == '.' && *pattern_next == '\0') {
652 for (p = name; p && *p; p = cm_ClientCharNext(p))
662 if (*name != *pattern)
664 pattern = cm_ClientCharNext(pattern);
665 name = cm_ClientCharNext(name);
670 /* if all we have left are wildcards, then we match */
671 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
672 if (*pattern != '*' && *pattern != '?')
678 /* do a case-folding search of the star name mask with the name in namep.
679 * Return 1 if we match, otherwise 0.
681 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
683 clientchar_t *newmask, lastchar = _C('\0');
684 int i, j, casefold, retval;
685 int star = 0, qmark = 0, dot = 0;
687 /* make sure we only match 8.3 names, if requested */
688 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
691 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
693 /* optimize the pattern:
694 * if there is a mixture of '?' and '*',
695 * for example the sequence "*?*?*?*"
696 * must be turned into the form "*"
698 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
699 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
701 switch ( maskp[i] ) {
716 } else if ( qmark ) {
720 newmask[j++] = maskp[i];
727 } else if ( qmark ) {
731 if (dot == 0 && lastchar == '<')
735 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
742 cm_TargetPerceivedAsDirectory(const fschar_t *target)
746 ext = PathFindExtension(target);
754 cm_LoadAfsdHookLib(void)
760 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
763 p = strrchr(dllname, '\\');
766 strcpy(p, AFSD_HOOK_DLL);
767 hLib = LoadLibrary(dllname);
769 hLib = LoadLibrary(AFSD_HOOK_DLL);
776 * Obtain the file info structure for the specified file.
777 * If a full path is not specified, the search order is the
778 * same as that used by LoadLibrary().
781 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
789 VS_FIXEDFILEINFO vsf;
791 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
796 pInfo = (char*)malloc(dwSize);
801 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
804 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
807 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
809 liVer->LowPart = vsf.dwFileVersionLS;
810 liVer->HighPart = vsf.dwFileVersionMS;
819 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
820 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
821 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
823 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
825 static BOOL fChecked = FALSE;
826 static BOOL fSupportsExtendedTimeouts = FALSE;
830 BOOL isWow64 = FALSE;
831 OSVERSIONINFOEX Version;
833 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
834 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
835 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
836 PVOID Wow64RedirectionState;
837 LARGE_INTEGER fvFile, fvHotFixMin;
839 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
841 * If we don't find the fnIsWow64Process function then we
842 * are not running in a Wow64 environment
845 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
847 memset (&Version, 0x00, sizeof(Version));
848 Version.dwOSVersionInfoSize = sizeof(Version);
849 GetVersionEx((OSVERSIONINFO *) &Version);
852 * Support is available as hot fixes / service packs on:
859 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
860 Version.dwMajorVersion >= 5) {
863 if (Version.dwMajorVersion == 5 &&
864 Version.dwMinorVersion == 1) {
866 fvHotFixMin.HighPart = (5 << 16) | 1;
868 switch (Version.wServicePackMajor) {
870 fvHotFixMin.LowPart = (2600 << 16) | 5815;
873 fvHotFixMin.LowPart = (2600 << 16) | 3572;
876 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
881 /* 64-bit XP and Server 2003 */
882 else if (Version.dwMajorVersion == 5 &&
883 Version.dwMinorVersion == 2) {
885 fvHotFixMin.HighPart = (5 << 16) | 2;
887 switch (Version.wServicePackMajor) {
889 fvHotFixMin.LowPart = (3790 << 16) | 4479;
892 fvHotFixMin.LowPart = (3790 << 16) | 3310;
895 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
900 /* Vista and Server 2008 */
901 else if (Version.dwMajorVersion == 6 &&
902 Version.dwMinorVersion == 0) {
904 fvHotFixMin.HighPart = (6 << 16) | 0;
906 switch (Version.wServicePackMajor) {
908 fvHotFixMin.LowPart = (6002 << 16) | 18005;
911 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
916 /* Windows 7 and Server 2008 R2 and beyond */
917 else if (Version.dwMajorVersion > 6 ||
918 Version.dwMajorVersion == 6 &&
919 Version.dwMinorVersion >= 1) {
920 fSupportsExtendedTimeouts = TRUE;
924 /* If wow64, disable wow64 redirection and preserve the existing state */
925 if (fnIsWow64Process &&
926 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
928 fnDisableWow64FsRedirection =
929 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
930 fnRevertWow64FsRedirection =
931 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
932 fnDisableWow64FsRedirection(&Wow64RedirectionState);
935 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
936 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
937 fSupportsExtendedTimeouts = TRUE;
939 /* If wow64, restore the previous redirection state */
940 if (fnIsWow64Process && isWow64) {
941 fnRevertWow64FsRedirection(Wow64RedirectionState);
948 return fSupportsExtendedTimeouts;
951 void cm_ResetServerPriority()
953 void * p = TlsGetValue(cm_TlsRequestSlot);
956 TlsSetValue(cm_TlsRequestSlot, NULL);
957 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
961 void cm_SetRequestStartTime()
963 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
965 tp = malloc(sizeof(time_t));
969 if (!TlsSetValue(cm_TlsRequestSlot, tp))
974 void cm_UpdateServerPriority()
976 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
979 time_t now = osi_Time();
981 /* Give one priority boost for each 15 seconds */
982 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
987 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
989 // Note that LONGLONG is a 64-bit value
992 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
993 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
994 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
997 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
999 // Note that LONGLONG is a 64-bit value
1002 ll = largeTimep->dwHighDateTime;
1004 ll += largeTimep->dwLowDateTime;
1006 ll -= 116444736000000000;
1009 *unixTimep = (DWORD)ll;
1012 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1017 struct tm localJunk;
1018 time_t t = unixTime;
1020 ltp = localtime(&t);
1022 /* if we fail, make up something */
1025 localJunk.tm_year = 89 - 20;
1026 localJunk.tm_mon = 4;
1027 localJunk.tm_mday = 12;
1028 localJunk.tm_hour = 0;
1029 localJunk.tm_min = 0;
1030 localJunk.tm_sec = 0;
1033 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1034 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1035 *searchTimep = (dosDate<<16) | dosTime;
1038 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1040 unsigned short dosDate;
1041 unsigned short dosTime;
1044 dosDate = (unsigned short) (searchTime & 0xffff);
1045 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1047 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1048 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1049 localTm.tm_mday = (dosDate) & 0x1f;
1050 localTm.tm_hour = (dosTime>>11) & 0x1f;
1051 localTm.tm_min = (dosTime >> 5) & 0x3f;
1052 localTm.tm_sec = (dosTime & 0x1f) * 2;
1053 localTm.tm_isdst = -1; /* compute whether DST in effect */
1055 *unixTimep = mktime(&localTm);