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