Blame view
fs/ubifs/ubifs.c
20.6 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
9eefe2a2b UBIFS: Implement ... |
2 3 4 5 6 |
/* * This file is part of UBIFS. * * Copyright (C) 2006-2008 Nokia Corporation. * |
b1a14f8a1 UBIFS: Change ubi... |
7 |
* (C) Copyright 2008-2010 |
9eefe2a2b UBIFS: Implement ... |
8 9 |
* Stefan Roese, DENX Software Engineering, sr@denx.de. * |
9eefe2a2b UBIFS: Implement ... |
10 11 12 |
* Authors: Artem Bityutskiy (Битюцкий Артём) * Adrian Hunter */ |
6e295186c Move malloc_cache... |
13 14 |
#include <common.h> #include <memalign.h> |
9eefe2a2b UBIFS: Implement ... |
15 |
#include "ubifs.h" |
c1a0fd5f2 ubifs: BUG: Block... |
16 |
#include <u-boot/zlib.h> |
9eefe2a2b UBIFS: Implement ... |
17 |
|
ff94bc40a mtd, ubi, ubifs: ... |
18 19 |
#include <linux/err.h> #include <linux/lzo.h> |
9eefe2a2b UBIFS: Implement ... |
20 21 22 23 24 |
DECLARE_GLOBAL_DATA_PTR; /* compress.c */ /* |
c1a0fd5f2 ubifs: BUG: Block... |
25 |
* We need a wrapper for zunzip() because the parameters are |
9eefe2a2b UBIFS: Implement ... |
26 27 28 29 30 |
* incompatible with the lzo decompressor. */ static int gzip_decompress(const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len) { |
8044c1387 ubifs: Fix ubifsl... |
31 32 |
return zunzip(out, *out_len, (unsigned char *)in, (unsigned long *)out_len, 0, 0); |
9eefe2a2b UBIFS: Implement ... |
33 34 35 36 37 |
} /* Fake description object for the "none" compressor */ static struct ubifs_compressor none_compr = { .compr_type = UBIFS_COMPR_NONE, |
ff94bc40a mtd, ubi, ubifs: ... |
38 |
.name = "none", |
9eefe2a2b UBIFS: Implement ... |
39 40 41 42 43 44 |
.capi_name = "", .decompress = NULL, }; static struct ubifs_compressor lzo_compr = { .compr_type = UBIFS_COMPR_LZO, |
ff94bc40a mtd, ubi, ubifs: ... |
45 46 47 48 |
#ifndef __UBOOT__ .comp_mutex = &lzo_mutex, #endif .name = "lzo", |
9eefe2a2b UBIFS: Implement ... |
49 50 51 52 53 54 |
.capi_name = "lzo", .decompress = lzo1x_decompress_safe, }; static struct ubifs_compressor zlib_compr = { .compr_type = UBIFS_COMPR_ZLIB, |
ff94bc40a mtd, ubi, ubifs: ... |
55 56 57 58 |
#ifndef __UBOOT__ .comp_mutex = &deflate_mutex, .decomp_mutex = &inflate_mutex, #endif |
9eefe2a2b UBIFS: Implement ... |
59 60 61 62 63 64 65 |
.name = "zlib", .capi_name = "deflate", .decompress = gzip_decompress, }; /* All UBIFS compressors */ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; |
ff94bc40a mtd, ubi, ubifs: ... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#ifdef __UBOOT__ /* from mm/util.c */ /** * kmemdup - duplicate region of memory * * @src: memory region to duplicate * @len: memory region length * @gfp: GFP mask to use */ void *kmemdup(const void *src, size_t len, gfp_t gfp) { void *p; p = kmalloc(len, gfp); if (p) memcpy(p, src, len); return p; } struct crypto_comp { int compressor; }; |
0195a7bb3 ubi,ubifs: sync w... |
90 91 |
static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name, u32 type, u32 mask) |
ff94bc40a mtd, ubi, ubifs: ... |
92 93 94 95 |
{ struct ubifs_compressor *comp; struct crypto_comp *ptr; int i = 0; |
4519668b2 mtd/nand/ubi: ass... |
96 |
ptr = malloc_cache_aligned(sizeof(struct crypto_comp)); |
ff94bc40a mtd, ubi, ubifs: ... |
97 98 99 100 101 102 103 104 105 106 107 108 109 |
while (i < UBIFS_COMPR_TYPES_CNT) { comp = ubifs_compressors[i]; if (!comp) { i++; continue; } if (strncmp(alg_name, comp->capi_name, strlen(alg_name)) == 0) { ptr->compressor = i; return ptr; } i++; } if (i >= UBIFS_COMPR_TYPES_CNT) { |
0195a7bb3 ubi,ubifs: sync w... |
110 |
dbg_gen("invalid compression type %s", alg_name); |
ff94bc40a mtd, ubi, ubifs: ... |
111 112 113 114 115 |
free (ptr); return NULL; } return ptr; } |
0195a7bb3 ubi,ubifs: sync w... |
116 117 118 119 |
static inline int crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) |
ff94bc40a mtd, ubi, ubifs: ... |
120 121 122 |
{ struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor]; int err; |
e4aa10ba5 fs: ubifs: Fix UB... |
123 |
size_t tmp_len = *dlen; |
ff94bc40a mtd, ubi, ubifs: ... |
124 125 126 127 128 129 |
if (compr->compr_type == UBIFS_COMPR_NONE) { memcpy(dst, src, slen); *dlen = slen; return 0; } |
e4aa10ba5 fs: ubifs: Fix UB... |
130 |
err = compr->decompress(src, slen, dst, &tmp_len); |
ff94bc40a mtd, ubi, ubifs: ... |
131 |
if (err) |
0195a7bb3 ubi,ubifs: sync w... |
132 |
ubifs_err(c, "cannot decompress %d bytes, compressor %s, " |
ff94bc40a mtd, ubi, ubifs: ... |
133 |
"error %d", slen, compr->name, err); |
e4aa10ba5 fs: ubifs: Fix UB... |
134 |
*dlen = tmp_len; |
ff94bc40a mtd, ubi, ubifs: ... |
135 136 137 138 |
return err; return 0; } |
dc2884315 ubifs: Import ato... |
139 140 141 142 143 |
/* from shrinker.c */ /* Global clean znode counter (for all mounted UBIFS instances) */ atomic_long_t ubifs_clean_zn_cnt; |
ff94bc40a mtd, ubi, ubifs: ... |
144 |
#endif |
9eefe2a2b UBIFS: Implement ... |
145 146 147 148 149 150 151 152 153 154 155 156 |
/** * ubifs_decompress - decompress data. * @in_buf: data to decompress * @in_len: length of the data to decompress * @out_buf: output buffer where decompressed data should * @out_len: output length is returned here * @compr_type: type of compression * * This function decompresses data from buffer @in_buf into buffer @out_buf. * The length of the uncompressed data is returned in @out_len. This functions * returns %0 on success or a negative error code on failure. */ |
0195a7bb3 ubi,ubifs: sync w... |
157 158 |
int ubifs_decompress(const struct ubifs_info *c, const void *in_buf, int in_len, void *out_buf, int *out_len, int compr_type) |
9eefe2a2b UBIFS: Implement ... |
159 160 161 162 163 |
{ int err; struct ubifs_compressor *compr; if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) { |
0195a7bb3 ubi,ubifs: sync w... |
164 |
ubifs_err(c, "invalid compression type %d", compr_type); |
9eefe2a2b UBIFS: Implement ... |
165 166 167 168 169 170 |
return -EINVAL; } compr = ubifs_compressors[compr_type]; if (unlikely(!compr->capi_name)) { |
0195a7bb3 ubi,ubifs: sync w... |
171 |
ubifs_err(c, "%s compression is not compiled in", compr->name); |
9eefe2a2b UBIFS: Implement ... |
172 173 174 175 176 177 178 179 |
return -EINVAL; } if (compr_type == UBIFS_COMPR_NONE) { memcpy(out_buf, in_buf, in_len); *out_len = in_len; return 0; } |
ff94bc40a mtd, ubi, ubifs: ... |
180 181 |
if (compr->decomp_mutex) mutex_lock(compr->decomp_mutex); |
0195a7bb3 ubi,ubifs: sync w... |
182 |
err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf, |
ff94bc40a mtd, ubi, ubifs: ... |
183 184 185 |
(unsigned int *)out_len); if (compr->decomp_mutex) mutex_unlock(compr->decomp_mutex); |
9eefe2a2b UBIFS: Implement ... |
186 |
if (err) |
0195a7bb3 ubi,ubifs: sync w... |
187 188 |
ubifs_err(c, "cannot decompress %d bytes, compressor %s," " error %d", in_len, compr->name, err); |
9eefe2a2b UBIFS: Implement ... |
189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
return err; } /** * compr_init - initialize a compressor. * @compr: compressor description object * * This function initializes the requested compressor and returns zero in case * of success or a negative error code in case of failure. */ static int __init compr_init(struct ubifs_compressor *compr) { ubifs_compressors[compr->compr_type] = compr; |
521af04d8 Conditionally per... |
203 |
|
2e5167cca Replace CONFIG_RE... |
204 |
#ifdef CONFIG_NEEDS_MANUAL_RELOC |
9eefe2a2b UBIFS: Implement ... |
205 206 207 |
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; |
521af04d8 Conditionally per... |
208 |
#endif |
ff94bc40a mtd, ubi, ubifs: ... |
209 210 211 |
if (compr->capi_name) { compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0); if (IS_ERR(compr->cc)) { |
0195a7bb3 ubi,ubifs: sync w... |
212 213 214 |
dbg_gen("cannot initialize compressor %s," " error %ld", compr->name, PTR_ERR(compr->cc)); |
ff94bc40a mtd, ubi, ubifs: ... |
215 216 217 |
return PTR_ERR(compr->cc); } } |
9eefe2a2b UBIFS: Implement ... |
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
return 0; } /** * ubifs_compressors_init - initialize UBIFS compressors. * * This function initializes the compressor which were compiled in. Returns * zero in case of success and a negative error code in case of failure. */ int __init ubifs_compressors_init(void) { int err; err = compr_init(&lzo_compr); if (err) return err; err = compr_init(&zlib_compr); if (err) return err; |
faac4fd85 UBIFS: Missing of... |
238 239 240 |
err = compr_init(&none_compr); if (err) return err; |
9eefe2a2b UBIFS: Implement ... |
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
return 0; } /* * ubifsls... */ static int filldir(struct ubifs_info *c, const char *name, int namlen, u64 ino, unsigned int d_type) { struct inode *inode; char filetime[32]; switch (d_type) { case UBIFS_ITYPE_REG: printf("\t"); break; case UBIFS_ITYPE_DIR: printf("<DIR>\t"); break; case UBIFS_ITYPE_LNK: printf("<LNK>\t"); break; default: printf("other\t"); break; } inode = ubifs_iget(c->vfs_sb, ino); if (IS_ERR(inode)) { printf("%s: Error in ubifs_iget(), ino=%lld ret=%p! ", __func__, ino, inode); return -1; } ctime_r((time_t *)&inode->i_mtime, filetime); printf("%9lld %24.24s ", inode->i_size, filetime); |
ff94bc40a mtd, ubi, ubifs: ... |
278 |
#ifndef __UBOOT__ |
9eefe2a2b UBIFS: Implement ... |
279 |
ubifs_iput(inode); |
ff94bc40a mtd, ubi, ubifs: ... |
280 |
#endif |
9eefe2a2b UBIFS: Implement ... |
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
printf("%s ", name); return 0; } static int ubifs_printdir(struct file *file, void *dirent) { int err, over = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file->f_path.dentry->d_inode; struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; if (file->f_pos == 1) { /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @file->f_pos or the * closest one. */ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); |
87deefecc ubifs: avoid asse... |
342 |
#ifndef __UBOOT__ |
9eefe2a2b UBIFS: Implement ... |
343 |
ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); |
87deefecc ubifs: avoid asse... |
344 |
#endif |
9eefe2a2b UBIFS: Implement ... |
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
nm.len = le16_to_cpu(dent->nlen); over = filldir(c, (char *)dent->name, nm.len, le64_to_cpu(dent->inum), dent->type); if (over) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = (char *)dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { |
0195a7bb3 ubi,ubifs: sync w... |
369 |
ubifs_err(c, "cannot find next direntry, error %d", err); |
9eefe2a2b UBIFS: Implement ... |
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
return err; } kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; } static int ubifs_finddir(struct super_block *sb, char *dirname, unsigned long root_inum, unsigned long *inum) { int err; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct ubifs_info *c; struct file *file; struct dentry *dentry; struct inode *dir; |
be73913b9 ubifs: Fix memory... |
390 |
int ret = 0; |
9eefe2a2b UBIFS: Implement ... |
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
file = kzalloc(sizeof(struct file), 0); dentry = kzalloc(sizeof(struct dentry), 0); dir = kzalloc(sizeof(struct inode), 0); if (!file || !dentry || !dir) { printf("%s: Error, no memory for malloc! ", __func__); err = -ENOMEM; goto out; } dir->i_sb = sb; file->f_path.dentry = dentry; file->f_path.dentry->d_parent = dentry; file->f_path.dentry->d_inode = dir; file->f_path.dentry->d_inode->i_ino = root_inum; c = sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); |
87deefecc ubifs: avoid asse... |
427 |
#ifndef __UBOOT__ |
9eefe2a2b UBIFS: Implement ... |
428 |
ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); |
87deefecc ubifs: avoid asse... |
429 |
#endif |
9eefe2a2b UBIFS: Implement ... |
430 431 432 433 434 |
nm.len = le16_to_cpu(dent->nlen); if ((strncmp(dirname, (char *)dent->name, nm.len) == 0) && (strlen(dirname) == nm.len)) { *inum = le64_to_cpu(dent->inum); |
be73913b9 ubifs: Fix memory... |
435 436 |
ret = 1; goto out_free; |
9eefe2a2b UBIFS: Implement ... |
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
} /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = (char *)dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: |
be73913b9 ubifs: Fix memory... |
455 |
if (err != -ENOENT) |
0195a7bb3 ubi,ubifs: sync w... |
456 |
dbg_gen("cannot find next direntry, error %d", err); |
9eefe2a2b UBIFS: Implement ... |
457 |
|
be73913b9 ubifs: Fix memory... |
458 |
out_free: |
4b29975fd ubifs: no NULL ch... |
459 460 461 462 |
kfree(file->private_data); free(file); free(dentry); free(dir); |
9eefe2a2b UBIFS: Implement ... |
463 |
|
be73913b9 ubifs: Fix memory... |
464 |
return ret; |
9eefe2a2b UBIFS: Implement ... |
465 466 467 468 469 470 471 |
} static unsigned long ubifs_findfile(struct super_block *sb, char *filename) { int ret; char *next; char fpath[128]; |
9d7952e4c ubifs: Add suppor... |
472 |
char symlinkpath[128]; |
9eefe2a2b UBIFS: Implement ... |
473 474 475 |
char *name = fpath; unsigned long root_inum = 1; unsigned long inum; |
9d7952e4c ubifs: Add suppor... |
476 |
int symlink_count = 0; /* Don't allow symlink recursion */ |
64b681784 ubifs.c: BUG: Err... |
477 |
char link_name[64]; |
9eefe2a2b UBIFS: Implement ... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
strcpy(fpath, filename); /* Remove all leading slashes */ while (*name == '/') name++; /* * Handle root-direcoty ('/') */ inum = root_inum; if (!name || *name == '\0') return inum; for (;;) { |
9d7952e4c ubifs: Add suppor... |
493 494 |
struct inode *inode; struct ubifs_inode *ui; |
9eefe2a2b UBIFS: Implement ... |
495 496 497 498 499 500 501 502 503 |
/* Extract the actual part from the pathname. */ next = strchr(name, '/'); if (next) { /* Remove all leading slashes. */ while (*next == '/') *(next++) = '\0'; } ret = ubifs_finddir(sb, name, root_inum, &inum); |
9d7952e4c ubifs: Add suppor... |
504 505 506 507 508 509 510 511 512 |
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) { |
9d7952e4c ubifs: Add suppor... |
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
char buf[128]; /* We have some sort of symlink recursion, bail out */ if (symlink_count++ > 8) { printf("Symlink recursion, aborting "); 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 */ |
ef37c6835 ubifs: Correct de... |
532 |
sprintf(buf, "%s/%s", |
9d7952e4c ubifs: Add suppor... |
533 534 535 536 537 |
link_name, next == NULL ? "" : next); memcpy(symlinkpath, buf, sizeof(buf)); next = name = symlinkpath; continue; } |
9eefe2a2b UBIFS: Implement ... |
538 539 540 541 542 543 |
/* * Check if directory with this name exists */ /* Found the node! */ |
9d7952e4c ubifs: Add suppor... |
544 545 |
if (!next || *next == '\0') return inum; |
9eefe2a2b UBIFS: Implement ... |
546 547 548 549 550 551 552 |
root_inum = inum; name = next; } return 0; } |
4101f6879 dm: Drop the bloc... |
553 |
int ubifs_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info) |
29cc5bcad ubifs: Add functi... |
554 555 556 557 558 559 560 561 |
{ if (rbdd) { debug("UBIFS cannot be used with normal block devices "); return -1; } /* |
e35929e4a dm: blk: Rename g... |
562 |
* Should never happen since blk_get_device_part_str() already checks |
29cc5bcad ubifs: Add functi... |
563 564 565 566 567 568 569 570 571 572 |
* this, but better safe then sorry. */ if (!ubifs_is_mounted()) { debug("UBIFS not mounted, use ubifsmount to mount volume first! "); return -1; } return 0; } |
ad15749b6 ubifs: Modify ubi... |
573 |
int ubifs_ls(const char *filename) |
9eefe2a2b UBIFS: Implement ... |
574 575 576 577 578 579 580 581 582 583 |
{ struct ubifs_info *c = ubifs_sb->s_fs_info; struct file *file; struct dentry *dentry; struct inode *dir; void *dirent = NULL; unsigned long inum; int ret = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); |
ad15749b6 ubifs: Modify ubi... |
584 |
inum = ubifs_findfile(ubifs_sb, (char *)filename); |
9eefe2a2b UBIFS: Implement ... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
if (!inum) { ret = -1; goto out; } file = kzalloc(sizeof(struct file), 0); dentry = kzalloc(sizeof(struct dentry), 0); dir = kzalloc(sizeof(struct inode), 0); if (!file || !dentry || !dir) { printf("%s: Error, no memory for malloc! ", __func__); ret = -ENOMEM; goto out_mem; } dir->i_sb = ubifs_sb; file->f_path.dentry = dentry; file->f_path.dentry->d_parent = dentry; file->f_path.dentry->d_inode = dir; file->f_path.dentry->d_inode->i_ino = inum; file->f_pos = 1; file->private_data = NULL; ubifs_printdir(file, dirent); out_mem: if (file) free(file); if (dentry) free(dentry); if (dir) free(dir); out: ubi_close_volume(c->ubi); return ret; } |
29cc5bcad ubifs: Add functi... |
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
int ubifs_exists(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); ubi_close_volume(c->ubi); return inum != 0; } int ubifs_size(const char *filename, loff_t *size) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; int err = 0; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; } inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld! ", __func__, inum); err = PTR_ERR(inode); goto out; } *size = inode->i_size; ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; } |
9eefe2a2b UBIFS: Implement ... |
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 |
/* * ubifsload... */ /* file.c */ static inline void *kmap(struct page *page) { return page->addr; } static int read_block(struct inode *inode, void *addr, unsigned int block, struct ubifs_data_node *dn) { struct ubifs_info *c = inode->i_sb->s_fs_info; int err, len, out_len; union ubifs_key key; unsigned int dlen; data_key_init(c, &key, inode->i_ino, block); err = ubifs_tnc_lookup(c, &key, dn); if (err) { if (err == -ENOENT) /* Not found, so it must be a hole */ memset(addr, 0, UBIFS_BLOCK_SIZE); return err; } ubifs_assert(le64_to_cpu(dn->ch.sqnum) > ubifs_inode(inode)->creat_sqnum); len = le32_to_cpu(dn->size); if (len <= 0 || len > UBIFS_BLOCK_SIZE) goto dump; dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; out_len = UBIFS_BLOCK_SIZE; |
0195a7bb3 ubi,ubifs: sync w... |
699 |
err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len, |
9eefe2a2b UBIFS: Implement ... |
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 |
le16_to_cpu(dn->compr_type)); if (err || len != out_len) goto dump; /* * Data length can be less than a full block, even for blocks that are * not the last in the file (e.g., as a result of making a hole and * appending data). Ensure that the remainder is zeroed out. */ if (len < UBIFS_BLOCK_SIZE) memset(addr + len, 0, UBIFS_BLOCK_SIZE - len); return 0; dump: |
0195a7bb3 ubi,ubifs: sync w... |
715 |
ubifs_err(c, "bad data node (block %u, inode %lu)", |
9eefe2a2b UBIFS: Implement ... |
716 |
block, inode->i_ino); |
ff94bc40a mtd, ubi, ubifs: ... |
717 |
ubifs_dump_node(c, dn); |
9eefe2a2b UBIFS: Implement ... |
718 719 |
return -EINVAL; } |
b1a14f8a1 UBIFS: Change ubi... |
720 721 |
static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page, int last_block_size) |
9eefe2a2b UBIFS: Implement ... |
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
{ void *addr; int err = 0, i; unsigned int block, beyond; struct ubifs_data_node *dn; loff_t i_size = inode->i_size; dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, i_size); addr = kmap(page); block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; if (block >= beyond) { /* Reading beyond inode */ memset(addr, 0, PAGE_CACHE_SIZE); goto out; } dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); |
165f9859b ubifs: fix small ... |
743 744 |
if (!dn) return -ENOMEM; |
9eefe2a2b UBIFS: Implement ... |
745 746 747 748 749 750 751 752 753 754 |
i = 0; while (1) { int ret; if (block >= beyond) { /* Reading beyond inode */ err = -ENOENT; memset(addr, 0, UBIFS_BLOCK_SIZE); } else { |
b1a14f8a1 UBIFS: Change ubi... |
755 756 757 758 759 760 761 762 763 764 765 766 767 768 |
/* * Reading last block? Make sure to not write beyond * the requested size in the destination buffer. */ if (((block + 1) == beyond) || last_block_size) { void *buff; int dlen; /* * We need to buffer the data locally for the * last block. This is to not pad the * destination area to a multiple of * UBIFS_BLOCK_SIZE. */ |
4519668b2 mtd/nand/ubi: ass... |
769 |
buff = malloc_cache_aligned(UBIFS_BLOCK_SIZE); |
b1a14f8a1 UBIFS: Change ubi... |
770 771 772 773 774 |
if (!buff) { printf("%s: Error, malloc fails! ", __func__); err = -ENOMEM; |
9eefe2a2b UBIFS: Implement ... |
775 |
break; |
b1a14f8a1 UBIFS: Change ubi... |
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 |
} /* Read block-size into temp buffer */ ret = read_block(inode, buff, block, dn); if (ret) { err = ret; if (err != -ENOENT) { free(buff); break; } } if (last_block_size) dlen = last_block_size; else dlen = le32_to_cpu(dn->size); /* Now copy required size back to dest */ memcpy(addr, buff, dlen); free(buff); } else { ret = read_block(inode, addr, block, dn); if (ret) { err = ret; if (err != -ENOENT) break; } |
9eefe2a2b UBIFS: Implement ... |
804 805 806 807 808 809 810 811 812 813 814 815 816 |
} } if (++i >= UBIFS_BLOCKS_PER_PAGE) break; block += 1; addr += UBIFS_BLOCK_SIZE; } if (err) { if (err == -ENOENT) { /* Not found, so it must be a hole */ dbg_gen("hole"); goto out_free; } |
0195a7bb3 ubi,ubifs: sync w... |
817 |
ubifs_err(c, "cannot read page %lu of inode %lu, error %d", |
9eefe2a2b UBIFS: Implement ... |
818 819 820 821 822 823 824 825 826 827 828 829 830 |
page->index, inode->i_ino, err); goto error; } out_free: kfree(dn); out: return 0; error: kfree(dn); return err; } |
ad15749b6 ubifs: Modify ubi... |
831 832 |
int ubifs_read(const char *filename, void *buf, loff_t offset, loff_t size, loff_t *actread) |
9eefe2a2b UBIFS: Implement ... |
833 834 835 836 837 838 839 840 |
{ struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; struct inode *inode; struct page page; int err = 0; int i; int count; |
b1a14f8a1 UBIFS: Change ubi... |
841 |
int last_block_size = 0; |
9eefe2a2b UBIFS: Implement ... |
842 |
|
ad15749b6 ubifs: Modify ubi... |
843 844 845 |
*actread = 0; if (offset & (PAGE_SIZE - 1)) { |
1381901e9 Fix spelling of "... |
846 847 |
printf("ubifs: Error offset must be a multiple of %d ", |
ad15749b6 ubifs: Modify ubi... |
848 849 850 |
PAGE_SIZE); return -1; } |
9eefe2a2b UBIFS: Implement ... |
851 |
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); |
9d7952e4c ubifs: Add suppor... |
852 853 |
/* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ |
ad15749b6 ubifs: Modify ubi... |
854 |
inum = ubifs_findfile(ubifs_sb, (char *)filename); |
9eefe2a2b UBIFS: Implement ... |
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 |
if (!inum) { err = -1; goto out; } /* * Read file inode */ inode = ubifs_iget(ubifs_sb, inum); if (IS_ERR(inode)) { printf("%s: Error reading inode %ld! ", __func__, inum); err = PTR_ERR(inode); goto out; } |
ad15749b6 ubifs: Modify ubi... |
870 871 872 873 874 875 876 |
if (offset > inode->i_size) { printf("ubifs: Error offset (%lld) > file-size (%lld) ", offset, size); err = -1; goto put_inode; } |
9eefe2a2b UBIFS: Implement ... |
877 |
/* |
9eefe2a2b UBIFS: Implement ... |
878 879 880 |
* If no size was specified or if size bigger than filesize * set size to filesize */ |
ad15749b6 ubifs: Modify ubi... |
881 882 |
if ((size == 0) || (size > (inode->i_size - offset))) size = inode->i_size - offset; |
9eefe2a2b UBIFS: Implement ... |
883 884 |
count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; |
9eefe2a2b UBIFS: Implement ... |
885 |
|
ad15749b6 ubifs: Modify ubi... |
886 887 |
page.addr = buf; page.index = offset / PAGE_SIZE; |
9eefe2a2b UBIFS: Implement ... |
888 889 |
page.inode = inode; for (i = 0; i < count; i++) { |
b1a14f8a1 UBIFS: Change ubi... |
890 891 892 893 894 895 896 |
/* * Make sure to not read beyond the requested size */ if (((i + 1) == count) && (size < inode->i_size)) last_block_size = size - (i * PAGE_SIZE); err = do_readpage(c, inode, &page, last_block_size); |
9eefe2a2b UBIFS: Implement ... |
897 898 899 900 901 902 |
if (err) break; page.addr += PAGE_SIZE; page.index++; } |
ad15749b6 ubifs: Modify ubi... |
903 |
if (err) { |
9eefe2a2b UBIFS: Implement ... |
904 905 |
printf("Error reading file '%s' ", filename); |
ad15749b6 ubifs: Modify ubi... |
906 907 908 |
*actread = i * PAGE_SIZE; } else { *actread = size; |
46d7274cd UBIFS: Change ubi... |
909 |
} |
9eefe2a2b UBIFS: Implement ... |
910 |
|
ad15749b6 ubifs: Modify ubi... |
911 |
put_inode: |
9eefe2a2b UBIFS: Implement ... |
912 913 914 915 916 917 |
ubifs_iput(inode); out: ubi_close_volume(c->ubi); return err; } |
ad15749b6 ubifs: Modify ubi... |
918 |
|
29cc5bcad ubifs: Add functi... |
919 920 921 |
void ubifs_close(void) { } |
ad15749b6 ubifs: Modify ubi... |
922 923 924 925 926 927 928 929 |
/* Compat wrappers for common/cmd_ubifs.c */ int ubifs_load(char *filename, u32 addr, u32 size) { loff_t actread; int err; printf("Loading file '%s' to addr 0x%08x... ", filename, addr); |
34cc30af2 fs: usbifs: Fix w... |
930 |
err = ubifs_read(filename, (void *)(uintptr_t)addr, 0, size, &actread); |
ad15749b6 ubifs: Modify ubi... |
931 |
if (err == 0) { |
018f53032 env: Rename commo... |
932 |
env_set_hex("filesize", actread); |
ad15749b6 ubifs: Modify ubi... |
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 |
printf("Done "); } return err; } void uboot_ubifs_umount(void) { if (ubifs_sb) { printf("Unmounting UBIFS volume %s! ", ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name); ubifs_umount(ubifs_sb->s_fs_info); ubifs_sb = NULL; } } |