Release 950727
[wine] / misc / file.c
1 /************************************************************************
2  * FILE.C     Copyright (C) 1993 John Burton
3  *
4  * File I/O routines for the Linux Wine Project.
5  *
6  * WARNING : Many options of OpenFile are not yet implemeted.
7  *
8  * NOV 93 Erik Bos (erik@xs4all.nl)
9  *              - removed ParseDosFileName, and DosDrive structures.
10  *              - structures dynamically configured at runtime.
11  *              - _lopen modified to use DOS_GetUnixFileName.
12  *              - Existing functions modified to use dosfs functions.
13  *              - Added _llseek, _lcreat, GetDriveType, GetTempDrive, 
14  *                GetWindowsDirectory, GetSystemDirectory, GetTempFileName.
15  *
16  ************************************************************************/
17
18 #include <stdio.h>
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <unistd.h>
22 #include <time.h>
23 #include <sys/stat.h>
24 #include <string.h>
25 #include "dos_fs.h"
26 #include "windows.h"
27 #include "msdos.h"
28 #include "options.h"
29 #include "stddebug.h"
30 #include "debug.h"
31
32 #define MAX_PATH 255
33
34 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
35
36 /***************************************************************************
37  _lopen 
38
39  Emulate the _lopen windows call
40  ***************************************************************************/
41 INT _lopen (LPSTR lpPathName, INT iReadWrite)
42 {
43   int  handle;
44   char *UnixFileName;
45   int mode = 0;
46
47   dprintf_file(stddeb, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite);
48   if ((UnixFileName = DOS_GetUnixFileName(lpPathName)) == NULL)
49         return HFILE_ERROR;
50   switch(iReadWrite & 3)
51   {
52   case OF_READ:      mode = O_RDONLY; break;
53   case OF_WRITE:     mode = O_WRONLY; break;
54   case OF_READWRITE: mode = O_RDWR; break;
55   }
56   handle = open( UnixFileName, mode );
57   if (( handle == -1 ) && Options.allowReadOnly)
58     handle = open( UnixFileName, O_RDONLY );
59
60   dprintf_file(stddeb, "_lopen: open: %s (handle %d)\n", UnixFileName, handle);
61
62   if (handle == -1)
63         return HFILE_ERROR;
64   else
65         return handle;
66 }
67
68 /***************************************************************************
69  _lread
70  ***************************************************************************/
71 INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes)
72 {
73   int result;
74
75   dprintf_file(stddeb, "_lread: handle %d, buffer = %ld, length = %d\n",
76                         hFile, (long) lpBuffer, wBytes);
77   
78   result = wBytes == 0 ? 0 : read (hFile, lpBuffer, wBytes);
79
80   if (result == -1)
81         return HFILE_ERROR;
82   else
83         return result;
84 }
85
86 /****************************************************************************
87  _lwrite
88 ****************************************************************************/
89 INT _lwrite (INT hFile, LPCSTR lpBuffer, WORD wBytes)
90 {
91     int result;
92
93     dprintf_file(stddeb, "_lwrite: handle %d, buffer = %ld, length = %d\n",
94                  hFile, (long) lpBuffer, wBytes);
95
96     result = wBytes == 0 ? 0 : write (hFile, lpBuffer, wBytes);
97
98     if (result == -1)
99         return HFILE_ERROR;
100     else
101         return result;
102 }
103
104 /***************************************************************************
105  _lclose
106  ***************************************************************************/
107 INT _lclose (INT hFile)
108 {
109     dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
110     
111     if (hFile == 0 || hFile == 1 || hFile == 2) {
112         fprintf( stderr, "Program attempted to close stdin, stdout or stderr!\n" );
113         return 0;
114     }
115     if (close (hFile))
116         return HFILE_ERROR;
117     else
118         return 0;
119 }
120
121 /**************************************************************************
122  OpenFile
123  **************************************************************************/
124 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
125 {
126     char         filename[MAX_PATH+1];
127     int          action;
128     struct stat  s;
129     struct tm   *now;
130     int          res, handle;
131     int          verify_time = 0;
132   
133     dprintf_file(stddeb,"Openfile(%s,<struct>,%d)\n",lpFileName,wStyle);
134   
135     action = wStyle & 0xff00;
136   
137   
138     /* OF_CREATE is completly different from all other options, so
139        handle it first */
140
141     if (action & OF_CREATE)
142     {
143         char *unixfilename;
144
145         if (!(action & OF_REOPEN)) strcpy(ofs->szPathName, lpFileName);
146         ofs->cBytes = sizeof(OFSTRUCT);
147         ofs->fFixedDisk = FALSE;
148         ofs->nErrCode = 0;
149         *((int*)ofs->reserved) = 0;
150
151         if ((unixfilename = DOS_GetUnixFileName (ofs->szPathName)) == NULL)
152         {
153             errno_to_doserr();
154             ofs->nErrCode = ExtendedError;
155             return -1;
156         }
157         handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0666);
158         if (handle == -1)
159         {
160             errno_to_doserr();
161             ofs->nErrCode = ExtendedError;
162         }   
163         return handle;
164     }
165
166
167     /* If path isn't given, try to find the file. */
168
169     if (!(action & OF_REOPEN))
170     {
171         char temp[MAX_PATH + 1];
172         
173         if(index(lpFileName,'\\') || index(lpFileName,'/') || 
174            index(lpFileName,':')) 
175         {
176             strcpy (filename,lpFileName);
177             goto found;
178         }
179         /* Try current directory */
180         if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, ".")) {
181             strcpy(filename, DOS_GetDosFileName(temp));
182             goto found;
183         }
184
185         /* Try Windows directory */
186         GetWindowsDirectory(filename, MAX_PATH);
187         if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
188             strcpy(filename, DOS_GetDosFileName(temp));
189             goto found;
190         }
191         
192         /* Try Windows system directory */
193         GetSystemDirectory(filename, MAX_PATH);
194         if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
195             strcpy(filename, DOS_GetDosFileName(temp));
196             goto found;
197         }
198
199         /* Try the path of the current executable */
200         if (GetCurrentTask())
201         {
202             char *p;
203             GetModuleFileName( GetCurrentTask(), filename, MAX_PATH );
204             if ((p = strrchr( filename, '\\' )))
205             {
206                 p[1] = '\0';
207                 if (DOS_FindFile(temp, MAX_PATH, lpFileName, NULL, filename)) {
208                     strcpy(filename, DOS_GetDosFileName(temp));
209                     goto found;
210                 }
211             }
212         }
213
214         /* Try all directories in path */
215
216         if (DOS_FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath))
217         {
218             strcpy(filename, DOS_GetDosFileName(temp));
219             goto found;
220         }
221         /* ??? shouldn't we give an error here? */
222         strcpy (filename, lpFileName);
223         
224         found:
225         
226         ofs->cBytes = sizeof(OFSTRUCT);
227         ofs->fFixedDisk = FALSE;
228         strcpy(ofs->szPathName, filename);
229         ofs->nErrCode = 0;
230         if (!(action & OF_VERIFY))
231           *((int*)ofs->reserved) = 0;
232     }
233     
234
235     if (action & OF_PARSE)
236       return 0;
237
238     if (action & OF_DELETE)
239       return unlink(ofs->szPathName);
240
241
242     /* Now on to getting some information about that file */
243
244     if ((res = stat(DOS_GetUnixFileName(ofs->szPathName), &s)))
245       {
246       errno_to_doserr();
247       ofs->nErrCode = ExtendedError;
248       return -1;
249     }
250     
251     now = localtime (&s.st_mtime);
252
253     if (action & OF_VERIFY)
254       verify_time = *((int*)ofs->reserved);
255     
256     *((WORD*)(&ofs->reserved[2]))=
257          ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2));
258     *((WORD*)(&ofs->reserved[0]))=
259          ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
260
261
262     if (action & OF_VERIFY)
263       return (verify_time != *((int*)ofs->reserved));
264
265     if (action & OF_EXIST)
266       return 0;
267     
268     if ((handle = _lopen( ofs->szPathName, wStyle )) == -1)
269     {
270         ofs->nErrCode = 2;  /* not found */
271         return -1;
272     }
273     return handle;
274 }
275
276
277 /**************************************************************************
278  SetHandleCount
279
280  Changes the number of file handles available to the application.  Since
281  Linux isn't limited to 20 files, this one's easy. - SL
282  **************************************************************************/
283
284 #if !defined (OPEN_MAX)
285 /* This one is for the Sun */
286 #define OPEN_MAX _POSIX_OPEN_MAX
287 #endif
288 WORD SetHandleCount (WORD wNumber)
289 {
290   dprintf_file(stddeb,"SetHandleCount(%d)\n",wNumber);
291   return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
292 }
293
294 /***************************************************************************
295  _llseek
296  ***************************************************************************/
297 LONG _llseek (INT hFile, LONG lOffset, INT nOrigin)
298 {
299         int origin;
300         
301         dprintf_file(stddeb, "_llseek: handle %d, offset %ld, origin %d\n", 
302                 hFile, lOffset, nOrigin);
303
304         switch (nOrigin) {
305                 case 1: origin = SEEK_CUR;
306                         break;
307                 case 2: origin = SEEK_END;
308                         break;
309                 default: origin = SEEK_SET;
310                         break;
311         }
312
313         return lseek(hFile, lOffset, origin);
314 }
315
316 /***************************************************************************
317  _lcreat
318  ***************************************************************************/
319 INT _lcreat (LPSTR lpszFilename, INT fnAttribute)
320 {
321         int handle;
322         char *UnixFileName;
323
324         dprintf_file(stddeb, "_lcreat: filename %s, attributes %d\n",
325                 lpszFilename, fnAttribute);
326         if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
327                 return HFILE_ERROR;
328         handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 0666);
329
330         if (handle == -1)
331                 return HFILE_ERROR;
332         else
333                 return handle;
334 }
335
336 /***************************************************************************
337  GetDriveType
338  ***************************************************************************/
339 UINT GetDriveType(INT drive)
340 {
341
342         dprintf_file(stddeb,"GetDriveType %c:\n",'A'+drive);
343
344         if (!DOS_ValidDrive(drive))
345                 return DRIVE_DOESNOTEXIST;
346
347         if (drive == 0 || drive == 1)
348                 return DRIVE_REMOVABLE;
349                  
350         return DRIVE_FIXED;
351 }
352
353 /***************************************************************************
354  GetTempDrive
355  ***************************************************************************/
356 BYTE GetTempDrive(BYTE chDriveLetter)
357 {
358     dprintf_file(stddeb,"GetTempDrive (%d)\n",chDriveLetter);
359     if (TempDirectory[1] == ':') return TempDirectory[0];
360     else return 'C';
361 }
362
363 /***************************************************************************
364  GetWindowsDirectory
365  ***************************************************************************/
366 UINT GetWindowsDirectory(LPSTR lpszSysPath, UINT cbSysPath)
367 {
368         if (cbSysPath < strlen(WindowsDirectory)) 
369                 *lpszSysPath = 0;
370         else
371                 strcpy(lpszSysPath, WindowsDirectory);
372         
373         dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
374
375         return strlen(lpszSysPath);
376 }
377 /***************************************************************************
378  GetSystemDirectory
379  ***************************************************************************/
380 UINT GetSystemDirectory(LPSTR lpszSysPath, UINT cbSysPath)
381 {
382         if (cbSysPath < strlen(SystemDirectory))
383                 *lpszSysPath = 0;
384         else
385                 strcpy(lpszSysPath, SystemDirectory);
386
387         dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
388
389         return strlen(lpszSysPath);
390 }
391 /***************************************************************************
392  GetTempFileName
393  ***************************************************************************/
394 INT GetTempFileName(BYTE bDriveLetter, LPCSTR lpszPrefixString, UINT uUnique, LPSTR lpszTempFileName)
395 {
396         int unique;
397         int handle;
398         char tempname[256];
399         
400         if (uUnique == 0)
401                 unique = time(NULL)%99999L;
402         else
403                 unique = uUnique%99999L;
404
405         strcpy(tempname,lpszPrefixString);
406         tempname[3]='\0';
407
408         sprintf(lpszTempFileName,"%s\\%s%d.tmp", TempDirectory, tempname, 
409                 unique);
410
411         ToDos(lpszTempFileName);
412
413         dprintf_file(stddeb,"GetTempFilename: %c %s %d => %s\n",bDriveLetter,
414                 lpszPrefixString,uUnique,lpszTempFileName);
415         if ((handle = _lcreat (lpszTempFileName, 0x0000)) == -1) {
416                 fprintf(stderr,"GetTempFilename: can't create temp file '%s' !\n", lpszTempFileName);
417         }
418         else
419                 close(handle);
420
421         return unique;
422 }
423
424 /***************************************************************************
425  SetErrorMode
426  ***************************************************************************/
427 WORD SetErrorMode(WORD x)
428 {
429     dprintf_file(stdnimp,"wine: SetErrorMode %4x (ignored)\n",x);
430
431     return 1;
432 }
433
434 /***************************************************************************
435  _hread
436  ***************************************************************************/
437 LONG _hread(INT hf, LPSTR hpvBuffer, LONG cbBuffer)
438 {
439     return cbBuffer == 0 ? 0 : read(hf, hpvBuffer, cbBuffer);
440 }
441 /***************************************************************************
442  _hwrite
443  ***************************************************************************/
444 LONG _hwrite(INT hf, LPCSTR hpvBuffer, LONG cbBuffer)
445 {
446     return cbBuffer == 0 ? 0 : write(hf, hpvBuffer, cbBuffer);
447 }