NTSTATUS LwioLocalChangePermissions( IN PCSTR pszPath, IN mode_t dwFileMode ) { NTSTATUS status = STATUS_SUCCESS; BAIL_ON_NULL_POINTER(pszPath); while (1) { if (chmod(pszPath, dwFileMode) < 0) { if (errno == EINTR) { continue; } status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } else { break; } } error: return status; }
NTSTATUS LwioLocalOpenFile( IN PCSTR pszFileName, IN INT dwMode, IN INT dwPerms, OUT INT *dwHandle ) { NTSTATUS status = STATUS_SUCCESS; int fd = -1; BAIL_ON_NULL_POINTER(pszFileName); if ((fd = open(pszFileName, dwMode, dwPerms)) == -1) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } error: *dwHandle = fd; return status; }
NTSTATUS LwioLocalRemoveFile( IN PCSTR pszPath ) { NTSTATUS status = STATUS_SUCCESS; BAIL_ON_NULL_POINTER(pszPath); while (1) { if (unlink(pszPath) < 0) { if (errno == EINTR) { continue; } status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } else { break; } } error: return status; }
NTSTATUS LwioLocalCreateDir( IN PCSTR pszPath, IN mode_t dwFileMode ) { NTSTATUS status = STATUS_SUCCESS; PSTR pszTmpPath = NULL; BAIL_ON_NULL_POINTER(pszPath); status = SMBAllocateString( pszPath, &pszTmpPath); BAIL_ON_NT_STATUS(status); status = LwioLocalCreateDirInternal( pszTmpPath, NULL, dwFileMode); BAIL_ON_NT_STATUS(status); cleanup: LWIO_SAFE_FREE_STRING(pszTmpPath); return status; error: goto cleanup; }
NTSTATUS CopyFile_LocalToLocal( PCSTR pszSrcPath, PCSTR pszDestPath, BOOLEAN bCopyRecursive ) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN bExists = FALSE; BAIL_ON_NULL_POINTER(pszSrcPath); BAIL_ON_NULL_POINTER(pszDestPath); status = LwioCheckLocalDirectoryExists(pszSrcPath, &bExists); BAIL_ON_NT_STATUS(status); if (bExists) { status = LwioCopyDirFromLocalToLocal(pszSrcPath, pszDestPath); BAIL_ON_NT_STATUS(status); goto done; } status = LwioCheckLocalFileExists(pszSrcPath, &bExists); BAIL_ON_NT_STATUS(status); if (bExists) { status = LwioCopyFileFromLocalToLocal(pszSrcPath, pszDestPath); BAIL_ON_NT_STATUS(status); } else { status = STATUS_NO_SUCH_FILE; BAIL_ON_NT_STATUS(status); } done: cleanup: return status; error: goto cleanup; }
NTSTATUS LwioCheckLocalFileExists( IN PCSTR pszPath, OUT PBOOLEAN pbFileExists ) { NTSTATUS status = STATUS_SUCCESS; struct stat statbuf; BAIL_ON_NULL_POINTER(pszPath); memset(&statbuf, 0, sizeof(struct stat)); while (1) { if (stat(pszPath, &statbuf) < 0) { if (errno == EINTR) { continue; } else if (errno == ENOENT || errno == ENOTDIR) { *pbFileExists = FALSE; break; } status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } else { *pbFileExists = (((statbuf.st_mode & S_IFMT) == S_IFREG) ? TRUE : FALSE); break; } } cleanup: return status; error: *pbFileExists = FALSE; goto cleanup; }
NTSTATUS LwioLocalCheckDirExists( IN PCSTR pszPath, IN PBOOLEAN pbDirExists ) { NTSTATUS status = STATUS_SUCCESS; struct stat statbuf; BAIL_ON_NULL_POINTER(pszPath); while (1) { memset(&statbuf, 0, sizeof(struct stat)); if (stat(pszPath, &statbuf) < 0) { if (errno == EINTR) { continue; } else if (errno == ENOENT || errno == ENOTDIR) { *pbDirExists = FALSE; break; } status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } *pbDirExists = (((statbuf.st_mode & S_IFMT) == S_IFDIR) ? TRUE : FALSE); break; } error: return status; }
NTSTATUS LwioRemoteWriteFile( IN HANDLE hFile, IN PVOID pBuffer, IN DWORD dwNumBytesToWrite, OUT PDWORD pdwNumBytesWritten ) { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK ioStatus ; BAIL_ON_NULL_POINTER(pBuffer); status = LwNtWriteFile( hFile, // File handle NULL, // Async control block &ioStatus, // IO status block pBuffer, // Buffer (ULONG) dwNumBytesToWrite, // Buffer size NULL, // File offset NULL); // Key BAIL_ON_NT_STATUS(status); *pdwNumBytesWritten = (int) ioStatus.BytesTransferred; cleanup: return status; error: *pdwNumBytesWritten = 0; 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 LwioCopyFileFromRemoteToRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; IO_FILE_HANDLE hRemSrcFile = NULL; IO_FILE_HANDLE hRemDstFile = NULL; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); status = LwioRemoteOpenFile( pszSourcePath, FILE_READ_DATA, /* Desired access mask */ FILE_SHARE_READ, /* Share access */ FILE_OPEN, /* Create disposition */ FILE_NON_DIRECTORY_FILE, /* Create options */ &hRemSrcFile); BAIL_ON_NT_STATUS(status); status = LwioRemoteOpenFile( pszTargetPath, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, &hRemDstFile); BAIL_ON_NT_STATUS(status); do { BYTE szBuff[BUFF_SIZE]; DWORD dwRead = 0; DWORD dwWrote = 0; status = LwioRemoteReadFile( hRemSrcFile, szBuff, sizeof(szBuff), &dwRead); BAIL_ON_NT_STATUS(status); if (!dwRead) { break; } status = LwioRemoteWriteFile( hRemDstFile, szBuff, dwRead, &dwWrote); BAIL_ON_NT_STATUS(status); } while(1); cleanup: if (hRemSrcFile) { LwNtCloseFile(hRemSrcFile); } if (hRemDstFile) { LwNtCloseFile(hRemDstFile); } return (status); error: goto cleanup; }
NTSTATUS LwioLocalRemoveDir( IN PCSTR pszPath ) { NTSTATUS status = STATUS_SUCCESS; DIR* pDir = NULL; struct dirent* pDirEntry = NULL; struct stat statbuf; CHAR szBuf[BUFF_SIZE+1]; BAIL_ON_NULL_POINTER(pszPath); if ((pDir = opendir(pszPath)) == NULL) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } while ((pDirEntry = readdir(pDir)) != NULL) { if (!strcmp(pDirEntry->d_name, "..") || !strcmp(pDirEntry->d_name, ".")) continue; sprintf(szBuf, "%s/%s", pszPath, pDirEntry->d_name); memset(&statbuf, 0, sizeof(struct stat)); if (stat(szBuf, &statbuf) < 0) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { status = LwioLocalRemoveDir(szBuf); BAIL_ON_NT_STATUS(status); if (rmdir(szBuf) < 0) { status = LwErrnoToNtStatus(status); BAIL_ON_NT_STATUS(status); } } else { status = LwioLocalRemoveFile(szBuf); BAIL_ON_NT_STATUS(status); } } if(closedir(pDir) < 0) { pDir = NULL; status = LwErrnoToNtStatus(status); BAIL_ON_NT_STATUS(status); } pDir = NULL; if (rmdir(pszPath) < 0) { status = LwErrnoToNtStatus(status); BAIL_ON_NT_STATUS(status); } error: if (pDir) closedir(pDir); return status; }
NTSTATUS LwioLocalCreateDirInternal( IN PSTR pszPath, IN PSTR pszLastSlash, IN mode_t dwFileMode ) { NTSTATUS status = STATUS_SUCCESS; PSTR pszSlash = NULL; BOOLEAN bDirExists = FALSE; BOOLEAN bDirCreated = FALSE; BAIL_ON_NULL_POINTER(pszPath); pszSlash = pszLastSlash ? strchr(pszLastSlash + 1, '/') : strchr(pszPath, '/'); if (pszSlash) { *pszSlash = '\0'; } if (pszPath[0]) { status = LwioLocalCheckDirExists(pszPath, &bDirExists); BAIL_ON_NT_STATUS(status); if (!bDirExists) { if (mkdir(pszPath, S_IRWXU) != 0) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } bDirCreated = TRUE; } } if (pszSlash) { *pszSlash = '/'; } if (pszSlash) { status = LwioLocalCreateDirInternal(pszPath, pszSlash, dwFileMode); BAIL_ON_NT_STATUS(status); } if (pszSlash) { *pszSlash = '\0'; } if (bDirCreated) { status = LwioLocalChangePermissions(pszPath, dwFileMode); BAIL_ON_NT_STATUS(status); } if (pszSlash) { *pszSlash = '/'; } cleanup: return status; error: if (pszSlash) { *pszSlash = '\0'; } if (bDirCreated) { LwioLocalRemoveDir(pszPath); } if (pszSlash) { *pszSlash = '/'; } goto cleanup; }
NTSTATUS LwioCopyFileFromRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; IO_FILE_HANDLE hRemoteFile = NULL; int hLocalFile = -1; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); status = LwioRemoteOpenFile( pszSourcePath, FILE_READ_DATA, /* Desired access mask */ FILE_SHARE_READ, /* Share access */ FILE_OPEN, /* Create disposition */ FILE_NON_DIRECTORY_FILE, /* Create options */ &hRemoteFile); BAIL_ON_NT_STATUS(status); status = LwioLocalOpenFile( (PCSTR)pszTargetPath, O_WRONLY|O_TRUNC|O_CREAT, 0666, &hLocalFile); BAIL_ON_NT_STATUS(status); do { BYTE szBuff[BUFF_SIZE]; DWORD dwRead = 0; DWORD dwWrote = 0; status = LwioRemoteReadFile( hRemoteFile, szBuff, sizeof(szBuff), &dwRead); BAIL_ON_NT_STATUS(status); if (!dwRead) { break; } if ((dwWrote = write(hLocalFile, szBuff, dwRead)) == -1) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } } while(1); cleanup: if (hRemoteFile) { LwNtCloseFile(hRemoteFile); } if (hLocalFile >= 0) { close(hLocalFile); } return (status); error: goto cleanup; }
NTSTATUS LwioCopyFileFromLocalToLocal( PCSTR pszSrcPath, PCSTR pszDestPath ) { NTSTATUS status = STATUS_SUCCESS; CHAR szBuf[BUFF_SIZE]; int hSrcFile = -1; int hDestFile = -1; DWORD dwBytesRead = 0; uid_t uid; gid_t gid; mode_t mode; BAIL_ON_NULL_POINTER(pszSrcPath); BAIL_ON_NULL_POINTER(pszDestPath); status = LwioLocalOpenFile( (PCSTR)pszSrcPath, O_RDONLY, 0, &hSrcFile); BAIL_ON_NT_STATUS(status); //Get UID GID and mode status = LwioGetLocalFileOwnerAndPerms( pszSrcPath, &uid, &gid, &mode); BAIL_ON_NT_STATUS(status); status = LwioLocalOpenFile( (PCSTR)pszDestPath, O_WRONLY|O_TRUNC|O_CREAT, 0666, &hDestFile); BAIL_ON_NT_STATUS(status); do { DWORD dwWrote = 0; memset (szBuf,0,BUFF_SIZE); if ((dwBytesRead = read(hSrcFile, szBuf, sizeof(szBuf))) == -1) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } if (dwBytesRead == 0) { break; } if ((dwWrote = write(hDestFile, szBuf, dwBytesRead)) == -1) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } } while(1); status = LwioChangeLocalFileOwnerAndPerms( pszDestPath, uid, gid, mode); BAIL_ON_NT_STATUS(status); cleanup: if (hSrcFile >= 0) { close(hSrcFile); } if (hDestFile >= 0) { close(hDestFile); } 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; }
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 LwioCopyFileToRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; IO_FILE_HANDLE hRemoteFile = NULL; int hLocalFile = -1; DWORD dwBytesRead = 0; CHAR szBuf[BUFF_SIZE]; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); status = LwioLocalOpenFile( (PCSTR)pszSourcePath, O_RDONLY, 0, &hLocalFile); BAIL_ON_NT_STATUS(status); status = LwioRemoteOpenFile( pszTargetPath, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, &hRemoteFile); BAIL_ON_NT_STATUS(status); do { DWORD dwWritten = 0; memset (szBuf,0,BUFF_SIZE); if ((dwBytesRead = read(hLocalFile, szBuf, sizeof(szBuf))) == -1) { status = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(status); } if (dwBytesRead == 0) { break; } status = LwioRemoteWriteFile( hRemoteFile, szBuf, dwBytesRead, &dwWritten); BAIL_ON_NT_STATUS(status); } while (dwBytesRead != 0); cleanup: if (hRemoteFile) { LwNtCloseFile(hRemoteFile); } if (hLocalFile >= 0) { close(hLocalFile); } return (status); error: goto cleanup; }