mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Replace pgwin32_is_junction() with lstat().
Now that lstat() reports junction points with S_IFLNK/S_ISLINK(), and unlink() can unlink them, there is no need for conditional code for Windows in a few places. That was expressed by testing for WIN32 or S_ISLNK, which we can now constant-fold. The coding around pgwin32_is_junction() was a bit suspect anyway, as we never checked for errors, and we also know that errors can be spuriously reported because of transient sharing violations on this OS. The lstat()-based code has handling for that. This also reverts4fc6b6eeon master only. That was done because lstat() didn't previously work for symlinks (junction points), but now it does. Tested-by: Andrew Dunstan <andrew@dunslane.net> Discussion: https://postgr.es/m/CA%2BhUKGLfOOeyZpm5ByVcAt7x5Pn-%3DxGRNCvgiUPVVzjFLtnY0w%40mail.gmail.com (cherry picked from commit5fc88c5d53) Author: Thomas Munro <tmunro@postgresql.org> Author: Alexandra Wang <alexandra.wang.oss@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Andrew Dunstan
					
				
			
			
				
	
			
			
			
						parent
						
							8a5e4982f9
						
					
				
				
					commit
					ca9921936e
				
			@@ -787,8 +787,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Try to remove the symlink.  We must however deal with the possibility
 | 
						 * Try to remove the symlink.  We must however deal with the possibility
 | 
				
			||||||
	 * that it's a directory instead of a symlink --- this could happen during
 | 
						 * that it's a directory instead of a symlink --- this could happen during
 | 
				
			||||||
	 * WAL replay (see TablespaceCreateDbspace), and it is also the case on
 | 
						 * WAL replay (see TablespaceCreateDbspace).
 | 
				
			||||||
	 * Windows where junction points lstat() as directories.
 | 
					 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * Note: in the redo case, we'll return true if this final step fails;
 | 
						 * Note: in the redo case, we'll return true if this final step fails;
 | 
				
			||||||
	 * there's no point in retrying it.  Also, ENOENT should provoke no more
 | 
						 * there's no point in retrying it.  Also, ENOENT should provoke no more
 | 
				
			||||||
@@ -818,7 +817,6 @@ remove_symlink:
 | 
				
			|||||||
							linkloc)));
 | 
												linkloc)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#ifdef S_ISLNK
 | 
					 | 
				
			||||||
	else if (S_ISLNK(st.st_mode))
 | 
						else if (S_ISLNK(st.st_mode))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (unlink(linkloc) < 0)
 | 
							if (unlink(linkloc) < 0)
 | 
				
			||||||
@@ -831,7 +829,6 @@ remove_symlink:
 | 
				
			|||||||
							linkloc)));
 | 
												linkloc)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* Refuse to remove anything that's not a directory or symlink */
 | 
							/* Refuse to remove anything that's not a directory or symlink */
 | 
				
			||||||
@@ -909,7 +906,6 @@ remove_tablespace_symlink(const char *linkloc)
 | 
				
			|||||||
					 errmsg("could not remove directory \"%s\": %m",
 | 
										 errmsg("could not remove directory \"%s\": %m",
 | 
				
			||||||
							linkloc)));
 | 
												linkloc)));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#ifdef S_ISLNK
 | 
					 | 
				
			||||||
	else if (S_ISLNK(st.st_mode))
 | 
						else if (S_ISLNK(st.st_mode))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (unlink(linkloc) < 0 && errno != ENOENT)
 | 
							if (unlink(linkloc) < 0 && errno != ENOENT)
 | 
				
			||||||
@@ -918,7 +914,6 @@ remove_tablespace_symlink(const char *linkloc)
 | 
				
			|||||||
					 errmsg("could not remove symbolic link \"%s\": %m",
 | 
										 errmsg("could not remove symbolic link \"%s\": %m",
 | 
				
			||||||
							linkloc)));
 | 
												linkloc)));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* Refuse to remove anything that's not a directory or symlink */
 | 
							/* Refuse to remove anything that's not a directory or symlink */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1415,13 +1415,7 @@ sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Allow symbolic links in pg_tblspc only */
 | 
							/* Allow symbolic links in pg_tblspc only */
 | 
				
			||||||
		if (strcmp(path, "./pg_tblspc") == 0 &&
 | 
							if (strcmp(path, "./pg_tblspc") == 0 && S_ISLNK(statbuf.st_mode))
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
			S_ISLNK(statbuf.st_mode)
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
			pgwin32_is_junction(pathbuf)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
			)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#if defined(HAVE_READLINK) || defined(WIN32)
 | 
					#if defined(HAVE_READLINK) || defined(WIN32)
 | 
				
			||||||
			char		linkpath[MAXPGPATH];
 | 
								char		linkpath[MAXPGPATH];
 | 
				
			||||||
