1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * Test & debug program for the SMB client
18 *
19 * This implements a simple command reader which accepts
20 * commands to simulate system calls into the file system.
21 */
22
23 #include <sys/types.h>
24 #include <sys/file.h>
25 #include <sys/stat.h>
26 #include <sys/mount.h>
27 #include <sys/dirent.h>
28 #include <sys/strlog.h> /* SL_NOTE */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <inttypes.h>
37 #include <unistd.h>
38
39 #include <sys/fs/smbfs_mount.h>
40 #include <netsmb/smb_lib.h>
41 #include <libfknsmb/common/libfknsmb.h>
42 #include <libfksmbfs/common/libfksmbfs.h>
43
44 #if _FILE_OFFSET_BITS != 64
45 #error "This calls (fake) VFS code which requires 64-bit off_t"
46 #endif
47
48 extern int list_shares(struct smb_ctx *);
49
50 #define MAXARG 10
51
52 struct cmd_tbl_ent {
53 void (*ce_func)(int, char **);
54 const char *ce_name;
55 const char *ce_argdesc;
56 };
57 static struct cmd_tbl_ent cmd_tbl[];
58
59 static struct smb_ctx *ctx = NULL;
60 static char *server = NULL;
61
62 static vfs_t *vfsp = NULL;
63
64 static void show_dents(vnode_t *, offset_t *, char *, int);
65 static void run_cli(void);
66
67 #define TBUFSZ 8192
68 static char tbuf[TBUFSZ];
69
70 static void
fksmbcl_usage(void)71 fksmbcl_usage(void)
72 {
73 printf("usage: fksmbcl //user@server (like smbutil)\n");
74 exit(1);
75 }
76
77 int
main(int argc,char * argv[])78 main(int argc, char *argv[])
79 {
80 int error, opt;
81
82 /*
83 * Initializations
84 */
85 nsmb_drv_load();
86 nsmb_drv_init();
87 fksmbfs_init();
88
89 while ((opt = getopt(argc, argv, "dv")) != -1) {
90 switch (opt) {
91 case 'd':
92 smb_debug++;
93 break;
94 case 'v':
95 smb_verbose++;
96 break;
97 case '?':
98 fksmbcl_usage();
99 break;
100 }
101 }
102 if (optind >= argc)
103 fksmbcl_usage();
104 server = argv[optind];
105
106 /*
107 * Setup the libsmbfs context
108 */
109 error = smb_ctx_alloc(&ctx);
110 if (error) {
111 fprintf(stderr, "%s: smb_ctx_alloc failed (%d)\n",
112 argv[0], error);
113 return (1);
114 }
115
116 error = smb_ctx_scan_argv(ctx, argc, argv,
117 SMBL_SERVER, SMBL_SERVER, USE_WILDCARD);
118 if (error) {
119 fprintf(stderr, "logon: smb_ctx_scan_argv, error %d\n", error);
120 return (1);
121 }
122 error = smb_ctx_readrc(ctx);
123 if (error) {
124 fprintf(stderr, "logon: smb_ctx_readrc, error %d\n", error);
125 return (1);
126 }
127
128 /* Do smb_ctx_setshare later, and smb_ctx_resolve. */
129
130 /*
131 * Next would be smb_ctx_get_ssn() but don't do that until
132 * the "logon" command so one can set breakpoints etc.
133 */
134
135 /*
136 * Run the CLI
137 */
138 run_cli();
139
140 /*
141 * Cleanup
142 */
143 fksmbfs_fini();
144 nsmb_drv_fini();
145
146 return (0);
147 }
148
149 static void
run_cli()150 run_cli()
151 {
152 static char cmdbuf[100];
153 int argc, i;
154 char *argv[MAXARG];
155 char *cmd;
156 char *savep = NULL;
157 char *sep = " \t\n";
158 char *prompt = NULL;
159 struct cmd_tbl_ent *ce;
160
161 if (isatty(0)) {
162 fputs("# Start with:\n"
163 "> logon [user [dom [pw]]]\n"
164 "> shares\n"
165 "> mount {share}\n\n",
166 stdout);
167 prompt = "> ";
168 }
169
170 for (;;) {
171 if (prompt) {
172 fputs(prompt, stdout);
173 fflush(stdout);
174 }
175
176 cmd = fgets(cmdbuf, sizeof (cmdbuf), stdin);
177 if (cmd == NULL)
178 break;
179 if (cmd[0] == '#')
180 continue;
181
182 if (prompt == NULL) {
183 /* Put commands in the output too. */
184 fprintf(stdout, "+ %s", cmdbuf);
185 }
186
187 argv[0] = strtok_r(cmd, sep, &savep);
188 if (argv[0] == NULL)
189 continue;
190 for (argc = 1; argc < MAXARG; argc++) {
191 argv[argc] = strtok_r(NULL, sep, &savep);
192 if (argv[argc] == NULL)
193 break;
194 }
195 for (i = argc; i < MAXARG; i++)
196 argv[i++] = NULL;
197
198 for (ce = cmd_tbl; ce->ce_name != NULL; ce++)
199 if (strcmp(ce->ce_name, argv[0]) == 0)
200 break;
201 if (ce->ce_name != NULL) {
202 ce->ce_func(argc, argv);
203 } else {
204 fprintf(stderr, "%s unknown command. Try help\n",
205 argv[0]);
206 }
207 }
208 }
209
210 /*
211 * Command handlers
212 */
213
214 static void
do_exit(int argc,char ** argv)215 do_exit(int argc, char **argv)
216 {
217 exit(0);
218 }
219
220 static void
do_help(int argc,char ** argv)221 do_help(int argc, char **argv)
222 {
223 struct cmd_tbl_ent *ce;
224
225 printf("Commands:\n");
226 for (ce = cmd_tbl; ce->ce_func != NULL; ce++)
227 printf("%s %s\n", ce->ce_name, ce->ce_argdesc);
228 }
229
230 static void
do_logon(int argc,char ** argv)231 do_logon(int argc, char **argv)
232 {
233 int error;
234
235 if (argc > 1) {
236 if (argv[1][0] == '-') {
237 smb_ctx_setuser(ctx, "", B_TRUE);
238 ctx->ct_flags |= SMBCF_NOPWD;
239 } else {
240 smb_ctx_setuser(ctx, argv[1], B_TRUE);
241 }
242 }
243 if (argc > 2)
244 smb_ctx_setdomain(ctx, argv[2], B_TRUE);
245 if (argc > 3)
246 smb_ctx_setpassword(ctx, argv[3], 0);
247
248 /*
249 * Resolve the server address, setup derived defaults.
250 */
251 error = smb_ctx_resolve(ctx);
252 if (error) {
253 fprintf(stderr, "logon: smb_ctx_resolve, error %d\n", error);
254 return;
255 }
256
257 /*
258 * Have server, share, etc. now.
259 * Get the logon session.
260 */
261 again:
262 error = smb_ctx_get_ssn(ctx);
263 if (error == EAUTH) {
264 int err2;
265 err2 = smb_get_authentication(ctx);
266 if (err2 == 0)
267 goto again;
268 }
269 if (error) {
270 fprintf(stderr, "//%s: login failed, error %d\n",
271 ctx->ct_fullserver, error);
272 }
273 }
274
275 /*
276 * Drop session created by the "logon" command.
277 */
278 static void
do_logoff(int argc,char ** argv)279 do_logoff(int argc, char **argv)
280 {
281
282 (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_SSN_RELE, NULL);
283 if (argc > 1) {
284 smb_ctx_done(ctx);
285 (void) smb_ctx_init(ctx);
286 }
287 }
288
289 /*
290 * List shares
291 */
292 static void
do_shares(int argc,char ** argv)293 do_shares(int argc, char **argv)
294 {
295 int error;
296
297 smb_ctx_setshare(ctx, "IPC$", USE_IPC);
298 error = smb_ctx_get_tree(ctx);
299 if (error) {
300 fprintf(stderr, "shares, tcon IPC$, error=%d\n", error);
301 return;
302 }
303
304 error = list_shares(ctx);
305 if (error) {
306 fprintf(stderr, "shares, enum, error=%d\n", error);
307 }
308
309 (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_TREE_RELE, NULL);
310 }
311
312 char mnt_opt_buf[MAX_MNTOPT_STR];
313 char mnt_resource[MAXPATHLEN];
314
315 /*
316 * Minimal excerpt from vfs.c:domount()
317 */
318 void
do_mount(int argc,char ** argv)319 do_mount(int argc, char **argv)
320 {
321 struct smbfs_args mdata;
322 struct mounta ma;
323 char *shrname;
324 int error;
325
326 if (vfsp != NULL) {
327 fprintf(stderr, "Already mounted\n");
328 return;
329 }
330
331 if (argc < 2) {
332 fprintf(stderr, "%s: missing share name\n", argv[0]);
333 return;
334 }
335 shrname = argv[1];
336 if (argc > 2)
337 strlcpy(mnt_opt_buf, argv[2], sizeof (mnt_opt_buf));
338 else
339 memset(mnt_opt_buf, 0, sizeof (mnt_opt_buf));
340
341 smb_ctx_setshare(ctx, shrname, USE_DISKDEV);
342 error = smb_ctx_get_tree(ctx);
343 if (error) {
344 fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
345 server, shrname, error);
346 return;
347 }
348
349 (void) snprintf(mnt_resource, sizeof (mnt_resource),
350 "//%s/%s", ctx->ct_fullserver, shrname);
351
352 bzero(&mdata, sizeof (mdata));
353 mdata.version = SMBFS_VERSION; /* smbfs mount version */
354 mdata.file_mode = S_IRWXU;
355 mdata.dir_mode = S_IRWXU;
356 mdata.devfd = ctx->ct_dev_fd;
357
358 /* Build mount args */
359 bzero(&ma, sizeof (ma));
360 ma.spec = mnt_resource;
361 ma.dir = "/";
362 ma.flags = MS_DATA | MS_OPTIONSTR | MS_NOSPLICE | MS_NOSUID;
363 ma.fstype = "smbfs";
364 ma.dataptr = (void *) &mdata;
365 ma.datalen = sizeof (mdata);
366 ma.optptr = mnt_opt_buf;
367 ma.optlen = sizeof (mnt_opt_buf);
368
369 error = fake_domount("smbfs", &ma, &vfsp);
370 if (error != 0) {
371 fprintf(stderr, "domount error=%d\n", error);
372 }
373
374 /* Mount takes a ref, so always rele here. */
375 (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_TREE_RELE, NULL);
376 }
377
378 void
do_unmount(int argc,char ** argv)379 do_unmount(int argc, char **argv)
380 {
381 int error;
382
383 if (vfsp == NULL) {
384 fprintf(stderr, "Not mounted\n");
385 return;
386 }
387
388 error = fake_dounmount(vfsp, 0);
389 if (error != 0) {
390 fprintf(stderr, "dounmount error=%d\n", error);
391 return;
392 }
393 vfsp = NULL;
394 }
395
396 void
do_statfs(int argc,char ** argv)397 do_statfs(int argc, char **argv)
398 {
399 statvfs64_t st;
400 int error;
401
402 if (vfsp == NULL) {
403 fprintf(stderr, "Not mounted\n");
404 return;
405 }
406
407 error = fsop_statfs(vfsp, &st);
408 if (error != 0) {
409 fprintf(stderr, "df error=%d\n", error);
410 return;
411 }
412 printf("bsize=%ld\n", st.f_bsize);
413 printf("frsize=%ld\n", st.f_frsize);
414 printf("blocks=%" PRIu64 "\n", st.f_blocks);
415 printf(" bfree=%" PRIu64 "\n", st.f_bfree);
416 printf("bavail=%" PRIu64 "\n", st.f_bavail);
417 }
418
419 void
do_dir(int argc,char ** argv)420 do_dir(int argc, char **argv)
421 {
422 char *rdir;
423 vnode_t *vp = NULL;
424 offset_t off;
425 int cnt;
426 int error;
427
428 if (vfsp == NULL) {
429 fprintf(stderr, "mnt required first\n");
430 return;
431 }
432 if (argc > 1)
433 rdir = argv[1];
434 else
435 rdir = "";
436
437 error = vn_open(rdir, 0, FREAD, 0, &vp, 0, 0);
438 if (error != 0) {
439 fprintf(stderr, "do_dir, vn_open error=%d\n", error);
440 return;
441 }
442
443 off = 0;
444 do {
445 cnt = fake_getdents(vp, &off, tbuf, TBUFSZ);
446 if (cnt < 0) {
447 fprintf(stderr, "do_dir, getdents %d\n", -cnt);
448 break;
449 }
450 show_dents(vp, &off, tbuf, cnt);
451 } while (cnt > 0);
452
453 if (vp != NULL)
454 vn_close_rele(vp, 0);
455 }
456
457 void
do_dirx(int argc,char ** argv)458 do_dirx(int argc, char **argv)
459 {
460 char *rdir;
461 vnode_t *vp = NULL;
462 offset_t off;
463 int cnt;
464 int error;
465
466 if (vfsp == NULL) {
467 fprintf(stderr, "mnt required first\n");
468 return;
469 }
470 if (argc > 1)
471 rdir = argv[1];
472 else
473 rdir = "";
474
475 error = vn_open(rdir, 0, FREAD|FXATTRDIROPEN, 0, &vp, 0, 0);
476 if (error != 0) {
477 fprintf(stderr, "do_dirx, vn_open error=%d\n", error);
478 return;
479 }
480
481 off = 0;
482 do {
483 cnt = fake_getdents(vp, &off, tbuf, TBUFSZ);
484 if (cnt < 0) {
485 fprintf(stderr, "do_dirx, getdents %d\n", -cnt);
486 break;
487 }
488 show_dents(vp, &off, tbuf, cnt);
489 } while (cnt > 0);
490
491 if (vp != NULL)
492 vn_close_rele(vp, 0);
493 }
494
495 static void
show_dents(vnode_t * dvp,offset_t * offp,char * buf,int cnt)496 show_dents(vnode_t *dvp, offset_t *offp, char *buf, int cnt)
497 {
498 char time_buf[40];
499 struct stat64 st;
500 vnode_t *vp;
501 char *p;
502 dirent_t *d;
503 offset_t offset = (offset_t)-1L;
504 int error;
505 uint_t mode;
506 char type;
507
508 p = buf;
509 while (p < (buf + cnt)) {
510 d = (dirent_t *)(void *)p;
511 p += d->d_reclen;
512 offset = d->d_off;
513
514 error = fake_lookup(dvp, d->d_name, &vp);
515 if (error != 0) {
516 fprintf(stderr, "%s: lookup error=%d\n",
517 d->d_name, error);
518 continue;
519 }
520 error = fake_stat(vp, &st, 0);
521 vn_rele(vp);
522 if (error != 0) {
523 fprintf(stderr, "%s: stat error=%d\n",
524 d->d_name, error);
525 continue;
526 }
527
528 /*
529 * Print type, mode, size, name
530 * First mode (only dir, file expected here)
531 */
532 if (S_ISDIR(st.st_mode)) {
533 type = 'd';
534 } else if (S_ISREG(st.st_mode)) {
535 type = ' ';
536 } else {
537 type = '?';
538 }
539 mode = st.st_mode & 0777;
540 (void) strftime(time_buf, sizeof (time_buf),
541 "%b %e %T %Y", localtime(&st.st_mtime));
542
543 printf("%c 0%3o %9" PRIu64 " %s %s\n",
544 type, mode,
545 (uint64_t)st.st_size,
546 time_buf,
547 d->d_name);
548 }
549 *offp = offset;
550 }
551
552 /*
553 * get rname [lname]
554 */
555 void
do_get(int argc,char ** argv)556 do_get(int argc, char **argv)
557 {
558 struct stat64 st;
559 char *rname;
560 char *lname;
561 vnode_t *vp = NULL;
562 offset_t off;
563 ssize_t cnt, x;
564 int oflg = O_RDWR | O_CREAT;
565 int lfd = -1;
566 int error;
567
568 if (vfsp == NULL) {
569 fprintf(stderr, "mnt required first\n");
570 return;
571 }
572 if (argc < 2) {
573 fprintf(stderr, "rname required\n");
574 return;
575 }
576 rname = argv[1];
577 if (argc > 2) {
578 lname = argv[2];
579 /*
580 * When local name is specified, overwrite.
581 * Convenient for scripts etc.
582 */
583 oflg |= O_TRUNC;
584 } else {
585 lname = rname;
586 /* Local file should not exist. */
587 oflg |= O_EXCL;
588 }
589
590 lfd = open(lname, oflg, 0644);
591 if (lfd < 0) {
592 perror(lname);
593 return;
594 }
595
596 error = vn_open(rname, 0, FREAD, 0, &vp, 0, 0);
597 if (error != 0) {
598 fprintf(stderr, "do_get, vn_open error=%d\n", error);
599 goto out;
600 }
601 error = fake_stat(vp, &st, 0);
602 if (error != 0) {
603 fprintf(stderr, "do_get, stat error=%d\n", error);
604 goto out;
605 }
606
607 off = 0;
608 do {
609 cnt = fake_pread(vp, tbuf, TBUFSZ, off);
610 if (cnt < 0) {
611 fprintf(stderr, "do_get, read %d\n", -cnt);
612 goto out;
613 }
614 x = write(lfd, tbuf, cnt);
615 if (x < 0) {
616 fprintf(stderr, "do_get, write %d\n", errno);
617 goto out;
618 }
619 off += x;
620 } while (off < st.st_size);
621
622 out:
623 if (vp != NULL)
624 vn_close_rele(vp, 0);
625 if (lfd != -1)
626 close(lfd);
627 }
628
629 /*
630 * put lname [rname]
631 */
632 void
do_put(int argc,char ** argv)633 do_put(int argc, char **argv)
634 {
635 struct stat64 rst;
636 struct stat st;
637 char *rname;
638 char *lname;
639 vnode_t *vp = NULL;
640 offset_t off;
641 ssize_t cnt, x;
642 int oflg = FREAD|FWRITE|FCREAT;
643 int lfd = -1;
644 int error;
645
646 if (vfsp == NULL) {
647 fprintf(stderr, "mnt required first\n");
648 return;
649 }
650 if (argc < 2) {
651 fprintf(stderr, "lname required\n");
652 return;
653 }
654 lname = argv[1];
655 if (argc > 2) {
656 rname = argv[2];
657 /*
658 * When remote name is specified, overwrite.
659 * Convenient for scripts etc.
660 */
661 oflg |= FTRUNC;
662 } else {
663 rname = lname;
664 /* Remote file should not exist. */
665 oflg |= FEXCL;
666 }
667
668 lfd = open(lname, O_RDONLY, 0);
669 if (lfd < 0) {
670 perror(lname);
671 return;
672 }
673 error = fstat(lfd, &st);
674 if (error != 0) {
675 fprintf(stderr, "do_put, stat error=%d\n", error);
676 goto out;
677 }
678
679 error = vn_open(rname, 0, oflg, 0, &vp, 0, 0);
680 if (error != 0) {
681 fprintf(stderr, "do_put, vn_open error=%d\n", error);
682 goto out;
683 }
684
685 off = 0;
686 do {
687 cnt = pread(lfd, tbuf, TBUFSZ, off);
688 if (cnt < 0) {
689 fprintf(stderr, "do_put, read %d\n", errno);
690 goto out;
691 }
692 x = fake_pwrite(vp, tbuf, cnt, off);
693 if (x < 0) {
694 fprintf(stderr, "do_put, write %d\n", -x);
695 goto out;
696 }
697 off += cnt;
698 } while (off < st.st_size);
699
700 /* This getattr should go OtW. */
701 error = fake_stat(vp, &rst, 0);
702 if (error != 0) {
703 fprintf(stderr, "do_put, stat error=%d\n", error);
704 goto out;
705 }
706 if (rst.st_size != st.st_size) {
707 fprintf(stderr, "do_put, wrong size?\n");
708 }
709
710 out:
711 if (vp != NULL)
712 vn_close_rele(vp, 0);
713 if (lfd != -1)
714 close(lfd);
715 }
716
717 /*
718 * rm rname
719 */
720 void
do_rm(int argc,char ** argv)721 do_rm(int argc, char **argv)
722 {
723 char *rname;
724 int error;
725
726 if (vfsp == NULL) {
727 fprintf(stderr, "mnt required first\n");
728 return;
729 }
730 if (argc < 2) {
731 fprintf(stderr, "rname required\n");
732 return;
733 }
734 rname = argv[1];
735
736 error = fake_unlink(rname, 0);
737 if (error != 0) {
738 fprintf(stderr, "do_rm, unlink error=%d\n", error);
739 }
740 }
741
742 /*
743 * mv fromname toname
744 */
745 void
do_mv(int argc,char ** argv)746 do_mv(int argc, char **argv)
747 {
748 int error;
749
750 if (vfsp == NULL) {
751 fprintf(stderr, "mnt required first\n");
752 return;
753 }
754 if (argc < 3) {
755 fprintf(stderr, "from_name to_name required\n");
756 return;
757 }
758
759 error = fake_rename(argv[1], argv[2]);
760 if (error != 0) {
761 fprintf(stderr, "do_mv, rename error=%d\n", error);
762 }
763 }
764
765 /*
766 * mkdir rname
767 */
768 void
do_mkdir(int argc,char ** argv)769 do_mkdir(int argc, char **argv)
770 {
771 char *rname;
772 vnode_t *vp = NULL;
773 int error;
774
775 if (vfsp == NULL) {
776 fprintf(stderr, "mnt required first\n");
777 return;
778 }
779 if (argc < 2) {
780 fprintf(stderr, "rname required\n");
781 return;
782 }
783 rname = argv[1];
784
785 error = vn_open(rname, 0, FCREAT, 0, &vp, CRMKDIR, 0);
786 if (error != 0) {
787 fprintf(stderr, "do_mkdir, vn_open error=%d\n", error);
788 }
789
790 if (vp != NULL)
791 vn_close_rele(vp, 0);
792 }
793
794 /*
795 * rmdir rname
796 */
797 void
do_rmdir(int argc,char ** argv)798 do_rmdir(int argc, char **argv)
799 {
800 char *rname;
801 int error;
802
803 if (vfsp == NULL) {
804 fprintf(stderr, "mnt required first\n");
805 return;
806 }
807 if (argc < 2) {
808 fprintf(stderr, "rname required\n");
809 return;
810 }
811 rname = argv[1];
812
813 error = fake_unlink(rname, AT_REMOVEDIR);
814 if (error != 0) {
815 fprintf(stderr, "do_rmdir, unlink error=%d\n", error);
816 }
817 }
818
819 /*
820 * Simple option setting
821 *
822 * Each arg is handled as one line in .nsmbrc [default]
823 */
824 void
do_opt(int argc,char ** argv)825 do_opt(int argc, char **argv)
826 {
827 static char template[20] = "/tmp/fksmbclXXXXXX";
828 static char rcname[30];
829 char *tdname;
830 char *save_home;
831 FILE *fp;
832 int err, i;
833
834 if (argc < 2) {
835 fprintf(stderr, "opt {key}[=value]\n");
836 return;
837 }
838
839 tdname = mkdtemp(template);
840 if (tdname == NULL) {
841 perror("mkdtemp");
842 return;
843 }
844 (void) snprintf(rcname, sizeof (rcname),
845 "%s/.nsmbrc", tdname);
846
847 fp = fopen(rcname, "w");
848 if (fp == NULL) {
849 perror(rcname);
850 goto out;
851 }
852 fprintf(fp, "[default]\n");
853 for (i = 1; i < argc; i++)
854 fprintf(fp, "%s\n", argv[i]);
855 fclose(fp);
856
857 save_home = ctx->ct_home;
858 ctx->ct_home = tdname;
859 err = smb_ctx_readrc(ctx);
860 ctx->ct_home = save_home;
861
862 if (err != 0)
863 fprintf(stderr, "readrc, err=%d\n", err);
864
865 out:
866 (void) unlink(rcname);
867 (void) rmdir(tdname);
868 }
869
870 /*
871 * Command table
872 */
873 static struct cmd_tbl_ent
874 cmd_tbl[] = {
875 { do_help, "help", "" },
876 { do_exit, "exit", "" },
877 { do_logon, "logon", "[user [dom [pass]]]" },
878 { do_logoff, "logoff", "[close-driver]" },
879 { do_shares, "shares", "" },
880 { do_mount, "mount", "{share} [optstr]" },
881 { do_unmount, "umount", "" },
882 { do_unmount, "unmount", "" },
883 { do_statfs, "statfs", "" },
884 { do_dir, "dir", "{rdir} [lfile]" },
885 { do_dirx, "dirx", "{rdir} [lfile]" },
886 { do_get, "get", "{rfile} [lfile]" },
887 { do_put, "put", "{lfile} [rfile]" },
888 { do_mv, "mv", "{from} {to}" },
889 { do_rm, "rm", "{rfile}" },
890 { do_mkdir, "mkdir", "{rfile}" },
891 { do_rmdir, "rmdir", "{rfile}" },
892 { do_opt, "opt", "{option}" },
893 { NULL, NULL, NULL }
894 };
895
896 /*
897 * Provide a real function (one that prints something) to replace
898 * the stub in libfakekernel. This prints cmn_err() messages.
899 */
900 void
fakekernel_putlog(char * msg,size_t len,int flags)901 fakekernel_putlog(char *msg, size_t len, int flags)
902 {
903
904 /*
905 * [CE_CONT, CE_NOTE, CE_WARN, CE_PANIC] maps to
906 * [SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL]
907 */
908 if (smb_debug == 0 && (flags & SL_NOTE))
909 return;
910 (void) fwrite(msg, 1, len, stdout);
911 (void) fflush(stdout);
912 }
913
914 /*
915 * Print nsmb debug messages via driver smb_debugmsg()
916 */
917 void
smb_debugmsg(const char * func,char * msg)918 smb_debugmsg(const char *func, char *msg)
919 {
920 if (smb_debug < 2)
921 return;
922 printf("[kmod] %s: %s\n", func, msg);
923 }
924
925 /*
926 * Enable libumem debugging
927 */
928 const char *
_umem_debug_init(void)929 _umem_debug_init(void)
930 {
931 return ("default,verbose"); /* $UMEM_DEBUG setting */
932 }
933
934 const char *
_umem_logging_init(void)935 _umem_logging_init(void)
936 {
937 return ("fail,contents"); /* $UMEM_LOGGING setting */
938 }
939