venus: Remove dedebug
[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(gle, "", 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(gle, 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     DWORD gle;
496
497     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
498
499     strcpy(path, AfsLocker);
500     strcat(path, fname);
501     if (create_options & FILE_DIRECTORY_FILE)
502     {
503         desired_access = FILE_READ_DATA;
504     }
505     else
506     {
507         desired_access = FILE_READ_DATA | FILE_WRITE_DATA;
508     }
509
510     StartFirstTimer();
511     fd = CreateObject(path,
512                        desired_access,
513                        0x0,
514                        FILE_SHARE_READ|FILE_SHARE_WRITE,
515                        create_disposition,
516                        create_options);
517
518     if (fd == INVALID_HANDLE_VALUE && handle != -1)
519     {
520         gle = GetLastError();
521         if (create_options & FILE_DIRECTORY_FILE)
522         {
523             EndFirstTimer(CMD_NTCREATEX, 0);
524             LeaveThread(gle, "", CMD_NTCREATEX);
525             sprintf(temp, "Directory: unable to create directory %s\n", path);
526             if (verbose)
527                 printf("%s", temp);
528             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
529             return(-1);
530         }
531         else
532         {
533             EndFirstTimer(CMD_NTCREATEX, 0);
534             LeaveThread(gle, "", CMD_NTCREATEX);
535             sprintf(temp, "File: unable to create file %s\n", path);
536             if (verbose)
537                 printf("%s", temp);
538             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
539             return(-1);
540         }
541     }
542
543     EndFirstTimer(CMD_NTCREATEX, 1);
544
545     if (fd != INVALID_HANDLE_VALUE && handle == -1)
546     {
547         CloseHandle(fd);
548         nb_unlink(fname);
549         return(0);
550     }
551
552     if (fd == INVALID_HANDLE_VALUE && handle == -1)
553         return(0);
554
555     for (i = 0; i < MAX_FILES; i++)
556     {
557         if (ftable[i].handle == 0)
558             break;
559     }
560     if (i == MAX_FILES)
561     {
562         printf("(%d) file table full for %s\n", LineCount, path);
563         return(LeaveThread(1, "file table is full\n", CMD_NTCREATEX));
564     }
565     ftable[i].handle = handle;
566     ftable[i].fd = fd;
567     if (ftable[i].name)
568         free(ftable[i].name);
569     ftable[i].name = strdup(path);
570     ftable[i].reads = ftable[i].writes = 0;
571     return(0);
572 }
573
574 int nb_writex(int handle, int offset, int size, int ret_size)
575 {
576     int     i;
577     ssize_t status;
578     char    FileName[128];
579     char    temp[512];
580     unsigned char magic = (unsigned char)getpid();
581     DWORD gle;
582
583     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
584
585     if (IoBuffer[0] != magic ||
586         IoBuffer[1] != magic ||
587         IoBuffer[2] != magic ||
588         IoBuffer[3] != magic)
589         memset(IoBuffer, magic, BufferSize);
590
591     if ((i = FindHandle(handle)) == -1)
592         return(-1);
593     StartFirstTimer();
594     status = nb_write(ftable[i].fd, IoBuffer, offset, size);
595     if (status != ret_size)
596     {
597         gle = GetLastError();
598         EndFirstTimer(CMD_WRITEX, 0);
599         LeaveThread(gle, "", CMD_WRITEX);
600         if (status == 0)
601             sprintf(temp, "File: %s. wrote %d bytes, got %d bytes\n", ftable[i].name, size, status);
602         if (status == -1)
603             sprintf(temp, "File: %s. On write, cannot set file pointer\n", ftable[i].name);
604         if (verbose)
605             printf("%s", temp);
606         nb_close(handle);
607         if (verbose)
608             printf("%s", temp);
609         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
610         return(-1);
611         }
612     EndFirstTimer(CMD_WRITEX, 1);
613
614     ftable[i].writes++;
615     return(0);
616 }
617
618 int nb_lock(int handle, int offset, int size, int timeout, unsigned char locktype, NTSTATUS exp)
619 {
620 /*
621     int         i;
622     NTSTATUS    ret;
623     char        FileName[128];
624     char        temp[512];
625
626     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
627
628     if ((i = FindHandle(handle)) == -1)
629     {
630         LeaveThread(0, "", CMD_LOCKINGX);
631         sprintf(temp, "File unlock: Cannot find handle for %s", ftable[i].name);
632         if (verbose)
633             printf("%s", temp);
634         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
635         return(-1);
636     }
637
638     StartFirstTimer();
639     ret = cli_locktype(c, i, offset, size, timeout, locktype);
640
641     if (ret != exp)
642     {
643         EndFirstTimer(CMD_LOCKINGX, 0);
644         LeaveThread(0, "", CMD_LOCKINGX);
645         sprintf(temp, "(%d) ERROR: lock failed on handle %d ofs=%d size=%d timeout= %d exp=%d fd %d errno %d (%s)\n",
646                LineCount, handle, offset, size, timeout, exp, ftable[i].fd, exp, "");
647         sprintf(temp, "File unlock: lock failed %s", ftable[i].name);
648         if (verbose)
649             printf("%s", temp);
650         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
651         return(-1);
652     }
653     EndFirstTimer(CMD_LOCKINGX, 1);
654 */
655     return(0);
656 }
657
658 int nb_readx(int handle, int offset, int size, int ret_size)
659 {
660     int     i;
661     ssize_t ret;
662     char    FileName[128];
663     char    temp[512];
664     DWORD   gle;
665
666     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
667
668     if ((i = FindHandle(handle)) == -1)
669         return(-1);
670
671     StartFirstTimer();
672     ret = nb_read(ftable[i].fd, IoBuffer, offset, size);
673     gle = GetLastError();
674     if ((ret != size) && (ret != ret_size))
675     {
676         EndFirstTimer(CMD_READX, 0);
677         LeaveThread(gle, "", CMD_READX);
678         if (ret == 0)
679             sprintf(temp, "File: read failed on index=%d, offset=%d ReadSize=%d ActualRead=%d handle=%p GLE(0x%x)\n",
680                     handle, offset, size, ret, ftable[i].fd, gle);
681         if (ret == -1)
682             sprintf(temp, "File: %s. On read, cannot set file pointer GLE(0x%x)\n", ftable[i].name, gle);
683         if (verbose)
684             printf("%s", temp);
685         nb_close(handle);
686         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
687         return(-1);
688     }
689     EndFirstTimer(CMD_READX, 1);
690     ftable[i].reads++;
691     return(0);
692 }
693
694 int nb_close(int handle)
695 {
696     int     i;
697     int     ret;
698     char    FileName[128];
699     char    temp[512];
700     DWORD   gle;
701
702     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
703
704     if ((i = FindHandle(handle)) == -1)
705         return(0);
706
707     StartFirstTimer();
708     ret = nb_close1(ftable[i].fd);
709     gle = GetLastError();
710     EndFirstTimer(CMD_CLOSE, ret);
711     if (!ret)
712     {
713         LeaveThread(gle, "", CMD_CLOSE);
714         sprintf(temp, "(%d) close failed on handle %d\n", LineCount, handle);
715         if (verbose)
716             printf("%s", temp);
717         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
718         return(-1);
719     }
720
721     ftable[i].handle = 0;
722     ftable[i].fd = 0;
723     if (ftable[i].name)
724         free(ftable[i].name);
725     ftable[i].name = NULL;
726     return(0);
727 }
728
729 int nb_rmdir(char *fname)
730 {
731     int     rc;
732     pstring path;
733     char    FileName[128];
734     char    temp[512];
735     DWORD   gle;
736
737     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
738
739     strcpy(path, AfsLocker);
740     strcat(path, fname);
741
742     StartFirstTimer();
743     rc = RemoveDirectory(path);
744     gle = GetLastError();
745     EndFirstTimer(CMD_RMDIR, rc);
746
747     if (!rc)
748     {
749         LeaveThread(gle, "", CMD_RMDIR);
750         sprintf(temp, "Directory: RemoveDirectory %s failed GLE(0x%x)\n", fname, gle);
751         if (verbose)
752             printf("%s", temp);
753         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
754         return(-1);
755     }
756     return(0);
757 }
758
759 int nb_rename(char *old, char *New)
760 {
761     int     rc;
762     pstring opath;
763     pstring npath;
764     char    FileName[128];
765     char    temp[512];
766     DWORD   gle;
767
768     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
769
770     strcpy(opath, AfsLocker);
771     strcat(opath, old);
772     strcpy(npath, AfsLocker);
773     strcat(npath, New);
774
775     StartFirstTimer();
776     rc = MoveFileEx(opath, npath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
777     gle = GetLastError();
778     EndFirstTimer(CMD_RENAME, rc);
779
780     if (!rc)
781     {
782         LeaveThread(gle, "", CMD_RENAME);
783         sprintf(temp, "File: rename %s %s failed GLE(0x%x)\n", old, New, gle);
784         if (verbose)
785             printf("%s", temp);
786         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
787         return(-1);
788     }
789     return(0);
790 }
791
792 /*
793  * Type is used to determine whether the file is expected
794  * to exist or not.  It is overloaded (temporarily) to control
795  * Flag which indicates whether an error is treated as an error
796  * or not.  The StreamFiles.txt script does not have the Type
797  * parameter set correctly for all 120,000+ lines.  As a result
798  * it is not possible to enforce the presence test throughout
799  * the entire script.
800  */
801 int nb_qpathinfo(char *fname, int Type)
802 {
803     pstring path;
804     int     rc;
805     char    FileName[128];
806     char    temp[512];
807     DWORD   gle = 0;
808
809     if (Type == 1111) {
810         EnforcePathInfoErrors = 1;
811         Type = 1;
812     } else if (Type == 1001) {
813         EnforcePathInfoErrors = 0;
814         Type = 1;
815     } else if (Type == 1000) {
816         EnforcePathInfoErrors = 0;
817         Type = 0;
818     } else if (Type == 1110) {
819         EnforcePathInfoErrors = 1;
820         Type = 0;
821     }
822
823     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
824
825     strcpy(path, AfsLocker);
826     strcat(path, fname);
827
828     StartFirstTimer();
829     rc = GetPathInfo(path, NULL, NULL, NULL, NULL, NULL);
830     if (rc == 0)
831         gle = GetLastError();
832     if (strstr(fname, "~TS"))
833     {
834         if (rc == 0)
835             rc = 1;
836         else
837             rc = 0;
838     }
839
840     if (!EnforcePathInfoErrors)
841     {
842         if (Type)
843         {
844             if (rc)
845                 rc = 0;
846             else
847                 rc = 1;
848         }
849         if (!rc)
850         {
851             EndFirstTimer(CMD_QUERY_PATH_INFO, 0);
852             LeaveThread(gle, "", CMD_QUERY_PATH_INFO);
853             sprintf(temp, "File: qpathinfo failed for %s type %d GLE(0x%x)\n", path, Type, gle);
854             if (verbose)
855                 printf("%s", temp);
856             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
857             return(-1);
858         }
859     }
860     EndFirstTimer(CMD_QUERY_PATH_INFO, 1);
861     return(0);
862 }
863
864 int nb_qfileinfo(int handle)
865 {
866     int     i;
867     int     rc;
868     char    FileName[128];
869     char    temp[512];
870     DWORD   gle;
871
872     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
873
874     if ((i = FindHandle(handle)) == -1)
875         return(-1);
876
877     StartFirstTimer();
878     rc = GetFileInfo(ftable[i].name, ftable[i].fd, NULL, NULL, NULL, NULL, NULL, NULL);
879     gle = GetLastError();
880     if (!rc)
881     {
882         EndFirstTimer(CMD_QUERY_FILE_INFO, 0);
883         LeaveThread(gle, "", CMD_QUERY_FILE_INFO);
884         sprintf(temp, "File: qfileinfo failed for %s GLE(0x%x)\n", ftable[i].name, gle);
885         if (verbose)
886             printf("%s", temp);
887         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
888         return(-1);
889     }
890     EndFirstTimer(CMD_QUERY_FILE_INFO, 1);
891
892     return(0);
893 }
894
895 int nb_qfsinfo(int level)
896 {
897
898 //      int     bsize;
899 //    int     total;
900 //    int     avail;
901     int     rc;
902     char    FileName[128];
903     char    temp[512];
904     char    Path[512];
905     ULARGE_INTEGER FreeBytesAvailable;
906     ULARGE_INTEGER TotalNumberOfBytes;
907     ULARGE_INTEGER TotalNumberOfFreeBytes;
908     DWORD   gle;
909
910     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
911     sprintf(Path, "%s\\%s%05d", AfsLocker, HostName, LogID);
912
913     StartFirstTimer();
914     rc = GetDiskFreeSpaceEx(Path, &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes);
915 //    rc = cli_dskattr(c, &bsize, &total, &avail);
916     gle = GetLastError();
917
918     if (!rc)
919     {
920         EndFirstTimer(CMD_QUERY_FS_INFO, 0);
921         LeaveThread(gle, "", CMD_QUERY_FS_INFO);
922         sprintf(temp, "File: Disk free space failed GLE(0x%x)\n", gle);
923         if (verbose)
924             printf("%s", temp);
925         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
926         return(-1);
927     }
928     EndFirstTimer(CMD_QUERY_FS_INFO, 1);
929
930     return(0);
931 }
932
933 void find_fn(file_info *finfo, char *name, void *state)
934 {
935         /* noop */
936 }
937
938 int nb_findfirst(char *mask)
939 {
940     int     rc;
941     char    FileName[128];
942     char    NewMask[512];
943     char    temp[512];
944
945     if (strstr(mask, "<.JNK"))
946         return(0);
947
948     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
949
950     strcpy(NewMask, AfsLocker);
951     strcat(NewMask, mask);
952
953     StartFirstTimer();
954     rc = GetFileList(NewMask, (void *)find_fn, NULL);
955
956     if (!rc)
957     {
958         EndFirstTimer(CMD_FIND_FIRST, 0);
959         sprintf(temp, "File: findfirst cannot find for %s\n", mask);
960         if (verbose)
961             printf("%s", temp);
962         LeaveThread(1, temp, CMD_FIND_FIRST);
963         LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
964         return(-1);
965     }
966     EndFirstTimer(CMD_FIND_FIRST, 1);
967     return(0);
968 }
969
970 int nb_flush(int handle)
971 {
972     int i;
973
974     if ((i = FindHandle(handle)) == -1)
975         return(-1);
976
977     FlushFileBuffers(ftable[i].fd);
978     return(0);
979 }
980
981 static int total_deleted;
982
983 void delete_fn(file_info *finfo, const char *name, void *state)
984 {
985     int     rc;
986     char    temp[512];
987     char    s[1024];
988     char    FileName[128];
989     DWORD   gle;
990
991     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
992
993     if (finfo->mode & aDIR)
994     {
995         char s2[1024];
996         sprintf(s2, "%s\\*", name);
997         GetFileList(s2, delete_fn, NULL);
998         sprintf(s, "%s", &name[strlen(AfsLocker)]);
999         nb_rmdir(s);
1000     }
1001     else
1002     {
1003         rc = DeleteFile(name);
1004         gle = GetLastError();
1005         if (!rc)
1006         {
1007             LeaveThread(gle, "", CMD_UNLINK);
1008             sprintf(temp, "FILE: DeleteFile %s failed GLE(0x%x)\n", name, gle);
1009             if (verbose)
1010                 printf("%s", temp);
1011             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
1012             return;
1013         }
1014     }
1015     return;
1016 }
1017
1018 int nb_deltree(char *dname)
1019 {
1020     int     rc;
1021     char    mask[1024];
1022     pstring path;
1023     DWORD   gle;
1024
1025     strcpy(path, AfsLocker);
1026     strcat(path, dname);
1027     sprintf(mask, "%s\\*", path);
1028
1029     total_deleted = 0;
1030
1031     StartFirstTimer();
1032     GetFileList(mask, delete_fn, NULL);
1033
1034 //    pstrcpy(path, AfsLocker);
1035 //    pstrcat(path, dname);
1036     rc = RemoveDirectory(path);
1037     gle = GetLastError();
1038     EndFirstTimer(CMD_DELTREE, rc);
1039     if (!rc)
1040     {
1041         char FileName[256];
1042         char temp[512];
1043
1044         if ((gle != ERROR_FILE_NOT_FOUND) && (gle != ERROR_PATH_NOT_FOUND))
1045         {
1046             LeaveThread(gle, "", CMD_DELTREE);
1047             sprintf(FileName, "Thread_%05d.log", ProcessNumber);
1048             sprintf(temp, "ERROR: Thread %d - Unable to remove %s.\n", ProcessNumber, path);
1049             LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
1050             SetLastError(gle);
1051             if (verbose)
1052                 printf(temp);
1053             return(-1);
1054         }
1055     }
1056     return(0);
1057 }
1058
1059
1060 int nb_cleanup(char *cname)
1061 {
1062     char temp[256];
1063
1064     strcpy(temp, "\\clients\\client1");
1065     SubstituteString(temp, "client1", cname, sizeof(temp));
1066     SubstituteString(temp, "clients", HostName, sizeof(temp));
1067     nb_deltree(temp);
1068     return(0);
1069 }
1070
1071 int LeaveThread(int status, char *Reason, int cmd)
1072 {
1073     char    FileName[256];
1074     char    temp[512];
1075     DWORD   rc;
1076
1077     if (cmd != -1)
1078         ++ThreadCommandInfo[cmd].ErrorCount;
1079
1080     if (strlen(Reason) == 0)
1081     {
1082         if (status == 0)
1083             rc = GetLastError();
1084         else
1085             rc = status;
1086         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1087                       NULL,
1088                       rc,
1089                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1090                       pExitStatus->Reason,
1091                       sizeof(pExitStatus->Reason),
1092                       NULL);
1093         LastKnownError = rc;
1094     }
1095     else
1096         strcpy(pExitStatus->Reason, Reason);
1097
1098     if (strlen(pExitStatus->Reason) == 0)
1099         strcpy(pExitStatus->Reason, "\n");
1100     if (pExitStatus->Reason[strlen(pExitStatus->Reason) - 1] != '\n')
1101         strcat(pExitStatus->Reason, "\n");
1102     sprintf(FileName, "Thread_%05d.log", ProcessNumber);
1103     if (strlen(Reason) == 0)
1104         sprintf(temp, "ERROR(%d): Thread %d - (%d) %s", LineCount, ProcessNumber, rc, pExitStatus->Reason);
1105     else
1106         sprintf(temp, "ERROR(%d): Thread %d - %s", LineCount, ProcessNumber, pExitStatus->Reason);
1107     LogMessage(ProcessNumber, HostName, FileName, temp, LogID);
1108     if (verbose)
1109         printf("%s", temp);
1110     pExitStatus->ExitStatus = status;
1111     if (AfsTrace)
1112         DumpAFSLog(HostName, LogID);
1113     (*pThreadStatus) = 0;
1114     return(-1);
1115 }
1116
1117 void StartFirstTimer(void)
1118 {
1119
1120     EndSecondTime(CMD_NONAFS);
1121     TickCount1 = GetTickCount();
1122 }
1123
1124 void EndFirstTimer(int cmd, int Type)
1125 {
1126     DWORD   MilliTick;
1127     DWORD   cmd_time;
1128
1129     ThreadCommandInfo[cmd].count++;
1130     cmd_time = 0;
1131     MilliTick = GetTickCount() - TickCount1;
1132     if (MilliTick <= 0)
1133     {
1134         StartSecondTime(CMD_NONAFS);
1135         return;
1136     }
1137
1138     ThreadCommandInfo[cmd].MilliSeconds += MilliTick;
1139     while (ThreadCommandInfo[cmd].MilliSeconds > 1000)
1140     {
1141         ThreadCommandInfo[cmd].MilliSeconds -= 1000;
1142         cmd_time += 1;
1143     }
1144
1145     if (cmd_time == 0)
1146     {
1147         ThreadCommandInfo[cmd].min_sec = cmd_time;
1148         StartSecondTime(CMD_NONAFS);
1149         return;
1150     }
1151
1152     if (!Type)
1153         ThreadCommandInfo[cmd].ErrorTime += cmd_time;
1154     else
1155     {
1156         ThreadCommandInfo[cmd].total_sec += cmd_time;
1157         if (cmd_time < (int)ThreadCommandInfo[cmd].min_sec)
1158             ThreadCommandInfo[cmd].min_sec = cmd_time;
1159         if ((int)ThreadCommandInfo[cmd].max_sec < cmd_time)
1160             ThreadCommandInfo[cmd].max_sec = cmd_time;
1161     }
1162
1163     StartSecondTime(CMD_NONAFS);
1164 }
1165
1166 void StartSecondTime(int cmd)
1167 {
1168
1169     TickCount2 = GetTickCount();
1170
1171 }
1172
1173 void EndSecondTime(int cmd)
1174 {
1175     DWORD   MilliTick;
1176     DWORD   cmd_time;
1177
1178     ThreadCommandInfo[cmd].count++;
1179     cmd_time = 0;
1180     MilliTick = GetTickCount() - TickCount2;
1181
1182     if (MilliTick <= 0)
1183         return;
1184
1185     ThreadCommandInfo[cmd].MilliSeconds += MilliTick;
1186     while (ThreadCommandInfo[cmd].MilliSeconds > 1000)
1187     {
1188         ThreadCommandInfo[cmd].MilliSeconds -= 1000;
1189         cmd_time += 1;
1190     }
1191     if (cmd_time == 0)
1192     {
1193         ThreadCommandInfo[cmd].min_sec = cmd_time;
1194         return;
1195     }
1196     if (cmd_time < (int)ThreadCommandInfo[cmd].min_sec)
1197         ThreadCommandInfo[cmd].min_sec = cmd_time;
1198     if ((int)ThreadCommandInfo[cmd].max_sec < cmd_time)
1199         ThreadCommandInfo[cmd].max_sec = cmd_time;
1200     ThreadCommandInfo[cmd].total_sec += cmd_time;
1201 }
1202
1203
1204 intptr_t SystemCall(char *command)
1205 {
1206     intptr_t rc;
1207     char    *argv[6];
1208
1209     argv[0] = getenv("COMSPEC");
1210     argv[1] = "/q";
1211     argv[2] = "/c";
1212     argv[3] = (char *)command;
1213     argv[4] = NULL;
1214
1215     rc = spawnve(_P_WAIT,argv[0],argv,NULL);
1216 // != -1 || (errno != ENOENT && errno != EACCES))
1217     return(rc);
1218 }
1219
1220 HANDLE CreateObject(const char *fname, uint32 DesiredAccess,
1221                  uint32 FileAttributes, uint32 ShareAccess,
1222                  uint32 CreateDisposition, uint32 CreateOptions)
1223 {
1224     HANDLE   fd;
1225     DWORD dwCreateDisposition = 0;
1226     DWORD dwDesiredAccess = 0;
1227     DWORD dwShareAccess = 0;
1228     DWORD dwFlags = 0;
1229
1230     if (CreateOptions & FILE_DIRECTORY_FILE)
1231     {
1232         DWORD rc;
1233
1234         if (!CreateDirectory(fname, NULL) && (rc = GetLastError()) != ERROR_ALREADY_EXISTS)
1235         {
1236             SetLastError(rc);
1237             fd = INVALID_HANDLE_VALUE;
1238         }
1239         else
1240         {
1241             fd = CreateFile(fname, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1242         }
1243     }
1244     else
1245     {
1246         dwDesiredAccess = 0;
1247         if (DesiredAccess & FILE_READ_DATA)
1248             dwDesiredAccess |= GENERIC_READ;
1249         if (DesiredAccess & FILE_WRITE_DATA)
1250             dwDesiredAccess |= GENERIC_WRITE;
1251         dwShareAccess = ShareAccess;
1252         dwShareAccess |= FILE_SHARE_DELETE;
1253         dwCreateDisposition = OPEN_ALWAYS;
1254         if (CreateDisposition == 1)
1255             dwCreateDisposition = OPEN_EXISTING;
1256         fd = CreateFile(fname, dwDesiredAccess, ShareAccess, NULL, dwCreateDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
1257     }
1258
1259     return(fd);
1260 }
1261
1262 BOOL nb_close1(HANDLE fd)
1263 {
1264     int dwFlags = 0;
1265     int rc = 1;
1266
1267     if (fd != INVALID_HANDLE_VALUE)
1268     {
1269         if (rc = GetHandleInformation(fd, &dwFlags))
1270             CloseHandle(fd);
1271     }
1272     return(rc);
1273 }
1274
1275 /****************************************************************************
1276   do a directory listing, calling fn on each file found
1277   this uses the old SMBsearch interface. It is needed for testing Samba,
1278   but should otherwise not be used
1279   ****************************************************************************/
1280 int nb_list_old(const char *Mask, void (*fn)(file_info *, const char *, void *), void *state)
1281 {
1282     int     num_received = 0;
1283     pstring mask;
1284     char    temp[512];
1285     char    cFileName[1024];
1286     int     dwFileAttributes;
1287     HANDLE  hFind;
1288     void    *FileData;
1289
1290     strcpy(mask,Mask);
1291
1292
1293     if (!strcmp(&mask[strlen(mask)-2], "\"*"))
1294     {
1295         strcpy(&mask[strlen(mask)-2], "*");
1296     }
1297     FileData = NULL;
1298     dwFileAttributes = 0;
1299     memset(cFileName, '\0', sizeof(cFileName));
1300     hFind = WinFindFirstFile(mask, &FileData, cFileName, &dwFileAttributes);
1301     if (hFind == INVALID_HANDLE_VALUE)
1302     {
1303         return(0);
1304     }
1305     mask[strlen(mask) - 1] = '\0';
1306     while (1)
1307     {
1308         if (cFileName[0] != '.')
1309         {
1310             file_info finfo;
1311
1312             memset(&finfo, '\0', sizeof(finfo));
1313             if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1314                 finfo.mode = aDIR;
1315             strcpy(finfo.name, cFileName);
1316             sprintf(temp, "%s%s", mask, cFileName);
1317                 fn(&finfo, temp, state);
1318             ++num_received;
1319         }
1320         memset(cFileName, '\0', sizeof(cFileName));
1321         dwFileAttributes = 0;
1322         if (!WinFindNextFile(hFind, &FileData, cFileName, &dwFileAttributes))
1323             break;
1324     }
1325     FindClose(hFind);
1326     return(num_received);
1327 }
1328
1329
1330 /****************************************************************************
1331   do a directory listing, calling fn on each file found
1332   this auto-switches between old and new style
1333   ****************************************************************************/
1334 int GetFileList(char *Mask, void (*fn)(file_info *, const char *, void *), void *state)
1335 {
1336     return(nb_list_old(Mask, fn, state));
1337 }
1338
1339 HANDLE WinFindFirstFile(char *Mask, void **FileData, char *cFileName, int *dwFileAttributes)
1340 {
1341     HANDLE  rc;
1342     static WIN32_FIND_DATAW FileDataW;
1343     static WIN32_FIND_DATAA FileDataA;
1344
1345     memset(&FileDataA, '\0', sizeof(FileDataA));
1346     rc = FindFirstFile(Mask, &FileDataA);
1347     if (rc != INVALID_HANDLE_VALUE)
1348     {
1349         (*FileData) = (void *)&FileDataA;
1350         (*dwFileAttributes) = FileDataA.dwFileAttributes;
1351         strcpy(cFileName, FileDataA.cFileName);
1352     }
1353
1354     return(rc);
1355 }
1356
1357 int WinFindNextFile(HANDLE hFind, void **FileData, char *cFileName, int *dwFileAttributes)
1358 {
1359     int     rc;
1360     WIN32_FIND_DATAA *FileDataA;
1361
1362     FileDataA = (WIN32_FIND_DATAA *)(*FileData);
1363     if (!(rc = FindNextFile(hFind, FileDataA)))
1364     {
1365         return(rc);
1366     }
1367     (*dwFileAttributes) = FileDataA->dwFileAttributes;
1368     strcpy(cFileName, FileDataA->cFileName);
1369
1370     return(rc);
1371 }
1372
1373 void SubstituteString(char *s,const char *pattern,const char *insert, size_t len)
1374 {
1375     char *p;
1376     ssize_t ls,lp,li;
1377
1378     if (!insert || !pattern || !s) return;
1379
1380     ls = (ssize_t)strlen(s);
1381     lp = (ssize_t)strlen(pattern);
1382     li = (ssize_t)strlen(insert);
1383
1384     if (!*pattern) return;
1385
1386     while (lp <= ls && (p = strstr(s,pattern)))
1387     {
1388         if (len && (ls + (li-lp) >= (int)len))
1389         {
1390             break;
1391         }
1392         if (li != lp)
1393         {
1394             memmove(p+li,p+lp,strlen(p+lp)+1);
1395         }
1396         memcpy(p, insert, li);
1397         s = p + li;
1398         ls += (li-lp);
1399     }
1400 }
1401
1402 #define CHANGE_TIME(A,B) \
1403 B.tm_hour = A.wHour; \
1404 B.tm_sec = A.wSecond; \
1405 B.tm_min = A.wMinute; \
1406 B.tm_mon = A.wMonth - 1; \
1407 B.tm_yday = 0; \
1408 B.tm_year = A.wYear - 1900; \
1409 B.tm_wday = A.wDayOfWeek - 1; \
1410 B.tm_isdst = -1; \
1411 B.tm_mday = A.wDay;
1412
1413
1414 BOOL GetPathInfo(const char *fname,
1415                    time_t *c_time, time_t *a_time, time_t *m_time,
1416                    size_t *size, uint16 *mode)
1417 {
1418     WIN32_FILE_ATTRIBUTE_DATA FileInfo;
1419     int         rc;
1420     SYSTEMTIME  SystemTime;
1421     struct tm   tm_time;
1422
1423     rc = GetFileAttributesEx(fname, GetFileExInfoStandard, &FileInfo);
1424     if (rc != 0)
1425     {
1426         if (c_time)
1427         {
1428             rc = FileTimeToSystemTime(&FileInfo.ftCreationTime, &SystemTime);
1429             CHANGE_TIME(SystemTime, tm_time)
1430             (*c_time) = mktime(&tm_time);
1431         }
1432         if (a_time)
1433         {
1434             rc = FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SystemTime);
1435             CHANGE_TIME(SystemTime, tm_time)
1436             (*a_time) = mktime(&tm_time);
1437         }
1438         if (m_time)
1439         {
1440             rc = FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SystemTime);
1441             CHANGE_TIME(SystemTime, tm_time)
1442             (*m_time) = mktime(&tm_time);
1443         }
1444         if (size)
1445         {
1446             rc = 1;
1447             if (!(FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
1448                 *size = FileInfo.nFileSizeLow;
1449         }
1450         if (mode)
1451         {
1452             rc = 1;
1453             (*mode) = 0;
1454         }
1455     }
1456     return(rc);
1457 }
1458
1459 /****************************************************************************
1460 send a qfileinfo call
1461 ****************************************************************************/
1462 BOOL GetFileInfo(char *FileName, HANDLE fd,
1463                    uint16 *mode, size_t *size,
1464                    time_t *c_time, time_t *a_time, time_t *m_time,
1465                    time_t *w_time)
1466 {
1467     WIN32_FILE_ATTRIBUTE_DATA FileInfo;
1468     int         rc;
1469     SYSTEMTIME  SystemTime;
1470     struct tm   tm_time;
1471
1472     rc = GetFileAttributesEx(FileName, GetFileExInfoStandard, &FileInfo);
1473     if (rc != 0)
1474     {
1475         if (c_time)
1476         {
1477             rc = FileTimeToSystemTime(&FileInfo.ftCreationTime, &SystemTime);
1478             CHANGE_TIME(SystemTime, tm_time)
1479             (*c_time) = mktime(&tm_time);
1480         }
1481         if (a_time)
1482         {
1483             rc = FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SystemTime);
1484             CHANGE_TIME(SystemTime, tm_time)
1485             (*a_time) = mktime(&tm_time);
1486         }
1487         if (m_time)
1488         {
1489             rc = FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SystemTime);
1490             CHANGE_TIME(SystemTime, tm_time)
1491             (*m_time) = mktime(&tm_time);
1492         }
1493         if (size)
1494         {
1495             rc = 0;
1496             if (!(FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
1497                *size = FileInfo.nFileSizeLow;
1498             }
1499             if (mode)
1500         {
1501             rc = 0;
1502             (*mode) = 0;
1503         }
1504     }
1505     return(rc);
1506 }
1507
1508 /****************************************************************************
1509   Read size bytes at offset offset using SMBreadX.
1510 ****************************************************************************/
1511
1512 ssize_t nb_read(HANDLE fd, char *IoBuffer, off_t offset, size_t size)
1513 {
1514     DWORD   total = 0;
1515     int     rc;
1516     DWORD   LowDword;
1517
1518     if (size == 0)
1519         return(0);
1520
1521     LowDword = SetFilePointer(fd, offset, 0, FILE_BEGIN);
1522
1523     if (LowDword == INVALID_SET_FILE_POINTER)
1524         return(-1);
1525     rc = ReadFile(fd, IoBuffer, (DWORD)size, &total, NULL);
1526     if (!rc)
1527         return(rc);
1528
1529     return(total);
1530 }
1531
1532 /****************************************************************************
1533   write to a file
1534 ****************************************************************************/
1535
1536 ssize_t nb_write(HANDLE fd, char *IoBuffer, off_t offset, size_t size)
1537 {
1538     DWORD   bwritten = 0;
1539     int     rc;
1540     DWORD   LowDword;
1541
1542     LowDword = SetFilePointer(fd, offset, 0, FILE_BEGIN);
1543     if (LowDword == INVALID_SET_FILE_POINTER)
1544         return(-1);
1545     rc = WriteFile(fd, IoBuffer, (DWORD)size, &bwritten, NULL);
1546     if (!rc)
1547         return(rc);
1548     FlushFileBuffers(fd);
1549     return(bwritten);
1550 }
1551