1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <rpc/rpc.h>
28 #include <rpc/clnt.h>
29 #include <rpc/clnt_soc.h>
30 #include "nfs4_prot.h"
31 #include "nfstcl4.h"
32
33 /* nfsv4 operations table */
34 NFSOP nfs_op[] = {
35 {"Access", Access },
36 {"Close", Close },
37 {"Commit", Commit },
38 {"Create", Create },
39 {"Delegpurge", Delegpurge},
40 {"Delegreturn", Delegreturn},
41 {"Getattr", Getattr },
42 {"Getfh", Getfh },
43 {"Illegal", Illegal },
44 {"Link", Link },
45 {"Lock", Lock },
46 {"Lockt", Lockt },
47 {"Locku", Locku },
48 {"Lookup", Lookup },
49 {"Lookupp", Lookupp },
50 {"Nverify", Nverify },
51 {"Open", Open },
52 {"Openattr", Openattr},
53 {"Open_confirm", Open_confirm},
54 {"Open_downgrade", Open_downgrade},
55 {"Putfh", Putfh },
56 {"Putpubfh", Putpubfh},
57 {"Putrootfh", Putrootfh},
58 {"Read", Read },
59 {"Readdir", Readdir },
60 {"Readlink", Readlink},
61 {"Release_lockowner", Release_lockowner},
62 {"Remove", Remove },
63 {"Rename", Rename },
64 {"Renew", Renew },
65 {"Restorefh", Restorefh},
66 {"Savefh", Savefh },
67 {"Secinfo", Secinfo },
68 {"Setattr", Setattr },
69 {"Setclientid", Setclientid},
70 {"Setclientid_confirm", Setclientid_confirm},
71 {"Verify", Verify },
72 {"Write", Write },
73 {0, 0 },
74 };
75
76 /* ------------------------------ */
77 /* Operation request functions. */
78 /* ------------------------------ */
79
80 int
81 Access(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
82 {
83 uint32_t access;
84 char *acl, ac;
85
86 nfs_argop4 *opp = new_argop();
87
88 if (argc != 2) {
89 interp->result = "Usage: Access { rlmtdx i(0x100) }";
90 return (TCL_ERROR);
91 }
92
93 opp->argop = OP_ACCESS;
94
95 access = (uint32_t)0;
96 substitution(interp, argv[1]);
97 argv[1] = interp->result;
98 acl = argv[1];
99 while ((ac = *acl++) != '\0') {
100 switch (ac) {
101 case 'r':
102 access = access | (uint32_t)ACCESS4_READ;
103 break;
104 case 'l':
105 access = access | (uint32_t)ACCESS4_LOOKUP;
106 break;
107 case 'm':
108 access = access | (uint32_t)ACCESS4_MODIFY;
109 break;
110 case 't':
111 access = access | (uint32_t)ACCESS4_EXTEND;
112 break;
113 case 'd':
114 access = access | (uint32_t)ACCESS4_DELETE;
115 break;
116 case 'x':
117 access = access | (uint32_t)ACCESS4_EXECUTE;
118 break;
119 case 'i':
120 access = access | (uint32_t)0x00000100;
121 break;
122 default:
123 interp->result =
124 "Unknown accessreq, use {rlmtdx i(0x100)}";
125 return (TCL_ERROR);
126 }
127 }
128
129 opp->nfs_argop4_u.opaccess.access = access;
130
131 return (TCL_OK);
132 }
133
134 int
135 Close(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
136 {
137 stateid4 stateid;
138 nfs_argop4 *opp = new_argop();
139
140 if (argc < 3) {
141 interp->result = "Usage: Close seqid stateid{seqid other}";
142 return (TCL_ERROR);
143 }
144
145 opp->argop = OP_CLOSE;
146 substitution(interp, argv[1]);
147 argv[1] = interp->result;
148 opp->nfs_argop4_u.opclose.seqid = (seqid4) atoi(argv[1]);
149 substitution(interp, argv[2]);
150 argv[2] = interp->result;
151 if (str2stateid(interp, argv[2], &stateid) != TCL_OK) {
152 interp->result = "Close: str2stateid() error";
153 return (TCL_ERROR);
154 }
155 opp->nfs_argop4_u.opclose.open_stateid = stateid;
156
157 return (TCL_OK);
158 }
159
160 int
161 Commit(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
162 {
163 nfs_argop4 *opp = new_argop();
164
165 if (argc < 3) {
166 interp->result = "Usage: Commit offset count";
167 return (TCL_ERROR);
168 }
169
170 opp->argop = OP_COMMIT;
171 substitution(interp, argv[1]);
172 argv[1] = interp->result;
173 opp->nfs_argop4_u.opcommit.offset = (offset4) atol(argv[1]);
174 substitution(interp, argv[2]);
175 argv[2] = interp->result;
176 opp->nfs_argop4_u.opcommit.count = (count4) atoi(argv[2]);
177
178 return (TCL_OK);
179 }
180
181 int
182 Create(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
183 {
184 char ct;
185 char buf[80];
186 char lv4[1024], lv5[1024];
187 createtype4 ctype;
188 bitmap4 bm;
189 attrlist4 av;
190
191 nfs_argop4 *opp = new_argop();
192
193 if (argc < 4) {
194 interp->result = "Usage: Create objname "
195 "{{name val} {name val} ...}\n "
196 "s | f | d | l linkdata | b specd1 specd2 | "
197 "c specd1 specd2";
198 return (TCL_ERROR);
199 }
200
201 opp->argop = OP_CREATE;
202
203 substitution(interp, argv[3]);
204 argv[3] = interp->result;
205 ct = *argv[3];
206 if (argc >= 5) {
207 substitution(interp, argv[4]);
208 strcpy(lv4, interp->result);
209 }
210 if (argc >= 6) {
211 substitution(interp, argv[5]);
212 strcpy(lv5, interp->result);
213 }
214 switch (ct) {
215 case 'l': ctype.type = NF4LNK;
216 if (argc != 5) {
217 interp->result = "Usage: "
218 "Create objname {attrs} l linkdata";
219 return (TCL_ERROR);
220 }
221 ctype.createtype4_u.linkdata = *str2utf8(lv4);
222 break;
223 case 'b': ctype.type = NF4BLK;
224 if (argc != 6) {
225 interp->result = "Usage: "
226 "Create objname {attrs} b specd1 specd2";
227 return (TCL_ERROR);
228 }
229 ctype.createtype4_u.devdata.specdata1 =
230 (uint32_t)atoi(lv4);
231 ctype.createtype4_u.devdata.specdata2 =
232 (uint32_t)atoi(lv5);
233 break;
234 case 'c': ctype.type = NF4CHR;
235 if (argc != 6) {
236 interp->result = "Usage: "
237 "Create objname {attrs} c specd1 specd2";
238 return (TCL_ERROR);
239 }
240 ctype.createtype4_u.devdata.specdata1 =
241 (uint32_t)atoi(lv4);
242 ctype.createtype4_u.devdata.specdata2 =
243 (uint32_t)atoi(lv5);
244 break;
245 case 's': ctype.type = NF4SOCK; break;
246 case 'f': ctype.type = NF4FIFO; break;
247 case 'd': ctype.type = NF4DIR; break;
248 /*
249 * XXX the following 'r' type is added for testing BADTYPE
250 */
251 case 'r': ctype.type = NF4REG; break;
252 default:
253 sprintf(buf, "Unknown create-type [%c]", ct);
254 interp->result = buf;
255 return (TCL_ERROR);
256 }
257
258 substitution(interp, argv[1]);
259 argv[1] = interp->result;
260 opp->nfs_argop4_u.opcreate.objname = *str2utf8(argv[1]);
261
262 substitution(interp, argv[2]);
263 argv[2] = interp->result;
264 if ((attr_encode(interp, argv[2], &bm, &av)) != TCL_OK)
265 return (TCL_ERROR);
266 opp->nfs_argop4_u.opcreate.createattrs.attrmask = bm;
267 opp->nfs_argop4_u.opcreate.createattrs.attr_vals = av;
268
269 opp->nfs_argop4_u.opcreate.objtype = ctype;
270
271 return (TCL_OK);
272 }
273
274 int
275 Delegpurge(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
276 {
277 nfs_argop4 *opp = new_argop();
278
279 if (argc < 2) {
280 interp->result = "Usage: Delegpurge clientid";
281 return (TCL_ERROR);
282 }
283
284 opp->argop = OP_DELEGPURGE;
285 substitution(interp, argv[1]);
286 argv[1] = interp->result;
287 opp->nfs_argop4_u.opdelegpurge.clientid = strtoull(argv[1], NULL, 16);
288
289 return (TCL_OK);
290 }
291
292 int
293 Delegreturn(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
294 {
295 int lc;
296 char **lv;
297 stateid4 stateid;
298
299 nfs_argop4 *opp = new_argop();
300
301 if (argc < 2) {
302 interp->result = "Usage: Delegreturn stateid{seqid other}";
303 return (TCL_ERROR);
304 }
305
306 opp->argop = OP_DELEGRETURN;
307 substitution(interp, argv[1]);
308 argv[1] = interp->result;
309 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
310 interp->result = "Delegreturn: str2stateid() error";
311 return (TCL_ERROR);
312 }
313
314 opp->nfs_argop4_u.opdelegreturn.deleg_stateid = stateid;
315
316 return (TCL_OK);
317 }
318
319 int
320 Getattr(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
321 {
322 bitmap4 bm;
323 int err;
324 char lv1[2048];
325
326 nfs_argop4 *opp = new_argop();
327
328 if (argc != 2) {
329 interp->result =
330 "Usage: Getattr { attrname attrname ... }";
331 return (TCL_ERROR);
332 }
333
334 opp->argop = OP_GETATTR;
335
336 substitution(interp, argv[1]);
337 strcpy(lv1, interp->result);
338 err = names2bitmap(interp, lv1, &bm);
339 if (err != TCL_OK)
340 return (err);
341
342 opp->nfs_argop4_u.opgetattr.attr_request = bm;
343
344 return (TCL_OK);
345 }
346
347 int
348 Getfh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
349 {
350 nfs_argop4 *opp = new_argop();
351 if (argc != 1) {
352 interp->result = "Arguments ignored!\nUsage: Getfh";
353 }
354 opp->argop = OP_GETFH;
355
356 return (TCL_OK);
357 }
358
359 int
360 Illegal(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
361 {
362 nfs_argop4 *opp = new_argop();
363 if (argc != 1) {
364 interp->result = "Arguments ignored!\nUsage: Illegal";
365 }
366 opp->argop = OP_ILLEGAL;
367
368 return (TCL_OK);
369 }
370
371 int
372 Link(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
373 {
374 nfs_argop4 *opp = new_argop();
375
376 if (argc != 2) {
377 interp->result = "Usage: Link newname";
378 return (TCL_ERROR);
379 }
380
381 opp->argop = OP_LINK;
382 substitution(interp, argv[1]);
383 argv[1] = interp->result;
384 opp->nfs_argop4_u.oplink.newname = *str2utf8(argv[1]);
385
386 return (TCL_OK);
387 }
388
389 int
390 Lock(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
391 {
392 int lt;
393 bool_t rc;
394 stateid4 stateid;
395 lock_owner4 lowner;
396 seqid4 lseqid;
397 seqid4 oseqid;
398 int lc;
399 char **lv;
400 char buf[80], lv2[1024];
401
402 nfs_argop4 *opp = new_argop();
403
404 if (argc < 8) {
405 interp->result =
406 "Usage: Lock ltype(1|2|3|4) reclaim(T|F) offset "
407 "length newlock(T|F)\n "
408 "stateid{seqid other} lseqid {oseqid clientid lowner}";
409 return (TCL_ERROR);
410 }
411
412 opp->argop = OP_LOCK;
413 substitution(interp, argv[1]);
414 argv[1] = interp->result;
415 lt = atoi(argv[1]);
416 switch (lt) {
417 case 1:
418 opp->nfs_argop4_u.oplock.locktype = READ_LT;
419 break;
420 case 2:
421 opp->nfs_argop4_u.oplock.locktype = WRITE_LT;
422 break;
423 case 3:
424 opp->nfs_argop4_u.oplock.locktype = READW_LT;
425 break;
426 case 4:
427 opp->nfs_argop4_u.oplock.locktype = WRITEW_LT;
428 break;
429 default:
430 sprintf(buf, "Unknown lock-type [%s]", argv[1]);
431 interp->result = buf;
432 return (TCL_ERROR);
433 }
434 substitution(interp, argv[2]);
435 argv[2] = interp->result;
436 rc = argv[2][0];
437 switch (rc) {
438 case 'T':
439 case 't':
440 opp->nfs_argop4_u.oplock.reclaim = TRUE;
441 break;
442 case 'F':
443 case 'f':
444 opp->nfs_argop4_u.oplock.reclaim = FALSE;
445 break;
446 default:
447 sprintf(buf, "Unknown reclaim [%s]; should be T|F", argv[2]);
448 interp->result = buf;
449 return (TCL_ERROR);
450 }
451 substitution(interp, argv[3]);
452 argv[3] = interp->result;
453 opp->nfs_argop4_u.oplock.offset = (offset4) strtoull(argv[3], NULL, 10);
454 substitution(interp, argv[4]);
455 argv[4] = interp->result;
456 opp->nfs_argop4_u.oplock.length = (length4) strtoull(argv[4], NULL, 10);
457 substitution(interp, argv[5]);
458 argv[5] = interp->result;
459 rc = argv[5][0];
460 substitution(interp, argv[6]);
461 argv[6] = interp->result;
462 if (str2stateid(interp, argv[6], &stateid) != TCL_OK) {
463 interp->result = "Lock: str2stateid() error";
464 return (TCL_ERROR);
465 }
466 substitution(interp, argv[7]);
467 argv[7] = interp->result;
468 lseqid = (seqid4) atoi(argv[7]);
469 /*
470 * argv[8] is for new open only;
471 * Need to split "{oseqid clientid owner}".
472 */
473 substitution(interp, argv[8]);
474 argv[8] = interp->result;
475 if (Tcl_SplitList(interp, argv[8], &lc,
476 (CONST84 char ***)&lv) != TCL_OK) {
477 sprintf(buf, "Lock arg error, can't split {%s}", argv[8]);
478 interp->result = buf;
479 return (TCL_ERROR);
480 }
481 if (lc < 3) {
482 sprintf(buf,
483 "Lock arg error, {%s} needs at least 3 fields", argv[8]);
484 interp->result = buf;
485 if (lv)
486 free((char *)lv);
487 return (TCL_ERROR);
488 }
489 substitution(interp, lv[0]);
490 oseqid = (seqid4)atoi(interp->result);
491 substitution(interp, lv[1]);
492 lowner.clientid = (clientid4)strtoull(interp->result, NULL, 16);
493 substitution(interp, lv[2]);
494 strcpy(lv2, interp->result);
495 lowner.owner.owner_val = lv2;
496 lowner.owner.owner_len = strlen(lowner.owner.owner_val);
497 switch (rc) {
498 case 'T':
499 case 't':
500 opp->nfs_argop4_u.oplock.locker.new_lock_owner = TRUE;
501 opp->nfs_argop4_u.oplock.locker.locker4_u.open_owner.open_stateid =
502 stateid;
503 opp->nfs_argop4_u.oplock.locker.locker4_u.open_owner.open_seqid =
504 oseqid;
505 opp->nfs_argop4_u.oplock.locker.locker4_u.open_owner.lock_seqid =
506 lseqid;
507 opp->nfs_argop4_u.oplock.locker.locker4_u.open_owner.lock_owner =
508 lowner;
509 break;
510 case 'F':
511 case 'f':
512 opp->nfs_argop4_u.oplock.locker.new_lock_owner = FALSE;
513 opp->nfs_argop4_u.oplock.locker.locker4_u.lock_owner.lock_stateid =
514 stateid;
515 opp->nfs_argop4_u.oplock.locker.locker4_u.lock_owner.lock_seqid =
516 lseqid;
517 break;
518 default:
519 sprintf(buf, "Unknown newlock [%s]; should be T|F", argv[5]);
520 interp->result = buf;
521 if (lv)
522 free((char *)lv);
523 return (TCL_ERROR);
524 }
525
526 if (lv)
527 free((char *)lv);
528 return (TCL_OK);
529 }
530
531 int
532 Lockt(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
533 {
534 int lt;
535 bool_t rc;
536 char buf[80], lv3[1024];
537
538 nfs_argop4 *opp = new_argop();
539
540 if (argc != 6) {
541 interp->result = "Usage: Lockt type(1|2|3|4) "
542 "clientid lowner offset length";
543 return (TCL_ERROR);
544 }
545
546 opp->argop = OP_LOCKT;
547 substitution(interp, argv[1]);
548 argv[1] = interp->result;
549 lt = atoi(argv[1]);
550 switch (lt) {
551 case 1:
552 opp->nfs_argop4_u.oplockt.locktype = READ_LT;
553 break;
554 case 2:
555 opp->nfs_argop4_u.oplockt.locktype = WRITE_LT;
556 break;
557 case 3:
558 opp->nfs_argop4_u.oplockt.locktype = READW_LT;
559 break;
560 case 4:
561 opp->nfs_argop4_u.oplockt.locktype = WRITEW_LT;
562 break;
563 default:
564 sprintf(buf, "Unknown lock-type [%s]", argv[1]);
565 interp->result = buf;
566 return (TCL_ERROR);
567 }
568 substitution(interp, argv[2]);
569 argv[2] = interp->result;
570 opp->nfs_argop4_u.oplockt.owner.clientid =
571 (clientid4) strtoull(argv[2], NULL, 16);
572
573 substitution(interp, argv[3]);
574 strcpy(lv3, interp->result);
575
576 opp->nfs_argop4_u.oplockt.owner.owner.owner_val = lv3;
577 opp->nfs_argop4_u.oplockt.owner.owner.owner_len = strlen(lv3);
578 substitution(interp, argv[4]);
579 argv[4] = interp->result;
580 opp->nfs_argop4_u.oplockt.offset =
581 (offset4) strtoull(argv[4], (char **)NULL, 10);
582 substitution(interp, argv[5]);
583 argv[5] = interp->result;
584 opp->nfs_argop4_u.oplockt.length =
585 (length4) strtoull(argv[5], (char **)NULL, 10);
586
587 return (TCL_OK);
588 }
589
590 int
591 Locku(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
592 {
593 int lt;
594 char buf[80];
595 stateid4 stateid;
596
597 nfs_argop4 *opp = new_argop();
598
599 if (argc != 6) {
600 interp->result =
601 "Usage: Locku type(1|2|3|4) lseqid "
602 "lstateid{seqid other} offset length";
603 return (TCL_ERROR);
604 }
605
606 opp->argop = OP_LOCKU;
607 substitution(interp, argv[1]);
608 argv[1] = interp->result;
609 lt = atoi(argv[1]);
610 switch (lt) {
611 case 1:
612 opp->nfs_argop4_u.oplocku.locktype = READ_LT;
613 break;
614 case 2:
615 opp->nfs_argop4_u.oplocku.locktype = WRITE_LT;
616 break;
617 case 3:
618 opp->nfs_argop4_u.oplocku.locktype = READW_LT;
619 break;
620 case 4:
621 opp->nfs_argop4_u.oplocku.locktype = WRITEW_LT;
622 break;
623 default:
624 sprintf(buf, "Unknown locktype [%s]", argv[1]);
625 interp->result = buf;
626 return (TCL_ERROR);
627 }
628 substitution(interp, argv[2]);
629 argv[2] = interp->result;
630 opp->nfs_argop4_u.oplocku.seqid = (seqid4)atoi(argv[2]);
631 substitution(interp, argv[3]);
632 argv[3] = interp->result;
633 if (str2stateid(interp, argv[3], &stateid) != TCL_OK) {
634 interp->result = "Locku: str2stateid() error";
635 return (TCL_ERROR);
636 }
637 opp->nfs_argop4_u.oplocku.lock_stateid = stateid;
638 substitution(interp, argv[4]);
639 argv[4] = interp->result;
640 opp->nfs_argop4_u.oplocku.offset =
641 (offset4) strtoull(argv[4], (char **)NULL, 10);
642 substitution(interp, argv[5]);
643 argv[5] = interp->result;
644 opp->nfs_argop4_u.oplocku.length =
645 (length4) strtoull(argv[5], (char **)NULL, 10);
646
647 return (TCL_OK);
648 }
649
650 int
651 Lookup(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
652 {
653 nfs_argop4 *opp = new_argop();
654
655 if (argc != 2) {
656 interp->result = "Usage: Lookup objname";
657 return (TCL_ERROR);
658 }
659
660 opp->argop = OP_LOOKUP;
661
662 substitution(interp, argv[1]);
663 argv[1] = interp->result;
664 opp->nfs_argop4_u.oplookup.objname = *str2utf8(argv[1]);
665
666 return (TCL_OK);
667 }
668
669 int
670 Lookupp(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
671 {
672 nfs_argop4 *opp = new_argop();
673 if (argc != 1) {
674 interp->result = "Arguments ignored!\nUsage: Lookupp";
675 }
676 opp->argop = OP_LOOKUPP;
677
678 return (TCL_OK);
679 }
680
681 int
682 Nverify(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
683 {
684 bitmap4 bm;
685 attrlist4 av;
686 char lv1[2048];
687
688 nfs_argop4 *opp = new_argop();
689
690 if (argc != 2) {
691 interp->result =
692 "Usage: Nverify { {name val} {name val} ... }";
693 return (TCL_ERROR);
694 }
695
696 opp->argop = OP_NVERIFY;
697
698 substitution(interp, argv[1]);
699 strcpy(lv1, interp->result);
700 if ((attr_encode(interp, lv1, &bm, &av)) != TCL_OK)
701 return (TCL_ERROR);
702
703 opp->nfs_argop4_u.opnverify.obj_attributes.attrmask = bm;
704 opp->nfs_argop4_u.opnverify.obj_attributes.attr_vals = av;
705
706 return (TCL_OK);
707 }
708
709 int
710 Open(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
711 {
712 nfs_argop4 *opp = new_argop();
713
714 if (argc != 7) {
715 interp->result =
716 "Usage: Open\n oseqid "
717 "access(1|2|3) deny(0|1|2|3) {clientid open_owner}\n"
718 " {opentype(0|1) createmode(0|1|2) "
719 "{{name val} {name val}...} | createverf}\n "
720 "{claim(0|1|2|3) {filename | delegate_type | "
721 "{delegate_stateid filename}}}\n ";
722 return (TCL_ERROR);
723 }
724
725 opp->argop = OP_OPEN;
726 substitution(interp, argv[1]);
727 argv[1] = interp->result;
728 opp->nfs_argop4_u.opopen.seqid = (seqid4)atoi(argv[1]);
729 substitution(interp, argv[2]);
730 argv[2] = interp->result;
731 opp->nfs_argop4_u.opopen.share_access = (uint32_t)atoi(argv[2]);
732 substitution(interp, argv[3]);
733 argv[3] = interp->result;
734 opp->nfs_argop4_u.opopen.share_deny = (uint32_t)atoi(argv[3]);
735 /* no substitution is needed for argv[4] to argv[6] here, */
736 /* since its done inside the set_xxxxx() functions */
737 if (set_owner(interp, argv[4], &opp->nfs_argop4_u.opopen.owner)
738 != TCL_OK)
739 return (TCL_ERROR);
740 if (set_opentype(interp, argv[5], &opp->nfs_argop4_u.opopen.openhow)
741 != TCL_OK)
742 return (TCL_ERROR);
743 if (set_openclaim(interp, argv[6], &opp->nfs_argop4_u.opopen.claim)
744 != TCL_OK)
745 return (TCL_ERROR);
746
747 return (TCL_OK);
748 }
749
750 int
751 Openattr(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
752 {
753 bool_t cdir;
754 char buf[80];
755
756 nfs_argop4 *opp = new_argop();
757
758 if (argc != 2) {
759 interp->result = "Usage: Openattr createdir(T|F)";
760 return (TCL_ERROR);
761 }
762
763 opp->argop = OP_OPENATTR;
764
765 substitution(interp, argv[1]);
766 argv[1] = interp->result;
767 cdir = argv[1][0];
768 switch (cdir) {
769 case 'T':
770 case 't':
771 opp->nfs_argop4_u.opopenattr.createdir = TRUE;
772 break;
773 case 'F':
774 case 'f':
775 opp->nfs_argop4_u.opopenattr.createdir = FALSE;
776 break;
777 default:
778 sprintf(buf, "Unknown createdir [%s]; should be T|F", argv[1]);
779 interp->result = buf;
780 return (TCL_ERROR);
781 }
782
783 return (TCL_OK);
784 }
785
786 int
787 Open_confirm(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
788 {
789 stateid4 stateid;
790 nfs_argop4 *opp = new_argop();
791
792 if (argc != 3) {
793 interp->result = "Usage: Open_confirm "
794 "open_stateid{seqid other} seqid";
795 return (TCL_ERROR);
796 }
797
798 opp->argop = OP_OPEN_CONFIRM;
799 substitution(interp, argv[1]);
800 argv[1] = interp->result;
801 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
802 interp->result = "Open_confirm: str2stateid() error";
803 return (TCL_ERROR);
804 }
805 opp->nfs_argop4_u.opopen_confirm.open_stateid = stateid;
806 substitution(interp, argv[2]);
807 argv[2] = interp->result;
808 opp->nfs_argop4_u.opopen_confirm.seqid = (seqid4) atoi(argv[2]);
809
810 return (TCL_OK);
811 }
812
813 int
814 Open_downgrade(ClientData clientData, Tcl_Interp *interp,
815 int argc, char *argv[])
816 {
817 stateid4 stateid;
818 nfs_argop4 *opp = new_argop();
819
820 if (argc != 5) {
821 interp->result =
822 "Usage: Open_downgrade stateid{seqid other} "
823 "seqid access deny";
824 return (TCL_ERROR);
825 }
826
827 opp->argop = OP_OPEN_DOWNGRADE;
828 substitution(interp, argv[1]);
829 argv[1] = interp->result;
830 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
831 interp->result = "Open_downgrade: str2stateid() error";
832 return (TCL_ERROR);
833 }
834 opp->nfs_argop4_u.opopen_downgrade.open_stateid = stateid;
835 substitution(interp, argv[2]);
836 argv[2] = interp->result;
837 opp->nfs_argop4_u.opopen_downgrade.seqid = (seqid4)atoi(argv[2]);
838 substitution(interp, argv[3]);
839 argv[3] = interp->result;
840 opp->nfs_argop4_u.opopen_downgrade.share_access =
841 (uint32_t)atoi(argv[3]);
842 substitution(interp, argv[4]);
843 argv[4] = interp->result;
844 opp->nfs_argop4_u.opopen_downgrade.share_deny =
845 (uint32_t)atoi(argv[4]);
846
847 return (TCL_OK);
848 }
849
850 int
851 Putfh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
852 {
853 char *fhstr;
854 int fhlen;
855 char *fhp;
856
857 nfs_argop4 *opp = new_argop();
858
859 if (argc != 2) {
860 interp->result = "Usage: Putfh <fh>";
861 return (TCL_ERROR);
862 }
863
864 opp->argop = OP_PUTFH;
865 substitution(interp, argv[1]);
866 argv[1] = interp->result;
867 fhstr = argv[1];
868 fhlen = (strlen(fhstr) + 1) / 2;
869
870 fhp = malloc(fhlen);
871 if (fhp == NULL) {
872 interp->result = "malloc failure in Putfh";
873 return (TCL_ERROR);
874 }
875 (void) memcpy(fhp, hex2bin(fhstr, (unsigned)fhlen), fhlen);
876
877 opp->nfs_argop4_u.opputfh.object.nfs_fh4_len = fhlen;
878 opp->nfs_argop4_u.opputfh.object.nfs_fh4_val = fhp;
879
880 return (TCL_OK);
881 }
882
883 int
884 Putpubfh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
885 {
886 nfs_argop4 *opp = new_argop();
887 if (argc != 1) {
888 interp->result = "Arguments ignored!\nUsage: Putpubfh";
889 }
890 opp->argop = OP_PUTPUBFH;
891
892 return (TCL_OK);
893 }
894
895 int
896 Putrootfh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
897 {
898 nfs_argop4 *opp = new_argop();
899 if (argc != 1) {
900 interp->result = "Arguments ignored!\nUsage: Putrootfh";
901 }
902 opp->argop = OP_PUTROOTFH;
903
904 return (TCL_OK);
905 }
906
907 int
908 Read(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
909 {
910 stateid4 stateid;
911 nfs_argop4 *opp = new_argop();
912
913 if (argc != 4) {
914 interp->result = "Usage: Read stateid{seqid other} "
915 "offset count";
916 return (TCL_ERROR);
917 }
918
919 opp->argop = OP_READ;
920
921 substitution(interp, argv[1]);
922 argv[1] = interp->result;
923 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
924 interp->result = "Read: str2stateid() error";
925 return (TCL_ERROR);
926 }
927 opp->nfs_argop4_u.opread.stateid = stateid;
928 substitution(interp, argv[2]);
929 argv[2] = interp->result;
930 opp->nfs_argop4_u.opread.offset =
931 (offset4) strtoull(argv[2], (char **)NULL, 10);
932 substitution(interp, argv[3]);
933 argv[3] = interp->result;
934 opp->nfs_argop4_u.opread.count = (count4) atoi(argv[3]);
935
936 return (TCL_OK);
937 }
938
939 int
940 Readdir(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
941 {
942 nfs_cookie4 cookie;
943 verifier4 verf;
944 count4 dircount;
945 count4 maxcount;
946 bitmap4 bm;
947 int err;
948 char lv3[1024], lv4[1024], lv5[2048];
949
950 nfs_argop4 *opp = new_argop();
951
952 if (argc != 6) {
953 interp->result =
954 "Usage: Readdir cookie verf "
955 "dircount maxcount {attrname ...}";
956 return (TCL_ERROR);
957 }
958
959 opp->argop = OP_READDIR;
960
961 substitution(interp, argv[1]);
962 argv[1] = interp->result;
963
964 cookie = (nfs_cookie4) strtoull(argv[1], NULL, 10);
965
966 substitution(interp, argv[2]);
967 argv[2] = interp->result;
968 (void) memcpy(verf, hex2bin(argv[2], sizeof (verf)), sizeof (verf));
969
970 substitution(interp, argv[3]);
971 strcpy(lv3, interp->result);
972 if (Tcl_GetInt(interp, lv3, (int *)&dircount) != TCL_OK)
973 goto err;
974
975 substitution(interp, argv[4]);
976 strcpy(lv4, interp->result);
977 if (Tcl_GetInt(interp, lv4, (int *)&maxcount) != TCL_OK)
978 goto err;
979
980 opp->nfs_argop4_u.opreaddir.cookie = cookie;
981 (void) memcpy(opp->nfs_argop4_u.opreaddir.cookieverf,
982 verf, sizeof (verf));
983 opp->nfs_argop4_u.opreaddir.dircount = dircount;
984 opp->nfs_argop4_u.opreaddir.maxcount = maxcount;
985
986 substitution(interp, argv[5]);
987 strcpy(lv5, interp->result);
988 err = names2bitmap(interp, lv5, &bm);
989 if (err != TCL_OK)
990 return (err);
991
992 opp->nfs_argop4_u.opreaddir.attr_request = bm;
993
994 return (TCL_OK);
995
996 err:
997 return (TCL_ERROR);
998 }
999
1000 int
1001 Readlink(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1002 {
1003 nfs_argop4 *opp = new_argop();
1004 if (argc != 1) {
1005 interp->result = "Arguments ignored!\nUsage: Readlink";
1006 }
1007 opp->argop = OP_READLINK;
1008
1009 return (TCL_OK);
1010 }
1011
1012 int
1013 Release_lockowner(ClientData clientData, Tcl_Interp *interp,
1014 int argc, char *argv[])
1015 {
1016 char tmp[1024];
1017 nfs_argop4 *opp = new_argop();
1018
1019 if (argc != 3) {
1020 interp->result = "Usage: Release_lockowner clientid lowner";
1021 return (TCL_ERROR);
1022 }
1023
1024 opp->argop = OP_RELEASE_LOCKOWNER;
1025 substitution(interp, argv[1]);
1026 argv[1] = interp->result;
1027 opp->nfs_argop4_u.oprelease_lockowner.lock_owner.clientid =
1028 (clientid4) strtoull(argv[1], NULL, 16);
1029
1030 substitution(interp, argv[2]);
1031 strcpy(tmp, interp->result);
1032 opp->nfs_argop4_u.oprelease_lockowner.lock_owner.owner.owner_val = tmp;
1033 opp->nfs_argop4_u.oprelease_lockowner.lock_owner.owner.owner_len =
1034 strlen(tmp);
1035
1036 return (TCL_OK);
1037 }
1038
1039 int
1040 Remove(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1041 {
1042 nfs_argop4 *opp = new_argop();
1043
1044 if (argc != 2) {
1045 interp->result = "Usage: Remove target";
1046 return (TCL_ERROR);
1047 }
1048
1049 opp->argop = OP_REMOVE;
1050 substitution(interp, argv[1]);
1051 argv[1] = interp->result;
1052 opp->nfs_argop4_u.oplink.newname = *str2utf8(argv[1]);
1053
1054 return (TCL_OK);
1055 }
1056
1057 int
1058 Rename(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1059 {
1060 nfs_argop4 *opp = new_argop();
1061
1062 if (argc != 3) {
1063 interp->result = "Usage: Rename oldname newname";
1064 return (TCL_ERROR);
1065 }
1066
1067 opp->argop = OP_RENAME;
1068 substitution(interp, argv[1]);
1069 argv[1] = interp->result;
1070 opp->nfs_argop4_u.oprename.oldname = *str2utf8(argv[1]);
1071 substitution(interp, argv[2]);
1072 argv[2] = interp->result;
1073 opp->nfs_argop4_u.oprename.newname = *str2utf8(argv[2]);
1074
1075 return (TCL_OK);
1076 }
1077
1078 int
1079 Renew(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1080 {
1081 nfs_argop4 *opp = new_argop();
1082
1083 if (argc != 2) {
1084 interp->result = "Usage: Renew clientid";
1085 return (TCL_ERROR);
1086 }
1087
1088 opp->argop = OP_RENEW;
1089
1090 substitution(interp, argv[1]);
1091 argv[1] = interp->result;
1092 opp->nfs_argop4_u.oprenew.clientid =
1093 (clientid4) strtoull(argv[1], NULL, 16);
1094
1095 return (TCL_OK);
1096 }
1097
1098 int
1099 Restorefh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1100 {
1101 nfs_argop4 *opp = new_argop();
1102 if (argc != 1) {
1103 interp->result = "Arguments ignored!\nUsage: Restorefh";
1104 }
1105 opp->argop = OP_RESTOREFH;
1106
1107 return (TCL_OK);
1108 }
1109
1110 int
1111 Savefh(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1112 {
1113 nfs_argop4 *opp = new_argop();
1114 if (argc != 1) {
1115 interp->result = "Arguments ignored!\nUsage: Savefh";
1116 }
1117 opp->argop = OP_SAVEFH;
1118
1119 return (TCL_OK);
1120 }
1121
1122 int
1123 Secinfo(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1124 {
1125 nfs_argop4 *opp = new_argop();
1126
1127 if (argc != 2) {
1128 interp->result = "Usage: Secinfo name";
1129 return (TCL_ERROR);
1130 }
1131
1132 opp->argop = OP_SECINFO;
1133 substitution(interp, argv[1]);
1134 argv[1] = interp->result;
1135 opp->nfs_argop4_u.opsecinfo.name = *str2utf8(argv[1]);
1136
1137 return (TCL_OK);
1138 }
1139
1140 int
1141 Setattr(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1142 {
1143 bitmap4 bm;
1144 attrlist4 av;
1145 stateid4 stateid;
1146 char lv2[2048];
1147
1148 nfs_argop4 *opp = new_argop();
1149
1150 if (argc != 3) {
1151 interp->result =
1152 "Usage: Setattr stateid{seqid other}"
1153 " { {name val} {name val} ... }";
1154 return (TCL_ERROR);
1155 }
1156 opp->argop = OP_SETATTR;
1157
1158 substitution(interp, argv[1]);
1159 argv[1] = interp->result;
1160 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
1161 interp->result = "Setattr: str2stateid() error";
1162 return (TCL_ERROR);
1163 }
1164 opp->nfs_argop4_u.opsetattr.stateid = stateid;
1165
1166 substitution(interp, argv[2]);
1167 strcpy(lv2, interp->result);
1168 if ((attr_encode(interp, lv2, &bm, &av)) != TCL_OK)
1169 return (TCL_ERROR);
1170 opp->nfs_argop4_u.opsetattr.obj_attributes.attrmask = bm;
1171 opp->nfs_argop4_u.opsetattr.obj_attributes.attr_vals = av;
1172
1173 return (TCL_OK);
1174 }
1175
1176 int
1177 Setclientid(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1178 {
1179 char lv2[1024];
1180 nfs_argop4 *opp = new_argop();
1181
1182 if (argc != 4) {
1183 interp->result =
1184 "Usage: Setclientid verifier id {cb_prog netid addr} \n\
1185 \t(The callback is not yet implemented; its values are set to NULL.)";
1186 return (TCL_ERROR);
1187 }
1188
1189 opp->argop = OP_SETCLIENTID;
1190 substitution(interp, argv[1]);
1191 argv[1] = interp->result;
1192 (void) memcpy(opp->nfs_argop4_u.opsetclientid.client.verifier,
1193 hex2bin(argv[1], sizeof (verifier4)), sizeof (verifier4));
1194
1195 substitution(interp, argv[2]);
1196 strcpy(lv2, interp->result);
1197 opp->nfs_argop4_u.opsetclientid.client.id.id_val = lv2;
1198 opp->nfs_argop4_u.opsetclientid.client.id.id_len = strlen(lv2);
1199
1200 /*
1201 * XXX The callback program has not yet been implemented;
1202 * thus it uses NULL for these temporary.
1203 */
1204 opp->nfs_argop4_u.opsetclientid.callback.cb_program = 0;
1205 opp->nfs_argop4_u.opsetclientid.callback.cb_location.r_netid = NULL;
1206 opp->nfs_argop4_u.opsetclientid.callback.cb_location.r_addr = NULL;
1207
1208
1209 /*
1210 * XXX callback_ident is not yet implemented, nor it is the interface
1211 * to get its value from the user. Use 0 as a temporal value.
1212 * This is to avoid modifying all occurrences of setclientid in
1213 * testcases while callback is not implemented.
1214 */
1215 opp->nfs_argop4_u.opsetclientid.callback_ident = 0;
1216
1217 return (TCL_OK);
1218 }
1219
1220 int
1221 Setclientid_confirm(ClientData clientData, Tcl_Interp *interp,
1222 int argc, char *argv[])
1223 {
1224 nfs_argop4 *opp = new_argop();
1225
1226 if (argc != 3) {
1227 interp->result =
1228 "Usage: Setclientid_confirm clientid verifier";
1229 return (TCL_ERROR);
1230 }
1231
1232 opp->argop = OP_SETCLIENTID_CONFIRM;
1233 substitution(interp, argv[1]);
1234 argv[1] = interp->result;
1235 opp->nfs_argop4_u.opsetclientid_confirm.clientid =
1236 (clientid4) strtoull(argv[1], NULL, 16);
1237 substitution(interp, argv[2]);
1238 argv[2] = interp->result;
1239 (void) memcpy(
1240 opp->nfs_argop4_u.opsetclientid_confirm.setclientid_confirm,
1241 hex2bin(argv[2], sizeof (verifier4)), sizeof (verifier4));
1242
1243 return (TCL_OK);
1244 }
1245
1246 int
1247 Verify(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1248 {
1249 bitmap4 bm;
1250 attrlist4 av;
1251 char lv1[2048];
1252
1253 nfs_argop4 *opp = new_argop();
1254
1255 if (argc != 2) {
1256 interp->result =
1257 "Usage: Verify { {name val} {name val} ... }";
1258 return (TCL_ERROR);
1259 }
1260
1261 opp->argop = OP_VERIFY;
1262
1263 substitution(interp, argv[1]);
1264 strcpy(lv1, interp->result);
1265 if ((attr_encode(interp, lv1, &bm, &av)) != TCL_OK)
1266 return (TCL_ERROR);
1267
1268 opp->nfs_argop4_u.opverify.obj_attributes.attrmask = bm;
1269 opp->nfs_argop4_u.opverify.obj_attributes.attr_vals = av;
1270
1271 return (TCL_OK);
1272 }
1273
1274 int
1275 Write(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1276 {
1277 stateid4 stateid;
1278 offset4 offset;
1279 stable_how4 stable;
1280 char *data;
1281 int datalen;
1282 char *dp;
1283 char sh, dt, buf[1024];
1284
1285 nfs_argop4 *opp = new_argop();
1286
1287 if (argc != 6) {
1288 interp->result = "Usage: Write stateid{seqid other} "
1289 "offset how-u|d|f datatype-a|h {data}";
1290 return (TCL_ERROR);
1291 }
1292
1293 opp->argop = OP_WRITE;
1294
1295 substitution(interp, argv[1]);
1296 argv[1] = interp->result;
1297 if (str2stateid(interp, argv[1], &stateid) != TCL_OK) {
1298 interp->result = "Write: str2stateid() error";
1299 return (TCL_ERROR);
1300 }
1301 opp->nfs_argop4_u.opwrite.stateid = stateid;
1302
1303 substitution(interp, argv[2]);
1304 argv[2] = interp->result;
1305 opp->nfs_argop4_u.opwrite.offset =
1306 (offset4) strtoull(argv[2], (char **)NULL, 10);
1307
1308 substitution(interp, argv[3]);
1309 argv[3] = interp->result;
1310 sh = *argv[3];
1311 switch (sh) {
1312 case 'u': stable = UNSTABLE4; break;
1313 case 'd': stable = (uint32_t)DATA_SYNC4; break;
1314 case 'f': stable = (uint32_t)FILE_SYNC4; break;
1315 default:
1316 sprintf(buf, "Unknown stable_how (%s);\n", argv[3]);
1317 strcat(buf, "use u-UNSTABLE, d-DATA_SYNC, f-FILE_SYNC");
1318 interp->result = buf;
1319 return (TCL_ERROR);
1320 }
1321 opp->nfs_argop4_u.opwrite.stable = stable;
1322
1323 substitution(interp, argv[4]);
1324 argv[4] = interp->result;
1325 dt = *argv[4];
1326
1327 /* save the data from interp->result to avoid being overwritten */
1328 substitution(interp, argv[5]);
1329 argv[5] = interp->result;
1330 datalen = strlen(argv[5]);
1331 data = malloc(datalen);
1332 if (data == NULL) {
1333 interp->result = "Write: malloc() error";
1334 return (TCL_ERROR);
1335 }
1336 (void) memcpy(data, argv[5], datalen);
1337 switch (dt) {
1338 case 'a':
1339 opp->nfs_argop4_u.opwrite.data.data_val = data;
1340 opp->nfs_argop4_u.opwrite.data.data_len = datalen;
1341 break;
1342 case 'h': /* XXX user entered HEX data, utf8string? */
1343 datalen = strlen(data) / 2;
1344 dp = malloc(datalen);
1345 if (dp == NULL) {
1346 interp->result = "malloc failure in Write";
1347 return (TCL_ERROR);
1348 }
1349 (void) memcpy(dp, hex2bin(data, (unsigned)datalen), datalen);
1350 opp->nfs_argop4_u.opwrite.data.data_val = dp;
1351 opp->nfs_argop4_u.opwrite.data.data_len = datalen;
1352 default:
1353 sprintf(buf, "Unknown data-type(%s);\n", argv[4]);
1354 strcat(buf, "use a-ASCII, h-HEX_DATA");
1355 interp->result = buf;
1356 return (TCL_ERROR);
1357 }
1358
1359 return (TCL_OK);
1360 }
1361
1362
1363 /* ---------------------------------------- */
1364 /* Operation result evaluation functions. */
1365 /* ---------------------------------------- */
1366
1367 /*
1368 * Now the functions to decode the result
1369 */
1370
1371 int
1372 Access_res(Tcl_Interp *interp, Tcl_DString *strp, ACCESS4res *resp)
1373 {
1374 Tcl_DStringStartSublist(strp);
1375 Tcl_DStringAppendElement(strp, "Access");
1376 Tcl_DStringAppendElement(strp, errstr(resp->status));
1377
1378 if (resp->status == NFS4_OK) {
1379 char buf[80];
1380
1381 Tcl_DStringStartSublist(strp);
1382
1383 sprintf(buf, "supported %s",
1384 access2name(resp->ACCESS4res_u.resok4.supported));
1385 Tcl_DStringAppendElement(strp, buf);
1386 sprintf(buf, "access %s",
1387 access2name(resp->ACCESS4res_u.resok4.access));
1388 Tcl_DStringAppendElement(strp, buf);
1389
1390 Tcl_DStringEndSublist(strp);
1391 }
1392
1393 Tcl_DStringEndSublist(strp);
1394 return (TCL_OK);
1395 }
1396
1397 int
1398 Close_res(Tcl_Interp *interp, Tcl_DString *strp, CLOSE4res *resp)
1399 {
1400 char buf[80];
1401 stateid4 stateid;
1402
1403 Tcl_DStringStartSublist(strp);
1404 Tcl_DStringAppendElement(strp, "Close");
1405 Tcl_DStringAppendElement(strp, errstr(resp->status));
1406
1407 stateid = resp->CLOSE4res_u.open_stateid;
1408 sprintf(buf, "%lu %s", stateid.seqid,
1409 bin2hex(stateid.other, sizeof (stateid.other)));
1410 Tcl_DStringAppendElement(strp, buf);
1411
1412 Tcl_DStringEndSublist(strp);
1413 return (TCL_OK);
1414 }
1415
1416 int
1417 Commit_res(Tcl_Interp *interp, Tcl_DString *strp, COMMIT4res *resp)
1418 {
1419 char buf[80];
1420 verifier4 verf;
1421
1422 Tcl_DStringStartSublist(strp);
1423 Tcl_DStringAppendElement(strp, "Commit");
1424 Tcl_DStringAppendElement(strp, errstr(resp->status));
1425
1426 if (resp->status == NFS4_OK) {
1427 (void) memcpy(verf, resp->COMMIT4res_u.resok4.writeverf,
1428 sizeof (verf));
1429 sprintf(buf, "%s", bin2hex(verf, sizeof (verf)));
1430 Tcl_DStringAppendElement(strp, buf);
1431 }
1432
1433 Tcl_DStringEndSublist(strp);
1434 return (TCL_OK);
1435 }
1436
1437 int
1438 Create_res(Tcl_Interp *interp, Tcl_DString *strp, CREATE4res *resp)
1439 {
1440 Tcl_DStringStartSublist(strp);
1441 Tcl_DStringAppendElement(strp, "Create");
1442 Tcl_DStringAppendElement(strp, errstr(resp->status));
1443
1444 if (resp->status == NFS4_OK) {
1445 char buf[80];
1446 change_info4 c;
1447
1448 c = resp->CREATE4res_u.resok4.cinfo;
1449 Tcl_DStringStartSublist(strp);
1450
1451 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
1452 Tcl_DStringAppendElement(strp, buf);
1453 sprintf(buf, "before %.8llx", c.before);
1454 Tcl_DStringAppendElement(strp, buf);
1455 sprintf(buf, "after %.8llx", c.after);
1456 Tcl_DStringAppendElement(strp, buf);
1457
1458 Tcl_DStringStartSublist(strp);
1459 prn_attrname(strp, &resp->CREATE4res_u.resok4.attrset);
1460 Tcl_DStringEndSublist(strp);
1461
1462 Tcl_DStringEndSublist(strp);
1463 }
1464
1465 Tcl_DStringEndSublist(strp);
1466 return (TCL_OK);
1467 }
1468
1469 int
1470 Delegpurge_res(Tcl_Interp *interp, Tcl_DString *strp, DELEGPURGE4res *resp)
1471 {
1472 Tcl_DStringStartSublist(strp);
1473 Tcl_DStringAppendElement(strp, "Delegpurge");
1474 Tcl_DStringAppendElement(strp, errstr(resp->status));
1475 Tcl_DStringEndSublist(strp);
1476 return (TCL_OK);
1477 }
1478
1479 int
1480 Delegreturn_res(Tcl_Interp *interp, Tcl_DString *strp, DELEGRETURN4res *resp)
1481 {
1482 Tcl_DStringStartSublist(strp);
1483 Tcl_DStringAppendElement(strp, "Delegreturn");
1484 Tcl_DStringAppendElement(strp, errstr(resp->status));
1485 Tcl_DStringEndSublist(strp);
1486 return (TCL_OK);
1487 }
1488
1489 int
1490 Getattr_res(Tcl_Interp *interp, Tcl_DString *strp, GETATTR4res *resp)
1491 {
1492 Tcl_DStringStartSublist(strp);
1493 Tcl_DStringAppendElement(strp, "Getattr");
1494 Tcl_DStringAppendElement(strp, errstr(resp->status));
1495
1496 if (resp->status == NFS4_OK) {
1497 bitmap4 bm;
1498 attrlist4 attrvals;
1499 int err;
1500
1501 bm = resp->GETATTR4res_u.resok4.obj_attributes.attrmask;
1502 attrvals = resp->GETATTR4res_u.resok4.obj_attributes.attr_vals;
1503 err = attr_decode(interp, strp, &bm, &attrvals);
1504 if (err != TCL_OK)
1505 return (TCL_ERROR);
1506 }
1507
1508 Tcl_DStringEndSublist(strp);
1509 return (TCL_OK);
1510 }
1511
1512 int
1513 Getfh_res(Tcl_Interp *interp, Tcl_DString *strp, GETFH4res *resp)
1514 {
1515 Tcl_DStringStartSublist(strp);
1516 Tcl_DStringAppendElement(strp, "Getfh");
1517 Tcl_DStringAppendElement(strp, errstr(resp->status));
1518
1519 if (resp->status == NFS4_OK) {
1520 unsigned fh_len;
1521 char *fh_val;
1522
1523 fh_len = resp->GETFH4res_u.resok4.object.nfs_fh4_len;
1524 fh_val = resp->GETFH4res_u.resok4.object.nfs_fh4_val;
1525 Tcl_DStringAppendElement(strp, bin2hex(fh_val, fh_len));
1526 }
1527
1528 Tcl_DStringEndSublist(strp);
1529 return (TCL_OK);
1530 }
1531
1532 int
1533 Illegal_res(Tcl_Interp *interp, Tcl_DString *strp, ILLEGAL4res *resp)
1534 {
1535 Tcl_DStringStartSublist(strp);
1536 Tcl_DStringAppendElement(strp, "Illegal");
1537 Tcl_DStringAppendElement(strp, errstr(resp->status));
1538 Tcl_DStringEndSublist(strp);
1539 return (TCL_OK);
1540 }
1541
1542 int
1543 Link_res(Tcl_Interp *interp, Tcl_DString *strp, LINK4res *resp)
1544 {
1545 Tcl_DStringStartSublist(strp);
1546 Tcl_DStringAppendElement(strp, "Link");
1547 Tcl_DStringAppendElement(strp, errstr(resp->status));
1548
1549 if (resp->status == NFS4_OK) {
1550 char buf[80];
1551 change_info4 c;
1552
1553 c = resp->LINK4res_u.resok4.cinfo;
1554 Tcl_DStringStartSublist(strp);
1555
1556 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
1557 Tcl_DStringAppendElement(strp, buf);
1558 sprintf(buf, "before %.8llx", c.before);
1559 Tcl_DStringAppendElement(strp, buf);
1560 sprintf(buf, "after %.8llx", c.after);
1561 Tcl_DStringAppendElement(strp, buf);
1562
1563 Tcl_DStringEndSublist(strp);
1564 }
1565
1566 Tcl_DStringEndSublist(strp);
1567 return (TCL_OK);
1568 }
1569
1570 int
1571 Lock_res(Tcl_Interp *interp, Tcl_DString *strp, LOCK4res *resp)
1572 {
1573 char buf[80];
1574
1575 Tcl_DStringStartSublist(strp);
1576 Tcl_DStringAppendElement(strp, "Lock");
1577 Tcl_DStringAppendElement(strp, errstr(resp->status));
1578
1579 if (resp->status == NFS4_OK) {
1580 stateid4 stateid;
1581 stateid = resp->LOCK4res_u.resok4.lock_stateid;
1582 sprintf(buf, "%lu %s", stateid.seqid,
1583 bin2hex(stateid.other, sizeof (stateid.other)));
1584 Tcl_DStringAppendElement(strp, buf);
1585 } else {
1586 if (resp->status == NFS4ERR_DENIED) {
1587 lock_owner4 lowner;
1588
1589 sprintf(buf, "%llu %llu %d",
1590 resp->LOCK4res_u.denied.offset,
1591 resp->LOCK4res_u.denied.length,
1592 resp->LOCK4res_u.denied.locktype);
1593 Tcl_DStringAppendElement(strp, buf);
1594 lowner = resp->LOCK4res_u.denied.owner;
1595 sprintf(buf, "%llx ", lowner.clientid);
1596 if (lowner.owner.owner_val != NULL)
1597 strncat(buf, lowner.owner.owner_val,
1598 lowner.owner.owner_len);
1599 Tcl_DStringAppendElement(strp, buf);
1600 }
1601 }
1602
1603 Tcl_DStringEndSublist(strp);
1604 return (TCL_OK);
1605 }
1606
1607 int
1608 Lockt_res(Tcl_Interp *interp, Tcl_DString *strp, LOCKT4res *resp)
1609 {
1610 Tcl_DStringStartSublist(strp);
1611 Tcl_DStringAppendElement(strp, "Lockt");
1612 Tcl_DStringAppendElement(strp, errstr(resp->status));
1613
1614 if (resp->status == NFS4ERR_DENIED) {
1615 char buf[80];
1616 lock_owner4 lowner;
1617
1618 sprintf(buf, "%llu %llu %d",
1619 resp->LOCKT4res_u.denied.offset,
1620 resp->LOCKT4res_u.denied.length,
1621 resp->LOCKT4res_u.denied.locktype);
1622 Tcl_DStringAppendElement(strp, buf);
1623 lowner = resp->LOCKT4res_u.denied.owner;
1624 sprintf(buf, "%llx ", lowner.clientid);
1625 if (lowner.owner.owner_val != NULL)
1626 strncat(buf, lowner.owner.owner_val,
1627 lowner.owner.owner_len);
1628 Tcl_DStringAppendElement(strp, buf);
1629 }
1630
1631 Tcl_DStringEndSublist(strp);
1632 return (TCL_OK);
1633 }
1634
1635 int
1636 Locku_res(Tcl_Interp *interp, Tcl_DString *strp, LOCKU4res *resp)
1637 {
1638 char buf[80];
1639 stateid4 stateid;
1640
1641 Tcl_DStringStartSublist(strp);
1642 Tcl_DStringAppendElement(strp, "Locku");
1643 Tcl_DStringAppendElement(strp, errstr(resp->status));
1644
1645 stateid = resp->LOCKU4res_u.lock_stateid;
1646 sprintf(buf, "%lu %s", stateid.seqid,
1647 bin2hex(stateid.other, sizeof (stateid.other)));
1648 Tcl_DStringAppendElement(strp, buf);
1649
1650 Tcl_DStringEndSublist(strp);
1651 return (TCL_OK);
1652 }
1653
1654 int
1655 Lookup_res(Tcl_Interp *interp, Tcl_DString *strp, LOOKUP4res *resp)
1656 {
1657 Tcl_DStringStartSublist(strp);
1658 Tcl_DStringAppendElement(strp, "Lookup");
1659 Tcl_DStringAppendElement(strp, errstr(resp->status));
1660 Tcl_DStringEndSublist(strp);
1661 return (TCL_OK);
1662 }
1663
1664 int
1665 Lookupp_res(Tcl_Interp *interp, Tcl_DString *strp, LOOKUPP4res *resp)
1666 {
1667 Tcl_DStringStartSublist(strp);
1668 Tcl_DStringAppendElement(strp, "Lookupp");
1669 Tcl_DStringAppendElement(strp, errstr(resp->status));
1670 Tcl_DStringEndSublist(strp);
1671 return (TCL_OK);
1672 }
1673
1674 int
1675 Nverify_res(Tcl_Interp *interp, Tcl_DString *strp, NVERIFY4res *resp)
1676 {
1677 Tcl_DStringStartSublist(strp);
1678 Tcl_DStringAppendElement(strp, "Nverify");
1679 Tcl_DStringAppendElement(strp, errstr(resp->status));
1680 Tcl_DStringEndSublist(strp);
1681 return (TCL_OK);
1682 }
1683
1684 int
1685 Open_res(Tcl_Interp *interp, Tcl_DString *strp, OPEN4res *resp)
1686 {
1687 Tcl_DStringStartSublist(strp);
1688 Tcl_DStringAppendElement(strp, "Open");
1689 Tcl_DStringAppendElement(strp, errstr(resp->status));
1690
1691 if (resp->status == NFS4_OK) {
1692 char buf[80];
1693 change_info4 c;
1694 stateid4 stateid;
1695
1696 /* Stateid for open */
1697 stateid = resp->OPEN4res_u.resok4.stateid;
1698 sprintf(buf, "%lu %s", stateid.seqid,
1699 bin2hex(stateid.other, sizeof (stateid.other)));
1700 Tcl_DStringAppendElement(strp, buf);
1701
1702 /* Directory Change Info */
1703 Tcl_DStringStartSublist(strp);
1704 c = resp->OPEN4res_u.resok4.cinfo;
1705 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
1706 Tcl_DStringAppendElement(strp, buf);
1707 sprintf(buf, "before %.8llx", c.before);
1708 Tcl_DStringAppendElement(strp, buf);
1709 sprintf(buf, "after %.8llx", c.after);
1710 Tcl_DStringAppendElement(strp, buf);
1711 Tcl_DStringEndSublist(strp);
1712
1713 /* Result flags */
1714 sprintf(buf, "%u", resp->OPEN4res_u.resok4.rflags);
1715 Tcl_DStringAppendElement(strp, buf);
1716
1717 /* Info of the attribute from Open */
1718 Tcl_DStringStartSublist(strp);
1719 prn_attrname(strp, &resp->OPEN4res_u.resok4.attrset);
1720 Tcl_DStringEndSublist(strp);
1721
1722 /* Info on any open delegation */
1723 switch (resp->OPEN4res_u.resok4.delegation.delegation_type) {
1724 open_read_delegation4 dr;
1725 open_write_delegation4 dw;
1726 nfs_modified_limit4 *p;
1727 uint32_t s;
1728 uint32_t b;
1729
1730 case OPEN_DELEGATE_NONE:
1731 Tcl_DStringAppendElement(strp, "NONE");
1732 break;
1733
1734 case OPEN_DELEGATE_READ:
1735 Tcl_DStringStartSublist(strp);
1736 Tcl_DStringAppendElement(strp, "READ");
1737 dr = resp->OPEN4res_u.resok4.delegation.open_delegation4_u.read;
1738 sprintf(buf, "%lu %s", dr.stateid.seqid,
1739 bin2hex(dr.stateid.other,
1740 sizeof (dr.stateid.other)));
1741 Tcl_DStringAppendElement(strp, buf);
1742 sprintf(buf, "%s %s",
1743 dr.recall ? "true" : "false",
1744 prn_ace4(dr.permissions));
1745 Tcl_DStringAppendElement(strp, buf);
1746 Tcl_DStringEndSublist(strp);
1747 break;
1748
1749 case OPEN_DELEGATE_WRITE:
1750 Tcl_DStringStartSublist(strp);
1751 Tcl_DStringAppendElement(strp, "WRITE");
1752 dw =
1753 resp->OPEN4res_u.resok4.delegation.open_delegation4_u.write;
1754 sprintf(buf, "%lu %s", dw.stateid.seqid,
1755 bin2hex(dw.stateid.other,
1756 sizeof (dw.stateid.other)));
1757 Tcl_DStringAppendElement(strp, buf);
1758
1759 switch (dw.space_limit.limitby) {
1760 case NFS_LIMIT_SIZE:
1761 s = dw.space_limit.nfs_space_limit4_u.filesize;
1762 sprintf(buf, "%s %s %llu %s",
1763 dw.recall ? "true" : "false",
1764 "SIZE", s, prn_ace4(dw.permissions));
1765 Tcl_DStringAppendElement(strp, buf);
1766 break;
1767
1768 case NFS_LIMIT_BLOCKS:
1769 p = &(dw.space_limit.nfs_space_limit4_u.mod_blocks);
1770 s = p->num_blocks;
1771 b = p->bytes_per_block;
1772 sprintf(buf, "%s %s %lu %lu %s",
1773 dw.recall ? "true" : "false",
1774 "BLOCKS", s, b, prn_ace4(dw.permissions));
1775 Tcl_DStringAppendElement(strp, buf);
1776 break;
1777
1778 default:
1779 break;
1780 }
1781
1782 Tcl_DStringEndSublist(strp);
1783 break;
1784
1785 default:
1786 break;
1787 }
1788 }
1789
1790 Tcl_DStringEndSublist(strp);
1791 return (TCL_OK);
1792 }
1793
1794 int
1795 Openattr_res(Tcl_Interp *interp, Tcl_DString *strp, OPENATTR4res *resp)
1796 {
1797 Tcl_DStringStartSublist(strp);
1798 Tcl_DStringAppendElement(strp, "Openattr");
1799 Tcl_DStringAppendElement(strp, errstr(resp->status));
1800 Tcl_DStringEndSublist(strp);
1801 return (TCL_OK);
1802 }
1803
1804 int
1805 Open_confirm_res(Tcl_Interp *interp, Tcl_DString *strp, OPEN_CONFIRM4res *resp)
1806 {
1807 Tcl_DStringStartSublist(strp);
1808 Tcl_DStringAppendElement(strp, "Open_confirm");
1809 Tcl_DStringAppendElement(strp, errstr(resp->status));
1810
1811 if (resp->status == NFS4_OK) {
1812 char buf[80];
1813 stateid4 stateid;
1814
1815 stateid = resp->OPEN_CONFIRM4res_u.resok4.open_stateid;
1816 sprintf(buf, "%lu %s", stateid.seqid,
1817 bin2hex(stateid.other, sizeof (stateid.other)));
1818 Tcl_DStringAppendElement(strp, buf);
1819 }
1820
1821 Tcl_DStringEndSublist(strp);
1822 return (TCL_OK);
1823 }
1824
1825 int
1826 Open_downgrade_res(Tcl_Interp *interp, Tcl_DString *strp,
1827 OPEN_DOWNGRADE4res *resp)
1828 {
1829 Tcl_DStringStartSublist(strp);
1830 Tcl_DStringAppendElement(strp, "Open_downgrade");
1831 Tcl_DStringAppendElement(strp, errstr(resp->status));
1832
1833 if (resp->status == NFS4_OK) {
1834 char buf[80];
1835 stateid4 stateid;
1836
1837 stateid = resp->OPEN_DOWNGRADE4res_u.resok4.open_stateid;
1838 sprintf(buf, "%lu %s", stateid.seqid,
1839 bin2hex(stateid.other, sizeof (stateid.other)));
1840 Tcl_DStringAppendElement(strp, buf);
1841 }
1842
1843 Tcl_DStringEndSublist(strp);
1844 return (TCL_OK);
1845 }
1846
1847 int
1848 Putfh_res(Tcl_Interp *interp, Tcl_DString *strp, PUTFH4res *resp)
1849 {
1850 Tcl_DStringStartSublist(strp);
1851 Tcl_DStringAppendElement(strp, "Putfh");
1852 Tcl_DStringAppendElement(strp, errstr(resp->status));
1853 Tcl_DStringEndSublist(strp);
1854 return (TCL_OK);
1855 }
1856
1857 int
1858 Putpubfh_res(Tcl_Interp *interp, Tcl_DString *strp, PUTPUBFH4res *resp)
1859 {
1860 Tcl_DStringStartSublist(strp);
1861 Tcl_DStringAppendElement(strp, "Putpubfh");
1862 Tcl_DStringAppendElement(strp, errstr(resp->status));
1863 Tcl_DStringEndSublist(strp);
1864 return (TCL_OK);
1865 }
1866
1867 int
1868 Putrootfh_res(Tcl_Interp *interp, Tcl_DString *strp, PUTROOTFH4res *resp)
1869 {
1870 Tcl_DStringStartSublist(strp);
1871 Tcl_DStringAppendElement(strp, "Putrootfh");
1872 Tcl_DStringAppendElement(strp, errstr(resp->status));
1873 Tcl_DStringEndSublist(strp);
1874 return (TCL_OK);
1875 }
1876
1877 int
1878 Read_res(Tcl_Interp *interp, Tcl_DString *strp, READ4res *resp)
1879 {
1880 Tcl_DStringStartSublist(strp);
1881 Tcl_DStringAppendElement(strp, "Read");
1882 Tcl_DStringAppendElement(strp, errstr(resp->status));
1883
1884 if (resp->status == NFS4_OK) {
1885 bool_t eof;
1886 uint_t len;
1887 char *val;
1888 char buf[80];
1889
1890 eof = resp->READ4res_u.resok4.eof;
1891 len = resp->READ4res_u.resok4.data.data_len;
1892 val = resp->READ4res_u.resok4.data.data_val;
1893
1894 Tcl_DStringStartSublist(strp);
1895 sprintf(buf, "eof %s", eof ? "true" : "false");
1896 Tcl_DStringAppendElement(strp, buf);
1897
1898 sprintf(buf, "len %u", len);
1899 Tcl_DStringAppendElement(strp, buf);
1900
1901 if (val != NULL) {
1902 char *np;
1903 np = malloc(len + 1);
1904 snprintf(np, (len + 1), "%s", val);
1905 Tcl_DStringAppendElement(strp, np);
1906 free(np);
1907 }
1908 Tcl_DStringEndSublist(strp);
1909 }
1910
1911 Tcl_DStringEndSublist(strp);
1912 return (TCL_OK);
1913 }
1914
1915 int
1916 Readdir_res(Tcl_Interp *interp, Tcl_DString *strp, READDIR4res *resp)
1917 {
1918 Tcl_DStringStartSublist(strp);
1919 Tcl_DStringAppendElement(strp, "Readdir");
1920 Tcl_DStringAppendElement(strp, errstr(resp->status));
1921
1922 if (resp->status == NFS4_OK) {
1923 nfs_cookie4 cookie;
1924 verifier4 verf;
1925 bool_t eof;
1926 entry4 *d;
1927 bitmap4 bm;
1928 attrlist4 attrvals;
1929
1930 /* The cookie verifier */
1931 (void) memcpy(verf, resp->READDIR4res_u.resok4.cookieverf,
1932 sizeof (verf));
1933 Tcl_DStringAppendElement(strp,
1934 bin2hex(verf, sizeof (verf)));
1935
1936 /* The directory list */
1937 Tcl_DStringStartSublist(strp);
1938 eof = resp->READDIR4res_u.resok4.reply.eof;
1939 for (d = resp->READDIR4res_u.resok4.reply.entries;
1940 d != NULL; d = d->nextentry) {
1941 char buf[64];
1942
1943 Tcl_DStringStartSublist(strp);
1944 sprintf(buf, "%llu", d->cookie);
1945 Tcl_DStringAppendElement(strp, buf);
1946 Tcl_DStringAppendElement(strp, utf82str(d->name));
1947
1948 bm = d->attrs.attrmask;
1949 attrvals = d->attrs.attr_vals;
1950 attr_decode(interp, strp, &bm, &attrvals);
1951 Tcl_DStringEndSublist(strp);
1952 }
1953 Tcl_DStringEndSublist(strp);
1954 Tcl_DStringAppendElement(strp, eof ? "true" : "false");
1955 }
1956
1957 Tcl_DStringEndSublist(strp);
1958 return (TCL_OK);
1959 }
1960
1961 int
1962 Readlink_res(Tcl_Interp *interp, Tcl_DString *strp, READLINK4res *resp)
1963 {
1964 Tcl_DStringStartSublist(strp);
1965 Tcl_DStringAppendElement(strp, "Readlink");
1966 Tcl_DStringAppendElement(strp, errstr(resp->status));
1967
1968 if (resp->status == NFS4_OK) {
1969 linktext4 l;
1970 char buf[256];
1971
1972 l = resp->READLINK4res_u.resok4.link;
1973 snprintf(buf, l.utf8string_len + 1, "%s", l.utf8string_val);
1974 Tcl_DStringAppendElement(strp, buf);
1975 }
1976
1977 Tcl_DStringEndSublist(strp);
1978 return (TCL_OK);
1979 }
1980
1981 int
1982 Release_lockowner_res(Tcl_Interp *interp, Tcl_DString *strp,
1983 RELEASE_LOCKOWNER4res *resp)
1984 {
1985 Tcl_DStringStartSublist(strp);
1986 Tcl_DStringAppendElement(strp, "Release_lockowner");
1987 Tcl_DStringAppendElement(strp, errstr(resp->status));
1988 Tcl_DStringEndSublist(strp);
1989 return (TCL_OK);
1990 }
1991
1992 int
1993 Remove_res(Tcl_Interp *interp, Tcl_DString *strp, REMOVE4res *resp)
1994 {
1995 Tcl_DStringStartSublist(strp);
1996 Tcl_DStringAppendElement(strp, "Remove");
1997 Tcl_DStringAppendElement(strp, errstr(resp->status));
1998
1999 if (resp->status == NFS4_OK) {
2000 change_info4 c;
2001 char buf[80];
2002
2003 c = resp->REMOVE4res_u.resok4.cinfo;
2004 Tcl_DStringStartSublist(strp);
2005
2006 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
2007 Tcl_DStringAppendElement(strp, buf);
2008 sprintf(buf, "before %.8llx", c.before);
2009 Tcl_DStringAppendElement(strp, buf);
2010 sprintf(buf, "after %.8llx", c.after);
2011 Tcl_DStringAppendElement(strp, buf);
2012
2013 Tcl_DStringEndSublist(strp);
2014 }
2015
2016 Tcl_DStringEndSublist(strp);
2017 return (TCL_OK);
2018 }
2019
2020 int
2021 Rename_res(Tcl_Interp *interp, Tcl_DString *strp, RENAME4res *resp)
2022 {
2023 Tcl_DStringStartSublist(strp);
2024 Tcl_DStringAppendElement(strp, "Rename");
2025 Tcl_DStringAppendElement(strp, errstr(resp->status));
2026
2027 if (resp->status == NFS4_OK) {
2028 change_info4 c;
2029 char buf[80];
2030
2031 /* source cinfo */
2032 c = resp->RENAME4res_u.resok4.source_cinfo;
2033 Tcl_DStringStartSublist(strp);
2034 Tcl_DStringAppendElement(strp, "source");
2035
2036 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
2037 Tcl_DStringAppendElement(strp, buf);
2038 sprintf(buf, "before %.8llx", c.before);
2039 Tcl_DStringAppendElement(strp, buf);
2040 sprintf(buf, "after %.8llx", c.after);
2041 Tcl_DStringAppendElement(strp, buf);
2042
2043 Tcl_DStringEndSublist(strp);
2044
2045 /* target cinfo */
2046 c = resp->RENAME4res_u.resok4.target_cinfo;
2047 Tcl_DStringStartSublist(strp);
2048 Tcl_DStringAppendElement(strp, "target");
2049
2050 sprintf(buf, "atomic %s", c.atomic ? "true" : "false");
2051 Tcl_DStringAppendElement(strp, buf);
2052 sprintf(buf, "before %.8llx", c.before);
2053 Tcl_DStringAppendElement(strp, buf);
2054 sprintf(buf, "after %.8llx", c.after);
2055 Tcl_DStringAppendElement(strp, buf);
2056
2057 Tcl_DStringEndSublist(strp);
2058
2059 }
2060
2061 Tcl_DStringEndSublist(strp);
2062 return (TCL_OK);
2063 }
2064
2065 int
2066 Renew_res(Tcl_Interp *interp, Tcl_DString *strp, RENEW4res *resp)
2067 {
2068 Tcl_DStringStartSublist(strp);
2069 Tcl_DStringAppendElement(strp, "Renew");
2070 Tcl_DStringAppendElement(strp, errstr(resp->status));
2071 Tcl_DStringEndSublist(strp);
2072 return (TCL_OK);
2073 }
2074
2075 int
2076 Restorefh_res(Tcl_Interp *interp, Tcl_DString *strp, RESTOREFH4res *resp)
2077 {
2078 Tcl_DStringStartSublist(strp);
2079 Tcl_DStringAppendElement(strp, "Restorefh");
2080 Tcl_DStringAppendElement(strp, errstr(resp->status));
2081 Tcl_DStringEndSublist(strp);
2082 return (TCL_OK);
2083 }
2084
2085 int
2086 Savefh_res(Tcl_Interp *interp, Tcl_DString *strp, SAVEFH4res *resp)
2087 {
2088 Tcl_DStringStartSublist(strp);
2089 Tcl_DStringAppendElement(strp, "Savefh");
2090 Tcl_DStringAppendElement(strp, errstr(resp->status));
2091 Tcl_DStringEndSublist(strp);
2092 return (TCL_OK);
2093 }
2094
2095 int
2096 Secinfo_res(Tcl_Interp *interp, Tcl_DString *strp, SECINFO4res *resp)
2097 {
2098 Tcl_DStringStartSublist(strp);
2099 Tcl_DStringAppendElement(strp, "Secinfo");
2100 Tcl_DStringAppendElement(strp, errstr(resp->status));
2101
2102 if (resp->status == NFS4_OK) {
2103 secinfo4 *sp;
2104 char buf[80];
2105 char buf2[10];
2106 int i;
2107
2108 Tcl_DStringStartSublist(strp);
2109 for (i = 0;
2110 i < resp->SECINFO4res_u.resok4.SECINFO4resok_len;
2111 i++) {
2112
2113 sp = &resp->SECINFO4res_u.resok4.SECINFO4resok_val[i];
2114
2115 if (sp->flavor == AUTH_SYS) {
2116 sprintf(buf, "AUTH_SYS");
2117 } else if (sp->flavor == AUTH_NONE) {
2118 sprintf(buf, "AUTH_NONE");
2119 } else if (sp->flavor == AUTH_DH) {
2120 sprintf(buf, "AUTH_DH");
2121 } else if (sp->flavor == RPCSEC_GSS) {
2122 /*
2123 * XXX used hardcoded mapping here:
2124 * For Solaris,
2125 * KRB5-OID=2A864886F712010202
2126 * (in HEX); * XXX Need HEX
2127 * values for LIBKEY & SPKM3 OID
2128 * mapping as well.
2129 */
2130 char krboid[] = "2A864886F712010202";
2131 char lkeyoid[] = "1.3.6.1.5.5.9";
2132 char spkmoid[] = "1.3.6.1.5.5.1.3";
2133 char *oid;
2134 rpcsec_gss_info rinfo;
2135
2136 sprintf(buf, "RPCSEC_GSS ");
2137 rinfo = sp->secinfo4_u.flavor_info;
2138 oid = bin2hex(rinfo.oid.sec_oid4_val,
2139 rinfo.oid.sec_oid4_len);
2140 if ((strcmp(oid, krboid)) == 0) {
2141 strcat(buf, "KRB5");
2142 } else if ((strcmp(oid, lkeyoid)) == 0) {
2143 strcat(buf, "LIBKEY");
2144 } else if ((strcmp(oid, spkmoid)) == 0) {
2145 strcat(buf, "SPKM3");
2146 } else {
2147 strcat(buf, oid);
2148 }
2149 sprintf(buf2, " %u", rinfo.qop);
2150 strcat(buf, buf2);
2151 switch (rinfo.service) {
2152 case RPC_GSS_SVC_NONE:
2153 strcat(buf, " NONE");
2154 break;
2155 case RPC_GSS_SVC_INTEGRITY:
2156 strcat(buf, " INTEGRITY");
2157 break;
2158 case RPC_GSS_SVC_PRIVACY:
2159 strcat(buf, " PRIVACY");
2160 break;
2161 default:
2162 break;
2163 }
2164 } else { /* unknown flavor, no mapping */
2165 sprintf(buf, "%u", sp->flavor);
2166 }
2167 Tcl_DStringAppendElement(strp, buf);
2168 }
2169 Tcl_DStringEndSublist(strp);
2170 }
2171
2172 Tcl_DStringEndSublist(strp);
2173 return (TCL_OK);
2174 }
2175
2176 int
2177 Setattr_res(Tcl_Interp *interp, Tcl_DString *strp, SETATTR4res *resp)
2178 {
2179 Tcl_DStringStartSublist(strp);
2180 Tcl_DStringAppendElement(strp, "Setattr");
2181 Tcl_DStringAppendElement(strp, errstr(resp->status));
2182
2183 Tcl_DStringStartSublist(strp);
2184 prn_attrname(strp, &resp->attrsset);
2185 Tcl_DStringEndSublist(strp);
2186
2187 Tcl_DStringEndSublist(strp);
2188 return (TCL_OK);
2189 }
2190
2191 int
2192 Setclientid_res(Tcl_Interp *interp, Tcl_DString *strp, SETCLIENTID4res *resp)
2193 {
2194 verifier4 verf;
2195 char buf[80];
2196
2197 Tcl_DStringStartSublist(strp);
2198 Tcl_DStringAppendElement(strp, "Setclientid");
2199 Tcl_DStringAppendElement(strp, errstr(resp->status));
2200
2201 if (resp->status == NFS4_OK) {
2202 /* the setclientid verifier */
2203 (void) memcpy(verf,
2204 resp->SETCLIENTID4res_u.resok4.setclientid_confirm,
2205 sizeof (verf));
2206 sprintf(buf, "%llx %s",
2207 resp->SETCLIENTID4res_u.resok4.clientid,
2208 bin2hex(verf, sizeof (verf)));
2209 } else if (resp->status == NFS4ERR_CLID_INUSE) {
2210 sprintf(buf, "%s %s",
2211 resp->SETCLIENTID4res_u.client_using.r_netid,
2212 resp->SETCLIENTID4res_u.client_using.r_addr);
2213 }
2214 Tcl_DStringAppendElement(strp, buf);
2215 Tcl_DStringEndSublist(strp);
2216
2217 return (TCL_OK);
2218 }
2219
2220 int
2221 Setclientid_confirm_res(Tcl_Interp *interp, Tcl_DString *strp,
2222 SETCLIENTID_CONFIRM4res *resp)
2223 {
2224 Tcl_DStringStartSublist(strp);
2225 Tcl_DStringAppendElement(strp, "Setclientid_confirm");
2226 Tcl_DStringAppendElement(strp, errstr(resp->status));
2227 Tcl_DStringEndSublist(strp);
2228 return (TCL_OK);
2229 }
2230
2231 int
2232 Verify_res(Tcl_Interp *interp, Tcl_DString *strp, VERIFY4res *resp)
2233 {
2234 Tcl_DStringStartSublist(strp);
2235 Tcl_DStringAppendElement(strp, "Verify");
2236 Tcl_DStringAppendElement(strp, errstr(resp->status));
2237 Tcl_DStringEndSublist(strp);
2238 return (TCL_OK);
2239 }
2240
2241 int
2242 Write_res(Tcl_Interp *interp, Tcl_DString *strp, WRITE4res *resp)
2243 {
2244 Tcl_DStringStartSublist(strp);
2245 Tcl_DStringAppendElement(strp, "Write");
2246 Tcl_DStringAppendElement(strp, errstr(resp->status));
2247
2248 if (resp->status == NFS4_OK) {
2249 verifier4 verf;
2250 char buf[81];
2251
2252 /* the write count */
2253 sprintf(buf, "%u ", resp->WRITE4res_u.resok4.count);
2254
2255 /* the stable_how */
2256 switch (resp->WRITE4res_u.resok4.committed) {
2257 case 0:
2258 strcat(buf, "UNSTABLE");
2259 break;
2260 case 1:
2261 strcat(buf, "DATA_SYNC");
2262 break;
2263 case 2:
2264 strcat(buf, "FILE_SYNC");
2265 break;
2266 default:
2267 strcat(buf, "UNKNOWN");
2268 break;
2269 }
2270
2271 /* the write verifier */
2272 (void) memcpy(verf, resp->WRITE4res_u.resok4.writeverf,
2273 sizeof (verf));
2274 strcat(buf, " ");
2275 strcat(buf, bin2hex(verf, sizeof (verf)));
2276 Tcl_DStringAppendElement(strp, buf);
2277 }
2278
2279 Tcl_DStringEndSublist(strp);
2280 return (TCL_OK);
2281 }
2282
2283 /*
2284 * Called to handle a compound result
2285 */
2286 int
2287 compound_result(Tcl_Interp *interp, COMPOUND4res *resp)
2288 {
2289 int ops_complete;
2290 nfs_resop4 *resop;
2291 Tcl_DString str;
2292 int i;
2293 int err = TCL_OK;
2294
2295 Tcl_SetVar(interp, "status", errstr(resp->status), 0);
2296
2297 if (resp->tag.utf8string_val == NULL)
2298 Tcl_SetVar(interp, "tag", "", 0);
2299 else {
2300 Tcl_SetVar(interp, "tag", utf82str(resp->tag), 0);
2301 }
2302
2303 ops_complete = resp->resarray.resarray_len;
2304 Tcl_SetVar(interp, "opcount", itoa(ops_complete), 0);
2305
2306 Tcl_DStringInit(&str);
2307
2308 for (i = 0; i < ops_complete; i++) {
2309 resop = &resp->resarray.resarray_val[i];
2310 switch (resop->resop) {
2311 case OP_ACCESS:
2312 err = Access_res(interp, &str,
2313 &resop->nfs_resop4_u.opaccess);
2314 break;
2315
2316 case OP_CLOSE:
2317 err = Close_res(interp, &str,
2318 &resop->nfs_resop4_u.opclose);
2319 break;
2320
2321 case OP_COMMIT:
2322 err = Commit_res(interp, &str,
2323 &resop->nfs_resop4_u.opcommit);
2324 break;
2325
2326 case OP_CREATE:
2327 err = Create_res(interp, &str,
2328 &resop->nfs_resop4_u.opcreate);
2329 break;
2330
2331 case OP_DELEGPURGE:
2332 err = Delegpurge_res(interp, &str,
2333 &resop->nfs_resop4_u.opdelegpurge);
2334 break;
2335
2336 case OP_DELEGRETURN:
2337 err = Delegreturn_res(interp, &str,
2338 &resop->nfs_resop4_u.opdelegreturn);
2339 break;
2340
2341 case OP_GETATTR:
2342 err = Getattr_res(interp, &str,
2343 &resop->nfs_resop4_u.opgetattr);
2344 break;
2345
2346 case OP_GETFH:
2347 err = Getfh_res(interp, &str,
2348 &resop->nfs_resop4_u.opgetfh);
2349 break;
2350
2351 case OP_ILLEGAL:
2352 err = Illegal_res(interp, &str,
2353 &resop->nfs_resop4_u.opillegal);
2354 break;
2355
2356 case OP_LINK:
2357 err = Link_res(interp, &str,
2358 &resop->nfs_resop4_u.oplink);
2359 break;
2360
2361 case OP_LOCK:
2362 err = Lock_res(interp, &str,
2363 &resop->nfs_resop4_u.oplock);
2364 break;
2365
2366 case OP_LOCKT:
2367 err = Lockt_res(interp, &str,
2368 &resop->nfs_resop4_u.oplockt);
2369 break;
2370
2371 case OP_LOCKU:
2372 err = Locku_res(interp, &str,
2373 &resop->nfs_resop4_u.oplocku);
2374 break;
2375
2376 case OP_LOOKUP:
2377 err = Lookup_res(interp, &str,
2378 &resop->nfs_resop4_u.oplookup);
2379 break;
2380
2381 case OP_LOOKUPP:
2382 err = Lookupp_res(interp, &str,
2383 &resop->nfs_resop4_u.oplookupp);
2384 break;
2385
2386 case OP_NVERIFY:
2387 err = Nverify_res(interp, &str,
2388 &resop->nfs_resop4_u.opnverify);
2389 break;
2390
2391 case OP_OPEN:
2392 err = Open_res(interp, &str,
2393 &resop->nfs_resop4_u.opopen);
2394 break;
2395
2396 case OP_OPENATTR:
2397 err = Openattr_res(interp, &str,
2398 &resop->nfs_resop4_u.opopenattr);
2399 break;
2400
2401 case OP_OPEN_CONFIRM:
2402 err = Open_confirm_res(interp, &str,
2403 &resop->nfs_resop4_u.opopen_confirm);
2404 break;
2405
2406 case OP_OPEN_DOWNGRADE:
2407 err = Open_downgrade_res(interp, &str,
2408 &resop->nfs_resop4_u.opopen_downgrade);
2409 break;
2410
2411 case OP_PUTFH:
2412 err = Putfh_res(interp, &str,
2413 &resop->nfs_resop4_u.opputfh);
2414 break;
2415
2416 case OP_PUTPUBFH:
2417 err = Putpubfh_res(interp, &str,
2418 &resop->nfs_resop4_u.opputpubfh);
2419 break;
2420
2421 case OP_PUTROOTFH:
2422 err = Putrootfh_res(interp, &str,
2423 &resop->nfs_resop4_u.opputrootfh);
2424 break;
2425
2426 case OP_READ:
2427 err = Read_res(interp, &str,
2428 &resop->nfs_resop4_u.opread);
2429 break;
2430
2431 case OP_READDIR:
2432 err = Readdir_res(interp, &str,
2433 &resop->nfs_resop4_u.opreaddir);
2434 break;
2435
2436 case OP_READLINK:
2437 err = Readlink_res(interp, &str,
2438 &resop->nfs_resop4_u.opreadlink);
2439 break;
2440
2441 case OP_RELEASE_LOCKOWNER:
2442 err = Release_lockowner_res(interp, &str,
2443 &resop->nfs_resop4_u.oprelease_lockowner);
2444 break;
2445
2446 case OP_REMOVE:
2447 err = Remove_res(interp, &str,
2448 &resop->nfs_resop4_u.opremove);
2449 break;
2450
2451 case OP_RENAME:
2452 err = Rename_res(interp, &str,
2453 &resop->nfs_resop4_u.oprename);
2454 break;
2455
2456 case OP_RENEW:
2457 err = Renew_res(interp, &str,
2458 &resop->nfs_resop4_u.oprenew);
2459 break;
2460
2461 case OP_RESTOREFH:
2462 err = Restorefh_res(interp, &str,
2463 &resop->nfs_resop4_u.oprestorefh);
2464 break;
2465
2466 case OP_SAVEFH:
2467 err = Savefh_res(interp, &str,
2468 &resop->nfs_resop4_u.opsavefh);
2469 break;
2470
2471 case OP_SECINFO:
2472 err = Secinfo_res(interp, &str,
2473 &resop->nfs_resop4_u.opsecinfo);
2474 break;
2475
2476 case OP_SETATTR:
2477 err = Setattr_res(interp, &str,
2478 &resop->nfs_resop4_u.opsetattr);
2479 break;
2480
2481 case OP_SETCLIENTID:
2482 err = Setclientid_res(interp, &str,
2483 &resop->nfs_resop4_u.opsetclientid);
2484 break;
2485
2486 case OP_SETCLIENTID_CONFIRM:
2487 err = Setclientid_confirm_res(interp, &str,
2488 &resop->nfs_resop4_u.opsetclientid_confirm);
2489 break;
2490
2491 case OP_VERIFY:
2492 err = Verify_res(interp, &str,
2493 &resop->nfs_resop4_u.opverify);
2494 break;
2495
2496 case OP_WRITE:
2497 err = Write_res(interp, &str,
2498 &resop->nfs_resop4_u.opwrite);
2499 break;
2500
2501 default:
2502 (void) sprintf(interp->result,
2503 "Unknown op in result: %d",
2504 resop->resop);
2505 err = TCL_ERROR;
2506 break;
2507 }
2508
2509 if (err != TCL_OK) {
2510 Tcl_DStringFree(&str);
2511 return (err);
2512 }
2513 }
2514
2515 Tcl_DStringResult(interp, &str);
2516
2517 return (TCL_OK);
2518 }
2519
2520 void
2521 op_createcom(Tcl_Interp *interp)
2522 {
2523 int i;
2524
2525 for (i = 0; nfs_op[i].name != NULL; i++) {
2526 Tcl_CreateCommand(interp,
2527 nfs_op[i].name, nfs_op[i].func,
2528 (ClientData) NULL,
2529 (Tcl_CmdDeleteProc *) NULL);
2530 }
2531 }