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