void file_info_to_attrib(LPBY_HANDLE_FILE_INFORMATION file_info, FILE_ID_INFO *fileid_info, Attrib *a) { attrib_clear(a); a->flags = 0; a->flags |= SSH2_FILEXFER_ATTR_SIZE; a->size = (file_info->nFileSizeHigh * (MAXDWORD+1)) + file_info->nFileSizeLow; a->flags |= SSH2_FILEXFER_ATTR_UIDGID; a->uid = 0; a->gid = 0; a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a->perm = 0644; if ( file_info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { a->perm = 0755; a->perm ^= S_IFDIR; } else { a->perm ^= S_IFREG; } if ( file_info->dwFileAttributes & FILE_ATTRIBUTE_READONLY ) a->perm &= ~0222; a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME; a->atime = filetime_to_time_t( file_info->ftLastAccessTime ); a->mtime = filetime_to_time_t( file_info->ftLastWriteTime ); }
int mingw_fstat(int fd, struct stat *buf) { HANDLE fh = (HANDLE)_get_osfhandle(fd); BY_HANDLE_FILE_INFORMATION fdata; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } /* direct non-file handles to MS's fstat() */ if (GetFileType(fh) != FILE_TYPE_DISK) return _fstati64(fd, buf); if (GetFileInformationByHandle(fh, &fdata)) { buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); buf->st_size = fdata.nFileSizeLow | (((off_t)fdata.nFileSizeHigh)<<32); buf->st_dev = buf->st_rdev = 0; /* not used by Git */ 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 0; } errno = EBADF; return -1; }
int mingw_fstat(int fd, struct mingw_stat *buf) { HANDLE fh = (HANDLE)_get_osfhandle(fd); BY_HANDLE_FILE_INFORMATION fdata; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } /* direct non-file handles to MS's fstat() */ if (GetFileType(fh) != FILE_TYPE_DISK) { struct stat st; if (fstat(fd, &st)) return -1; buf->st_ino = st.st_ino; buf->st_gid = st.st_gid; buf->st_uid = st.st_uid; buf->st_mode = st.st_mode; buf->st_size = st.st_size; buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = st.st_dev; buf->st_atime = st.st_atime; buf->st_mtime = st.st_mtime; buf->st_ctime = st.st_ctime; return 0; } if (GetFileInformationByHandle(fh, &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; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_mode = fMode; buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = _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 0; } errno = EBADF; return -1; }
static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; wchar_t* fbuf = gitwin_to_utf16(file_name); if (GetFileAttributesExW(fbuf, 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)); git__free(fbuf); return GIT_SUCCESS; } git__free(fbuf); 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; } }
/* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. * * If follow is true then act like stat() and report on the link * target. Otherwise report on the link itself. */ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) { int err; WIN32_FILE_ATTRIBUTE_DATA fdata; if (!(err = get_file_attr(file_name, &fdata))) { int len = strlen(file_name); buf->st_ino = 0; buf->st_uid = DEFAULT_UID; buf->st_gid = DEFAULT_GID; buf->st_nlink = 1; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); if (len > 4 && (!strcasecmp(file_name+len-4, ".exe") || !strcasecmp(file_name+len-4, ".com"))) buf->st_mode |= S_IEXEC; buf->st_size = fdata.nFileSizeLow | (((off64_t)fdata.nFileSizeHigh)<<32); buf->st_dev = buf->st_rdev = 0; /* not used by Git */ 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)); if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { WIN32_FIND_DATAA findbuf; HANDLE handle = FindFirstFileA(file_name, &findbuf); if (handle != INVALID_HANDLE_VALUE) { if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { if (follow) { char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); } else { buf->st_mode = S_IFLNK; } buf->st_mode |= S_IREAD; if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) buf->st_mode |= S_IWRITE; } FindClose(handle); } } /* * Assume a block is 4096 bytes and calculate number of 512 byte * sectors. */ buf->st_blksize = 4096; buf->st_blocks = ((buf->st_size+4095)>>12)<<3; return 0; }
static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; DWORD last_error; wchar_t* fbuf = gitwin_to_utf16(file_name); if (!fbuf) return -1; if (GetFileAttributesExW(fbuf, 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 = ((git_off_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow; 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)); git__free(fbuf); return 0; } last_error = GetLastError(); if (last_error == ERROR_FILE_NOT_FOUND) errno = ENOENT; else if (last_error == ERROR_PATH_NOT_FOUND) errno = ENOTDIR; git__free(fbuf); return -1; }
/* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. */ 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; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_mode = fMode; buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = _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)); 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: errno = ENOENT; break; } return -1; }
int lstat(const char *path, struct stat *buffer) { WIN32_FILE_ATTRIBUTE_DATA fdata; if (GetFileAttributesEx(path, 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; buffer->st_ino = 0; buffer->st_gid = 0; buffer->st_uid = 0; buffer->st_nlink = 1; buffer->st_mode = fMode; buffer->st_size = fdata.nFileSizeLow; buffer->st_dev = buffer->st_rdev = 0; buffer->st_atime = filetime_to_time_t(&fdata.ftLastAccessTime); buffer->st_mtime = filetime_to_time_t(&fdata.ftLastWriteTime); buffer->st_ctime = filetime_to_time_t(&fdata.ftCreationTime); if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { WIN32_FIND_DATA find; HANDLE handle = FindFirstFile(path, &find); if (handle != INVALID_HANDLE_VALUE) { if ((find.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && (find.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { buffer->st_mode = S_IFLNK; } } } _set_errno(0); return 0; } errno = winErrorToPosix(GetLastError()); return -1; }
/* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. */ static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; if (!(errno = get_file_attr(file_name, &fdata))) { buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_dev = buf->st_rdev = 0; /* not used by Git */ 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 0; } return -1; }
/* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. * * If follow is true then act like stat() and report on the link * target. Otherwise report on the link itself. */ static int do_lstat(int follow, const char *file_name, struct stat *buf) { int err; WIN32_FILE_ATTRIBUTE_DATA fdata; if (!(err = get_file_attr(file_name, &fdata))) { buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); buf->st_size = fdata.nFileSizeLow | (((off_t)fdata.nFileSizeHigh)<<32); buf->st_dev = buf->st_rdev = 0; /* not used by Git */ 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)); if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { WIN32_FIND_DATAA findbuf; HANDLE handle = FindFirstFileA(file_name, &findbuf); if (handle != INVALID_HANDLE_VALUE) { if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { if (follow) { char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); } else { buf->st_mode = S_IFLNK; } buf->st_mode |= S_IREAD; if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) buf->st_mode |= S_IWRITE; } FindClose(handle); } } return 0; } errno = err; return -1; }
static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; wchar_t fbuf[GIT_WIN_PATH], lastch; int flen; flen = git__utf8_to_16(fbuf, GIT_WIN_PATH, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { lastch = fbuf[flen - 1]; if (WIN32_IS_WSEP(lastch)) fbuf[flen - 1] = L'\0'; else if (lastch != L'\0') break; } if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { int fMode = S_IREAD; if (!buf) return 0; 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 = ((git_off_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow; 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)); /* Windows symlinks have zero file size, call readlink to determine * the length of the path pointed to, which we expect everywhere else */ if (S_ISLNK(fMode)) { char target[GIT_WIN_PATH]; int readlink_result; readlink_result = p_readlink(file_name, target, GIT_WIN_PATH); if (readlink_result == -1) return -1; buf->st_size = strlen(target); } return 0; } errno = ENOENT; /* We need POSIX behavior, then ENOTDIR must set when any of the folders in the * file path is a regular file,otherwise ENOENT must be set. */ if (posix_enotdir) { /* scan up path until we find an existing item */ while (1) { /* remove last directory component */ for (--flen; flen > 0 && !WIN32_IS_WSEP(fbuf[flen]); --flen); if (flen <= 0) break; fbuf[flen] = L'\0'; if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) errno = ENOTDIR; break; } } } return -1; }
char * win32_ls_file(const char *name, LPWIN32_FIND_DATA file, int remote, int si_units) { int ulen, glen, sz = 0; //struct tm *ltime = localtime(&st->st_mtime); char *user, *group; char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; char sbuf[FMT_SCALED_STRSIZE]; SYSTEMTIME now; SYSTEMTIME ftime; time_t mtime = filetime_to_time_t( file->ftLastWriteTime ); BOOL time_conv_ok = FileTimeToSystemTime( &file->ftLastWriteTime, &ftime); struct tm *ltime = localtime( &mtime ); if (!time_conv_ok) { error("Failed to convert file time to localtime"); } strmode(0644, mode); if (!remote) { user = user_from_uid(0, 0); } else { snprintf(ubuf, sizeof ubuf, "%u", 0); user = ubuf; } if (!remote) { group = group_from_gid(0, 0); } else { snprintf(gbuf, sizeof gbuf, "%u", 0); group = gbuf; } if (time_conv_ok) { //now = time(NULL); GetSystemTime(&now); if ( (time_diff(now, ftime) / 10000000ULL) < (365*24*60*60) ) { //if (now - (365*24*60*60)/2 < st->st_mtime && // now >= st->st_mtime) sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime); } else { sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime); } } if (sz == 0) tbuf[0] = '\0'; ulen = MAX(strlen(user), 8); glen = MAX(strlen(group), 8); long long size = (file->nFileSizeHigh * (MAXDWORD+1)) + file->nFileSizeLow; if (si_units) { fmt_scaled(size, sbuf); snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode, 1 /*nlink -- FIXME */, ulen, user, glen, group, sbuf, tbuf, name); } else { snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode, 1 /*nlink -- FIXME */, ulen, user, glen, group, size, tbuf, name); } return xstrdup(buf); }