void TestCase(LPSTR input, LPSTR expectedOutput) { // Save the input for debug logging since the input is edited in-place char* pOriginalInput = (char*)malloc(strlen(input) * sizeof(char) + 1); strcpy(pOriginalInput, input); char* pInput = (char*)malloc(strlen(input) * sizeof(char) + 1); strcpy(pInput, pOriginalInput); FILECanonicalizePath(pInput); if (strcmp(pInput, expectedOutput) != 0) { free(pOriginalInput); free(pInput); Fail("FILECanonicalizePath error: input %s did not match expected output %s; got %s instead", pOriginalInput, expectedOutput, pInput); } free(pOriginalInput); free(pInput); }
/*++ 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: GetFullPathNameA See MSDN doc. --*/ DWORD PALAPI GetFullPathNameA( IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart) { DWORD nReqPathLen, nRet = 0; LPSTR lpUnixPath = NULL; BOOL fullPath = FALSE; PERF_ENTRY(GetFullPathNameA); ENTRY("GetFullPathNameA(lpFileName=%p (%s), nBufferLength=%u, lpBuffer=%p, " "lpFilePart=%p)\n", lpFileName?lpFileName:"NULL", lpFileName?lpFileName:"NULL", nBufferLength, lpBuffer, lpFilePart); if(NULL == lpFileName) { WARN("lpFileName is NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); goto done; } /* find out if lpFileName is a partial or full path */ if ('\\' == *lpFileName || '/' == *lpFileName) { fullPath = TRUE; } if(fullPath) { lpUnixPath = strdup( lpFileName ); if(NULL == lpUnixPath) { ERROR("strdup() failed; error is %d (%s)\n", errno, strerror(errno)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } } else { size_t max_len; /* allocate memory for full non-canonical path */ max_len = strlen(lpFileName)+1; /* 1 for the slash to append */ max_len += MAX_PATH + 1; lpUnixPath = malloc(max_len); if(NULL == lpUnixPath) { ERROR("malloc() failed; error is %d (%s)\n", errno, strerror(errno)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } /* build full path */ if(!GetCurrentDirectoryA(MAX_PATH + 1, lpUnixPath)) { /* no reason for this to fail now... */ ASSERT("GetCurrentDirectoryA() failed! lasterror is %#xd\n", GetLastError()); SetLastError(ERROR_INTERNAL_ERROR); goto done; } strcat(lpUnixPath,"/"); strcat(lpUnixPath, lpFileName); } /* do conversion to Unix path */ FILEDosToUnixPathA( lpUnixPath ); /* now we can canonicalize this */ FILECanonicalizePath(lpUnixPath); /* at last, we can figure out how long this path is */ nReqPathLen = strlen(lpUnixPath)+1; if(nBufferLength < nReqPathLen) { TRACE("reporting insufficient buffer : minimum is %d, caller " "provided %d\n", nReqPathLen, nBufferLength); nRet = nReqPathLen; goto done; } nRet = nReqPathLen-1; strcpy(lpBuffer, lpUnixPath); /* locate the filename component if caller cares */ if(lpFilePart) { *lpFilePart = strrchr(lpBuffer, '/'); if (*lpFilePart == NULL) { ASSERT("Not able to find '/' in the full path.\n"); SetLastError( ERROR_INTERNAL_ERROR ); nRet = 0; goto done; } else { (*lpFilePart)++; } } done: free (lpUnixPath); LOGEXIT("GetFullPathNameA returns DWORD %u\n", nRet); PERF_EXIT(GetFullPathNameA); return nRet; }
/*++ 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; }