You've already forked linux-apfs-rw
mirror of
https://github.com/linux-apfs/linux-apfs-rw.git
synced 2026-05-01 15:01:34 -07:00
Ban writes to compressed files explicitly
The official implementation doesn't seem to truly support writes to compressed files: when it's attempted, the file gets decompressed transparently instead. I don't intend to that in this driver, unless someone actually requests it. Users can just make a decompressed copy of the file and replace the original. By mistake, truncating compressed files is currently allowed, but since compressed reads don't depend on the vfs-reported size, nothing seems to happen. Other writes fail, but the error code is confusing and there is no output on dmesg. Ban all writes explicitly, and explain the problem in the console. Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
This commit is contained in:
+18
@@ -521,11 +521,29 @@ static int apfs_compress_file_release(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t apfs_compress_file_write(struct file *filp, const char __user *buf, size_t size, loff_t *off)
|
||||
{
|
||||
struct apfs_compress_file_data *fd = filp->private_data;
|
||||
struct super_block *sb = fd->sb;
|
||||
|
||||
/*
|
||||
* The official implementation seems to transparently decompress files
|
||||
* when you write to them. Doing that atomically inside the kernel is
|
||||
* probably a chore, so for now I'll just leave it to the user to make
|
||||
* an uncompressed copy themselves and replace the original. I might
|
||||
* fix this in the future, but only if people complain (TODO).
|
||||
*/
|
||||
apfs_warn(sb, "writes to compressed files are not supported");
|
||||
apfs_warn(sb, "you can work with a copy of the file instead");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
const struct file_operations apfs_compress_file_operations = {
|
||||
.open = apfs_compress_file_open,
|
||||
.llseek = generic_file_llseek,
|
||||
.read = apfs_compress_file_read,
|
||||
.release = apfs_compress_file_release,
|
||||
.write = apfs_compress_file_write,
|
||||
};
|
||||
|
||||
int apfs_compress_get_size(struct inode *inode, loff_t *size)
|
||||
|
||||
@@ -1788,11 +1788,18 @@ int apfs_setattr(struct mnt_idmap *idmap,
|
||||
#endif
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct apfs_inode_info *ai = APFS_I(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct apfs_max_ops maxops;
|
||||
bool resizing = S_ISREG(inode->i_mode) && (iattr->ia_valid & ATTR_SIZE);
|
||||
int err;
|
||||
|
||||
if (resizing && (ai->i_bsd_flags & APFS_INOBSD_COMPRESSED)) {
|
||||
apfs_warn(sb, "resizing compressed files is not supported");
|
||||
apfs_warn(sb, "you can work with a copy of the file instead");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (resizing && iattr->ia_size > APFS_MAX_FILE_SIZE)
|
||||
return -EFBIG;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user