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; }
__cdecl _fullpath( char *absPath, const char *relPath, size_t maxLength) { char realpath_buf[MAXPATHLEN]; char path_copy[MAXPATHLEN]; char *retval = NULL; PERF_ENTRY(_fullpath); ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %d)\n", absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); strcpy(path_copy, relPath ? relPath : "."); FILEDosToUnixPathA(path_copy); if(NULL == realpath(path_copy, realpath_buf)) { TRACE("realpath() failed; problem path is '%s'. errno is %d (%s)\n", realpath_buf, errno, strerror(errno)); } else { int min_length; TRACE("real path is %s\n", realpath_buf); min_length = strlen(realpath_buf)+1; if(NULL == absPath) { ASSERT("Invalid absPath parameter value (NULL)\n"); } else { if(min_length > maxLength) { TRACE("maxLength is %d, we need at least %d\n", maxLength, min_length); } else { strcpy(absPath, realpath_buf); retval = absPath; } } } LOGEXIT("_fullpath returns char * %p\n", retval); PERF_EXIT(_fullpath); return retval; }
/*++ Function: _makepath See MSDN doc. --*/ void __cdecl _makepath( char *path, const char *drive, const char *dir, const char *fname, const char *ext) { UINT Length = 0; PERF_ENTRY(_makepath); ENTRY( "_makepath (path=%p, drive=%p (%s), dir=%p (%s), fname=%p (%s), ext=%p (%s))\n", path, drive ? drive:"NULL", drive ? drive:"NULL", dir ? dir:"NULL", dir ? dir:"NULL", fname ? fname:"NULL", fname ? fname:"NULL", ext ? ext:"NULL", ext ? ext:"NULL"); path[ 0 ] = '\0'; /* According to the rotor_pal documentation, host operating systems that don't support drive letters, the "drive" parameter must always be null. */ if ( drive != NULL && drive[0] != '\0' ) { ASSERT( "The drive parameter must always be NULL on systems that don't" "support drive letters. drive is being ignored!.\n" ); } if ( dir != NULL && dir[ 0 ] != '\0' ) { UINT DirLength = strlen( dir ); Length += DirLength ; if ( Length < _MAX_PATH ) { strncat( path, dir, DirLength ); if ( dir[ DirLength - 1 ] != '/' && dir[ DirLength - 1 ] != '\\' ) { if ( Length + 1 < _MAX_PATH ) { path[ Length ] = '/'; Length++; path[ Length ] = '\0'; } else { goto Max_Path_Error; } } } else { goto Max_Path_Error; } } if ( fname != NULL && fname[ 0 ] != '\0' ) { UINT fNameLength = strlen( fname ); Length += fNameLength; if ( Length < _MAX_PATH ) { strncat( path, fname, fNameLength ); } else { goto Max_Path_Error; } } if ( ext != NULL && ext[ 0 ] != '\0' ) { UINT ExtLength = strlen( ext ); Length += ExtLength; if ( ext[ 0 ] != '.' ) { /* Add a '.' */ if ( Length + 1 < _MAX_PATH ) { path[ Length - ExtLength ] = '.'; Length++; path[ Length - ExtLength ] = '\0'; strncat( path, ext, ExtLength ); } else { goto Max_Path_Error; } } else { /* Already has a '.' */ if ( Length < _MAX_PATH ) { strncat( path, ext, ExtLength ); } else { goto Max_Path_Error; } } } FILEDosToUnixPathA( path ); LOGEXIT( "_makepath returning void.\n" ); PERF_EXIT(_makepath); return; Max_Path_Error: ERROR( "path cannot be greater then _MAX_PATH\n" ); path[ 0 ] = '\0'; LOGEXIT( "_makepath returning void \n" ); PERF_EXIT(_makepath); return; }
/*++ 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: 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; }
__cdecl PAL_fopen(const char * fileName, const char * mode) { PAL_FILE *f = NULL; LPSTR supported = NULL; LPSTR UnixFileName = NULL; struct stat stat_data; BOOL bTextMode = TRUE; PERF_ENTRY(fopen); ENTRY("fopen ( fileName=%p (%s) mode=%p (%s))\n", fileName, fileName, mode , mode ); _ASSERTE(fileName != NULL); _ASSERTE(mode != NULL); if ( *mode == 'r' || *mode == 'w' || *mode == 'a' ) { supported = MapFileOpenModes( (char*)mode,&bTextMode); if ( !supported ) { goto done; } UnixFileName = PAL__strdup(fileName); if (UnixFileName == NULL ) { ERROR("PAL__strdup() failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; } FILEDosToUnixPathA( UnixFileName ); /*I am not checking for the case where stat fails *as fopen will handle the error more gracefully in case *UnixFileName is invalid*/ if ((stat(UnixFileName, &stat_data) == 0 ) && ((stat_data.st_mode & S_IFMT) == S_IFDIR)) { goto done; } f = (PAL_FILE*)PAL_malloc( sizeof( PAL_FILE ) ); if ( f ) { f->bsdFilePtr = (FILE*)fopen( UnixFileName, supported ); f->PALferrorCode = PAL_FILE_NOERROR; f->bTextMode = bTextMode; if ( !f->bsdFilePtr ) { /* Failed */ PAL_free( f ); f = NULL; } #if UNGETC_NOT_RETURN_EOF else { f->bWriteOnlyMode = WriteOnlyMode(f->bsdFilePtr); } #endif //UNGETC_NOT_RETURN_EOF } else { ERROR( "Unable to allocate memory to the PAL_FILE wrapper\n" ); } } else { ERROR( "The mode flags must start with either an a, w, or r.\n" ); } done: PAL_free( supported ); supported = NULL; PAL_free( UnixFileName ); LOGEXIT( "fopen returns FILE* %p\n", f ); PERF_EXIT(fopen); return f; }
__cdecl _fullpath( char *absPath, const char *relPath, size_t maxLength) { char realpath_buf[PATH_MAX+1]; char path_copy[PATH_MAX+1]; char *retval = NULL; DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]); size_t min_length; BOOL fBufAllocated = FALSE; PERF_ENTRY(_fullpath); ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n", absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength); if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS) { TRACE("_fullpath: strncpy_s failed!\n"); goto fullpathExit; } FILEDosToUnixPathA(path_copy); if(NULL == realpath(path_copy, realpath_buf)) { ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n", realpath_buf, errno, strerror(errno)); goto fullpathExit; } TRACE("real path is %s\n", realpath_buf); min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator if(NULL == absPath) { absPath = static_cast<char *>( PAL_malloc(_MAX_PATH * sizeof(char))); if (!absPath) { ERROR("PAL_malloc failed with error %d\n", errno); goto fullpathExit; } maxLength = _MAX_PATH; fBufAllocated = TRUE; } if(min_length > maxLength) { ERROR("maxLength is %lu, we need at least %lu\n", maxLength, min_length); if (fBufAllocated) { PAL_free(absPath); fBufAllocated = FALSE; } goto fullpathExit; } strcpy_s(absPath, maxLength, realpath_buf); retval = absPath; fullpathExit: LOGEXIT("_fullpath returns char * %p\n", retval); PERF_EXIT(_fullpath); return retval; }