From 38704c29b593e32404ad13f93d0bce6330ee41d1 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Sun, 8 Mar 2020 17:15:02 -0500 Subject: [PATCH v12 06/11] Show links to dirs with isdir=false.. ..this is needed to avoid infinite recursion in pg_ls_dir_recurse. Change pg_stat_file for consistency. --- doc/src/sgml/func.sgml | 2 +- src/backend/utils/adt/genfile.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 4b966ed847..68c7327e1d 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -21545,7 +21545,7 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8'); size, last accessed time stamp, last modified time stamp, last file status change time stamp (Unix platforms only), file creation time stamp (Windows only), and a boolean - indicating if it is a directory (or a symbolic link to a directory). + indicating if it is a directory (and not a symbolic link to a directory). Typical usages include: SELECT * FROM pg_stat_file('filename'); diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index 98ab9a2b92..70b541388e 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -365,6 +365,22 @@ pg_read_binary_file_all(PG_FUNCTION_ARGS) return pg_read_binary_file(fcinfo); } +/* Return true iff path is a symbolic link (unix) or junction (win32) */ +static bool +islink(const char *path) +{ +#ifndef WIN32 + struct stat attrib; + if (lstat(path, &attrib) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not stat file \"%s\": %m", path))); + return S_ISLNK(attrib.st_mode); +#else + return pgwin32_is_junction(path); +#endif +} + /* * stat a file */ @@ -428,7 +444,7 @@ pg_stat_file(PG_FUNCTION_ARGS) isnull[3] = true; values[4] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime)); #endif - values[5] = BoolGetDatum(S_ISDIR(fst.st_mode)); + values[5] = BoolGetDatum(S_ISDIR(fst.st_mode) && !islink(filename)); tuple = heap_form_tuple(tupdesc, values, isnull); @@ -614,7 +630,8 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, int flags) values[1] = Int64GetDatum((int64) attrib.st_size); values[2] = TimestampTzGetDatum(time_t_to_timestamptz(attrib.st_mtime)); if (flags & LS_DIR_ISDIR) - values[3] = BoolGetDatum(S_ISDIR(attrib.st_mode)); + values[3] = BoolGetDatum(S_ISDIR(attrib.st_mode) && + !islink(path)); } memset(nulls, 0, sizeof(nulls)); -- 2.17.0