d0acc47f68a9f5379800582fe725cbaf4dc5abd7
[nfs-utils.git] / tools / nlmtest / nlmtest.c
1 /*
2  * nlmtest
3  *
4  * Simple tool for NLM testing. You will have to adjust the values in
5  * host.h to your test system.
6  *
7  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
8  */
9
10 #include "config.h"
11
12 #include <sys/stat.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <nfs/nfs.h>
18 #include <getopt.h>
19 #include "nlm_prot.h"
20 #include "host.h"
21
22 static char             myhostname[256];
23 static int              hostnamelen;
24
25 static void             makelock(struct nlm_lock *, u_int32_t, off_t, off_t);
26 static void             makeowner(struct netobj *, u_int32_t);
27 static void             makefileh(struct netobj *);
28 static char *           nlm_stat_name(int status);
29 static char *           holderstr(struct netobj *oh);
30
31 int
32 main(int argc, char **argv)
33 {
34         CLIENT          *client;
35         nlm_testargs    testargs;
36         nlm_lockargs    lockargs;
37         nlm_unlockargs  unlockargs;
38         nlm_lock        alock;
39         nlm_testres     *testres;
40         nlm_res         *lockres;
41         char            *filename = NLMTEST_FILE;
42         char            *svchost = NLMTEST_HOST;
43         unsigned long   offset = 0, length = 0;
44         int             exclusive = 0;
45         int             blocking = 0;
46         int             unlock = 0;
47         u_int32_t               cookie = 4321;
48         u_int32_t               mypid = 1234;
49         int             c;
50
51         while ((c = getopt(argc, argv, "bf:h:l:o:p:ux")) != EOF) {
52                 switch(c) {
53                 case 'b':
54                         blocking = 1;
55                         break;
56                 case 'f':
57                         filename = optarg;
58                         break;
59                 case 'h':
60                         svchost = optarg;
61                         break;
62                 case 'l':
63                         length = atoi(optarg);
64                         break;
65                 case 'o':
66                         offset = atoi(optarg);
67                         break;
68                 case 'p':
69                         mypid = atoi(optarg);
70                         break;
71                 case 'u':
72                         unlock = 1;
73                         break;
74                 case 'x':
75                         exclusive = 1;
76                         break;
77                 default:
78                         fprintf(stderr, "nlmtest: bad option %c\n", c);
79                         exit (2);
80                 }
81         }
82
83         client = clnt_create(svchost, NLM_PROG, NLM_VERS, "udp");
84         if (client == NULL) {
85                 clnt_pcreateerror("localhost");
86                 exit(1);
87         }
88
89         /* Get local host name */
90         if (gethostname(myhostname, sizeof(myhostname)) < 0)
91                 strcpy(myhostname, "unknown");
92         hostnamelen = strlen(myhostname);
93
94         makelock(&alock, mypid, offset, length);
95
96         testargs.cookie.n_bytes = (void*)&cookie;
97         testargs.cookie.n_len   = 4;
98         testargs.exclusive      = exclusive;
99         testargs.alock          = alock;
100
101         if ((testres = nlm_test_1(&testargs, client)) == NULL) {
102                 clnt_perror(client, "nlm_test call failed:");
103                 exit (1);
104         }
105         printf ("nlm_test reply:\n"
106                 "\tcookie:      %d\n"
107                 "\tstatus:      %s\n",
108                         *(int*)(testres->cookie.n_bytes),
109                         nlm_stat_name(testres->stat.stat)
110                 );
111
112         if (testres->stat.stat == nlm_denied) {
113                 nlm_holder *holder = &(testres->stat.nlm_testrply_u.holder);
114                 printf ("\tconflicting lock:\n"
115                         "\t oh:         %s\n"
116                         "\t pid:        %d\n"
117                         "\t offset:     %d\n"
118                         "\t length:     %d\n"
119                         "\t exclusive:  %d\n",
120                         holderstr(&holder->oh),
121                         holder->svid,
122                         holder->l_offset,
123                         holder->l_len,
124                         holder->exclusive);
125         }
126
127         if (testres->stat.stat != nlm_granted && !unlock && !blocking)
128                 return 1;
129
130         if (unlock) {
131                 unlockargs.cookie.n_bytes = (void*)&cookie;
132                 unlockargs.cookie.n_len   = sizeof(cookie);
133                 unlockargs.alock          = alock;
134
135                 if ((lockres = nlm_unlock_1(&unlockargs, client)) == NULL) {
136                         clnt_perror(client, "nlm_unlock call failed:");
137                         exit (1);
138                 }
139                 printf ("nlm_unlock reply:\n"
140                         "\tcookie:      %d\n"
141                         "\tstatus:      %s\n",
142                                 *(int*)(lockres->cookie.n_bytes),
143                                 nlm_stat_name(lockres->stat.stat)
144                         );
145         } else {
146                 lockargs.cookie.n_bytes = (void*)&cookie;
147                 lockargs.cookie.n_len   = sizeof(cookie);
148                 lockargs.exclusive      = exclusive;
149                 lockargs.alock          = alock;
150                 lockargs.reclaim        = 0;
151                 lockargs.state          = 0;
152
153                 if ((lockres = nlm_lock_1(&lockargs, client)) == NULL) {
154                         clnt_perror(client, "nlm_lock call failed:");
155                         exit (1);
156                 }
157                 printf ("nlm_lock reply:\n"
158                         "\tcookie:      %d\n"
159                         "\tstatus:      %s\n",
160                                 *(int*)(lockres->cookie.n_bytes),
161                                 nlm_stat_name(lockres->stat.stat)
162                         );
163         }
164
165         return 0;
166 }
167
168 static char *
169 nlm_stat_name(int status)
170 {
171         static char     buf[12];
172
173         switch (status) {
174         case nlm_granted:
175                 return "nlm_granted";
176         case nlm_denied:
177                 return "nlm_denied";
178         case nlm_denied_nolocks:
179                 return "nlm_denied_nolocks";
180         case nlm_blocked:
181                 return "nlm_blocked";
182         case nlm_denied_grace_period:
183                 return "nlm_denied_grace_period";
184         }
185         sprintf(buf, "%d", status);
186         return buf;
187 }
188
189 static char *
190 holderstr(struct netobj *oh)
191 {
192         static char     buffer[4096];
193         unsigned char   c, *sp;
194         int             i;
195
196         for (i = 0, sp = buffer; i < oh->n_len; i++) {
197                 c = (unsigned char) oh->n_bytes[i];
198                 if (c < 0x20 || c > 0x7f)
199                         sp += sprintf(sp, "\\%03o", c);
200                 else
201                         *sp++ = c;
202         }
203         *sp++ = '\0';
204
205         return buffer;
206 }
207
208 static void
209 makelock(struct nlm_lock *alock, u_int32_t mypid, off_t offset, off_t length)
210 {
211         makeowner(&alock->oh, mypid);   /* Create owner handle */
212         makefileh(&alock->fh);          /* Create file handle */
213
214         alock->caller_name = myhostname;
215         alock->svid        = mypid;
216         alock->l_offset    = offset;
217         alock->l_len       = length;
218 }
219
220 static void
221 makeowner(struct netobj *oh, u_int32_t mypid)
222 {
223         static char     ohdata[1024];
224
225         oh->n_bytes = ohdata;
226         oh->n_len   = hostnamelen + 1 + 4;
227
228         strcpy(ohdata, myhostname);
229         memcpy(ohdata + hostnamelen + 1, &mypid, 4);
230 }
231
232 static void
233 makefileh(struct netobj *fh)
234 {
235         static struct knfs_fh   f;
236         struct stat             stb;
237 #error this needs updating if it is still wanted
238         memset(&f, 0, sizeof(f));
239 #if 0
240         if (stat(NLMTEST_DIR, &stb) < 0) {
241                 perror("couldn't stat mount point " NLMTEST_DIR);
242                 exit(1);
243         }
244         f.fh_xdev = stb.st_dev;
245         f.fh_xino = stb.st_ino;
246
247         if (stat(NLMTEST_DIR, &stb) < 0) {
248                 perror("couldn't stat mount point " NLMTEST_DIR);
249                 exit(1);
250         }
251         f.fh_dev = stb.st_dev;
252         f.fh_ino = stb.st_ino;
253
254         f.fh_version = NLMTEST_VERSION;
255 #else
256         f.fh_xdev = 0x801;
257         f.fh_xino = 37596;
258         f.fh_dev  = 0x801;
259         f.fh_ino  = 37732;
260 #endif
261
262         fh->n_len   = 32;
263         fh->n_bytes = (void *) &f;
264 }