📄 intrep.c
字号:
}/* Used for traversing all nodes in the hash table. */intjffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *)){ struct jffs_file *f; struct jffs_file *next_f; int pos; int r; int result = 0; for (pos = 0; pos < c->hash_len; pos++) { for (f = c->hash[pos]; f; f = next_f) { /* We need a reference to the next file in the list because `func' might remove the current file `f'. */ next_f = f->hash_next; if ((r = func(f)) < 0) { return r; } result += r; } } return result;}/* Free all memory associated with a file. */intjffs_free_node_list(struct jffs_file *f){ struct jffs_node *node; struct jffs_node *p; D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n", f->ino, (f->name ? f->name : ""))); node = f->version_head; while (node) { p = node; node = node->version_next; kfree(p); DJM(no_jffs_node--); } return 0;}/* See if a file is deleted. If so, mark that file's nodes as obsolete. */intjffs_possibly_delete_file(struct jffs_file *f){ struct jffs_node *n; D3(printk("jffs_possibly_delete_file(): ino: %u\n", f->ino)); ASSERT(if (!f) { printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n"); return -1; }); if (f->deleted) { /* First try to remove all older versions. */ for (n = f->version_head; n; n = n->version_next) { if (!n->fm) { continue; } if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) { break; } } /* Unlink the file from the filesystem. */ jffs_unlink_file_from_tree(f); jffs_unlink_file_from_hash(f); jffs_free_node_list(f); if (f->name) { kfree(f->name); DJM(no_name--); } kfree(f); DJM(no_jffs_file--); } return 0;}/* Used in conjunction with jffs_foreach_file() to count the number of files in the file system. */intjffs_file_count(struct jffs_file *f){ return 1;}/* Build up a file's range list from scratch by going through the version list. */intjffs_build_file(struct jffs_file *f){ struct jffs_node *n; D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n", f->ino, (f->name ? f->name : ""))); for (n = f->version_head; n; n = n->version_next) { jffs_update_file(f, n); } return 0;}/* Remove an amount of data from a file. If this amount of data is zero, that could mean that a node should be split in two parts. We remove or change the appropriate nodes in the lists. Starting offset of area to be removed is node->data_offset, and the length of the area is in node->removed_size. */static voidjffs_delete_data(struct jffs_file *f, struct jffs_node *node){ struct jffs_node *n; __u32 offset = node->data_offset; __u32 remove_size = node->removed_size; D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n", offset, remove_size)); if (remove_size == 0 && f->range_tail && f->range_tail->data_offset + f->range_tail->data_size == offset) { /* A simple append; nothing to remove or no node to split. */ return; } /* Find the node where we should begin the removal. */ for (n = f->range_head; n; n = n->range_next) { if (n->data_offset + n->data_size > offset) { break; } } if (!n) { /* If there's no data in the file there's no data to remove either. */ return; } if (n->data_offset > offset) { /* XXX: Not implemented yet. */ printk(KERN_WARNING "JFFS: An unexpected situation " "occurred in jffs_delete_data.\n"); } else if (n->data_offset < offset) { /* See if the node has to be split into two parts. */ if (n->data_offset + n->data_size < offset + remove_size) { /* Do the split. */ struct jffs_node *new_node; D3(printk("jffs_delete_data(): Split node with " "version number %u.\n", n->version)); if (!(new_node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) { D(printk("jffs_delete_data(): -ENOMEM\n")); return; } DJM(no_jffs_node++); new_node->ino = n->ino; new_node->version = n->version; new_node->data_offset = offset; new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset)); new_node->fm_offset = n->fm_offset + n->data_size + remove_size; new_node->name_size = n->name_size; new_node->fm = n->fm; new_node->version_prev = n; new_node->version_next = n->version_next; if (new_node->version_next) { new_node->version_next->version_prev = new_node; } else { f->version_tail = new_node; } n->version_next = new_node; new_node->range_prev = n; new_node->range_next = n->range_next; if (new_node->range_next) { new_node->range_next->range_prev = new_node; } else { f->range_tail = new_node; } /* A very interesting can of worms. */ n->range_next = new_node; n->data_size = offset - n->data_offset; jffs_add_node(new_node); n = new_node->range_next; remove_size = 0; } else { /* No. No need to split the node. Just remove the end of the node. */ int r = jffs_min(n->data_offset + n->data_size - offset, remove_size); n->data_size -= r; remove_size -= r; n = n->range_next; } } /* Remove as many nodes as necessary. */ while (n && remove_size) { if (n->data_size <= remove_size) { struct jffs_node *p = n; remove_size -= n->data_size; n = n->range_next; D3(printk("jffs_delete_data(): Removing node: " "ino: %u, version: %u\n", p->ino, p->version)); if (p->fm) { jffs_fmfree(f->c->fmc, p->fm, p); } jffs_unlink_node_from_range_list(f, p); jffs_unlink_node_from_version_list(f, p); kfree(p); DJM(no_jffs_node--); } else { n->data_size -= remove_size; n->fm_offset += remove_size; n->data_offset -= (node->removed_size - remove_size); n = n->range_next; break; } } /* Adjust the following nodes' information about offsets etc. */ while (n && node->removed_size) { n->data_offset -= node->removed_size; n = n->range_next; } f->size -= node->removed_size; D3(printk("jffs_delete_data(): f->size = %d\n", f->size));} /* jffs_delete_data() *//* Insert some data into a file. Prior to the call to this function, jffs_delete_data() should be called. */static voidjffs_insert_data(struct jffs_file *f, struct jffs_node *node){ D3(printk("jffs_insert_data(): node->data_offset = %u, " "node->data_size = %u, f->size = %u\n", node->data_offset, node->data_size, f->size)); /* Find the position where we should insert data. */ if (node->data_offset == f->size) { /* A simple append. This is the most common operation. */ node->range_next = 0; node->range_prev = f->range_tail; if (node->range_prev) { node->range_prev->range_next = node; } f->range_tail = node; f->size += node->data_size; if (!f->range_head) { f->range_head = node; } } else if (node->data_offset < f->size) { /* Trying to insert data into the middle of the file. This means no problem because jffs_delete_data() has already prepared the range list for us. */ struct jffs_node *n; /* Find the correct place for the insertion and then insert the node. */ for (n = f->range_head; n; n = n->range_next) { D1(printk("Cool stuff's happening!\n")); if (n->data_offset == node->data_offset) { node->range_prev = n->range_prev; if (node->range_prev) { node->range_prev->range_next = node; } else { f->range_head = node; } node->range_next = n; n->range_prev = node; break; } ASSERT(else if (n->data_offset + n->data_size > node->data_offset) { printk(KERN_ERR "jffs_insert_data(): " "Couldn't find a place to insert " "the data!\n"); return; }); } /* Adjust later nodes' offsets etc. */ n = node->range_next; while (n) { n->data_offset += node->data_size; n = n->range_next; } f->size += node->data_size; } else if (node->data_offset > f->size) { /* Not implemented yet. */#if 0 /* Below is some example code for future use if we decide to implement it. */ /* This is code that isn't supported by VFS. So there aren't really any reasons to implement it yet. */ if (!f->range_head) { if (node->data_offset > f->size) { if (!(nn = jffs_alloc_node())) { D(printk("jffs_insert_data(): " "Allocation failed.\n")); return; } nn->version = JFFS_MAGIC_BITMASK; nn->data_offset = 0; nn->data_size = node->data_offset; nn->removed_size = 0; nn->fm_offset = 0; nn->name_size = 0; nn->fm = 0; /* This is a virtual data holder. */ nn->version_prev = 0; nn->version_next = 0; nn->range_prev = 0; nn->range_next = 0; nh->range_head = nn; nh->range_tail = nn; } }#endif } D3(printk("jffs_insert_data(): f->size = %d\n", f->size));}/* A new node (with data) has been added to the file and now the range list has to be modified. */static intjffs_update_file(struct jffs_file *f, struct jffs_node *node){ D3(printk("jffs_update_file(): ino: %u, version: %u\n", f->ino, node->version)); if (node->data_size == 0) { if (node->removed_size == 0) { /* data_offset == X */ /* data_size == 0 */ /* remove_size == 0 */ } else { /* data_offset == X */ /* data_size == 0 */ /* remove_size != 0 */ jffs_delete_data(f, node); } } else { /* data_offset == X */ /* data_size != 0 */ /* remove_size == Y */ jffs_delete_data(f, node); jffs_insert_data(f, node); } return 0;}/* Print the contents of a node. */voidjffs_print_node(struct jffs_node *n){ D(printk("jffs_node: 0x%p\n", n)); D(printk("{\n")); D(printk(" 0x%08x, /* version */\n", n->version)); D(printk(" 0x%08x, /* data_offset */\n", n->data_offset)); D(printk(" 0x%08x, /* data_size */\n", n->data_size)); D(printk(" 0x%08x, /* removed_size */\n", n->removed_size)); D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset)); D(printk(" 0x%02x, /* name_size */\n", n->name_size)); D(printk(" 0x%p, /* fm, fm->offset: %u */\n", n->fm, n->fm->offset)); D(printk(" 0x%p, /* version_prev */\n", n->version_prev)); D(printk(" 0x%p, /* version_next */\n", n->version_next)); D(printk(" 0x%p, /* range_prev */\n", n->range_prev)); D(printk(" 0x%p, /* range_next */\n", n->range_next)); D(printk("}\n"));}/* Print the contents of a raw inode. */voidjffs_print_raw_inode(struct jffs_raw_inode *raw_inode){ D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino)); D(printk("{\n")); D(printk(" 0x%08x, /* magic */\n", raw_inode->magic)); D(printk(" 0x%08x, /* ino */\n", raw_inode->ino)); D(printk(" 0x%08x, /* pino */\n", raw_inode->pino)); D(printk(" 0x%08x, /* version */\n", raw_inode->version)); D(printk(" 0x%08x, /* mode */\n", raw_inode->mode)); D(printk(" 0x%04x, /* uid */\n", raw_inode->uid)); D(printk(" 0x%04x, /* gid */\n", raw_inode->gid)); D(printk(" 0x%08x, /* atime */\n", raw_inode->atime)); D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime)); D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime)); D(printk(" 0x%08x, /* offset */\n", raw_inode->offset)); D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize)); D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize)); D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize)); D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink)); D(printk(" 0x%02x, /* spare */\n", raw_inode->spare)); D(printk(" %u, /* rename */\n", raw_inode->rename)); D(printk(" %u, /* deleted */\n", raw_inode->deleted)); D(printk(" 0x%02x, /* accurate */\n", raw_inode->accurate)); D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum)); D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum)); D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum)); D(printk("}\n"));}/* Print the contents of a file. */intjffs_print_file(struct jffs_file *f){ D(int i); D(printk("jffs_file: 0x%p\n", f)); D(printk("{\n")); D(printk(" 0x%08x, /* ino */\n", f->ino)); D(printk(" 0x%08x, /* pino */\n", f->pino)); D(printk(" 0x%08x, /* mode */\n", f->mode)); D(printk(" 0x%04x, /* uid */\n", f->uid)); D(printk(" 0x%04x, /* gid */\n", f->gid)); D(printk(" 0x%08x, /* atime */\n", f->atime)); D(printk(" 0x%08x, /* mtime */\n", f->mtime)); D(printk(" 0x%08x, /* ctime */\n", f->ctime)); D(printk(" 0x%02x, /* nsize */\n", f->nsize)); D(printk(" 0x%02x, /* nlink */\n", f->nlink)); D(printk(" 0x%02x, /* deleted */\n", f->deleted)); D(printk(" \"%s\", ", (f->name ? f->name : ""))); D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) { printk(" "); }); D(printk("/* name */\n")); D(printk(" 0x%08x, /* size */\n", f->size)); D(printk(" 0x%08x, /* highest_version */\n", f->highest_version)); D(printk(" 0x%p, /* c */\n", f->c)); D(printk(" 0x%p, /* parent */\n", f->parent)); D(printk(" 0x%p, /* children */\n", f->children)); D(printk(" 0x%p, /* sibling_prev */\n", f->sibling_prev)); D(printk(" 0x%p, /* sibling_next */\n", f->sibling_next)); D(printk(" 0x%p, /* hash_prev */\n", f->hash_prev)); D(printk(" 0x%p, /* hash_next */\n", f->hash_next)); D(printk(" 0x%p, /* range_head */\n", f->range_head)); D(printk(" 0x%p, /* range_tail */\n", f->range_tail)); D(printk(" 0x%p, /* version_head */\n", f->version_head)); D(printk("
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -