/* * 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 */ #include "config.h" #include #include #include #include #include #include #include #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; }