Add AFFS NLS support
Subsystems (2)
PATCH 1/1 Add AFFS NLS support
AFFS almost always uses latin1. However usual iocharset by now is UTF-8. So NLS support is required.
Signed-off-by Vladimir Serbinenko <[email protected]>
fs/affs/Kconfig +8 -0
@@ -19,3 +19,11 @@ config AFFS_FS To compile this file system support as a module, choose M here: the module will be called affs. If unsure, say N. + +config AFFS_DEFAULT_CODEPAGE + string "Default codepage for AFFS" + depends on AFFS_FS + default "iso8859-1" + help + This option should be set to the codepage of your AFFS filesystems. + It can be overridden with the "codepage" mount option.
fs/affs/affs.h +14 -2
@@ -12,6 +12,8 @@*/ /*#define AFFS_NO_TRUNCATE */ +#define AFFS_MAXNAME 30 +/* Ugly macros make the code more pretty. */ #define GET_END_PTR (st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st))))
@@ -107,6 +109,10 @@ struct affs_sb_info {u32 s_bmap_bits;/* # of bits in one bitmap blocks */ u32 s_last_bmap;struct buffer_head *s_bmap_bh; +char *iocharset; +char *codepage; +struct nls_table *nls_io; +struct nls_table *nls_disk;char *s_prefix;/* Prefix for volumes and assigns. */ char s_volume[32 ];/* Volume prefix for absolute symlinks. */ spinlock_t symlink_lock;/* protects the previous two */
@@ -142,8 +148,9 @@ extern umode_t prot_to_mode(u32 prot);extern void mode_to_prot (struct inode *inode);extern void affs_error (struct super_block *sb,const char *function,const char *fmt, ...);extern void affs_warning (struct super_block *sb,const char *function,const char *fmt, ...); -extern int affs_check_name (const unsigned char *name,int len); -extern int affs_copy_name (unsigned char *bstr,struct dentry *dentry); +extern int affs_check_name (const unsigned char *name,unsigned int len); +extern int affs_copy_name (struct super_block *sb,unsigned char *bstr, +struct dentry *dentry);/* bitmap. c */
@@ -165,8 +172,13 @@ extern int affs_link(struct dentry *olddentry, struct inode *dir, struct dentry *dentry);extern int affs_symlink (struct inode *dir,struct dentry *dentry,const char *symname); +extern int affs_read_symlink (struct inode *inode, +char *link);extern int affs_rename (struct inode *old_dir,struct dentry *old_dentry,struct inode *new_dir,struct dentry *new_dentry); +extern size_t affs_translate (u8 *to,const u8 *from,struct nls_table *nls_to, +struct nls_table *nls_from,size_t limit, +size_t from_len);/* inode.c */
fs/affs/amigaffs.c +3 -19
@@ -477,15 +477,15 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)/* Check if the name is valid for a affs object. */ int -affs_check_name (const unsigned char *name,int len) +affs_check_name (const unsigned char *name,unsigned int len) {int i; - if (len > 30) + if (len > AFFS_MAXNAME)#ifdef AFFS_NO_TRUNCATE return -ENAMETOOLONG ;#else - len =30 ; + len =AFFS_MAXNAME ;#endif for (i =0 ; i < len; i++) {
@@ -497,19 +497,3 @@ affs_check_name(const unsigned char *name, int len)return 0 ; } -/* This function copies name to bstr, with at most 30 -* characters length. The bstr will be prepended by -* a length byte. -* NOTE: The name will must be already checked by -* affs_check_name()! -*/ - -int -affs_copy_name (unsigned char *bstr,struct dentry *dentry) -{ -int len =min (dentry->d_name.len,30u ); - - *bstr++ = len; -memcpy (bstr, dentry->d_name.name, len); -return len; -}
fs/affs/dir.c +18 -2
@@ -55,6 +55,8 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)u32 ino;int stored;int res; +struct nls_table *nls_io =AFFS_SB (sb)->nls_io; +struct nls_table *nls_disk =AFFS_SB (sb)->nls_disk;pr_debug ("AFFS: readdir(ino=%lu,f_pos=%lx)\n" ,inode->i_ino,(unsigned long )filp->f_pos);
@@ -122,17 +124,31 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) f_pos = (hash_pos <<16 ) +2 ; inside: do { + /* AFFS names are at most 30 characters and are all in + BMP. So at most 90 characters resulting translation + assuming UTF-8 as iocharset. Then comes paranoia. + In worst-case scenario filenames get truncated but + no overflow occurs. + */ + char buf[200]; + size_t translatedlen; fh_bh = affs_bread(sb, ino); if (!fh_bh) { affs_error(sb, "readdir","Cannot read block %d", ino); goto readdir_done; } - namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30); + namelen = min(((u8 *)AFFS_TAIL(sb, fh_bh)->name)[0], + (u8)AFFS_MAXNAME); name = AFFS_TAIL(sb, fh_bh)->name + 1; + translatedlen = affs_translate(buf, name, + nls_io, nls_disk, + sizeof(buf), + namelen); pr_debug("AFFS: readdir(): filldir(\"%.*s\", ino=%u), hash=%d, f_pos=%x\n", namelen, name, ino, hash_pos, f_pos); - if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0) + if (filldir(dirent, buf, translatedlen, f_pos, ino, + DT_UNKNOWN) < 0) goto readdir_done; stored++; f_pos++;
fs/affs/inode.c +7 -1
@@ -143,11 +143,17 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) inode->i_fop = &affs_file_operations;break ;case ST_SOFTLINK : + { +int s; inode->i_mode |=S_IFLNK ; inode->i_op = &affs_symlink_inode_operations; inode->i_data.a_ops = &affs_symlink_aops; + s =affs_read_symlink (inode,0 ); + + inode->i_size = s >=0 ? s :0 ;break ; } + } inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = (be32_to_cpu(tail->change.days) * (24 * 60 * 60) +
@@ -375,7 +381,7 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3AFFS_HEAD (bh)->ptype =cpu_to_be32 (T_SHORT );AFFS_HEAD (bh)->key =cpu_to_be32 (bh->b_blocknr); -affs_copy_name (AFFS_TAIL (sb, bh)->name, dentry); +affs_copy_name (sb,AFFS_TAIL (sb, bh)->name, dentry);AFFS_TAIL (sb, bh)->stype =cpu_to_be32 (type);AFFS_TAIL (sb, bh)->parent =cpu_to_be32 (dir->i_ino);
fs/affs/namei.c +171 -34
326 lines not on this page · raw message
fs/affs/super.c +100 -8
189 lines not on this page · raw message
fs/affs/symlink.c +82 -17
135 lines not on this page · raw message