]> granicus.if.org Git - postgresql/blob - contrib/dbsize/dbsize.c
has_table_privilege spawns scions has_database_privilege, has_function_privilege,
[postgresql] / contrib / dbsize / dbsize.c
1 #include "postgres.h"
2
3 #include <sys/types.h>
4 #include <dirent.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <errno.h>
8
9 #include "access/heapam.h"
10 #include "catalog/catalog.h"
11 #include "catalog/namespace.h"
12 #include "commands/dbcommands.h"
13 #include "fmgr.h"
14 #include "utils/builtins.h"
15
16
17 static char *
18 psnprintf(size_t len, const char *fmt,...)
19 {
20         va_list         ap;
21         char       *buf;
22
23         buf = palloc(len);
24
25         va_start(ap, fmt);
26         vsnprintf(buf, len, fmt, ap);
27         va_end(ap);
28
29         return buf;
30 }
31
32
33
34 /*
35  * SQL function: database_size(name) returns bigint
36  */
37
38 PG_FUNCTION_INFO_V1(database_size);
39
40 Datum database_size(PG_FUNCTION_ARGS);
41
42 Datum
43 database_size(PG_FUNCTION_ARGS)
44 {
45         Name            dbname = PG_GETARG_NAME(0);
46
47         Oid                     dbid;
48         char       *dbpath;
49         DIR                *dirdesc;
50         struct dirent *direntry;
51         int64           totalsize;
52
53         dbid = get_database_oid(NameStr(*dbname));
54         if (!OidIsValid(dbid))
55                 elog(ERROR, "database %s does not exist", NameStr(*dbname));
56
57         dbpath = GetDatabasePath(dbid);
58
59         dirdesc = opendir(dbpath);
60         if (!dirdesc)
61                 elog(ERROR, "could not open directory %s: %s", dbpath, strerror(errno));
62
63         totalsize = 0;
64         for (;;)
65         {
66                 char       *fullname;
67                 struct stat statbuf;
68
69                 errno = 0;
70                 direntry = readdir(dirdesc);
71                 if (!direntry)
72                 {
73                         if (errno)
74                                 elog(ERROR, "error reading directory: %s", strerror(errno));
75                         else
76                                 break;
77                 }
78
79                 fullname = psnprintf(strlen(dbpath) + 1 + strlen(direntry->d_name) + 1,
80                                                          "%s/%s", dbpath, direntry->d_name);
81                 if (stat(fullname, &statbuf) == -1)
82                         elog(ERROR, "could not stat %s: %s", fullname, strerror(errno));
83                 totalsize += statbuf.st_size;
84                 pfree(fullname);
85         }
86
87         closedir(dirdesc);
88
89         PG_RETURN_INT64(totalsize);
90 }
91
92
93
94 /*
95  * SQL function: relation_size(text) returns bigint
96  */
97
98 PG_FUNCTION_INFO_V1(relation_size);
99
100 Datum relation_size(PG_FUNCTION_ARGS);
101
102 Datum
103 relation_size(PG_FUNCTION_ARGS)
104 {
105         text       *relname = PG_GETARG_TEXT_P(0);
106
107         RangeVar   *relrv;
108         Relation        relation;
109         Oid                     relnode;
110         int64           totalsize;
111         unsigned int segcount;
112
113         relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
114                                                                                                                          "relation_size"));
115         relation = relation_openrv(relrv, AccessShareLock);
116
117         relnode = relation->rd_rel->relfilenode;
118
119         totalsize = 0;
120         segcount = 0;
121         for (;;)
122         {
123                 char       *fullname;
124                 struct stat statbuf;
125
126                 if (segcount == 0)
127                         fullname = psnprintf(25, "%u", (unsigned) relnode);
128                 else
129                         fullname = psnprintf(50, "%u.%u", (unsigned) relnode, segcount);
130
131                 if (stat(fullname, &statbuf) == -1)
132                 {
133                         if (errno == ENOENT)
134                                 break;
135                         else
136                                 elog(ERROR, "could not stat %s: %m", fullname);
137                 }
138                 totalsize += statbuf.st_size;
139                 pfree(fullname);
140                 segcount++;
141         }
142
143         relation_close(relation, AccessShareLock);
144
145         PG_RETURN_INT64(totalsize);
146 }