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