Age Owner Branch data TLA 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 *
34 alvherre@kurilemu.de 30 :GNC 138 : 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 [ - + ]: 138 : if (tablespaceOid == InvalidOid)
34 alvherre@kurilemu.de 43 :UNC 0 : tablespaceOid = MyDatabaseTableSpace;
44 : :
45 : : /*
46 : : * Return empty string for the cluster's default tablespaces
47 : : */
34 alvherre@kurilemu.de 48 [ + + - + ]:GNC 138 : 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 : 39 : 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 [ - + ]: 39 : if (lstat(sourcepath, &st) < 0)
34 alvherre@kurilemu.de 65 [ # # ]:UNC 0 : ereport(ERROR,
66 : : errcode_for_file_access(),
67 : : errmsg("could not stat file \"%s\": %m",
68 : : sourcepath));
69 : :
34 alvherre@kurilemu.de 70 [ + + ]:GNC 39 : 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 : 2 : rllen = readlink(sourcepath, targetpath, sizeof(targetpath));
77 [ - + ]: 2 : if (rllen < 0)
34 alvherre@kurilemu.de 78 [ # # ]:UNC 0 : ereport(ERROR,
79 : : errcode_for_file_access(),
80 : : errmsg("could not read symbolic link \"%s\": %m",
81 : : sourcepath));
34 alvherre@kurilemu.de 82 [ - + ]:GNC 2 : if (rllen >= sizeof(targetpath))
34 alvherre@kurilemu.de 83 [ # # ]:UNC 0 : ereport(ERROR,
84 : : errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
85 : : errmsg("symbolic link \"%s\" target is too long",
86 : : sourcepath));
34 alvherre@kurilemu.de 87 :GNC 2 : targetpath[rllen] = '\0';
88 : :
89 : 2 : return pstrdup(targetpath);
90 : : }
|