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