Commit 5532d6b3 authored by Per Cederqvist's avatar Per Cederqvist
Browse files

New file.

parent abcb3f15
# Copyright (C) 2003 Lysator Academic Computer Association.
#
# This file is part of the LysKOM server.
#
# LysKOM is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
# LysKOM is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with LysKOM; see the file COPYING. If not, write to
# Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
# or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
# MA 02139, USA.
#
# Please report bugs at http://bugzilla.lysator.liu.se/.
#
include $(top_srcdir)/scripts/common.make
EXTRA_DIST = fsusage.m4
/*
* Copyright (C) 2003 Lysator Academic Computer Association.
*
* This file is part of the LysKOM server.
*
* LysKOM is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* LysKOM is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with LysKOM; see the file COPYING. If not, write to
* Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
* or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* Please report bugs at http://bugzilla.lysator.liu.se/.
*/
/*
* checkspace.c - Check free space on db partition.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <float.h>
#include "linkansi.h"
#include "getopt.h"
#include "kom-config.h"
#include "misc-types.h"
#include "kom-types.h"
#include "param.h"
#include "version-info.h"
#include "log.h"
#include "debug.h"
#include "lyskomd.h"
#include "server-config.h"
#include "server/smalloc.h"
#include "fsusage.h"
int buglevel = 0;
BUGDECL;
static struct option longopts[] = {
{"help", 0, 0, 'h' },
{"debug", 0, 0, 'd' },
{ 0, 0, 0, 0 }
};
struct stats {
struct fs_usage filesys;
struct stat db;
struct stat backup_db;
struct stat text;
};
static int
is_nonzero(double val)
{
#ifdef FP_ZERO
return fpclassify(val) != FP_ZERO;
#else
return val >= DBL_MIN || val <= -DBL_MIN;
#endif
}
static void
usage(const char *default_config)
{
printf("checkspace for %s version %s\n",
kom_version_info.server_name,
kom_version_info.server_version);
puts("Usage: checkspace [options] [config_file]");
puts("Available options:");
puts(" -h --help Output this message and exit.");
puts(" -d --debug Only intended for use by the test suite.");
printf("The config_file argument defaults to %s\n", default_config);
exit(0);
}
static void
stat_text(struct stat *res)
{
if (stat(param.textfile_name, res) < 0)
{
fprintf(stderr, "checkspace: stat: ");
perror(param.textfile_name);
exit(2);
}
}
static void
stat_backup_db(struct stat *res)
{
int save;
/* This file will be missing on a new installation until the
database has been saved once. Fresh installations will get
this error for a while. But if this file is ever missing on a
system that has been up and running for a while it indicates a
serious error, so report this as an error. */
if (stat(param.backupfile_name, res) < 0)
{
save = errno;
fprintf(stderr, "checkspace: stat: ");
errno = save;
perror(param.backupfile_name);
if (save == ENOENT)
fprintf(stderr, "If this is a new installation this error "
"will go away after\nroughly %g minutes.\n",
param.sync_interval.tv_sec / 60.0);
exit(2);
}
}
static void
stat_db(struct stat *res)
{
int tries_left = 3;
again:
if (stat(param.datafile_name, res) == 0)
return;
if (errno == EINTR)
goto again;
if (errno == ENOENT && --tries_left > 0)
{
sleep(1);
goto again;
}
fprintf(stderr, "checkspace: stat: ");
perror(param.datafile_name);
exit(2);
}
static void
stat_partition(struct fs_usage *res)
{
if (get_fs_usage(param.textfile_name, NULL, res) < 0)
{
if (errno == 0)
{
/* I don't believe there are any such system still running
nowadays, so it isn't worth the effort to make it work.
Give a good error message in case I'm wrong. */
fprintf(stderr,
"Congratulations! You have found a "
"system that requires the DISK\n"
"argument of get_fs_usage() to be non-NULL. "
"Please report this as a bug at\n"
"http://bugzilla.lysator.liu.se/. Please "
"include \"get_fs_usage\" in the\n"
"description, and describe the system.\n");
exit(2);
}
fprintf(stderr, "checkspace: get_fs_uage: ");
perror(param.textfile_name);
exit(2);
}
}
static void
read_stats(struct stats *res)
{
stat_partition(&res->filesys);
stat_backup_db(&res->backup_db);
stat_text(&res->text);
stat_db(&res->db);
}
static int
check(double limit, double value)
{
return is_nonzero(limit) && value < limit;
}
static int
doit(void)
{
int retry = 10;
int res = 0;
double space_left;
double percent_left;
double inodes_left;
double percent_inodes_left;
struct stats prev;
struct stats current;
read_stats(&prev);
again:
read_stats(&current);
if ((current.filesys.fsu_bavail > prev.filesys.fsu_bavail
|| current.db.st_size < prev.db.st_size)
&& --retry > 0)
{
prev = current;
sleep(1);
goto again;
}
space_left = (((double)current.filesys.fsu_bavail
* current.filesys.fsu_blocksize)
+ current.db.st_size
- current.backup_db.st_size);
percent_left = 100.0 * space_left / ((double)current.filesys.fsu_blocks
* current.filesys.fsu_blocksize);
inodes_left = current.filesys.fsu_ffree;
percent_inodes_left = 100.0 * inodes_left / current.filesys.fsu_files;
printf("Diskspace ");
if (check(param.chkspc_crit_space_abs, space_left)
|| check(param.chkspc_crit_space_percent, percent_left)
|| check(param.chkspc_crit_inode_abs, inodes_left)
|| check(param.chkspc_crit_inode_percent, percent_inodes_left))
{
printf("error: ");
res = 2;
}
else if (check(param.chkspc_warn_space_abs, space_left)
|| check(param.chkspc_warn_space_percent, percent_left)
|| check(param.chkspc_warn_inode_abs, inodes_left)
|| check(param.chkspc_warn_inode_percent, percent_inodes_left))
{
printf("warning: ");
res = 1;
}
else
printf("OK: ");
printf("%g MB (%.1f%%) and %g inodes (%.1f%%) free\n",
space_left / 1024.0 / 1024.0, percent_left,
inodes_left, percent_inodes_left);
return res;
}
#if 0
printf("Size of a block: %lu\n",
(unsigned long)info.fsu_blocksize);
printf("Total blocks: %lu\n",
(unsigned long)info.fsu_blocks);
printf("Free blocks available to superuser: %lu\n",
(unsigned long)info.fsu_bfree);
printf("Free blocks available to non-superuser: %lu\n",
(unsigned long)info.fsu_bavail);
printf("1 if fsu_bavail represents a value < 0: %lu\n",
(unsigned long)info.fsu_bavail_top_bit_set);
printf("Total file nodes: %lu\n",
(unsigned long)info.fsu_files);
printf("Free file nodes: %lu\n",
(unsigned long)info.fsu_ffree);
#endif
/* Stop "no previous prototype" warning from gcc 2.0 */
int main(int, char**);
int
main (int argc,
char **argv)
{
int hflag = 0;
const char *config_file;
int optc;
int ret;
link_ansi();
#ifdef TRACED_ALLOCATIONS
/* We must do this before we allocate any memory... */
{
char buf[1024];
char *nl;
fputs("Where does the trace want to go today? [stderr]\n", stdout);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) != buf)
{
fprintf(stderr, "unable to read trace location\n");
exit(2);
}
if ((nl = strchr(buf, '\n')) != NULL)
*nl = '\0';
trace_alloc_file(buf);
}
#endif
while ((optc = getopt_long(argc, argv, "hd",
longopts, (int *) 0)) != EOF)
{
switch (optc)
{
case 'h':
hflag = 1;
break;
#ifndef NDEBUG
case 'd':
buglevel++;
break;
#endif
default:
restart_kom("Try --help for usage message.\n");
}
}
/* Check if help was requested. */
if (hflag > 0)
usage(get_default_config_file_name());
/* Continue reading in the configuration file. */
if (optind < argc)
config_file = argv[optind++];
else
config_file = get_default_config_file_name();
read_configuration(config_file);
free_default_config_file_name();
if (optind != argc)
restart_kom("%s: too many arguments. %s --help for usage.\n",
argv[0], argv[0]);
s_set_storage_management(smalloc, srealloc, sfree);
ret = doit();
/* Don't actually die until something is entered on stdin in debug
mode. This is mainly here for the benefit of the test suite,
but is could also be useful to be able to attach a debugger and
do pre-mortem debugging of the process at this point. */
if (buglevel > 0)
{
kom_log("Press enter to terminate checkspace\n");
getchar();
}
return ret;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment