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_MSGSIZE ||
218 error = CM_ERROR_TIMEDOUT;
219 else if (error == RX_INVALID_OPERATION)
220 error = CM_ERROR_INVAL_NET_RESP;
222 error = CM_ERROR_UNKNOWN;
223 else if (error == EINVAL)
224 error = CM_ERROR_INVAL;
225 else if (error == EROFS)
226 error = CM_ERROR_READONLY;
227 else if (error == EACCES)
228 error = CM_ERROR_NOACCESS;
229 else if (error == EXDEV)
230 error = CM_ERROR_CROSSDEVLINK;
231 else if (error == EEXIST)
232 error = CM_ERROR_EXISTS;
233 else if (error == ENOTDIR)
234 error = CM_ERROR_NOTDIR;
235 else if (error == ENOENT)
236 error = CM_ERROR_NOSUCHFILE;
237 else if (error == EAGAIN
238 || error == 35 /* EAGAIN, Digital UNIX */
239 || error == WSAEWOULDBLOCK)
240 error = CM_ERROR_WOULDBLOCK;
241 else if (error == VDISKFULL
243 error = CM_ERROR_SPACE;
244 else if (error == VOVERQUOTA
246 || error == 49 /* EDQUOT on Solaris */
247 || error == 88 /* EDQUOT on AIX */
248 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
249 || error == 122 /* EDQUOT on Linux */
250 || error == 1133) /* EDQUOT on Irix */
251 error = CM_ERROR_QUOTA;
252 else if (error == VNOVNODE)
253 error = CM_ERROR_BADFD;
254 else if (error == VSALVAGE || error == VOFFLINE)
255 error = CM_ERROR_ALLOFFLINE;
256 else if (error == VBUSY || error == VRESTARTING)
257 error = CM_ERROR_ALLBUSY;
258 else if (error == EISDIR)
259 return CM_ERROR_ISDIR;
263 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
268 /* If we had to stop retrying, report our saved error code. */
269 if (reqp && error == CM_ERROR_TIMEDOUT) {
270 if (reqp->accessError)
271 return reqp->accessError;
272 if (reqp->volumeError)
273 return reqp->volumeError;
275 return reqp->rpcError;
279 error = et_to_sys_error(error);
281 if (error == RX_CALL_DEAD ||
282 error == RX_CALL_TIMEOUT ||
283 error == RX_MSGSIZE ||
285 error = CM_ERROR_TIMEDOUT;
286 else if (error == VNOVNODE)
287 error = CM_ERROR_BADFD;
288 else if (error == VSALVAGE || error == VOFFLINE)
289 error = CM_ERROR_ALLOFFLINE;
290 else if (error == VBUSY || error == VRESTARTING)
291 error = CM_ERROR_ALLBUSY;
292 else if (error == RX_INVALID_OPERATION)
293 error = CM_ERROR_INVAL_NET_RESP;
295 error = CM_ERROR_UNKNOWN;
296 else if (error == EROFS)
297 error = CM_ERROR_READONLY;
298 else if (error == ENOTDIR)
299 error = CM_ERROR_NOTDIR;
300 else if (error == EACCES)
301 error = CM_ERROR_NOACCESS;
302 else if (error == ENOENT)
303 error = CM_ERROR_NOSUCHFILE;
304 else if (error == EINVAL)
305 error = CM_ERROR_INVAL;
306 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_MSGSIZE ||
337 error = CM_ERROR_TIMEDOUT;
338 else if (error == RX_INVALID_OPERATION)
339 error = CM_ERROR_INVAL_NET_RESP;
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 #ifdef _USE_32BIT_TIME_T
1052 ll.QuadPart = UInt32x32To64(unixTime, 10000000) + 116444736000000000;
1054 ll.QuadPart = unixTime * 10000000 + 116444736000000000;
1056 largeTimep->dwLowDateTime = ll.LowPart;
1057 largeTimep->dwHighDateTime = ll.HighPart;
1060 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1062 // Note that LONGLONG is a 64-bit value
1065 ll.HighPart = largeTimep->dwHighDateTime;
1066 ll.LowPart = largeTimep->dwLowDateTime;
1068 ll.QuadPart -= 116444736000000000;
1069 ll.QuadPart /= 10000000;
1071 *unixTimep = (time_t)ll.QuadPart;
1074 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1079 struct tm localJunk;
1080 time_t t = unixTime;
1082 ltp = localtime(&t);
1084 /* if we fail, make up something */
1087 localJunk.tm_year = 89 - 20;
1088 localJunk.tm_mon = 4;
1089 localJunk.tm_mday = 12;
1090 localJunk.tm_hour = 0;
1091 localJunk.tm_min = 0;
1092 localJunk.tm_sec = 0;
1095 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1096 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1097 *searchTimep = (dosDate<<16) | dosTime;
1100 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1102 unsigned short dosDate;
1103 unsigned short dosTime;
1106 dosDate = (unsigned short) (searchTime & 0xffff);
1107 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1109 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1110 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1111 localTm.tm_mday = (dosDate) & 0x1f;
1112 localTm.tm_hour = (dosTime>>11) & 0x1f;
1113 localTm.tm_min = (dosTime >> 5) & 0x3f;
1114 localTm.tm_sec = (dosTime & 0x1f) * 2;
1115 localTm.tm_isdst = -1; /* compute whether DST in effect */
1117 *unixTimep = mktime(&localTm);
1121 cm_NextHighestPowerOf2(afs_uint32 n)