C
для тех, кто все еще хочет, чтобы инструмент проверял свободное пространство на сервере postgresql. Только для Linux и FreeBSD в настоящее время необходимо добавить соответствующие заголовки и определить для других ОС.
#if defined __FreeBSD__
# include <sys/param.h>
# include <sys/mount.h>
#elif defined __linux__
# define _XOPEN_SOURCE
# define _BSD_SOURCE
# include <sys/vfs.h>
#else
# error Unsupported OS
#endif
#include <postgres.h>
#include <catalog/pg_type.h>
#include <funcapi.h>
#include <utils/builtins.h>
/* Registration:
CREATE FUNCTION disk_free(path TEXT) RETURNS TABLE (
size BIGINT, free BIGINT, available BIGINT, inodes INTEGER, ifree INTEGER, blksize INTEGER
) AS '$pglib/pg_df.so', 'df' LANGUAGE c STRICT;
*/
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(df);
Datum df(PG_FUNCTION_ARGS)
{
TupleDesc tupdesc;
AttInMetadata *attinmeta;
HeapTuple tuple;
Datum result;
char **values;
struct statfs sfs;
const char* path = text_to_cstring(PG_GETARG_TEXT_P(0));
if(get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record")));
attinmeta = TupleDescGetAttInMetadata(tupdesc);
if(0 != statfs(path, &sfs))
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("statfs() system call failed: %m")));
values = (char **) palloc(6 * sizeof(char *));
values[0] = (char *) palloc(20 * sizeof(char));
values[1] = (char *) palloc(20 * sizeof(char));
values[2] = (char *) palloc(20 * sizeof(char));
values[3] = (char *) palloc(10 * sizeof(char));
values[4] = (char *) palloc(10 * sizeof(char));
values[5] = (char *) palloc(10 * sizeof(char));
int64 df_total_bytes = sfs.f_blocks * sfs.f_bsize;
int64 df_free_bytes = sfs.f_bfree * sfs.f_bsize;
int64 df_avail_bytes = sfs.f_bavail * sfs.f_bsize;
snprintf(values[0], 20, "%lld", df_total_bytes);
snprintf(values[1], 20, "%lld", df_free_bytes);
snprintf(values[2], 20, "%lld", df_avail_bytes);
snprintf(values[3], 10, "%d", sfs.f_files);
snprintf(values[4], 10, "%d", sfs.f_ffree);
snprintf(values[5], 10, "%d", sfs.f_bsize);
tuple = BuildTupleFromCStrings(attinmeta, values);
return HeapTupleGetDatum(tuple);
}