17
17
#include < my_global.h>
18
18
#include < sys/statvfs.h>
19
19
#include < sys/types.h>
20
+ #if defined(HAVE_GETMNTENT)
20
21
#include < mntent.h>
22
+ #elif !defined(HAVE_GETMNTINFO_TAKES_statvfs)
23
+ /* getmntinfo (the not NetBSD variants) */
24
+ #include < sys/param.h>
25
+ #include < sys/ucred.h>
26
+ #include < sys/mount.h>
27
+ #endif
28
+ #if defined(HAVE_GETMNTENT_IN_SYS_MNTAB)
29
+ #include < sys/mnttab.h>
30
+ #define HAVE_GETMNTENT
31
+ #endif
21
32
#include < sql_class.h>
22
33
#include < table.h>
23
34
#include < sql_acl.h> /* check_global_access() */
24
35
36
+ /*
37
+ This intends to support *BSD's, macOS, Solaris, AIX, HP-UX, and Linux.
38
+
39
+ specificly:
40
+ FreeBSD/OpenBSD/DragonFly (statfs) NetBSD (statvfs) uses getmntinfo().
41
+ macOS uses getmntinfo64().
42
+ Linux can use getmntent_r(), but we've just used getmntent for simplification.
43
+ Linux/Solaris/AIX/HP-UX uses setmntent()/getmntent().
44
+ Solaris uses getmntent() with a diffent prototype, return structure, and
45
+ no setmntent(fopen instead)
46
+ */
47
+ #if defined(HAVE_GETMNTINFO_TAKES_statvfs) || defined(HAVE_GETMNTENT)
48
+ typedef struct statvfs st_info;
49
+ #elif defined(HAVE_GETMNTINFO64)
50
+ typedef struct statfs64 st_info;
51
+ #else // GETMNTINFO
52
+ typedef struct statfs st_info;
53
+ #endif
54
+ #ifndef MOUNTED
55
+ /* HPUX - https://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/getmntent.3X.html */
56
+ #define MOUNTED MNT_MNTTAB
57
+ #endif
58
+
25
59
bool schema_table_store_record (THD *thd, TABLE *table);
26
60
27
61
namespace
@@ -39,23 +73,40 @@ ST_FIELD_INFO disks_table_fields[]=
39
73
{ 0 , 0 , MYSQL_TYPE_NULL, 0 , 0 , 0 , 0 }
40
74
};
41
75
42
- int disks_table_add_row (THD* pThd,
43
- TABLE* pTable,
44
- const char * zDisk,
45
- const char * zPath,
46
- const struct statvfs & info)
76
+ static int disks_table_add_row_stat (
77
+ THD* pThd,
78
+ TABLE* pTable,
79
+ const char * zDisk,
80
+ const char * zPath,
81
+ const st_info &info)
47
82
{
48
83
// From: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html
84
+ // and same for statfs:
85
+ // From: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/statfs.2.html#//apple_ref/doc/man/2/statfs
86
+ // and: https://www.freebsd.org/cgi/man.cgi?query=statfs&sektion=2&apropos=0&manpath=FreeBSD+13.1-RELEASE+and+Ports
49
87
//
50
- // f_frsize Fundamental file system block size.
88
+ // f_bsize Fundamental file system block size.
51
89
// f_blocks Total number of blocks on file system in units of f_frsize.
52
90
// f_bfree Total number of free blocks.
53
91
// f_bavail Number of free blocks available to non-privileged process.
92
+ ulong block_size= (ulong) info.f_bsize ;
54
93
55
- ulonglong total = ((ulonglong)info. f_frsize * info.f_blocks ) / 1024 ;
56
- ulonglong used = ((ulonglong)info. f_frsize *
94
+ ulonglong total = ((ulonglong) block_size * info.f_blocks ) / 1024 ;
95
+ ulonglong used = ((ulonglong) block_size *
57
96
(info.f_blocks - info.f_bfree )) / 1024 ;
58
- ulonglong avail = ((ulonglong)info.f_frsize * info.f_bavail ) / 1024 ;
97
+ ulonglong avail = ((ulonglong) block_size * info.f_bavail ) / 1024 ;
98
+
99
+ /* skip filesystems that don't have any space */
100
+ if (!info.f_blocks )
101
+ return 0 ;
102
+
103
+ /* skip RO mounted filesystems */
104
+ #if defined(HAVE_GETMNTINFO_TAKES_statvfs) || defined(HAVE_GETMNTENT)
105
+ if (info.f_flag & ST_RDONLY)
106
+ #else
107
+ if (info.f_flags & MNT_RDONLY)
108
+ #endif
109
+ return 0 ;
59
110
60
111
pTable->field [0 ]->store (zDisk, strlen (zDisk), system_charset_info);
61
112
pTable->field [1 ]->store (zPath, strlen (zPath), system_charset_info);
@@ -67,71 +118,147 @@ int disks_table_add_row(THD* pThd,
67
118
return (schema_table_store_record (pThd, pTable) != 0 ) ? 1 : 0 ;
68
119
}
69
120
70
- int disks_table_add_row (THD* pThd, TABLE* pTable, const char * zDisk, const char * zPath)
121
+
122
+ #ifdef HAVE_GETMNTENT
123
+ static int disks_table_add_row (THD* pThd, TABLE* pTable, const char * zDisk, const char * zPath)
71
124
{
72
125
int rv = 0 ;
73
126
74
- struct statvfs info;
127
+ st_info info;
75
128
76
129
if (statvfs (zPath, &info) == 0 ) // We ignore failures.
77
130
{
78
- rv = disks_table_add_row (pThd, pTable, zDisk, zPath, info);
131
+ rv = disks_table_add_row_stat (pThd, pTable, zDisk, zPath, info);
79
132
}
80
133
81
134
return rv;
82
135
}
136
+ #endif
83
137
84
- int disks_fill_table (THD* pThd, TABLE_LIST* pTables, Item* pCond)
138
+
139
+ #ifdef HAVE_GETMNTINFO
140
+ static int disks_fill_table (THD* pThd, TABLE_LIST* pTables, Item* pCond)
85
141
{
86
- int rv = 1 ;
87
- TABLE* pTable = pTables->table ;
142
+ st_info *s;
143
+ int count, rv= 0 ;
144
+ TABLE* pTable= pTables->table ;
88
145
89
146
if (check_global_access (pThd, FILE_ACL, true ))
90
- return 0 ;
147
+ return 0 ;
148
+
149
+ #if defined(HAVE_GETMNTINFO_TAKES_statvfs)
150
+ count= getmntinfo (&s, ST_WAIT);
151
+ #elif defined(HAVE_GETMNTINFO64)
152
+ count= getmntinfo64 (&s, MNT_WAIT);
153
+ #else
154
+ count= getmntinfo (&s, MNT_WAIT);
155
+ #endif
156
+ if (count == 0 )
157
+ return 1 ;
158
+
159
+ while (count && rv == 0 )
160
+ {
161
+ rv= disks_table_add_row_stat (pThd, pTable, s->f_mntfromname , s->f_mntonname , *s);
162
+ count--;
163
+ s++;
164
+ }
165
+ return rv;
166
+ }
167
+ #else /* HAVE_GETMNTINFO */
168
+
169
+ static mysql_mutex_t m_getmntent;
91
170
92
- FILE* pFile = setmntent (" /etc/mtab" , " r" );
171
+ /* HAVE_GETMNTENT */
172
+ static int disks_fill_table (THD* pThd, TABLE_LIST* pTables, Item* pCond)
173
+ {
174
+ int rv= 1 ;
175
+ #ifdef HAVE_SETMNTENT
176
+ struct mntent * pEnt;
177
+ #else
178
+ struct mnttab mnttabent, *pEnt= &mnttabent;
179
+ #endif
180
+ FILE* pFile;
181
+ TABLE* pTable= pTables->table ;
93
182
94
- if (pFile)
183
+ if (check_global_access (pThd, FILE_ACL, true ))
184
+ return 0 ;
185
+
186
+ #ifdef HAVE_SETMNTENT
187
+ pFile= setmntent (MOUNTED, " r" );
188
+ #else
189
+ /* Solaris */
190
+ pFile= fopen (" /etc/mnttab" , " r" );
191
+ #endif
192
+
193
+ if (!pFile)
194
+ return 1 ;
195
+
196
+ rv= 0 ;
197
+
198
+ /*
199
+ We lock the outer loop rather than between getmntent so the multiple
200
+ infomation_schema.disks reads don't all start blocking each other and
201
+ no-one gets any answers.
202
+ */
203
+ mysql_mutex_lock (&m_getmntent);
204
+
205
+ while ((rv == 0 ) &&
206
+ #if defined(HAVE_SETMNTENT)
207
+ (pEnt = getmntent (pFile))
208
+
209
+ #else
210
+ getmntent (pFile, pEnt) != 0
211
+ #endif
212
+ )
95
213
{
96
- const size_t BUFFER_SIZE = 4096 ; // 4K should be sufficient.
97
-
98
- char * pBuffer = new (std::nothrow) char [BUFFER_SIZE];
99
-
100
- if (pBuffer)
101
- {
102
- rv = 0 ;
103
-
104
- struct mntent ent;
105
- struct mntent * pEnt;
106
-
107
- while ((rv == 0 ) && (pEnt = getmntent_r (pFile, &ent, pBuffer, BUFFER_SIZE)))
108
- {
109
- // We only report the ones that refer to physical disks.
110
- if (pEnt->mnt_fsname [0 ] == ' /' )
111
- {
112
- rv = disks_table_add_row (pThd, pTable, pEnt->mnt_fsname , pEnt->mnt_dir );
113
- }
114
- }
115
-
116
- delete [] pBuffer;
117
- }
118
- else
119
- {
120
- rv = 1 ;
121
- }
122
-
123
- endmntent (pFile);
214
+ struct stat f;
215
+ const char *path, *point;
216
+ #ifdef HAVE_SETMNTENT
217
+ path= pEnt->mnt_dir ;
218
+ point= pEnt->mnt_fsname ;
219
+ #else
220
+ path= pEnt->mnt_mountp ;
221
+ point= pEnt->mnt_special ;
222
+ #endif
223
+ // Try to keep to real storage by excluding
224
+ // read only mounts, and mount points that aren't directories
225
+ if (hasmntopt (pEnt, MNTOPT_RO) != NULL )
226
+ continue ;
227
+ if (stat (path, &f))
228
+ continue ;
229
+ if (!S_ISDIR (f.st_mode ))
230
+ continue ;
231
+ rv= disks_table_add_row (pThd, pTable, point, path);
124
232
}
233
+ mysql_mutex_unlock (&m_getmntent);
234
+
235
+ #ifdef HAVE_SETMNTENT
236
+ endmntent (pFile);
237
+ #else
238
+ fclose (pFile);
239
+ #endif
125
240
126
241
return rv;
127
242
}
243
+ #endif /* HAVE_GETMNTINFO */
128
244
129
- int disks_table_init (void *ptr)
245
+ static int disks_table_init (void *ptr)
130
246
{
131
247
ST_SCHEMA_TABLE* pSchema_table = (ST_SCHEMA_TABLE*)ptr;
132
248
133
249
pSchema_table->fields_info = disks_table_fields;
134
250
pSchema_table->fill_table = disks_fill_table;
251
+ #ifndef HAVE_GETMNTINFO
252
+ mysql_mutex_init (0 , &m_getmntent, MY_MUTEX_INIT_SLOW);
253
+ #endif
254
+ return 0 ;
255
+ }
256
+
257
+ static int disks_table_deinit (void *ptr __attribute__ ((unused)))
258
+ {
259
+ #ifndef HAVE_GETMNTINFO
260
+ mysql_mutex_destroy (&m_getmntent);
261
+ #endif
135
262
return 0 ;
136
263
}
137
264
@@ -145,15 +272,15 @@ maria_declare_plugin(disks)
145
272
MYSQL_INFORMATION_SCHEMA_PLUGIN,
146
273
&disks_table_info, /* type-specific descriptor */
147
274
" DISKS" , /* table name */
148
- " Johan Wikman" , /* author */
275
+ " Johan Wikman, Daniel Black " , /* author */
149
276
" Disk space information" , /* description */
150
277
PLUGIN_LICENSE_GPL, /* license type */
151
278
disks_table_init, /* init function */
152
- NULL , /* deinit function */
153
- 0x0101 , /* version = 1.1 */
279
+ disks_table_deinit, /* deinit function */
280
+ 0x0102 , /* version = 1.2 */
154
281
NULL , /* no status variables */
155
282
NULL , /* no system variables */
156
- " 1.1 " , /* String version representation */
283
+ " 1.2 " , /* String version representation */
157
284
MariaDB_PLUGIN_MATURITY_STABLE /* Maturity (see include/mysql/plugin.h)*/
158
285
}
159
286
mysql_declare_plugin_end;
0 commit comments