2 * File handling functions
4 * Copyright 1993 John Burton
5 * Copyright 1996 Alexandre Julliard
15 #include <sys/errno.h>
42 DWORD type; /* Type for win32 apps */
46 /***********************************************************************
51 static HFILE32 FILE_Alloc( DOS_FILE **file )
54 *file = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE) );
57 DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk );
60 (*file)->header.type = K32OBJ_FILE;
61 (*file)->header.refcount = 0;
62 (*file)->unix_handle = -1;
63 (*file)->unix_name = NULL;
64 (*file)->type = FILE_TYPE_DISK;
66 handle = PROCESS_AllocHandle( &(*file)->header, 0 );
67 if (handle == INVALID_HANDLE_VALUE32) *file = NULL;
72 /***********************************************************************
77 void FILE_Destroy( K32OBJ *ptr )
79 DOS_FILE *file = (DOS_FILE *)ptr;
80 assert( ptr->type == K32OBJ_FILE );
82 if (file->unix_handle != -1) close( file->unix_handle );
83 if (file->unix_name) HeapFree( SystemHeap, 0, file->unix_name );
84 ptr->type = K32OBJ_UNKNOWN;
85 HeapFree( SystemHeap, 0, file );
89 /***********************************************************************
92 * Return the DOS file associated to a task file handle. FILE_ReleaseFile must
93 * be called to release the file.
95 static DOS_FILE *FILE_GetFile( HFILE32 handle )
97 return (DOS_FILE *)PROCESS_GetObjPtr( handle, K32OBJ_FILE );
101 /***********************************************************************
104 * Release a DOS file obtained with FILE_GetFile.
106 static void FILE_ReleaseFile( DOS_FILE *file )
108 K32OBJ_DecCount( &file->header );
112 /***********************************************************************
115 * Return the Unix handle associated to a file handle.
117 int FILE_GetUnixHandle( HFILE32 hFile )
122 if (!(file = FILE_GetFile( hFile ))) return -1;
123 ret = file->unix_handle;
124 FILE_ReleaseFile( file );
129 /***********************************************************************
132 * Set the DOS error code from errno.
134 void FILE_SetDosError(void)
136 dprintf_file(stddeb, "FILE_SetDosError: errno = %d\n", errno );
140 DOS_ERROR( ER_ShareViolation, EC_Temporary, SA_Retry, EL_Disk );
143 DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk );
146 DOS_ERROR( ER_DiskFull, EC_MediaError, SA_Abort, EL_Disk );
151 DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
154 DOS_ERROR( ER_LockViolation, EC_AccessDenied, SA_Abort, EL_Disk );
157 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
160 DOS_ERROR( ER_CanNotMakeDir, EC_AccessDenied, SA_Abort, EL_Unknown );
164 DOS_ERROR( ER_NoMoreFiles, EC_MediaError, SA_Abort, EL_Unknown );
167 DOS_ERROR( ER_FileExists, EC_Exists, SA_Abort, EL_Disk );
170 perror( "int21: unknown errno" );
171 DOS_ERROR( ER_GeneralFailure, EC_SystemFailure, SA_Abort, EL_Unknown );
177 /***********************************************************************
180 * Duplicate a Unix handle into a task handle.
182 HFILE32 FILE_DupUnixHandle( int fd )
187 if ((handle = FILE_Alloc( &file )) != INVALID_HANDLE_VALUE32)
189 if ((file->unix_handle = dup(fd)) == -1)
192 CloseHandle( handle );
193 return INVALID_HANDLE_VALUE32;
200 /***********************************************************************
203 static HFILE32 FILE_OpenUnixFile( const char *name, int mode )
209 if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
210 return INVALID_HANDLE_VALUE32;
212 if ((file->unix_handle = open( name, mode, 0666 )) == -1)
214 if (!Options.failReadOnly && (mode == O_RDWR))
215 file->unix_handle = open( name, O_RDONLY );
217 if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
220 CloseHandle( handle );
221 return INVALID_HANDLE_VALUE32;
223 if (S_ISDIR(st.st_mode))
225 DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
226 CloseHandle( handle );
227 return INVALID_HANDLE_VALUE32;
230 /* File opened OK, now fill the DOS_FILE */
232 file->unix_name = HEAP_strdupA( SystemHeap, 0, name );
237 /***********************************************************************
240 HFILE32 FILE_Open( LPCSTR path, INT32 mode )
242 DOS_FULL_NAME full_name;
243 const char *unixName;
245 dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode );
246 if ((unixName = DOSFS_IsDevice( path )) != NULL)
248 dprintf_file( stddeb, "FILE_Open: opening device '%s'\n", unixName );
249 if (!unixName[0]) /* Non-existing device */
251 dprintf_file(stddeb, "FILE_Open: Non-existing device\n");
252 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
253 return HFILE_ERROR32;
256 else /* check for filename, don't check for last entry if creating */
258 if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
259 return HFILE_ERROR32;
260 unixName = full_name.long_name;
262 return FILE_OpenUnixFile( unixName, mode );
266 /***********************************************************************
269 static HFILE32 FILE_Create( LPCSTR path, int mode, int unique )
273 const char *unixName;
274 DOS_FULL_NAME full_name;
276 dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique );
278 if ((unixName = DOSFS_IsDevice( path )) != NULL)
280 dprintf_file(stddeb, "FILE_Create: creating device '%s'!\n", unixName);
281 DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk );
282 return INVALID_HANDLE_VALUE32;
285 if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
286 return INVALID_HANDLE_VALUE32;
288 if (!DOSFS_GetFullName( path, FALSE, &full_name ))
290 CloseHandle( handle );
291 return INVALID_HANDLE_VALUE32;
293 if ((file->unix_handle = open( full_name.long_name,
294 O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
298 CloseHandle( handle );
299 return INVALID_HANDLE_VALUE32;
302 /* File created OK, now fill the DOS_FILE */
304 file->unix_name = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
309 /***********************************************************************
312 * Fill a file information from a struct stat.
314 static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
316 info->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
317 if (S_ISDIR(st->st_mode))
318 info->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
320 DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime, 0 );
321 DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime, 0 );
322 DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime, 0 );
324 info->dwVolumeSerialNumber = 0; /* FIXME */
325 info->nFileSizeHigh = 0;
326 info->nFileSizeLow = S_ISDIR(st->st_mode) ? 0 : st->st_size;
327 info->nNumberOfLinks = st->st_nlink;
328 info->nFileIndexHigh = 0;
329 info->nFileIndexLow = st->st_ino;
333 /***********************************************************************
336 * Stat a Unix path name. Return TRUE if OK.
338 BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
342 if (stat( unixName, &st ) == -1)
347 FILE_FillInfo( &st, info );
352 /***********************************************************************
353 * GetFileInformationByHandle (KERNEL32.219)
355 DWORD GetFileInformationByHandle( HFILE32 hFile,
356 BY_HANDLE_FILE_INFORMATION *info )
362 if (!(file = FILE_GetFile( hFile ))) return 0;
363 if (fstat( file->unix_handle, &st ) == -1) FILE_SetDosError();
366 FILE_FillInfo( &st, info );
369 FILE_ReleaseFile( file );
374 /**************************************************************************
375 * GetFileAttributes16 (KERNEL.420)
377 DWORD GetFileAttributes16( LPCSTR name )
379 return GetFileAttributes32A( name );
383 /**************************************************************************
384 * GetFileAttributes32A (KERNEL32.217)
386 DWORD GetFileAttributes32A( LPCSTR name )
388 DOS_FULL_NAME full_name;
389 BY_HANDLE_FILE_INFORMATION info;
391 if (!DOSFS_GetFullName( name, TRUE, &full_name )) return -1;
392 if (!FILE_Stat( full_name.long_name, &info )) return -1;
393 return info.dwFileAttributes;
397 /**************************************************************************
398 * GetFileAttributes32W (KERNEL32.218)
400 DWORD GetFileAttributes32W( LPCWSTR name )
402 LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
403 DWORD res = GetFileAttributes32A( nameA );
404 HeapFree( GetProcessHeap(), 0, nameA );
409 /***********************************************************************
410 * GetFileSize (KERNEL32.220)
412 DWORD GetFileSize( HFILE32 hFile, LPDWORD filesizehigh )
414 BY_HANDLE_FILE_INFORMATION info;
415 if (!GetFileInformationByHandle( hFile, &info )) return 0;
416 if (filesizehigh) *filesizehigh = info.nFileSizeHigh;
417 return info.nFileSizeLow;
421 /***********************************************************************
422 * GetFileTime (KERNEL32.221)
424 BOOL32 GetFileTime( HFILE32 hFile, FILETIME *lpCreationTime,
425 FILETIME *lpLastAccessTime, FILETIME *lpLastWriteTime )
427 BY_HANDLE_FILE_INFORMATION info;
428 if (!GetFileInformationByHandle( hFile, &info )) return FALSE;
429 if (lpCreationTime) *lpCreationTime = info.ftCreationTime;
430 if (lpLastAccessTime) *lpLastAccessTime = info.ftLastAccessTime;
431 if (lpLastWriteTime) *lpLastWriteTime = info.ftLastWriteTime;
436 /***********************************************************************
439 * dup() function for DOS handles.
441 HFILE32 FILE_Dup( HFILE32 hFile )
446 dprintf_file( stddeb, "FILE_Dup for handle %d\n", hFile );
447 if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR32;
448 handle = PROCESS_AllocHandle( &file->header, 0 );
449 FILE_ReleaseFile( file );
450 dprintf_file( stddeb, "FILE_Dup return handle %d\n", handle );
455 /***********************************************************************
458 * dup2() function for DOS handles.
460 HFILE32 FILE_Dup2( HFILE32 hFile1, HFILE32 hFile2 )
464 dprintf_file( stddeb, "FILE_Dup2 for handle %d\n", hFile1 );
465 if (!(file = FILE_GetFile( hFile1 ))) return HFILE_ERROR32;
466 if (!PROCESS_SetObjPtr( hFile2, &file->header, 0 )) hFile2 = HFILE_ERROR32;
467 FILE_ReleaseFile( file );
472 /***********************************************************************
473 * GetTempFileName16 (KERNEL.97)
475 UINT16 GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
480 if ((drive & TF_FORCEDRIVE) &&
481 !DRIVE_IsValid( toupper(drive & ~TF_FORCEDRIVE) - 'A' ))
483 drive &= ~TF_FORCEDRIVE;
484 fprintf( stderr, "Warning: GetTempFileName: invalid drive %d specified\n",
488 if (drive & TF_FORCEDRIVE)
489 sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
492 GetTempPath32A( 132, temppath );
493 strcat( temppath, "\\" );
495 return (UINT16)GetTempFileName32A( temppath, prefix, unique, buffer );
499 /***********************************************************************
500 * GetTempFileName32A (KERNEL32.290)
502 UINT32 GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
505 DOS_FULL_NAME full_name;
508 UINT32 num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
511 strcpy( buffer, path );
512 p = buffer + strlen(buffer);
514 for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
515 sprintf( p, "%04x.tmp", num );
517 /* Now try to create it */
523 HFILE32 handle = FILE_Create( buffer, 0666, TRUE );
524 if (handle != INVALID_HANDLE_VALUE32)
525 { /* We created it */
526 dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer);
527 CloseHandle( handle );
530 if (DOS_ExtendedError != ER_FileExists)
531 break; /* No need to go on */
533 sprintf( p, "%04x.tmp", num );
534 } while (num != (unique & 0xffff));
537 /* Get the full path name */
539 if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
541 if (access( full_name.long_name, W_OK ) == -1)
543 "Warning: GetTempFileName returns '%s', which doesn't seem to be writeable.\n"
544 "Please check your configuration file if this generates a failure.\n",
547 dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
548 return unique ? unique : num;
552 /***********************************************************************
553 * GetTempFileName32W (KERNEL32.291)
555 UINT32 GetTempFileName32W( LPCWSTR path, LPCWSTR prefix, UINT32 unique,
563 patha = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
564 prefixa = HEAP_strdupWtoA( GetProcessHeap(), 0, prefix );
565 ret = GetTempFileName32A( patha, prefixa, unique, buffera );
566 lstrcpyAtoW( buffer, buffera );
567 HeapFree( GetProcessHeap(), 0, patha );
568 HeapFree( GetProcessHeap(), 0, prefixa );
573 /***********************************************************************
576 * Implementation of OpenFile16() and OpenFile32().
578 static HFILE32 FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT32 mode,
583 WORD filedatetime[2];
584 DOS_FULL_NAME full_name;
588 ofs->cBytes = sizeof(OFSTRUCT);
590 if (mode & OF_REOPEN) name = ofs->szPathName;
591 dprintf_file( stddeb, "OpenFile: %s %04x\n", name, mode );
593 /* OF_PARSE simply fills the structure */
597 if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
598 ofs->szPathName, NULL )) goto error;
599 ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' )
601 dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s'\n",
602 name, ofs->szPathName );
606 /* OF_CREATE is completely different from all other options, so
609 if (mode & OF_CREATE)
611 if ((hFileRet = FILE_Create(name,0666,FALSE))== INVALID_HANDLE_VALUE32)
613 GetFullPathName32A( name, sizeof(ofs->szPathName),
614 ofs->szPathName, NULL );
618 /* If OF_SEARCH is set, ignore the given path */
620 if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
622 /* First try the file name as is */
623 if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
624 /* Now remove the path */
625 if (name[0] && (name[1] == ':')) name += 2;
626 if ((p = strrchr( name, '\\' ))) name = p + 1;
627 if ((p = strrchr( name, '/' ))) name = p + 1;
628 if (!name[0]) goto not_found;
631 /* Now look for the file */
633 if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
636 dprintf_file( stddeb, "OpenFile: found %s = %s\n",
637 full_name.long_name, full_name.short_name );
638 lstrcpyn32A( ofs->szPathName, full_name.short_name,
639 sizeof(ofs->szPathName) );
641 if (mode & OF_DELETE)
643 if (unlink( full_name.long_name ) == -1) goto not_found;
644 dprintf_file( stddeb, "OpenFile(%s): OF_DELETE return = OK\n", name);
651 unixMode = O_WRONLY; break;
653 unixMode = O_RDWR; break;
656 unixMode = O_RDONLY; break;
659 hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
660 if (hFileRet == HFILE_ERROR32) goto not_found;
661 GetFileTime( hFileRet, NULL, NULL, &filetime );
662 FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
663 if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
665 if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) ))
667 CloseHandle( hFileRet );
668 dprintf_file( stddeb, "OpenFile(%s): OF_VERIFY failed\n", name );
669 /* FIXME: what error here? */
670 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
674 memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) );
676 success: /* We get here if the open was successful */
677 dprintf_file( stddeb, "OpenFile(%s): OK, return = %d\n", name, hFileRet );
678 if (mode & OF_EXIST) /* Return the handle, but close it first */
679 CloseHandle( hFileRet );
682 not_found: /* We get here if the file does not exist */
683 dprintf_file( stddeb, "OpenFile: '%s' not found\n", name );
684 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
687 error: /* We get here if there was an error opening the file */
688 ofs->nErrCode = DOS_ExtendedError;
689 dprintf_file( stddeb, "OpenFile(%s): return = HFILE_ERROR\n", name );
690 return HFILE_ERROR32;
694 /***********************************************************************
695 * OpenFile16 (KERNEL.74)
697 HFILE16 OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
699 return FILE_DoOpenFile( name, ofs, mode, FALSE );
703 /***********************************************************************
704 * OpenFile32 (KERNEL32.396)
706 HFILE32 OpenFile32( LPCSTR name, OFSTRUCT *ofs, UINT32 mode )
708 return FILE_DoOpenFile( name, ofs, mode, TRUE );
712 /***********************************************************************
713 * _lclose16 (KERNEL.81)
715 HFILE16 _lclose16( HFILE16 hFile )
717 dprintf_file( stddeb, "_lclose16: handle %d\n", hFile );
718 return CloseHandle( hFile ) ? 0 : HFILE_ERROR16;
722 /***********************************************************************
723 * _lclose32 (KERNEL32.592)
725 HFILE32 _lclose32( HFILE32 hFile )
727 dprintf_file( stddeb, "_lclose32: handle %d\n", hFile );
728 return CloseHandle( hFile ) ? 0 : HFILE_ERROR32;
732 /***********************************************************************
735 LONG WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
739 dprintf_file( stddeb, "_hread16: %d %08lx %ld\n",
740 hFile, (DWORD)buffer, count );
742 /* Some programs pass a count larger than the allocated buffer */
743 maxlen = GetSelectorLimit( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
744 if (count > maxlen) count = maxlen;
745 return _lread32( hFile, PTR_SEG_TO_LIN(buffer), count );
749 /***********************************************************************
752 UINT16 WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
754 return (UINT16)WIN16_hread( hFile, buffer, (LONG)count );
758 /***********************************************************************
759 * _lread32 (KERNEL32.596)
761 UINT32 _lread32( HFILE32 hFile, LPVOID buffer, UINT32 count )
766 dprintf_file( stddeb, "_lread32: %d %p %d\n", hFile, buffer, count );
767 if (!(file = FILE_GetFile( hFile ))) return -1;
768 if (!count) result = 0;
769 else if ((result = read( file->unix_handle, buffer, count )) == -1)
771 FILE_ReleaseFile( file );
776 /***********************************************************************
777 * _lread16 (KERNEL.82)
779 UINT16 _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
781 return (UINT16)_lread32( hFile, buffer, (LONG)count );
785 /***********************************************************************
786 * _lcreat16 (KERNEL.83)
788 HFILE16 _lcreat16( LPCSTR path, INT16 attr )
790 int mode = (attr & 1) ? 0444 : 0666;
791 dprintf_file( stddeb, "_lcreat16: %s %02x\n", path, attr );
792 return (HFILE16)FILE_Create( path, mode, FALSE );
796 /***********************************************************************
797 * _lcreat32 (KERNEL32.593)
799 HFILE32 _lcreat32( LPCSTR path, INT32 attr )
801 int mode = (attr & 1) ? 0444 : 0666;
802 dprintf_file( stddeb, "_lcreat32: %s %02x\n", path, attr );
803 return FILE_Create( path, mode, FALSE );
807 /***********************************************************************
808 * _lcreat_uniq (Not a Windows API)
810 HFILE32 _lcreat_uniq( LPCSTR path, INT32 attr )
812 int mode = (attr & 1) ? 0444 : 0666;
813 dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr );
814 return FILE_Create( path, mode, TRUE );
818 /***********************************************************************
819 * SetFilePointer (KERNEL32.492)
821 DWORD SetFilePointer( HFILE32 hFile, LONG distance, LONG *highword,
827 if (highword && *highword)
829 fprintf( stderr, "SetFilePointer: 64-bit offsets not supported yet\n");
830 SetLastError( ERROR_INVALID_PARAMETER );
833 dprintf_file( stddeb, "SetFilePointer: handle %d offset %ld origin %ld\n",
834 hFile, distance, method );
836 if (!(file = FILE_GetFile( hFile ))) return 0xffffffff;
839 case 1: origin = SEEK_CUR; break;
840 case 2: origin = SEEK_END; break;
841 default: origin = SEEK_SET; break;
844 if ((result = lseek( file->unix_handle, distance, origin )) == -1)
846 FILE_ReleaseFile( file );
847 return (DWORD)result;
851 /***********************************************************************
852 * _llseek16 (KERNEL.84)
854 LONG _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
856 return SetFilePointer( hFile, lOffset, NULL, nOrigin );
860 /***********************************************************************
861 * _llseek32 (KERNEL32.594)
863 LONG _llseek32( HFILE32 hFile, LONG lOffset, INT32 nOrigin )
865 return SetFilePointer( hFile, lOffset, NULL, nOrigin );
869 /***********************************************************************
870 * _lopen16 (KERNEL.85)
872 HFILE16 _lopen16( LPCSTR path, INT16 mode )
874 return _lopen32( path, mode );
878 /***********************************************************************
879 * _lopen32 (KERNEL32.595)
881 HFILE32 _lopen32( LPCSTR path, INT32 mode )
885 dprintf_file(stddeb, "_lopen('%s',%04x)\n", path, mode );
890 unixMode = O_WRONLY | O_TRUNC;
900 return FILE_Open( path, unixMode );
904 /***********************************************************************
905 * _lwrite16 (KERNEL.86)
907 UINT16 _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
909 return (UINT16)_hwrite32( hFile, buffer, (LONG)count );
912 /***********************************************************************
913 * _lwrite32 (KERNEL.86)
915 UINT32 _lwrite32( HFILE32 hFile, LPCSTR buffer, UINT32 count )
917 return (UINT32)_hwrite32( hFile, buffer, (LONG)count );
921 /***********************************************************************
922 * _hread16 (KERNEL.349)
924 LONG _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
926 return _lread32( hFile, buffer, count );
930 /***********************************************************************
931 * _hread32 (KERNEL32.590)
933 LONG _hread32( HFILE32 hFile, LPVOID buffer, LONG count)
935 return _lread32( hFile, buffer, count );
939 /***********************************************************************
940 * _hwrite16 (KERNEL.350)
942 LONG _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
944 return _hwrite32( hFile, buffer, count );
948 /***********************************************************************
949 * _hwrite32 (KERNEL32.591)
951 LONG _hwrite32( HFILE32 hFile, LPCSTR buffer, LONG count )
956 dprintf_file( stddeb, "_hwrite: %d %p %ld\n", hFile, buffer, count );
958 if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR32;
959 if (count == 0) /* Expand or truncate at current position */
960 result = ftruncate( file->unix_handle,
961 lseek( file->unix_handle, 0, SEEK_CUR ) );
963 result = write( file->unix_handle, buffer, count );
965 if (result == -1) FILE_SetDosError();
966 FILE_ReleaseFile( file );
971 /***********************************************************************
972 * SetHandleCount16 (KERNEL.199)
974 UINT16 SetHandleCount16( UINT16 count )
976 HGLOBAL16 hPDB = GetCurrentPDB();
977 PDB *pdb = (PDB *)GlobalLock16( hPDB );
978 BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
980 dprintf_file( stddeb, "SetHandleCount(%d)\n", count );
982 if (count < 20) count = 20; /* No point in going below 20 */
983 else if (count > 254) count = 254;
987 if (pdb->nbFiles > 20)
989 memcpy( pdb->fileHandles, files, 20 );
990 GlobalFree16( pdb->hFileHandles );
991 pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
992 GlobalHandleToSel( hPDB ) );
993 pdb->hFileHandles = 0;
997 else /* More than 20, need a new file handles table */
1000 HGLOBAL16 newhandle = GlobalAlloc16( GMEM_MOVEABLE, count );
1003 DOS_ERROR( ER_OutOfMemory, EC_OutOfResource, SA_Abort, EL_Memory );
1004 return pdb->nbFiles;
1006 newfiles = (BYTE *)GlobalLock16( newhandle );
1008 if (count > pdb->nbFiles)
1010 memcpy( newfiles, files, pdb->nbFiles );
1011 memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
1013 else memcpy( newfiles, files, count );
1014 if (pdb->nbFiles > 20) GlobalFree16( pdb->hFileHandles );
1015 pdb->fileHandlesPtr = WIN16_GlobalLock16( newhandle );
1016 pdb->hFileHandles = newhandle;
1017 pdb->nbFiles = count;
1019 return pdb->nbFiles;
1023 /*************************************************************************
1024 * SetHandleCount32 (KERNEL32.494)
1026 UINT32 SetHandleCount32( UINT32 count )
1028 return MIN( 256, count );
1032 /***********************************************************************
1033 * FlushFileBuffers (KERNEL32.133)
1035 BOOL32 FlushFileBuffers( HFILE32 hFile )
1040 dprintf_file( stddeb, "FlushFileBuffers(%d)\n", hFile );
1041 if (!(file = FILE_GetFile( hFile ))) return FALSE;
1042 if (fsync( file->unix_handle ) != -1) ret = TRUE;
1048 FILE_ReleaseFile( file );
1053 /**************************************************************************
1054 * SetEndOfFile (KERNEL32.483)
1056 BOOL32 SetEndOfFile( HFILE32 hFile )
1061 dprintf_file( stddeb, "SetEndOfFile(%d)\n", hFile );
1062 if (!(file = FILE_GetFile( hFile ))) return FALSE;
1063 if (ftruncate( file->unix_handle,
1064 lseek( file->unix_handle, 0, SEEK_CUR ) ))
1069 FILE_ReleaseFile( file );
1074 /***********************************************************************
1075 * DeleteFile16 (KERNEL.146)
1077 BOOL16 DeleteFile16( LPCSTR path )
1079 return DeleteFile32A( path );
1083 /***********************************************************************
1084 * DeleteFile32A (KERNEL32.71)
1086 BOOL32 DeleteFile32A( LPCSTR path )
1088 DOS_FULL_NAME full_name;
1089 const char *unixName;
1091 dprintf_file(stddeb, "DeleteFile: '%s'\n", path );
1093 if ((unixName = DOSFS_IsDevice( path )) != NULL)
1095 dprintf_file(stddeb, "DeleteFile: removing device '%s'!\n", unixName);
1096 DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
1100 if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
1101 if (unlink( full_name.long_name ) == -1)
1110 /***********************************************************************
1111 * DeleteFile32W (KERNEL32.72)
1113 BOOL32 DeleteFile32W( LPCWSTR path )
1115 LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
1116 BOOL32 ret = RemoveDirectory32A( xpath );
1117 HeapFree( GetProcessHeap(), 0, xpath );
1122 /***********************************************************************
1125 BOOL32 FILE_SetFileType( HFILE32 hFile, DWORD type )
1127 DOS_FILE *file = FILE_GetFile( hFile );
1128 if (!file) return FALSE;
1130 FILE_ReleaseFile( file );
1135 /***********************************************************************
1136 * GetFileType (KERNEL32.222)
1138 DWORD GetFileType( HFILE32 hFile )
1140 DOS_FILE *file = FILE_GetFile(hFile);
1141 if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
1142 FILE_ReleaseFile( file );
1147 /**************************************************************************
1148 * MoveFile32A (KERNEL32.387)
1150 BOOL32 MoveFile32A( LPCSTR fn1, LPCSTR fn2 )
1152 DOS_FULL_NAME full_name1, full_name2;
1154 dprintf_file( stddeb, "MoveFile32A(%s,%s)\n", fn1, fn2 );
1156 if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
1157 if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
1158 /* FIXME: should not replace an existing file */
1159 /* FIXME: should handle renaming across devices */
1160 if (rename( full_name1.long_name, full_name2.long_name ) == -1)
1169 /**************************************************************************
1170 * MoveFile32W (KERNEL32.390)
1172 BOOL32 MoveFile32W( LPCWSTR fn1, LPCWSTR fn2 )
1174 LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
1175 LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
1176 BOOL32 res = MoveFile32A( afn1, afn2 );
1177 HeapFree( GetProcessHeap(), 0, afn1 );
1178 HeapFree( GetProcessHeap(), 0, afn2 );
1183 /**************************************************************************
1184 * CopyFile32A (KERNEL32.36)
1186 BOOL32 CopyFile32A( LPCSTR source, LPCSTR dest, BOOL32 fail_if_exists )
1189 BY_HANDLE_FILE_INFORMATION info;
1195 if ((h1 = _lopen32( source, OF_READ )) == HFILE_ERROR32) return FALSE;
1196 if (!GetFileInformationByHandle( h1, &info ))
1201 mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
1202 if ((h2 = FILE_Create( dest, mode, fail_if_exists )) == HFILE_ERROR32)
1207 while ((count = _lread32( h2, buffer, sizeof(buffer) )) > 0)
1212 INT32 res = _lwrite32( h2, p, count );
1213 if (res <= 0) goto done;
1226 /**************************************************************************
1227 * CopyFile32W (KERNEL32.37)
1229 BOOL32 CopyFile32W( LPCWSTR source, LPCWSTR dest, BOOL32 fail_if_exists )
1231 LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
1232 LPSTR destA = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
1233 BOOL32 ret = CopyFile32A( sourceA, destA, fail_if_exists );
1234 HeapFree( GetProcessHeap(), 0, sourceA );
1235 HeapFree( GetProcessHeap(), 0, destA );
1240 /***********************************************************************
1241 * SetFileTime (KERNEL32.493)
1243 BOOL32 SetFileTime( HFILE32 hFile,
1244 const FILETIME *lpCreationTime,
1245 const FILETIME *lpLastAccessTime,
1246 const FILETIME *lpLastWriteTime )
1248 DOS_FILE *file = FILE_GetFile(hFile);
1249 struct utimbuf utimbuf;
1251 if (!file) return FILE_TYPE_UNKNOWN; /* FIXME: correct? */
1252 dprintf_file(stddeb,"SetFileTime(%s,%p,%p,%p)\n",
1258 if (lpLastAccessTime)
1259 utimbuf.actime = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
1261 utimbuf.actime = 0; /* FIXME */
1262 if (lpLastWriteTime)
1263 utimbuf.modtime = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
1265 utimbuf.modtime = 0; /* FIXME */
1266 if (-1==utime(file->unix_name,&utimbuf))
1268 FILE_ReleaseFile( file );
1272 FILE_ReleaseFile( file );