Release 941030
[wine/multimedia.git] / misc / file.c
blob2320a8b0e320516a86d969563159f119672c4ae1
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@(trashcan.)hacktic.nl
9 * - removed ParseDosFileName, and DosDrive structures.
10 * - structures dynamically configured at runtime.
11 * - _lopen modified to use GetUnixFileName.
13 * DEC 93 Erik Bos (erik@(trashcan.)hacktic.nl)
14 * - Existing functions modified to use dosfs functions.
15 * - Added _llseek, _lcreat, GetDriveType, GetTempDrive,
16 * GetWindowsDirectory, GetSystemDirectory, GetTempFileName.
18 ************************************************************************/
20 #include <stdio.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <unistd.h>
24 #include <time.h>
25 #include <sys/stat.h>
26 #include <string.h>
27 #include "prototypes.h"
28 #include "regfunc.h"
29 #include "windows.h"
30 #include "wine.h"
31 #include "msdos.h"
32 #include "registers.h"
33 #include "options.h"
34 #include "stddebug.h"
35 /* #define DEBUG_FILE /* */
36 /* #undef DEBUG_FILE /* */
37 #include "debug.h"
39 #define MAX_PATH 255
41 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
42 extern char WindowsPath[256];
44 extern char WindowsPath[];
45 extern WORD ExtendedError;
48 char *GetDosFileName(char *unixfilename);
50 /***************************************************************************
51 _lopen
53 Emulate the _lopen windows call
54 ***************************************************************************/
55 INT _lopen (LPSTR lpPathName, INT iReadWrite)
57 int handle;
58 char *UnixFileName;
60 dprintf_file(stddeb, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite);
61 if ((UnixFileName = GetUnixFileName(lpPathName)) == NULL)
62 return HFILE_ERROR;
63 iReadWrite &= 0x000F;
64 handle = open (UnixFileName, iReadWrite);
66 dprintf_file(stddeb, "_lopen: open: %s (handle %d)\n", UnixFileName, handle);
68 if (handle == -1)
69 return HFILE_ERROR;
70 else
71 return handle;
74 /***************************************************************************
75 _lread
76 ***************************************************************************/
77 INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes)
79 int result;
81 dprintf_file(stddeb, "_lread: handle %d, buffer = %ld, length = %d\n",
82 hFile, (int) lpBuffer, wBytes);
84 result = read (hFile, lpBuffer, wBytes);
86 if (result == -1)
87 return HFILE_ERROR;
88 else
89 return result;
92 /****************************************************************************
93 _lwrite
94 ****************************************************************************/
95 INT _lwrite (INT hFile, LPSTR lpBuffer, WORD wBytes)
97 int result;
99 dprintf_file(stddeb, "_lwrite: handle %d, buffer = %ld, length = %d\n",
100 hFile, (int) lpBuffer, wBytes);
102 result = write (hFile, lpBuffer, wBytes);
104 if (result == -1)
105 return HFILE_ERROR;
106 else
107 return result;
110 /***************************************************************************
111 _lclose
112 ***************************************************************************/
113 INT _lclose (INT hFile)
115 dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
116 if (close (hFile))
117 return HFILE_ERROR;
118 else
119 return 0;
122 /**************************************************************************
123 OpenFile
124 **************************************************************************/
125 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
127 int handle;
128 #ifndef PROCEMU
129 struct sigcontext_struct ccontext;
130 /* To make macros like EAX happy */
131 struct sigcontext_struct *context=&ccontext;
132 #endif
133 char filename[MAX_PATH+1];
134 int action;
135 struct stat s;
136 struct tm *now;
137 int res;
138 int verify_time;
140 dprintf_file(stddeb,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
142 action = wStyle & 0xff00;
145 /* OF_CREATE is completly different from all other options, so
146 handle it first */
148 if (action & OF_CREATE)
150 int handle;
151 char *unixfilename;
153 if (!(action & OF_REOPEN))
154 strcpy(ofs->szPathName, lpFileName);
155 ofs->cBytes = sizeof(OFSTRUCT);
156 ofs->fFixedDisk = FALSE;
157 ofs->nErrCode = 0;
158 *((int*)ofs->reserved) = 0;
160 if ((unixfilename = GetUnixFileName (ofs->szPathName)) == NULL)
162 errno_to_doserr();
163 ofs->nErrCode = ExtendedError;
164 return -1;
166 handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0x666);
167 if (handle == -1)
169 errno_to_doserr();
170 ofs->nErrCode = ExtendedError;
172 return handle;
176 /* If path isn't given, try to find the file. */
178 if (!(action & OF_REOPEN))
180 if( !( index(lpFileName,'\\') || index(lpFileName,'/') ||
181 index(lpFileName,':')))
182 while(1)
184 char temp[MAX_PATH+1];
185 strcpy (filename, lpFileName);
186 if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
187 break;
188 GetWindowsDirectory (filename,MAX_PATH);
189 if ((!filename[0])||(filename[strlen(filename)-1]!='\\'))
190 strcat(filename, "\\");
191 strcat (filename, lpFileName);
192 if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
193 break;
194 GetSystemDirectory (filename,MAX_PATH);
195 if ((!filename[0])||(filename[strlen(filename)-1]!='\\'))
196 strcat(filename, "\\");
197 strcat (filename, lpFileName);
198 if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) )
199 break;
200 if (!FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath))
202 strcpy(filename, GetDosFileName(temp));
203 break;
205 strcpy (filename, lpFileName);
206 break;
208 else
209 strcpy (filename,lpFileName);
211 ofs->cBytes = sizeof(OFSTRUCT);
212 ofs->fFixedDisk = FALSE;
213 strcpy(ofs->szPathName, filename);
214 ofs->nErrCode = 0;
215 if (!(action & OF_VERIFY))
216 *((int*)ofs->reserved) = 0;
220 if (action & OF_PARSE)
221 return 0;
223 if (action & OF_DELETE)
224 return unlink(ofs->szPathName);
227 /* Now on to getting some information about that file */
229 if (res = stat(GetUnixFileName(ofs->szPathName), &s))
231 errno_to_doserr();
232 ofs->nErrCode = ExtendedError;
233 return -1;
236 now = localtime (&s.st_mtime);
238 if (action & OF_VERIFY)
239 verify_time = *((int*)ofs->reserved);
241 *((WORD*)(&ofs->reserved[2]))=
242 ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2));
243 *((WORD*)(&ofs->reserved[0]))=
244 ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday);
246 if (action & OF_EXIST)
247 return 0;
249 if (action & OF_VERIFY)
250 return (verify_time != *((int*)ofs->reserved));
253 /* Now we are actually going to open the file. According to Microsoft's
254 Knowledge Basis, this is done by calling int 21h, ax=3dh. */
256 AX = 0x3d00;
257 AL = (AL & 0x0f) | (wStyle & 0x70); /* Handle OF_SHARE_xxx etc. */
258 AL = (AL & 0xf0) | (wStyle & 0x03); /* Handle OF_READ etc. */
259 DS = segment (ofs->szPathName);
260 DX = offset (ofs->szPathName);
262 OpenExistingFile (context);
264 if (EFL & 0x00000001) /* Cflag */
266 ofs->nErrCode = AL;
267 return -1;
270 return AX;
273 /**************************************************************************
274 SetHandleCount
276 Changes the number of file handles available to the application. Since
277 Linux isn't limited to 20 files, this one's easy. - SL
278 **************************************************************************/
280 #if !defined (OPEN_MAX)
281 /* This one is for the Sun */
282 #define OPEN_MAX _POSIX_OPEN_MAX
283 #endif
284 WORD SetHandleCount (WORD wNumber)
286 dprintf_file(stddeb,"SetHandleCount(%d)\n",wNumber);
287 return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
290 /***************************************************************************
291 _llseek
292 ***************************************************************************/
293 LONG _llseek (INT hFile, LONG lOffset, INT nOrigin)
295 int origin;
297 dprintf_file(stddeb, "_llseek: handle %d, offset %ld, origin %d\n",
298 hFile, lOffset, nOrigin);
300 switch (nOrigin) {
301 case 1: origin = SEEK_CUR;
302 break;
303 case 2: origin = SEEK_END;
304 break;
305 default: origin = SEEK_SET;
306 break;
309 return ( lseek(hFile, lOffset, origin) );
312 /***************************************************************************
313 _lcreat
314 ***************************************************************************/
315 INT _lcreat (LPSTR lpszFilename, INT fnAttribute)
317 int handle;
318 char *UnixFileName;
320 dprintf_file(stddeb, "_lcreat: filename %s, attributes %d\n",
321 lpszFilename, fnAttribute);
322 if ((UnixFileName = GetUnixFileName(lpszFilename)) == NULL)
323 return HFILE_ERROR;
324 handle = open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 426);
326 if (handle == -1)
327 return HFILE_ERROR;
328 else
329 return handle;
332 /***************************************************************************
333 GetDriveType
334 ***************************************************************************/
335 UINT GetDriveType(INT drive)
338 dprintf_file(stddeb,"GetDriveType %c:\n",'A'+drive);
340 if (!DOS_ValidDrive(drive))
341 return DRIVE_DOESNOTEXIST;
343 if (drive == 0 || drive == 1)
344 return DRIVE_REMOVABLE;
346 return DRIVE_FIXED;
349 /***************************************************************************
350 GetTempDrive
351 ***************************************************************************/
352 BYTE GetTempDrive(BYTE chDriveLetter)
354 dprintf_file(stddeb,"GetTempDrive (%d)\n",chDriveLetter);
355 return('C');
358 /***************************************************************************
359 GetWindowsDirectory
360 ***************************************************************************/
361 UINT GetWindowsDirectory(LPSTR lpszSysPath, UINT cbSysPath)
363 if (cbSysPath < strlen(WindowsDirectory))
364 *lpszSysPath = 0;
365 else
366 strcpy(lpszSysPath, WindowsDirectory);
368 dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
370 ChopOffSlash(lpszSysPath);
371 return(strlen(lpszSysPath));
373 /***************************************************************************
374 GetSystemDirectory
375 ***************************************************************************/
376 UINT GetSystemDirectory(LPSTR lpszSysPath, UINT cbSysPath)
378 if (cbSysPath < strlen(SystemDirectory))
379 *lpszSysPath = 0;
380 else
381 strcpy(lpszSysPath, SystemDirectory);
383 dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
385 ChopOffSlash(lpszSysPath);
386 return(strlen(lpszSysPath));
388 /***************************************************************************
389 GetTempFileName
390 ***************************************************************************/
391 INT GetTempFileName(BYTE bDriveLetter, LPCSTR lpszPrefixString, UINT uUnique, LPSTR lpszTempFileName)
393 int unique;
394 int handle;
395 char tempname[256];
397 if (uUnique == 0)
398 unique = time(NULL)%99999L;
399 else
400 unique = uUnique%99999L;
402 strcpy(tempname,lpszPrefixString);
403 tempname[3]='\0';
405 sprintf(lpszTempFileName,"%s\\%s%d.tmp", TempDirectory, tempname,
406 unique);
408 ToDos(lpszTempFileName);
410 dprintf_file(stddeb,"GetTempFilename: %c %s %d => %s\n",bDriveLetter,
411 lpszPrefixString,uUnique,lpszTempFileName);
412 if ((handle = _lcreat (lpszTempFileName, 0x0000)) == -1) {
413 fprintf(stderr,"GetTempFilename: can't create temp file '%s' !\n", lpszTempFileName);
415 else
416 close(handle);
418 return unique;
421 /***************************************************************************
422 SetErrorMode
423 ***************************************************************************/
424 WORD SetErrorMode(WORD x)
426 dprintf_file(stdnimp,"wine: SetErrorMode %4x (ignored)\n",x);
429 /***************************************************************************
430 _hread
431 ***************************************************************************/
432 long _hread(int hf, void FAR *hpvBuffer, long cbBuffer)
434 return read(hf, hpvBuffer, cbBuffer);
436 /***************************************************************************
437 _hwrite
438 ***************************************************************************/
439 long _hwrite(int hf, const void FAR *hpvBuffer, long cbBuffer)
441 return write(hf, hpvBuffer, cbBuffer);