Merge tag 'affs-for-5.9-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull affs fix from David Sterba: "One fix to make permissions work the same way as on AmigaOS" * tag 'affs-for-5.9-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: affs: fix basic permission bits to actually work
This commit is contained in:
@@ -110,13 +110,15 @@ The Amiga protection flags RWEDRWEDHSPARWED are handled as follows:
|
||||
|
||||
- R maps to r for user, group and others. On directories, R implies x.
|
||||
|
||||
- If both W and D are allowed, w will be set.
|
||||
- W maps to w.
|
||||
|
||||
- E maps to x.
|
||||
|
||||
- H and P are always retained and ignored under Linux.
|
||||
- D is ignored.
|
||||
|
||||
- A is always reset when a file is written to.
|
||||
- H, S and P are always retained and ignored under Linux.
|
||||
|
||||
- A is cleared when a file is written to.
|
||||
|
||||
User id and group id will be used unless set[gu]id are given as mount
|
||||
options. Since most of the Amiga file systems are single user systems
|
||||
@@ -128,11 +130,13 @@ Linux -> Amiga:
|
||||
|
||||
The Linux rwxrwxrwx file mode is handled as follows:
|
||||
|
||||
- r permission will set R for user, group and others.
|
||||
- r permission will allow R for user, group and others.
|
||||
|
||||
- w permission will set W and D for user, group and others.
|
||||
- w permission will allow W for user, group and others.
|
||||
|
||||
- x permission of the user will set E for plain files.
|
||||
- x permission of the user will allow E for plain files.
|
||||
|
||||
- D will be allowed for user, group and others.
|
||||
|
||||
- All other flags (suid, sgid, ...) are ignored and will
|
||||
not be retained.
|
||||
|
||||
@@ -420,24 +420,51 @@ affs_mode_to_prot(struct inode *inode)
|
||||
u32 prot = AFFS_I(inode)->i_protect;
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
/*
|
||||
* First, clear all RWED bits for owner, group, other.
|
||||
* Then, recalculate them afresh.
|
||||
*
|
||||
* We'll always clear the delete-inhibit bit for the owner, as that is
|
||||
* the classic single-user mode AmigaOS protection bit and we need to
|
||||
* stay compatible with all scenarios.
|
||||
*
|
||||
* Since multi-user AmigaOS is an extension, we'll only set the
|
||||
* delete-allow bit if any of the other bits in the same user class
|
||||
* (group/other) are used.
|
||||
*/
|
||||
prot &= ~(FIBF_NOEXECUTE | FIBF_NOREAD
|
||||
| FIBF_NOWRITE | FIBF_NODELETE
|
||||
| FIBF_GRP_EXECUTE | FIBF_GRP_READ
|
||||
| FIBF_GRP_WRITE | FIBF_GRP_DELETE
|
||||
| FIBF_OTR_EXECUTE | FIBF_OTR_READ
|
||||
| FIBF_OTR_WRITE | FIBF_OTR_DELETE);
|
||||
|
||||
/* Classic single-user AmigaOS flags. These are inverted. */
|
||||
if (!(mode & 0100))
|
||||
prot |= FIBF_NOEXECUTE;
|
||||
if (!(mode & 0400))
|
||||
prot |= FIBF_NOREAD;
|
||||
if (!(mode & 0200))
|
||||
prot |= FIBF_NOWRITE;
|
||||
|
||||
/* Multi-user extended flags. Not inverted. */
|
||||
if (mode & 0010)
|
||||
prot |= FIBF_GRP_EXECUTE;
|
||||
if (mode & 0040)
|
||||
prot |= FIBF_GRP_READ;
|
||||
if (mode & 0020)
|
||||
prot |= FIBF_GRP_WRITE;
|
||||
if (mode & 0070)
|
||||
prot |= FIBF_GRP_DELETE;
|
||||
|
||||
if (mode & 0001)
|
||||
prot |= FIBF_OTR_EXECUTE;
|
||||
if (mode & 0004)
|
||||
prot |= FIBF_OTR_READ;
|
||||
if (mode & 0002)
|
||||
prot |= FIBF_OTR_WRITE;
|
||||
if (mode & 0007)
|
||||
prot |= FIBF_OTR_DELETE;
|
||||
|
||||
AFFS_I(inode)->i_protect = prot;
|
||||
}
|
||||
|
||||
@@ -429,6 +429,24 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int affs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned int len, unsigned int copied,
|
||||
struct page *page, void *fsdata)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
int ret;
|
||||
|
||||
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
|
||||
|
||||
/* Clear Archived bit on file writes, as AmigaOS would do */
|
||||
if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
|
||||
AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
|
||||
{
|
||||
return generic_block_bmap(mapping,block,affs_get_block);
|
||||
@@ -438,7 +456,7 @@ const struct address_space_operations affs_aops = {
|
||||
.readpage = affs_readpage,
|
||||
.writepage = affs_writepage,
|
||||
.write_begin = affs_write_begin,
|
||||
.write_end = generic_write_end,
|
||||
.write_end = affs_write_end,
|
||||
.direct_IO = affs_direct_IO,
|
||||
.bmap = _affs_bmap
|
||||
};
|
||||
@@ -795,6 +813,12 @@ done:
|
||||
if (tmp > inode->i_size)
|
||||
inode->i_size = AFFS_I(inode)->mmu_private = tmp;
|
||||
|
||||
/* Clear Archived bit on file writes, as AmigaOS would do */
|
||||
if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
|
||||
AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
|
||||
err_first_bh:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
Reference in New Issue
Block a user