Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * pg_tablespace.c 4 : * routines to support manipulation of the pg_tablespace relation 5 : * 6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group 7 : * Portions Copyright (c) 1994, Regents of the University of California 8 : * 9 : * 10 : * IDENTIFICATION 11 : * src/backend/catalog/pg_tablespace.c 12 : * 13 : *------------------------------------------------------------------------- 14 : */ 15 : #include "postgres.h" 16 : 17 : #include <unistd.h> 18 : #include <sys/stat.h> 19 : 20 : #include "catalog/pg_tablespace.h" 21 : #include "commands/tablespace.h" 22 : #include "miscadmin.h" 23 : 24 : 25 : /* 26 : * get_tablespace_location 27 : * Get a tablespace's location as a C-string, by its OID 28 : */ 29 : char * 30 264 : get_tablespace_location(Oid tablespaceOid) 31 : { 32 : char sourcepath[MAXPGPATH]; 33 : char targetpath[MAXPGPATH]; 34 : int rllen; 35 : struct stat st; 36 : 37 : /* 38 : * It's useful to apply this to pg_class.reltablespace, wherein zero means 39 : * "the database's default tablespace". So, rather than throwing an error 40 : * for zero, we choose to assume that's what is meant. 41 : */ 42 264 : if (tablespaceOid == InvalidOid) 43 0 : tablespaceOid = MyDatabaseTableSpace; 44 : 45 : /* 46 : * Return empty string for the cluster's default tablespaces 47 : */ 48 264 : if (tablespaceOid == DEFAULTTABLESPACE_OID || 49 : tablespaceOid == GLOBALTABLESPACE_OID) 50 186 : return pstrdup(""); 51 : 52 : /* 53 : * Find the location of the tablespace by reading the symbolic link that 54 : * is in pg_tblspc/<oid>. 55 : */ 56 78 : snprintf(sourcepath, sizeof(sourcepath), "%s/%u", PG_TBLSPC_DIR, tablespaceOid); 57 : 58 : /* 59 : * Before reading the link, check if the source path is a link or a 60 : * junction point. Note that a directory is possible for a tablespace 61 : * created with allow_in_place_tablespaces enabled. If a directory is 62 : * found, a relative path to the data directory is returned. 63 : */ 64 78 : if (lstat(sourcepath, &st) < 0) 65 0 : ereport(ERROR, 66 : errcode_for_file_access(), 67 : errmsg("could not stat file \"%s\": %m", 68 : sourcepath)); 69 : 70 78 : if (!S_ISLNK(st.st_mode)) 71 74 : return pstrdup(sourcepath); 72 : 73 : /* 74 : * In presence of a link or a junction point, return the path pointed to. 75 : */ 76 4 : rllen = readlink(sourcepath, targetpath, sizeof(targetpath)); 77 4 : if (rllen < 0) 78 0 : ereport(ERROR, 79 : errcode_for_file_access(), 80 : errmsg("could not read symbolic link \"%s\": %m", 81 : sourcepath)); 82 4 : if (rllen >= sizeof(targetpath)) 83 0 : ereport(ERROR, 84 : errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), 85 : errmsg("symbolic link \"%s\" target is too long", 86 : sourcepath)); 87 4 : targetpath[rllen] = '\0'; 88 : 89 4 : return pstrdup(targetpath); 90 : }