File indexing completed on 2024-05-19 03:56:19
0001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 0002 0003 SPDX-FileCopyrightText: 2010 Mozilla Foundation 0004 SPDX-FileContributor: Taras Glek <tglek@mozilla.com> 0005 0006 SPDX-License-Identifier: MPL-1.1 OR GPL-2.0-or-later OR LGPL-2.1-or-later 0007 */ 0008 0009 #ifndef POSIX_FALLOCATE_MAC_H 0010 #define POSIX_FALLOCATE_MAC_H 0011 0012 #include <fcntl.h> 0013 #include <sys/stat.h> 0014 #include <sys/types.h> 0015 #include <unistd.h> 0016 0017 // created from the OSX-specific code from Mozilla's mozilla::fallocation() function 0018 // of which the licensing information is copied above. 0019 // Adaptation (C) 2015,2016 R.J.V. Bertin 0020 0021 // From Linux `man posix_fallocate`: 0022 // DESCRIPTION 0023 // The function posix_fallocate() ensures that disk space is allocated for 0024 // the file referred to by the descriptor fd for the bytes in the range 0025 // starting at offset and continuing for len bytes. After a successful 0026 // call to posix_fallocate(), subsequent writes to bytes in the specified 0027 // range are guaranteed not to fail because of lack of disk space. 0028 // 0029 // If the size of the file is less than offset+len, then the file is 0030 // increased to this size; otherwise the file size is left unchanged. 0031 0032 // From OS X man fcntl: 0033 // F_PREALLOCATE Preallocate file storage space. Note: upon success, the space 0034 // that is allocated can be the same size or larger than the space 0035 // requested. 0036 // The F_PREALLOCATE command operates on the following structure: 0037 // typedef struct fstore { 0038 // u_int32_t fst_flags; /* IN: flags word */ 0039 // int fst_posmode; /* IN: indicates offset field */ 0040 // off_t fst_offset; /* IN: start of the region */ 0041 // off_t fst_length; /* IN: size of the region */ 0042 // off_t fst_bytesalloc; /* OUT: number of bytes allocated */ 0043 // } fstore_t; 0044 // The flags (fst_flags) for the F_PREALLOCATE command are as follows: 0045 // F_ALLOCATECONTIG Allocate contiguous space. 0046 // F_ALLOCATEALL Allocate all requested space or no space at all. 0047 // The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use 0048 // the offset field. The modes are as follows: 0049 // F_PEOFPOSMODE Allocate from the physical end of file. 0050 // F_VOLPOSMODE Allocate from the volume offset. 0051 0052 // From OS X man ftruncate: 0053 // DESCRIPTION 0054 // ftruncate() and truncate() cause the file named by path, or referenced by fildes, to 0055 // be truncated (or extended) to length bytes in size. If the file size exceeds length, 0056 // any extra data is discarded. If the file size is smaller than length, the file 0057 // extended and filled with zeros to the indicated length. The ftruncate() form requires 0058 // the file to be open for writing. 0059 // Note: ftruncate() and truncate() do not modify the current file offset for any open 0060 // file descriptions associated with the file. 0061 0062 static int posix_fallocate(int fd, off_t offset, off_t len) 0063 { 0064 off_t c_test; 0065 int ret; 0066 if (!__builtin_saddll_overflow(offset, len, &c_test)) { 0067 fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, offset + len, 0}; 0068 // Try to get a continuous chunk of disk space 0069 ret = fcntl(fd, F_PREALLOCATE, &store); 0070 if (ret < 0) { 0071 // OK, perhaps we are too fragmented, allocate non-continuous 0072 store.fst_flags = F_ALLOCATEALL; 0073 ret = fcntl(fd, F_PREALLOCATE, &store); 0074 if (ret < 0) { 0075 return ret; 0076 } 0077 } 0078 ret = ftruncate(fd, offset + len); 0079 } else { 0080 // offset+len would overflow. 0081 ret = -1; 0082 } 0083 return ret; 0084 } 0085 0086 #endif