1/*
2 Copyright (c) 2017, MariaDB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17#include <my_global.h>
18#include <sys/statvfs.h>
19#include <sys/types.h>
20#include <mntent.h>
21#include <sql_class.h>
22#include <table.h>
23
24bool schema_table_store_record(THD *thd, TABLE *table);
25
26namespace
27{
28
29struct st_mysql_information_schema disks_table_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
30
31ST_FIELD_INFO disks_table_fields[]=
32{
33 { "Disk", PATH_MAX, MYSQL_TYPE_STRING, 0, 0 ,0, 0 },
34 { "Path", PATH_MAX, MYSQL_TYPE_STRING, 0, 0 ,0, 0 },
35 { "Total", 32, MYSQL_TYPE_LONG, 0, 0 ,0 ,0 }, // Total amount available
36 { "Used", 32, MYSQL_TYPE_LONG, 0, 0 ,0 ,0 }, // Amount of space used
37 { "Available", 32, MYSQL_TYPE_LONG, 0, 0 ,0 ,0 }, // Amount available to users other than root.
38 { 0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0 }
39};
40
41int disks_table_add_row(THD* pThd,
42 TABLE* pTable,
43 const char* zDisk,
44 const char* zPath,
45 const struct statvfs& info)
46{
47 // From: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
48 //
49 // f_frsize Fundamental file system block size.
50 // f_blocks Total number of blocks on file system in units of f_frsize.
51 // f_bfree Total number of free blocks.
52 // f_bavail Number of free blocks available to non-privileged process.
53
54 size_t total = (info.f_frsize * info.f_blocks) / 1024;
55 size_t used = (info.f_frsize * (info.f_blocks - info.f_bfree)) / 1024;
56 size_t avail = (info.f_frsize * info.f_bavail) / 1024;
57
58 pTable->field[0]->store(zDisk, strlen(zDisk), system_charset_info);
59 pTable->field[1]->store(zPath, strlen(zPath), system_charset_info);
60 pTable->field[2]->store(total);
61 pTable->field[3]->store(used);
62 pTable->field[4]->store(avail);
63
64 // 0 means success.
65 return (schema_table_store_record(pThd, pTable) != 0) ? 1 : 0;
66}
67
68int disks_table_add_row(THD* pThd, TABLE* pTable, const char* zDisk, const char* zPath)
69{
70 int rv = 0;
71
72 struct statvfs info;
73
74 if (statvfs(zPath, &info) == 0) // We ignore failures.
75 {
76 rv = disks_table_add_row(pThd, pTable, zDisk, zPath, info);
77 }
78
79 return rv;
80}
81
82int disks_fill_table(THD* pThd, TABLE_LIST* pTables, Item* pCond)
83{
84 int rv = 1;
85 TABLE* pTable = pTables->table;
86
87 FILE* pFile = setmntent("/etc/mtab", "r");
88
89 if (pFile)
90 {
91 const size_t BUFFER_SIZE = 4096; // 4K should be sufficient.
92
93 char* pBuffer = new (std::nothrow) char [BUFFER_SIZE];
94
95 if (pBuffer)
96 {
97 rv = 0;
98
99 struct mntent ent;
100 struct mntent* pEnt;
101
102 while ((rv == 0) && (pEnt = getmntent_r(pFile, &ent, pBuffer, BUFFER_SIZE)))
103 {
104 // We only report the ones that refer to physical disks.
105 if (pEnt->mnt_fsname[0] == '/')
106 {
107 rv = disks_table_add_row(pThd, pTable, pEnt->mnt_fsname, pEnt->mnt_dir);
108 }
109 }
110
111 delete [] pBuffer;
112 }
113 else
114 {
115 rv = 1;
116 }
117
118 endmntent(pFile);
119 }
120
121 return rv;
122}
123
124int disks_table_init(void *ptr)
125{
126 ST_SCHEMA_TABLE* pSchema_table = (ST_SCHEMA_TABLE*)ptr;
127
128 pSchema_table->fields_info = disks_table_fields;
129 pSchema_table->fill_table = disks_fill_table;
130 return 0;
131}
132
133}
134
135extern "C"
136{
137
138maria_declare_plugin(disks)
139{
140 MYSQL_INFORMATION_SCHEMA_PLUGIN,
141 &disks_table_info, /* type-specific descriptor */
142 "DISKS", /* table name */
143 "Johan Wikman", /* author */
144 "Disk space information", /* description */
145 PLUGIN_LICENSE_GPL, /* license type */
146 disks_table_init, /* init function */
147 NULL, /* deinit function */
148 0x0100, /* version = 1.0 */
149 NULL, /* no status variables */
150 NULL, /* no system variables */
151 "1.0", /* String version representation */
152 MariaDB_PLUGIN_MATURITY_BETA /* Maturity (see include/mysql/plugin.h)*/
153}
154mysql_declare_plugin_end;
155
156}
157