Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix raw_fallocate for Android and deal with unsupported filesystems. #2363

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 74 additions & 24 deletions io/include/pcl/io/low_level_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ typedef SSIZE_T ssize_t;
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/fcntl.h>
# include <cerrno>
#endif

namespace pcl
Expand Down Expand Up @@ -97,9 +98,15 @@ namespace pcl
return ::_write(fd, buffer, count);
}

inline int raw_fallocate(int fd, long len)
inline int raw_ftruncate(int fd, long length)
{
return ::_chsize(fd, len);
return ::_chsize(fd, length);
}

inline int raw_fallocate(int fd, long length)
{
// Doesn't actually allocate, but best we can do?
return raw_ftruncate(fd, length);
}
#else
inline int raw_open(const char * pathname, int flags, int mode)
Expand Down Expand Up @@ -132,32 +139,75 @@ namespace pcl
return ::write(fd, buffer, count);
}

# ifndef __APPLE__
inline int raw_fallocate(int fd, off_t len)
inline int raw_ftruncate(int fd, off_t length)
{
return ::posix_fallocate(fd, 0, len);
return ::ftruncate(fd, length);
}
# else
inline int raw_fallocate(int fd, off_t len)

# ifdef __APPLE__
inline int raw_fallocate(int fd, off_t length)
{
// OS X doesn't have posix_fallocate, but it has a fcntl that does the job.
// It may make the file too big though, so we truncate before returning.

// Try to allocate contiguous space first.
::fstore_t store = {F_ALLOCATEALL | F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len};
if (::fcntl(fd, F_PREALLOCATE, &store) < 0)
{
// Try fragmented if that failed.
store.fst_flags = F_ALLOCATEALL;
int ret = ::fcntl(fd, F_PREALLOCATE, &store);

// Bail if it still failed.
if (ret < 0) {
return ret;
}
}

// File could be larger than requested, so truncate.
return ::ftruncate(fd, len);
}
# endif // __APPLE__
::fstore_t store = {F_ALLOCATEALL | F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, length};
if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
return raw_ftruncate(fd, length);

// Try fragmented if it failed.
store.fst_flags = F_ALLOCATEALL;
if (::fcntl(fd, F_PREALLOCATE, &store) != -1)
return raw_ftruncate(fd, length);

// Fragmented also failed.
return -1;
}

# else // __APPLE__
inline int raw_fallocate(int fd, off_t length)
{
# ifdef ANDROID
// Android's libc doesn't have posix_fallocate.
if (::fallocate(fd, 0, 0, length) == 0)
return 0;
# else
// Conforming POSIX systems have posix_fallocate.
if (::posix_fallocate(fd, 0, length) == 0)
return 0;
# endif

// EINVAL should indicate an unsupported filesystem.
// All other errors are passed up.
if (errno != EINVAL)
return -1;

// Try to deal with unsupported filesystems by simply seeking + writing.
// This may not really allocate space, but the file size will be set.
// Writes to the mmapped file may still trigger SIGBUS errors later.

// Remember the old position and seek to the desired length.
off_t old_pos = raw_lseek(fd, 0, SEEK_CUR);
if (old_pos == -1)
return -1;
if (raw_lseek(fd, length - 1, SEEK_SET) == -1)
return -1;

// Write a single byte to resize the file.
char buffer = 0;
ssize_t written = raw_write(fd, &buffer, 1);

// Seek back to the old position.
if (raw_lseek(fd, old_pos, SEEK_SET) == -1)
return -1;

// Fail if we didn't write exactly one byte,
if (written != 1)
return -1;

return 0;
}
# endif // __APPLE
#endif // _WIN32

}
Expand Down