From fae83e948c7f8bd9f8f33ef6f088f8d7b5cf465a Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 24 Jun 2015 11:26:02 +0900 Subject: [PATCH 5/8] Add new column islink in pg_stat_file This allows to detect if the file path evaluated is a synlink or not. pg_stat_file is switched to use as well lstat to enable soft link detection. --- doc/src/sgml/func.sgml | 5 +++-- src/backend/utils/adt/genfile.c | 15 +++++++++++---- src/include/catalog/pg_proc.h | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 3b5161a..20b91ab 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17903,8 +17903,9 @@ SELECT convert_from(pg_read_binary_file('file_in_utf8.txt'), 'UTF8'); pg_stat_file returns a record containing the file 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. Typical usages include: + file creation time stamp (Windows only), a boolean + indicating if it is a directory, and a boolean + indicating if it is a symbolic link. Typical usages include: SELECT * FROM pg_stat_file('filename'); SELECT (pg_stat_file('filename')).modification; diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index 12866dd..456061b 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -392,8 +392,8 @@ stat_file_wrapper(PG_FUNCTION_ARGS) text *filename_t = PG_GETARG_TEXT_P(0); char *filename; struct stat fst; - Datum values[6]; - bool isnull[6]; + Datum values[7]; + bool isnull[7]; HeapTuple tuple; TupleDesc tupdesc; bool if_not_exists = false; @@ -410,7 +410,7 @@ stat_file_wrapper(PG_FUNCTION_ARGS) filename = convert_and_check_filename(filename_t); - if (stat(filename, &fst) < 0) + if (lstat(filename, &fst) < 0) { if (if_not_exists && errno == ENOENT) return_null = true; @@ -424,7 +424,7 @@ stat_file_wrapper(PG_FUNCTION_ARGS) * This record type had better match the output parameters declared for me * in pg_proc.h. */ - tupdesc = CreateTemplateTupleDesc(6, false); + tupdesc = CreateTemplateTupleDesc(7, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "size", INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, @@ -437,6 +437,8 @@ stat_file_wrapper(PG_FUNCTION_ARGS) "creation", TIMESTAMPTZOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 6, "isdir", BOOLOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, + "islink", BOOLOID, -1, 0); BlessTupleDesc(tupdesc); memset(isnull, return_null, sizeof(isnull)); @@ -455,6 +457,11 @@ stat_file_wrapper(PG_FUNCTION_ARGS) values[4] = TimestampTzGetDatum(time_t_to_timestamptz(fst.st_ctime)); #endif values[5] = BoolGetDatum(S_ISDIR(fst.st_mode)); +#ifndef WIN32 + values[6] = BoolGetDatum(S_ISLNK(fst.st_mode)); +#else + values[6] = BoolGetDatum(pgwin32_is_junction(filename)); +#endif } tuple = heap_form_tuple(tupdesc, values, isnull); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index b559572..36d3e15 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3183,9 +3183,9 @@ DESCR("reload configuration files"); DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ )); DESCR("rotate log file"); -DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file _null_ _null_ _null_ )); +DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16,16}" "{i,o,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir,islink}" _null_ _null_ pg_stat_file _null_ _null_ _null_ )); DESCR("get information about file"); -DATA(insert OID = 3307 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 2249 "25 16" "{25,16,20,1184,1184,1184,1184,16}" "{i,i,o,o,o,o,o,o}" "{filename,if_not_exists,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file_extended _null_ _null_ _null_ )); +DATA(insert OID = 3307 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 2249 "25 16" "{25,16,20,1184,1184,1184,1184,16,16}" "{i,i,o,o,o,o,o,o,o}" "{filename,if_not_exists,size,access,modification,change,creation,isdir,islink}" _null_ _null_ pg_stat_file_extended _null_ _null_ _null_ )); DESCR("get information about file"); DATA(insert OID = 2624 ( pg_read_file PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 25 "25 20 20" _null_ _null_ _null_ _null_ _null_ pg_read_file _null_ _null_ _null_ )); DESCR("read text from a file"); -- 2.4.4