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