blob: 8f018674d1895d0caafaee89cbb3cf51ddd0a25f [file] [log] [blame]
/*
drbdadm_minor_table.c
This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
It was written by Johannes Thoma <johannes.thoma@linbit.com>
Copyright (C) 2002-2008, LINBIT Information Technologies GmbH.
Copyright (C) 2002-2008, Philipp Reisner <philipp.reisner@linbit.com>.
Copyright (C) 2002-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
drbd 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 2, or (at your option)
any later version.
drbd 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 drbd; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* This keeps track of which DRBD minor was configured in which
* config file. This is required to have alternative config files
* (-c switch) and userland event handlers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include "config.h"
#define MAX_MINOR 256
#define MAX_REGISTER_PATH_LEN 1024
/* buf has to be big enough to hold that path.
* it is assumed that sprintf cannot fail :-] */
void linkname_from_minor(char *buf, int minor)
{
sprintf(buf, "%s/drbd-minor-%d.conf", DRBD_LIB_DIR, minor);
}
int unregister_minor(int minor)
{
char buf[255];
if (minor >= MAX_MINOR || minor < 0) {
fprintf(stderr, "unregister_minor: minor too big (%d).\n", minor);
return -1;
}
linkname_from_minor(buf, minor);
if (unlink(buf) < 0) {
if (errno != ENOENT) {
perror("unlink");
return -1;
}
}
return 0;
}
int register_minor(int minor, const char *path)
{
char buf[255];
struct stat stat_buf;
int err = -1;
if (minor >= MAX_MINOR || minor < 0) {
fprintf(stderr, "register_minor: minor too big (%d).\n", minor);
return -1;
}
linkname_from_minor(buf, minor);
if (!path || !path[0])
fprintf(stderr, "Cannot register an empty path.\n");
else if (path[0] != '/')
fprintf(stderr, "Absolute path expected, "
"won't register relative path (%s).\n", path);
else if (strlen(path) >= MAX_REGISTER_PATH_LEN)
fprintf(stderr, "path (%s):\ntoo long to be registered, "
"max path len supported: %u\n",
path, MAX_REGISTER_PATH_LEN-1);
else if (stat(path, &stat_buf) < 0)
fprintf(stderr, "stat(%s): %m\n", path);
else if (unlink(buf) < 0 && errno != ENOENT)
fprintf(stderr, "unlink(%s): %m\n", buf);
else if (symlink(path, buf) < 0)
fprintf(stderr, "symlink(%s, %s): %m\n", path, buf);
else
/* it did work out after all! */
err = 0;
return err;
}
/* This returns a static buffer containing the real
* configuration file known to be used last for this minor.
* If you need the return value longer, stuff it away with strdup. */
char *lookup_minor(int minor)
{
static char buf[255];
static char resolved_path[MAX_REGISTER_PATH_LEN+1];
struct stat stat_buf;
ssize_t len;
if (minor >= MAX_MINOR || minor < 0) {
fprintf(stderr, "register_minor: minor too big (%d).\n", minor);
return NULL;
}
linkname_from_minor(buf, minor);
if (stat(buf, &stat_buf) < 0) {
if (errno != ENOENT)
fprintf(stderr, "stat(%s): %m\n", buf);
return NULL;
}
len = readlink(buf, resolved_path, sizeof(resolved_path)-1);
if (len < 0) {
perror("readlink");
return NULL;
}
if (len >= MAX_REGISTER_PATH_LEN)
fprintf(stderr, "readlink(%s): result has probably been truncated\n",
buf);
resolved_path[len] = '\0';
return resolved_path;
}
#ifdef TEST
int main(int argc, char ** argv)
{
register_minor(1, "/etc/drbd-xy.conf");
register_minor(15, "/etc/drbd-82.conf");
register_minor(14, "/../../../../../../etc/drbd-82.conf");
printf("Minor 1 is %s.\n", lookup_minor(1));
printf("Minor 2 is %s.\n", lookup_minor(2));
printf("Minor 14 is %s.\n", lookup_minor(14));
printf("Minor 15 is %s.\n", lookup_minor(15));
return 0;
}
#endif