dc0552c52a0ad33b96216e4610a00753972d98df
[openafs.git] / src / WINNT / tests / torture / Source / nbio.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Richard Sharpe  2002
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "common.h"
24
25 extern int verbose;
26
27 #define off_t DWORD
28
29 __declspec( thread ) extern int     ProcessNumber;
30 __declspec( thread ) extern int     LineCount;
31 __declspec( thread ) extern int     AfsTrace;
32 __declspec( thread ) extern int     *pThreadStatus;
33 __declspec( thread ) extern int     LogID;
34 __declspec( thread ) extern char    *IoBuffer;
35 __declspec( thread ) extern int     BufferSize;
36 __declspec( thread ) extern char    AfsLocker[256];
37 __declspec( thread ) extern char    OriginalAfsLocker[256];
38 __declspec( thread ) extern char    HostName[256];
39 __declspec( thread ) extern DWORD   TickCount1, TickCount2, MilliTickStart;
40 __declspec( thread ) extern FTABLE  ftable[MAX_FILES];
41 __declspec( thread ) extern struct  cmd_struct ThreadCommandInfo[CMD_MAX_CMD + 1];
42 __declspec( thread ) extern EXIT_STATUS *pExitStatus;
43 __declspec( thread ) extern DWORD   LastKnownError;
44 extern void LogMessage(int ProcessNumber, char *HostName, char *FileName, char *message, int LogID);
45
46 HANDLE CreateObject(const char *fname, uint32 DesiredAccess,
47                   uint32 FileAttributes, uint32 ShareAccess,
48                   uint32 CreateDisposition, uint32 CreateOptions);
49 void DumpAFSLog(char * HostName, int LogID);
50 int  FindHandle(int handle);
51 int  GetFileList(char *Mask, void (*fn)(file_info *, const char *, void *), void *state);
52 BOOL GetFileInfo(char *FileName, HANDLE fd, uint16 *mode, size_t *size,
53                         time_t *c_time, time_t *a_time, time_t *m_time, 
54                         time_t *w_time);
55 BOOL GetPathInfo(const char *fname, time_t *c_time, time_t *a_time, time_t *m_time, 
56                          size_t *size, uint16 *mode);
57 int  LeaveThread(int status, char *Reason, int cmd);
58 void StartFirstTimer();
59 void EndFirstTimer(int cmd, int Type);
60 void StartSecondTime(int cmd);
61 void EndSecondTime(int cmd);
62 void SubstituteString(char *s,const char *pattern,const char *insert, size_t len);
63 intptr_t  SystemCall(char *command);
64 HANDLE WinFindFirstFile(char *Mask, void **FileData, char *cFileName, int *dwFileAttributes);
65 int  WinFindNextFile(HANDLE hFind, void **FileData, char *cFileName, int *dwFileAttributes);
66
67 int FindHandle(int handle)
68 {
69     int i;
70     for (i=0;i<MAX_FILES;i++)
71     {
72         if (ftable[i].handle == handle)
73             return(i);
74     }
75     if (verbose)
76         printf("(%d) ERROR: handle %d was not found\n", LineCount, handle);
77     return(LeaveThread(1, "", -1));
78 }
79
80 int nb_unlink(char *fname)
81 {
82     int     rc;
83     char    temp[256];
84     char    FileName[128];
85     pstring path;
86
87     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
88
89     strcpy(path, AfsLocker);
90     strcat(path, fname);
91
92     StartFirstTimer();
93     rc = DeleteFile(path);
94     EndFirstTimer(CMD_UNLINK, 1);
95     if (!rc)
96     {
97         LeaveThread(0, "", CMD_UNLINK);
98         sprintf(temp, "FILE: DeleteFile %s failed GLE(0x%x)\n", fname, GetLastError());
99         if (verbose)
100             printf("%s", temp);
101         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
102         return(-1);
103     }
104
105     return(0);
106 }
107
108 int nb_SetLocker(char *Locker)
109 {
110
111     StartFirstTimer();
112     if (strlen(Locker) == 0)
113         strcpy(AfsLocker, OriginalAfsLocker);
114     else
115         strcpy(AfsLocker, Locker);
116     EndFirstTimer(CMD_SETLOCKER, 1);
117     return(0);
118 }
119
120 int nb_Xrmdir(char *Directory, char *type)
121 {
122     DWORD   rc;
123     char    FileName[128];
124     char    command[256];
125     char    NewDirectory[256];
126     char    temp[512];
127
128     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
129     if (strlen(Directory) == 0)
130     {
131         return(LeaveThread(1, "rmdir failed no path specified\n", CMD_XRMDIR));
132     }
133     strcpy(NewDirectory, Directory);
134     memset(command, '\0', sizeof(command));
135     strcpy(command,"rmdir /Q ");
136     if (!stricmp(type, "all"))
137     {
138         strcat(command, "/S ");
139     }
140     strcat(command, NewDirectory);
141
142     StartFirstTimer();
143     rc = system(command);
144
145     if ((rc) && (rc != 2) && (rc != 3))
146     {
147         EndFirstTimer(CMD_XRMDIR, 0);
148         sprintf(temp, "rmdir failed on %s\n", command);
149         LeaveThread(rc, temp, CMD_XRMDIR);
150         sprintf(temp, "FAILURE: Thread %d - Xrmdir failed on \"%s\"\n", ProcessNumber, command);
151         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
152         return(-1);
153     }
154     EndFirstTimer(CMD_XRMDIR, 1);
155     return(0);
156 }
157
158
159 int nb_Mkdir(char *Directory)
160 {
161     DWORD   rc;
162     char    FileName[128];
163     char    command[256];
164     char    NewDirectory[256];
165     char    temp[512];
166
167     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
168     if (strlen(Directory) == 0)
169     {
170         return(LeaveThread(1, "mkdir failed on no path specified\n", CMD_MKDIR));
171     }
172     strcpy(NewDirectory, Directory);
173     memset(command, '\0', sizeof(command));
174     strcpy(command,"mkdir ");
175     strcat(command, NewDirectory);
176
177     StartFirstTimer();
178     rc = system(command);
179
180     if (rc > 1)
181     {
182         EndFirstTimer(CMD_MKDIR, 0);
183         sprintf(temp,  "mkdir failed on %s\n", command);
184         LeaveThread(rc, temp, CMD_MKDIR);
185         sprintf(temp, "ERROR: Thread %d - mkdir failed on \"%s\"\n", ProcessNumber, command);
186         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
187         return(-1);
188     }
189     EndFirstTimer(CMD_MKDIR, 1);
190     return(0);
191 }
192
193 int nb_Attach(char *Locker, char *Drive)
194 {
195     DWORD   rc;
196     char    FileName[128];
197     char    command[512];
198     char    temp[512];
199
200     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
201     if (strlen(Locker) == 0)
202     {
203         return(LeaveThread(1, "attach failed no locker specified\n", CMD_ATTACH));
204     }
205     memset(command, '\0', sizeof(command));
206     strcpy(command,"attach -q ");
207     rc = 0;
208     if (strlen(Drive) != 0)
209     {
210         sprintf(temp, "-D %s ", Drive);
211         strcat(command, temp);
212     }
213     strcat(command, Locker);
214
215     StartFirstTimer();
216     rc = system(command);
217
218     if (rc)
219     {
220         EndFirstTimer(CMD_ATTACH, 0);
221         sprintf(pExitStatus->Reason, "attach failed on %s\n", command);
222         pExitStatus->ExitStatus = rc;
223         sprintf(temp, "ERROR: Thread %d - attach failed on \"%s\"\n", ProcessNumber, command);
224         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
225     }
226     EndFirstTimer(CMD_ATTACH, 1);
227     return(0);
228 }
229
230 int nb_Detach(char *Name, char *type)
231 {
232     DWORD   rc;
233     char    FileName[128];
234     char    command[512];
235     char    temp[512];
236
237     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
238     memset(command, '\0', sizeof(command));
239     strcpy(command,"detach -q ");
240     rc = 0;
241     if (!stricmp(type, "drive"))
242     {
243         sprintf(temp, "-D %s ", Name);
244         strcat(command, temp);
245     }
246     else if (!stricmp(type, "locker"))
247     {
248         strcat(command, Name);
249     }
250     else
251     {
252         return(LeaveThread(1, "nb_Detach failed unknown type: %s\n", CMD_DETACH));
253     }
254
255     StartFirstTimer();
256     rc = system(command);
257
258     if (rc)
259     {
260         EndFirstTimer(CMD_DETACH, 0);
261         sprintf(temp, "detach failed on %s\n", command);
262         LeaveThread(rc, temp, CMD_DETACH);
263         sprintf(temp, "ERROR: Thread %d - detach failed on \"%s\"\n", ProcessNumber, command);
264         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
265         return(-1);
266     }
267     EndFirstTimer(CMD_DETACH, 1);
268     return(0);
269 }
270
271 int nb_CreateFile(char *path, DWORD size)
272 {
273     char    NewPath[256];
274     char    Buffer[512];
275     char    temp[512];
276     char    FileName[128];
277     HANDLE  fHandle;
278     DWORD   Moved;
279     DWORD   BytesWritten;
280     DWORD   BytesToWrite;
281     BOOL    rc;
282
283     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
284     if (strlen(path) == 0)
285     {
286         return(LeaveThread(1, "nb_DeleteFile failed no path specified\n", CMD_CREATEFILE));
287     }
288
289     strcpy(NewPath, path);
290
291     StartFirstTimer();
292     fHandle = CreateFile(NewPath, 
293                          GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL,
294                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
295                          NULL,
296                          CREATE_ALWAYS,
297                          FILE_ATTRIBUTE_NORMAL,
298                          NULL);
299
300     if (fHandle == INVALID_HANDLE_VALUE)
301     {
302         rc = GetLastError();
303         EndFirstTimer(CMD_CREATEFILE, 0);
304         sprintf(temp, "Create file failed on \"%s\" GLE(0x%x)\n", NewPath, rc);
305         LeaveThread(0, temp, CMD_CREATEFILE);
306         sprintf(temp, "ERROR: Thread %d - Create file failed on \"%s\" GLE(0x%x)\n", ProcessNumber, NewPath, rc);
307         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
308         return(-1);
309     }
310     EndFirstTimer(CMD_CREATEFILE, 1);
311     Moved = SetFilePointer(fHandle,
312                            size,
313                            NULL,
314                            FILE_BEGIN);
315     memset(Buffer, 'A', sizeof(Buffer));
316     BytesToWrite = sizeof(Buffer);
317     rc = WriteFile(fHandle, Buffer, BytesToWrite, &BytesWritten, NULL);
318
319     FlushFileBuffers(fHandle);
320     CloseHandle(fHandle);
321
322     return(0);
323 }
324
325 int nb_CopyFile(char *Source, char *Destination)
326 {
327     DWORD   rc;
328     char    FileName[128];
329     char    temp[512];
330     char    command[256];
331     char    NewSource[256];
332     char    NewDestination[256];
333
334     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
335     if ((strlen(Source) == 0) || (strlen(Destination) == 0))
336     {
337         return(LeaveThread(1, "nb_CopyFile failed to copy files: either source or destination path not specified\n", CMD_COPYFILES));
338     }
339     strcpy(NewSource, Source);
340     strcpy(NewDestination, Destination);
341
342     memset(command, '\0', sizeof(command));
343     sprintf(command, "copy /V /Y /B %s %s > .\\test\\%s%d", NewSource, NewDestination, HostName, ProcessNumber);
344
345     StartFirstTimer();
346     rc = system(command);
347
348     if (rc)
349     {
350         EndFirstTimer(CMD_COPYFILES, 0);
351         sprintf(temp, "copy failed on \"%s\"\n", command);
352         LeaveThread(rc, temp, CMD_COPYFILES);
353         sprintf(temp, "FAILURE: Thread %d - copy failed on \"%s\"\n", ProcessNumber, command);
354         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
355         if (verbose)
356             printf("%s", temp);
357         return(-1);
358     }
359     EndFirstTimer(CMD_COPYFILES, 1);
360     return(0);
361 }
362
363 int nb_DeleteFile(char *path)
364 {
365     DWORD   rc;
366     char    FileName[128];
367     char    command[256];
368     char    NewPath[256];
369     char    temp[512];
370
371     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
372     if (strlen(path) == 0)
373     {
374         return(LeaveThread(1, "nb_DeleteFile failed to delete files: no path specified\n", CMD_DELETEFILES));
375     }
376     strcpy(NewPath, path);
377
378     memset(command, '\0', sizeof(command));
379     sprintf(command, "del /Q %s", NewPath);
380
381     StartFirstTimer();
382     rc = system(command);
383
384     if (rc)
385     {
386         EndFirstTimer(CMD_DELETEFILES, 0);
387         sprintf(temp, "del failed on \"%s\"\n", NewPath);
388         LeaveThread(rc, temp, CMD_DELETEFILES);
389         sprintf(temp, "ERROR: Thread %d - del failed on \"%s\"\n", ProcessNumber, command);
390         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
391         return(-1);
392     }
393     EndFirstTimer(CMD_DELETEFILES, 1);
394     return(0);
395 }
396
397 int nb_xcopy(char *Source, char *Destination)
398 {
399     intptr_t   rc;
400     char    FileName[128];
401     char    temp[512];
402     char    command[256];
403     char    NewSource[256];
404     char    NewDestination[256];
405
406     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
407     if ((strlen(Source) == 0) || (strlen(Destination) == 0))
408     {
409         return(LeaveThread(1, "nb_xcopy failed to xcopy: either source or destination is missing\n", CMD_XCOPY));
410     }
411     strcpy(NewSource, Source);
412     strcpy(NewDestination, Destination);
413     memset(command, '\0', sizeof(command));
414     sprintf(command, "xcopy /E /I /V /Y /Q %s %s > .\\test\\%s%d", NewSource, NewDestination, HostName, ProcessNumber);
415
416     StartFirstTimer();
417     rc = SystemCall(command);
418
419     if (rc)
420     {
421         EndFirstTimer(CMD_XCOPY, 0);
422         sprintf(temp, "xcopy failed on %s\n", command);
423         LeaveThread((int)rc, temp, CMD_XCOPY);
424         sprintf(temp, "FAIURE: Thread %d - xcopy failed on \"%s\"\n", ProcessNumber, command);
425         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
426         return(-1);
427     }
428     EndFirstTimer(CMD_XCOPY, 1);
429     return(0);
430 }
431
432 int nb_Move(char *Source, char *Destination)
433 {
434     DWORD   rc;
435     char    command[256];
436     char    FileName[128];
437     char    temp[512];
438     char    NewSource[256];
439     char    NewDestination[256];
440
441     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
442     if ((strlen(Source) == 0) || (strlen(Destination) == 0))
443     {
444         return(LeaveThread(1, "nb_Move failed to move: either source or destination is missing\n", CMD_MOVE));
445     }
446     strcpy(NewSource, Source);
447     strcpy(NewDestination, Destination);
448     memset(command, '\0', sizeof(command));
449     sprintf(command, "move /Y %s %s > .\\test\\%s%d", NewSource, NewDestination, HostName, ProcessNumber);
450     StartFirstTimer();
451     rc = system(command);
452
453     if (rc)
454     {
455         EndFirstTimer(CMD_MOVE, 0);
456         sprintf(temp, "move failed on \"%s\"\n", command);
457         LeaveThread(rc, temp, CMD_MOVE);
458         sprintf(temp, "FAILURE: Thread %d - move failed on \"%s\"\n", ProcessNumber, command);
459         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
460         return(-1);
461     }
462     EndFirstTimer(CMD_MOVE, 1);
463     return(0);
464 }
465
466 int nb_createx(char *fname, unsigned create_options, unsigned create_disposition, int handle)
467 {
468     HANDLE  fd;
469     int     i;
470     uint32  desired_access;
471     char    FileName[128];
472     char    temp[512];
473     pstring path;
474
475     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
476
477     strcpy(path, AfsLocker);
478     strcat(path, fname);
479     if (create_options & FILE_DIRECTORY_FILE)
480     {
481         desired_access = FILE_READ_DATA;
482     }
483     else
484     {
485         desired_access = FILE_READ_DATA | FILE_WRITE_DATA;
486     }
487
488     StartFirstTimer();
489     fd = CreateObject(path, 
490                        desired_access,
491                        0x0,
492                        FILE_SHARE_READ|FILE_SHARE_WRITE, 
493                        create_disposition, 
494                        create_options);
495
496     if (fd == INVALID_HANDLE_VALUE && handle != -1)
497     {
498         if (create_options & FILE_DIRECTORY_FILE)
499         {
500             EndFirstTimer(CMD_NTCREATEX, 0);
501             LeaveThread(0, "", CMD_NTCREATEX);
502             sprintf(temp, "Directory: unable to create directory %s\n", path);
503             if (verbose)
504                 printf("%s", temp);
505             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
506             return(-1);
507         }
508         else
509         {
510             EndFirstTimer(CMD_NTCREATEX, 0);
511             LeaveThread(0, "", CMD_NTCREATEX);
512             sprintf(temp, "File: unable to create file %s\n", path);
513             if (verbose)
514                 printf("%s", temp);
515             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
516             return(-1);
517         }
518     }
519
520     EndFirstTimer(CMD_NTCREATEX, 1);
521
522     if (fd != INVALID_HANDLE_VALUE && handle == -1)
523     {
524         CloseHandle(fd);
525         nb_unlink(fname);
526         return(0);
527     }
528
529     if (fd == INVALID_HANDLE_VALUE && handle == -1)
530         return(0);
531
532     for (i = 0; i < MAX_FILES; i++) 
533     {
534         if (ftable[i].handle == 0) 
535             break;
536     }
537     if (i == MAX_FILES) 
538     {
539         printf("(%d) file table full for %s\n", LineCount, path);
540         return(LeaveThread(1, "file table is full\n", CMD_NTCREATEX));
541     }
542     ftable[i].handle = handle;
543     ftable[i].fd = fd;
544     if (ftable[i].name) 
545         free(ftable[i].name);
546     ftable[i].name = strdup(path);
547     ftable[i].reads = ftable[i].writes = 0;
548     return(0);
549 }
550
551 int nb_writex(int handle, int offset, int size, int ret_size)
552 {
553     int     i;
554     ssize_t status;
555     char    FileName[128];
556     char    temp[512];
557
558     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
559
560     if (IoBuffer[0] == 0) 
561         memset(IoBuffer, 1, BufferSize);
562
563     if ((i = FindHandle(handle)) == -1)
564         return(-1);
565     StartFirstTimer();
566     status = nb_write(ftable[i].fd, IoBuffer, offset, size);
567     if (status != ret_size) 
568     {
569         EndFirstTimer(CMD_WRITEX, 0);
570                 LeaveThread(0, "", CMD_WRITEX);
571         if (status == 0)
572             sprintf(temp, "File: %s. wrote %d bytes, got %d bytes\n", ftable[i].name, size, status);
573         if (status == -1)
574             sprintf(temp, "File: %s. On write, cannot set file pointer\n", ftable[i].name);
575         if (verbose)
576             printf("%s", temp);
577         nb_close(handle);
578         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
579         return(-1);
580         }
581     EndFirstTimer(CMD_WRITEX, 1);
582
583     ftable[i].writes++;
584     return(0);
585 }
586
587 int nb_lock(int handle, int offset, int size, int timeout, unsigned char locktype, NTSTATUS exp)
588 {
589 /*
590     int         i;
591     NTSTATUS    ret;
592     char        FileName[128];
593     char        temp[512];
594
595     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
596
597     if ((i = FindHandle(handle)) == -1)
598     {
599         LeaveThread(0, "", CMD_LOCKINGX);
600         sprintf(temp, "File unlock: Cannot find handle for %s", ftable[i].name);
601         if (verbose)
602             printf("%s", temp);
603         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
604         return(-1);
605     }
606
607     StartFirstTimer();
608     ret = cli_locktype(c, i, offset, size, timeout, locktype);
609
610     if (ret != exp)
611     {
612         EndFirstTimer(CMD_LOCKINGX, 0);
613         LeaveThread(0, "", CMD_LOCKINGX);
614         sprintf(temp, "(%d) ERROR: lock failed on handle %d ofs=%d size=%d timeout= %d exp=%d fd %d errno %d (%s)\n",
615                LineCount, handle, offset, size, timeout, exp, ftable[i].fd, exp, "");
616         sprintf(temp, "File unlock: lock failed %s", ftable[i].name);
617         if (verbose)
618             printf("%s", temp);
619         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
620         return(-1);
621     }
622     EndFirstTimer(CMD_LOCKINGX, 1);
623 */
624     return(0);
625 }
626
627 int nb_readx(int handle, int offset, int size, int ret_size)
628 {
629     int     i;
630     ssize_t ret;
631     char    FileName[128];
632     char    temp[512];
633
634     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
635
636     if ((i = FindHandle(handle)) == -1)
637         return(-1);
638
639     StartFirstTimer();
640     ret = nb_read(ftable[i].fd, IoBuffer, offset, size);
641
642     if ((ret != size) && (ret != ret_size))
643     {
644         EndFirstTimer(CMD_READX, 0);
645         LeaveThread(0, "", CMD_READX);
646         if (ret == 0)
647             sprintf(temp, "File: read failed on index=%d, offset=%d ReadSize=%d ActualRead=%d handle=%p GLE(0x%x)\n",
648                     handle, offset, size, ret, ftable[i].fd, GetLastError());
649         if (ret == -1)
650             sprintf(temp, "File: %s. On read, cannot set file pointer GLE(0x%x)\n", ftable[i].name, GetLastError());
651         if (verbose)
652             printf("%s", temp);
653         nb_close(handle);
654         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
655         return(-1);
656     }
657     EndFirstTimer(CMD_READX, 1);
658     ftable[i].reads++;
659     return(0);
660 }
661
662 int nb_close(int handle)
663 {
664     int     i;
665     int     ret;
666     char    FileName[128];
667     char    temp[512];
668
669     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
670
671     if ((i = FindHandle(handle)) == -1)
672         return(0);
673
674     StartFirstTimer();
675     ret = nb_close1(ftable[i].fd); 
676     EndFirstTimer(CMD_CLOSE, ret);
677     if (!ret) 
678     {
679         LeaveThread(0, "", CMD_CLOSE);
680         sprintf(temp, "(%d) close failed on handle %d\n", LineCount, handle);
681         if (verbose)
682             printf("%s", temp);
683         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
684         return(-1);
685     }
686
687     ftable[i].handle = 0;
688     ftable[i].fd = 0;
689     if (ftable[i].name) 
690         free(ftable[i].name);
691     ftable[i].name = NULL;
692     return(0);   
693 }
694
695 int nb_rmdir(char *fname)
696 {
697     int     rc;
698     pstring path;
699     char    FileName[128];
700     char    temp[512];
701
702     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
703
704     strcpy(path, AfsLocker);
705     strcat(path, fname);
706
707     StartFirstTimer();
708     rc = RemoveDirectory(path);
709     EndFirstTimer(CMD_RMDIR, rc);
710
711     if (!rc)
712     {
713         LeaveThread(0, "", CMD_RMDIR);
714         sprintf(temp, "Directory: RemoveDirectory %s failed GLE(0x%x)\n", fname, GetLastError());
715         if (verbose)
716             printf("%s", temp);
717         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
718         return(-1);
719     }
720     return(0);
721 }
722
723 int nb_rename(char *old, char *New)
724 {
725     int     rc;
726     pstring opath;
727     pstring npath;
728     char    FileName[128];
729     char    temp[512];
730
731     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
732
733     strcpy(opath, AfsLocker);
734     strcat(opath, old);
735     strcpy(npath, AfsLocker);
736     strcat(npath, New); 
737
738     StartFirstTimer();
739     rc = MoveFileEx(opath, npath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
740     EndFirstTimer(CMD_RENAME, rc);
741
742     if (!rc)
743     {
744         LeaveThread(0, "", CMD_RENAME);
745         sprintf(temp, "File: rename %s %s failed GLE(0x%x)\n", old, New, GetLastError());
746         if (verbose)
747             printf("%s", temp);
748         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
749         return(-1);
750     }
751     return(0);
752 }
753
754
755 int nb_qpathinfo(char *fname, int Type)
756 {
757     pstring path;
758     int     rc;
759     char    FileName[128];
760     char    temp[512];
761     int     Flag = 0;
762
763     if (Type == 1111)
764         Flag = 1;
765
766     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
767
768     strcpy(path, AfsLocker);
769     strcat(path, fname);
770
771     StartFirstTimer();
772     rc = GetPathInfo(path, NULL, NULL, NULL, NULL, NULL);
773
774     if (strstr(fname, "~TS"))
775     {
776         if (rc == 0)
777             rc = 1;
778         else
779             rc = 0;
780     }
781
782     if (!Flag)
783     {
784         if (Type)
785         {
786             if (rc)
787                 rc = 0;
788             else
789                 rc = 1;
790         }
791         if (!rc)
792         {
793             EndFirstTimer(CMD_QUERY_PATH_INFO, 0);
794             LeaveThread(0, "", CMD_QUERY_PATH_INFO);
795             sprintf(temp, "File: qpathinfo failed for %s GLE(0x%x)\n", path, GetLastError());
796             if (verbose)
797                 printf("%s", temp);
798             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
799             return(-1);
800         }
801     }
802     EndFirstTimer(CMD_QUERY_PATH_INFO, 1);
803     return(0);
804 }
805
806 int nb_qfileinfo(int handle)
807 {
808     int     i;
809     int     rc;
810     char    FileName[128];
811     char    temp[512];
812
813     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
814
815     if ((i = FindHandle(handle)) == -1)
816         return(-1);
817
818     StartFirstTimer();
819     rc = GetFileInfo(ftable[i].name, ftable[i].fd, NULL, NULL, NULL, NULL, NULL, NULL);
820
821     if (!rc)
822     {
823         EndFirstTimer(CMD_QUERY_FILE_INFO, 0);
824         LeaveThread(0, "", CMD_QUERY_FILE_INFO);
825         sprintf(temp, "File: qfileinfo failed for %s GLE(0x%x)\n", ftable[i].name, GetLastError());
826         if (verbose)
827             printf("%s", temp);
828         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
829         return(-1);
830     }
831     EndFirstTimer(CMD_QUERY_FILE_INFO, 1);
832
833     return(0);
834 }
835
836 int nb_qfsinfo(int level)
837 {
838
839 //      int     bsize;
840 //    int     total;
841 //    int     avail;
842     int     rc;
843     char    FileName[128];
844     char    temp[512];
845     char    Path[512];
846     ULARGE_INTEGER FreeBytesAvailable;
847     ULARGE_INTEGER TotalNumberOfBytes;
848     ULARGE_INTEGER TotalNumberOfFreeBytes;
849  
850     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
851     sprintf(Path, "%s\\%s%05d", AfsLocker, HostName, LogID);
852
853     StartFirstTimer();
854     rc = GetDiskFreeSpaceEx(Path, &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes);
855 //    rc = cli_dskattr(c, &bsize, &total, &avail);
856
857     if (!rc)
858     {
859         EndFirstTimer(CMD_QUERY_FS_INFO, 0);
860         LeaveThread(0, "", CMD_QUERY_FS_INFO);
861         sprintf(temp, "File: Disk free space failed GLE(0x%x)\n", GetLastError());
862         if (verbose)
863             printf("%s", temp);
864         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
865         return(-1);
866     }
867     EndFirstTimer(CMD_QUERY_FS_INFO, 1);
868
869     return(0);
870 }
871
872 void find_fn(file_info *finfo, char *name, void *state)
873 {
874         /* noop */
875 }
876
877 int nb_findfirst(char *mask)
878 {
879     int     rc;
880     char    FileName[128];
881     char    NewMask[512];
882     char    temp[512];
883
884     if (strstr(mask, "<.JNK"))
885         return(0);
886
887     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
888
889     strcpy(NewMask, AfsLocker);
890     strcat(NewMask, mask);
891
892     StartFirstTimer();
893     rc = GetFileList(NewMask, (void *)find_fn, NULL);
894
895     if (!rc)
896     {
897         EndFirstTimer(CMD_FIND_FIRST, 0);
898         sprintf(temp, "File: findfirst cannot find for %s\n", mask);
899         if (verbose)
900             printf("%s", temp);
901         LeaveThread(1, temp, CMD_FIND_FIRST);
902         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
903         return(-1);
904     }
905     EndFirstTimer(CMD_FIND_FIRST, 1);
906     return(0);
907 }
908
909 int nb_flush(int handle)
910 {
911     int i;
912
913     if ((i = FindHandle(handle)) == -1)
914         return(-1);
915
916     FlushFileBuffers(ftable[i].fd);
917     return(0);
918 }
919
920 static int total_deleted;
921
922 void delete_fn(file_info *finfo, const char *name, void *state)
923 {
924     int     rc;
925     char    temp[256];
926     char    s[1024];
927     char    FileName[128];
928
929     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
930
931     if (finfo->mode & aDIR) 
932     {
933         char s2[1024];
934         sprintf(s2, "%s\\*", name);
935         GetFileList(s2, delete_fn, NULL);
936         sprintf(s, "%s", &name[strlen(AfsLocker)]);
937         nb_rmdir(s);
938     }
939     else
940     {
941         rc = DeleteFile(name);
942         if (!rc)
943         {
944             LeaveThread(0, "", CMD_UNLINK);
945             sprintf(temp, "FILE: DeleteFile %s failed GLE(0x%x)\n", name, GetLastError());
946             if (verbose)
947                 printf("%s", temp);
948             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
949             return;
950         }
951     }
952     return;
953 }
954
955 int nb_deltree(char *dname)
956 {
957     int     rc;
958     char    mask[1024];
959     pstring path;
960
961
962     strcpy(path, AfsLocker);
963     strcat(path, dname);
964     sprintf(mask, "%s\\*", path);
965
966     total_deleted = 0;
967
968     StartFirstTimer();
969     GetFileList(mask, delete_fn, NULL);
970
971 //    pstrcpy(path, AfsLocker);
972 //    pstrcat(path, dname);
973     rc = RemoveDirectory(path);
974     EndFirstTimer(CMD_DELTREE, rc);
975     if (!rc)
976     {
977         char FileName[256];
978         char temp[128];
979         int  rc;
980
981         rc = GetLastError();
982         if ((rc != ERROR_FILE_NOT_FOUND) && (rc != ERROR_PATH_NOT_FOUND))
983         {
984             SetLastError(rc);
985             LeaveThread(0, "", CMD_DELTREE);
986             sprintf(FileName, "Thread_%05d.log", ProcessNumber);
987             sprintf(temp, "ERROR: Thread %d - Unable to remove %s.\n", ProcessNumber, path);
988             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
989             if (verbose)
990                 printf(temp);
991             return(-1);
992         }
993     }
994     return(0);
995 }
996
997
998 int nb_cleanup(char *cname)
999 {
1000     char temp[256];
1001
1002     strcpy(temp, "\\clients\\client1");
1003     SubstituteString(temp, "client1", cname, sizeof(temp));
1004     SubstituteString(temp, "clients", HostName, sizeof(temp));
1005     nb_deltree(temp);
1006     return(0);
1007 }
1008
1009 int LeaveThread(int status, char *Reason, int cmd)
1010 {
1011     char    FileName[256];
1012     char    temp[512];
1013     DWORD   rc;
1014
1015     if (cmd != -1)
1016         ++ThreadCommandInfo[cmd].ErrorCount;
1017
1018     if (strlen(Reason) == 0)
1019     {
1020         if (status == 0)
1021             rc = GetLastError();
1022         else
1023             rc = status;
1024         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1025                       NULL,
1026                       rc,
1027                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1028                       pExitStatus->Reason,
1029                       sizeof(pExitStatus->Reason),
1030                       NULL);
1031         LastKnownError = rc;
1032     }
1033     else
1034         strcpy(pExitStatus->Reason, Reason);
1035
1036     if (strlen(pExitStatus->Reason) == 0)
1037         strcpy(pExitStatus->Reason, "\n");
1038     if (pExitStatus->Reason[strlen(pExitStatus->Reason) - 1] != '\n')
1039         strcat(pExitStatus->Reason, "\n");
1040     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
1041     if (strlen(Reason) == 0)
1042         sprintf(temp, "ERROR(%d): Thread %d - (%d) %s", LineCount, ProcessNumber, rc, pExitStatus->Reason);
1043     else
1044         sprintf(temp, "ERROR(%d): Thread %d - %s", LineCount, ProcessNumber, pExitStatus->Reason);
1045     LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
1046     if (verbose)
1047         printf("%s", temp);
1048     pExitStatus->ExitStatus = status;
1049     if (AfsTrace)
1050         DumpAFSLog(HostName, LogID);
1051     (*pThreadStatus) = 0;
1052     return(-1);
1053 }
1054
1055 void StartFirstTimer(void)
1056 {
1057
1058     EndSecondTime(CMD_NONAFS);
1059     TickCount1 = GetTickCount();
1060 }
1061
1062 void EndFirstTimer(int cmd, int Type)
1063 {
1064     DWORD   MilliTick;
1065     DWORD   cmd_time;
1066
1067     ThreadCommandInfo[cmd].count++;
1068     cmd_time = 0;
1069     MilliTick = GetTickCount() - TickCount1;
1070     if (MilliTick <= 0)
1071     {
1072         StartSecondTime(CMD_NONAFS);
1073         return;
1074     }
1075
1076     ThreadCommandInfo[cmd].MilliSeconds += MilliTick;
1077     while (ThreadCommandInfo[cmd].MilliSeconds > 1000)
1078     {
1079         ThreadCommandInfo[cmd].MilliSeconds -= 1000;
1080         cmd_time += 1;
1081     }
1082
1083     if (cmd_time == 0)
1084     {
1085         ThreadCommandInfo[cmd].min_sec = cmd_time;
1086         StartSecondTime(CMD_NONAFS);
1087         return;
1088     }
1089
1090     if (!Type)
1091         ThreadCommandInfo[cmd].ErrorTime += cmd_time;
1092     else
1093     {
1094         ThreadCommandInfo[cmd].total_sec += cmd_time;
1095         if (cmd_time < (int)ThreadCommandInfo[cmd].min_sec)
1096             ThreadCommandInfo[cmd].min_sec = cmd_time;
1097         if ((int)ThreadCommandInfo[cmd].max_sec < cmd_time)
1098             ThreadCommandInfo[cmd].max_sec = cmd_time;
1099     }
1100
1101     StartSecondTime(CMD_NONAFS);
1102 }
1103
1104 void StartSecondTime(int cmd)
1105 {
1106
1107     TickCount2 = GetTickCount();
1108
1109 }
1110
1111 void EndSecondTime(int cmd)
1112 {
1113     DWORD   MilliTick;
1114     DWORD   cmd_time;
1115
1116     ThreadCommandInfo[cmd].count++;
1117     cmd_time = 0;
1118     MilliTick = GetTickCount() - TickCount2;
1119
1120     if (MilliTick <= 0)
1121         return;
1122
1123     ThreadCommandInfo[cmd].MilliSeconds += MilliTick;
1124     while (ThreadCommandInfo[cmd].MilliSeconds > 1000)
1125     {
1126         ThreadCommandInfo[cmd].MilliSeconds -= 1000;
1127         cmd_time += 1;
1128     }
1129     if (cmd_time == 0)
1130     {
1131         ThreadCommandInfo[cmd].min_sec = cmd_time;
1132         return;
1133     }
1134     if (cmd_time < (int)ThreadCommandInfo[cmd].min_sec)
1135         ThreadCommandInfo[cmd].min_sec = cmd_time;
1136     if ((int)ThreadCommandInfo[cmd].max_sec < cmd_time)
1137         ThreadCommandInfo[cmd].max_sec = cmd_time;
1138     ThreadCommandInfo[cmd].total_sec += cmd_time;
1139 }
1140
1141
1142 intptr_t SystemCall(char *command)
1143 {
1144     intptr_t rc;
1145     char    *argv[6];
1146
1147     argv[0] = getenv("COMSPEC");
1148     argv[1] = "/q";
1149     argv[2] = "/c";
1150     argv[3] = (char *)command;
1151     argv[4] = NULL;
1152
1153     rc = spawnve(_P_WAIT,argv[0],argv,NULL);
1154 // != -1 || (errno != ENOENT && errno != EACCES))
1155     return(rc);
1156 }
1157
1158 HANDLE CreateObject(const char *fname, uint32 DesiredAccess,
1159                  uint32 FileAttributes, uint32 ShareAccess,
1160                  uint32 CreateDisposition, uint32 CreateOptions)
1161 {
1162     HANDLE   fd;
1163     DWORD dwCreateDisposition = 0;
1164     DWORD dwDesiredAccess = 0;
1165     DWORD dwShareAccess = 0;
1166     DWORD dwFlags = 0;
1167
1168     if (CreateOptions & FILE_DIRECTORY_FILE)
1169     {
1170         DWORD rc;
1171
1172         if (!CreateDirectory(fname, NULL) && (rc = GetLastError()) != ERROR_ALREADY_EXISTS) 
1173         {
1174             SetLastError(rc);
1175             fd = INVALID_HANDLE_VALUE;
1176         }
1177         else
1178         {
1179             fd = CreateFile(fname, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1180         }
1181     }
1182     else
1183     {
1184         dwDesiredAccess = 0;
1185         if (DesiredAccess & FILE_READ_DATA)
1186             dwDesiredAccess |= GENERIC_READ;
1187         if (DesiredAccess & FILE_WRITE_DATA)
1188             dwDesiredAccess |= GENERIC_WRITE;
1189         dwShareAccess = ShareAccess;
1190         dwShareAccess |= FILE_SHARE_DELETE;
1191         dwCreateDisposition = OPEN_ALWAYS;
1192         if (CreateDisposition == 1)
1193             dwCreateDisposition = OPEN_EXISTING;
1194         fd = CreateFile(fname, dwDesiredAccess, ShareAccess, NULL, dwCreateDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
1195     }
1196
1197     return(fd);
1198 }
1199
1200 BOOL nb_close1(HANDLE fd)
1201 {
1202     int dwFlags = 0;
1203     int rc = 1;
1204
1205     if (fd != INVALID_HANDLE_VALUE)
1206     {
1207         if (rc = GetHandleInformation(fd, &dwFlags))
1208             CloseHandle(fd);
1209     }
1210     return(rc);
1211 }
1212
1213 /****************************************************************************
1214   do a directory listing, calling fn on each file found
1215   this uses the old SMBsearch interface. It is needed for testing Samba,
1216   but should otherwise not be used
1217   ****************************************************************************/
1218 int nb_list_old(const char *Mask, void (*fn)(file_info *, const char *, void *), void *state)
1219 {
1220     int     num_received = 0;
1221     pstring mask;
1222     char    temp[512];
1223     char    cFileName[1024];
1224     int     dwFileAttributes;
1225     HANDLE  hFind;
1226     void    *FileData;
1227
1228     strcpy(mask,Mask);
1229
1230
1231     if (!strcmp(&mask[strlen(mask)-2], "\"*"))
1232     {
1233         strcpy(&mask[strlen(mask)-2], "*");
1234     }
1235     FileData = NULL;
1236     dwFileAttributes = 0;
1237     memset(cFileName, '\0', sizeof(cFileName));
1238     hFind = WinFindFirstFile(mask, &FileData, cFileName, &dwFileAttributes);
1239     if (hFind == INVALID_HANDLE_VALUE)
1240     {
1241         return(0);
1242     }
1243     mask[strlen(mask) - 1] = '\0';
1244     while (1)
1245     {
1246         if (cFileName[0] != '.')
1247         {
1248             file_info finfo;
1249
1250             memset(&finfo, '\0', sizeof(finfo));
1251             if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1252                 finfo.mode = aDIR;
1253             strcpy(finfo.name, cFileName);
1254             sprintf(temp, "%s%s", mask, cFileName);
1255                 fn(&finfo, temp, state);
1256             ++num_received;
1257         }
1258         memset(cFileName, '\0', sizeof(cFileName));
1259         dwFileAttributes = 0;
1260         if (!WinFindNextFile(hFind, &FileData, cFileName, &dwFileAttributes))
1261             break;
1262     }
1263     FindClose(hFind);
1264     return(num_received);
1265 }
1266
1267
1268 /****************************************************************************
1269   do a directory listing, calling fn on each file found
1270   this auto-switches between old and new style
1271   ****************************************************************************/
1272 int GetFileList(char *Mask, void (*fn)(file_info *, const char *, void *), void *state)
1273 {
1274     return(nb_list_old(Mask, fn, state));
1275 }
1276
1277 HANDLE WinFindFirstFile(char *Mask, void **FileData, char *cFileName, int *dwFileAttributes)
1278 {
1279     HANDLE  rc;
1280     static WIN32_FIND_DATAW FileDataW;
1281     static WIN32_FIND_DATAA FileDataA;
1282
1283     memset(&FileDataA, '\0', sizeof(FileDataA));
1284     rc = FindFirstFile(Mask, &FileDataA);
1285     if (rc != INVALID_HANDLE_VALUE)
1286     {
1287         (*FileData) = (void *)&FileDataA;
1288         (*dwFileAttributes) = FileDataA.dwFileAttributes;
1289         strcpy(cFileName, FileDataA.cFileName);
1290     }
1291
1292     return(rc);
1293 }
1294
1295 int WinFindNextFile(HANDLE hFind, void **FileData, char *cFileName, int *dwFileAttributes)
1296 {
1297     int     rc;
1298     WIN32_FIND_DATAA *FileDataA;
1299
1300     FileDataA = (WIN32_FIND_DATAA *)(*FileData);
1301     if (!(rc = FindNextFile(hFind, FileDataA)))
1302     {
1303         return(rc);
1304     }
1305     (*dwFileAttributes) = FileDataA->dwFileAttributes;
1306     strcpy(cFileName, FileDataA->cFileName);
1307
1308     return(rc);
1309 }
1310
1311 void SubstituteString(char *s,const char *pattern,const char *insert, size_t len)
1312 {
1313     char *p;
1314     ssize_t ls,lp,li;
1315
1316     if (!insert || !pattern || !s) return;
1317
1318     ls = (ssize_t)strlen(s);
1319     lp = (ssize_t)strlen(pattern);
1320     li = (ssize_t)strlen(insert);
1321
1322     if (!*pattern) return;
1323         
1324     while (lp <= ls && (p = strstr(s,pattern)))
1325     {
1326         if (len && (ls + (li-lp) >= (int)len)) 
1327         {
1328             break;
1329         }
1330         if (li != lp) 
1331         {
1332             memmove(p+li,p+lp,strlen(p+lp)+1);
1333         }
1334         memcpy(p, insert, li);
1335         s = p + li;
1336         ls += (li-lp);
1337     }
1338 }
1339
1340 #define CHANGE_TIME(A,B) \
1341 B.tm_hour = A.wHour; \
1342 B.tm_sec = A.wSecond; \
1343 B.tm_min = A.wMinute; \
1344 B.tm_mon = A.wMonth - 1; \
1345 B.tm_yday = 0; \
1346 B.tm_year = A.wYear - 1900; \
1347 B.tm_wday = A.wDayOfWeek - 1; \
1348 B.tm_isdst = -1; \
1349 B.tm_mday = A.wDay;
1350
1351
1352 BOOL GetPathInfo(const char *fname, 
1353                    time_t *c_time, time_t *a_time, time_t *m_time, 
1354                    size_t *size, uint16 *mode)
1355 {
1356     WIN32_FILE_ATTRIBUTE_DATA FileInfo;
1357     int         rc;
1358     SYSTEMTIME  SystemTime;
1359     struct tm   tm_time;
1360
1361     rc = GetFileAttributesEx(fname, GetFileExInfoStandard, &FileInfo);
1362     if (rc != 0)
1363     {
1364         if (c_time)
1365         {
1366             rc = FileTimeToSystemTime(&FileInfo.ftCreationTime, &SystemTime);
1367             CHANGE_TIME(SystemTime, tm_time)
1368             (*c_time) = mktime(&tm_time);
1369         }
1370         if (a_time)
1371         {
1372             rc = FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SystemTime);
1373             CHANGE_TIME(SystemTime, tm_time)
1374             (*a_time) = mktime(&tm_time);
1375         }
1376         if (m_time)
1377         {
1378             rc = FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SystemTime);
1379             CHANGE_TIME(SystemTime, tm_time)
1380             (*m_time) = mktime(&tm_time);
1381         }
1382         if (size) 
1383         {
1384             rc = 1;
1385             if (!(FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
1386                 *size = FileInfo.nFileSizeLow;
1387         }
1388         if (mode)
1389         {
1390             rc = 1;
1391             (*mode) = 0;
1392         }
1393     }
1394     return(rc);
1395 }
1396
1397 /****************************************************************************
1398 send a qfileinfo call
1399 ****************************************************************************/
1400 BOOL GetFileInfo(char *FileName, HANDLE fd, 
1401                    uint16 *mode, size_t *size,
1402                    time_t *c_time, time_t *a_time, time_t *m_time, 
1403                    time_t *w_time)
1404 {
1405     WIN32_FILE_ATTRIBUTE_DATA FileInfo;
1406     int         rc;
1407     SYSTEMTIME  SystemTime;
1408     struct tm   tm_time;
1409
1410     rc = GetFileAttributesEx(FileName, GetFileExInfoStandard, &FileInfo);
1411     if (rc != 0)
1412     {
1413         if (c_time)
1414         {
1415             rc = FileTimeToSystemTime(&FileInfo.ftCreationTime, &SystemTime);
1416             CHANGE_TIME(SystemTime, tm_time)
1417             (*c_time) = mktime(&tm_time);
1418         }
1419         if (a_time)
1420         {
1421             rc = FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SystemTime);
1422             CHANGE_TIME(SystemTime, tm_time)
1423             (*a_time) = mktime(&tm_time);
1424         }
1425         if (m_time)
1426         {
1427             rc = FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SystemTime);
1428             CHANGE_TIME(SystemTime, tm_time)
1429             (*m_time) = mktime(&tm_time);
1430         }
1431         if (size) 
1432         {
1433             rc = 0;
1434             if (!(FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
1435                *size = FileInfo.nFileSizeLow;
1436             }
1437             if (mode)
1438         {
1439             rc = 0;
1440             (*mode) = 0;
1441         }
1442     }
1443     return(rc);
1444 }
1445
1446 /****************************************************************************
1447   Read size bytes at offset offset using SMBreadX.
1448 ****************************************************************************/
1449
1450 ssize_t nb_read(HANDLE fd, char *IoBuffer, off_t offset, size_t size)
1451 {
1452     DWORD   total = 0;
1453     int     rc;
1454     DWORD   LowDword;
1455
1456     if (size == 0) 
1457         return(0);
1458
1459     LowDword = SetFilePointer(fd, offset, 0, FILE_BEGIN);
1460
1461     if (LowDword == INVALID_SET_FILE_POINTER)
1462         return(-1);
1463     rc = ReadFile(fd, IoBuffer, (DWORD)size, &total, NULL);
1464     if (!rc)
1465         return(rc);
1466
1467     return(total);
1468 }
1469
1470 /****************************************************************************
1471   write to a file
1472 ****************************************************************************/
1473
1474 ssize_t nb_write(HANDLE fd, char *IoBuffer, off_t offset, size_t size)
1475 {
1476     DWORD   bwritten = 0;
1477     int     rc;
1478     DWORD   LowDword;
1479
1480     LowDword = SetFilePointer(fd, offset, 0, FILE_BEGIN);
1481     if (LowDword == INVALID_SET_FILE_POINTER)
1482         return(-1);
1483     rc = WriteFile(fd, IoBuffer, (DWORD)size, &bwritten, NULL);
1484     if (!rc)
1485         return(rc);
1486     FlushFileBuffers(fd);
1487     return(bwritten);
1488 }
1489