static BOOL RemoveDirectoryHelper ( LPSTR lpPathName, LPDWORD dwLastError ) { BOOL bRet = FALSE; *dwLastError = 0; FILEDosToUnixPathA( lpPathName ); if ( !FILEGetFileNameFromSymLink(lpPathName)) { FILEGetProperNotFoundError( lpPathName, dwLastError ); goto done; } if ( rmdir(lpPathName) != 0 ) { TRACE("Removal of directory [%s] was unsuccessful, errno = %d.\n", lpPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: { struct stat stat_data; if ( stat( lpPathName, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ *dwLastError = ERROR_DIRECTORY; } else { FILEGetProperNotFoundError( lpPathName, dwLastError ); } break; } case ENOTEMPTY: *dwLastError = ERROR_DIR_NOT_EMPTY; break; default: *dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Removal of directory [%s] was successful.\n", lpPathName); bRet = TRUE; } done: return bRet; }
/*++ Function: SetCurrentDirectoryA See MSDN doc. --*/ BOOL PALAPI SetCurrentDirectoryA( IN LPCSTR lpPathName) { BOOL bRet = FALSE; DWORD dwLastError = 0; int result; LPSTR UnixPathName = NULL; ENTRY("SetCurrentDirectoryA(lpPathName=%p (%s))\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL"); /*check if the given path is null. If so return FALSE*/ if (lpPathName == NULL ) { ERROR("Invalid path/directory name\n"); dwLastError = ERROR_INVALID_NAME; goto done; } UnixPathName = strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("malloc() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); TRACE("Attempting to open Unix dir [%s]\n", UnixPathName); result = chdir(UnixPathName); if ( result == 0 ) { bRet = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { struct stat stat_data; if ( stat( UnixPathName, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ dwLastError = ERROR_DIRECTORY; } else { FILEGetProperNotFoundError( UnixPathName, &dwLastError ); } TRACE("chdir() failed, path was invalid.\n"); } else { dwLastError = ERROR_ACCESS_DENIED; ERROR("chdir() failed; errno is %d (%s)\n", errno, strerror(errno)); } } done: if( dwLastError ) { SetLastError(dwLastError); } if(UnixPathName != NULL) { free( UnixPathName ); } LOGEXIT("SetCurrentDirectoryA returns BOOL %d\n", bRet); return bRet; }
/*++ Function: CreateDirectoryA Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; char *realPath; LPSTR UnixPathName = NULL; int pathLength; int i; const int mode = S_IRWXU | S_IRWXG | S_IRWXO; ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } UnixPathName = strdup(lpPathName); if (UnixPathName == NULL ) { ERROR("malloc() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( UnixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(UnixPathName); i = pathLength; while(i > 1) { if(UnixPathName[i - 1] =='/') { UnixPathName[i - 1]='\0'; i--; } else { break; } } // Check the constraint for the real path length (should be < MAX_PATH). // Get an absolute path. if (UnixPathName[0] == '/') { realPath = UnixPathName; } else { const char *cwd = getcwd(NULL, MAX_PATH); // Copy cwd, '/', path realPath = alloca(strlen(cwd) + 1 + pathLength + 1); sprintf(realPath, "%s/%s", cwd, UnixPathName); } // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPath); if (strlen(realPath) >= MAX_PATH) { ERROR("UnixPathName is larger than MAX_PATH (%d)!\n", MAX_PATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; goto done; } if ( mkdir(realPath, mode) != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", UnixPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: FILEGetProperNotFoundError( realPath, &dwLastError ); goto done; case EEXIST: dwLastError = ERROR_ALREADY_EXISTS; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Creation of directory [%s] was successful.\n", UnixPathName); bRet = TRUE; } done: if( dwLastError ) { SetLastError( dwLastError ); } free( UnixPathName ); LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); return bRet; }
/*++ Function: RemoveDirectoryW See MSDN doc. --*/ BOOL PALAPI RemoveDirectoryW( IN LPCWSTR lpPathName) { char mb_dir[MAX_PATH]; int mb_size; DWORD dwLastError = 0; BOOL bRet = FALSE; ENTRY("RemoveDirectoryW(lpPathName=%p (%S))\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING); if (lpPathName == NULL) { dwLastError = ERROR_PATH_NOT_FOUND; goto done; } mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, MAX_PATH, NULL, NULL ); if( mb_size == 0 ) { dwLastError = GetLastError(); if( dwLastError == ERROR_INSUFFICIENT_BUFFER ) { ERROR("lpPathName is larger than MAX_PATH (%d)!\n", MAX_PATH); } else { ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); } dwLastError = ERROR_INVALID_PARAMETER; goto done; } FILEDosToUnixPathA( mb_dir ); if ( !FILEGetFileNameFromSymLink(mb_dir)) { FILEGetProperNotFoundError( mb_dir, &dwLastError ); goto done; } if ( rmdir(mb_dir) != 0 ) { TRACE("Removal of directory [%s] was unsuccessful, errno = %d.\n", mb_dir, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: { struct stat stat_data; if ( stat( mb_dir, &stat_data) == 0 && (stat_data.st_mode & S_IFMT) == S_IFREG ) { /* Not a directory, it is a file. */ dwLastError = ERROR_DIRECTORY; } else { FILEGetProperNotFoundError( mb_dir, &dwLastError ); } break; } case ENOTEMPTY: dwLastError = ERROR_DIR_IS_NOT_EMPTY; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Removal of directory [%s] was successful.\n", mb_dir); bRet = TRUE; } done: if( dwLastError ) { SetLastError( dwLastError ); } LOGEXIT("RemoveDirectoryW returns BOOL %d\n", bRet); return bRet; }
/*++ Function: GetDiskFreeSpaceW See MSDN doc. --*/ PALIMPORT BOOL PALAPI GetDiskFreeSpaceW( LPCWSTR lpDirectoryName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, /* Caller will ignore output value */ LPDWORD lpTotalNumberOfClusters) /* Caller will ignore output value */ { BOOL bRetVal = FALSE; pal_statfs fsInfoBuffer; INT statfsRetVal = 0; DWORD dwLastError = NO_ERROR; CHAR DirNameBuffer[ MAX_LONGPATH ]; PERF_ENTRY(GetDiskFreeSpaceW); ENTRY( "GetDiskFreeSpaceW( lpDirectoryName=%p (%S), lpSectorsPerCluster=%p," "lpBytesPerSector=%p, lpNumberOfFreeClusters=%p, " "lpTotalNumberOfClusters=%p )\n", lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters ); /* Sanity checks. */ if ( !lpSectorsPerCluster ) { ERROR( "lpSectorsPerCluster cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( !lpBytesPerSector ) { ERROR( "lpBytesPerSector cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( lpNumberOfFreeClusters || lpTotalNumberOfClusters ) { TRACE("GetDiskFreeSpaceW is ignoring lpNumberOfFreeClusters" " and lpTotalNumberOfClusters\n" ); } if ( lpDirectoryName && PAL_wcslen( lpDirectoryName ) == 0 ) { ERROR( "lpDirectoryName is empty.\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } /* Fusion uses this API to round file sizes up to their actual size on-disk based on the BytesPerSector * SectorsPerCluster. The intent is to avoid computing the sum of all file sizes in the cache just in bytes and not account for the cluster-sized slop, when determining if the cache is too large or not. */ if ( lpDirectoryName ) { if ( WideCharToMultiByte( CP_ACP, 0, lpDirectoryName, -1, DirNameBuffer,MAX_LONGPATH, 0, 0 ) != 0 ) { FILEDosToUnixPathA( DirNameBuffer ); statfsRetVal = statfs( DirNameBuffer, &fsInfoBuffer ); } else { ASSERT( "Unable to convert the lpDirectoryName to multibyte.\n" ); dwLastError = ERROR_INTERNAL_ERROR; goto exit; } } else { statfsRetVal = statfs( "/", &fsInfoBuffer ); } if ( statfsRetVal == 0 ) { *lpBytesPerSector = fsInfoBuffer.f_bsize; *lpSectorsPerCluster = 1; bRetVal = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { FILEGetProperNotFoundError( DirNameBuffer, &dwLastError ); goto exit; } dwLastError = FILEGetLastErrorFromErrno(); if ( ERROR_INTERNAL_ERROR == dwLastError ) { ASSERT("statfs() not expected to fail with errno:%d (%s)\n", errno, strerror(errno)); } else { TRACE("statfs() failed, errno:%d (%s)\n", errno, strerror(errno)); } } exit: if ( NO_ERROR != dwLastError ) { SetLastError( dwLastError ); } LOGEXIT( "GetDiskFreeSpace returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); PERF_EXIT(GetDiskFreeSpaceW); return bRetVal; }
/*++ Function: CreateDirectoryA Note: lpSecurityAttributes always NULL. See MSDN doc. --*/ BOOL PALAPI CreateDirectoryA( IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes) { BOOL bRet = FALSE; DWORD dwLastError = 0; PathCharString realPath; char* realPathBuf; LPSTR unixPathName = NULL; int pathLength; int i; const int mode = S_IRWXU | S_IRWXG | S_IRWXO; PERF_ENTRY(CreateDirectoryA); ENTRY("CreateDirectoryA(lpPathName=%p (%s), lpSecurityAttr=%p)\n", lpPathName?lpPathName:"NULL", lpPathName?lpPathName:"NULL", lpSecurityAttributes); if ( lpSecurityAttributes ) { ASSERT("lpSecurityAttributes is not NULL as it should be\n"); dwLastError = ERROR_INVALID_PARAMETER; goto done; } // Windows returns ERROR_PATH_NOT_FOUND when called with NULL. // If we don't have this check, strdup(NULL) segfaults. if (lpPathName == NULL) { ERROR("CreateDirectoryA called with NULL pathname!\n"); dwLastError = ERROR_PATH_NOT_FOUND; goto done; } unixPathName = PAL__strdup(lpPathName); if (unixPathName == NULL ) { ERROR("PAL__strdup() failed\n"); dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } FILEDosToUnixPathA( unixPathName ); // Remove any trailing slashes at the end because mkdir might not // handle them appropriately on all platforms. pathLength = strlen(unixPathName); i = pathLength; while(i > 1) { if(unixPathName[i - 1] =='/') { unixPathName[i - 1]='\0'; i--; } else { break; } } // Get an absolute path. if (unixPathName[0] == '/') { realPathBuf = unixPathName; } else { DWORD len = GetCurrentDirectoryA(realPath); if (len == 0 || !realPath.Reserve(realPath.GetCount() + pathLength + 1 )) { dwLastError = DIRGetLastErrorFromErrno(); WARN("Getcwd failed with errno=%d \n", dwLastError); goto done; } realPath.Append("/", 1); realPath.Append(unixPathName, pathLength); realPathBuf = realPath.OpenStringBuffer(realPath.GetCount()); } // Canonicalize the path so we can determine its length. FILECanonicalizePath(realPathBuf); if ( mkdir(realPathBuf, mode) != 0 ) { TRACE("Creation of directory [%s] was unsuccessful, errno = %d.\n", unixPathName, errno); switch( errno ) { case ENOTDIR: /* FALL THROUGH */ case ENOENT: FILEGetProperNotFoundError( realPathBuf, &dwLastError ); goto done; case EEXIST: dwLastError = ERROR_ALREADY_EXISTS; break; default: dwLastError = ERROR_ACCESS_DENIED; } } else { TRACE("Creation of directory [%s] was successful.\n", unixPathName); bRet = TRUE; } realPath.CloseBuffer(0); //The PathCharString usage is done done: if( dwLastError ) { SetLastError( dwLastError ); } PAL_free( unixPathName ); LOGEXIT("CreateDirectoryA returns BOOL %d\n", bRet); PERF_EXIT(CreateDirectoryA); return bRet; }