@@ -1884,11 +1878,7 @@ _tarWriteDir(const char *pathbuf, int basepathlen, struct stat *statbuf,
 | 
				
			|||||||
			 bool sizeonly)
 | 
								 bool sizeonly)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* If symlink, write it as a directory anyway */
 | 
						/* If symlink, write it as a directory anyway */
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
	if (S_ISLNK(statbuf->st_mode))
 | 
						if (S_ISLNK(statbuf->st_mode))
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	if (pgwin32_is_junction(pathbuf))
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		statbuf->st_mode = S_IFDIR | pg_dir_create_mode;
 | 
							statbuf->st_mode = S_IFDIR | pg_dir_create_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return _tarWriteHeader(pathbuf + basepathlen + 1, NULL, statbuf, sizeonly);
 | 
						return _tarWriteHeader(pathbuf + basepathlen + 1, NULL, statbuf, sizeonly);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3351,7 +3351,6 @@ SyncDataDirectory(void)
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	xlog_is_symlink = false;
 | 
						xlog_is_symlink = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct stat st;
 | 
							struct stat st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3363,10 +3362,6 @@ SyncDataDirectory(void)
 | 
				
			|||||||
		else if (S_ISLNK(st.st_mode))
 | 
							else if (S_ISLNK(st.st_mode))
 | 
				
			||||||
			xlog_is_symlink = true;
 | 
								xlog_is_symlink = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	if (pgwin32_is_junction("pg_wal"))
 | 
					 | 
				
			||||||
		xlog_is_symlink = true;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_SYNCFS
 | 
					#ifdef HAVE_SYNCFS
 | 
				
			||||||
	if (recovery_init_sync_method == RECOVERY_INIT_SYNC_METHOD_SYNCFS)
 | 
						if (recovery_init_sync_method == RECOVERY_INIT_SYNC_METHOD_SYNCFS)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -310,9 +310,7 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	char		sourcepath[MAXPGPATH];
 | 
						char		sourcepath[MAXPGPATH];
 | 
				
			||||||
	char		targetpath[MAXPGPATH];
 | 
						char		targetpath[MAXPGPATH];
 | 
				
			||||||
	int			rllen;
 | 
						int			rllen;
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
	struct stat st;
 | 
						struct stat st;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * It's useful to apply this function to pg_class.reltablespace, wherein
 | 
						 * It's useful to apply this function to pg_class.reltablespace, wherein
 | 
				
			||||||
@@ -343,10 +341,6 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
 | 
				
			|||||||
	 * created with allow_in_place_tablespaces enabled.  If a directory is
 | 
						 * created with allow_in_place_tablespaces enabled.  If a directory is
 | 
				
			||||||
	 * found, a relative path to the data directory is returned.
 | 
						 * found, a relative path to the data directory is returned.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
