Have ntvfs_connect() accept union smb_tcon *tcon instead of char* sharename
[metze/samba/wip.git] / source4 / ntvfs / nbench / vfs_nbench.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    a pass-thru NTVFS module to record a NBENCH load file
5
6    Copyright (C) Andrew Tridgell 2004
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23   "passthru" in this module refers to the next level of NTVFS being used
24 */
25
26 #include "includes.h"
27 #include "ntvfs/ntvfs.h"
28 #include "system/filesys.h"
29
30 /* this is stored in ntvfs_private */
31 struct nbench_private {
32         int log_fd;
33 };
34
35 /*
36   log one request to the nbench log
37 */
38 static void nbench_log(struct ntvfs_request *req,
39                        const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
40
41 static void nbench_log(struct ntvfs_request *req,
42                        const char *format, ...)
43 {
44         struct nbench_private *nprivates = req->async_states->ntvfs->private_data;
45         va_list ap;
46         char *s = NULL;
47
48         va_start(ap, format);
49         vasprintf(&s, format, ap);
50         va_end(ap);
51
52         write(nprivates->log_fd, s, strlen(s));
53         free(s);
54 }
55
56 static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_handle *h)
57 {
58         DATA_BLOB key;
59         uint16_t fnum = 0;
60
61         key = ntvfs_handle_get_wire_key(h, req);
62
63         switch (key.length) {
64         case 2: /* SMB fnum */
65                 fnum = SVAL(key.data, 0);
66                 break;
67         default:
68                 DEBUG(0,("%s: invalid wire handle size: %u\n",
69                         __FUNCTION__, (unsigned)key.length));
70                 break;
71         }
72
73         return talloc_asprintf(req, "%u", fnum);
74 }
75
76 /*
77   this pass through macro operates on request contexts, and disables
78   async calls. 
79
80   async calls are a pain for the nbench module as it makes pulling the
81   status code and any result parameters much harder.
82 */
83 #define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
84         status = ntvfs_async_state_push(ntvfs, req, par1, nbench_##op##_send); \
85         if (!NT_STATUS_IS_OK(status)) { \
86                 return status; \
87         } \
88 } while (0)
89
90 #define PASS_THRU_REQ_POST_ASYNC(req) do { \
91         req->async_states->status = status; \
92         if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
93                 req->async_states->send_fn(req); \
94         } \
95 } while (0)
96
97 #define PASS_THRU_REQ(ntvfs, req, op, par1, args) do { \
98         PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1); \
99         status = ntvfs_next_##op args; \
100         PASS_THRU_REQ_POST_ASYNC(req); \
101 } while (0)
102
103 #define PASS_THRU_REP_POST(req) do { \
104         ntvfs_async_state_pop(req); \
105         if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
106                 req->async_states->send_fn(req); \
107         } \
108 } while (0)
109
110 /*
111   connect to a share - used when a tree_connect operation comes in.
112 */
113 static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
114                                struct ntvfs_request *req,
115                                union smb_tcon* con)
116 {
117         struct nbench_private *nprivates;
118         NTSTATUS status;
119         char *logname = NULL;
120
121         nprivates = talloc(ntvfs, struct nbench_private);
122         if (!nprivates) {
123                 return NT_STATUS_NO_MEMORY;
124         }
125
126         asprintf(&logname, "/tmp/nbenchlog%d.%u", ntvfs->depth, getpid());
127         nprivates->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
128         free(logname);
129
130         if (nprivates->log_fd == -1) {
131                 DEBUG(0,("Failed to open nbench log\n"));
132                 return NT_STATUS_UNSUCCESSFUL;
133         }
134
135         ntvfs->private_data = nprivates;
136
137         status = ntvfs_next_connect(ntvfs, req, con);
138
139         return status;
140 }
141
142 /*
143   disconnect from a share
144 */
145 static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs)
146 {
147         struct nbench_private *nprivates = ntvfs->private_data;
148         NTSTATUS status;
149
150         close(nprivates->log_fd);
151
152         status = ntvfs_next_disconnect(ntvfs);
153
154         return status;
155 }
156
157 /*
158   delete a file - the dirtype specifies the file types to include in the search. 
159   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
160 */
161 static void nbench_unlink_send(struct ntvfs_request *req)
162 {
163         union smb_unlink *unl = req->async_states->private_data;
164
165         nbench_log(req, "Unlink \"%s\" 0x%x %s\n", 
166                    unl->unlink.in.pattern, unl->unlink.in.attrib, 
167                    get_nt_error_c_code(req->async_states->status));
168
169         PASS_THRU_REP_POST(req);
170 }
171
172 static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
173                               struct ntvfs_request *req,
174                               union smb_unlink *unl)
175 {
176         NTSTATUS status;
177
178         PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
179
180         return status;
181 }
182
183 /*
184   ioctl interface
185 */
186 static void nbench_ioctl_send(struct ntvfs_request *req)
187 {
188         nbench_log(req, "Ioctl - NOT HANDLED\n");
189
190         PASS_THRU_REP_POST(req);
191 }
192
193 static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
194                              struct ntvfs_request *req, union smb_ioctl *io)
195 {
196         NTSTATUS status;
197
198         PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
199
200         return status;
201 }
202
203 /*
204   check if a directory exists
205 */
206 static void nbench_chkpath_send(struct ntvfs_request *req)
207 {
208         union smb_chkpath *cp = req->async_states->private_data;
209
210         nbench_log(req, "Chkpath \"%s\" %s\n", 
211                    cp->chkpath.in.path, 
212                    get_nt_error_c_code(req->async_states->status));
213
214         PASS_THRU_REP_POST(req);
215 }
216
217 static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
218                                struct ntvfs_request *req,
219                                union smb_chkpath *cp)
220 {
221         NTSTATUS status;
222
223         PASS_THRU_REQ(ntvfs, req, chkpath, cp, (ntvfs, req, cp));
224
225         return status;
226 }
227
228 /*
229   return info on a pathname
230 */
231 static void nbench_qpathinfo_send(struct ntvfs_request *req)
232 {
233         union smb_fileinfo *info = req->async_states->private_data;
234
235         nbench_log(req, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
236                    info->generic.in.file.path, 
237                    info->generic.level,
238                    get_nt_error_c_code(req->async_states->status));
239
240         PASS_THRU_REP_POST(req);
241 }
242
243 static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
244                                  struct ntvfs_request *req, union smb_fileinfo *info)
245 {
246         NTSTATUS status;
247
248         PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
249
250         return status;
251 }
252
253 /*
254   query info on a open file
255 */
256 static void nbench_qfileinfo_send(struct ntvfs_request *req)
257 {
258         union smb_fileinfo *info = req->async_states->private_data;
259
260         nbench_log(req, "QUERY_FILE_INFORMATION %s %d %s\n", 
261                    nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
262                    info->generic.level,
263                    get_nt_error_c_code(req->async_states->status));
264
265         PASS_THRU_REP_POST(req);
266 }
267
268 static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
269                                  struct ntvfs_request *req, union smb_fileinfo *info)
270 {
271         NTSTATUS status;
272
273         PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
274
275         return status;
276 }
277
278 /*
279   set info on a pathname
280 */
281 static void nbench_setpathinfo_send(struct ntvfs_request *req)
282 {
283         union smb_setfileinfo *st = req->async_states->private_data;
284
285         nbench_log(req, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
286                    st->generic.in.file.path, 
287                    st->generic.level,
288                    get_nt_error_c_code(req->async_states->status));
289
290         PASS_THRU_REP_POST(req);
291 }
292
293 static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
294                                    struct ntvfs_request *req, union smb_setfileinfo *st)
295 {
296         NTSTATUS status;
297
298         PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
299
300         return status;
301 }
302
303 /*
304   open a file
305 */
306 static void nbench_open_send(struct ntvfs_request *req)
307 {
308         union smb_open *io = req->async_states->private_data;
309
310         switch (io->generic.level) {
311         case RAW_OPEN_NTCREATEX:
312                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
313                         ZERO_STRUCT(io->ntcreatex.out);
314                 }
315                 nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %s %s\n", 
316                            io->ntcreatex.in.fname, 
317                            io->ntcreatex.in.create_options, 
318                            io->ntcreatex.in.open_disposition, 
319                            nbench_ntvfs_handle_string(req, io->ntcreatex.out.file.ntvfs),
320                            get_nt_error_c_code(req->async_states->status));
321                 break;
322
323         default:
324                 nbench_log(req, "Open-%d - NOT HANDLED\n",
325                            io->generic.level);
326                 break;
327         }
328
329         PASS_THRU_REP_POST(req);
330 }
331
332 static NTSTATUS nbench_open(struct ntvfs_module_context *ntvfs,
333                             struct ntvfs_request *req, union smb_open *io)
334 {
335         NTSTATUS status;
336
337 #undef open /* AIX defines open to be open64 */
338         PASS_THRU_REQ(ntvfs, req, open, io, (ntvfs, req, io));
339
340         return status;
341 }
342
343 /*
344   create a directory
345 */
346 static void nbench_mkdir_send(struct ntvfs_request *req)
347 {
348         nbench_log(req, "Mkdir - NOT HANDLED\n");
349
350         PASS_THRU_REP_POST(req);
351 }
352
353 static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
354                              struct ntvfs_request *req, union smb_mkdir *md)
355 {
356         NTSTATUS status;
357
358         PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
359
360         return status;
361 }
362
363 /*
364   remove a directory
365 */
366 static void nbench_rmdir_send(struct ntvfs_request *req)
367 {
368         struct smb_rmdir *rd = req->async_states->private_data;
369
370         nbench_log(req, "Rmdir \"%s\" %s\n", 
371                    rd->in.path, 
372                    get_nt_error_c_code(req->async_states->status));
373
374         PASS_THRU_REP_POST(req);
375 }
376
377 static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
378                              struct ntvfs_request *req, struct smb_rmdir *rd)
379 {
380         NTSTATUS status;
381
382         PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
383
384         return status;
385 }
386
387 /*
388   rename a set of files
389 */
390 static void nbench_rename_send(struct ntvfs_request *req)
391 {
392         union smb_rename *ren = req->async_states->private_data;
393
394         switch (ren->generic.level) {
395         case RAW_RENAME_RENAME:
396                 nbench_log(req, "Rename \"%s\" \"%s\" %s\n", 
397                            ren->rename.in.pattern1, 
398                            ren->rename.in.pattern2, 
399                            get_nt_error_c_code(req->async_states->status));
400                 break;
401
402         default:
403                 nbench_log(req, "Rename-%d - NOT HANDLED\n",
404                            ren->generic.level);
405                 break;
406         }
407
408         PASS_THRU_REP_POST(req);
409 }
410
411 static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
412                               struct ntvfs_request *req, union smb_rename *ren)
413 {
414         NTSTATUS status;
415
416         PASS_THRU_REQ(ntvfs, req, rename, ren, (ntvfs, req, ren));
417
418         return status;
419 }
420
421 /*
422   copy a set of files
423 */
424 static void nbench_copy_send(struct ntvfs_request *req)
425 {
426         nbench_log(req, "Copy - NOT HANDLED\n");
427
428         PASS_THRU_REP_POST(req);
429 }
430
431 static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
432                             struct ntvfs_request *req, struct smb_copy *cp)
433 {
434         NTSTATUS status;
435
436         PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
437
438         return status;
439 }
440
441 /*
442   read from a file
443 */
444 static void nbench_read_send(struct ntvfs_request *req)
445 {
446         union smb_read *rd = req->async_states->private_data;
447         
448         switch (rd->generic.level) {
449         case RAW_READ_READX:
450                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
451                         ZERO_STRUCT(rd->readx.out);
452                 }
453                 nbench_log(req, "ReadX %s %d %d %d %s\n", 
454                            nbench_ntvfs_handle_string(req, rd->readx.in.file.ntvfs),
455                            (int)rd->readx.in.offset,
456                            rd->readx.in.maxcnt,
457                            rd->readx.out.nread,
458                            get_nt_error_c_code(req->async_states->status));
459                 break;
460         default:
461                 nbench_log(req, "Read-%d - NOT HANDLED\n",
462                            rd->generic.level);
463                 break;
464         }
465
466         PASS_THRU_REP_POST(req);
467 }
468
469 static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
470                             struct ntvfs_request *req, union smb_read *rd)
471 {
472         NTSTATUS status;
473
474         PASS_THRU_REQ(ntvfs, req, read, rd, (ntvfs, req, rd));
475
476         return status;
477 }
478
479 /*
480   write to a file
481 */
482 static void nbench_write_send(struct ntvfs_request *req)
483 {
484         union smb_write *wr = req->async_states->private_data;
485
486         switch (wr->generic.level) {
487         case RAW_WRITE_WRITEX:
488                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
489                         ZERO_STRUCT(wr->writex.out);
490                 }
491                 nbench_log(req, "WriteX %s %d %d %d %s\n", 
492                            nbench_ntvfs_handle_string(req, wr->writex.in.file.ntvfs),
493                            (int)wr->writex.in.offset,
494                            wr->writex.in.count,
495                            wr->writex.out.nwritten,
496                            get_nt_error_c_code(req->async_states->status));
497                 break;
498
499         case RAW_WRITE_WRITE:
500                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
501                         ZERO_STRUCT(wr->write.out);
502                 }
503                 nbench_log(req, "Write %s %d %d %d %s\n", 
504                            nbench_ntvfs_handle_string(req, wr->write.in.file.ntvfs),
505                            wr->write.in.offset,
506                            wr->write.in.count,
507                            wr->write.out.nwritten,
508                            get_nt_error_c_code(req->async_states->status));
509                 break;
510
511         default:
512                 nbench_log(req, "Write-%d - NOT HANDLED\n",
513                            wr->generic.level);
514                 break;
515         }
516
517         PASS_THRU_REP_POST(req);
518 }
519
520 static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
521                              struct ntvfs_request *req, union smb_write *wr)
522 {
523         NTSTATUS status;
524
525         PASS_THRU_REQ(ntvfs, req, write, wr, (ntvfs, req, wr));
526
527         return status;
528 }
529
530 /*
531   seek in a file
532 */
533 static void nbench_seek_send(struct ntvfs_request *req)
534 {
535         nbench_log(req, "Seek - NOT HANDLED\n");
536
537         PASS_THRU_REP_POST(req);
538 }
539
540 static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
541                             struct ntvfs_request *req,
542                             union smb_seek *io)
543 {
544         NTSTATUS status;
545
546         PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
547
548         return status;
549 }
550
551 /*
552   flush a file
553 */
554 static void nbench_flush_send(struct ntvfs_request *req)
555 {
556         union smb_flush *io = req->async_states->private_data;
557
558         switch (io->generic.level) {
559         case RAW_FLUSH_FLUSH:
560                 nbench_log(req, "Flush %s %s\n",
561                            nbench_ntvfs_handle_string(req, io->flush.in.file.ntvfs),
562                            get_nt_error_c_code(req->async_states->status));
563                 break;
564         case RAW_FLUSH_ALL:
565                 nbench_log(req, "Flush %d %s\n",
566                            0xFFFF,
567                            get_nt_error_c_code(req->async_states->status));
568                 break;
569         default:
570                 nbench_log(req, "Flush-%d - NOT HANDLED\n",
571                            io->generic.level);
572                 break;
573         }
574
575         PASS_THRU_REP_POST(req);
576 }
577
578 static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
579                              struct ntvfs_request *req,
580                              union smb_flush *io)
581 {
582         NTSTATUS status;
583
584         PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
585
586         return status;
587 }
588
589 /*
590   close a file
591 */
592 static void nbench_close_send(struct ntvfs_request *req)
593 {
594         union smb_close *io = req->async_states->private_data;
595
596         switch (io->generic.level) {
597         case RAW_CLOSE_CLOSE:
598                 nbench_log(req, "Close %s %s\n",
599                            nbench_ntvfs_handle_string(req, io->close.in.file.ntvfs),
600                            get_nt_error_c_code(req->async_states->status));
601                 break;
602
603         default:
604                 nbench_log(req, "Close-%d - NOT HANDLED\n",
605                            io->generic.level);
606                 break;
607         }               
608
609         PASS_THRU_REP_POST(req);
610 }
611
612 static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
613                              struct ntvfs_request *req, union smb_close *io)
614 {
615         NTSTATUS status;
616
617         PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
618
619         return status;
620 }
621
622 /*
623   exit - closing files
624 */
625 static void nbench_exit_send(struct ntvfs_request *req)
626 {
627         nbench_log(req, "Exit - NOT HANDLED\n");
628
629         PASS_THRU_REP_POST(req);
630 }
631
632 static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
633                             struct ntvfs_request *req)
634 {
635         NTSTATUS status;
636
637         PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
638
639         return status;
640 }
641
642 /*
643   logoff - closing files
644 */
645 static void nbench_logoff_send(struct ntvfs_request *req)
646 {
647         nbench_log(req, "Logoff - NOT HANDLED\n");
648
649         PASS_THRU_REP_POST(req);
650 }
651
652 static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
653                               struct ntvfs_request *req)
654 {
655         NTSTATUS status;
656
657         PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
658
659         return status;
660 }
661
662 /*
663   async_setup - send fn
664 */
665 static void nbench_async_setup_send(struct ntvfs_request *req)
666 {
667         PASS_THRU_REP_POST(req);
668 }
669
670 /*
671   async setup
672 */
673 static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
674                                    struct ntvfs_request *req,
675                                    void *private_data)
676 {
677         NTSTATUS status;
678
679         PASS_THRU_REQ(ntvfs, req, async_setup, NULL, (ntvfs, req, private_data));
680
681         return status;
682 }
683
684
685 static void nbench_cancel_send(struct ntvfs_request *req)
686 {
687         PASS_THRU_REP_POST(req);
688 }
689
690 /*
691   cancel an existing async request
692 */
693 static NTSTATUS nbench_cancel(struct ntvfs_module_context *ntvfs,
694                               struct ntvfs_request *req)
695 {
696         NTSTATUS status;
697
698         PASS_THRU_REQ(ntvfs, req, cancel, NULL, (ntvfs, req));
699
700         return status;
701 }
702
703 /*
704   lock a byte range
705 */
706 static void nbench_lock_send(struct ntvfs_request *req)
707 {
708         union smb_lock *lck = req->async_states->private_data;
709
710         if (lck->generic.level == RAW_LOCK_LOCKX &&
711             lck->lockx.in.lock_cnt == 1 &&
712             lck->lockx.in.ulock_cnt == 0) {
713                 nbench_log(req, "LockX %s %d %d %s\n", 
714                            nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
715                            (int)lck->lockx.in.locks[0].offset,
716                            (int)lck->lockx.in.locks[0].count,
717                            get_nt_error_c_code(req->async_states->status));
718         } else if (lck->generic.level == RAW_LOCK_LOCKX &&
719                    lck->lockx.in.ulock_cnt == 1) {
720                 nbench_log(req, "UnlockX %s %d %d %s\n", 
721                            nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
722                            (int)lck->lockx.in.locks[0].offset,
723                            (int)lck->lockx.in.locks[0].count,
724                            get_nt_error_c_code(req->async_states->status));
725         } else {
726                 nbench_log(req, "Lock-%d - NOT HANDLED\n", lck->generic.level);
727         }
728
729         PASS_THRU_REP_POST(req);
730 }
731
732 static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
733                             struct ntvfs_request *req, union smb_lock *lck)
734 {
735         NTSTATUS status;
736
737         PASS_THRU_REQ(ntvfs, req, lock, lck, (ntvfs, req, lck));
738
739         return status;
740 }
741
742 /*
743   set info on a open file
744 */
745 static void nbench_setfileinfo_send(struct ntvfs_request *req)
746 {
747         union smb_setfileinfo *info = req->async_states->private_data;
748
749         nbench_log(req, "SET_FILE_INFORMATION %s %d %s\n", 
750                    nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
751                    info->generic.level,
752                    get_nt_error_c_code(req->async_states->status));
753
754         PASS_THRU_REP_POST(req);
755 }
756
757 static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
758                                    struct ntvfs_request *req, 
759                                    union smb_setfileinfo *info)
760 {
761         NTSTATUS status;
762
763         PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
764
765         return status;
766 }
767
768 /*
769   return filesystem space info
770 */
771 static void nbench_fsinfo_send(struct ntvfs_request *req)
772 {
773         union smb_fsinfo *fs = req->async_states->private_data;
774
775         nbench_log(req, "QUERY_FS_INFORMATION %d %s\n", 
776                    fs->generic.level, 
777                    get_nt_error_c_code(req->async_states->status));
778
779         PASS_THRU_REP_POST(req);
780 }
781
782 static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
783                               struct ntvfs_request *req, union smb_fsinfo *fs)
784 {
785         NTSTATUS status;
786
787         PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
788
789         return status;
790 }
791
792 /*
793   return print queue info
794 */
795 static void nbench_lpq_send(struct ntvfs_request *req)
796 {
797         union smb_lpq *lpq = req->async_states->private_data;
798
799         nbench_log(req, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
800
801         PASS_THRU_REP_POST(req);
802 }
803
804 static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
805                            struct ntvfs_request *req, union smb_lpq *lpq)
806 {
807         NTSTATUS status;
808
809         PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
810
811         return status;
812 }
813
814 /* 
815    list files in a directory matching a wildcard pattern
816 */
817 static void nbench_search_first_send(struct ntvfs_request *req)
818 {
819         union smb_search_first *io = req->async_states->private_data;
820         
821         switch (io->generic.level) {
822         case RAW_SEARCH_TRANS2:
823                 if (NT_STATUS_IS_ERR(req->async_states->status)) {
824                         ZERO_STRUCT(io->t2ffirst.out);
825                 }
826                 nbench_log(req, "FIND_FIRST \"%s\" %d %d %d %s\n", 
827                            io->t2ffirst.in.pattern,
828                            io->t2ffirst.data_level,
829                            io->t2ffirst.in.max_count,
830                            io->t2ffirst.out.count,
831                            get_nt_error_c_code(req->async_states->status));
832                 break;
833                 
834         default:
835                 nbench_log(req, "Search-%d - NOT HANDLED\n", io->generic.level);
836                 break;
837         }
838
839         PASS_THRU_REP_POST(req);
840 }
841
842 static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
843                                     struct ntvfs_request *req, union smb_search_first *io, 
844                                     void *search_private, 
845                                     bool (*callback)(void *, const union smb_search_data *))
846 {
847         NTSTATUS status;
848
849         PASS_THRU_REQ(ntvfs, req, search_first, io, (ntvfs, req, io, search_private, callback));
850
851         return status;
852 }
853
854 /* continue a search */
855 static void nbench_search_next_send(struct ntvfs_request *req)
856 {
857         union smb_search_next *io = req->async_states->private_data;
858
859         nbench_log(req, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
860
861         PASS_THRU_REP_POST(req);
862 }
863
864 static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
865                                    struct ntvfs_request *req, union smb_search_next *io, 
866                                    void *search_private, 
867                                    bool (*callback)(void *, const union smb_search_data *))
868 {
869         NTSTATUS status;
870
871         PASS_THRU_REQ(ntvfs, req, search_next, io, (ntvfs, req, io, search_private, callback));
872
873         return status;
874 }
875
876 /* close a search */
877 static void nbench_search_close_send(struct ntvfs_request *req)
878 {
879         union smb_search_close *io = req->async_states->private_data;
880
881         nbench_log(req, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
882
883         PASS_THRU_REP_POST(req);
884 }
885
886 static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
887                                     struct ntvfs_request *req, union smb_search_close *io)
888 {
889         NTSTATUS status;
890
891         PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
892
893         return status;
894 }
895
896 /* SMBtrans - not used on file shares */
897 static void nbench_trans_send(struct ntvfs_request *req)
898 {
899         nbench_log(req, "Trans - NOT HANDLED\n");
900
901         PASS_THRU_REP_POST(req);
902 }
903
904 static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
905                              struct ntvfs_request *req, struct smb_trans2 *trans2)
906 {
907         NTSTATUS status;
908
909         PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
910
911         return status;
912 }
913
914 /*
915   initialise the nbench backend, registering ourselves with the ntvfs subsystem
916  */
917 NTSTATUS ntvfs_nbench_init(void)
918 {
919         NTSTATUS ret;
920         struct ntvfs_ops ops;
921         NTVFS_CURRENT_CRITICAL_SIZES(vers);
922
923         ZERO_STRUCT(ops);
924
925         /* fill in the name and type */
926         ops.name = "nbench";
927         ops.type = NTVFS_DISK;
928         
929         /* fill in all the operations */
930         ops.connect = nbench_connect;
931         ops.disconnect = nbench_disconnect;
932         ops.unlink = nbench_unlink;
933         ops.chkpath = nbench_chkpath;
934         ops.qpathinfo = nbench_qpathinfo;
935         ops.setpathinfo = nbench_setpathinfo;
936         ops.open = nbench_open;
937         ops.mkdir = nbench_mkdir;
938         ops.rmdir = nbench_rmdir;
939         ops.rename = nbench_rename;
940         ops.copy = nbench_copy;
941         ops.ioctl = nbench_ioctl;
942         ops.read = nbench_read;
943         ops.write = nbench_write;
944         ops.seek = nbench_seek;
945         ops.flush = nbench_flush;       
946         ops.close = nbench_close;
947         ops.exit = nbench_exit;
948         ops.lock = nbench_lock;
949         ops.setfileinfo = nbench_setfileinfo;
950         ops.qfileinfo = nbench_qfileinfo;
951         ops.fsinfo = nbench_fsinfo;
952         ops.lpq = nbench_lpq;
953         ops.search_first = nbench_search_first;
954         ops.search_next = nbench_search_next;
955         ops.search_close = nbench_search_close;
956         ops.trans = nbench_trans;
957         ops.logoff = nbench_logoff;
958         ops.async_setup = nbench_async_setup;
959         ops.cancel = nbench_cancel;
960
961         /* we don't register a trans2 handler as we want to be able to
962            log individual trans2 requests */
963         ops.trans2 = NULL;
964
965         /* register ourselves with the NTVFS subsystem. */
966         ret = ntvfs_register(&ops, &vers);
967
968         if (!NT_STATUS_IS_OK(ret)) {
969                 DEBUG(0,("Failed to register nbench backend!\n"));
970         }
971         
972         return ret;
973 }