implemented lock and mknod
[ira/wip.git] / source / torture / cmd_vfs.c
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "vfstest.h"
25
26 static char *null_string = "";
27
28 static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
29 {
30         struct smb_vfs_handle_struct *handle;
31         char *path = lp_vfs_path(0);
32         char name[PATH_MAX];
33         
34         if (argc != 2) {
35                 printf("Usage: load <module path>\n");
36                 return NT_STATUS_OK;
37         }
38
39         if (path != NULL && *path != '\0') {
40                 snprintf(name, PATH_MAX, "%s/%s", path, argv[1]);
41         } else {
42                 snprintf(name, PATH_MAX, "%s", argv[1]);
43         }
44         vfs->conn->vfs_private = NULL;
45         handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct));
46         handle->handle = NULL;
47         DLIST_ADD(vfs->conn->vfs_private, handle)
48         if (!vfs_init_custom(vfs->conn, name)) {
49                 DEBUG(0, ("load: error=-1 (vfs_init_custom failed for %s)\n", argv[1]));
50                 return NT_STATUS_UNSUCCESSFUL;
51         }
52         printf("load: ok\n");
53         return NT_STATUS_OK;
54 }
55
56 static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
57 {
58         char c;
59         size_t size;
60         if (argc != 3) {
61                 printf("Usage: populate <char> <size>\n");
62                 return NT_STATUS_OK;
63         }
64         c = argv[1][0];
65         size = atoi(argv[2]);
66         vfs->data = (char *)talloc(mem_ctx, size);
67         if (vfs->data == NULL) {
68                 printf("populate: error=-1 (not enough memory)");
69                 return NT_STATUS_UNSUCCESSFUL;
70         }
71         memset(vfs->data, c, size);
72         vfs->data_size = size;
73         return NT_STATUS_OK;
74 }
75
76 static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
77 {
78         size_t offset;
79         size_t len;
80         if (argc != 1 && argc != 3) {
81                 printf("Usage: showdata [<offset> <len>]\n");
82                 return NT_STATUS_OK;
83         }
84         if (vfs->data == NULL || vfs->data_size == 0) {
85                 printf("show_data: error=-1 (buffer empty)\n");
86                 return NT_STATUS_UNSUCCESSFUL;
87         }
88
89         if (argc == 3) {
90                 offset = atoi(argv[1]);
91                 len = atoi(argv[2]);
92         } else {
93                 offset = 0;
94                 len = vfs->data_size;
95         }
96         if ((offset + len) > vfs->data_size) {
97                 printf("show_data: error=-1 (not enough data in buffer)\n");
98                 return NT_STATUS_UNSUCCESSFUL;
99         }
100         dump_data(0, (char *)(vfs->data) + offset, len);
101         return NT_STATUS_OK;
102 }
103
104 static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
105 {
106         vfs->conn->vfs_ops.connect(vfs->conn, lp_servicename(vfs->conn->service), "vfstest");
107         return NT_STATUS_OK;
108 }
109
110 static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
111 {
112         vfs->conn->vfs_ops.disconnect(vfs->conn);
113         return NT_STATUS_OK;
114 }
115
116 static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
117 {
118         SMB_BIG_UINT diskfree, bsize, dfree, dsize;
119         if (argc != 2) {
120                 printf("Usage: disk_free <path>\n");
121                 return NT_STATUS_OK;
122         }
123
124         diskfree = vfs->conn->vfs_ops.disk_free(vfs->conn, argv[1], False, &bsize, &dfree, &dsize);
125         printf("disk_free: %ld, bsize = %ld, dfree = %ld, dsize = %ld\n", diskfree, bsize, dfree, dsize);
126         return NT_STATUS_OK;
127 }
128
129
130 static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
131 {
132         if (argc != 2) {
133                 printf("Usage: opendir <fname>\n");
134                 return NT_STATUS_OK;
135         }
136
137         vfs->currentdir = vfs->conn->vfs_ops.opendir(vfs->conn, argv[1]);
138         if (vfs->currentdir == NULL) {
139                 printf("opendir error=%d (%s)\n", errno, strerror(errno));
140                 return NT_STATUS_UNSUCCESSFUL;
141         }
142
143         printf("opendir: ok\n");
144         return NT_STATUS_OK;
145 }
146
147
148 static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
149 {
150         struct dirent *dent;
151
152         if (vfs->currentdir == NULL) {
153                 printf("readdir: error=-1 (no open directory)\n");
154                 return NT_STATUS_UNSUCCESSFUL;
155         }
156
157         dent = vfs->conn->vfs_ops.readdir(vfs->conn, vfs->currentdir);
158         if (dent == NULL) {
159                 printf("readdir: NULL\n");
160                 return NT_STATUS_OK;
161         }
162
163         printf("readdir: %s\n", dent->d_name);
164         return NT_STATUS_OK;
165 }
166
167
168 static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
169 {
170         if (argc != 2) {
171                 printf("Usage: mkdir <path>\n");
172                 return NT_STATUS_OK;
173         }
174
175         if (vfs->conn->vfs_ops.mkdir(vfs->conn, argv[1], 00755) == -1) {
176                 printf("mkdir error=%d (%s)\n", errno, strerror(errno));
177                 return NT_STATUS_UNSUCCESSFUL;
178         }
179         
180         printf("mkdir: ok\n");
181         return NT_STATUS_OK;
182 }
183
184
185 static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
186 {
187         int ret;
188         
189         if (vfs->currentdir == NULL) {
190                 printf("closedir: failure (no directory open)\n");
191                 return NT_STATUS_UNSUCCESSFUL;
192         }
193
194         ret = vfs->conn->vfs_ops.closedir(vfs->conn, vfs->currentdir);
195         if (ret == -1) {
196                 printf("closedir failure: %s\n", strerror(errno));
197                 return NT_STATUS_UNSUCCESSFUL;
198         }
199
200         printf("closedir: ok\n");
201         vfs->currentdir = NULL;
202         return NT_STATUS_OK;
203 }
204
205
206 static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
207 {
208         int flags, fd;
209         mode_t mode;
210         char *flagstr;
211
212         mode = 00400;
213
214         if (argc < 3 || argc > 5) {
215                 printf("Usage: open <filename> <flags> <mode>\n");
216                 printf("  flags: O = O_RDONLY\n");
217                 printf("         R = O_RDWR\n");
218                 printf("         W = O_WRONLY\n");
219                 printf("         C = O_CREAT\n");
220                 printf("         E = O_EXCL\n");
221                 printf("         T = O_TRUNC\n");
222                 printf("         A = O_APPEND\n");
223                 printf("         N = O_NONBLOCK/O_NDELAY\n");
224 #ifdef O_SYNC
225                 printf("         S = O_SYNC\n");
226 #endif
227 #ifdef O_NOFOLLOW
228                 printf("         F = O_NOFOLLOW\n");
229 #endif
230                 printf("  mode: see open.2\n");
231                 printf("        mode is ignored if C flag not present\n");
232                 printf("        mode defaults to 00400\n");
233                 return NT_STATUS_OK;
234         }
235         flags = 0;
236         flagstr = argv[2];
237         while (*flagstr) {
238                 switch (*flagstr) {
239                 case 'O':
240                         flags |= O_RDONLY;
241                         break;
242                 case 'R':
243                         flags |= O_RDWR;
244                         break;
245                 case 'W':
246                         flags |= O_WRONLY;
247                         break;
248                 case 'C':
249                         flags |= O_CREAT;
250                         break;
251                 case 'E':
252                         flags |= O_EXCL;
253                         break;
254                 case 'T':
255                         flags |= O_TRUNC;
256                         break;
257                 case 'A':
258                         flags |= O_APPEND;
259                         break;
260                 case 'N':
261                         flags |= O_NONBLOCK;
262                         break;
263 #ifdef O_SYNC
264                 case 'S':
265                         flags |= O_SYNC;
266                         break;
267 #endif
268 #ifdef O_NOFOLLOW
269                 case 'F':
270                         flags |= O_NOFOLLOW;
271                         break;
272 #endif
273                 default:
274                         printf("open: error=-1 (invalid flag!)\n");
275                         return NT_STATUS_UNSUCCESSFUL;
276                 }
277                 flagstr++;
278         }
279         if ((flags & O_CREAT) && argc == 4) {
280                 if (sscanf(argv[3], "%o", &mode) == 0) {
281                         printf("open: error=-1 (invalid mode!)\n");
282                         return NT_STATUS_UNSUCCESSFUL;
283                 }
284         }
285
286         fd = vfs->conn->vfs_ops.open(vfs->conn, argv[1], flags, mode);
287         if (fd == -1) {
288                 printf("open: error=%d (%s)\n", errno, strerror(errno));
289                 return NT_STATUS_UNSUCCESSFUL;
290         }
291
292         vfs->files[fd] = (struct files_struct *)malloc(sizeof(struct files_struct));
293         vfs->files[fd]->fsp_name = strdup(argv[1]);
294         vfs->files[fd]->fd = fd;
295         vfs->files[fd]->conn = vfs->conn;
296         printf("open: fd=%d\n", fd);
297         return NT_STATUS_OK;
298 }
299
300
301 static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
302 {
303         int ret = -1;
304
305         if (argc != 2) {
306                 printf("Usage: %s <path>\n", argv[0]);
307                 return NT_STATUS_OK;
308         }
309
310         if (strcmp("rmdir", argv[0]) == 0 ) {
311                 ret = vfs->conn->vfs_ops.rmdir(vfs->conn, argv[1]);
312         } else if (strcmp("unlink", argv[0]) == 0 ) {
313                 ret = vfs->conn->vfs_ops.unlink(vfs->conn, argv[1]);
314         } else if (strcmp("chdir", argv[0]) == 0 ) {
315                 ret = vfs->conn->vfs_ops.chdir(vfs->conn, argv[1]);
316         } else {
317                 printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
318                 return NT_STATUS_UNSUCCESSFUL;
319         }
320
321         if (ret == -1) {
322                 printf("%s: error=%d (%s)\n", argv[0], errno, strerror(errno));
323                 return NT_STATUS_UNSUCCESSFUL;
324         }
325
326         printf("%s: ok\n", argv[0]);
327         return NT_STATUS_OK;
328 }
329
330
331 static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
332 {
333         int fd, ret;
334
335         if (argc != 2) {
336                 printf("Usage: close <fd>\n");
337                 return NT_STATUS_OK;
338         }
339
340         fd = atoi(argv[1]);
341         if (vfs->files[fd] == NULL) {
342                 printf("close: error=-1 (invalid file descriptor)\n");
343                 return NT_STATUS_OK;
344         }
345
346         ret = vfs->conn->vfs_ops.close(vfs->files[fd], fd);
347         if (ret == -1 )
348                 printf("close: error=%d (%s)\n", errno, strerror(errno));
349         else
350                 printf("close: ok\n");
351
352         SAFE_FREE(vfs->files[fd]->fsp_name);
353         SAFE_FREE(vfs->files[fd]);
354         vfs->files[fd] = NULL;
355         return NT_STATUS_OK;
356 }
357
358
359 static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
360 {
361         int fd;
362         size_t size, rsize;
363
364         if (argc != 3) {
365                 printf("Usage: read <fd> <size>\n");
366                 return NT_STATUS_OK;
367         }
368
369         /* do some error checking on these */
370         fd = atoi(argv[1]);
371         size = atoi(argv[2]);
372         vfs->data = (char *)talloc(mem_ctx, size);
373         if (vfs->data == NULL) {
374                 printf("read: error=-1 (not enough memory)");
375                 return NT_STATUS_UNSUCCESSFUL;
376         }
377         vfs->data_size = size;
378         
379         rsize = vfs->conn->vfs_ops.read(vfs->files[fd], fd, vfs->data, size);
380         if (rsize == -1) {
381                 printf("read: error=%d (%s)\n", errno, strerror(errno));
382                 return NT_STATUS_UNSUCCESSFUL;
383         }
384
385         printf("read: ok\n");
386         return NT_STATUS_OK;
387 }
388
389
390 static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
391 {
392         int fd, size, wsize;
393
394         if (argc != 3) {
395                 printf("Usage: write <fd> <size>\n");
396                 return NT_STATUS_OK;
397         }
398
399         /* some error checking should go here */
400         fd = atoi(argv[1]);
401         size = atoi(argv[2]);
402         if (vfs->data == NULL) {
403                 printf("write: error=-1 (buffer empty, please populate it before writing)");
404                 return NT_STATUS_UNSUCCESSFUL;
405         }
406
407         if (vfs->data_size < size) {
408                 printf("write: error=-1 (buffer too small, please put some more data in)");
409                 return NT_STATUS_UNSUCCESSFUL;
410         }
411
412         wsize = vfs->conn->vfs_ops.write(vfs->files[fd], fd, vfs->data, size);
413
414         if (wsize == -1) {
415                 printf("write: error=%d (%s)\n", errno, strerror(errno));
416                 return NT_STATUS_UNSUCCESSFUL;
417         }
418
419         printf("write: ok\n");
420         return NT_STATUS_OK;
421 }
422
423
424 static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
425 {
426         int fd, offset, whence;
427         SMB_OFF_T pos;
428
429         if (argc != 4) {
430                 printf("Usage: lseek <fd> <offset> <whence>\n...where whence is 1 => SEEK_SET, 2 => SEEK_CUR, 3 => SEEK_END\n");
431                 return NT_STATUS_OK;
432         }
433
434         fd = atoi(argv[1]);
435         offset = atoi(argv[2]);
436         whence = atoi(argv[3]);
437         switch (whence) {
438                 case 1:         whence = SEEK_SET; break;
439                 case 2:         whence = SEEK_CUR; break;
440                 default:        whence = SEEK_END;
441         }
442
443         pos = vfs->conn->vfs_ops.lseek(vfs->files[fd], fd, offset, whence);
444         if (pos == (SMB_OFF_T)-1) {
445                 printf("lseek: error=%d (%s)\n", errno, strerror(errno));
446                 return NT_STATUS_UNSUCCESSFUL;
447         }
448
449         printf("lseek: ok\n");
450         return NT_STATUS_OK;
451 }
452
453
454 static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
455 {
456         int ret;
457         if (argc != 3) {
458                 printf("Usage: rename <old> <new>\n");
459                 return NT_STATUS_OK;
460         }
461
462         ret = vfs->conn->vfs_ops.rename(vfs->conn, argv[1], argv[2]);
463         if (ret == -1) {
464                 printf("rename: error=%d (%s)\n", errno, strerror(errno));
465                 return NT_STATUS_UNSUCCESSFUL;
466         }
467
468         printf("rename: ok\n");
469         return NT_STATUS_OK;
470 }
471
472
473 static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
474 {
475         int ret, fd;
476         if (argc != 2) {
477                 printf("Usage: fsync <fd>\n");
478                 return NT_STATUS_OK;
479         }
480
481         fd = atoi(argv[1]);
482         ret = vfs->conn->vfs_ops.fsync(vfs->files[fd], fd);
483         if (ret == -1) {
484                 printf("fsync: error=%d (%s)\n", errno, strerror(errno));
485                 return NT_STATUS_UNSUCCESSFUL;
486         }
487
488         printf("fsync: ok\n");
489         return NT_STATUS_OK;
490 }
491
492
493 static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
494 {
495         int ret;
496         char *user;
497         char *group;
498         struct passwd *pwd;
499         struct group *grp;
500         SMB_STRUCT_STAT st;
501
502         if (argc != 2) {
503                 printf("Usage: stat <fname>\n");
504                 return NT_STATUS_OK;
505         }
506
507         ret = vfs->conn->vfs_ops.stat(vfs->conn, argv[1], &st);
508         if (ret == -1) {
509                 printf("stat: error=%d (%s)\n", errno, strerror(errno));
510                 return NT_STATUS_UNSUCCESSFUL;
511         }
512
513         pwd = sys_getpwuid(st.st_uid);
514         if (pwd != NULL) user = strdup(pwd->pw_name);
515         else user = null_string;
516         grp = sys_getgrgid(st.st_gid);
517         if (grp != NULL) group = strdup(grp->gr_name);
518         else group = null_string;
519
520         printf("stat: ok\n");
521         printf("  File: %s", argv[1]);
522         if (S_ISREG(st.st_mode)) printf("  Regular File\n");
523         else if (S_ISDIR(st.st_mode)) printf("  Directory\n");
524         else if (S_ISCHR(st.st_mode)) printf("  Character Device\n");
525         else if (S_ISBLK(st.st_mode)) printf("  Block Device\n");
526         else if (S_ISFIFO(st.st_mode)) printf("  Fifo\n");
527         else if (S_ISLNK(st.st_mode)) printf("  Symbolic Link\n");
528         else if (S_ISSOCK(st.st_mode)) printf("  Socket\n");
529         printf("  Size: %10d", st.st_size);
530         printf(" Blocks: %9d", st.st_blocks);
531         printf(" IO Block: %d\n", st.st_blksize);
532         printf("  Device: 0x%10x", st.st_dev);
533         printf(" Inode: %10d", st.st_ino);
534         printf(" Links: %10d\n", st.st_nlink);
535         printf("  Access: %05o", (st.st_mode) & 007777);
536         printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group);
537         printf("  Access: %s", ctime(&(st.st_atime)));
538         printf("  Modify: %s", ctime(&(st.st_mtime)));
539         printf("  Change: %s", ctime(&(st.st_ctime)));
540         if (user != null_string) SAFE_FREE(user);
541         if (group!= null_string) SAFE_FREE(group);
542         return NT_STATUS_OK;
543 }
544
545
546 static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
547 {
548         int fd;
549         char *user;
550         char *group;
551         struct passwd *pwd;
552         struct group *grp;
553         SMB_STRUCT_STAT st;
554
555         if (argc != 2) {
556                 printf("Usage: fstat <fd>\n");
557                 return NT_STATUS_OK;
558         }
559
560         fd = atoi(argv[1]);
561         if (fd < 0 || fd > 1024) {
562                 printf("fstat: error=%d (file descriptor out of range)\n", EBADF);
563                 return NT_STATUS_OK;
564         }
565
566         if (vfs->files[fd] == NULL) {
567                 printf("fstat: error=%d (invalid file descriptor)\n", EBADF);
568                 return NT_STATUS_OK;
569         }
570
571         if (vfs->conn->vfs_ops.fstat(vfs->files[fd], fd, &st) == -1) {
572                 printf("fstat: error=%d (%s)\n", errno, strerror(errno));
573                 return NT_STATUS_UNSUCCESSFUL;
574         }
575
576         pwd = sys_getpwuid(st.st_uid);
577         if (pwd != NULL) user = strdup(pwd->pw_name);
578         else user = null_string;
579         grp = sys_getgrgid(st.st_gid);
580         if (grp != NULL) group = strdup(grp->gr_name);
581         else group = null_string;
582
583         printf("fstat: ok\n");
584         if (S_ISREG(st.st_mode)) printf("  Regular File\n");
585         else if (S_ISDIR(st.st_mode)) printf("  Directory\n");
586         else if (S_ISCHR(st.st_mode)) printf("  Character Device\n");
587         else if (S_ISBLK(st.st_mode)) printf("  Block Device\n");
588         else if (S_ISFIFO(st.st_mode)) printf("  Fifo\n");
589         else if (S_ISLNK(st.st_mode)) printf("  Symbolic Link\n");
590         else if (S_ISSOCK(st.st_mode)) printf("  Socket\n");
591         printf("  Size: %10d", st.st_size);
592         printf(" Blocks: %9d", st.st_blocks);
593         printf(" IO Block: %d\n", st.st_blksize);
594         printf("  Device: 0x%10x", st.st_dev);
595         printf(" Inode: %10d", st.st_ino);
596         printf(" Links: %10d\n", st.st_nlink);
597         printf("  Access: %05o", (st.st_mode) & 007777);
598         printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group);
599         printf("  Access: %s", ctime(&(st.st_atime)));
600         printf("  Modify: %s", ctime(&(st.st_mtime)));
601         printf("  Change: %s", ctime(&(st.st_ctime)));
602         if (user != null_string) SAFE_FREE(user);
603         if (group!= null_string) SAFE_FREE(group);
604         return NT_STATUS_OK;
605 }
606
607
608 static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
609 {
610         char *user;
611         char *group;
612         struct passwd *pwd;
613         struct group *grp;
614         SMB_STRUCT_STAT st;
615
616         if (argc != 2) {
617                 printf("Usage: lstat <path>\n");
618                 return NT_STATUS_OK;
619         }
620
621         if (vfs->conn->vfs_ops.lstat(vfs->conn, argv[1], &st) == -1) {
622                 printf("lstat: error=%d (%s)\n", errno, strerror(errno));
623                 return NT_STATUS_UNSUCCESSFUL;
624         }
625
626         pwd = sys_getpwuid(st.st_uid);
627         if (pwd != NULL) user = strdup(pwd->pw_name);
628         else user = null_string;
629         grp = sys_getgrgid(st.st_gid);
630         if (grp != NULL) group = strdup(grp->gr_name);
631         else group = null_string;
632
633         printf("lstat: ok\n");
634         if (S_ISREG(st.st_mode)) printf("  Regular File\n");
635         else if (S_ISDIR(st.st_mode)) printf("  Directory\n");
636         else if (S_ISCHR(st.st_mode)) printf("  Character Device\n");
637         else if (S_ISBLK(st.st_mode)) printf("  Block Device\n");
638         else if (S_ISFIFO(st.st_mode)) printf("  Fifo\n");
639         else if (S_ISLNK(st.st_mode)) printf("  Symbolic Link\n");
640         else if (S_ISSOCK(st.st_mode)) printf("  Socket\n");
641         printf("  Size: %10d", st.st_size);
642         printf(" Blocks: %9d", st.st_blocks);
643         printf(" IO Block: %d\n", st.st_blksize);
644         printf("  Device: 0x%10x", st.st_dev);
645         printf(" Inode: %10d", st.st_ino);
646         printf(" Links: %10d\n", st.st_nlink);
647         printf("  Access: %05o", (st.st_mode) & 007777);
648         printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group);
649         printf("  Access: %s", ctime(&(st.st_atime)));
650         printf("  Modify: %s", ctime(&(st.st_mtime)));
651         printf("  Change: %s", ctime(&(st.st_ctime)));
652         if (user != null_string) SAFE_FREE(user);
653         if (group!= null_string) SAFE_FREE(group);
654         return NT_STATUS_OK;
655 }
656
657
658 static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
659 {
660         mode_t mode;
661         if (argc != 3) {
662                 printf("Usage: chmod <path> <mode>\n");
663                 return NT_STATUS_OK;
664         }
665
666         mode = atoi(argv[2]);
667         if (vfs->conn->vfs_ops.chmod(vfs->conn, argv[1], mode) == -1) {
668                 printf("chmod: error=%d (%s)\n", errno, strerror(errno));
669                 return NT_STATUS_UNSUCCESSFUL;
670         }
671
672         printf("chmod: ok\n");
673         return NT_STATUS_OK;
674 }
675
676
677 static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
678 {
679         int fd;
680         mode_t mode;
681         if (argc != 3) {
682                 printf("Usage: fchmod <fd> <mode>\n");
683                 return NT_STATUS_OK;
684         }
685
686         fd = atoi(argv[1]);
687         mode = atoi(argv[2]);
688         if (fd < 0 || fd > 1024) {
689                 printf("fchmod: error=%d (file descriptor out of range)\n", EBADF);
690                 return NT_STATUS_OK;
691         }
692         if (vfs->files[fd] == NULL) {
693                 printf("fchmod: error=%d (invalid file descriptor)\n", EBADF);
694                 return NT_STATUS_OK;
695         }
696
697         if (vfs->conn->vfs_ops.fchmod(vfs->files[fd], fd, mode) == -1) {
698                 printf("fchmod: error=%d (%s)\n", errno, strerror(errno));
699                 return NT_STATUS_UNSUCCESSFUL;
700         }
701
702         printf("fchmod: ok\n");
703         return NT_STATUS_OK;
704 }
705
706
707 static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
708 {
709         uid_t uid;
710         gid_t gid;
711         if (argc != 4) {
712                 printf("Usage: chown <path> <uid> <gid>\n");
713                 return NT_STATUS_OK;
714         }
715
716         uid = atoi(argv[2]);
717         gid = atoi(argv[3]);
718         if (vfs->conn->vfs_ops.chown(vfs->conn, argv[1], uid, gid) == -1) {
719                 printf("chown: error=%d (%s)\n", errno, strerror(errno));
720                 return NT_STATUS_UNSUCCESSFUL;
721         }
722
723         printf("chown: ok\n");
724         return NT_STATUS_OK;
725 }
726
727
728 static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
729 {
730         uid_t uid;
731         gid_t gid;
732         int fd;
733         if (argc != 4) {
734                 printf("Usage: fchown <fd> <uid> <gid>\n");
735                 return NT_STATUS_OK;
736         }
737
738         uid = atoi(argv[2]);
739         gid = atoi(argv[3]);
740         fd = atoi(argv[1]);
741         if (fd < 0 || fd > 1024) {
742                 printf("fchown: faliure=%d (file descriptor out of range)\n", EBADF);
743                 return NT_STATUS_OK;
744         }
745         if (vfs->files[fd] == NULL) {
746                 printf("fchown: error=%d (invalid file descriptor)\n", EBADF);
747                 return NT_STATUS_OK;
748         }
749         if (vfs->conn->vfs_ops.fchown(vfs->files[fd], fd, uid, gid) == -1) {
750                 printf("fchown error=%d (%s)\n", errno, strerror(errno));
751                 return NT_STATUS_UNSUCCESSFUL;
752         }
753
754         printf("fchown: ok\n");
755         return NT_STATUS_OK;
756 }
757
758
759 static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
760 {
761         char buf[PATH_MAX];
762         if (vfs->conn->vfs_ops.getwd(vfs->conn, buf) == NULL) {
763                 printf("getwd: error=%d (%s)\n", errno, strerror(errno));
764                 return NT_STATUS_UNSUCCESSFUL;
765         }
766
767         printf("getwd: %s\n", buf);
768         return NT_STATUS_OK;
769 }
770
771 static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
772 {
773         struct utimbuf times;
774         if (argc != 4) {
775                 printf("Usage: utime <path> <access> <modify>\n");
776                 return NT_STATUS_OK;
777         }
778         times.actime = atoi(argv[2]);
779         times.modtime = atoi(argv[3]);
780         if (vfs->conn->vfs_ops.utime(vfs->conn, argv[1], &times) != 0) {
781                 printf("utime: error=%d (%s)\n", errno, strerror(errno));
782                 return NT_STATUS_UNSUCCESSFUL;
783         }
784
785         printf("utime: ok\n");
786         return NT_STATUS_OK;
787 }
788
789 static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
790 {
791         int fd;
792         SMB_OFF_T off;
793         if (argc != 3) {
794                 printf("Usage: ftruncate <fd> <length>\n");
795                 return NT_STATUS_OK;
796         }
797
798         fd = atoi(argv[1]);
799         off = atoi(argv[2]);
800         if (fd < 0 || fd > 1024) {
801                 printf("ftruncate: error=%d (file descriptor out of range)\n", EBADF);
802                 return NT_STATUS_OK;
803         }
804         if (vfs->files[fd] == NULL) {
805                 printf("ftruncate: error=%d (invalid file descriptor)\n", EBADF);
806                 return NT_STATUS_OK;
807         }
808
809         if (vfs->conn->vfs_ops.ftruncate(vfs->files[fd], fd, off) == -1) {
810                 printf("ftruncate: error=%d (%s)\n", errno, strerror(errno));
811                 return NT_STATUS_UNSUCCESSFUL;
812         }
813
814         printf("ftruncate: ok\n");
815         return NT_STATUS_OK;
816 }
817
818 static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
819 {
820         BOOL ret;
821         int fd;
822         int op;
823         long offset;
824         long count;
825         int type;
826         char *typestr;
827         
828         if (argc != 6) {
829                 printf("Usage: lock <fd> <op> <offset> <count> <type>\n");
830                 printf("  ops: G = F_GETLK\n");
831                 printf("       S = F_SETLK\n");
832                 printf("       W = F_SETLKW\n");
833                 printf("  type: R = F_RDLCK\n");
834                 printf("        W = F_WRLCK\n");
835                 printf("        U = F_UNLCK\n");
836                 return NT_STATUS_OK;
837         }
838
839         if (sscanf(argv[1], "%d", &fd) == 0) {
840                 printf("lock: error=-1 (error parsing fd)\n");
841                 return NT_STATUS_UNSUCCESSFUL;
842         }
843
844         op = 0;
845         switch (*argv[2]) {
846         case 'G':
847                 op = F_GETLK;
848                 break;
849         case 'S':
850                 op = F_SETLK;
851                 break;
852         case 'W':
853                 op = F_SETLKW;
854                 break;
855         default:
856                 printf("lock: error=-1 (invalid op flag!)\n");
857                 return NT_STATUS_UNSUCCESSFUL;
858         }
859
860         if (sscanf(argv[3], "%ld", &offset) == 0) {
861                 printf("lock: error=-1 (error parsing fd)\n");
862                 return NT_STATUS_UNSUCCESSFUL;
863         }
864
865         if (sscanf(argv[4], "%ld", &count) == 0) {
866                 printf("lock: error=-1 (error parsing fd)\n");
867                 return NT_STATUS_UNSUCCESSFUL;
868         }
869
870         type = 0;
871         typestr = argv[5];
872         while(*typestr) {
873                 switch (*typestr) {
874                 case 'R':
875                         type |= F_RDLCK;
876                         break;
877                 case 'W':
878                         type |= F_WRLCK;
879                         break;
880                 case 'U':
881                         type |= F_UNLCK;
882                         break;
883                 default:
884                         printf("lock: error=-1 (invalid type flag!)\n");
885                         return NT_STATUS_UNSUCCESSFUL;
886                 }
887                 typestr++;
888         }
889
890         printf("lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d))\n", fd, op, offset, count, type);
891
892         if ((ret = vfs->conn->vfs_ops.lock(vfs->files[fd], fd, op, offset, count, type)) == False) {
893                 printf("lock: error=%d (%s)\n", errno, strerror(errno));
894                 return NT_STATUS_UNSUCCESSFUL;
895         }
896
897         printf("lock: ok\n");
898         return NT_STATUS_OK;
899 }
900
901 static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
902 {
903         if (argc != 3) {
904                 printf("Usage: symlink <path> <link>\n");
905                 return NT_STATUS_OK;
906         }
907
908         if (vfs->conn->vfs_ops.symlink(vfs->conn, argv[1], argv[2]) == -1) {
909                 printf("symlink: error=%d (%s)\n", errno, strerror(errno));
910                 return NT_STATUS_UNSUCCESSFUL;
911         }
912
913         printf("symlink: ok\n");
914         return NT_STATUS_OK;
915 }
916
917
918 static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
919 {
920         char buffer[PATH_MAX];
921         int size;
922
923         if (argc != 2) {
924                 printf("Usage: readlink <path>\n");
925                 return NT_STATUS_OK;
926         }
927
928         if ((size = vfs->conn->vfs_ops.readlink(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) {
929                 printf("readlink: error=%d (%s)\n", errno, strerror(errno));
930                 return NT_STATUS_UNSUCCESSFUL;
931         }
932
933         buffer[size] = '\0';
934         printf("readlink: %s\n", buffer);
935         return NT_STATUS_OK;
936 }
937
938
939 static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
940 {
941         if (argc != 3) {
942                 printf("Usage: link <path> <link>\n");
943                 return NT_STATUS_OK;
944         }
945
946         if (vfs->conn->vfs_ops.link(vfs->conn, argv[1], argv[2]) == -1) {
947                 printf("link: error=%d (%s)\n", errno, strerror(errno));
948                 return NT_STATUS_UNSUCCESSFUL;
949         }
950
951         printf("link: ok\n");
952         return NT_STATUS_OK;
953 }
954
955 static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
956 {
957         mode_t mode;
958         SMB_DEV_T dev;
959         
960         if (argc != 4) {
961                 printf("Usage: mknod <path> <mode> <dev>\n");
962                 printf("  mode is octal\n");
963                 printf("  dev is hex\n");
964                 return NT_STATUS_OK;
965         }
966
967         if (sscanf(argv[2], "%o", &mode) == 0) {
968                 printf("open: error=-1 (invalid mode!)\n");
969                 return NT_STATUS_UNSUCCESSFUL;
970         }
971
972         if (sscanf(argv[3], "%x", &dev) == 0) {
973                 printf("open: error=-1 (invalid dev!)\n");
974                 return NT_STATUS_UNSUCCESSFUL;
975         }
976
977         if (vfs->conn->vfs_ops.mknod(vfs->conn, argv[1], mode, dev) == -1) {
978                 printf("mknod: error=%d (%s)\n", errno, strerror(errno));
979                 return NT_STATUS_UNSUCCESSFUL;
980         }
981
982         printf("mknod: ok\n");
983         return NT_STATUS_OK;
984 }
985
986 static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv)
987 {
988         char respath[PATH_MAX];
989         
990         if (argc != 2) {
991                 printf("Usage: realpath <path>\n");
992                 return NT_STATUS_OK;
993         }
994
995         if (vfs->conn->vfs_ops.realpath(vfs->conn, argv[1], respath) == NULL) {
996                 printf("realpath: error=%d (%s)\n", errno, strerror(errno));
997                 return NT_STATUS_UNSUCCESSFUL;
998         }
999
1000         printf("realpath: ok\n");
1001         return NT_STATUS_OK;
1002 }
1003
1004 struct cmd_set vfs_commands[] = {
1005
1006         { "VFS Commands" },
1007
1008         { "load", cmd_load_module, "Load a module", "load <module.so>" },
1009         { "populate", cmd_populate, "Populate a data buffer", "populate <char> <size>" },
1010         { "showdata", cmd_show_data, "Show data currently in data buffer", "show_data [<offset> <len>]"},
1011         { "connect",   cmd_connect,   "VFS connect()",    "connect" },
1012         { "disconnect",   cmd_disconnect,   "VFS disconnect()",    "disconnect" },
1013         { "disk_free",   cmd_disk_free,   "VFS disk_free()",    "disk_free <path>" },
1014         { "opendir",   cmd_opendir,   "VFS opendir()",    "opendir <fname>" },
1015         { "readdir",   cmd_readdir,   "VFS readdir()",    "readdir" },
1016         { "mkdir",   cmd_mkdir,   "VFS mkdir()",    "mkdir <path>" },
1017         { "rmdir",   cmd_pathfunc,   "VFS rmdir()",    "rmdir <path>" },
1018         { "closedir",   cmd_closedir,   "VFS closedir()",    "closedir" },
1019         { "open",   cmd_open,   "VFS open()",    "open <fname>" },
1020         { "close",   cmd_close,   "VFS close()",    "close <fd>" },
1021         { "read",   cmd_read,   "VFS read()",    "read <fd> <size>" },
1022         { "write",   cmd_write,   "VFS write()",    "write <fd> <size>" },
1023         { "lseek",   cmd_lseek,   "VFS lseek()",    "lseek <fd> <offset> <whence>" },
1024         { "rename",   cmd_rename,   "VFS rename()",    "rename <old> <new>" },
1025         { "fsync",   cmd_fsync,   "VFS fsync()",    "fsync <fd>" },
1026         { "stat",   cmd_stat,   "VFS stat()",    "stat <fname>" },
1027         { "fstat",   cmd_fstat,   "VFS fstat()",    "fstat <fd>" },
1028         { "lstat",   cmd_lstat,   "VFS lstat()",    "lstat <fname>" },
1029         { "unlink",   cmd_pathfunc,   "VFS unlink()",    "unlink <fname>" },
1030         { "chmod",   cmd_chmod,   "VFS chmod()",    "chmod <path> <mode>" },
1031         { "fchmod",   cmd_fchmod,   "VFS fchmod()",    "fchmod <fd> <mode>" },
1032         { "chown",   cmd_chown,   "VFS chown()",    "chown <path> <uid> <gid>" },
1033         { "fchown",   cmd_fchown,   "VFS fchown()",    "fchown <fd> <uid> <gid>" },
1034         { "chdir",   cmd_pathfunc,   "VFS chdir()",    "chdir <path>" },
1035         { "getwd",   cmd_getwd,   "VFS getwd()",    "getwd" },
1036         { "utime",   cmd_utime,   "VFS utime()",    "utime <path> <access> <modify>" },
1037         { "ftruncate",   cmd_ftruncate,   "VFS ftruncate()",    "ftruncate <fd> <length>" },
1038         { "lock",   cmd_lock,   "VFS lock()",    "lock <f> <op> <offset> <count> <type>" },
1039         { "symlink",   cmd_symlink,   "VFS symlink()",    "symlink <old> <new>" },
1040         { "readlink",   cmd_readlink,   "VFS readlink()",    "readlink <path>" },
1041         { "link",   cmd_link,   "VFS link()",    "link <oldpath> <newpath>" },
1042         { "mknod",   cmd_mknod,   "VFS mknod()",    "mknod <path> <mode> <dev>" },
1043         { "realpath",   cmd_realpath,   "VFS realpath()",    "realpath <path>" },
1044         { NULL }
1045 };