diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ubifs/super.c | 1 | ||||
-rw-r--r-- | fs/ubifs/ubifs.c | 72 | ||||
-rw-r--r-- | fs/ubifs/ubifs.h | 32 |
3 files changed, 48 insertions, 57 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 391dea4..9efe7cd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1178,6 +1178,7 @@ int ubifs_mount(char *vol_name) ubifs_umount(ubifs_sb->s_fs_info); INIT_LIST_HEAD(&ubifs_infos); + INIT_LIST_HEAD(&(ubifs_fs_type.fs_supers)); /* * Mount in read-only mode diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 8ede188..82f1c54 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -124,9 +124,13 @@ int ubifs_decompress(const void *in_buf, int in_len, void *out_buf, static int __init compr_init(struct ubifs_compressor *compr) { ubifs_compressors[compr->compr_type] = compr; + +#ifndef CONFIG_RELOC_FIXUP_WORKS ubifs_compressors[compr->compr_type]->name += gd->reloc_off; ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off; ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off; +#endif + return 0; } @@ -379,9 +383,11 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) int ret; char *next; char fpath[128]; + char symlinkpath[128]; char *name = fpath; unsigned long root_inum = 1; unsigned long inum; + int symlink_count = 0; /* Don't allow symlink recursion */ strcpy(fpath, filename); @@ -397,6 +403,9 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) return inum; for (;;) { + struct inode *inode; + struct ubifs_inode *ui; + /* Extract the actual part from the pathname. */ next = strchr(name, '/'); if (next) { @@ -406,18 +415,48 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) } ret = ubifs_finddir(sb, name, root_inum, &inum); + if (!ret) + return 0; + inode = ubifs_iget(sb, inum); + + if (!inode) + return 0; + ui = ubifs_inode(inode); + + if ((inode->i_mode & S_IFMT) == S_IFLNK) { + char link_name[64]; + char buf[128]; + + /* We have some sort of symlink recursion, bail out */ + if (symlink_count++ > 8) { + printf("Symlink recursion, aborting\n"); + return 0; + } + memcpy(link_name, ui->data, ui->data_len); + link_name[ui->data_len] = '\0'; + + if (link_name[0] == '/') { + /* Absolute path, redo everything without + * the leading slash */ + next = name = link_name + 1; + root_inum = 1; + continue; + } + /* Relative to cur dir */ + sprintf(buf, "%s/%s", + link_name, next == NULL ? "" : next); + memcpy(symlinkpath, buf, sizeof(buf)); + next = name = symlinkpath; + continue; + } /* * Check if directory with this name exists */ /* Found the node! */ - if (!next || *next == '\0') { - if (ret) - return inum; - - break; - } + if (!next || *next == '\0') + return inum; root_inum = inum; name = next; @@ -614,10 +653,10 @@ int ubifs_load(char *filename, u32 addr, u32 size) int err = 0; int i; int count; - char link_name[64]; - struct ubifs_inode *ui; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); + /* ubifs_findfile will resolve symlinks, so we know that we get + * the real file here */ inum = ubifs_findfile(ubifs_sb, filename); if (!inum) { err = -1; @@ -635,23 +674,6 @@ int ubifs_load(char *filename, u32 addr, u32 size) } /* - * Check for symbolic link - */ - ui = ubifs_inode(inode); - if (((inode->i_mode & S_IFMT) == S_IFLNK) && ui->data_len) { - memcpy(link_name, ui->data, ui->data_len); - link_name[ui->data_len] = '\0'; - printf("%s is linked to %s!\n", filename, link_name); - ubifs_iput(inode); - - /* - * Now we have the "real" filename, call ubifs_load() - * again (recursive call) to load this file instead - */ - return ubifs_load(link_name, addr, size); - } - - /* * If no size was specified or if size bigger than filesize * set size to filesize */ diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 43865aa..06772af 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -449,38 +449,6 @@ static inline ino_t parent_ino(struct dentry *dentry) return res; } -/* linux/include/linux/bitops.h */ - -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) - -/* linux/include/asm-generic/bitops/non-atomic.h */ - -/** - * __set_bit - Set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike set_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static inline void __set_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p |= mask; -} - -static inline void __clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = BIT_MASK(nr); - unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); - - *p &= ~mask; -} - /* debug.c */ #define DEFINE_SPINLOCK(...) |