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>
34 #include <cm_scache.h>
40 #include <pioctl_nt.h>
41 static char AFSConfigKeyName[] =
42 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
44 #define FS_IOCTLREQUEST_MAXSIZE 8192
45 /* big structure for representing and storing an IOCTL request */
46 typedef struct fs_ioctlRequest {
47 char *mp; /* marshalling/unmarshalling ptr */
48 long nbytes; /* bytes received (when unmarshalling) */
49 char data[FS_IOCTLREQUEST_MAXSIZE]; /* data we're marshalling */
53 CMtoUNIXerror(int cm_code)
56 case CM_ERROR_TIMEDOUT:
58 case CM_ERROR_NOACCESS:
60 case CM_ERROR_NOSUCHFILE:
68 case CM_ERROR_CROSSDEVLINK:
74 case CM_ERROR_READONLY:
76 case CM_ERROR_WOULDBLOCK:
78 case CM_ERROR_NOSUCHCELL:
79 return ESRCH; /* hack */
80 case CM_ERROR_NOSUCHVOLUME:
81 return EPIPE; /* hack */
82 case CM_ERROR_NOMORETOKENS:
83 return EDOM; /* hack */
84 case CM_ERROR_TOOMANYBUFS:
85 return EFBIG; /* hack */
92 InitFSRequest(fs_ioctlRequest_t * rp)
99 GetIoctlHandle(char *fileNamep, HANDLE * handlep)
111 drivep = strchr(fileNamep, ':');
112 if (drivep && (drivep - fileNamep) >= 1) {
113 tbuffer[0] = *(drivep - 1);
115 strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
117 strcpy(tbuffer, SMB_IOCTL_FILENAME);
119 /* No file name specified, use UNC name */
120 /* First look for gateway host in Registry */
122 RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
123 KEY_QUERY_VALUE, &parmKey);
124 if (code != ERROR_SUCCESS)
126 dummyLen = sizeof(hostName);
128 RegQueryValueEx(parmKey, "Gateway", NULL, NULL, hostName,
130 RegCloseKey(parmKey);
131 if (code == ERROR_SUCCESS)
134 /* No gateway name in registry; use ourself */
135 #ifndef AFS_WIN95_ENV
136 gethostname(hostName, sizeof(hostName));
140 /* DJGPP version of gethostname gets the NetBIOS
141 * name of the machine, so that is what we are using for
142 * the AFS server name instead of the DNS name. */
143 hostsize = sizeof(hostName);
144 GetComputerName(hostName, &hostsize);
146 #endif /* AFS_WIN95_ENV */
149 ctemp = strchr(hostName, '.'); /* turn ntafs.* into ntafs */
155 sprintf(tbuffer, "\\\\%s-AFS\\all%s", hostName, SMB_IOCTL_FILENAME);
159 /* now open the file */
160 fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
161 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
162 FILE_FLAG_WRITE_THROUGH, NULL);
164 if (fh == INVALID_HANDLE_VALUE)
167 /* return fh and success code */
173 Transceive(HANDLE handle, fs_ioctlRequest_t * reqp)
178 rcount = reqp->mp - reqp->data;
180 return EINVAL; /* not supposed to happen */
182 if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
183 /* failed to write */
184 return GetLastError();
187 if (!ReadFile(handle, reqp->data, sizeof(reqp->data), &ioCount, NULL)) {
189 return GetLastError();
192 reqp->nbytes = ioCount; /* set # of bytes available */
193 reqp->mp = reqp->data; /* restart marshalling */
200 MarshallLong(fs_ioctlRequest_t * reqp, long val)
202 memcpy(reqp->mp, &val, 4);
208 UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
210 /* not enough data left */
211 if (reqp->nbytes < 4) {
215 memcpy(valp, reqp->mp, 4);
221 /* includes marshalling NULL pointer as a null (0 length) string */
223 MarshallString(fs_ioctlRequest_t * reqp, char *stringp)
228 count = strlen(stringp) + 1; /* space required including null */
232 /* watch for buffer overflow */
233 if ((reqp->mp - reqp->data) + count > sizeof(reqp->data))
237 memcpy(reqp->mp, stringp, count);
244 /* take a path with a drive letter, possibly relative, and return a full path
245 * without the drive letter. This is the full path relative to the working
246 * dir for that drive letter. The input and output paths can be the same.
249 fs_GetFullPath(char *pathp, char *outPathp, long outSize)
259 if (pathp[0] != 0 && pathp[1] == ':') {
260 /* there's a drive letter there */
268 if (*firstp == '\\' || *firstp == '/') {
269 /* already an absolute pathname, just copy it back */
270 strcpy(outPathp, firstp);
274 GetCurrentDirectory(sizeof(origPath), origPath);
277 if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) {
278 /* a drive has been specified and it isn't our current drive.
279 * to get path, switch to it first. Must case-fold drive letters
280 * for user convenience.
286 if (!SetCurrentDirectory(newPath)) {
287 code = GetLastError();
292 /* now get the absolute path to the current wdir in this drive */
293 GetCurrentDirectory(sizeof(tpath), tpath);
294 strcpy(outPathp, tpath + 2); /* skip drive letter */
295 /* if there is a non-null name after the drive, append it */
297 strcat(outPathp, "\\");
298 strcat(outPathp, firstp);
301 /* finally, if necessary, switch back to our home drive letter */
303 SetCurrentDirectory(origPath);
310 pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow)
312 fs_ioctlRequest_t preq;
318 code = GetIoctlHandle(pathp, &reqHandle);
327 /* init the request structure */
328 InitFSRequest(&preq);
330 /* marshall the opcode, the path name and the input parameters */
331 MarshallLong(&preq, opcode);
332 /* when marshalling the path, remove the drive letter, since we already
333 * used the drive letter to find the AFS daemon; we don't need it any more.
334 * Eventually we'll expand relative path names here, too, since again, only
335 * we understand those.
338 code = fs_GetFullPath(pathp, fullPath, sizeof(fullPath));
340 CloseHandle(reqHandle);
345 strcpy(fullPath, "");
348 MarshallString(&preq, fullPath);
349 if (blobp->in_size) {
350 memcpy(preq.mp, blobp->in, blobp->in_size);
351 preq.mp += blobp->in_size;
354 /* now make the call */
355 code = Transceive(reqHandle, &preq);
357 CloseHandle(reqHandle);
361 /* now unmarshall the return value */
362 UnmarshallLong(&preq, &temp);
364 CloseHandle(reqHandle);
365 errno = CMtoUNIXerror(temp);
369 /* otherwise, unmarshall the output parameters */
370 if (blobp->out_size) {
371 temp = blobp->out_size;
372 if (preq.nbytes < temp)
374 memcpy(blobp->out, preq.mp, temp);
375 blobp->out_size = temp;
378 /* and return success */
379 CloseHandle(reqHandle);