/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
-/* AFSIFS portions copyright (c) 2005
- * the regents of the university of michigan
- * all rights reserved
- *
- * permission is granted to use, copy, create derivative works and
- * redistribute this software and such derivative works for any purpose,
- * so long as the name of the university of michigan is not used in
- * any advertising or publicity pertaining to the use or distribution
- * of this software without specific, written prior authorization. if
- * the above copyright notice or any other identification of the
- * university of michigan is included in any copy of any portion of
- * this software, then the disclaimer below must also be included.
- *
- * this software is provided as is, without representation from the
- * university of michigan as to its fitness for any purpose, and without
- * warranty by the university of michigan of any kind, either express
- * or implied, including without limitation the implied warranties of
- * merchantability and fitness for a particular purpose. the regents
- * of the university of michigan shall not be liable for any damages,
- * including special, indirect, incidental, or consequential damages,
- * with respect to any claim arising out or in connection with the use
- * of the software, even if it has been or is hereafter advised of the
- * possibility of such damages.
- */
#include <afsconfig.h>
#include <afs/param.h>
+#include <afs/stds.h>
-RCSID
- ("$Header$");
+#include <roken.h>
-#include <afs/stds.h>
#include <windows.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <malloc.h>
-#include <string.h>
#include <winioctl.h>
#include <winsock2.h>
#define SECURITY_WIN32
#include <osi.h>
#include <cm.h>
-#include <cm_dir.h>
+#include <cm_nls.h>
+#include <cm_server.h>
#include <cm_cell.h>
#include <cm_user.h>
#include <cm_conn.h>
#include <cm_scache.h>
#include <cm_buf.h>
+#include <cm_dir.h>
#include <cm_utils.h>
#include <cm_ioctl.h>
#include <pioctl_nt.h>
#include <WINNT/afsreg.h>
#include <lanahelper.h>
-#include <../WINNT/afsrdr/kif.h>
#include <loadfuncs-krb5.h>
#include <krb5.h>
static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY;
+static const char utf8_prefix[] = UTF8_PREFIX;
+static const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char);
+
#define FS_IOCTLREQUEST_MAXSIZE 8192
/* big structure for representing and storing an IOCTL request */
typedef struct fs_ioctlRequest {
case CM_ERROR_NOACCESS:
return EACCES;
case CM_ERROR_NOSUCHFILE:
+ case CM_ERROR_NOSUCHPATH:
+ case CM_ERROR_BPLUS_NOMATCH:
return ENOENT;
case CM_ERROR_INVAL:
return EINVAL;
case CM_ERROR_BADFD:
return EBADF;
case CM_ERROR_EXISTS:
+ case CM_ERROR_INEXACT_MATCH:
return EEXIST;
case CM_ERROR_CROSSDEVLINK:
return EXDEV;
return EDOM; /* hack */
case CM_ERROR_TOOMANYBUFS:
return EFBIG; /* hack */
+ case CM_ERROR_ALLBUSY:
+ return EBUSY;
+ case CM_ERROR_ALLDOWN:
+ return ENOSYS; /* hack */
+ case CM_ERROR_ALLOFFLINE:
+ return ENXIO; /* hack */
default:
if (cm_code > 0 && cm_code < EILSEQ)
return cm_code;
if ( !init ) {
HKEY hk;
- if (RegOpenKey (HKEY_LOCAL_MACHINE,
+ if (RegOpenKey (HKEY_LOCAL_MACHINE,
TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
{
DWORD dwSize = sizeof(BOOL);
return debug;
}
+static BOOL
+DisableServiceManagerCheck(void)
+{
+ static int init = 0;
+ static BOOL smcheck = 0;
+
+ if ( !init ) {
+ HKEY hk;
+
+ if (RegOpenKey (HKEY_LOCAL_MACHINE,
+ TEXT("Software\\OpenAFS\\Client"), &hk) == 0)
+ {
+ DWORD dwSize = sizeof(BOOL);
+ DWORD dwType = REG_DWORD;
+ RegQueryValueEx (hk, TEXT("DisableIoctlSMCheck"), NULL, &dwType, (PBYTE)&smcheck, &dwSize);
+ RegCloseKey (hk);
+ }
+
+ init = 1;
+ }
+
+ return smcheck;
+}
+
+static DWORD
+GetServiceStatus(
+ LPSTR lpszMachineName,
+ LPSTR lpszServiceName,
+ DWORD *lpdwCurrentState)
+{
+ DWORD hr = NOERROR;
+ SC_HANDLE schSCManager = NULL;
+ SC_HANDLE schService = NULL;
+ DWORD fdwDesiredAccess = 0;
+ SERVICE_STATUS ssServiceStatus = {0};
+ BOOL fRet = FALSE;
+
+ *lpdwCurrentState = 0;
+
+ fdwDesiredAccess = GENERIC_READ;
+
+ schSCManager = OpenSCManager(lpszMachineName,
+ NULL,
+ fdwDesiredAccess);
+
+ if(schSCManager == NULL)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ schService = OpenService(schSCManager,
+ lpszServiceName,
+ fdwDesiredAccess);
+
+ if(schService == NULL)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ fRet = QueryServiceStatus(schService,
+ &ssServiceStatus);
+
+ if(fRet == FALSE)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ *lpdwCurrentState = ssServiceStatus.dwCurrentState;
+
+cleanup:
+
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+
+ return(hr);
+}
// krb5 functions
DECL_FUNC_PTR(krb5_cc_default_name);
if (error) return 0;
return 1;
}
-
+#if defined(_IA64_) || defined(_AMD64_)
+#define KERB5DLL "krb5_64.dll"
+#else
#define KERB5DLL "krb5_32.dll"
+#endif
static BOOL
IsKrb5Available()
{
szUser[*dwSize-1] = '\0';
success = 1;
}
- *dwSize = strlen(pname);
+ *dwSize = (DWORD)strlen(pname);
cleanup:
if (pname)
return success;
}
+//
+// Recursively evaluate drivestr to find the final
+// dos drive letter to which the source is mapped.
+//
+static BOOL
+DriveSubstitution(char *drivestr, char *subststr, size_t substlen)
+{
+ char device[MAX_PATH];
+
+ if ( QueryDosDevice(drivestr, device, MAX_PATH) )
+ {
+ if ( device[0] == '\\' &&
+ device[1] == '?' &&
+ device[2] == '?' &&
+ device[3] == '\\' &&
+ isalpha(device[4]) &&
+ device[5] == ':')
+ {
+ device[0] = device[4];
+ device[1] = ':';
+ device[2] = '\0';
+ if ( DriveSubstitution(device, subststr, substlen) )
+ {
+ return TRUE;
+ } else {
+ subststr[0] = device[0];
+ subststr[1] = ':';
+ subststr[2] = '\0';
+ return TRUE;
+ }
+ } else
+ if ( device[0] == '\\' &&
+ device[1] == '?' &&
+ device[2] == '?' &&
+ device[3] == '\\' &&
+ device[4] == 'U' &&
+ device[5] == 'N' &&
+ device[6] == 'C' &&
+ device[7] == '\\')
+ {
+ subststr[0] = '\\';
+ strncpy(&subststr[1], &device[7], substlen-1);
+ subststr[substlen-1] = '\0';
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//
+// drivestr - is "<drive-letter>:"
+//
+static BOOL
+DriveIsMappedToAFS(char *drivestr, char *NetbiosName)
+{
+ DWORD dwResult, dwResultEnum;
+ HANDLE hEnum;
+ DWORD cbBuffer = 16384; // 16K is a good size
+ DWORD cEntries = -1; // enumerate all possible entries
+ LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
+ DWORD i;
+ BOOL bIsAFS = FALSE;
+ char subststr[MAX_PATH];
+
+ //
+ // Handle drive letter substitution created with "SUBST <drive> <path>".
+ // If a substitution has occurred, use the target drive letter instead
+ // of the source.
+ //
+ if ( DriveSubstitution(drivestr, subststr, MAX_PATH) )
+ {
+ if (subststr[0] == '\\' &&
+ subststr[1] == '\\')
+ {
+ if (_strnicmp( &subststr[2], NetbiosName, strlen(NetbiosName)) == 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ drivestr = subststr;
+ }
+
+ //
+ // Call the WNetOpenEnum function to begin the enumeration.
+ //
+ dwResult = WNetOpenEnum(RESOURCE_CONNECTED,
+ RESOURCETYPE_DISK,
+ RESOURCEUSAGE_ALL,
+ NULL, // NULL first time the function is called
+ &hEnum); // handle to the resource
+
+ if (dwResult != NO_ERROR)
+ return FALSE;
+
+ //
+ // Call the GlobalAlloc function to allocate resources.
+ //
+ lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
+ if (lpnrLocal == NULL)
+ return FALSE;
+
+ do {
+ //
+ // Initialize the buffer.
+ //
+ ZeroMemory(lpnrLocal, cbBuffer);
+ //
+ // Call the WNetEnumResource function to continue
+ // the enumeration.
+ //
+ cEntries = -1;
+ dwResultEnum = WNetEnumResource(hEnum, // resource handle
+ &cEntries, // defined locally as -1
+ lpnrLocal, // LPNETRESOURCE
+ &cbBuffer); // buffer size
+ //
+ // If the call succeeds, loop through the structures.
+ //
+ if (dwResultEnum == NO_ERROR) {
+ for (i = 0; i < cEntries; i++) {
+ if (lpnrLocal[i].lpLocalName &&
+ toupper(lpnrLocal[i].lpLocalName[0]) == toupper(drivestr[0])) {
+ //
+ // Skip the two backslashes at the start of the UNC device name
+ //
+ if ( _strnicmp( &(lpnrLocal[i].lpRemoteName[2]), NetbiosName, strlen(NetbiosName)) == 0 )
+ {
+ bIsAFS = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ // Process errors.
+ //
+ else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
+ break;
+ }
+ while (dwResultEnum != ERROR_NO_MORE_ITEMS);
+
+ //
+ // Call the GlobalFree function to free the memory.
+ //
+ GlobalFree((HGLOBAL) lpnrLocal);
+ //
+ // Call WNetCloseEnum to end the enumeration.
+ //
+ dwResult = WNetCloseEnum(hEnum);
+
+ return bIsAFS;
+}
+
+static BOOL
+DriveIsGlobalAutoMapped(char *drivestr)
+{
+ DWORD dwResult;
+ HKEY hKey;
+ DWORD dwSubMountSize;
+ char szSubMount[260];
+ DWORD dwType;
+
+ dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_SVC_PARAM_SUBKEY "\\GlobalAutoMapper",
+ 0, KEY_QUERY_VALUE, &hKey);
+ if (dwResult != ERROR_SUCCESS)
+ return FALSE;
+
+ dwSubMountSize = sizeof(szSubMount);
+ dwType = REG_SZ;
+ dwResult = RegQueryValueEx(hKey, drivestr, 0, &dwType, szSubMount, &dwSubMountSize);
+ RegCloseKey(hKey);
+
+ if (dwResult == ERROR_SUCCESS && dwType == REG_SZ)
+ return TRUE;
+ else
+ return FALSE;
+}
+
static long
GetIoctlHandle(char *fileNamep, HANDLE * handlep)
{
- char *drivep;
+ char *drivep = NULL;
char netbiosName[MAX_NB_NAME_LENGTH];
- char tbuffer[256]="";
+ DWORD CurrentState = 0;
+ char HostName[64] = "";
+ char tbuffer[MAX_PATH]="";
HANDLE fh;
HKEY hk;
char szUser[128] = "";
DWORD ioctlDebug = IoctlDebug();
DWORD gle;
DWORD dwSize = sizeof(szUser);
+ int saveerrno;
+ UINT driveType;
+ int sharingViolation;
+
+ memset(HostName, '\0', sizeof(HostName));
+ gethostname(HostName, sizeof(HostName));
+ if (!DisableServiceManagerCheck() &&
+ GetServiceStatus(HostName, TEXT("TransarcAFSDaemon"), &CurrentState) == NOERROR &&
+ CurrentState != SERVICE_RUNNING)
+ return -1;
+
+ // Populate the Netbios Name
+ lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
-#ifndef AFSIFS
if (fileNamep) {
drivep = strchr(fileNamep, ':');
if (drivep && (drivep - fileNamep) >= 1) {
tbuffer[0] = *(drivep - 1);
tbuffer[1] = ':';
- strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
- } else if (fileNamep[0] == fileNamep[1] &&
+ tbuffer[2] = '\0';
+
+ driveType = GetDriveType(tbuffer);
+ switch (driveType) {
+ case DRIVE_UNKNOWN:
+ case DRIVE_REMOTE:
+ if (DriveIsMappedToAFS(tbuffer, netbiosName) ||
+ DriveIsGlobalAutoMapped(tbuffer))
+ strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+ else
+ return -1;
+ break;
+ default:
+ if (DriveIsGlobalAutoMapped(tbuffer))
+ strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+ else
+ return -1;
+ }
+ } else if (fileNamep[0] == fileNamep[1] &&
(fileNamep[0] == '\\' || fileNamep[0] == '/'))
{
int count = 0, i = 0;
count++;
i++;
}
- if (fileNamep[i] == 0)
+ if (fileNamep[i] == 0 || (fileNamep[i-1] != '\\' && fileNamep[i-1] != '/'))
tbuffer[i++] = '\\';
tbuffer[i] = 0;
- strcat(tbuffer, SMB_IOCTL_FILENAME);
+ strcat(tbuffer, SMB_IOCTL_FILENAME_NOSLASH);
} else {
- char curdir[256]="";
+ char curdir[MAX_PATH]="";
GetCurrentDirectory(sizeof(curdir), curdir);
if ( curdir[1] == ':' ) {
tbuffer[0] = curdir[0];
tbuffer[1] = ':';
- strcpy(tbuffer + 2, SMB_IOCTL_FILENAME);
+ tbuffer[2] = '\0';
+
+ driveType = GetDriveType(tbuffer);
+ switch (driveType) {
+ case DRIVE_UNKNOWN:
+ case DRIVE_REMOTE:
+ if (DriveIsMappedToAFS(tbuffer, netbiosName) ||
+ DriveIsGlobalAutoMapped(tbuffer))
+ strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+ else
+ return -1;
+ break;
+ default:
+ if (DriveIsGlobalAutoMapped(tbuffer))
+ strcpy(&tbuffer[2], SMB_IOCTL_FILENAME);
+ else
+ return -1;
+ }
} else if (curdir[0] == curdir[1] &&
- (curdir[0] == '\\' || curdir[0] == '/'))
+ (curdir[0] == '\\' || curdir[0] == '/'))
{
int count = 0, i = 0;
count++;
i++;
}
- if (tbuffer[i] == 0)
+ if (curdir[i] == 0 || (curdir[i-1] != '\\' && curdir[i-1] != '/'))
tbuffer[i++] = '\\';
tbuffer[i] = 0;
strcat(tbuffer, SMB_IOCTL_FILENAME_NOSLASH);
}
if (!tbuffer[0]) {
/* No file name starting with drive colon specified, use UNC name */
- lana_GetNetbiosName(netbiosName,LANA_NETBIOS_NAME_FULL);
sprintf(tbuffer,"\\\\%s\\all%s",netbiosName,SMB_IOCTL_FILENAME);
}
-#else
- sprintf(tbuffer,"\\\\.\\afscom\\ioctl");
-#endif
fflush(stdout);
/* now open the file */
- fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_WRITE_THROUGH, NULL);
-
- fflush(stdout);
+ sharingViolation = 0;
+ do {
+ if (sharingViolation)
+ Sleep(100);
+ fh = CreateFile(tbuffer, FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation++;
+ } while (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_SHARING_VIOLATION &&
+ sharingViolation < 100);
+ fflush(stdout);
-#ifdef AFSIFS
if (fh == INVALID_HANDLE_VALUE) {
- return -1;
- }
-#endif
-
- if (fh == INVALID_HANDLE_VALUE) {
- int gonext = 0;
-
gle = GetLastError();
if (gle && ioctlDebug ) {
char buf[4096];
+ saveerrno = errno;
if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
gle,
fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
tbuffer,gle,buf);
}
+ errno = saveerrno;
+ SetLastError(gle);
}
+ }
+
+ if (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() != ERROR_SHARING_VIOLATION) {
+ int gonext = 0;
lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
- if (RegOpenKey (HKEY_CURRENT_USER,
+ if (RegOpenKey (HKEY_CURRENT_USER,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hk) == 0)
{
DWORD dwType = REG_SZ;
}
if ( szUser[0] ) {
- if ( ioctlDebug )
+ if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl Explorer logon user: [%s]\r\n",szUser);
-
+ errno = saveerrno;
+ }
sprintf(szPath, "\\\\%s", szClient);
memset (&nr, 0x00, sizeof(NETRESOURCE));
nr.dwType=RESOURCETYPE_DISK;
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
gonext = 1;
}
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
gonext = 1;
}
if (gonext)
goto try_lsa_principal;
- fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation = 0;
+ do {
+ if (sharingViolation)
+ Sleep(100);
+ fh = CreateFile(tbuffer, FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation++;
+ } while (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_SHARING_VIOLATION &&
+ sharingViolation < 100);
fflush(stdout);
if (fh == INVALID_HANDLE_VALUE) {
gle = GetLastError();
if (gle && ioctlDebug ) {
char buf[4096];
+ saveerrno = errno;
if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
gle,
fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
tbuffer,gle,buf);
}
+ errno = saveerrno;
+ SetLastError(gle);
}
}
}
}
try_lsa_principal:
- if (fh == INVALID_HANDLE_VALUE) {
+ if (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() != ERROR_SHARING_VIOLATION) {
int gonext = 0;
dwSize = sizeof(szUser);
if (GetLSAPrincipalName(szUser, &dwSize)) {
- if ( ioctlDebug )
+ if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl LSA Principal logon user: [%s]\r\n",szUser);
-
+ errno = saveerrno;
+ }
sprintf(szPath, "\\\\%s", szClient);
memset (&nr, 0x00, sizeof(NETRESOURCE));
nr.dwType=RESOURCETYPE_DISK;
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
gonext = 1;
}
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
gonext = 1;
}
if (gonext)
goto try_sam_compat;
- fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation = 0;
+ do {
+ if (sharingViolation)
+ Sleep(100);
+ fh = CreateFile(tbuffer, FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation++;
+ } while (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_SHARING_VIOLATION &&
+ sharingViolation < 100);
fflush(stdout);
if (fh == INVALID_HANDLE_VALUE) {
gle = GetLastError();
if (gle && ioctlDebug ) {
char buf[4096];
+ saveerrno = errno;
if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
gle,
fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
tbuffer,gle,buf);
}
+ errno = saveerrno;
+ SetLastError(gle);
}
}
}
}
try_sam_compat:
- if ( fh == INVALID_HANDLE_VALUE ) {
+ if (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() != ERROR_SHARING_VIOLATION) {
dwSize = sizeof(szUser);
if (GetUserNameEx(NameSamCompatible, szUser, &dwSize)) {
- if ( ioctlDebug )
+ if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl SamCompatible logon user: [%s]\r\n",szUser);
-
+ errno = saveerrno;
+ }
sprintf(szPath, "\\\\%s", szClient);
memset (&nr, 0x00, sizeof(NETRESOURCE));
nr.dwType=RESOURCETYPE_DISK;
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
}
res = WNetAddConnection2(&nr,NULL,szUser,0);
if (res) {
if ( ioctlDebug ) {
+ saveerrno = errno;
fprintf(stderr, "pioctl WNetAddConnection2(%s,%s) failed: 0x%X\r\n",
szPath,szUser,res);
+ errno = saveerrno;
}
return -1;
}
- fh = CreateFile(tbuffer, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation = 0;
+ do {
+ if (sharingViolation)
+ Sleep(100);
+ fh = CreateFile(tbuffer, FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_WRITE_THROUGH, NULL);
+ sharingViolation++;
+ } while (fh == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_SHARING_VIOLATION &&
+ sharingViolation < 100);
fflush(stdout);
if (fh == INVALID_HANDLE_VALUE) {
gle = GetLastError();
if (gle && ioctlDebug ) {
char buf[4096];
+ saveerrno = errno;
if ( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
gle,
fprintf(stderr,"pioctl CreateFile(%s) failed: 0x%X\r\n\t[%s]\r\n",
tbuffer,gle,buf);
}
+ errno = saveerrno;
}
return -1;
}
}
}
+ if (fh == INVALID_HANDLE_VALUE)
+ return -1;
+
/* return fh and success code */
*handlep = fh;
return 0;
long rcount;
long ioCount;
DWORD gle;
- char *data;
+ DWORD ioctlDebug = IoctlDebug();
+ int save;
- rcount = reqp->mp - reqp->data;
+ rcount = (long)(reqp->mp - reqp->data);
if (rcount <= 0) {
- if ( IoctlDebug() )
+ if ( ioctlDebug ) {
+ save = errno;
fprintf(stderr, "pioctl Transceive rcount <= 0: %d\r\n",rcount);
+ errno = save;
+ }
return EINVAL; /* not supposed to happen */
}
-#ifndef AFSIFS
if (!WriteFile(handle, reqp->data, rcount, &ioCount, NULL)) {
/* failed to write */
gle = GetLastError();
- if ( IoctlDebug() )
+ if ( ioctlDebug ) {
+ save = errno;
fprintf(stderr, "pioctl Transceive WriteFile failed: 0x%X\r\n",gle);
+ errno = save;
+ }
return gle;
}
/* failed to read */
gle = GetLastError();
- if ( IoctlDebug() )
+ if ( ioctlDebug ) {
+ save = errno;
fprintf(stderr, "pioctl Transceive ReadFile failed: 0x%X\r\n",gle);
+ errno = save;
+ }
return gle;
}
-#else
- /* ioctl completes as one operation, so copy input to a new buffer, and use as output buffer */
- data = malloc(rcount);
- memcpy(data, reqp->data, rcount);
- if (!DeviceIoControl(handle, IOCTL_AFSRDR_IOCTL, data, rcount, reqp->data, sizeof(reqp->data), &ioCount, NULL))
- {
- free(data);
- return GetLastError();
- }
- free(data);
-#endif
reqp->nbytes = ioCount; /* set # of bytes available */
reqp->mp = reqp->data; /* restart marshalling */
static long
UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp)
{
+ int save;
+
/* not enough data left */
if (reqp->nbytes < 4) {
- if ( IoctlDebug() )
+ if ( IoctlDebug() ) {
+ save = errno;
fprintf(stderr, "pioctl UnmarshallLong reqp->nbytes < 4: %d\r\n",
reqp->nbytes);
+ errno = save;
+ }
return -1;
}
/* includes marshalling NULL pointer as a null (0 length) string */
static long
-MarshallString(fs_ioctlRequest_t * reqp, char *stringp)
+MarshallString(fs_ioctlRequest_t * reqp, char *stringp, int is_utf8)
{
int count;
+ int save;
if (stringp)
- count = strlen(stringp) + 1; /* space required including null */
+ count = (int)strlen(stringp) + 1;/* space required including null */
else
count = 1;
+ if (is_utf8) {
+ count += utf8_prefix_size;
+ }
+
/* watch for buffer overflow */
if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) {
- if ( IoctlDebug() )
+ if ( IoctlDebug() ) {
+ save = errno;
fprintf(stderr, "pioctl MarshallString buffer overflow\r\n");
+ errno = save;
+ }
return -1;
}
+ if (is_utf8) {
+ memcpy(reqp->mp, utf8_prefix, utf8_prefix_size);
+ reqp->mp += utf8_prefix_size;
+ count -= utf8_prefix_size;
+ }
+
if (stringp)
memcpy(reqp->mp, stringp, count);
else
int pathHasDrive;
int doSwitch;
char newPath[3];
- HANDLE rootDir;
- wchar_t *wpath;
- unsigned long length;
char * p;
-
-#ifdef AFSIFS
- if (!pathp)
- return CM_ERROR_NOSUCHPATH;
-
- //sprintf(tpath, "%c:\\", pathp[0]);
- rootDir = CreateFile(pathp, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (rootDir == INVALID_HANDLE_VALUE)
- return CM_ERROR_NOSUCHPATH;
-
- wpath = tpath;
- length = 0;
- if (!DeviceIoControl(rootDir, IOCTL_AFSRDR_GET_PATH, NULL, 0, wpath, 1000, &length, NULL))
- {
- CloseHandle(rootDir);
- return CM_ERROR_NOSUCHPATH;
- }
- CloseHandle(rootDir);
-
- code = WideCharToMultiByte(CP_UTF8, 0/*WC_NO_BEST_FIT_CHARS*/, wpath, length/sizeof(wchar_t), outPathp, outSize/sizeof(wchar_t), NULL, NULL);
-
-// strcpy(outPathp, tpath);
- return 0;
-#endif
+ int save;
if (pathp[0] != 0 && pathp[1] == ':') {
/* there's a drive letter there */
pathHasDrive = 0;
}
- if ( firstp[0] == '\\' && firstp[1] == '\\' ||
+ if ( firstp[0] == '\\' && firstp[1] == '\\' ||
firstp[0] == '/' && firstp[1] == '/') {
/* UNC path - strip off the server and sharename */
int i, count;
if (!SetCurrentDirectory(newPath)) {
code = GetLastError();
- if ( IoctlDebug() )
+ if ( IoctlDebug() ) {
+ save = errno;
fprintf(stderr, "pioctl fs_GetFullPath SetCurrentDirectory(%s) failed: 0x%X\r\n",
newPath, code);
+ errno = save;
+ }
return code;
}
}
/* if there is a non-null name after the drive, append it */
if (*firstp != 0) {
- int len = strlen(outPathp);
- if (outPathp[len-1] != '\\' && outPathp[len-1] != '/')
+ int len = (int)strlen(outPathp);
+ if (outPathp[len-1] != '\\' && outPathp[len-1] != '/')
strcat(outPathp, "\\");
strcat(outPathp, firstp);
}
return 0;
}
-long
-pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow)
+static int
+pioctl_int(char *pathp, afs_int32 opcode, struct ViceIoctl *blobp, afs_int32 follow, afs_int32 is_utf8)
{
fs_ioctlRequest_t preq;
long code;
long temp;
char fullPath[1000];
HANDLE reqHandle;
+ int save;
code = GetIoctlHandle(pathp, &reqHandle);
if (code) {
strcpy(fullPath, "");
}
- MarshallString(&preq, fullPath);
+ MarshallString(&preq, fullPath, is_utf8);
if (blobp->in_size) {
+ if (blobp->in_size > sizeof(preq.data) - (preq.mp - preq.data)*sizeof(char)) {
+ errno = E2BIG;
+ return -1;
+ }
memcpy(preq.mp, blobp->in, blobp->in_size);
preq.mp += blobp->in_size;
}
if (temp != 0) {
CloseHandle(reqHandle);
errno = CMtoUNIXerror(temp);
- if ( IoctlDebug() )
+ if ( IoctlDebug() ) {
+ save = errno;
fprintf(stderr, "pioctl temp != 0: 0x%X\r\n",temp);
+ errno = save;
+ }
return -1;
}
CloseHandle(reqHandle);
return 0;
}
+
+int
+pioctl_utf8(char * pathp, afs_int32 opcode, struct ViceIoctl * blobp, afs_int32 follow)
+{
+ return pioctl_int(pathp, opcode, blobp, follow, TRUE);
+}
+
+int
+pioctl(char * pathp, afs_int32 opcode, struct ViceIoctl * blobp, afs_int32 follow)
+{
+ return pioctl_int(pathp, opcode, blobp, follow, FALSE);
+}
+