From 02f99901ed1c9d828e3ea117f94ce2264bf8389e Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Mon, 24 Aug 2009 09:09:50 +0200 Subject: Move __set/clear_bit from ubifs.h to bitops.h __set_bit and __clear_bit are defined in ubifs.h as well as in asm/include/bitops.h for some architectures. This patch moves the generic implementation to include/linux/bitops.h and uses that unless it's defined by the architecture. Signed-off-by: Simon Kagstrom --- fs/ubifs/ubifs.h | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'fs') 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(...) -- cgit v1.1 From 9d7952e4c636b8c99289a44dbe28c6f93c43b9f7 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Tue, 15 Sep 2009 09:53:29 +0200 Subject: ubifs: Add support for looking up directory and relative symlinks This patch adds support for resolving symlinks to directories as well as relative symlinks. Symlinks are now always resolved during file lookup, so the load stage no longer needs to special-case them. Signed-off-by: Simon Kagstrom Signed-off-by: Stefan Roese --- fs/ubifs/ubifs.c | 68 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 25 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 8ede188..b03ed0b 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -379,9 +379,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 +399,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 +411,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 +649,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 +670,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 */ -- cgit v1.1 From ef37c6835eac66206a9c7c11f0c7186f5d64bf91 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Fri, 25 Sep 2009 14:05:57 +0200 Subject: ubifs: Correct dereferencing of files-after-symlinks Files in directories which are symlinked to were not dereferenced correctly in last commit. E.g., with a symlink /boot/lnk -> /boot/real_dir loading /boot/lnk/uImage will fail. This patch fixes that by simply seeing to it that the target base directory has a slash after it. Signed-off-by: Simon Kagstrom Signed-off-by: Stefan Roese --- fs/ubifs/ubifs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index b03ed0b..286739c 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -439,7 +439,7 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) continue; } /* Relative to cur dir */ - sprintf(buf, "%s%s", + sprintf(buf, "%s/%s", link_name, next == NULL ? "" : next); memcpy(symlinkpath, buf, sizeof(buf)); next = name = symlinkpath; -- cgit v1.1