summaryrefslogtreecommitdiff
path: root/fs/ubifs
diff options
context:
space:
mode:
authorTerry Lv <r65388@freescale.com>2009-12-10 11:26:52 +0800
committerTerry Lv <r65388@freescale.com>2009-12-11 12:44:24 +0800
commit1ee27e13d6fdb19d297f8d1d6d3d7d8449d0361e (patch)
tree90de615a82637ea82d8f81914ea6a5249b85512b /fs/ubifs
parent270ba8ac5b8c52a0b4fcf0d77eb66ac647c7f37c (diff)
downloadu-boot-imx-1ee27e13d6fdb19d297f8d1d6d3d7d8449d0361e.zip
u-boot-imx-1ee27e13d6fdb19d297f8d1d6d3d7d8449d0361e.tar.gz
u-boot-imx-1ee27e13d6fdb19d297f8d1d6d3d7d8449d0361e.tar.bz2
ENGR00119171: ubifs support for android recovery mode.
ubifs support for android recovery mode. Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/super.c1
-rw-r--r--fs/ubifs/ubifs.c72
-rw-r--r--fs/ubifs/ubifs.h32
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(...)