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