Release 950319
[wine.git] / misc / file.c
blob2f3aa2f4f05ba74868a35ae99bd2962383ea426f
1 /************************************************************************
2 * FILE.C Copyright (C) 1993 John Burton
4 * File I/O routines for the Linux Wine Project.
6 * WARNING : Many options of OpenFile are not yet implemeted.
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.
16 ************************************************************************/
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 "regfunc.h"
27 #include "windows.h"
28 #include "wine.h"
29 #include "msdos.h"
30 #include "registers.h"
31 #include "options.h"
32 #include "stddebug.h"
33 #include "debug.h"
35 #define MAX_PATH 255
37 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
39 /***************************************************************************
40 _lopen
42 Emulate the _lopen windows call
43 ***************************************************************************/
44 INT _lopen (LPSTR lpPathName, INT iReadWrite)
46 int handle;
47 char *UnixFileName;
49 dprintf_file(stddeb, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite);
50 if ((UnixFileName = DOS_GetUnixFileName(lpPathName)) == NULL)
51 return HFILE_ERROR;
52 iReadWrite &= 0x000F;
53 handle = open (UnixFileName, iReadWrite);
54 if( ( handle == -1 ) && Options.allowReadOnly )
55 handle = open( UnixFileName, O_RDONLY );
57 dprintf_file(stddeb, "_lopen: open: %s (handle %d)\n", UnixFileName, handle);
59 if (handle == -1)
60 return HFILE_ERROR;
61 else
62 return handle;
65 /***************************************************************************
66 _lread
67 ***************************************************************************/
68 INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes)
70 int result;
72 dprintf_file(stddeb, "_lread: handle %d, buffer = %ld, length = %d\n",
73 hFile, (long) lpBuffer, wBytes);
75 result = read (hFile, lpBuffer, wBytes);
77 if (result == -1)
78 return HFILE_ERROR;
79 else
80 return result;
83 /****************************************************************************
84 _lwrite
85 ****************************************************************************/
86 INT _lwrite (INT hFile, LPSTR lpBuffer, WORD wBytes)
88 int result;
90 dprintf_file(stddeb, "_lwrite: handle %d, buffer = %ld, length = %d\n",
91 hFile, (long) lpBuffer, wBytes);
93 result = write (hFile, lpBuffer, wBytes);
95 if (result == -1)
96 return HFILE_ERROR;
97 else
98 return result;
101 /***************************************************************************
102 _lclose
103 ***************************************************************************/
104 INT _lclose (INT hFile)
106 dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
107 if (close (hFile))
108 return HFILE_ERROR;
109 else
110 return 0;
113 /**************************************************************************
114 OpenFile
115 **************************************************************************/
116 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
118 #ifdef WINELIB
119 dprintf_file(stdnimp, "OpenFile: not implemented\n");
120 #else
121 #ifndef PROCEMU
122 struct sigcontext_struct ccontext;
123 /* To make macros like EAX happy */
124 struct sigcontext_struct *context=&ccontext;
125 #endif
126 char filename[MAX_PATH+1];
127 int action;
128 struct stat s;
129 struct tm *now;
130 int res;
131 int verify_time;
133 dprintf_file(stddeb,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
135 action = wStyle & 0xff00;
138 /* OF_CREATE is completly different from all other options, so
139 handle it first */
141 if (action & OF_CREATE)
143 int handle;
144 char *unixfilename;
146 if (!(action & OF_REOPEN))
147 strcpy(ofs->szPathName, lpFileName);
148 ofs->cBytes = sizeof(OFSTRUCT);
149 ofs->fFixedDisk = FALSE;
150 ofs->nErrCode = 0;
151 *((int*)ofs->reserved) = 0;
153 if ((unixfilename = DOS_GetUnixFileName (ofs->szPathName)) == NULL)
155 errno_to_doserr();
156 ofs->nErrCode = ExtendedError;
157 return -1;
159 handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0x666);
160 if (handle == -1)
162 errno_to_doserr();
163 ofs->nErrCode = ExtendedError;
165 return handle;
169 /* If path isn't given, try to find the file. */
171 if (!(action & OF_REOPEN))
173 if( !( index(lpFileName,'\\') || index(lpFileName,'/') ||
174 index(lpFileName,':')))
175 while(1)
177 char temp[MAX_PATH+1];
178 strcpy (filename, lpFileName);
179 if ( (!stat(DOS_GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
180 break;
181 GetWindowsDirectory (filename,MAX_PATH);
182 if ((!filename[0])||(filename[strlen(filename)-1]!='\\'))
183 strcat(filename, "\\");
184 strcat (filename, lpFileName);
185 if ( (!stat(DOS_GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
186 break;
187 GetSystemDirectory (filename,MAX_PATH);
188 if ((!filename[0])||(filename[strlen(filename)-1]!='\\'))
189 strcat(filename, "\\");
190 strcat (filename, lpFileName);
191 if ( (!stat(DOS_GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
192 break;
193 if (!DOS_FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath))
195 strcpy(filename, DOS_GetDosFileName(temp));
196 break;
198 strcpy (filename, lpFileName);
199 break;
201 else
202 strcpy (filename,lpFileName);
204 ofs->cBytes = sizeof(OFSTRUCT);
205 ofs->fFixedDisk = FALSE;
206 strcpy(ofs->szPathName, filename);
207 ofs->nErrCode = 0;
208 if (!(action & OF_VERIFY))
209 *((int*)ofs->reserved) = 0;
213 if (action & OF_PARSE)
214 return 0;
216 if (action & OF_DELETE)
217 return unlink(ofs->szPathName);
220 /* Now on to getting some information about that file */
222 if ((res = stat(DOS_GetUnixFileName(ofs->szPathName), &s)))
224 errno_to_doserr();
225 ofs->nErrCode = ExtendedError;
226 return -1;
229 now = localtime (&s.st_mtime);
231 if (action & OF_VERIFY)
232 verify_time = *((int*)ofs->reserved);
234 *((WORD*)(&ofs->reserved[2]))=
235 ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2));
236 *((WORD*)(&ofs->reserved[0]))=
237 ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
240 if (action & OF_VERIFY)
241 return (verify_time != *((int*)ofs->reserved));
243 if (action & OF_EXIST)
244 return 0;
246 /* Now we are actually going to open the file. According to Microsoft's
247 Knowledge Basis, this is done by calling int 21h, ax=3dh. */
249 #if 0
250 AX = 0x3d00;
251 AL = (AL & 0x0f) | (wStyle & 0x70); /* Handle OF_SHARE_xxx etc. */
252 AL = (AL & 0xf0) | (wStyle & 0x03); /* Handle OF_READ etc. */
253 DS = SELECTOROF(ofs->szPathName);
254 DX = OFFSETOF(ofs->szPathName);
256 OpenExistingFile (context);
258 if (EFL & 0x00000001) /* Cflag */
260 ofs->nErrCode = AL;
261 return -1;
264 return AX;
265 #endif
266 /* FIXME: Quick hack to get it to work without calling DOS --AJ */
268 int mode, handle;
269 switch(wStyle & 3)
271 case 0: mode = O_RDONLY; break;
272 case 1: mode = O_WRONLY; break;
273 default: mode = O_RDWR; break;
275 if ((handle = open(DOS_GetUnixFileName(ofs->szPathName), mode)) == -1)
277 ofs->nErrCode = 2; /* not found */
278 return -1;
280 /* don't bother with locking for now */
282 return handle;
284 #endif /*WINELIB*/
287 /**************************************************************************
288 SetHandleCount
290 Changes the number of file handles available to the application. Since
291 Linux isn't limited to 20 files, this one's easy. - SL
292 **************************************************************************/
294 #if !defined (OPEN_MAX)
295 /* This one is for the Sun */
296 #define OPEN_MAX _POSIX_OPEN_MAX
297 #endif
298 WORD SetHandleCount (WORD wNumber)
300 dprintf_file(stddeb,"SetHandleCount(%d)\n",wNumber);
301 return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
304 /***************************************************************************
305 _llseek
306 ***************************************************************************/
307 LONG _llseek (INT hFile, LONG lOffset, INT nOrigin)
309 int origin;
311 dprintf_file(stddeb, "_llseek: handle %d, offset %ld, origin %d\n",
312 hFile, lOffset, nOrigin);
314 switch (nOrigin) {
315 case 1: origin = SEEK_CUR;
316 break;
317 case 2: origin = SEEK_END;
318 break;
319 default: origin = SEEK_SET;
320 break;
323 return ( lseek(hFile, lOffset, origin) );
326 /***************************************************************************
327 _lcreat
328 ***************************************************************************/
329 INT _lcreat (LPSTR lpszFilename, INT fnAttribute)
331 int handle;
332 char *UnixFileName;
334 dprintf_file(stddeb, "_lcreat: filename %s, attributes %d\n",
335 lpszFilename, fnAttribute);
336 if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
337 return HFILE_ERROR;
338 handle = open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 426);
340 if (handle == -1)
341 return HFILE_ERROR;
342 else
343 return handle;
346 /***************************************************************************
347 GetDriveType
348 ***************************************************************************/
349 UINT GetDriveType(INT drive)
352 dprintf_file(stddeb,"GetDriveType %c:\n",'A'+drive);
354 if (!DOS_ValidDrive(drive))
355 return DRIVE_DOESNOTEXIST;
357 if (drive == 0 || drive == 1)
358 return DRIVE_REMOVABLE;
360 return DRIVE_FIXED;
363 /***************************************************************************
364 GetTempDrive
365 ***************************************************************************/
366 BYTE GetTempDrive(BYTE chDriveLetter)
368 dprintf_file(stddeb,"GetTempDrive (%d)\n",chDriveLetter);
369 return('C');
372 /***************************************************************************
373 GetWindowsDirectory
374 ***************************************************************************/
375 UINT GetWindowsDirectory(LPSTR lpszSysPath, UINT cbSysPath)
377 if (cbSysPath < strlen(WindowsDirectory))
378 *lpszSysPath = 0;
379 else
380 strcpy(lpszSysPath, WindowsDirectory);
382 dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
384 ChopOffSlash(lpszSysPath);
385 return(strlen(lpszSysPath));
387 /***************************************************************************
388 GetSystemDirectory
389 ***************************************************************************/
390 UINT GetSystemDirectory(LPSTR lpszSysPath, UINT cbSysPath)
392 if (cbSysPath < strlen(SystemDirectory))
393 *lpszSysPath = 0;
394 else
395 strcpy(lpszSysPath, SystemDirectory);
397 dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
399 ChopOffSlash(lpszSysPath);
400 return(strlen(lpszSysPath));
402 /***************************************************************************
403 GetTempFileName
404 ***************************************************************************/
405 INT GetTempFileName(BYTE bDriveLetter, LPCSTR lpszPrefixString, UINT uUnique, LPSTR lpszTempFileName)
407 int unique;
408 int handle;
409 char tempname[256];
411 if (uUnique == 0)
412 unique = time(NULL)%99999L;
413 else
414 unique = uUnique%99999L;
416 strcpy(tempname,lpszPrefixString);
417 tempname[3]='\0';
419 sprintf(lpszTempFileName,"%s\\%s%d.tmp", TempDirectory, tempname,
420 unique);
422 ToDos(lpszTempFileName);
424 dprintf_file(stddeb,"GetTempFilename: %c %s %d => %s\n",bDriveLetter,
425 lpszPrefixString,uUnique,lpszTempFileName);
426 if ((handle = _lcreat (lpszTempFileName, 0x0000)) == -1) {
427 fprintf(stderr,"GetTempFilename: can't create temp file '%s' !\n", lpszTempFileName);
429 else
430 close(handle);
432 return unique;
435 /***************************************************************************
436 SetErrorMode
437 ***************************************************************************/
438 WORD SetErrorMode(WORD x)
440 dprintf_file(stdnimp,"wine: SetErrorMode %4x (ignored)\n",x);
442 return 1;
445 /***************************************************************************
446 _hread
447 ***************************************************************************/
448 long _hread(int hf, void FAR *hpvBuffer, long cbBuffer)
450 return read(hf, hpvBuffer, cbBuffer);
452 /***************************************************************************
453 _hwrite
454 ***************************************************************************/
455 long _hwrite(int hf, const void FAR *hpvBuffer, long cbBuffer)
457 return write(hf, hpvBuffer, cbBuffer);