On 19.11.19 г. 9:10 ч., Namjae Jeon wrote: > This adds the implementation of file operations for exfat. > > Signed-off-by: Namjae Jeon <namjae.jeon@xxxxxxxxxxx> > Signed-off-by: Sungjong Seo <sj1557.seo@xxxxxxxxxxx> > --- > fs/exfat/file.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 346 insertions(+) > create mode 100644 fs/exfat/file.c > > diff --git a/fs/exfat/file.c b/fs/exfat/file.c > new file mode 100644 > index 000000000000..5afd65a36eb5 > --- /dev/null > +++ b/fs/exfat/file.c > @@ -0,0 +1,346 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. > + */ > + > +#include <linux/slab.h> > +#include <linux/cred.h> > +#include <linux/buffer_head.h> > + > +#include "exfat_raw.h" > +#include "exfat_fs.h" > + <snip> > + > +static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) > +{ > + mode_t allow_utime = sbi->options.allow_utime; > + > + if (!uid_eq(current_fsuid(), inode->i_uid)) { > + if (in_group_p(inode->i_gid)) > + allow_utime >>= 3; > + if (allow_utime & MAY_WRITE) > + return 1; > + } > + > + /* use a default check */ > + return 0; this function can be made to return bool. > +} > + <snip> > +/* resize the file length */ > +int __exfat_truncate(struct inode *inode, loff_t new_size) > +{ > + unsigned int num_clusters_new, num_clusters_phys; > + unsigned int last_clu = FREE_CLUSTER; > + struct exfat_chain clu; > + struct exfat_timestamp tm; > + struct exfat_dentry *ep, *ep2; > + struct super_block *sb = inode->i_sb; > + struct exfat_sb_info *sbi = EXFAT_SB(sb); > + struct exfat_inode_info *ei = EXFAT_I(inode); > + struct exfat_entry_set_cache *es = NULL; > + int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0; > + > + /* check if the given file ID is opened */ > + if (ei->type != TYPE_FILE && ei->type != TYPE_DIR) > + return -EPERM; > + > + exfat_set_vol_flags(sb, VOL_DIRTY); > + > + num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi); > + num_clusters_phys = > + EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi); > + > + exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags); > + > + if (new_size > 0) { > + /* > + * Truncate FAT chain num_clusters after the first cluster > + * num_clusters = min(new, phys); > + */ > + unsigned int num_clusters = > + min(num_clusters_new, num_clusters_phys); > + > + /* > + * Follow FAT chain > + * (defensive coding - works fine even with corrupted FAT table > + */ > + if (clu.flags == 0x03) { That 0x03 is magic constant, better define actual flags and check clu.flag == (FLAG1|FLAG2) > + clu.dir += num_clusters; > + clu.size -= num_clusters; > + } else { > + while (num_clusters > 0) { > + last_clu = clu.dir; > + if (exfat_get_next_cluster(sb, &(clu.dir))) > + return -EIO; > + > + num_clusters--; > + clu.size--; > + } > + } > + } else { > + ei->flags = 0x03; again, magic constant. > + ei->start_clu = EOF_CLUSTER; > + } > + > + i_size_write(inode, new_size); > + > + if (ei->type == TYPE_FILE) > + ei->attr |= ATTR_ARCHIVE; <snip>