示例#1
0
文件: cygwin.c 项目: julesbowden/git
/* do_stat is a common implementation for cygwin_lstat and cygwin_stat.
 *
 * To simplify its logic, in the case of cygwin symlinks, this implementation
 * falls back to the cygwin version of stat/lstat, which is provided as the
 * last argument.
 */
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);

	if (!(errno = get_file_attr(file_name, &fdata))) {
		/*
		 * 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);

		/* fill out the stat structure */
		buf->st_dev = buf->st_rdev = 0; /* not used by Git */
		buf->st_ino = 0;
		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
		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);
		return 0;
	} else if (errno == ENOENT) {
		/*
		 * 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;
}
示例#2
0
/*
 * Allocate and initialize an fsentry from a FILE_FULL_DIR_INFORMATION structure.
 */
static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsentry *list,
		PFILE_FULL_DIR_INFORMATION fdata)
{
	char buf[MAX_PATH * 3];
	int len;
	struct fsentry *fse;

	len = xwcstoutfn(buf, ARRAY_SIZE(buf), fdata->FileName, fdata->FileNameLength / sizeof(wchar_t));

	fse = fsentry_alloc(cache, list, buf, len);

	/*
	 * On certain Windows versions, host directories mapped into
	 * Windows Containers ("Volumes", see https://docs.docker.com/storage/volumes/)
	 * look like symbolic links, but their targets are paths that
	 * are valid only in kernel mode.
	 *
	 * Let's work around this by detecting that situation and
	 * telling Git that these are *not* symbolic links.
	 */
	if (fdata->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
	    fdata->EaSize == IO_REPARSE_TAG_SYMLINK &&
	    sizeof(buf) > (list ? list->len + 1 : 0) + fse->len + 1 &&
	    is_inside_windows_container()) {
		size_t off = 0;
		if (list) {
			memcpy(buf, list->name, list->len);
			buf[list->len] = '/';
			off = list->len + 1;
		}
		memcpy(buf + off, fse->name, fse->len);
		buf[off + fse->len] = '\0';
	}

	fse->st_mode = file_attr_to_st_mode(fdata->FileAttributes,
			fdata->EaSize, buf);
	fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
			fdata->EndOfFile.LowPart | (((off_t)fdata->EndOfFile.HighPart) << 32);
	filetime_to_timespec((FILETIME *)&(fdata->LastAccessTime), &(fse->st_atim));
	filetime_to_timespec((FILETIME *)&(fdata->LastWriteTime), &(fse->st_mtim));
	filetime_to_timespec((FILETIME *)&(fdata->CreationTime), &(fse->st_ctim));

	return fse;
}
示例#3
0
文件: fscache.c 项目: guban/git
/*
 * Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
 */
static struct fsentry *fseentry_create_entry(struct fsentry *list,
		const WIN32_FIND_DATAW *fdata)
{
	char buf[MAX_PATH * 3];
	int len;
	struct fsentry *fse;
	len = xwcstoutf(buf, fdata->cFileName, ARRAY_SIZE(buf));

	fse = fsentry_alloc(list, buf, len);

	fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
			fdata->dwReserved0);
	fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
			fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
	filetime_to_timespec(&(fdata->ftLastAccessTime), &(fse->st_atim));
	filetime_to_timespec(&(fdata->ftLastWriteTime), &(fse->st_mtim));
	filetime_to_timespec(&(fdata->ftCreationTime), &(fse->st_ctim));

	return fse;
}