/** * @brief Get status information on a file */ int __win_stat(const char *path, struct stat *buffer, int iDeref) { char szFile[_MAX_PATH + 1]; long lRet; if ((lRet = plibc_conv_to_win_path(path, szFile)) != ERROR_SUCCESS) { SetErrnoFromWinError(lRet); return -1; } /* Remove trailing slash */ lRet = strlen(szFile) - 1; if (szFile[lRet] == '\\') { szFile[lRet] = 0; } /* Dereference symlinks */ if (iDeref) { if (__win_deref(szFile) == -1 && errno != EINVAL) return -1; } /* stat sets errno */ return stat(szFile, buffer); }
/** * @brief Get status information on a file */ int __win_stat64(const char *path, struct stat64 *buffer, int iDeref) { char szFile[_MAX_PATH + 1]; long lRet; if ((lRet = plibc_conv_to_win_path(path, szFile)) != ERROR_SUCCESS) { SetErrnoFromWinError(lRet); return -1; } /* Remove trailing slash */ lRet = strlen(szFile) - 1; if (szFile[lRet] == '\\') { szFile[lRet] = 0; } /* Dereference symlinks */ if (iDeref) { if (__win_deref(szFile) == -1 && errno != EINVAL) return -1; } if (!_plibc_stat64) { /* not supported under Windows 9x */ struct stat theStat; int iRet; iRet = __win_stat(path, &theStat, iDeref); buffer->st_dev = theStat.st_dev; buffer->st_ino = theStat.st_ino; buffer->st_mode = theStat.st_mode; buffer->st_nlink = theStat.st_nlink; buffer->st_uid = theStat.st_uid; buffer->st_gid = theStat.st_gid; buffer->st_rdev = theStat.st_rdev; buffer->st_size = (theStat.st_size > LONG_MAX) ? LONG_MAX : theStat.st_size; buffer->st_atime = (theStat.st_atime > LONG_MAX) ? LONG_MAX : theStat.st_atime; buffer->st_mtime = (theStat.st_mtime > LONG_MAX) ? LONG_MAX : theStat.st_mtime; buffer->st_ctime = (theStat.st_ctime > LONG_MAX) ? LONG_MAX : theStat.st_ctime; return iRet; } else /* stat sets errno */ return _plibc_stat64(szFile, buffer); }
/** * @brief Convert a POSIX-sytle path to a Windows-style path * @param pszUnix POSIX path * @param pszWindows Windows path * @param derefLinks 1 to dereference links * @return Error code from winerror.h, ERROR_SUCCESS on success */ int plibc_conv_to_win_path_ex(const char *pszUnix, char *pszWindows, int derefLinks) { char *pSrc, *pDest; long iSpaceUsed; int iUnixLen; if (!pszUnix || !pszWindows) return ERROR_INVALID_PARAMETER; iUnixLen = strlen(pszUnix); /* Check if we already have a windows path */ if((strchr(pszUnix, '\\') != NULL) || (strchr(pszUnix, ':') != NULL)) { if(iUnixLen > MAX_PATH) return ERROR_BUFFER_OVERFLOW; strcpy(pszWindows, pszUnix); } /* Temp. dir? */ if(strncmp(pszUnix, "/tmp", 4) == 0) { iSpaceUsed = GetTempPath(_MAX_PATH, pszWindows); if (iSpaceUsed > _MAX_PATH) return ERROR_BUFFER_OVERFLOW; pDest = pszWindows + iSpaceUsed; pSrc = (char *) pszUnix + 4; } /* Bit bucket? */ else if (strncmp(pszUnix, "/dev/null", 9) == 0) { strcpy(pszWindows, "nul"); iSpaceUsed = 3; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 9; } /* Data directories */ else if (strncmp(pszUnix, "/etc", 4) == 0 || strncmp(pszUnix, "/com", 4) == 0 || strncmp(pszUnix, "/var", 4) == 0) { strcpy(pszWindows, szDataDir); iSpaceUsed = lDataDirLen; pDest = pszWindows + lDataDirLen; pSrc = (char *) pszUnix + 1; } /* Is the unix path a full path? */ else if(pszUnix[0] == '/') { strcpy(pszWindows, szRootDir); iSpaceUsed = lRootDirLen; pDest = pszWindows + lRootDirLen; pSrc = (char *) pszUnix + 1; } /* Home dir? */ else if (pszUnix[0] == '~') { strcpy(pszWindows, szHomeDir); iSpaceUsed = lHomeDirLen; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 1; } /* Home dir (env var)? */ else if (strncmp(pszUnix, "$HOME", 5) == 0) { strcpy(pszWindows, szHomeDir); iSpaceUsed = lHomeDirLen; pDest = pszWindows + lHomeDirLen; pSrc = (char *) pszUnix + 5; } else { pDest = pszWindows; iSpaceUsed = 0; pSrc = (char *) pszUnix; } iSpaceUsed += strlen(pSrc); if(iSpaceUsed + 1 > _MAX_PATH) return ERROR_BUFFER_OVERFLOW; /* substitute all slashes */ while(*pSrc) { if(*pSrc == '/') *pDest = '\\'; else *pDest = *pSrc; pDest++; pSrc++; } *pDest = 0; if (derefLinks) __win_deref(pszWindows); else { /* The filename possibly refers to a symlink, but the .lnk extension may be missing. 1. Check if the requested file seems to be a normal file 2. Check if the file exists 2.1. Yes: Finished 2.2. No: Check if "filename.lnk" exists 2.2.1 Yes: Append ".lnk" */ if (strnicmp(pDest - 4, ".lnk", 4) != 0) { HANDLE h = CreateFile(pszWindows, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { /* File doesn't exist, try shortcut */ char *pLnk; int mal; if (iSpaceUsed + 5 > _MAX_PATH) { pLnk = malloc(iSpaceUsed + 5); strcpy(pLnk, pszWindows); mal = 1; } else { pLnk = pszWindows; mal = 0; } strcat(pLnk, ".lnk"); h = CreateFile(pLnk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { /* Shortcut exists */ CloseHandle(h); if (mal) /* Need to copy */ if (iSpaceUsed + 5 <= _MAX_PATH) strcpy(pszWindows, pLnk); else { free(pLnk); return ERROR_BUFFER_OVERFLOW; } } else pLnk[iSpaceUsed] = 0; if (mal) free(pLnk); } else CloseHandle(h); } } #if DEBUG_WINPROC { char szInfo[1001]; _win_snprintf(szInfo, 1000, "Posix path %s resolved to %s\n", pszUnix, pszWindows); szInfo[1000] = 0; __plibc_panic(INT_MAX, szInfo); } #endif return ERROR_SUCCESS; }