From 26b03ef7622f20936864f33fa6410df9b87b5047 Mon Sep 17 00:00:00 2001 From: laishenghao Date: Sat, 3 Jun 2023 17:51:39 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=88=9B=E5=BB=BA=E8=A1=A8?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=EF=BC=8C=E7=BB=9D=E5=AF=B9=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=97=B6=E4=BC=9A=E8=AF=9D=E5=8D=A1?= =?UTF-8?q?=E4=BD=8F=EF=BC=8C=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E5=85=B3=E9=97=AD=E4=B9=9F?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E7=99=BB=E9=99=86=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../optimizer/commands/tablespace.cpp | 54 +++++++++++++++++++ src/test/regress/input/tablespace.source | 9 +++- src/test/regress/output/tablespace_1.source | 7 +++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/gausskernel/optimizer/commands/tablespace.cpp b/src/gausskernel/optimizer/commands/tablespace.cpp index cf13efc250..3ca2a56e6d 100644 --- a/src/gausskernel/optimizer/commands/tablespace.cpp +++ b/src/gausskernel/optimizer/commands/tablespace.cpp @@ -100,6 +100,8 @@ static void createtbspc_abort_callback(bool isCommit, const void* arg); Datum CanonicalizeTablespaceOptions(Datum datum); +#define CHECK_PATH_RETRY_COUNT 100 + #define CANONICALIZE_PATH(path) \ do { \ if (NULL != (path)) { \ @@ -2478,12 +2480,56 @@ char* get_tablespace_name(Oid spc_oid) return result; } +bool IsPathContainsSymlink(char* path) +{ + struct stat statbuf; + errno_t rc; + char* ptr = path; + + if (*ptr == '/') { + ++ptr; + } + + for (bool isLast = false; !isLast; ++ptr) { + if (*ptr == '\0') { + isLast = true; + } else if (*ptr != '/') { + continue; + } + + if (!isLast && ptr[1] == '\0') { + isLast = true; + } + + *ptr = '\0'; + rc = memset_s(&statbuf, sizeof(statbuf), 0, sizeof(statbuf)); + if (rc != EOK) { + continue; + } + + if (lstat(path, &statbuf) == 0 && S_ISLNK(statbuf.st_mode)) { + return true; + } + + if (!isLast) { + *ptr = '/'; + } + } + + return false; +} + /* check if the dir(location) is exist, if not create it */ void check_create_dir(char* location) { int ret; + int retryCount = 0; + bool hasLink = IsPathContainsSymlink(location); recheck: + if (hasLink) { + ++retryCount; + } /* We believe that the location we got from the record is credible. */ switch (ret = pg_check_dir(location)) { case 0: { @@ -2492,6 +2538,14 @@ recheck: if (pg_mkdir_p_used_by_gaussdb(tmplocation, S_IRWXU) == -1) { if (errno == EEXIST) { pfree_ext(tmplocation); + + if (hasLink && retryCount > CHECK_PATH_RETRY_COUNT) { + ereport(ERROR, (errmodule(MOD_TBLSPC), + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("recheck location \"%s\" exeed max times.", location), + errdetail("the location contains symbolic link, the linked path likely has been deleted."))); + } + goto recheck; } else ereport(ERROR, diff --git a/src/test/regress/input/tablespace.source b/src/test/regress/input/tablespace.source index 3381662346..0548e8e499 100644 --- a/src/test/regress/input/tablespace.source +++ b/src/test/regress/input/tablespace.source @@ -140,4 +140,11 @@ DROP TABLESPACE testspace; -- symlink location \! mkdir -p @testtablespace@/symlink/sym1 \! ln -s @testtablespace@/symlink/sym1 @testtablespace@/symlink/sym2 -CREATE TABLESPACE test_symlink LOCATION '@testtablespace@/symlink/sym2'; \ No newline at end of file +CREATE TABLESPACE test_symlink LOCATION '@testtablespace@/symlink/sym2'; + +-- check linked path deleted +\! mkdir -p @testtablespace@/symlink/will_delete +\! ln -s @testtablespace@/symlink/will_delete @testtablespace@/symlink/will_delete_link +\! rm -rf @testtablespace@/symlink/will_delete + +CREATE TABLESPACE deleted_symlink LOCATION '@testtablespace@/symlink/will_delete_link/local'; diff --git a/src/test/regress/output/tablespace_1.source b/src/test/regress/output/tablespace_1.source index 1d507edb80..5c5e542fd5 100644 --- a/src/test/regress/output/tablespace_1.source +++ b/src/test/regress/output/tablespace_1.source @@ -272,3 +272,10 @@ DROP TABLESPACE testspace; \! ln -s @testtablespace@/symlink/sym1 @testtablespace@/symlink/sym2 CREATE TABLESPACE test_symlink LOCATION '@testtablespace@/symlink/sym2'; ERROR: location "@testtablespace@/symlink/sym2" is symbolic link +-- check linked path deleted +\! mkdir -p @testtablespace@/symlink/will_delete +\! ln -s @testtablespace@/symlink/will_delete @testtablespace@/symlink/will_delete_link +\! rm -rf @testtablespace@/symlink/will_delete +CREATE TABLESPACE deleted_symlink LOCATION '@testtablespace@/symlink/will_delete_link/local'; +ERROR: recheck location "@testtablespace@/symlink/will_delete_link" exeed max times. +DETAIL: the location contains symbolic link, the linked path likely has been deleted. -- Gitee