]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - fs/ubifs/ubifs.c
applied patches from Freescale and Ka-Ro
[karo-tx-uboot.git] / fs / ubifs / ubifs.c
1 /*
2  * This file is part of UBIFS.
3  *
4  * Copyright (C) 2006-2008 Nokia Corporation.
5  *
6  * (C) Copyright 2008-2009
7  * Stefan Roese, DENX Software Engineering, sr@denx.de.
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2 as published by
11  * the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * Authors: Artem Bityutskiy (Битюцкий Артём)
23  *          Adrian Hunter
24  */
25
26 #include "ubifs.h"
27 #include <u-boot/zlib.h>
28
29 #if !defined(CONFIG_SYS_64BIT_VSPRINTF)
30 #warning Please define CONFIG_SYS_64BIT_VSPRINTF for correct output!
31 #endif
32
33 DECLARE_GLOBAL_DATA_PTR;
34
35 /* compress.c */
36
37 /*
38  * We need a wrapper for zunzip() because the parameters are
39  * incompatible with the lzo decompressor.
40  */
41 static int gzip_decompress(const unsigned char *in, size_t in_len,
42                            unsigned char *out, size_t *out_len)
43 {
44         unsigned long len = in_len;
45         return zunzip(out, *out_len, (unsigned char *)in, &len, 0, 0);
46 }
47
48 /* Fake description object for the "none" compressor */
49 static struct ubifs_compressor none_compr = {
50         .compr_type = UBIFS_COMPR_NONE,
51         .name = "no compression",
52         .capi_name = "",
53         .decompress = NULL,
54 };
55
56 static struct ubifs_compressor lzo_compr = {
57         .compr_type = UBIFS_COMPR_LZO,
58         .name = "LZO",
59         .capi_name = "lzo",
60         .decompress = lzo1x_decompress_safe,
61 };
62
63 static struct ubifs_compressor zlib_compr = {
64         .compr_type = UBIFS_COMPR_ZLIB,
65         .name = "zlib",
66         .capi_name = "deflate",
67         .decompress = gzip_decompress,
68 };
69
70 /* All UBIFS compressors */
71 struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
72
73 /**
74  * ubifs_decompress - decompress data.
75  * @in_buf: data to decompress
76  * @in_len: length of the data to decompress
77  * @out_buf: output buffer where decompressed data should
78  * @out_len: output length is returned here
79  * @compr_type: type of compression
80  *
81  * This function decompresses data from buffer @in_buf into buffer @out_buf.
82  * The length of the uncompressed data is returned in @out_len. This functions
83  * returns %0 on success or a negative error code on failure.
84  */
85 int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
86                      int *out_len, int compr_type)
87 {
88         int err;
89         struct ubifs_compressor *compr;
90
91         if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
92                 ubifs_err("invalid compression type %d", compr_type);
93                 return -EINVAL;
94         }
95
96         compr = ubifs_compressors[compr_type];
97
98         if (unlikely(!compr->capi_name)) {
99                 ubifs_err("%s compression is not compiled in", compr->name);
100                 return -EINVAL;
101         }
102
103         if (compr_type == UBIFS_COMPR_NONE) {
104                 memcpy(out_buf, in_buf, in_len);
105                 *out_len = in_len;
106                 return 0;
107         }
108
109         err = compr->decompress(in_buf, in_len, out_buf, (size_t *)out_len);
110         if (err)
111                 ubifs_err("cannot decompress %d bytes, compressor %s, "
112                           "error %d", in_len, compr->name, err);
113
114         return err;
115 }
116
117 /**
118  * compr_init - initialize a compressor.
119  * @compr: compressor description object
120  *
121  * This function initializes the requested compressor and returns zero in case
122  * of success or a negative error code in case of failure.
123  */
124 static int __init compr_init(struct ubifs_compressor *compr)
125 {
126         ubifs_compressors[compr->compr_type] = compr;
127
128 #ifndef CONFIG_RELOC_FIXUP_WORKS
129         ubifs_compressors[compr->compr_type]->name += gd->reloc_off;
130         ubifs_compressors[compr->compr_type]->capi_name += gd->reloc_off;
131         ubifs_compressors[compr->compr_type]->decompress += gd->reloc_off;
132 #endif
133
134         return 0;
135 }
136
137 /**
138  * ubifs_compressors_init - initialize UBIFS compressors.
139  *
140  * This function initializes the compressor which were compiled in. Returns
141  * zero in case of success and a negative error code in case of failure.
142  */
143 int __init ubifs_compressors_init(void)
144 {
145         int err;
146
147         err = compr_init(&lzo_compr);
148         if (err)
149                 return err;
150
151         err = compr_init(&zlib_compr);
152         if (err)
153                 return err;
154
155         err = compr_init(&none_compr);
156         if (err)
157                 return err;
158
159         return 0;
160 }
161
162 /*
163  * ubifsls...
164  */
165
166 static int filldir(struct ubifs_info *c, const char *name, int namlen,
167                    u64 ino, unsigned int d_type)
168 {
169         struct inode *inode;
170         char filetime[32];
171
172         switch (d_type) {
173         case UBIFS_ITYPE_REG:
174                 printf("\t");
175                 break;
176         case UBIFS_ITYPE_DIR:
177                 printf("<DIR>\t");
178                 break;
179         case UBIFS_ITYPE_LNK:
180                 printf("<LNK>\t");
181                 break;
182         default:
183                 printf("other\t");
184                 break;
185         }
186
187         inode = ubifs_iget(c->vfs_sb, ino);
188         if (IS_ERR(inode)) {
189                 printf("%s: Error in ubifs_iget(), ino=%lld ret=%p!\n",
190                        __func__, ino, inode);
191                 return -1;
192         }
193         ctime_r((time_t *)&inode->i_mtime, filetime);
194         printf("%9lld  %24.24s  ", inode->i_size, filetime);
195         ubifs_iput(inode);
196
197         printf("%s\n", name);
198
199         return 0;
200 }
201
202 static int ubifs_printdir(struct file *file, void *dirent)
203 {
204         int err, over = 0;
205         struct qstr nm;
206         union ubifs_key key;
207         struct ubifs_dent_node *dent;
208         struct inode *dir = file->f_path.dentry->d_inode;
209         struct ubifs_info *c = dir->i_sb->s_fs_info;
210
211         dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
212
213         if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
214                 /*
215                  * The directory was seek'ed to a senseless position or there
216                  * are no more entries.
217                  */
218                 return 0;
219
220         if (file->f_pos == 1) {
221                 /* Find the first entry in TNC and save it */
222                 lowest_dent_key(c, &key, dir->i_ino);
223                 nm.name = NULL;
224                 dent = ubifs_tnc_next_ent(c, &key, &nm);
225                 if (IS_ERR(dent)) {
226                         err = PTR_ERR(dent);
227                         goto out;
228                 }
229
230                 file->f_pos = key_hash_flash(c, &dent->key);
231                 file->private_data = dent;
232         }
233
234         dent = file->private_data;
235         if (!dent) {
236                 /*
237                  * The directory was seek'ed to and is now readdir'ed.
238                  * Find the entry corresponding to @file->f_pos or the
239                  * closest one.
240                  */
241                 dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
242                 nm.name = NULL;
243                 dent = ubifs_tnc_next_ent(c, &key, &nm);
244                 if (IS_ERR(dent)) {
245                         err = PTR_ERR(dent);
246                         goto out;
247                 }
248                 file->f_pos = key_hash_flash(c, &dent->key);
249                 file->private_data = dent;
250         }
251
252         while (1) {
253                 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
254                         dent->name, (unsigned long long)le64_to_cpu(dent->inum),
255                         key_hash_flash(c, &dent->key));
256                 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
257
258                 nm.len = le16_to_cpu(dent->nlen);
259                 over = filldir(c, (char *)dent->name, nm.len,
260                                le64_to_cpu(dent->inum), dent->type);
261                 if (over)
262                         return 0;
263
264                 /* Switch to the next entry */
265                 key_read(c, &dent->key, &key);
266                 nm.name = (char *)dent->name;
267                 dent = ubifs_tnc_next_ent(c, &key, &nm);
268                 if (IS_ERR(dent)) {
269                         err = PTR_ERR(dent);
270                         goto out;
271                 }
272
273                 kfree(file->private_data);
274                 file->f_pos = key_hash_flash(c, &dent->key);
275                 file->private_data = dent;
276                 cond_resched();
277         }
278
279 out:
280         if (err != -ENOENT) {
281                 ubifs_err("cannot find next direntry, error %d", err);
282                 return err;
283         }
284
285         kfree(file->private_data);
286         file->private_data = NULL;
287         file->f_pos = 2;
288         return 0;
289 }
290
291 static int ubifs_finddir(struct super_block *sb, char *dirname,
292                          unsigned long root_inum, unsigned long *inum)
293 {
294         int err;
295         struct qstr nm;
296         union ubifs_key key;
297         struct ubifs_dent_node *dent;
298         struct ubifs_info *c;
299         struct file *file;
300         struct dentry *dentry;
301         struct inode *dir;
302
303         file = kzalloc(sizeof(struct file), 0);
304         dentry = kzalloc(sizeof(struct dentry), 0);
305         dir = kzalloc(sizeof(struct inode), 0);
306         if (!file || !dentry || !dir) {
307                 printf("%s: Error, no memory for malloc!\n", __func__);
308                 err = -ENOMEM;
309                 goto out;
310         }
311
312         dir->i_sb = sb;
313         file->f_path.dentry = dentry;
314         file->f_path.dentry->d_parent = dentry;
315         file->f_path.dentry->d_inode = dir;
316         file->f_path.dentry->d_inode->i_ino = root_inum;
317         c = sb->s_fs_info;
318
319         dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
320
321         /* Find the first entry in TNC and save it */
322         lowest_dent_key(c, &key, dir->i_ino);
323         nm.name = NULL;
324         dent = ubifs_tnc_next_ent(c, &key, &nm);
325         if (IS_ERR(dent)) {
326                 err = PTR_ERR(dent);
327                 goto out;
328         }
329
330         file->f_pos = key_hash_flash(c, &dent->key);
331         file->private_data = dent;
332
333         while (1) {
334                 dbg_gen("feed '%s', ino %llu, new f_pos %#x",
335                         dent->name, (unsigned long long)le64_to_cpu(dent->inum),
336                         key_hash_flash(c, &dent->key));
337                 ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum);
338
339                 nm.len = le16_to_cpu(dent->nlen);
340                 if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) &&
341                     (strlen(dirname) == nm.len)) {
342                         *inum = le64_to_cpu(dent->inum);
343                         return 1;
344                 }
345
346                 /* Switch to the next entry */
347                 key_read(c, &dent->key, &key);
348                 nm.name = (char *)dent->name;
349                 dent = ubifs_tnc_next_ent(c, &key, &nm);
350                 if (IS_ERR(dent)) {
351                         err = PTR_ERR(dent);
352                         goto out;
353                 }
354
355                 kfree(file->private_data);
356                 file->f_pos = key_hash_flash(c, &dent->key);
357                 file->private_data = dent;
358                 cond_resched();
359         }
360
361 out:
362         if (err != -ENOENT) {
363                 ubifs_err("cannot find next direntry, error %d", err);
364                 return err;
365         }
366
367         if (file)
368                 free(file);
369         if (dentry)
370                 free(dentry);
371         if (dir)
372                 free(dir);
373
374         if (file->private_data)
375                 kfree(file->private_data);
376         file->private_data = NULL;
377         file->f_pos = 2;
378         return 0;
379 }
380
381 static unsigned long ubifs_findfile(struct super_block *sb, char *filename)
382 {
383         int ret;
384         char *next;
385         char fpath[128];
386         char symlinkpath[128];
387         char *name = fpath;
388         unsigned long root_inum = 1;
389         unsigned long inum;
390         int symlink_count = 0; /* Don't allow symlink recursion */
391
392         strcpy(fpath, filename);
393
394         /* Remove all leading slashes */
395         while (*name == '/')
396                 name++;
397
398         /*
399          * Handle root-direcoty ('/')
400          */
401         inum = root_inum;
402         if (!name || *name == '\0')
403                 return inum;
404
405         for (;;) {
406                 struct inode *inode;
407                 struct ubifs_inode *ui;
408
409                 /* Extract the actual part from the pathname.  */
410                 next = strchr(name, '/');
411                 if (next) {
412                         /* Remove all leading slashes.  */
413                         while (*next == '/')
414                                 *(next++) = '\0';
415                 }
416
417                 ret = ubifs_finddir(sb, name, root_inum, &inum);
418                 if (!ret)
419                         return 0;
420                 inode = ubifs_iget(sb, inum);
421
422                 if (!inode)
423                         return 0;
424                 ui = ubifs_inode(inode);
425
426                 if ((inode->i_mode & S_IFMT) == S_IFLNK) {
427                         char link_name[64];
428                         char buf[128];
429
430                         /* We have some sort of symlink recursion, bail out */
431                         if (symlink_count++ > 8) {
432                                 printf("Symlink recursion, aborting\n");
433                                 return 0;
434                         }
435                         memcpy(link_name, ui->data, ui->data_len);
436                         link_name[ui->data_len] = '\0';
437
438                         if (link_name[0] == '/') {
439                                 /* Absolute path, redo everything without
440                                  * the leading slash */
441                                 next = name = link_name + 1;
442                                 root_inum = 1;
443                                 continue;
444                         }
445                         /* Relative to cur dir */
446                         sprintf(buf, "%s/%s",
447                                         link_name, next == NULL ? "" : next);
448                         memcpy(symlinkpath, buf, sizeof(buf));
449                         next = name = symlinkpath;
450                         continue;
451                 }
452
453                 /*
454                  * Check if directory with this name exists
455                  */
456
457                 /* Found the node!  */
458                 if (!next || *next == '\0')
459                         return inum;
460
461                 root_inum = inum;
462                 name = next;
463         }
464
465         return 0;
466 }
467
468 int ubifs_ls(char *filename)
469 {
470         struct ubifs_info *c = ubifs_sb->s_fs_info;
471         struct file *file;
472         struct dentry *dentry;
473         struct inode *dir;
474         void *dirent = NULL;
475         unsigned long inum;
476         int ret = 0;
477
478         c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
479         inum = ubifs_findfile(ubifs_sb, filename);
480         if (!inum) {
481                 ret = -1;
482                 goto out;
483         }
484
485         file = kzalloc(sizeof(struct file), 0);
486         dentry = kzalloc(sizeof(struct dentry), 0);
487         dir = kzalloc(sizeof(struct inode), 0);
488         if (!file || !dentry || !dir) {
489                 printf("%s: Error, no memory for malloc!\n", __func__);
490                 ret = -ENOMEM;
491                 goto out_mem;
492         }
493
494         dir->i_sb = ubifs_sb;
495         file->f_path.dentry = dentry;
496         file->f_path.dentry->d_parent = dentry;
497         file->f_path.dentry->d_inode = dir;
498         file->f_path.dentry->d_inode->i_ino = inum;
499         file->f_pos = 1;
500         file->private_data = NULL;
501         ubifs_printdir(file, dirent);
502
503 out_mem:
504         if (file)
505                 free(file);
506         if (dentry)
507                 free(dentry);
508         if (dir)
509                 free(dir);
510
511 out:
512         ubi_close_volume(c->ubi);
513         return ret;
514 }
515
516 /*
517  * ubifsload...
518  */
519
520 /* file.c */
521
522 static inline void *kmap(struct page *page)
523 {
524         return page->addr;
525 }
526
527 static int read_block(struct inode *inode, void *addr, unsigned int block,
528                       struct ubifs_data_node *dn)
529 {
530         struct ubifs_info *c = inode->i_sb->s_fs_info;
531         int err, len, out_len;
532         union ubifs_key key;
533         unsigned int dlen;
534
535         data_key_init(c, &key, inode->i_ino, block);
536         err = ubifs_tnc_lookup(c, &key, dn);
537         if (err) {
538                 if (err == -ENOENT)
539                         /* Not found, so it must be a hole */
540                         memset(addr, 0, UBIFS_BLOCK_SIZE);
541                 return err;
542         }
543
544         ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum);
545
546         len = le32_to_cpu(dn->size);
547         if (len <= 0 || len > UBIFS_BLOCK_SIZE)
548                 goto dump;
549
550         dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
551         out_len = UBIFS_BLOCK_SIZE;
552         err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
553                                le16_to_cpu(dn->compr_type));
554         if (err || len != out_len)
555                 goto dump;
556
557         /*
558          * Data length can be less than a full block, even for blocks that are
559          * not the last in the file (e.g., as a result of making a hole and
560          * appending data). Ensure that the remainder is zeroed out.
561          */
562         if (len < UBIFS_BLOCK_SIZE)
563                 memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
564
565         return 0;
566
567 dump:
568         ubifs_err("bad data node (block %u, inode %lu)",
569                   block, inode->i_ino);
570         dbg_dump_node(c, dn);
571         return -EINVAL;
572 }
573
574 static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page)
575 {
576         void *addr;
577         int err = 0, i;
578         unsigned int block, beyond;
579         struct ubifs_data_node *dn;
580         loff_t i_size = inode->i_size;
581
582         dbg_gen("ino %lu, pg %lu, i_size %lld",
583                 inode->i_ino, page->index, i_size);
584
585         addr = kmap(page);
586
587         block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
588         beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
589         if (block >= beyond) {
590                 /* Reading beyond inode */
591                 memset(addr, 0, PAGE_CACHE_SIZE);
592                 goto out;
593         }
594
595         dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS);
596         if (!dn)
597                 return -ENOMEM;
598
599         i = 0;
600         while (1) {
601                 int ret;
602
603                 if (block >= beyond) {
604                         /* Reading beyond inode */
605                         err = -ENOENT;
606                         memset(addr, 0, UBIFS_BLOCK_SIZE);
607                 } else {
608                         ret = read_block(inode, addr, block, dn);
609                         if (ret) {
610                                 err = ret;
611                                 if (err != -ENOENT)
612                                         break;
613                         } else if (block + 1 == beyond) {
614                                 int dlen = le32_to_cpu(dn->size);
615                                 int ilen = i_size & (UBIFS_BLOCK_SIZE - 1);
616
617                                 if (ilen && ilen < dlen)
618                                         memset(addr + ilen, 0, dlen - ilen);
619                         }
620                 }
621                 if (++i >= UBIFS_BLOCKS_PER_PAGE)
622                         break;
623                 block += 1;
624                 addr += UBIFS_BLOCK_SIZE;
625         }
626         if (err) {
627                 if (err == -ENOENT) {
628                         /* Not found, so it must be a hole */
629                         dbg_gen("hole");
630                         goto out_free;
631                 }
632                 ubifs_err("cannot read page %lu of inode %lu, error %d",
633                           page->index, inode->i_ino, err);
634                 goto error;
635         }
636
637 out_free:
638         kfree(dn);
639 out:
640         return 0;
641
642 error:
643         kfree(dn);
644         return err;
645 }
646
647 int ubifs_load(char *filename, u32 addr, u32 size)
648 {
649         struct ubifs_info *c = ubifs_sb->s_fs_info;
650         unsigned long inum;
651         struct inode *inode;
652         struct page page;
653         int err = 0;
654         int i;
655         int count;
656
657         c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY);
658         /* ubifs_findfile will resolve symlinks, so we know that we get
659          * the real file here */
660         inum = ubifs_findfile(ubifs_sb, filename);
661         if (!inum) {
662                 err = -1;
663                 goto out;
664         }
665
666         /*
667          * Read file inode
668          */
669         inode = ubifs_iget(ubifs_sb, inum);
670         if (IS_ERR(inode)) {
671                 printf("%s: Error reading inode %ld!\n", __func__, inum);
672                 err = PTR_ERR(inode);
673                 goto out;
674         }
675
676         /*
677          * If no size was specified or if size bigger than filesize
678          * set size to filesize
679          */
680         if ((size == 0) || (size > inode->i_size))
681                 size = inode->i_size;
682
683         count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
684         printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n",
685                filename, addr, size, size);
686
687         page.addr = (void *)addr;
688         page.index = 0;
689         page.inode = inode;
690         for (i = 0; i < count; i++) {
691                 err = do_readpage(c, inode, &page);
692                 if (err)
693                         break;
694
695                 page.addr += PAGE_SIZE;
696                 page.index++;
697         }
698
699         if (err)
700                 printf("Error reading file '%s'\n", filename);
701         else
702                 printf("Done\n");
703
704         ubifs_iput(inode);
705
706 out:
707         ubi_close_volume(c->ubi);
708         return err;
709 }