fallocate.cpp 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /*
  2. * Copyright (c) 2022, Leon Albrecht <leon.a@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Checked.h>
  7. #include <Kernel/FileSystem/Inode.h>
  8. #include <Kernel/FileSystem/InodeFile.h>
  9. #include <Kernel/FileSystem/OpenFileDescription.h>
  10. #include <Kernel/Process.h>
  11. namespace Kernel {
  12. // https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
  13. ErrorOr<FlatPtr> Process::sys$posix_fallocate(int fd, Userspace<off_t const*> userspace_offset, Userspace<off_t const*> userspace_length)
  14. {
  15. VERIFY_NO_PROCESS_BIG_LOCK(this);
  16. TRY(require_promise(Pledge::stdio));
  17. // [EINVAL] The len argument is less than zero, or the offset argument is less than zero, or the underlying file system does not support this operation.
  18. auto offset = TRY(copy_typed_from_user(userspace_offset));
  19. if (offset < 0)
  20. return EINVAL;
  21. auto length = TRY(copy_typed_from_user(userspace_length));
  22. if (length <= 0)
  23. return EINVAL;
  24. Checked<size_t> checked_size { length };
  25. checked_size += offset;
  26. // FIXME: Return EFBIG if offset+length > FileSizeMax
  27. if (checked_size.has_overflow())
  28. return EFBIG;
  29. auto description = TRY(open_file_description(fd));
  30. // [EBADF] The fd argument references a file that was opened without write permission.
  31. if (!description->is_writable())
  32. return EBADF;
  33. // [ESPIPE] The fd argument is associated with a pipe or FIFO.
  34. if (description->is_fifo())
  35. return ESPIPE;
  36. // [ENODEV] The fd argument does not refer to a regular file.
  37. if (!description->file().is_regular_file())
  38. return ENODEV;
  39. VERIFY(description->file().is_inode());
  40. auto& file = static_cast<InodeFile&>(description->file());
  41. if (file.inode().size() >= checked_size.value())
  42. return 0;
  43. // Note: truncate essentially calls resize in the inodes implementation
  44. // while resize is not a standard member of an inode, so we just call
  45. // truncate instead
  46. TRY(file.inode().truncate(checked_size.value()));
  47. // FIXME: EINTR: A signal was caught during execution.
  48. return 0;
  49. }
  50. }