#ifdef WIN32
 | 
					 | 
				
			||||||
	if (!pgwin32_is_junction(sourcepath))
 | 
					 | 
				
			||||||
		PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	if (lstat(sourcepath, &st) < 0)
 | 
						if (lstat(sourcepath, &st) < 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ereport(ERROR,
 | 
							ereport(ERROR,
 | 
				
			||||||
@@ -357,7 +351,6 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (!S_ISLNK(st.st_mode))
 | 
						if (!S_ISLNK(st.st_mode))
 | 
				
			||||||
		PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
 | 
							PG_RETURN_TEXT_P(cstring_to_text(sourcepath));
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * In presence of a link or a junction point, return the path pointing to.
 | 
						 * In presence of a link or a junction point, return the path pointing to.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -391,11 +391,7 @@ scan_directory(const char *basedir, const char *subdir, bool sizeonly)
 | 
				
			|||||||
			if (!sizeonly)
 | 
								if (!sizeonly)
 | 
				
			||||||
				scan_file(fn, segmentno);
 | 
									scan_file(fn, segmentno);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
		else if (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
 | 
							else if (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * If going through the entries of pg_tblspc, we assume to operate
 | 
								 * If going through the entries of pg_tblspc, we assume to operate
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -431,11 +431,7 @@ recurse_dir(const char *datadir, const char *parentpath,
 | 
				
			|||||||
			/* recurse to handle subdirectories */
 | 
								/* recurse to handle subdirectories */
 | 
				
			||||||
			recurse_dir(datadir, path, callback);
 | 
								recurse_dir(datadir, path, callback);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
		else if (S_ISLNK(fst.st_mode))
 | 
							else if (S_ISLNK(fst.st_mode))
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		else if (pgwin32_is_junction(fullpath))
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#if defined(HAVE_READLINK) || defined(WIN32)
 | 
					#if defined(HAVE_READLINK) || defined(WIN32)
 | 
				
			||||||
			char		link_target[MAXPGPATH];
 | 
								char		link_target[MAXPGPATH];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,6 @@ fsync_pgdata(const char *pg_data,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	xlog_is_symlink = false;
 | 
						xlog_is_symlink = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef WIN32
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		struct stat st;
 | 
							struct stat st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,10 +87,6 @@ fsync_pgdata(const char *pg_data,
 | 
				
			|||||||
		else if (S_ISLNK(st.st_mode))
 | 
							else if (S_ISLNK(st.st_mode))
 | 
				
			||||||
			xlog_is_symlink = true;
 | 
								xlog_is_symlink = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	if (pgwin32_is_junction(pg_wal))
 | 
					 | 
				
			||||||
		xlog_is_symlink = true;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If possible, hint to the kernel that we're soon going to fsync the data
 | 
						 * If possible, hint to the kernel that we're soon going to fsync the data
 | 
				
			||||||
@@ -459,27 +454,9 @@ get_dirent_type(const char *path,
 | 
				
			|||||||
			result = PGFILETYPE_REG;
 | 
								result = PGFILETYPE_REG;
 | 
				
			||||||
		else if (S_ISDIR(fst.st_mode))
 | 
							else if (S_ISDIR(fst.st_mode))
 | 
				
			||||||
			result = PGFILETYPE_DIR;
 | 
								result = PGFILETYPE_DIR;
 | 
				
			||||||
#ifdef S_ISLNK
 | 
					 | 
				
			||||||
		else if (S_ISLNK(fst.st_mode))
 | 
							else if (S_ISLNK(fst.st_mode))
 | 
				
			||||||
			result = PGFILETYPE_LNK;
 | 
								result = PGFILETYPE_LNK;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(WIN32) && !defined(_MSC_VER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * If we're on native Windows (not Cygwin, which has its own POSIX
 | 
					 | 
				
			||||||
	 * symlinks), but not using the MSVC compiler, then we're using a
 | 
					 | 
				
			||||||
	 * readdir() emulation provided by the MinGW runtime that has no d_type.
 | 
					 | 
				
			||||||
	 * Since the lstat() fallback code reports junction points as directories,
 | 
					 | 
				
			||||||
	 * we need an extra system call to check if we should report them as
 | 
					 | 
				
			||||||
	 * symlinks instead, following our convention.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (result == PGFILETYPE_DIR &&
 | 
					 | 
				
			||||||
		!look_through_symlinks &&
 | 
					 | 
				
			||||||
		pgwin32_is_junction(path))
 | 
					 | 
				
			||||||
		result = PGFILETYPE_LNK;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -284,7 +284,6 @@ extern int	pgunlink(const char *path);
 | 
				
			|||||||
#if defined(WIN32) && !defined(__CYGWIN__)
 | 
					#if defined(WIN32) && !defined(__CYGWIN__)
 | 
				
			||||||
extern int	pgsymlink(const char *oldpath, const char *newpath);
 | 
					extern int	pgsymlink(const char *oldpath, const char *newpath);
 | 
				
			||||||
extern int	pgreadlink(const char *path, char *buf, size_t size);
 | 
					extern int	pgreadlink(const char *path, char *buf, size_t size);
 | 
				
			||||||
extern bool pgwin32_is_junction(const char *path);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define symlink(oldpath, newpath)	pgsymlink(oldpath, newpath)
 | 
					#define symlink(oldpath, newpath)	pgsymlink(oldpath, newpath)
 | 
				
			||||||
#define readlink(path, buf, size)	pgreadlink(path, buf, size)
 | 
					#define readlink(path, buf, size)	pgreadlink(path, buf, size)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -228,7 +228,6 @@ extern pgoff_t _pgftello64(FILE *stream);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
extern int	pgsymlink(const char *oldpath, const char *newpath);
 | 
					extern int	pgsymlink(const char *oldpath, const char *newpath);
 | 
				
			||||||
extern int	pgreadlink(const char *path, char *buf, size_t size);
 | 
					extern int	pgreadlink(const char *path, char *buf, size_t size);
 | 
				
			||||||
extern bool pgwin32_is_junction(const char *path);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define symlink(oldpath, newpath)	pgsymlink(oldpath, newpath)
 | 
					#define symlink(oldpath, newpath)	pgsymlink(oldpath, newpath)
 | 
				
			||||||
#define readlink(path, buf, size)	pgreadlink(path, buf, size)
 | 
					#define readlink(path, buf, size)	pgreadlink(path, buf, size)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -362,20 +362,4 @@ pgreadlink(const char *path, char *buf, size_t size)
 | 
				
			|||||||
	return r;
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Assumes the file exists, so will return false if it doesn't
 | 
					 | 
				
			||||||
 * (since a nonexistent file is not a junction)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
bool
 | 
					 | 
				
			||||||
pgwin32_is_junction(const char *path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	DWORD		attr = GetFileAttributes(path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (attr == INVALID_FILE_ATTRIBUTES)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		_dosmaperr(GetLastError());
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif							/* defined(WIN32) && !defined(__CYGWIN__) */
 | 
					#endif							/* defined(WIN32) && !defined(__CYGWIN__) */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user