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-2026, 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 156 : 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 156 : if (tablespaceOid == InvalidOid)
43 0 : tablespaceOid = MyDatabaseTableSpace;
44 :
45 : /*
46 : * Return empty string for the cluster's default tablespaces
47 : */
48 156 : if (tablespaceOid == DEFAULTTABLESPACE_OID ||
49 : tablespaceOid == GLOBALTABLESPACE_OID)
50 99 : 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 57 : 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 57 : 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 57 : if (!S_ISLNK(st.st_mode))
71 37 : return pstrdup(sourcepath);
72 :
73 : /*
74 : * In presence of a link or a junction point, return the path pointed to.
75 : */
76 20 : rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
77 20 : if (rllen < 0)
78 0 : ereport(ERROR,
79 : errcode_for_file_access(),
80 : errmsg("could not read symbolic link \"%s\": %m",
81 : sourcepath));
82 20 : 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 20 : targetpath[rllen] = '\0';
88 :
89 20 : return pstrdup(targetpath);
90 : }
|