blob: d0acc47f68a9f5379800582fe725cbaf4dc5abd7 [file] [log] [blame]
/*
* nlmtest
*
* Simple tool for NLM testing. You will have to adjust the values in
* host.h to your test system.
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#include "config.h"
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <nfs/nfs.h>
#include <getopt.h>
#include "nlm_prot.h"
#include "host.h"
static char myhostname[256];
static int hostnamelen;
static void makelock(struct nlm_lock *, u_int32_t, off_t, off_t);
static void makeowner(struct netobj *, u_int32_t);
static void makefileh(struct netobj *);
static char * nlm_stat_name(int status);
static char * holderstr(struct netobj *oh);
int
main(int argc, char **argv)
{
CLIENT *client;
nlm_testargs testargs;
nlm_lockargs lockargs;
nlm_unlockargs unlockargs;
nlm_lock alock;
nlm_testres *testres;
nlm_res *lockres;
char *filename = NLMTEST_FILE;
char *svchost = NLMTEST_HOST;
unsigned long offset = 0, length = 0;
int exclusive = 0;
int blocking = 0;
int unlock = 0;
u_int32_t cookie = 4321;
u_int32_t mypid = 1234;
int c;
while ((c = getopt(argc, argv, "bf:h:l:o:p:ux")) != EOF) {
switch(c) {
case 'b':
blocking = 1;
break;
case 'f':
filename = optarg;
break;
case 'h':
svchost = optarg;
break;
case 'l':
length = atoi(optarg);
break;
case 'o':
offset = atoi(optarg);
break;
case 'p':
mypid = atoi(optarg);
break;
case 'u':
unlock = 1;
break;
case 'x':
exclusive = 1;
break;
default:
fprintf(stderr, "nlmtest: bad option %c\n", c);
exit (2);
}
}
client = clnt_create(svchost, NLM_PROG, NLM_VERS, "udp");
if (client == NULL) {
clnt_pcreateerror("localhost");
exit(1);
}
/* Get local host name */
if (gethostname(myhostname, sizeof(myhostname)) < 0)
strcpy(myhostname, "unknown");
hostnamelen = strlen(myhostname);
makelock(&alock, mypid, offset, length);
testargs.cookie.n_bytes = (void*)&cookie;
testargs.cookie.n_len = 4;
testargs.exclusive = exclusive;
testargs.alock = alock;
if ((testres = nlm_test_1(&testargs, client)) == NULL) {
clnt_perror(client, "nlm_test call failed:");
exit (1);
}
printf ("nlm_test reply:\n"
"\tcookie: %d\n"
"\tstatus: %s\n",
*(int*)(testres->cookie.n_bytes),
nlm_stat_name(testres->stat.stat)
);
if (testres->stat.stat == nlm_denied) {
nlm_holder *holder = &(testres->stat.nlm_testrply_u.holder);
printf ("\tconflicting lock:\n"
"\t oh: %s\n"
"\t pid: %d\n"
"\t offset: %d\n"
"\t length: %d\n"
"\t exclusive: %d\n",
holderstr(&holder->oh),
holder->svid,
holder->l_offset,
holder->l_len,
holder->exclusive);
}
if (testres->stat.stat != nlm_granted && !unlock && !blocking)
return 1;
if (unlock) {
unlockargs.cookie.n_bytes = (void*)&cookie;
unlockargs.cookie.n_len = sizeof(cookie);
unlockargs.alock = alock;
if ((lockres = nlm_unlock_1(&unlockargs, client)) == NULL) {
clnt_perror(client, "nlm_unlock call failed:");
exit (1);
}
printf ("nlm_unlock reply:\n"
"\tcookie: %d\n"
"\tstatus: %s\n",
*(int*)(lockres->cookie.n_bytes),
nlm_stat_name(lockres->stat.stat)
);
} else {
lockargs.cookie.n_bytes = (void*)&cookie;
lockargs.cookie.n_len = sizeof(cookie);
lockargs.exclusive = exclusive;
lockargs.alock = alock;
lockargs.reclaim = 0;
lockargs.state = 0;
if ((lockres = nlm_lock_1(&lockargs, client)) == NULL) {
clnt_perror(client, "nlm_lock call failed:");
exit (1);
}
printf ("nlm_lock reply:\n"
"\tcookie: %d\n"
"\tstatus: %s\n",
*(int*)(lockres->cookie.n_bytes),
nlm_stat_name(lockres->stat.stat)
);
}
return 0;
}
static char *
nlm_stat_name(int status)
{
static char buf[12];
switch (status) {
case nlm_granted:
return "nlm_granted";
case nlm_denied:
return "nlm_denied";
case nlm_denied_nolocks:
return "nlm_denied_nolocks";
case nlm_blocked:
return "nlm_blocked";
case nlm_denied_grace_period:
return "nlm_denied_grace_period";
}
sprintf(buf, "%d", status);
return buf;
}
static char *
holderstr(struct netobj *oh)
{
static char buffer[4096];
unsigned char c, *sp;
int i;
for (i = 0, sp = buffer; i < oh->n_len; i++) {
c = (unsigned char) oh->n_bytes[i];
if (c < 0x20 || c > 0x7f)
sp += sprintf(sp, "\\%03o", c);
else
*sp++ = c;
}
*sp++ = '\0';
return buffer;
}
static void
makelock(struct nlm_lock *alock, u_int32_t mypid, off_t offset, off_t length)
{
makeowner(&alock->oh, mypid); /* Create owner handle */
makefileh(&alock->fh); /* Create file handle */
alock->caller_name = myhostname;
alock->svid = mypid;
alock->l_offset = offset;
alock->l_len = length;
}
static void
makeowner(struct netobj *oh, u_int32_t mypid)
{
static char ohdata[1024];
oh->n_bytes = ohdata;
oh->n_len = hostnamelen + 1 + 4;
strcpy(ohdata, myhostname);
memcpy(ohdata + hostnamelen + 1, &mypid, 4);
}
static void
makefileh(struct netobj *fh)
{
static struct knfs_fh f;
struct stat stb;
#error this needs updating if it is still wanted
memset(&f, 0, sizeof(f));
#if 0
if (stat(NLMTEST_DIR, &stb) < 0) {
perror("couldn't stat mount point " NLMTEST_DIR);
exit(1);
}
f.fh_xdev = stb.st_dev;
f.fh_xino = stb.st_ino;
if (stat(NLMTEST_DIR, &stb) < 0) {
perror("couldn't stat mount point " NLMTEST_DIR);
exit(1);
}
f.fh_dev = stb.st_dev;
f.fh_ino = stb.st_ino;
f.fh_version = NLMTEST_VERSION;
#else
f.fh_xdev = 0x801;
f.fh_xino = 37596;
f.fh_dev = 0x801;
f.fh_ino = 37732;
#endif
fh->n_len = 32;
fh->n_bytes = (void *) &f;
}