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