• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/torture/
1/*
2   Unix SMB/CIFS implementation.
3   VFS module functions
4
5   Copyright (C) Simo Sorce 2002
6   Copyright (C) Eric Lorimer 2002
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "vfstest.h"
24
25static const char *null_string = "";
26
27static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
28{
29	int i;
30
31	if (argc < 2) {
32		printf("Usage: load <modules>\n");
33		return NT_STATUS_OK;
34	}
35
36	for (i=argc-1;i>0;i--) {
37		if (!vfs_init_custom(vfs->conn, argv[i])) {
38			DEBUG(0, ("load: (vfs_init_custom failed for %s)\n", argv[i]));
39			return NT_STATUS_UNSUCCESSFUL;
40		}
41	}
42	printf("load: ok\n");
43	return NT_STATUS_OK;
44}
45
46static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
47{
48	char c;
49	size_t size;
50	if (argc != 3) {
51		printf("Usage: populate <char> <size>\n");
52		return NT_STATUS_OK;
53	}
54	c = argv[1][0];
55	size = atoi(argv[2]);
56	vfs->data = TALLOC_ARRAY(mem_ctx, char, size);
57	if (vfs->data == NULL) {
58		printf("populate: error=-1 (not enough memory)");
59		return NT_STATUS_UNSUCCESSFUL;
60	}
61	memset(vfs->data, c, size);
62	vfs->data_size = size;
63	return NT_STATUS_OK;
64}
65
66static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
67{
68	size_t offset;
69	size_t len;
70	if (argc != 1 && argc != 3) {
71		printf("Usage: showdata [<offset> <len>]\n");
72		return NT_STATUS_OK;
73	}
74	if (vfs->data == NULL || vfs->data_size == 0) {
75		printf("show_data: error=-1 (buffer empty)\n");
76		return NT_STATUS_UNSUCCESSFUL;
77	}
78
79	if (argc == 3) {
80		offset = atoi(argv[1]);
81		len = atoi(argv[2]);
82	} else {
83		offset = 0;
84		len = vfs->data_size;
85	}
86	if ((offset + len) > vfs->data_size) {
87		printf("show_data: error=-1 (not enough data in buffer)\n");
88		return NT_STATUS_UNSUCCESSFUL;
89	}
90	dump_data(0, (uint8 *)(vfs->data) + offset, len);
91	return NT_STATUS_OK;
92}
93
94static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
95{
96	SMB_VFS_CONNECT(vfs->conn, lp_servicename(SNUM(vfs->conn)), "vfstest");
97	return NT_STATUS_OK;
98}
99
100static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
101{
102	SMB_VFS_DISCONNECT(vfs->conn);
103	return NT_STATUS_OK;
104}
105
106static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
107{
108	uint64_t diskfree, bsize, dfree, dsize;
109	if (argc != 2) {
110		printf("Usage: disk_free <path>\n");
111		return NT_STATUS_OK;
112	}
113
114	diskfree = SMB_VFS_DISK_FREE(vfs->conn, argv[1], False, &bsize, &dfree, &dsize);
115	printf("disk_free: %lu, bsize = %lu, dfree = %lu, dsize = %lu\n",
116			(unsigned long)diskfree,
117			(unsigned long)bsize,
118			(unsigned long)dfree,
119			(unsigned long)dsize);
120	return NT_STATUS_OK;
121}
122
123
124static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
125{
126	if (argc != 2) {
127		printf("Usage: opendir <fname>\n");
128		return NT_STATUS_OK;
129	}
130
131	vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, argv[1], NULL, 0);
132	if (vfs->currentdir == NULL) {
133		printf("opendir error=%d (%s)\n", errno, strerror(errno));
134		return NT_STATUS_UNSUCCESSFUL;
135	}
136
137	printf("opendir: ok\n");
138	return NT_STATUS_OK;
139}
140
141
142static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
143{
144	SMB_STRUCT_STAT st;
145	SMB_STRUCT_DIRENT *dent = NULL;
146
147	if (vfs->currentdir == NULL) {
148		printf("readdir: error=-1 (no open directory)\n");
149		return NT_STATUS_UNSUCCESSFUL;
150	}
151
152	dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir, &st);
153	if (dent == NULL) {
154		printf("readdir: NULL\n");
155		return NT_STATUS_OK;
156	}
157
158	printf("readdir: %s\n", dent->d_name);
159	if (VALID_STAT(st)) {
160		time_t tmp_time;
161		printf("  stat available");
162		if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
163		else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
164		else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
165		else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
166		else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
167		else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
168		else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
169		printf("  Size: %10u", (unsigned int)st.st_ex_size);
170#ifdef HAVE_STAT_ST_BLOCKS
171		printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
172#endif
173#ifdef HAVE_STAT_ST_BLKSIZE
174		printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
175#endif
176		printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
177		printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
178		printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
179		printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
180		printf(" Uid: %5lu Gid: %5lu\n",
181		       (unsigned long)st.st_ex_uid,
182		       (unsigned long)st.st_ex_gid);
183		tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
184		printf("  Access: %s", ctime(&tmp_time));
185		tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
186		printf("  Modify: %s", ctime(&tmp_time));
187		tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
188		printf("  Change: %s", ctime(&tmp_time));
189	}
190
191	return NT_STATUS_OK;
192}
193
194
195static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
196{
197	if (argc != 2) {
198		printf("Usage: mkdir <path>\n");
199		return NT_STATUS_OK;
200	}
201
202	if (SMB_VFS_MKDIR(vfs->conn, argv[1], 00755) == -1) {
203		printf("mkdir error=%d (%s)\n", errno, strerror(errno));
204		return NT_STATUS_UNSUCCESSFUL;
205	}
206
207	printf("mkdir: ok\n");
208	return NT_STATUS_OK;
209}
210
211
212static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
213{
214	int ret;
215
216	if (vfs->currentdir == NULL) {
217		printf("closedir: failure (no directory open)\n");
218		return NT_STATUS_UNSUCCESSFUL;
219	}
220
221	ret = SMB_VFS_CLOSEDIR(vfs->conn, vfs->currentdir);
222	if (ret == -1) {
223		printf("closedir failure: %s\n", strerror(errno));
224		return NT_STATUS_UNSUCCESSFUL;
225	}
226
227	printf("closedir: ok\n");
228	vfs->currentdir = NULL;
229	return NT_STATUS_OK;
230}
231
232
233static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
234{
235	int flags;
236	mode_t mode;
237	const char *flagstr;
238	files_struct *fsp;
239	struct smb_filename *smb_fname = NULL;
240	NTSTATUS status;
241
242	mode = 00400;
243
244	if (argc < 3 || argc > 5) {
245		printf("Usage: open <filename> <flags> <mode>\n");
246		printf("  flags: O = O_RDONLY\n");
247		printf("         R = O_RDWR\n");
248		printf("         W = O_WRONLY\n");
249		printf("         C = O_CREAT\n");
250	       	printf("         E = O_EXCL\n");
251	       	printf("         T = O_TRUNC\n");
252	       	printf("         A = O_APPEND\n");
253	       	printf("         N = O_NONBLOCK/O_NDELAY\n");
254#ifdef O_SYNC
255	       	printf("         S = O_SYNC\n");
256#endif
257#ifdef O_NOFOLLOW
258	       	printf("         F = O_NOFOLLOW\n");
259#endif
260		printf("  mode: see open.2\n");
261		printf("        mode is ignored if C flag not present\n");
262		printf("        mode defaults to 00400\n");
263		return NT_STATUS_OK;
264	}
265	flags = 0;
266	flagstr = argv[2];
267	while (*flagstr) {
268		switch (*flagstr) {
269		case 'O':
270			flags |= O_RDONLY;
271			break;
272		case 'R':
273			flags |= O_RDWR;
274			break;
275		case 'W':
276			flags |= O_WRONLY;
277			break;
278		case 'C':
279			flags |= O_CREAT;
280			break;
281		case 'E':
282			flags |= O_EXCL;
283			break;
284		case 'T':
285			flags |= O_TRUNC;
286			break;
287		case 'A':
288			flags |= O_APPEND;
289			break;
290		case 'N':
291			flags |= O_NONBLOCK;
292			break;
293#ifdef O_SYNC
294		case 'S':
295			flags |= O_SYNC;
296			break;
297#endif
298#ifdef O_NOFOLLOW
299		case 'F':
300			flags |= O_NOFOLLOW;
301			break;
302#endif
303		default:
304			printf("open: error=-1 (invalid flag!)\n");
305			return NT_STATUS_UNSUCCESSFUL;
306		}
307		flagstr++;
308	}
309	if ((flags & O_CREAT) && argc == 4) {
310		if (sscanf(argv[3], "%ho", (unsigned short *)&mode) == 0) {
311			printf("open: error=-1 (invalid mode!)\n");
312			return NT_STATUS_UNSUCCESSFUL;
313		}
314	}
315
316	fsp = SMB_MALLOC_P(struct files_struct);
317	if (fsp == NULL) {
318		return NT_STATUS_NO_MEMORY;
319	}
320	fsp->fh = SMB_MALLOC_P(struct fd_handle);
321	if (fsp->fh == NULL) {
322		SAFE_FREE(fsp->fsp_name);
323		SAFE_FREE(fsp);
324		return NT_STATUS_NO_MEMORY;
325	}
326	fsp->conn = vfs->conn;
327
328	status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
329						  &smb_fname);
330	if (!NT_STATUS_IS_OK(status)) {
331		SAFE_FREE(fsp);
332		return status;
333	}
334
335	fsp->fsp_name = smb_fname;
336
337	fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode);
338	if (fsp->fh->fd == -1) {
339		printf("open: error=%d (%s)\n", errno, strerror(errno));
340		SAFE_FREE(fsp->fh);
341		SAFE_FREE(fsp);
342		TALLOC_FREE(smb_fname);
343		return NT_STATUS_UNSUCCESSFUL;
344	}
345
346	vfs->files[fsp->fh->fd] = fsp;
347	printf("open: fd=%d\n", fsp->fh->fd);
348	return NT_STATUS_OK;
349}
350
351
352static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
353{
354	int ret = -1;
355
356	if (argc != 2) {
357		printf("Usage: %s <path>\n", argv[0]);
358		return NT_STATUS_OK;
359	}
360
361	if (strcmp("rmdir", argv[0]) == 0 ) {
362		ret = SMB_VFS_RMDIR(vfs->conn, argv[1]);
363	} else if (strcmp("unlink", argv[0]) == 0 ) {
364		struct smb_filename *smb_fname = NULL;
365		NTSTATUS status;
366
367		status = create_synthetic_smb_fname_split(mem_ctx, argv[1],
368							  NULL, &smb_fname);
369		if (!NT_STATUS_IS_OK(status)) {
370			return status;
371		}
372
373		ret = SMB_VFS_UNLINK(vfs->conn, smb_fname);
374		TALLOC_FREE(smb_fname);
375	} else if (strcmp("chdir", argv[0]) == 0 ) {
376		ret = SMB_VFS_CHDIR(vfs->conn, argv[1]);
377	} else {
378		printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
379		return NT_STATUS_UNSUCCESSFUL;
380	}
381
382	if (ret == -1) {
383		printf("%s: error=%d (%s)\n", argv[0], errno, strerror(errno));
384		return NT_STATUS_UNSUCCESSFUL;
385	}
386
387	printf("%s: ok\n", argv[0]);
388	return NT_STATUS_OK;
389}
390
391
392static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
393{
394	int fd, ret;
395
396	if (argc != 2) {
397		printf("Usage: close <fd>\n");
398		return NT_STATUS_OK;
399	}
400
401	fd = atoi(argv[1]);
402	if (vfs->files[fd] == NULL) {
403		printf("close: error=-1 (invalid file descriptor)\n");
404		return NT_STATUS_OK;
405	}
406
407	ret = SMB_VFS_CLOSE(vfs->files[fd]);
408	if (ret == -1 )
409		printf("close: error=%d (%s)\n", errno, strerror(errno));
410	else
411		printf("close: ok\n");
412
413	TALLOC_FREE(vfs->files[fd]->fsp_name);
414	SAFE_FREE(vfs->files[fd]->fh);
415	SAFE_FREE(vfs->files[fd]);
416	vfs->files[fd] = NULL;
417	return NT_STATUS_OK;
418}
419
420
421static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
422{
423	int fd;
424	size_t size, rsize;
425
426	if (argc != 3) {
427		printf("Usage: read <fd> <size>\n");
428		return NT_STATUS_OK;
429	}
430
431	/* do some error checking on these */
432	fd = atoi(argv[1]);
433	size = atoi(argv[2]);
434	vfs->data = TALLOC_ARRAY(mem_ctx, char, size);
435	if (vfs->data == NULL) {
436		printf("read: error=-1 (not enough memory)");
437		return NT_STATUS_UNSUCCESSFUL;
438	}
439	vfs->data_size = size;
440
441	rsize = SMB_VFS_READ(vfs->files[fd], vfs->data, size);
442	if (rsize == -1) {
443		printf("read: error=%d (%s)\n", errno, strerror(errno));
444		return NT_STATUS_UNSUCCESSFUL;
445	}
446
447	printf("read: ok\n");
448	return NT_STATUS_OK;
449}
450
451
452static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
453{
454	int fd, size, wsize;
455
456	if (argc != 3) {
457		printf("Usage: write <fd> <size>\n");
458		return NT_STATUS_OK;
459	}
460
461	/* some error checking should go here */
462	fd = atoi(argv[1]);
463	size = atoi(argv[2]);
464	if (vfs->data == NULL) {
465		printf("write: error=-1 (buffer empty, please populate it before writing)");
466		return NT_STATUS_UNSUCCESSFUL;
467	}
468
469	if (vfs->data_size < size) {
470		printf("write: error=-1 (buffer too small, please put some more data in)");
471		return NT_STATUS_UNSUCCESSFUL;
472	}
473
474	wsize = SMB_VFS_WRITE(vfs->files[fd], vfs->data, size);
475
476	if (wsize == -1) {
477		printf("write: error=%d (%s)\n", errno, strerror(errno));
478		return NT_STATUS_UNSUCCESSFUL;
479	}
480
481	printf("write: ok\n");
482	return NT_STATUS_OK;
483}
484
485
486static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
487{
488	int fd, offset, whence;
489	SMB_OFF_T pos;
490
491	if (argc != 4) {
492		printf("Usage: lseek <fd> <offset> <whence>\n...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END\n");
493		return NT_STATUS_OK;
494	}
495
496	fd = atoi(argv[1]);
497	offset = atoi(argv[2]);
498	whence = atoi(argv[3]);
499	switch (whence) {
500		case 1:		whence = SEEK_SET; break;
501		case 2:		whence = SEEK_CUR; break;
502		default:	whence = SEEK_END;
503	}
504
505	pos = SMB_VFS_LSEEK(vfs->files[fd], offset, whence);
506	if (pos == (SMB_OFF_T)-1) {
507		printf("lseek: error=%d (%s)\n", errno, strerror(errno));
508		return NT_STATUS_UNSUCCESSFUL;
509	}
510
511	printf("lseek: ok\n");
512	return NT_STATUS_OK;
513}
514
515
516static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
517{
518	int ret;
519	struct smb_filename *smb_fname_src = NULL;
520	struct smb_filename *smb_fname_dst = NULL;
521	NTSTATUS status;
522
523	if (argc != 3) {
524		printf("Usage: rename <old> <new>\n");
525		return NT_STATUS_OK;
526	}
527
528	status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
529						  &smb_fname_src);
530	if (!NT_STATUS_IS_OK(status)) {
531		return status;
532	}
533
534	status = create_synthetic_smb_fname_split(mem_ctx, argv[2], NULL,
535						  &smb_fname_dst);
536	if (!NT_STATUS_IS_OK(status)) {
537		TALLOC_FREE(smb_fname_src);
538		return status;
539	}
540
541	ret = SMB_VFS_RENAME(vfs->conn, smb_fname_src, smb_fname_dst);
542	TALLOC_FREE(smb_fname_src);
543	TALLOC_FREE(smb_fname_dst);
544	if (ret == -1) {
545		printf("rename: error=%d (%s)\n", errno, strerror(errno));
546		return NT_STATUS_UNSUCCESSFUL;
547	}
548
549	printf("rename: ok\n");
550	return NT_STATUS_OK;
551}
552
553
554static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
555{
556	int ret, fd;
557	if (argc != 2) {
558		printf("Usage: fsync <fd>\n");
559		return NT_STATUS_OK;
560	}
561
562	fd = atoi(argv[1]);
563	ret = SMB_VFS_FSYNC(vfs->files[fd]);
564	if (ret == -1) {
565		printf("fsync: error=%d (%s)\n", errno, strerror(errno));
566		return NT_STATUS_UNSUCCESSFUL;
567	}
568
569	printf("fsync: ok\n");
570	return NT_STATUS_OK;
571}
572
573
574static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
575{
576	int ret;
577	const char *user;
578	const char *group;
579	struct passwd *pwd = NULL;
580	struct group *grp = NULL;
581	struct smb_filename *smb_fname = NULL;
582	SMB_STRUCT_STAT st;
583	time_t tmp_time;
584	NTSTATUS status;
585
586	if (argc != 2) {
587		printf("Usage: stat <fname>\n");
588		return NT_STATUS_OK;
589	}
590
591	status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
592						  &smb_fname);
593	if (!NT_STATUS_IS_OK(status)) {
594		return status;
595	}
596
597	ret = SMB_VFS_STAT(vfs->conn, smb_fname);
598	if (ret == -1) {
599		printf("stat: error=%d (%s)\n", errno, strerror(errno));
600		TALLOC_FREE(smb_fname);
601		return NT_STATUS_UNSUCCESSFUL;
602	}
603	st = smb_fname->st;
604	TALLOC_FREE(smb_fname);
605
606	pwd = sys_getpwuid(st.st_ex_uid);
607	if (pwd != NULL) user = pwd->pw_name;
608	else user = null_string;
609	grp = sys_getgrgid(st.st_ex_gid);
610	if (grp != NULL) group = grp->gr_name;
611	else group = null_string;
612
613	printf("stat: ok\n");
614	printf("  File: %s", argv[1]);
615	if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
616	else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
617	else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
618	else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
619	else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
620	else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
621	else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
622	printf("  Size: %10u", (unsigned int)st.st_ex_size);
623#ifdef HAVE_STAT_ST_BLOCKS
624	printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
625#endif
626#ifdef HAVE_STAT_ST_BLKSIZE
627	printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
628#endif
629	printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
630	printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
631	printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
632	printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
633	printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
634	       (unsigned long)st.st_ex_gid, group);
635	tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
636	printf("  Access: %s", ctime(&tmp_time));
637	tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
638	printf("  Modify: %s", ctime(&tmp_time));
639	tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
640	printf("  Change: %s", ctime(&tmp_time));
641
642	return NT_STATUS_OK;
643}
644
645
646static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
647{
648	int fd;
649	const char *user;
650	const char *group;
651	struct passwd *pwd = NULL;
652	struct group *grp = NULL;
653	SMB_STRUCT_STAT st;
654	time_t tmp_time;
655
656	if (argc != 2) {
657		printf("Usage: fstat <fd>\n");
658		return NT_STATUS_OK;
659	}
660
661	fd = atoi(argv[1]);
662	if (fd < 0 || fd >= 1024) {
663		printf("fstat: error=%d (file descriptor out of range)\n", EBADF);
664		return NT_STATUS_OK;
665	}
666
667	if (vfs->files[fd] == NULL) {
668		printf("fstat: error=%d (invalid file descriptor)\n", EBADF);
669		return NT_STATUS_OK;
670	}
671
672	if (SMB_VFS_FSTAT(vfs->files[fd], &st) == -1) {
673		printf("fstat: error=%d (%s)\n", errno, strerror(errno));
674		return NT_STATUS_UNSUCCESSFUL;
675	}
676
677	pwd = sys_getpwuid(st.st_ex_uid);
678	if (pwd != NULL) user = pwd->pw_name;
679	else user = null_string;
680	grp = sys_getgrgid(st.st_ex_gid);
681	if (grp != NULL) group = grp->gr_name;
682	else group = null_string;
683
684	printf("fstat: ok\n");
685	if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
686	else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
687	else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
688	else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
689	else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
690	else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
691	else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
692	printf("  Size: %10u", (unsigned int)st.st_ex_size);
693#ifdef HAVE_STAT_ST_BLOCKS
694	printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
695#endif
696#ifdef HAVE_STAT_ST_BLKSIZE
697	printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
698#endif
699	printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
700	printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
701	printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
702	printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
703	printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
704	       (unsigned long)st.st_ex_gid, group);
705	tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
706	printf("  Access: %s", ctime(&tmp_time));
707	tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
708	printf("  Modify: %s", ctime(&tmp_time));
709	tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
710	printf("  Change: %s", ctime(&tmp_time));
711
712	return NT_STATUS_OK;
713}
714
715
716static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
717{
718	const char *user;
719	const char *group;
720	struct passwd *pwd = NULL;
721	struct group *grp = NULL;
722	struct smb_filename *smb_fname = NULL;
723	SMB_STRUCT_STAT st;
724	time_t tmp_time;
725	NTSTATUS status;
726
727	if (argc != 2) {
728		printf("Usage: lstat <path>\n");
729		return NT_STATUS_OK;
730	}
731
732	status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL,
733						  &smb_fname);
734	if (!NT_STATUS_IS_OK(status)) {
735		return status;
736	}
737
738	if (SMB_VFS_LSTAT(vfs->conn, smb_fname) == -1) {
739		printf("lstat: error=%d (%s)\n", errno, strerror(errno));
740		TALLOC_FREE(smb_fname);
741		return NT_STATUS_UNSUCCESSFUL;
742	}
743	st = smb_fname->st;
744	TALLOC_FREE(smb_fname);
745
746	pwd = sys_getpwuid(st.st_ex_uid);
747	if (pwd != NULL) user = pwd->pw_name;
748	else user = null_string;
749	grp = sys_getgrgid(st.st_ex_gid);
750	if (grp != NULL) group = grp->gr_name;
751	else group = null_string;
752
753	printf("lstat: ok\n");
754	if (S_ISREG(st.st_ex_mode)) printf("  Regular File\n");
755	else if (S_ISDIR(st.st_ex_mode)) printf("  Directory\n");
756	else if (S_ISCHR(st.st_ex_mode)) printf("  Character Device\n");
757	else if (S_ISBLK(st.st_ex_mode)) printf("  Block Device\n");
758	else if (S_ISFIFO(st.st_ex_mode)) printf("  Fifo\n");
759	else if (S_ISLNK(st.st_ex_mode)) printf("  Symbolic Link\n");
760	else if (S_ISSOCK(st.st_ex_mode)) printf("  Socket\n");
761	printf("  Size: %10u", (unsigned int)st.st_ex_size);
762#ifdef HAVE_STAT_ST_BLOCKS
763	printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks);
764#endif
765#ifdef HAVE_STAT_ST_BLKSIZE
766	printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize);
767#endif
768	printf("  Device: 0x%10x", (unsigned int)st.st_ex_dev);
769	printf(" Inode: %10u", (unsigned int)st.st_ex_ino);
770	printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink);
771	printf("  Access: %05o", (int)((st.st_ex_mode) & 007777));
772	printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user,
773	       (unsigned long)st.st_ex_gid, group);
774	tmp_time = convert_timespec_to_time_t(st.st_ex_atime);
775	printf("  Access: %s", ctime(&tmp_time));
776	tmp_time = convert_timespec_to_time_t(st.st_ex_mtime);
777	printf("  Modify: %s", ctime(&tmp_time));
778	tmp_time = convert_timespec_to_time_t(st.st_ex_ctime);
779	printf("  Change: %s", ctime(&tmp_time));
780
781	return NT_STATUS_OK;
782}
783
784
785static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
786{
787	mode_t mode;
788	if (argc != 3) {
789		printf("Usage: chmod <path> <mode>\n");
790		return NT_STATUS_OK;
791	}
792
793	mode = atoi(argv[2]);
794	if (SMB_VFS_CHMOD(vfs->conn, argv[1], mode) == -1) {
795		printf("chmod: error=%d (%s)\n", errno, strerror(errno));
796		return NT_STATUS_UNSUCCESSFUL;
797	}
798
799	printf("chmod: ok\n");
800	return NT_STATUS_OK;
801}
802
803
804static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
805{
806	int fd;
807	mode_t mode;
808	if (argc != 3) {
809		printf("Usage: fchmod <fd> <mode>\n");
810		return NT_STATUS_OK;
811	}
812
813	fd = atoi(argv[1]);
814	mode = atoi(argv[2]);
815	if (fd < 0 || fd >= 1024) {
816		printf("fchmod: error=%d (file descriptor out of range)\n", EBADF);
817		return NT_STATUS_OK;
818	}
819	if (vfs->files[fd] == NULL) {
820		printf("fchmod: error=%d (invalid file descriptor)\n", EBADF);
821		return NT_STATUS_OK;
822	}
823
824	if (SMB_VFS_FCHMOD(vfs->files[fd], mode) == -1) {
825		printf("fchmod: error=%d (%s)\n", errno, strerror(errno));
826		return NT_STATUS_UNSUCCESSFUL;
827	}
828
829	printf("fchmod: ok\n");
830	return NT_STATUS_OK;
831}
832
833
834static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
835{
836	uid_t uid;
837	gid_t gid;
838	if (argc != 4) {
839		printf("Usage: chown <path> <uid> <gid>\n");
840		return NT_STATUS_OK;
841	}
842
843	uid = atoi(argv[2]);
844	gid = atoi(argv[3]);
845	if (SMB_VFS_CHOWN(vfs->conn, argv[1], uid, gid) == -1) {
846		printf("chown: error=%d (%s)\n", errno, strerror(errno));
847		return NT_STATUS_UNSUCCESSFUL;
848	}
849
850	printf("chown: ok\n");
851	return NT_STATUS_OK;
852}
853
854
855static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
856{
857	uid_t uid;
858	gid_t gid;
859	int fd;
860	if (argc != 4) {
861		printf("Usage: fchown <fd> <uid> <gid>\n");
862		return NT_STATUS_OK;
863	}
864
865	uid = atoi(argv[2]);
866	gid = atoi(argv[3]);
867	fd = atoi(argv[1]);
868	if (fd < 0 || fd >= 1024) {
869		printf("fchown: faliure=%d (file descriptor out of range)\n", EBADF);
870		return NT_STATUS_OK;
871	}
872	if (vfs->files[fd] == NULL) {
873		printf("fchown: error=%d (invalid file descriptor)\n", EBADF);
874		return NT_STATUS_OK;
875	}
876	if (SMB_VFS_FCHOWN(vfs->files[fd], uid, gid) == -1) {
877		printf("fchown error=%d (%s)\n", errno, strerror(errno));
878		return NT_STATUS_UNSUCCESSFUL;
879	}
880
881	printf("fchown: ok\n");
882	return NT_STATUS_OK;
883}
884
885
886static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
887{
888	char buf[PATH_MAX];
889	if (SMB_VFS_GETWD(vfs->conn, buf) == NULL) {
890		printf("getwd: error=%d (%s)\n", errno, strerror(errno));
891		return NT_STATUS_UNSUCCESSFUL;
892	}
893
894	printf("getwd: %s\n", buf);
895	return NT_STATUS_OK;
896}
897
898static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
899{
900	struct smb_file_time ft;
901	struct smb_filename *smb_fname = NULL;
902	NTSTATUS status;
903
904	if (argc != 4) {
905		printf("Usage: utime <path> <access> <modify>\n");
906		return NT_STATUS_OK;
907	}
908
909	ZERO_STRUCT(ft);
910
911	ft.atime = convert_time_t_to_timespec(atoi(argv[2]));
912	ft.mtime = convert_time_t_to_timespec(atoi(argv[3]));
913
914	status = create_synthetic_smb_fname_split(mem_ctx, argv[1],
915						  NULL, &smb_fname);
916	if (!NT_STATUS_IS_OK(status)) {
917		return status;
918	}
919
920	if (SMB_VFS_NTIMES(vfs->conn, smb_fname, &ft) != 0) {
921		printf("utime: error=%d (%s)\n", errno, strerror(errno));
922		TALLOC_FREE(smb_fname);
923		return NT_STATUS_UNSUCCESSFUL;
924	}
925
926	TALLOC_FREE(smb_fname);
927	printf("utime: ok\n");
928	return NT_STATUS_OK;
929}
930
931static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
932{
933	int fd;
934	SMB_OFF_T off;
935	if (argc != 3) {
936		printf("Usage: ftruncate <fd> <length>\n");
937		return NT_STATUS_OK;
938	}
939
940	fd = atoi(argv[1]);
941	off = atoi(argv[2]);
942	if (fd < 0 || fd >= 1024) {
943		printf("ftruncate: error=%d (file descriptor out of range)\n", EBADF);
944		return NT_STATUS_OK;
945	}
946	if (vfs->files[fd] == NULL) {
947		printf("ftruncate: error=%d (invalid file descriptor)\n", EBADF);
948		return NT_STATUS_OK;
949	}
950
951	if (SMB_VFS_FTRUNCATE(vfs->files[fd], off) == -1) {
952		printf("ftruncate: error=%d (%s)\n", errno, strerror(errno));
953		return NT_STATUS_UNSUCCESSFUL;
954	}
955
956	printf("ftruncate: ok\n");
957	return NT_STATUS_OK;
958}
959
960static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
961{
962	int fd;
963	int op;
964	long offset;
965	long count;
966	int type;
967	const char *typestr;
968
969	if (argc != 6) {
970		printf("Usage: lock <fd> <op> <offset> <count> <type>\n");
971                printf("  ops: G = F_GETLK\n");
972                printf("       S = F_SETLK\n");
973                printf("       W = F_SETLKW\n");
974                printf("  type: R = F_RDLCK\n");
975                printf("        W = F_WRLCK\n");
976                printf("        U = F_UNLCK\n");
977		return NT_STATUS_OK;
978	}
979
980	if (sscanf(argv[1], "%d", &fd) == 0) {
981		printf("lock: error=-1 (error parsing fd)\n");
982		return NT_STATUS_UNSUCCESSFUL;
983	}
984
985	op = 0;
986	switch (*argv[2]) {
987	case 'G':
988		op = F_GETLK;
989		break;
990	case 'S':
991		op = F_SETLK;
992		break;
993	case 'W':
994		op = F_SETLKW;
995		break;
996	default:
997		printf("lock: error=-1 (invalid op flag!)\n");
998		return NT_STATUS_UNSUCCESSFUL;
999	}
1000
1001	if (sscanf(argv[3], "%ld", &offset) == 0) {
1002		printf("lock: error=-1 (error parsing fd)\n");
1003		return NT_STATUS_UNSUCCESSFUL;
1004	}
1005
1006	if (sscanf(argv[4], "%ld", &count) == 0) {
1007		printf("lock: error=-1 (error parsing fd)\n");
1008		return NT_STATUS_UNSUCCESSFUL;
1009	}
1010
1011	type = 0;
1012	typestr = argv[5];
1013	while(*typestr) {
1014		switch (*typestr) {
1015		case 'R':
1016			type |= F_RDLCK;
1017			break;
1018		case 'W':
1019			type |= F_WRLCK;
1020			break;
1021		case 'U':
1022			type |= F_UNLCK;
1023			break;
1024		default:
1025			printf("lock: error=-1 (invalid type flag!)\n");
1026			return NT_STATUS_UNSUCCESSFUL;
1027		}
1028		typestr++;
1029	}
1030
1031	printf("lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d))\n", fd, op, offset, count, type);
1032
1033	if (SMB_VFS_LOCK(vfs->files[fd], op, offset, count, type) == False) {
1034		printf("lock: error=%d (%s)\n", errno, strerror(errno));
1035		return NT_STATUS_UNSUCCESSFUL;
1036	}
1037
1038	printf("lock: ok\n");
1039	return NT_STATUS_OK;
1040}
1041
1042static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1043{
1044	if (argc != 3) {
1045		printf("Usage: symlink <path> <link>\n");
1046		return NT_STATUS_OK;
1047	}
1048
1049	if (SMB_VFS_SYMLINK(vfs->conn, argv[1], argv[2]) == -1) {
1050		printf("symlink: error=%d (%s)\n", errno, strerror(errno));
1051		return NT_STATUS_UNSUCCESSFUL;
1052	}
1053
1054	printf("symlink: ok\n");
1055	return NT_STATUS_OK;
1056}
1057
1058
1059static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1060{
1061	char buffer[PATH_MAX];
1062	int size;
1063
1064	if (argc != 2) {
1065		printf("Usage: readlink <path>\n");
1066		return NT_STATUS_OK;
1067	}
1068
1069	if ((size = SMB_VFS_READLINK(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) {
1070		printf("readlink: error=%d (%s)\n", errno, strerror(errno));
1071		return NT_STATUS_UNSUCCESSFUL;
1072	}
1073
1074	buffer[size] = '\0';
1075	printf("readlink: %s\n", buffer);
1076	return NT_STATUS_OK;
1077}
1078
1079
1080static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1081{
1082	if (argc != 3) {
1083		printf("Usage: link <path> <link>\n");
1084		return NT_STATUS_OK;
1085	}
1086
1087	if (SMB_VFS_LINK(vfs->conn, argv[1], argv[2]) == -1) {
1088		printf("link: error=%d (%s)\n", errno, strerror(errno));
1089		return NT_STATUS_UNSUCCESSFUL;
1090	}
1091
1092	printf("link: ok\n");
1093	return NT_STATUS_OK;
1094}
1095
1096static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1097{
1098	mode_t mode;
1099	unsigned int dev_val;
1100	SMB_DEV_T dev;
1101
1102	if (argc != 4) {
1103		printf("Usage: mknod <path> <mode> <dev>\n");
1104		printf("  mode is octal\n");
1105		printf("  dev is hex\n");
1106		return NT_STATUS_OK;
1107	}
1108
1109	if (sscanf(argv[2], "%ho", (unsigned short *)&mode) == 0) {
1110		printf("open: error=-1 (invalid mode!)\n");
1111		return NT_STATUS_UNSUCCESSFUL;
1112	}
1113
1114	if (sscanf(argv[3], "%x", &dev_val) == 0) {
1115		printf("open: error=-1 (invalid dev!)\n");
1116		return NT_STATUS_UNSUCCESSFUL;
1117	}
1118	dev = (SMB_DEV_T)dev_val;
1119
1120	if (SMB_VFS_MKNOD(vfs->conn, argv[1], mode, dev) == -1) {
1121		printf("mknod: error=%d (%s)\n", errno, strerror(errno));
1122		return NT_STATUS_UNSUCCESSFUL;
1123	}
1124
1125	printf("mknod: ok\n");
1126	return NT_STATUS_OK;
1127}
1128
1129static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
1130{
1131	char respath[PATH_MAX];
1132
1133	if (argc != 2) {
1134		printf("Usage: realpath <path>\n");
1135		return NT_STATUS_OK;
1136	}
1137
1138	if (SMB_VFS_REALPATH(vfs->conn, argv[1], respath) == NULL) {
1139		printf("realpath: error=%d (%s)\n", errno, strerror(errno));
1140		return NT_STATUS_UNSUCCESSFUL;
1141	}
1142
1143	printf("realpath: ok\n");
1144	return NT_STATUS_OK;
1145}
1146
1147struct cmd_set vfs_commands[] = {
1148
1149	{ "VFS Commands" },
1150
1151	{ "load", cmd_load_module, "Load a module", "load <module.so>" },
1152	{ "populate", cmd_populate, "Populate a data buffer", "populate <char> <size>" },
1153	{ "showdata", cmd_show_data, "Show data currently in data buffer", "show_data [<offset> <len>]"},
1154	{ "connect",   cmd_connect,   "VFS connect()",    "connect" },
1155	{ "disconnect",   cmd_disconnect,   "VFS disconnect()",    "disconnect" },
1156	{ "disk_free",   cmd_disk_free,   "VFS disk_free()",    "disk_free <path>" },
1157	{ "opendir",   cmd_opendir,   "VFS opendir()",    "opendir <fname>" },
1158	{ "readdir",   cmd_readdir,   "VFS readdir()",    "readdir" },
1159	{ "mkdir",   cmd_mkdir,   "VFS mkdir()",    "mkdir <path>" },
1160	{ "rmdir",   cmd_pathfunc,   "VFS rmdir()",    "rmdir <path>" },
1161	{ "closedir",   cmd_closedir,   "VFS closedir()",    "closedir" },
1162	{ "open",   cmd_open,   "VFS open()",    "open <fname>" },
1163	{ "close",   cmd_close,   "VFS close()",    "close <fd>" },
1164	{ "read",   cmd_read,   "VFS read()",    "read <fd> <size>" },
1165	{ "write",   cmd_write,   "VFS write()",    "write <fd> <size>" },
1166	{ "lseek",   cmd_lseek,   "VFS lseek()",    "lseek <fd> <offset> <whence>" },
1167	{ "rename",   cmd_rename,   "VFS rename()",    "rename <old> <new>" },
1168	{ "fsync",   cmd_fsync,   "VFS fsync()",    "fsync <fd>" },
1169	{ "stat",   cmd_stat,   "VFS stat()",    "stat <fname>" },
1170	{ "fstat",   cmd_fstat,   "VFS fstat()",    "fstat <fd>" },
1171	{ "lstat",   cmd_lstat,   "VFS lstat()",    "lstat <fname>" },
1172	{ "unlink",   cmd_pathfunc,   "VFS unlink()",    "unlink <fname>" },
1173	{ "chmod",   cmd_chmod,   "VFS chmod()",    "chmod <path> <mode>" },
1174	{ "fchmod",   cmd_fchmod,   "VFS fchmod()",    "fchmod <fd> <mode>" },
1175	{ "chown",   cmd_chown,   "VFS chown()",    "chown <path> <uid> <gid>" },
1176	{ "fchown",   cmd_fchown,   "VFS fchown()",    "fchown <fd> <uid> <gid>" },
1177	{ "chdir",   cmd_pathfunc,   "VFS chdir()",    "chdir <path>" },
1178	{ "getwd",   cmd_getwd,   "VFS getwd()",    "getwd" },
1179	{ "utime",   cmd_utime,   "VFS utime()",    "utime <path> <access> <modify>" },
1180	{ "ftruncate",   cmd_ftruncate,   "VFS ftruncate()",    "ftruncate <fd> <length>" },
1181	{ "lock",   cmd_lock,   "VFS lock()",    "lock <f> <op> <offset> <count> <type>" },
1182	{ "symlink",   cmd_symlink,   "VFS symlink()",    "symlink <old> <new>" },
1183	{ "readlink",   cmd_readlink,   "VFS readlink()",    "readlink <path>" },
1184	{ "link",   cmd_link,   "VFS link()",    "link <oldpath> <newpath>" },
1185	{ "mknod",   cmd_mknod,   "VFS mknod()",    "mknod <path> <mode> <dev>" },
1186	{ "realpath",   cmd_realpath,   "VFS realpath()",    "realpath <path>" },
1187	{ NULL }
1188};
1189