summaryrefslogtreecommitdiff
path: root/src/win32
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-07-04 11:43:34 +0200
committerVicent Marti <tanoku@gmail.com>2011-07-05 02:04:03 +0200
commitf79026b4912bcd2336667f4c1663c06e233f0b32 (patch)
tree645b776032e924b587fad986aa3f3dc08c98d4c5 /src/win32
parent678e9e045becdc5d75f2ce2259ed01c3531ee181 (diff)
downloadlibgit2-f79026b4912bcd2336667f4c1663c06e233f0b32.tar.gz
fileops: Cleanup
Cleaned up the structure of the whole OS-abstraction layer. fileops.c now contains a set of utility methods for file management used by the library. These are abstractions on top of the original POSIX calls. There's a new file called `posix.c` that contains emulations/reimplementations of all the POSIX calls the library uses. These are prefixed with `p_`. There's a specific posix file for each platform (win32 and unix). All the path-related methods have been moved from `utils.c` to `path.c` and have their own prefix.
Diffstat (limited to 'src/win32')
-rw-r--r--src/win32/fileops.c41
-rw-r--r--src/win32/map.c4
-rw-r--r--src/win32/posix.c191
-rw-r--r--src/win32/posix.h25
4 files changed, 218 insertions, 43 deletions
diff --git a/src/win32/fileops.c b/src/win32/fileops.c
deleted file mode 100644
index d435e706e..000000000
--- a/src/win32/fileops.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#define GIT__WIN32_NO_HIDE_FILEOPS
-#include "fileops.h"
-#include <errno.h>
-
-int git__unlink(const char *path)
-{
- chmod(path, 0666);
- return unlink(path);
-}
-
-int git__mkstemp(char *template)
-{
- char *file = mktemp(template);
- if (file == NULL)
- return -1;
- return open(file, O_RDWR | O_CREAT | O_BINARY, 0600);
-}
-
-int git__fsync(int fd)
-{
- HANDLE fh = (HANDLE)_get_osfhandle(fd);
-
- if (fh == INVALID_HANDLE_VALUE) {
- errno = EBADF;
- return -1;
- }
-
- if (!FlushFileBuffers(fh)) {
- DWORD code = GetLastError();
-
- if (code == ERROR_INVALID_HANDLE)
- errno = EINVAL;
- else
- errno = EIO;
-
- return -1;
- }
-
- return 0;
-}
-
diff --git a/src/win32/map.c b/src/win32/map.c
index c7a39fcf6..76b926490 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -16,7 +16,7 @@ static DWORD get_page_size(void)
return page_size;
}
-int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
DWORD page_size = get_page_size();
@@ -92,7 +92,7 @@ int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t o
return GIT_SUCCESS;
}
-int git__munmap(git_map *map)
+int p_munmap(git_map *map)
{
assert(map != NULL);
diff --git a/src/win32/posix.c b/src/win32/posix.c
new file mode 100644
index 000000000..003ce1fd6
--- /dev/null
+++ b/src/win32/posix.c
@@ -0,0 +1,191 @@
+#include "posix.h"
+#include <errno.h>
+
+int p_unlink(const char *path)
+{
+ chmod(path, 0666);
+ return unlink(path);
+}
+
+int p_fsync(int fd)
+{
+ HANDLE fh = (HANDLE)_get_osfhandle(fd);
+
+ if (fh == INVALID_HANDLE_VALUE) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (!FlushFileBuffers(fh)) {
+ DWORD code = GetLastError();
+
+ if (code == ERROR_INVALID_HANDLE)
+ errno = EINVAL;
+ else
+ errno = EIO;
+
+ return -1;
+ }
+
+ return 0;
+}
+
+GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
+{
+ long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+ winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+ winTime /= 10000000; /* Nano to seconds resolution */
+ return (time_t)winTime;
+}
+
+static int do_lstat(const char *file_name, struct stat *buf)
+{
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
+
+ if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
+ int fMode = S_IREAD;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ fMode |= S_IFDIR;
+ else
+ fMode |= S_IFREG;
+
+ if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ fMode |= S_IWRITE;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ fMode |= S_IFLNK;
+
+ buf->st_ino = 0;
+ buf->st_gid = 0;
+ buf->st_uid = 0;
+ buf->st_nlink = 1;
+ buf->st_mode = (mode_t)fMode;
+ buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+ buf->st_dev = buf->st_rdev = (_getdrive() - 1);
+ buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+ buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+ buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+ return GIT_SUCCESS;
+ }
+
+ switch (GetLastError()) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ return GIT_EOSERR;
+
+ case ERROR_BUFFER_OVERFLOW:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return GIT_ENOMEM;
+
+ default:
+ return GIT_EINVALIDPATH;
+ }
+}
+
+int p_lstat(const char *file_name, struct stat *buf)
+{
+ int namelen, error;
+ char alt_name[GIT_PATH_MAX];
+
+ if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
+ return GIT_SUCCESS;
+
+ /* if file_name ended in a '/', Windows returned ENOENT;
+ * try again without trailing slashes
+ */
+ if (error != GIT_EINVALIDPATH)
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ namelen = strlen(file_name);
+ if (namelen && file_name[namelen-1] != '/')
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ while (namelen && file_name[namelen-1] == '/')
+ --namelen;
+
+ if (!namelen || namelen >= GIT_PATH_MAX)
+ return git__throw(GIT_ENOMEM, "Failed to lstat file");
+
+ memcpy(alt_name, file_name, namelen);
+ alt_name[namelen] = 0;
+ return do_lstat(alt_name, buf);
+}
+
+int p_readlink(const char *link, char *target, size_t target_len)
+{
+ typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD);
+ static fpath_func pGetFinalPath = NULL;
+ HANDLE hFile;
+ DWORD dwRet;
+
+ /*
+ * Try to load the pointer to pGetFinalPath dynamically, because
+ * it is not available in platforms older than Vista
+ */
+ if (pGetFinalPath == NULL) {
+ HINSTANCE library = LoadLibrary("kernel32");
+
+ if (library != NULL)
+ pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA");
+
+ if (pGetFinalPath == NULL)
+ return git__throw(GIT_EOSERR,
+ "'GetFinalPathNameByHandleA' is not available in this platform");
+ }
+
+ hFile = CreateFile(link, // file to open
+ GENERIC_READ, // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // default security
+ OPEN_EXISTING, // existing file only
+ FILE_FLAG_BACKUP_SEMANTICS, // normal file
+ NULL); // no attr. template
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return GIT_EOSERR;
+
+ dwRet = pGetFinalPath(hFile, target, target_len, 0x0);
+ if (dwRet >= target_len)
+ return GIT_ENOMEM;
+
+ CloseHandle(hFile);
+
+ if (dwRet > 4) {
+ /* Skip first 4 characters if they are "\\?\" */
+ if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
+ char tmp[GIT_PATH_MAX];
+ unsigned int offset = 4;
+ dwRet -= 4;
+
+ /* \??\UNC\ */
+ if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
+ offset += 2;
+ dwRet -= 2;
+ target[offset] = '\\';
+ }
+
+ memcpy(tmp, target + offset, dwRet);
+ memcpy(target, tmp, dwRet);
+ }
+ }
+
+ target[dwRet] = '\0';
+ return dwRet;
+}
+
+int p_hide_directory__w32(const char *path)
+{
+ int error;
+
+ error = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) != 0 ?
+ GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
+
+ if (error < GIT_SUCCESS)
+ error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
+
+ return error;
+}
+
diff --git a/src/win32/posix.h b/src/win32/posix.h
new file mode 100644
index 000000000..31ee7201c
--- /dev/null
+++ b/src/win32/posix.h
@@ -0,0 +1,25 @@
+#ifndef INCLUDE_posix__w32_h__
+#define INCLUDE_posix__w32_h__
+
+#include "common.h"
+
+GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
+{
+ GIT_UNUSED_ARG(old)
+ GIT_UNUSED_ARG(new)
+ errno = ENOSYS;
+ return -1;
+}
+
+GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
+{
+ GIT_UNUSED_ARG(mode)
+ return mkdir(path);
+}
+
+extern int p_unlink(const char *path);
+extern int p_lstat(const char *file_name, struct stat *buf);
+extern int p_readlink(const char *link, char *target, size_t target_len);
+extern int p_hide_directory__w32(const char *path);
+
+#endif