NTSTATUS PvfsCanonicalPathName( PSTR *ppszPath, IO_FILE_NAME IoPath ) { PPVFS_CCB pRootCcb = NULL; NTSTATUS ntError = STATUS_SUCCESS; PSTR pszFilename = NULL; PSTR pszCompletePath = NULL; if (IoPath.FileName) { ntError = PvfsWC16CanonicalPathName(&pszFilename, IoPath.FileName); BAIL_ON_NT_STATUS(ntError); } if (IoPath.RootFileHandle) { ntError = PvfsAcquireCCB(IoPath.RootFileHandle, &pRootCcb); BAIL_ON_NT_STATUS(ntError); ntError = LwRtlCStringAllocatePrintf( &pszCompletePath, "%s%s%s", pRootCcb->pszFilename, (pszFilename ? (*pszFilename == '/' ? "" : "/") : ""), (pszFilename ? pszFilename : "")); BAIL_ON_NT_STATUS(ntError); } else { pszCompletePath = pszFilename; pszFilename = NULL; } if (!pszCompletePath) { ntError = STATUS_OBJECT_NAME_INVALID; BAIL_ON_NT_STATUS(ntError); } *ppszPath = pszCompletePath; cleanup: LwRtlCStringFree(&pszFilename); if (pRootCcb) { PvfsReleaseCCB(pRootCcb); } return ntError; error: LwRtlCStringFree(&pszCompletePath); goto cleanup; }
static DWORD LsaPstorepGetPluginPath( IN PCSTR pszName, OUT PSTR* ppszPath ) { DWORD dwError = 0; int EE = 0; HANDLE registryConnection = NULL; HKEY keyHandle = NULL; PSTR pszKeyPath = NULL; PSTR pszPath = NULL; dwError = LwNtStatusToWin32Error(LwRtlCStringAllocatePrintf( &pszKeyPath, "%s\\%s", LSA_PSTORE_REG_KEY_PATH_PLUGINS, pszName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwRegOpenServer(®istryConnection); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwRegOpenKeyExA( registryConnection, NULL, pszKeyPath, 0, GENERIC_READ, &keyHandle); if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE) { LW_RTL_LOG_ERROR("LSA pstore plugin '%s' is missing its configuration registry key '%s'", pszName, pszKeyPath); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LsaPstorepRegGetStringA( registryConnection, keyHandle, LSA_PSTORE_REG_VALUE_NAME_PLUGINS_PATH, &pszPath); if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE) { LW_RTL_LOG_ERROR("LSA pstore plugin '%s' is missing the '%s' configuration value from its configuration registry key '%s'", pszName, LSA_PSTORE_REG_VALUE_NAME_PLUGINS_PATH, pszKeyPath); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: if (dwError) { LSA_PSTORE_FREE(&pszPath); } if (keyHandle) { LwRegCloseKey(registryConnection, keyHandle); } if (registryConnection) { LwRegCloseServer(registryConnection); } LSA_PSTORE_FREE(&pszKeyPath); *ppszPath = pszPath; LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
LW_NTSTATUS LwRtlSvcmLoadModule( LW_IN LW_PCWSTR pServiceName, LW_IN LW_PCWSTR pModulePath, LW_OUT PLW_SVCM_INSTANCE* ppInstance ) { NTSTATUS status = STATUS_SUCCESS; PLW_SVCM_INSTANCE pInstance = NULL; PSTR pModulePathA = NULL; LW_SVCM_MODULE_ENTRY_FUNCTION Entry = NULL; PSTR pEntryName = NULL; PSTR pBareName = NULL; PSTR pFinalSlash = NULL; PSTR pFinalDot = NULL; status = InitPool(); GCOS(status); status = LwRtlCStringAllocateFromWC16String(&pModulePathA, pModulePath); GCOS(status); pFinalSlash = strrchr(pModulePathA, '/'); pFinalDot = strrchr(pModulePathA, '.'); if (!pFinalSlash) { pFinalSlash = pModulePathA; } else { pFinalSlash++; } if (!pFinalDot) { pFinalDot = pModulePathA + strlen(pModulePathA); } status = LW_RTL_ALLOCATE(&pBareName, CHAR, (pFinalDot - pFinalSlash) + 1); GCOS(status); memcpy(pBareName, pFinalSlash, pFinalDot - pFinalSlash); status = LwRtlCStringAllocatePrintf(&pEntryName, "_LwSvcmEntry_%s", pBareName); GCOS(status); status = LW_RTL_ALLOCATE_AUTO(&pInstance); GCOS(status); LW_RTL_LOG_DEBUG("Loading service module: %s", pModulePathA); (void) dlerror(); pInstance->pDlHandle = dlopen(pModulePathA, RTLD_LOCAL | RTLD_NOW); if (!pInstance->pDlHandle) { LW_RTL_LOG_ERROR( "Could not load service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); GCOS(status); } (void) dlerror(); Entry = dlsym(pInstance->pDlHandle, pEntryName); if (!Entry) { LW_RTL_LOG_ERROR( "Could not load entry point from service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); if (!status) { status = STATUS_BAD_DLL_ENTRYPOINT; } GCOS(status); } status = LwRtlSvcmInitializeInstance(pInstance, pServiceName, pModulePathA, Entry); GCOS(status); cleanup: RTL_FREE(&pModulePathA); RTL_FREE(&pBareName); RTL_FREE(&pEntryName); if (!NT_SUCCESS(status)) { LwRtlSvcmUnload(pInstance); pInstance = NULL; } *ppInstance = pInstance; return status; }
NTSTATUS PvfsAccessCheckFileEnumerate( PPVFS_CCB pCcb, PCSTR pszRelativeFilename ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PACCESS_TOKEN pToken = pCcb->pUserToken; PSTR pszFilename = NULL; ACCESS_MASK AccessMask = 0; ACCESS_MASK GrantedAccess = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; BYTE pRelativeSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulRelativeSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; BOOLEAN bGranted = FALSE; SECURITY_INFORMATION SecInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION); ACCESS_MASK Desired = (FILE_READ_ATTRIBUTES| FILE_READ_EA| FILE_READ_DATA| READ_CONTROL); PSID pOwner = NULL; BOOLEAN bOwnerDefaulted = FALSE; /* Create the absolute path */ ntError = LwRtlCStringAllocatePrintf( &pszFilename, "%s/%s", pCcb->pScb->pOwnerFcb->pszFilename, pszRelativeFilename); BAIL_ON_NT_STATUS(ntError); /* Check the file object itself */ ntError = PvfsGetSecurityDescriptorFilename( pszFilename, SecInfo, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer), &ulRelativeSecDescLength); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD( &pSecDesc, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer)); BAIL_ON_NT_STATUS(ntError); // Tests against NTFS/Win2003R2 show that the file/directory object // owner is always granted FILE_READ_ATTRIBUTE ntError = RtlGetOwnerSecurityDescriptor( pSecDesc, &pOwner, &bOwnerDefaulted); BAIL_ON_NT_STATUS(ntError); if (RtlIsSidMemberOfToken(pToken, pOwner)) { ClearFlag(Desired, FILE_READ_ATTRIBUTES); SetFlag(GrantedAccess, FILE_READ_ATTRIBUTES); } /* Now check access */ bGranted = RtlAccessCheck( pSecDesc, pToken, Desired, GrantedAccess, &gPvfsDriverState.GenericSecurityMap, &AccessMask, &ntError); if (!bGranted) { ntError = STATUS_ACCESS_DENIED; } BAIL_ON_NT_STATUS(ntError); cleanup: if (pszFilename) { LwRtlCStringFree(&pszFilename); } if (pSecDesc) { PvfsFreeAbsoluteSecurityDescriptor(&pSecDesc); } return ntError; error: goto cleanup; }
NTSTATUS LwioRemoteOpenFile( IN PCSTR pszFileName, IN ULONG ulDesiredAccess, IN ULONG ulShareAccess, IN ULONG ulCreateDisposition, IN ULONG ulCreateOptions, OUT PIO_FILE_HANDLE phFile ) { NTSTATUS status = STATUS_SUCCESS; IO_FILE_NAME filename = {0}; IO_FILE_HANDLE handle = NULL; IO_STATUS_BLOCK ioStatus ; PSTR pszRemoteFileName = NULL; BAIL_ON_NULL_POINTER(pszFileName); status = LwRtlCStringAllocatePrintf( &pszRemoteFileName, "/rdr%s", !strncmp(pszFileName, "//", sizeof("//")-1) ? pszFileName+1 : pszFileName); BAIL_ON_NT_STATUS(status); status = LwRtlUnicodeStringAllocateFromCString( &filename.Name, pszRemoteFileName); BAIL_ON_NT_STATUS(status); status = LwNtCreateFile( &handle, /* File handle */ NULL, /* Async control block */ &ioStatus, /* IO status block */ &filename, /* Filename */ NULL, /* Security descriptor */ NULL, /* Security QOS */ ulDesiredAccess, /* Desired access mask */ 0, /* Allocation size */ 0, /* File attributes */ ulShareAccess, /* Share access */ ulCreateDisposition, /* Create disposition */ ulCreateOptions, /* Create options */ NULL, /* EA buffer */ 0, /* EA length */ NULL, /* ECP list */ NULL); BAIL_ON_NT_STATUS(status); *phFile = handle; cleanup: RTL_FREE(&pszRemoteFileName); return status; error: *phFile = NULL; goto cleanup; }
NTSTATUS PvfsSysRemoveByFileName( IN PPVFS_FILE_NAME FileName ) { NTSTATUS ntError = STATUS_SUCCESS; PSTR fileName = NULL; PSTR streamDir = NULL; PVFS_STAT streamDirStat = { 0 }; PVFS_STAT fileStat = { 0 }; PSTR pszMetaDataPath = NULL; ntError = PvfsLookupStreamDiskFileName(&fileName, FileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStat(fileName, &fileStat); if (ntError == STATUS_SUCCESS) { if(S_ISDIR(fileStat.s_mode)) { ntError = LwRtlCStringAllocatePrintf( &pszMetaDataPath, "%s/%s", fileName, PVFS_STREAM_METADATA_DIR_NAME); BAIL_ON_NT_STATUS(ntError); if (PvfsSysIsEmptyDir(pszMetaDataPath)) { ntError = PvfsSysRemove(pszMetaDataPath); BAIL_ON_NT_STATUS(ntError); } } } BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysRemove(fileName); BAIL_ON_NT_STATUS(ntError); if (PvfsIsDefaultStreamName(FileName)) { // Have to remove the stream directory as well ntError = PvfsLookupStreamDirectoryPath(&streamDir, FileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStat(streamDir, &streamDirStat); if (ntError == STATUS_SUCCESS) { ntError = PvfsSysRemoveDir(streamDir) ; BAIL_ON_NT_STATUS(ntError); } else { // Squash the error is the stream directory did not exist ntError = STATUS_SUCCESS; } BAIL_ON_NT_STATUS(ntError); } error: if (fileName) { LwRtlCStringFree(&fileName); } if (streamDir) { LwRtlCStringFree(&streamDir); } if (pszMetaDataPath) { LwRtlCStringFree(&pszMetaDataPath); } return ntError; }
static NTSTATUS PvfsSysRemoveDir( PSTR pszDirname ) { NTSTATUS ntError = STATUS_SUCCESS; DIR *pDir = NULL; struct dirent *pDirEntry = NULL; struct dirent dirEntry = { 0 }; PSTR pszPath = NULL; PVFS_STAT streamDirStat = { 0 }; ntError = PvfsSysOpenDir(pszDirname, &pDir); BAIL_ON_NT_STATUS(ntError); for (ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry); pDirEntry; ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry)) { /* First check the error return */ BAIL_ON_NT_STATUS(ntError); memset(&streamDirStat, 0, sizeof(PVFS_STAT)); if (pszPath) { LwRtlCStringFree(&pszPath); } ntError = LwRtlCStringAllocatePrintf( &pszPath, "%s/%s", pszDirname, pDirEntry->d_name); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStat(pszPath, &streamDirStat); if (ntError == STATUS_SUCCESS) { if(S_ISDIR(streamDirStat.s_mode)) { if (!LwRtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) && !LwRtlCStringIsEqual(pDirEntry->d_name, "..", FALSE)) { ntError = PvfsSysRemoveDir(pszPath); BAIL_ON_NT_STATUS(ntError); } } else { ntError = PvfsSysRemove(pszPath); BAIL_ON_NT_STATUS(ntError); } } else { // Squash the error is the stream directory did not exist ntError = STATUS_SUCCESS; } } ntError = PvfsSysCloseDir(pDir); BAIL_ON_NT_STATUS(ntError); pDir = NULL; ntError = PvfsSysRemove(pszDirname); BAIL_ON_NT_STATUS(ntError); error: if (pszPath) { LwRtlCStringFree(&pszPath); } if (pDir) { PvfsSysCloseDir(pDir); } return ntError; }
NTSTATUS PvfsSysOpenByFileName( OUT int *pFd, OUT PBOOLEAN pbCreateOwnerFile, IN PPVFS_FILE_NAME pFileName, IN int iFlags, IN mode_t Mode ) { NTSTATUS ntError = STATUS_SUCCESS; int fd = -1; int unixerr = 0; PSTR pszFilename = NULL; PVFS_STAT Stat = {0}; int Ownerfd = -1; PSTR pszStreamDirectoryName = NULL; PSTR pszMetadataPath = NULL; BOOLEAN bCreateOwnerFile = FALSE; // Need make sure the object (file/directory) exists // Before non-default stream objects can be created if (!PvfsIsDefaultStreamName(pFileName)) { ntError = PvfsSysStat(pFileName->FileName, &Stat); if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError) { ntError = PvfsSysOpen( &Ownerfd, pFileName->FileName, iFlags, Mode); if (STATUS_SUCCESS == ntError) { bCreateOwnerFile = TRUE; } } BAIL_ON_NT_STATUS(ntError); ntError = PvfsLookupStreamDirectoryPath(&pszStreamDirectoryName, pFileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsFileDirname(&pszMetadataPath, pszStreamDirectoryName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysOpenDir(pszMetadataPath, NULL); if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError) { // create meta data directory ntError = PvfsSysMkDir( pszMetadataPath, (mode_t)gPvfsDriverConfig.CreateDirectoryMode); BAIL_ON_NT_STATUS(ntError); } BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysOpenDir(pszStreamDirectoryName, NULL); if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError) { // create stream directory for an object ntError = PvfsSysMkDir( pszStreamDirectoryName, (mode_t)gPvfsDriverConfig.CreateDirectoryMode); BAIL_ON_NT_STATUS(ntError); } BAIL_ON_NT_STATUS(ntError); ntError = LwRtlCStringAllocatePrintf( &pszFilename, "%s/%s", pszStreamDirectoryName, PvfsGetCStringBaseStreamName(pFileName)); BAIL_ON_NT_STATUS(ntError); } else { ntError = LwRtlCStringDuplicate(&pszFilename, PvfsGetCStringBaseFileName(pFileName)); BAIL_ON_NT_STATUS(ntError); } if ((fd = open(pszFilename, iFlags, Mode)) == -1) { PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError); } *pFd = fd; *pbCreateOwnerFile = bCreateOwnerFile; cleanup: if (pszFilename) { LwRtlCStringFree(&pszFilename); } if (pszStreamDirectoryName) { LwRtlCStringFree(&pszStreamDirectoryName); } if (pszMetadataPath) { LwRtlCStringFree(&pszMetadataPath); } if (Ownerfd != -1) { PvfsSysClose(Ownerfd); } return ntError; error: if (fd != -1) { PvfsSysClose(fd); } goto cleanup; }
DWORD RegSrvStartListenThread( void ) { PSTR pszCachePath = NULL; PSTR pszCommPath = NULL; BOOLEAN bDirExists = FALSE; DWORD dwError = 0; static LWMsgTime idleTimeout = {30, 0}; dwError = RegSrvGetCachePath(&pszCachePath); BAIL_ON_REG_ERROR(dwError); dwError = RegCheckDirectoryExists(pszCachePath, &bDirExists); BAIL_ON_REG_ERROR(dwError); if (!bDirExists) { // Directory should be RWX for root and accessible to all // (so they can see the socket. mode_t mode = S_IRWXU | S_IRGRP| S_IXGRP | S_IROTH | S_IXOTH; dwError = RegCreateDirectory(pszCachePath, mode); BAIL_ON_REG_ERROR(dwError); } dwError = LwRtlCStringAllocatePrintf(&pszCommPath, "%s/%s", pszCachePath, REG_SERVER_FILENAME); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_context_new(NULL, &gpContext)); BAIL_ON_REG_ERROR(dwError); lwmsg_context_set_log_function(gpContext, RegSrvLogIpc, NULL); /* Set up IPC protocol object */ dwError = MAP_LWMSG_ERROR(lwmsg_protocol_new(gpContext, &gpProtocol)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_protocol_add_protocol_spec( gpProtocol, RegIPCGetProtocolSpec())); BAIL_ON_REG_ERROR(dwError); /* Set up IPC server object */ dwError = MAP_LWMSG_ERROR(lwmsg_peer_new(gpContext, gpProtocol, &gpServer)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_add_dispatch_spec( gpServer, RegSrvGetDispatchSpec())); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_add_listen_endpoint( gpServer, LWMSG_ENDPOINT_DIRECT, "lwreg", 0)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_add_listen_endpoint( gpServer, LWMSG_ENDPOINT_LOCAL, pszCommPath, 0666)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_set_max_listen_clients( gpServer, MAX_CLIENTS)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_set_max_listen_backlog( gpServer, REG_MAX(5, MAX_CLIENTS / 4))); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_set_timeout( gpServer, LWMSG_TIMEOUT_IDLE, &idleTimeout)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_set_listen_session_functions( gpServer, RegSrvIpcConstructSession, RegSrvIpcDestructSession, NULL)); BAIL_ON_REG_ERROR(dwError); dwError = MAP_LWMSG_ERROR(lwmsg_peer_start_listen(gpServer)); error: LWREG_SAFE_FREE_STRING(pszCachePath); LWREG_SAFE_FREE_STRING(pszCommPath); if (dwError) { if (gpServer) { lwmsg_peer_stop_listen(gpServer); lwmsg_peer_delete(gpServer); gpServer = NULL; } } return dwError; }
NTSTATUS LwioCopyDirToRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; DIR* pDir = NULL; struct dirent* pDirEntry = NULL; struct stat statbuf; IO_FILE_HANDLE handle = NULL; PSTR pszLocalPath = NULL; PSTR pszRemotePath = NULL; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); if ((pDir = opendir(pszSourcePath)) == NULL) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } status = LwioRemoteOpenFile( pszTargetPath, FILE_LIST_DIRECTORY, FILE_SHARE_READ |FILE_SHARE_WRITE |FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE, &handle); BAIL_ON_NT_STATUS(status); while ((pDirEntry = readdir(pDir)) != NULL) { RTL_FREE(&pszRemotePath); RTL_FREE(&pszLocalPath); if (!strcmp(pDirEntry->d_name, "..") || !strcmp(pDirEntry->d_name, ".")) continue; status = LwRtlCStringAllocatePrintf( &pszLocalPath, "%s/%s", pszSourcePath, pDirEntry->d_name); BAIL_ON_NT_STATUS(status); memset(&statbuf, 0, sizeof(struct stat)); if (stat(pszLocalPath, &statbuf) < 0) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } status = LwRtlCStringAllocatePrintf( &pszRemotePath, "%s/%s", pszTargetPath, pDirEntry->d_name); BAIL_ON_NT_STATUS(status); if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { status = LwioCopyDirToRemote( pszLocalPath, pszRemotePath); BAIL_ON_NT_STATUS(status); } else { status = LwioCopyFileToRemote( pszLocalPath, pszRemotePath); BAIL_ON_NT_STATUS(status); } } if(closedir(pDir) < 0) { pDir = NULL; status = LwErrnoToNtStatus(status); BAIL_ON_NT_STATUS(status); } pDir = NULL; cleanup: if (handle) LwNtCloseFile(handle); if (pDir) closedir(pDir); RTL_FREE(&pszLocalPath); RTL_FREE(&pszRemotePath); return status; error: goto cleanup; }
NTSTATUS LwioCopyDirFromLocalToLocal( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; DIR* pDir = NULL; struct dirent* pDirEntry = NULL; struct stat statbuf; PSTR pszLocalPath = NULL; PSTR pszRemotePath = NULL; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); if ((pDir = opendir(pszSourcePath)) == NULL) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } status = LwioLocalCreateDir( pszTargetPath, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); BAIL_ON_NT_STATUS(status); while ((pDirEntry = readdir(pDir)) != NULL) { RTL_FREE(&pszRemotePath); RTL_FREE(&pszLocalPath); if (!strcmp(pDirEntry->d_name, "..") || !strcmp(pDirEntry->d_name, ".")) continue; status = LwRtlCStringAllocatePrintf( &pszLocalPath, "%s/%s", pszSourcePath, pDirEntry->d_name); BAIL_ON_NT_STATUS(status); memset(&statbuf, 0, sizeof(struct stat)); if (stat(pszLocalPath, &statbuf) < 0) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } status = LwRtlCStringAllocatePrintf( &pszRemotePath, "%s/%s", pszTargetPath, pDirEntry->d_name); BAIL_ON_NT_STATUS(status); if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { status = LwioCopyDirFromLocalToLocal( pszLocalPath, pszRemotePath); BAIL_ON_NT_STATUS(status); } else { status = LwioCopyFileFromLocalToLocal( pszLocalPath, pszRemotePath); BAIL_ON_NT_STATUS(status); } } if(closedir(pDir) < 0) { pDir = NULL; status = LwErrnoToNtStatus(status); BAIL_ON_NT_STATUS(status); } pDir = NULL; cleanup: if (pDir) closedir(pDir); RTL_FREE(&pszLocalPath); RTL_FREE(&pszRemotePath); return status; error: goto cleanup; }
NTSTATUS LwioCopyDirFromRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; BOOL bRestart = TRUE; IO_FILE_NAME filename = {0}; IO_FILE_HANDLE handle = NULL; IO_STATUS_BLOCK ioStatus ; PSTR pszEntryFilename = NULL; BYTE buffer[MAX_BUFFER]; PFILE_BOTH_DIR_INFORMATION pInfo = NULL; PSTR pszLocalPath = NULL; PSTR pszRemotePath = NULL; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); status = LwioRemoteOpenFile( pszSourcePath, FILE_LIST_DIRECTORY, /* Desired access mask */ FILE_SHARE_READ, /* Share access */ FILE_OPEN, /* Create disposition */ FILE_DIRECTORY_FILE, /* Create options */ &handle); BAIL_ON_NT_STATUS(status); status = LwioLocalCreateDir( pszTargetPath, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); BAIL_ON_NT_STATUS(status); for (;;) { status = LwNtQueryDirectoryFile( handle, /* File handle */ NULL, /* Async control block */ &ioStatus, /* IO status block */ buffer, /* Info structure */ sizeof(buffer), /* Info structure size */ FileBothDirectoryInformation, /* Info level */ FALSE, /* Do not return single entry */ NULL, /* File spec */ bRestart); /* Restart scan */ switch (status) { case STATUS_NO_MORE_MATCHES: status = STATUS_SUCCESS; goto cleanup; default: BAIL_ON_NT_STATUS(status); } bRestart = FALSE; for (pInfo = (PFILE_BOTH_DIR_INFORMATION) buffer; pInfo; pInfo = (pInfo->NextEntryOffset)?(PFILE_BOTH_DIR_INFORMATION) (((PBYTE) pInfo) + pInfo->NextEntryOffset):NULL) { RTL_FREE(&pszEntryFilename); RTL_FREE(&pszRemotePath); RTL_FREE(&pszLocalPath); status = LwRtlCStringAllocateFromWC16String( &pszEntryFilename, pInfo->FileName ); BAIL_ON_NT_STATUS(status); if (!strcmp(pszEntryFilename, "..") || !strcmp(pszEntryFilename, ".")) continue; status = LwRtlCStringAllocatePrintf( &pszRemotePath, "%s/%s", pszSourcePath, pszEntryFilename); BAIL_ON_NT_STATUS(status); status = LwRtlCStringAllocatePrintf( &pszLocalPath, "%s/%s", pszTargetPath, pszEntryFilename); BAIL_ON_NT_STATUS(status); if(pInfo->FileAttributes == FILE_ATTRIBUTE_DIRECTORY) { status = LwioCopyDirFromRemote( pszRemotePath, pszLocalPath); BAIL_ON_NT_STATUS(status); } else { status = LwioCopyFileFromRemote( pszRemotePath, pszLocalPath); BAIL_ON_NT_STATUS(status); } } } cleanup: if (handle) { LwNtCloseFile(handle); } RTL_FREE(&pszLocalPath); RTL_FREE(&pszRemotePath); RTL_FREE(&pszEntryFilename); RTL_FREE(&filename.FileName); return status; error: goto cleanup; }