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