2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
22 #define STRSAFE_NO_DEPRECATE
29 #include <afs/unified_afs.h>
31 static osi_once_t cm_utilsOnce;
33 osi_rwlock_t cm_utilsLock;
35 cm_space_t *cm_spaceListp;
37 static int et2sys[512];
39 static DWORD cm_TlsRequestSlot = -1;
41 void cm_utilsInit(void)
43 if (osi_Once(&cm_utilsOnce)) {
44 lock_InitializeRWLock(&cm_utilsLock, "cm_utilsLock", LOCK_HIERARCHY_UTILS_GLOBAL);
46 cm_TlsRequestSlot = TlsAlloc();
48 osi_EndOnce(&cm_utilsOnce);
52 void cm_utilsCleanup(void)
54 TlsFree(cm_TlsRequestSlot);
58 init_et_to_sys_error(void)
60 memset(&et2sys, 0, sizeof(et2sys));
61 et2sys[(UAEPERM - ERROR_TABLE_BASE_uae)] = EPERM;
62 et2sys[(UAENOENT - ERROR_TABLE_BASE_uae)] = ENOENT;
63 et2sys[(UAESRCH - ERROR_TABLE_BASE_uae)] = ESRCH;
64 et2sys[(UAEINTR - ERROR_TABLE_BASE_uae)] = EINTR;
65 et2sys[(UAEIO - ERROR_TABLE_BASE_uae)] = EIO;
66 et2sys[(UAENXIO - ERROR_TABLE_BASE_uae)] = ENXIO;
67 et2sys[(UAE2BIG - ERROR_TABLE_BASE_uae)] = E2BIG;
68 et2sys[(UAENOEXEC - ERROR_TABLE_BASE_uae)] = ENOEXEC;
69 et2sys[(UAEBADF - ERROR_TABLE_BASE_uae)] = EBADF;
70 et2sys[(UAECHILD - ERROR_TABLE_BASE_uae)] = ECHILD;
71 et2sys[(UAEAGAIN - ERROR_TABLE_BASE_uae)] = EAGAIN;
72 et2sys[(UAENOMEM - ERROR_TABLE_BASE_uae)] = ENOMEM;
73 et2sys[(UAEACCES - ERROR_TABLE_BASE_uae)] = EACCES;
74 et2sys[(UAEFAULT - ERROR_TABLE_BASE_uae)] = EFAULT;
75 et2sys[(UAENOTBLK - ERROR_TABLE_BASE_uae)] = ENOTBLK;
76 et2sys[(UAEBUSY - ERROR_TABLE_BASE_uae)] = EBUSY;
77 et2sys[(UAEEXIST - ERROR_TABLE_BASE_uae)] = EEXIST;
78 et2sys[(UAEXDEV - ERROR_TABLE_BASE_uae)] = EXDEV;
79 et2sys[(UAENODEV - ERROR_TABLE_BASE_uae)] = ENODEV;
80 et2sys[(UAENOTDIR - ERROR_TABLE_BASE_uae)] = ENOTDIR;
81 et2sys[(UAEISDIR - ERROR_TABLE_BASE_uae)] = EISDIR;
82 et2sys[(UAEINVAL - ERROR_TABLE_BASE_uae)] = EINVAL;
83 et2sys[(UAENFILE - ERROR_TABLE_BASE_uae)] = ENFILE;
84 et2sys[(UAEMFILE - ERROR_TABLE_BASE_uae)] = EMFILE;
85 et2sys[(UAENOTTY - ERROR_TABLE_BASE_uae)] = ENOTTY;
86 et2sys[(UAETXTBSY - ERROR_TABLE_BASE_uae)] = ETXTBSY;
87 et2sys[(UAEFBIG - ERROR_TABLE_BASE_uae)] = EFBIG;
88 et2sys[(UAENOSPC - ERROR_TABLE_BASE_uae)] = ENOSPC;
89 et2sys[(UAESPIPE - ERROR_TABLE_BASE_uae)] = ESPIPE;
90 et2sys[(UAEROFS - ERROR_TABLE_BASE_uae)] = EROFS;
91 et2sys[(UAEMLINK - ERROR_TABLE_BASE_uae)] = EMLINK;
92 et2sys[(UAEPIPE - ERROR_TABLE_BASE_uae)] = EPIPE;
93 et2sys[(UAEDOM - ERROR_TABLE_BASE_uae)] = EDOM;
94 et2sys[(UAERANGE - ERROR_TABLE_BASE_uae)] = ERANGE;
95 et2sys[(UAEDEADLK - ERROR_TABLE_BASE_uae)] = EDEADLK;
96 et2sys[(UAENAMETOOLONG - ERROR_TABLE_BASE_uae)] = ENAMETOOLONG;
97 et2sys[(UAENOLCK - ERROR_TABLE_BASE_uae)] = ENOLCK;
98 et2sys[(UAENOSYS - ERROR_TABLE_BASE_uae)] = ENOSYS;
99 et2sys[(UAENOTEMPTY - ERROR_TABLE_BASE_uae)] = ENOTEMPTY;
100 et2sys[(UAELOOP - ERROR_TABLE_BASE_uae)] = ELOOP;
101 et2sys[(UAEWOULDBLOCK - ERROR_TABLE_BASE_uae)] = EWOULDBLOCK;
102 et2sys[(UAENOMSG - ERROR_TABLE_BASE_uae)] = ENOMSG;
103 et2sys[(UAEIDRM - ERROR_TABLE_BASE_uae)] = EIDRM;
104 et2sys[(UAECHRNG - ERROR_TABLE_BASE_uae)] = ECHRNG;
105 et2sys[(UAEL2NSYNC - ERROR_TABLE_BASE_uae)] = EL2NSYNC;
106 et2sys[(UAEL3HLT - ERROR_TABLE_BASE_uae)] = EL3HLT;
107 et2sys[(UAEL3RST - ERROR_TABLE_BASE_uae)] = EL3RST;
108 et2sys[(UAELNRNG - ERROR_TABLE_BASE_uae)] = ELNRNG;
109 et2sys[(UAEUNATCH - ERROR_TABLE_BASE_uae)] = EUNATCH;
110 et2sys[(UAENOCSI - ERROR_TABLE_BASE_uae)] = ENOCSI;
111 et2sys[(UAEL2HLT - ERROR_TABLE_BASE_uae)] = EL2HLT;
112 et2sys[(UAEBADE - ERROR_TABLE_BASE_uae)] = EBADE;
113 et2sys[(UAEBADR - ERROR_TABLE_BASE_uae)] = EBADR;
114 et2sys[(UAEXFULL - ERROR_TABLE_BASE_uae)] = EXFULL;
115 et2sys[(UAENOANO - ERROR_TABLE_BASE_uae)] = ENOANO;
116 et2sys[(UAEBADRQC - ERROR_TABLE_BASE_uae)] = EBADRQC;
117 et2sys[(UAEBADSLT - ERROR_TABLE_BASE_uae)] = EBADSLT;
118 et2sys[(UAEBFONT - ERROR_TABLE_BASE_uae)] = EBFONT;
119 et2sys[(UAENOSTR - ERROR_TABLE_BASE_uae)] = ENOSTR;
120 et2sys[(UAENODATA - ERROR_TABLE_BASE_uae)] = ENODATA;
121 et2sys[(UAETIME - ERROR_TABLE_BASE_uae)] = ETIME;
122 et2sys[(UAENOSR - ERROR_TABLE_BASE_uae)] = ENOSR;
123 et2sys[(UAENONET - ERROR_TABLE_BASE_uae)] = ENONET;
124 et2sys[(UAENOPKG - ERROR_TABLE_BASE_uae)] = ENOPKG;
125 et2sys[(UAEREMOTE - ERROR_TABLE_BASE_uae)] = EREMOTE;
126 et2sys[(UAENOLINK - ERROR_TABLE_BASE_uae)] = ENOLINK;
127 et2sys[(UAEADV - ERROR_TABLE_BASE_uae)] = EADV;
128 et2sys[(UAESRMNT - ERROR_TABLE_BASE_uae)] = ESRMNT;
129 et2sys[(UAECOMM - ERROR_TABLE_BASE_uae)] = ECOMM;
130 et2sys[(UAEPROTO - ERROR_TABLE_BASE_uae)] = EPROTO;
131 et2sys[(UAEMULTIHOP - ERROR_TABLE_BASE_uae)] = EMULTIHOP;
132 et2sys[(UAEDOTDOT - ERROR_TABLE_BASE_uae)] = EDOTDOT;
133 et2sys[(UAEBADMSG - ERROR_TABLE_BASE_uae)] = EBADMSG;
134 et2sys[(UAEOVERFLOW - ERROR_TABLE_BASE_uae)] = EOVERFLOW;
135 et2sys[(UAENOTUNIQ - ERROR_TABLE_BASE_uae)] = ENOTUNIQ;
136 et2sys[(UAEBADFD - ERROR_TABLE_BASE_uae)] = EBADFD;
137 et2sys[(UAEREMCHG - ERROR_TABLE_BASE_uae)] = EREMCHG;
138 et2sys[(UAELIBACC - ERROR_TABLE_BASE_uae)] = ELIBACC;
139 et2sys[(UAELIBBAD - ERROR_TABLE_BASE_uae)] = ELIBBAD;
140 et2sys[(UAELIBSCN - ERROR_TABLE_BASE_uae)] = ELIBSCN;
141 et2sys[(UAELIBMAX - ERROR_TABLE_BASE_uae)] = ELIBMAX;
142 et2sys[(UAELIBEXEC - ERROR_TABLE_BASE_uae)] = ELIBEXEC;
143 et2sys[(UAEILSEQ - ERROR_TABLE_BASE_uae)] = EILSEQ;
144 et2sys[(UAERESTART - ERROR_TABLE_BASE_uae)] = ERESTART;
145 et2sys[(UAESTRPIPE - ERROR_TABLE_BASE_uae)] = ESTRPIPE;
146 et2sys[(UAEUSERS - ERROR_TABLE_BASE_uae)] = EUSERS;
147 et2sys[(UAENOTSOCK - ERROR_TABLE_BASE_uae)] = ENOTSOCK;
148 et2sys[(UAEDESTADDRREQ - ERROR_TABLE_BASE_uae)] = EDESTADDRREQ;
149 et2sys[(UAEMSGSIZE - ERROR_TABLE_BASE_uae)] = EMSGSIZE;
150 et2sys[(UAEPROTOTYPE - ERROR_TABLE_BASE_uae)] = EPROTOTYPE;
151 et2sys[(UAENOPROTOOPT - ERROR_TABLE_BASE_uae)] = ENOPROTOOPT;
152 et2sys[(UAEPROTONOSUPPORT - ERROR_TABLE_BASE_uae)] = EPROTONOSUPPORT;
153 et2sys[(UAESOCKTNOSUPPORT - ERROR_TABLE_BASE_uae)] = ESOCKTNOSUPPORT;
154 et2sys[(UAEOPNOTSUPP - ERROR_TABLE_BASE_uae)] = EOPNOTSUPP;
155 et2sys[(UAEPFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EPFNOSUPPORT;
156 et2sys[(UAEAFNOSUPPORT - ERROR_TABLE_BASE_uae)] = EAFNOSUPPORT;
157 et2sys[(UAEADDRINUSE - ERROR_TABLE_BASE_uae)] = EADDRINUSE;
158 et2sys[(UAEADDRNOTAVAIL - ERROR_TABLE_BASE_uae)] = EADDRNOTAVAIL;
159 et2sys[(UAENETDOWN - ERROR_TABLE_BASE_uae)] = ENETDOWN;
160 et2sys[(UAENETUNREACH - ERROR_TABLE_BASE_uae)] = ENETUNREACH;
161 et2sys[(UAENETRESET - ERROR_TABLE_BASE_uae)] = ENETRESET;
162 et2sys[(UAECONNABORTED - ERROR_TABLE_BASE_uae)] = ECONNABORTED;
163 et2sys[(UAECONNRESET - ERROR_TABLE_BASE_uae)] = ECONNRESET;
164 et2sys[(UAENOBUFS - ERROR_TABLE_BASE_uae)] = ENOBUFS;
165 et2sys[(UAEISCONN - ERROR_TABLE_BASE_uae)] = EISCONN;
166 et2sys[(UAENOTCONN - ERROR_TABLE_BASE_uae)] = ENOTCONN;
167 et2sys[(UAESHUTDOWN - ERROR_TABLE_BASE_uae)] = ESHUTDOWN;
168 et2sys[(UAETOOMANYREFS - ERROR_TABLE_BASE_uae)] = ETOOMANYREFS;
169 et2sys[(UAETIMEDOUT - ERROR_TABLE_BASE_uae)] = ETIMEDOUT;
170 et2sys[(UAECONNREFUSED - ERROR_TABLE_BASE_uae)] = ECONNREFUSED;
171 et2sys[(UAEHOSTDOWN - ERROR_TABLE_BASE_uae)] = EHOSTDOWN;
172 et2sys[(UAEHOSTUNREACH - ERROR_TABLE_BASE_uae)] = EHOSTUNREACH;
173 et2sys[(UAEALREADY - ERROR_TABLE_BASE_uae)] = EALREADY;
174 et2sys[(UAEINPROGRESS - ERROR_TABLE_BASE_uae)] = EINPROGRESS;
175 et2sys[(UAESTALE - ERROR_TABLE_BASE_uae)] = ESTALE;
176 et2sys[(UAEUCLEAN - ERROR_TABLE_BASE_uae)] = EUCLEAN;
177 et2sys[(UAENOTNAM - ERROR_TABLE_BASE_uae)] = ENOTNAM;
178 et2sys[(UAENAVAIL - ERROR_TABLE_BASE_uae)] = ENAVAIL;
179 et2sys[(UAEISNAM - ERROR_TABLE_BASE_uae)] = EISNAM;
180 et2sys[(UAEREMOTEIO - ERROR_TABLE_BASE_uae)] = EREMOTEIO;
181 et2sys[(UAEDQUOT - ERROR_TABLE_BASE_uae)] = EDQUOT;
182 et2sys[(UAENOMEDIUM - ERROR_TABLE_BASE_uae)] = ENOMEDIUM;
183 et2sys[(UAEMEDIUMTYPE - ERROR_TABLE_BASE_uae)] = EMEDIUMTYPE;
187 et_to_sys_error(afs_int32 in)
189 if (in < ERROR_TABLE_BASE_uae || in >= ERROR_TABLE_BASE_uae + 512)
191 if (et2sys[in - ERROR_TABLE_BASE_uae] != 0)
192 return et2sys[in - ERROR_TABLE_BASE_uae];
196 long cm_MapRPCError(long error, cm_req_t *reqp)
201 /* If we had to stop retrying, report our saved error code. */
202 if (reqp && error == CM_ERROR_TIMEDOUT) {
203 if (reqp->accessError)
204 return reqp->accessError;
205 if (reqp->volumeError)
206 return reqp->volumeError;
208 return reqp->rpcError;
212 error = et_to_sys_error(error);
214 if (error == RX_CALL_DEAD ||
215 error == RX_CALL_TIMEOUT ||
216 error == RX_CALL_BUSY ||
217 error == RX_MSGSIZE ||
219 error = CM_ERROR_RETRY;
220 else if (error == RX_CALL_IDLE)
222 else if (error == RX_INVALID_OPERATION)
223 error = CM_ERROR_INVAL_NET_RESP;
225 error = CM_ERROR_UNKNOWN;
226 else if (error == EINVAL)
227 error = CM_ERROR_INVAL;
228 else if (error == EROFS)
229 error = CM_ERROR_READONLY;
230 else if (error == EACCES)
231 error = CM_ERROR_NOACCESS;
232 else if (error == EXDEV)
233 error = CM_ERROR_CROSSDEVLINK;
234 else if (error == EEXIST)
235 error = CM_ERROR_EXISTS;
236 else if (error == ENOTDIR)
237 error = CM_ERROR_NOTDIR;
238 else if (error == ENOENT)
239 error = CM_ERROR_NOSUCHFILE;
240 else if (error == EAGAIN
241 || error == 35 /* EAGAIN, Digital UNIX */
242 || error == WSAEWOULDBLOCK)
243 error = CM_ERROR_WOULDBLOCK;
244 else if (error == VDISKFULL
246 error = CM_ERROR_SPACE;
247 else if (error == VOVERQUOTA
249 || error == 49 /* EDQUOT on Solaris */
250 || error == 88 /* EDQUOT on AIX */
251 || error == 69 /* EDQUOT on Digital UNIX and HPUX */
252 || error == 122 /* EDQUOT on Linux */
253 || error == 1133) /* EDQUOT on Irix */
254 error = CM_ERROR_QUOTA;
255 else if (error == VNOVNODE)
256 error = CM_ERROR_BADFD;
257 else if (error == VSALVAGE || error == VOFFLINE)
258 error = CM_ERROR_ALLOFFLINE;
259 else if (error == VBUSY || error == VRESTARTING)
260 error = CM_ERROR_ALLBUSY;
261 else if (error == EISDIR)
262 return CM_ERROR_ISDIR;
266 long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
271 /* If we had to stop retrying, report our saved error code. */
272 if (reqp && error == CM_ERROR_TIMEDOUT) {
273 if (reqp->accessError)
274 return reqp->accessError;
275 if (reqp->volumeError)
276 return reqp->volumeError;
278 return reqp->rpcError;
282 error = et_to_sys_error(error);
284 if (error == RX_CALL_DEAD ||
285 error == RX_CALL_TIMEOUT ||
286 error == RX_CALL_BUSY ||
287 error == RX_CALL_IDLE ||
288 error == RX_MSGSIZE ||
290 error = CM_ERROR_RETRY;
291 else if (error == VNOVNODE)
292 error = CM_ERROR_BADFD;
293 else if (error == VSALVAGE || error == VOFFLINE)
294 error = CM_ERROR_ALLOFFLINE;
295 else if (error == VBUSY || error == VRESTARTING)
296 error = CM_ERROR_ALLBUSY;
297 else if (error == RX_INVALID_OPERATION)
298 error = CM_ERROR_INVAL_NET_RESP;
300 error = CM_ERROR_UNKNOWN;
301 else if (error == EROFS)
302 error = CM_ERROR_READONLY;
303 else if (error == ENOTDIR)
304 error = CM_ERROR_NOTDIR;
305 else if (error == EACCES)
306 error = CM_ERROR_NOACCESS;
307 else if (error == ENOENT)
308 error = CM_ERROR_NOSUCHFILE;
309 else if (error == EINVAL)
310 error = CM_ERROR_INVAL;
311 else if (error == ENOTEMPTY
313 || error == 17 /* AIX */
314 || error == 66 /* SunOS 4, Digital UNIX */
315 || error == 93 /* Solaris 2, IRIX */
316 || error == 247) /* HP/UX */
317 error = CM_ERROR_NOTEMPTY;
321 long cm_MapVLRPCError(long error, cm_req_t *reqp)
323 if (error == 0) return 0;
325 /* If we had to stop retrying, report our saved error code. */
326 if (reqp && error == CM_ERROR_TIMEDOUT) {
327 if (reqp->accessError)
328 return reqp->accessError;
329 if (reqp->volumeError)
330 return reqp->volumeError;
332 return reqp->rpcError;
336 error = et_to_sys_error(error);
338 if (error == RX_CALL_DEAD ||
339 error == RX_CALL_TIMEOUT ||
340 error == RX_CALL_BUSY ||
341 error == RX_CALL_IDLE ||
342 error == RX_MSGSIZE ||
344 error = CM_ERROR_RETRY;
345 else if (error == RX_INVALID_OPERATION)
346 error = CM_ERROR_INVAL_NET_RESP;
347 else if (error == RX_RESTARTING)
348 error = CM_ERROR_ALLBUSY;
350 error = CM_ERROR_UNKNOWN;
351 else if (error == EINVAL)
352 error = CM_ERROR_INVAL;
353 else if (error == VL_NOENT || error == VL_BADNAME)
354 error = CM_ERROR_NOSUCHVOLUME;
358 cm_space_t *cm_GetSpace(void)
364 lock_ObtainWrite(&cm_utilsLock);
365 if (tsp = cm_spaceListp) {
366 cm_spaceListp = tsp->nextp;
368 else tsp = (cm_space_t *) malloc(sizeof(cm_space_t));
369 (void) memset(tsp, 0, sizeof(cm_space_t));
370 lock_ReleaseWrite(&cm_utilsLock);
375 void cm_FreeSpace(cm_space_t *tsp)
377 lock_ObtainWrite(&cm_utilsLock);
378 tsp->nextp = cm_spaceListp;
380 lock_ReleaseWrite(&cm_utilsLock);
383 /* characters that are legal in an 8.3 name */
385 * We used to have 1's for all characters from 128 to 254. But
386 * the NT client behaves better if we create an 8.3 name for any
387 * name that has a character with the high bit on, and if we
388 * delete those characters from 8.3 names. In particular, see
389 * Sybase defect 10859.
391 char cm_LegalChars[256] = {
392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
397 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
398 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
399 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
402 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
410 #define ISLEGALCHAR(c) ((c) < 256 && (c) > 0 && cm_LegalChars[(c)] != 0)
412 /* return true iff component is a valid 8.3 name */
413 int cm_Is8Dot3(clientchar_t *namep)
419 if (namep == NULL || !namep[0])
423 * can't have a leading dot;
424 * special case for . and ..
426 if (namep[0] == '.') {
429 if (namep[1] == '.' && namep[2] == 0)
433 while (tc = *namep++) {
435 /* saw another dot */
436 if (sawDot) return 0; /* second dot */
441 if (!ISLEGALCHAR(tc))
444 if (!sawDot && charCount > 8)
445 /* more than 8 chars in name */
447 if (sawDot && charCount > 3)
448 /* more than 3 chars in extension */
455 * Number unparsing map for generating 8.3 names;
456 * The version taken from DFS was on drugs.
457 * You can't include '&' and '@' in a file name.
459 char cm_8Dot3Mapping[42] =
460 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
461 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
462 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
463 'V', 'W', 'X', 'Y', 'Z', '_', '-', '$', '#', '!', '{', '}'
465 int cm_8Dot3MapSize = sizeof(cm_8Dot3Mapping);
467 void cm_Gen8Dot3NameInt(const fschar_t * longname, cm_dirFid_t * pfid,
468 clientchar_t *shortName, clientchar_t **shortNameEndp)
472 int vnode = ntohl(pfid->vnode);
474 int validExtension = 0;
478 /* Unparse the file's vnode number to get a "uniquifier" */
480 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
482 vnode /= cm_8Dot3MapSize;
486 * Look for valid extension. There has to be a dot, and
487 * at least one of the characters following has to be legal.
489 lastDot = strrchr(longname, '.');
491 temp = lastDot; temp++;
499 /* Copy name characters */
500 for (i = 0, name = longname;
501 i < (7 - nsize) && name != lastDot; ) {
506 if (!ISLEGALCHAR(tc))
509 *shortName++ = toupper(tc);
515 /* Copy uniquifier characters */
516 for (i=0; i < nsize; i++) {
517 *shortName++ = number[i];
520 if (validExtension) {
521 /* Copy extension characters */
522 *shortName++ = *lastDot++; /* copy dot */
523 for (i = 0, tc = *lastDot++;
526 if (ISLEGALCHAR(tc)) {
528 *shortName++ = toupper(tc);
537 *shortNameEndp = shortName;
540 void cm_Gen8Dot3NameIntW(const clientchar_t * longname, cm_dirFid_t * pfid,
541 clientchar_t *shortName, clientchar_t **shortNameEndp)
543 clientchar_t number[12];
545 int vnode = ntohl(pfid->vnode);
546 clientchar_t *lastDot;
547 int validExtension = 0;
548 clientchar_t tc, *temp;
549 const clientchar_t *name;
551 /* Unparse the file's vnode number to get a "uniquifier" */
553 number[nsize] = cm_8Dot3Mapping[vnode % cm_8Dot3MapSize];
555 vnode /= cm_8Dot3MapSize;
559 * Look for valid extension. There has to be a dot, and
560 * at least one of the characters following has to be legal.
562 lastDot = cm_ClientStrRChr(longname, '.');
564 temp = lastDot; temp++;
572 /* Copy name characters */
573 for (i = 0, name = longname;
574 i < (7 - nsize) && name != lastDot; ) {
579 if (!ISLEGALCHAR(tc))
582 *shortName++ = toupper((char) tc);
588 /* Copy uniquifier characters */
589 for (i=0; i < nsize; i++) {
590 *shortName++ = number[i];
593 if (validExtension) {
594 /* Copy extension characters */
595 *shortName++ = *lastDot++; /* copy dot */
596 for (i = 0, tc = *lastDot++;
599 if (ISLEGALCHAR(tc)) {
601 *shortName++ = toupper(tc);
610 *shortNameEndp = shortName;
613 void cm_Gen8Dot3VolNameW(afs_uint32 cell, afs_uint32 volume,
614 clientchar_t *shortName, clientchar_t **shortNameEndp)
616 clientchar_t number[12];
618 int validExtension = 0;
620 /* Unparse the file's cell and volume numbers */
622 number[nsize] = cm_8Dot3Mapping[cell % cm_8Dot3MapSize];
624 cell /= cm_8Dot3MapSize;
627 number[nsize] = cm_8Dot3Mapping[volume % cm_8Dot3MapSize];
629 volume /= cm_8Dot3MapSize;
630 } while (volume && nsize < 8);
632 /* Copy uniquifier characters */
633 for (i=0; i < nsize; i++) {
634 *shortName++ = number[i];
637 /* Add extension characters */
638 *shortName++ = '.'; /* copy dot */
647 *shortNameEndp = shortName;
650 /*! \brief Compare 'pattern' (containing metacharacters '*' and '?') with the file name 'name'.
652 \note This procedure works recursively calling itself.
654 \param[in] pattern string containing metacharacters.
655 \param[in] name File name to be compared with 'pattern'.
657 \return BOOL : TRUE/FALSE (match/mistmatch)
660 szWildCardMatchFileName(clientchar_t * pattern, clientchar_t * name, int casefold)
662 clientchar_t upattern[MAX_PATH];
663 clientchar_t uname[MAX_PATH];
665 clientchar_t * pename; // points to the last 'name' character
667 clientchar_t * pattern_next;
670 cm_ClientStrCpy(upattern, lengthof(upattern), pattern);
671 cm_ClientStrUpr(upattern);
674 cm_ClientStrCpy(uname, lengthof(uname), name);
675 cm_ClientStrUpr(uname);
678 /* The following translations all work on single byte
680 for (p=upattern; *p; p++) {
681 if (*p == '"') *p = '.'; continue;
682 if (*p == '<') *p = '*'; continue;
683 if (*p == '>') *p = '?'; continue;
686 for (p=uname; *p; p++) {
687 if (*p == '"') *p = '.'; continue;
688 if (*p == '<') *p = '*'; continue;
689 if (*p == '>') *p = '?'; continue;
693 pename = cm_ClientCharThis(name + cm_ClientStrLen(name));
698 pattern = cm_ClientCharNext(pattern);
701 name = cm_ClientCharNext(name);
705 pattern = cm_ClientCharNext(pattern);
706 if (*pattern == '\0')
709 pattern_next = cm_ClientCharNext(pattern);
711 for (p = pename; p >= name; p = cm_ClientCharPrev(p)) {
712 if (*p == *pattern &&
713 szWildCardMatchFileName(pattern_next,
714 cm_ClientCharNext(p), FALSE))
717 if (*pattern == '.' && *pattern_next == '\0') {
718 for (p = name; p && *p; p = cm_ClientCharNext(p))
728 if (*name != *pattern)
730 pattern = cm_ClientCharNext(pattern);
731 name = cm_ClientCharNext(name);
736 /* if all we have left are wildcards, then we match */
737 for (;*pattern; pattern = cm_ClientCharNext(pattern)) {
738 if (*pattern != '*' && *pattern != '?')
744 /* do a case-folding search of the star name mask with the name in namep.
745 * Return 1 if we match, otherwise 0.
747 int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags)
749 clientchar_t *newmask, lastchar = _C('\0');
750 int i, j, casefold, retval;
751 int star = 0, qmark = 0, dot = 0;
753 /* make sure we only match 8.3 names, if requested */
754 if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
757 casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
759 /* optimize the pattern:
760 * if there is a mixture of '?' and '*',
761 * for example the sequence "*?*?*?*"
762 * must be turned into the form "*"
764 newmask = (clientchar_t *)malloc((cm_ClientStrLen(maskp)+2)*sizeof(clientchar_t));
765 for ( i=0, j=0, star=0, qmark=0; maskp[i]; i++) {
767 switch ( maskp[i] ) {
782 } else if ( qmark ) {
786 newmask[j++] = maskp[i];
793 } else if ( qmark ) {
797 if (dot == 0 && lastchar == '<')
801 retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
808 cm_TargetPerceivedAsDirectory(const fschar_t *target)
812 ext = PathFindExtension(target);
820 cm_LoadAfsdHookLib(void)
826 if (!GetModuleFileName(NULL, dllname, sizeof(dllname)))
829 p = strrchr(dllname, '\\');
832 strcpy(p, AFSD_HOOK_DLL);
833 hLib = LoadLibrary(dllname);
835 hLib = LoadLibrary(AFSD_HOOK_DLL);
842 * Obtain the file info structure for the specified file.
843 * If a full path is not specified, the search order is the
844 * same as that used by LoadLibrary().
847 cm_GetOSFileVersion (char *filename, LARGE_INTEGER *liVer)
855 VS_FIXEDFILEINFO vsf;
857 dwSize = GetFileVersionInfoSizeA(filename,&dwHandle);
862 pInfo = (char*)malloc(dwSize);
867 rc = GetFileVersionInfoA(filename, dwHandle, dwSize, pInfo);
870 rc = VerQueryValueA(pInfo,"\\",&pbuf, &uLen);
873 memcpy(&vsf, pbuf, sizeof(VS_FIXEDFILEINFO));
875 liVer->LowPart = vsf.dwFileVersionLS;
876 liVer->HighPart = vsf.dwFileVersionMS;
885 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
886 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID *);
887 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID);
889 BOOL msftSMBRedirectorSupportsExtendedTimeouts(void)
891 static BOOL fChecked = FALSE;
892 static BOOL fSupportsExtendedTimeouts = FALSE;
896 BOOL isWow64 = FALSE;
897 OSVERSIONINFOEX Version;
899 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
900 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection = NULL;
901 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection = NULL;
902 PVOID Wow64RedirectionState;
903 LARGE_INTEGER fvFile, fvHotFixMin;
905 h1 = GetModuleHandle("kernel32.dll"); /* no refcount increase */
907 * If we don't find the fnIsWow64Process function then we
908 * are not running in a Wow64 environment
911 (LPFN_ISWOW64PROCESS)GetProcAddress(h1, "IsWow64Process");
913 memset (&Version, 0x00, sizeof(Version));
914 Version.dwOSVersionInfoSize = sizeof(Version);
915 GetVersionEx((OSVERSIONINFO *) &Version);
918 * Support is available as hot fixes / service packs on:
925 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
926 Version.dwMajorVersion >= 5) {
929 if (Version.dwMajorVersion == 5 &&
930 Version.dwMinorVersion == 1) {
932 fvHotFixMin.HighPart = (5 << 16) | 1;
934 switch (Version.wServicePackMajor) {
936 fvHotFixMin.LowPart = (2600 << 16) | 5815;
939 fvHotFixMin.LowPart = (2600 << 16) | 3572;
942 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 3);
947 /* 64-bit XP and Server 2003 */
948 else if (Version.dwMajorVersion == 5 &&
949 Version.dwMinorVersion == 2) {
951 fvHotFixMin.HighPart = (5 << 16) | 2;
953 switch (Version.wServicePackMajor) {
955 fvHotFixMin.LowPart = (3790 << 16) | 4479;
958 fvHotFixMin.LowPart = (3790 << 16) | 3310;
961 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
966 /* Vista and Server 2008 */
967 else if (Version.dwMajorVersion == 6 &&
968 Version.dwMinorVersion == 0) {
970 fvHotFixMin.HighPart = (6 << 16) | 0;
972 switch (Version.wServicePackMajor) {
974 fvHotFixMin.LowPart = (6002 << 16) | 18005;
977 fSupportsExtendedTimeouts = (Version.wServicePackMajor > 2);
982 /* Windows 7 and Server 2008 R2 and beyond */
983 else if (Version.dwMajorVersion > 6 ||
984 Version.dwMajorVersion == 6 &&
985 Version.dwMinorVersion >= 1) {
986 fSupportsExtendedTimeouts = TRUE;
990 /* If wow64, disable wow64 redirection and preserve the existing state */
991 if (fnIsWow64Process &&
992 fnIsWow64Process(GetCurrentProcess(), &isWow64) &&
994 fnDisableWow64FsRedirection =
995 (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64DisableWow64FsRedirection");
996 fnRevertWow64FsRedirection =
997 (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(h1, "Wow64RevertWow64FsRedirection");
998 fnDisableWow64FsRedirection(&Wow64RedirectionState);
1001 if (cm_GetOSFileVersion("drivers\\mrxsmb.sys", &fvFile) ||
1002 (fvFile.QuadPart >= fvHotFixMin.QuadPart))
1003 fSupportsExtendedTimeouts = TRUE;
1005 /* If wow64, restore the previous redirection state */
1006 if (fnIsWow64Process && isWow64) {
1007 fnRevertWow64FsRedirection(Wow64RedirectionState);
1014 return fSupportsExtendedTimeouts;
1017 void cm_ResetServerPriority()
1019 void * p = TlsGetValue(cm_TlsRequestSlot);
1022 TlsSetValue(cm_TlsRequestSlot, NULL);
1023 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1027 void cm_SetRequestStartTime()
1029 time_t * tp = TlsGetValue(cm_TlsRequestSlot);
1031 tp = malloc(sizeof(time_t));
1035 if (!TlsSetValue(cm_TlsRequestSlot, tp))
1040 void cm_UpdateServerPriority()
1042 time_t *tp = TlsGetValue(cm_TlsRequestSlot);
1045 time_t now = osi_Time();
1047 /* Give one priority boost for each 15 seconds */
1048 SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
1053 void cm_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
1055 // Note that LONGLONG is a 64-bit value
1058 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
1059 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
1060 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
1063 void cm_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
1065 // Note that LONGLONG is a 64-bit value
1068 ll = largeTimep->dwHighDateTime;
1070 ll += largeTimep->dwLowDateTime;
1072 ll -= 116444736000000000;
1075 *unixTimep = (DWORD)ll;
1078 void cm_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
1083 struct tm localJunk;
1084 time_t t = unixTime;
1086 ltp = localtime(&t);
1088 /* if we fail, make up something */
1091 localJunk.tm_year = 89 - 20;
1092 localJunk.tm_mon = 4;
1093 localJunk.tm_mday = 12;
1094 localJunk.tm_hour = 0;
1095 localJunk.tm_min = 0;
1096 localJunk.tm_sec = 0;
1099 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
1100 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
1101 *searchTimep = (dosDate<<16) | dosTime;
1104 void cm_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
1106 unsigned short dosDate;
1107 unsigned short dosTime;
1110 dosDate = (unsigned short) (searchTime & 0xffff);
1111 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
1113 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
1114 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
1115 localTm.tm_mday = (dosDate) & 0x1f;
1116 localTm.tm_hour = (dosTime>>11) & 0x1f;
1117 localTm.tm_min = (dosTime >> 5) & 0x3f;
1118 localTm.tm_sec = (dosTime & 0x1f) * 2;
1119 localTm.tm_isdst = -1; /* compute whether DST in effect */
1121 *unixTimep = mktime(&localTm);
1125 cm_NextHighestPowerOf2(afs_uint32 n)