VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp@ 40517

Last change on this file since 40517 was 39627, checked in by vboxsync, 13 years ago

backed out previous changeset

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.1 KB
Line 
1/* $Id: fileio-posix.cpp 39627 2011-12-15 11:44:19Z vboxsync $ */
2/** @file
3 * IPRT - File I/O, POSIX, Part 1.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_FILE
32
33#include <errno.h>
34#include <sys/stat.h>
35#include <sys/types.h>
36#include <sys/ioctl.h>
37#include <sys/fcntl.h>
38#include <fcntl.h>
39#ifdef _MSC_VER
40# include <io.h>
41# include <stdio.h>
42#else
43# include <unistd.h>
44# include <sys/time.h>
45#endif
46#ifdef RT_OS_LINUX
47# include <sys/file.h>
48#endif
49#if defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006)
50# include <io.h>
51#endif
52#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
53# include <sys/disk.h>
54#endif
55#ifdef RT_OS_SOLARIS
56# include <stropts.h>
57# include <sys/dkio.h>
58# include <sys/vtoc.h>
59#endif /* RT_OS_SOLARIS */
60
61#include <iprt/file.h>
62#include <iprt/path.h>
63#include <iprt/assert.h>
64#include <iprt/string.h>
65#include <iprt/err.h>
66#include <iprt/log.h>
67#include "internal/file.h"
68#include "internal/fs.h"
69#include "internal/path.h"
70
71
72
73/*******************************************************************************
74* Defined Constants And Macros *
75*******************************************************************************/
76/** Default file permissions for newly created files. */
77#if defined(S_IRUSR) && defined(S_IWUSR)
78# define RT_FILE_PERMISSION (S_IRUSR | S_IWUSR)
79#else
80# define RT_FILE_PERMISSION (00600)
81#endif
82
83
84RTDECL(bool) RTFileExists(const char *pszPath)
85{
86 bool fRc = false;
87 char const *pszNativePath;
88 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
89 if (RT_SUCCESS(rc))
90 {
91 struct stat s;
92 fRc = !stat(pszNativePath, &s)
93 && S_ISREG(s.st_mode);
94
95 rtPathFreeNative(pszNativePath, pszPath);
96 }
97
98 LogFlow(("RTFileExists(%p={%s}): returns %RTbool\n", pszPath, pszPath, fRc));
99 return fRc;
100}
101
102
103RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen)
104{
105 /*
106 * Validate input.
107 */
108 AssertPtrReturn(pFile, VERR_INVALID_POINTER);
109 *pFile = NIL_RTFILE;
110 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
111
112 /*
113 * Merge forced open flags and validate them.
114 */
115 int rc = rtFileRecalcAndValidateFlags(&fOpen);
116 if (RT_FAILURE(rc))
117 return rc;
118#ifndef O_NONBLOCK
119 if (fOpen & RTFILE_O_NON_BLOCK)
120 {
121 AssertMsgFailed(("Invalid parameters! fOpen=%#llx\n", fOpen));
122 return VERR_INVALID_PARAMETER;
123 }
124#endif
125
126 /*
127 * Calculate open mode flags.
128 */
129 int fOpenMode = 0;
130#ifdef O_BINARY
131 fOpenMode |= O_BINARY; /* (pc) */
132#endif
133#ifdef O_LARGEFILE
134 fOpenMode |= O_LARGEFILE; /* (linux, solaris) */
135#endif
136#ifdef O_NOINHERIT
137 if (!(fOpen & RTFILE_O_INHERIT))
138 fOpenMode |= O_NOINHERIT;
139#endif
140#ifdef O_CLOEXEC
141 static int s_fHave_O_CLOEXEC = 0; /* {-1,0,1}; since Linux 2.6.23 */
142 if (!(fOpen & RTFILE_O_INHERIT) && s_fHave_O_CLOEXEC >= 0)
143 fOpenMode |= O_CLOEXEC;
144#endif
145#ifdef O_NONBLOCK
146 if (fOpen & RTFILE_O_NON_BLOCK)
147 fOpenMode |= O_NONBLOCK;
148#endif
149#ifdef O_SYNC
150 if (fOpen & RTFILE_O_WRITE_THROUGH)
151 fOpenMode |= O_SYNC;
152#endif
153#if defined(O_DIRECT) && defined(RT_OS_LINUX)
154 /* O_DIRECT is mandatory to get async I/O working on Linux. */
155 if (fOpen & RTFILE_O_ASYNC_IO)
156 fOpenMode |= O_DIRECT;
157#endif
158#if defined(O_DIRECT) && (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD))
159 /* Disable the kernel cache. */
160 if (fOpen & RTFILE_O_NO_CACHE)
161 fOpenMode |= O_DIRECT;
162#endif
163
164 /* create/truncate file */
165 switch (fOpen & RTFILE_O_ACTION_MASK)
166 {
167 case RTFILE_O_OPEN: break;
168 case RTFILE_O_OPEN_CREATE: fOpenMode |= O_CREAT; break;
169 case RTFILE_O_CREATE: fOpenMode |= O_CREAT | O_EXCL; break;
170 case RTFILE_O_CREATE_REPLACE: fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */
171 }
172 if (fOpen & RTFILE_O_TRUNCATE)
173 fOpenMode |= O_TRUNC;
174
175 switch (fOpen & RTFILE_O_ACCESS_MASK)
176 {
177 case RTFILE_O_READ:
178 fOpenMode |= O_RDONLY; /* RTFILE_O_APPEND is ignored. */
179 break;
180 case RTFILE_O_WRITE:
181 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_WRONLY : O_WRONLY;
182 break;
183 case RTFILE_O_READWRITE:
184 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | O_RDWR : O_RDWR;
185 break;
186 default:
187 AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#llx\n", fOpen));
188 return VERR_INVALID_PARAMETER;
189 }
190
191 /* File mode. */
192 int fMode = (fOpen & RTFILE_O_CREATE_MODE_MASK)
193 ? (fOpen & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT
194 : RT_FILE_PERMISSION;
195
196 /** @todo sharing! */
197
198 /*
199 * Open/create the file.
200 */
201 char const *pszNativeFilename;
202 rc = rtPathToNative(&pszNativeFilename, pszFilename, NULL);
203 if (RT_FAILURE(rc))
204 return (rc);
205
206 int fh = open(pszNativeFilename, fOpenMode, fMode);
207 int iErr = errno;
208
209#ifdef O_CLOEXEC
210 if ( (fOpenMode & O_CLOEXEC)
211 && s_fHave_O_CLOEXEC == 0)
212 {
213 if (fh < 0 && iErr == EINVAL)
214 {
215 s_fHave_O_CLOEXEC = -1;
216 fh = open(pszNativeFilename, fOpenMode, fMode);
217 iErr = errno;
218 }
219 else if (fh >= 0)
220 s_fHave_O_CLOEXEC = fcntl(fh, F_GETFD, 0) > 0 ? 1 : -1;
221 }
222#endif
223
224 rtPathFreeNative(pszNativeFilename, pszFilename);
225 if (fh >= 0)
226 {
227 iErr = 0;
228
229 /*
230 * Mark the file handle close on exec, unless inherit is specified.
231 */
232 if ( !(fOpen & RTFILE_O_INHERIT)
233#ifdef O_NOINHERIT
234 && !(fOpenMode & O_NOINHERIT) /* Take care since it might be a zero value dummy. */
235#endif
236#ifdef O_CLOEXEC
237 && s_fHave_O_CLOEXEC <= 0
238#endif
239 )
240 iErr = fcntl(fh, F_SETFD, FD_CLOEXEC) >= 0 ? 0 : errno;
241
242 /*
243 * Switch direct I/O on now if requested and required.
244 */
245#if defined(RT_OS_DARWIN) \
246 || (defined(RT_OS_SOLARIS) && !defined(IN_GUEST))
247 if (iErr == 0 && (fOpen & RTFILE_O_NO_CACHE))
248 {
249# if defined(RT_OS_DARWIN)
250 iErr = fcntl(fh, F_NOCACHE, 1) >= 0 ? 0 : errno;
251# else
252 iErr = directio(fh, DIRECTIO_ON) >= 0 ? 0 : errno;
253# endif
254 }
255#endif
256
257 /*
258 * Implement / emulate file sharing.
259 *
260 * We need another mode which allows skipping this stuff completely
261 * and do things the UNIX way. So for the present this is just a debug
262 * aid that can be enabled by developers too lazy to test on Windows.
263 */
264#if 0 && defined(RT_OS_LINUX)
265 if (iErr == 0)
266 {
267 /* This approach doesn't work because only knfsd checks for these
268 buggers. :-( */
269 int iLockOp;
270 switch (fOpen & RTFILE_O_DENY_MASK)
271 {
272 default:
273 AssertFailed();
274 case RTFILE_O_DENY_NONE:
275 case RTFILE_O_DENY_NOT_DELETE:
276 iLockOp = LOCK_MAND | LOCK_READ | LOCK_WRITE;
277 break;
278 case RTFILE_O_DENY_READ:
279 case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
280 iLockOp = LOCK_MAND | LOCK_WRITE;
281 break;
282 case RTFILE_O_DENY_WRITE:
283 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
284 iLockOp = LOCK_MAND | LOCK_READ;
285 break;
286 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
287 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
288 iLockOp = LOCK_MAND;
289 break;
290 }
291 iErr = flock(fh, iLockOp | LOCK_NB);
292 if (iErr != 0)
293 iErr = errno == EAGAIN ? ETXTBSY : 0;
294 }
295#endif /* 0 && RT_OS_LINUX */
296#if defined(DEBUG_bird) && !defined(RT_OS_SOLARIS)
297 if (iErr == 0)
298 {
299 /* This emulation is incomplete but useful. */
300 switch (fOpen & RTFILE_O_DENY_MASK)
301 {
302 default:
303 AssertFailed();
304 case RTFILE_O_DENY_NONE:
305 case RTFILE_O_DENY_NOT_DELETE:
306 case RTFILE_O_DENY_READ:
307 case RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
308 break;
309 case RTFILE_O_DENY_WRITE:
310 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_NOT_DELETE:
311 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ:
312 case RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ | RTFILE_O_DENY_NOT_DELETE:
313 if (fOpen & RTFILE_O_WRITE)
314 {
315 iErr = flock(fh, LOCK_EX | LOCK_NB);
316 if (iErr != 0)
317 iErr = errno == EAGAIN ? ETXTBSY : 0;
318 }
319 break;
320 }
321 }
322#endif
323#ifdef RT_OS_SOLARIS
324 /** @todo Use fshare_t and associates, it's a perfect match. see sys/fcntl.h */
325#endif
326
327 /*
328 * We're done.
329 */
330 if (iErr == 0)
331 {
332 *pFile = (RTFILE)(uintptr_t)fh;
333 Assert((intptr_t)*pFile == fh);
334 LogFlow(("RTFileOpen(%p:{%RTfile}, %p:{%s}, %#llx): returns %Rrc\n",
335 pFile, *pFile, pszFilename, pszFilename, fOpen, rc));
336 return VINF_SUCCESS;
337 }
338
339 close(fh);
340 }
341 return RTErrConvertFromErrno(iErr);
342}
343
344
345RTR3DECL(int) RTFileOpenBitBucket(PRTFILE phFile, uint64_t fAccess)
346{
347 AssertReturn( fAccess == RTFILE_O_READ
348 || fAccess == RTFILE_O_WRITE
349 || fAccess == RTFILE_O_READWRITE,
350 VERR_INVALID_PARAMETER);
351 return RTFileOpen(phFile, "/dev/null", fAccess | RTFILE_O_DENY_NONE | RTFILE_O_OPEN);
352}
353
354
355RTR3DECL(int) RTFileClose(RTFILE hFile)
356{
357 if (hFile == NIL_RTFILE)
358 return VINF_SUCCESS;
359 if (close(RTFileToNative(hFile)) == 0)
360 return VINF_SUCCESS;
361 return RTErrConvertFromErrno(errno);
362}
363
364
365RTR3DECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative)
366{
367 AssertCompile(sizeof(uNative) == sizeof(*pFile));
368 if (uNative < 0)
369 {
370 AssertMsgFailed(("%p\n", uNative));
371 *pFile = NIL_RTFILE;
372 return VERR_INVALID_HANDLE;
373 }
374 *pFile = (RTFILE)uNative;
375 return VINF_SUCCESS;
376}
377
378
379RTR3DECL(RTHCINTPTR) RTFileToNative(RTFILE hFile)
380{
381 AssertReturn(hFile != NIL_RTFILE, -1);
382 return (intptr_t)hFile;
383}
384
385
386RTFILE rtFileGetStandard(RTHANDLESTD enmStdHandle)
387{
388 int fd;
389 switch (enmStdHandle)
390 {
391 case RTHANDLESTD_INPUT: fd = 0; break;
392 case RTHANDLESTD_OUTPUT: fd = 1; break;
393 case RTHANDLESTD_ERROR: fd = 2; break;
394 break;
395 default:
396 AssertFailedReturn(NIL_RTFILE);
397 }
398
399 struct stat st;
400 int rc = fstat(fd, &st);
401 if (rc == -1)
402 return NIL_RTFILE;
403 return (RTFILE)(intptr_t)fd;
404}
405
406
407RTR3DECL(int) RTFileDelete(const char *pszFilename)
408{
409 char const *pszNativeFilename;
410 int rc = rtPathToNative(&pszNativeFilename, pszFilename, NULL);
411 if (RT_SUCCESS(rc))
412 {
413 if (unlink(pszNativeFilename) != 0)
414 rc = RTErrConvertFromErrno(errno);
415 rtPathFreeNative(pszNativeFilename, pszFilename);
416 }
417 return rc;
418}
419
420
421RTR3DECL(int) RTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
422{
423 static const unsigned aSeekRecode[] =
424 {
425 SEEK_SET,
426 SEEK_CUR,
427 SEEK_END,
428 };
429
430 /*
431 * Validate input.
432 */
433 if (uMethod > RTFILE_SEEK_END)
434 {
435 AssertMsgFailed(("Invalid uMethod=%d\n", uMethod));
436 return VERR_INVALID_PARAMETER;
437 }
438
439 /* check that within off_t range. */
440 if ( sizeof(off_t) < sizeof(offSeek)
441 && ( (offSeek > 0 && (unsigned)(offSeek >> 32) != 0)
442 || (offSeek < 0 && (unsigned)(-offSeek >> 32) != 0)))
443 {
444 AssertMsgFailed(("64-bit search not supported\n"));
445 return VERR_NOT_SUPPORTED;
446 }
447
448 off_t offCurrent = lseek(RTFileToNative(hFile), (off_t)offSeek, aSeekRecode[uMethod]);
449 if (offCurrent != ~0)
450 {
451 if (poffActual)
452 *poffActual = (uint64_t)offCurrent;
453 return VINF_SUCCESS;
454 }
455 return RTErrConvertFromErrno(errno);
456}
457
458
459RTR3DECL(int) RTFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
460{
461 if (cbToRead <= 0)
462 return VINF_SUCCESS;
463
464 /*
465 * Attempt read.
466 */
467 ssize_t cbRead = read(RTFileToNative(hFile), pvBuf, cbToRead);
468 if (cbRead >= 0)
469 {
470 if (pcbRead)
471 /* caller can handle partial read. */
472 *pcbRead = cbRead;
473 else
474 {
475 /* Caller expects all to be read. */
476 while ((ssize_t)cbToRead > cbRead)
477 {
478 ssize_t cbReadPart = read(RTFileToNative(hFile), (char*)pvBuf + cbRead, cbToRead - cbRead);
479 if (cbReadPart <= 0)
480 {
481 if (cbReadPart == 0)
482 return VERR_EOF;
483 return RTErrConvertFromErrno(errno);
484 }
485 cbRead += cbReadPart;
486 }
487 }
488 return VINF_SUCCESS;
489 }
490
491 return RTErrConvertFromErrno(errno);
492}
493
494
495RTR3DECL(int) RTFileWrite(RTFILE hFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
496{
497 if (cbToWrite <= 0)
498 return VINF_SUCCESS;
499
500 /*
501 * Attempt write.
502 */
503 ssize_t cbWritten = write(RTFileToNative(hFile), pvBuf, cbToWrite);
504 if (cbWritten >= 0)
505 {
506 if (pcbWritten)
507 /* caller can handle partial write. */
508 *pcbWritten = cbWritten;
509 else
510 {
511 /* Caller expects all to be write. */
512 while ((ssize_t)cbToWrite > cbWritten)
513 {
514 ssize_t cbWrittenPart = write(RTFileToNative(hFile), (const char *)pvBuf + cbWritten, cbToWrite - cbWritten);
515 if (cbWrittenPart <= 0)
516 return RTErrConvertFromErrno(errno);
517 cbWritten += cbWrittenPart;
518 }
519 }
520 return VINF_SUCCESS;
521 }
522 return RTErrConvertFromErrno(errno);
523}
524
525
526RTR3DECL(int) RTFileSetSize(RTFILE hFile, uint64_t cbSize)
527{
528 /*
529 * Validate offset.
530 */
531 if ( sizeof(off_t) < sizeof(cbSize)
532 && (cbSize >> 32) != 0)
533 {
534 AssertMsgFailed(("64-bit filesize not supported! cbSize=%lld\n", cbSize));
535 return VERR_NOT_SUPPORTED;
536 }
537
538#if defined(_MSC_VER) || (defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006))
539 if (chsize(RTFileToNative(hFile), (off_t)cbSize) == 0)
540#else
541 /* This relies on a non-standard feature of FreeBSD, Linux, and OS/2
542 * LIBC v0.6 and higher. (SuS doesn't define ftruncate() and size bigger
543 * than the file.)
544 */
545 if (ftruncate(RTFileToNative(hFile), (off_t)cbSize) == 0)
546#endif
547 return VINF_SUCCESS;
548 return RTErrConvertFromErrno(errno);
549}
550
551
552RTR3DECL(int) RTFileGetSize(RTFILE hFile, uint64_t *pcbSize)
553{
554 /*
555 * Ask fstat() first.
556 */
557 struct stat st;
558 if (!fstat(RTFileToNative(hFile), &st))
559 {
560 *pcbSize = st.st_size;
561 if ( st.st_size != 0
562#if defined(RT_OS_SOLARIS)
563 || (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
564#elif defined(RT_OS_FREEBSD)
565 || !S_ISCHR(st.st_mode)
566#else
567 || !S_ISBLK(st.st_mode)
568#endif
569 )
570 return VINF_SUCCESS;
571
572 /*
573 * It could be a block device. Try determin the size by I/O control
574 * query or seek.
575 */
576#ifdef RT_OS_DARWIN
577 uint64_t cBlocks;
578 if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKCOUNT, &cBlocks))
579 {
580 uint32_t cbBlock;
581 if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKSIZE, &cbBlock))
582 {
583 *pcbSize = cBlocks * cbBlock;
584 return VINF_SUCCESS;
585 }
586 }
587 /* must be a block device, fail on failure. */
588
589#elif defined(RT_OS_SOLARIS)
590 struct dk_minfo MediaInfo;
591 if (!ioctl(RTFileToNative(hFile), DKIOCGMEDIAINFO, &MediaInfo))
592 {
593 *pcbSize = MediaInfo.dki_capacity * MediaInfo.dki_lbsize;
594 return VINF_SUCCESS;
595 }
596 /* might not be a block device. */
597 if (errno == EINVAL || errno == ENOTTY)
598 return VINF_SUCCESS;
599
600#elif defined(RT_OS_FREEBSD)
601 off_t cbMedia = 0;
602 if (!ioctl(RTFileToNative(hFile), DIOCGMEDIASIZE, &cbMedia))
603 {
604 *pcbSize = cbMedia;
605 return VINF_SUCCESS;
606 }
607 /* might not be a block device. */
608 if (errno == EINVAL || errno == ENOTTY)
609 return VINF_SUCCESS;
610
611#else
612 /* PORTME! Avoid this path when possible. */
613 uint64_t offSaved;
614 int rc = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offSaved);
615 if (RT_SUCCESS(rc))
616 {
617 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, pcbSize);
618 int rc2 = RTFileSeek(hFile, offSaved, RTFILE_SEEK_BEGIN, NULL);
619 if (RT_SUCCESS(rc))
620 return rc2;
621 }
622#endif
623 }
624 return RTErrConvertFromErrno(errno);
625}
626
627
628RTR3DECL(int) RTFileGetMaxSizeEx(RTFILE hFile, PRTFOFF pcbMax)
629{
630 /*
631 * Save the current location
632 */
633 uint64_t offOld;
634 int rc = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offOld);
635 if (RT_FAILURE(rc))
636 return rc;
637
638 /*
639 * Perform a binary search for the max file size.
640 */
641 uint64_t offLow = 0;
642 uint64_t offHigh = 8 * _1T; /* we don't need bigger files */
643 /** @todo Unfortunately this does not work for certain file system types,
644 * for instance cifs mounts. Even worse, statvfs.f_fsid returns 0 for such
645 * file systems. */
646 //uint64_t offHigh = INT64_MAX;
647 for (;;)
648 {
649 uint64_t cbInterval = (offHigh - offLow) >> 1;
650 if (cbInterval == 0)
651 {
652 if (pcbMax)
653 *pcbMax = offLow;
654 return RTFileSeek(hFile, offOld, RTFILE_SEEK_BEGIN, NULL);
655 }
656
657 rc = RTFileSeek(hFile, offLow + cbInterval, RTFILE_SEEK_BEGIN, NULL);
658 if (RT_FAILURE(rc))
659 offHigh = offLow + cbInterval;
660 else
661 offLow = offLow + cbInterval;
662 }
663}
664
665
666RTR3DECL(bool) RTFileIsValid(RTFILE hFile)
667{
668 if (hFile != NIL_RTFILE)
669 {
670 int fFlags = fcntl(RTFileToNative(hFile), F_GETFD);
671 if (fFlags >= 0)
672 return true;
673 }
674 return false;
675}
676
677
678RTR3DECL(int) RTFileFlush(RTFILE hFile)
679{
680 if (fsync(RTFileToNative(hFile)))
681 return RTErrConvertFromErrno(errno);
682 return VINF_SUCCESS;
683}
684
685
686RTR3DECL(int) RTFileIoCtl(RTFILE hFile, unsigned long ulRequest, void *pvData, unsigned cbData, int *piRet)
687{
688 NOREF(cbData);
689 int rc = ioctl(RTFileToNative(hFile), ulRequest, pvData);
690 if (piRet)
691 *piRet = rc;
692 return rc >= 0 ? VINF_SUCCESS : RTErrConvertFromErrno(errno);
693}
694
695
696RTR3DECL(int) RTFileSetMode(RTFILE hFile, RTFMODE fMode)
697{
698 /*
699 * Normalize the mode and call the API.
700 */
701 fMode = rtFsModeNormalize(fMode, NULL, 0);
702 if (!rtFsModeIsValid(fMode))
703 return VERR_INVALID_PARAMETER;
704
705 if (fchmod(RTFileToNative(hFile), fMode & RTFS_UNIX_MASK))
706 {
707 int rc = RTErrConvertFromErrno(errno);
708 Log(("RTFileSetMode(%RTfile,%RTfmode): returns %Rrc\n", hFile, fMode, rc));
709 return rc;
710 }
711 return VINF_SUCCESS;
712}
713
714
715RTR3DECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename)
716{
717 /*
718 * Validate input.
719 */
720 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
721 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
722 AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);
723 AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);
724 AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
725
726 /*
727 * Take common cause with RTPathRename.
728 */
729 int rc = rtPathPosixRename(pszSrc, pszDst, fRename, RTFS_TYPE_FILE);
730
731 LogFlow(("RTDirRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n",
732 pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
733 return rc;
734}
735
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette