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