[prev in list] [next in list] [prev in thread] [next in thread]
List: git
Subject: Re: [PATCH] add GIT_FAST_STAT mode for Cygwin
From: Johannes Sixt <johannes.sixt () telecom ! at>
Date: 2008-09-23 19:03:08
Message-ID: 200809232103.09133.johannes.sixt () telecom ! at
[Download RAW message or body]
On Dienstag, 23. September 2008, Dmitry Potapov wrote:
> +static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
> +{
> + long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
> + winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
> + ts->tv_sec = (time_t)(winTime/10000000); /* 100-nanosecond interval to seconds */
> + ts->tv_nsec = (long)(winTime - ts->tv_sec) * 100; /* nanoseconds */ +}
+ ts->tv_nsec = (long)(winTime - ts->tv_sec*10000000LL) * 100;
> +static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat)
> +{
> + WIN32_FILE_ATTRIBUTE_DATA fdata;
> +
> + if (file_name[0] == '/')
> + return cygstat (file_name, buf);
You should do this in the caller; it would make this function's
semantics much clearer.
> +
> + if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
> + int fMode = S_IREAD;
> + /*
> + * If the system attribute is set and it is not a directory then
> + * it could be a symbol link created in the nowinsymlinks mode.
> + * Normally, Cygwin works in the winsymlinks mode, so this situation
> + * is very unlikely. For the sake of simplicity of our code, let's
> + * Cygwin to handle it.
> + */
> + if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
> + !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
> + return cygstat (file_name, buf);
> +
> + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
> + fMode |= S_IFDIR;
> + else
> + fMode |= S_IFREG;
> + if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
> + fMode |= S_IWRITE;
> +
> + /* st_dev, st_rdev are not used by Git */
> + buf->st_dev = buf->st_rdev = 0;
> + /* it is difficult to obtain the inode number on Windows,
> + * so let's set it to zero as MinGW Git does. */
> + buf->st_ino = 0;
> + buf->st_mode = fMode;
> + buf->st_nlink = 1;
> + buf->st_uid = buf->st_gid = 0;
> +#ifdef __CYGWIN_USE_BIG_TYPES__
> + buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) +
> + fdata.nFileSizeLow;
> +#else
> + buf->st_size = (off_t)fdata.nFileSizeLow;
> +#endif
> + buf->st_blocks = size_to_blocks(buf->st_size);
> + filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim);
> + filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim);
> + filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim);
> + errno = 0;
> + return 0;
> + }
> +
> + switch (GetLastError()) {
> + case ERROR_ACCESS_DENIED:
> + case ERROR_SHARING_VIOLATION:
> + case ERROR_LOCK_VIOLATION:
> + case ERROR_SHARING_BUFFER_EXCEEDED:
> + errno = EACCES;
> + break;
> + case ERROR_BUFFER_OVERFLOW:
> + errno = ENAMETOOLONG;
> + break;
> + case ERROR_NOT_ENOUGH_MEMORY:
> + errno = ENOMEM;
> + break;
> + default:
> + /* In the winsymlinks mode (which is the default), Cygwin
> + * emulates symbol links using Windows shortcut files. These
> + * files are formed by adding .lnk extension. So, if we have
> + * not found the specified file name, it could be that it is
> + * a symbol link. Let's Cygwin to deal with that.
> + */
> + return cygstat (file_name, buf);
> + }
> + return -1;
You do duplicate a lot of code here. Any chances to factor out the
common parts? Start with platform specific function
filetime_to_stat_time() that is your filetime_to_timespec() on Cygwin,
but filetime_to_time_t() (which needs modification) on MinGW.
-- Hannes
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic