attrib.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,911 行 · 第 1/5 页
C
1,911 行
break; next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry + le16_to_cpu(al_entry->length)); if (le32_to_cpu(al_entry->type) > le32_to_cpu(type)) goto not_found; if (type != al_entry->type) continue; /* * If @name is present, compare the two names. If @name is * missing, assume we want an unnamed attribute. */ al_name_len = al_entry->name_length; al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset); if (!name) { if (al_name_len) goto not_found; } else if (!ntfs_are_names_equal(al_name, al_name_len, name, name_len, ic, vol->upcase, vol->upcase_len)) { register int rc; rc = ntfs_collate_names(name, name_len, al_name, al_name_len, 1, IGNORE_CASE, vol->upcase, vol->upcase_len); /* * If @name collates before al_name, there is no * matching attribute. */ if (rc == -1) goto not_found; /* If the strings are not equal, continue search. */ if (rc) continue; /* * FIXME: Reverse engineering showed 0, IGNORE_CASE but * that is inconsistent with ntfs_attr_find(). The * subsequent rc checks were also different. Perhaps I * made a mistake in one of the two. Need to recheck * which is correct or at least see what is going on... * (AIA) */ rc = ntfs_collate_names(name, name_len, al_name, al_name_len, 1, CASE_SENSITIVE, vol->upcase, vol->upcase_len); if (rc == -1) goto not_found; if (rc) continue; } /* * The names match or @name not present and attribute is * unnamed. Now check @lowest_vcn. Continue search if the * next attribute list entry still fits @lowest_vcn. Otherwise * we have reached the right one or the search has failed. */ if (lowest_vcn && (u8*)next_al_entry >= al_start && (u8*)next_al_entry + 6 < al_end && (u8*)next_al_entry + le16_to_cpu( next_al_entry->length) <= al_end && sle64_to_cpu(next_al_entry->lowest_vcn) <= lowest_vcn && next_al_entry->type == al_entry->type && next_al_entry->name_length == al_name_len && ntfs_are_names_equal((ntfschar*)((u8*) next_al_entry + next_al_entry->name_offset), next_al_entry->name_length, al_name, al_name_len, CASE_SENSITIVE, vol->upcase, vol->upcase_len)) continue; if (MREF_LE(al_entry->mft_reference) == ni->mft_no) { if (MSEQNO_LE(al_entry->mft_reference) != ni->seq_no) { ntfs_error(vol->sb, "Found stale mft " "reference in attribute list " "of base inode 0x%lx.%s", base_ni->mft_no, es); err = -EIO; break; } } else { /* Mft references do not match. */ /* If there is a mapped record unmap it first. */ if (ni != base_ni) unmap_extent_mft_record(ni); /* Do we want the base record back? */ if (MREF_LE(al_entry->mft_reference) == base_ni->mft_no) { ni = ctx->ntfs_ino = base_ni; ctx->mrec = ctx->base_mrec; } else { /* We want an extent record. */ ctx->mrec = map_extent_mft_record(base_ni, le64_to_cpu( al_entry->mft_reference), &ni); ctx->ntfs_ino = ni; if (IS_ERR(ctx->mrec)) { ntfs_error(vol->sb, "Failed to map " "extent mft record " "0x%lx of base inode " "0x%lx.%s", MREF_LE(al_entry-> mft_reference), base_ni->mft_no, es); err = PTR_ERR(ctx->mrec); if (err == -ENOENT) err = -EIO; break; } } ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + le16_to_cpu(ctx->mrec->attrs_offset)); } /* * ctx->vfs_ino, ctx->mrec, and ctx->attr now point to the * mft record containing the attribute represented by the * current al_entry. */ /* * We could call into ntfs_attr_find() to find the right * attribute in this mft record but this would be less * efficient and not quite accurate as ntfs_attr_find() ignores * the attribute instance numbers for example which become * important when one plays with attribute lists. Also, * because a proper match has been found in the attribute list * entry above, the comparison can now be optimized. So it is * worth re-implementing a simplified ntfs_attr_find() here. */ a = ctx->attr; /* * Use a manual loop so we can still use break and continue * with the same meanings as above. */do_next_attr_loop: if ((u8*)a < (u8*)ctx->mrec || (u8*)a > (u8*)ctx->mrec + le32_to_cpu(ctx->mrec->bytes_allocated)) break; if (a->type == AT_END) continue; if (!a->length) break; if (al_entry->instance != a->instance) goto do_next_attr; /* * If the type and/or the name are mismatched between the * attribute list entry and the attribute record, there is * corruption so we break and return error EIO. */ if (al_entry->type != a->type) break; if (!ntfs_are_names_equal((ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), a->name_length, al_name, al_name_len, CASE_SENSITIVE, vol->upcase, vol->upcase_len)) break; ctx->attr = a; /* * If no @val specified or @val specified and it matches, we * have found it! */ if (!val || (!a->non_resident && le32_to_cpu( a->data.resident.value_length) == val_len && !memcmp((u8*)a + le16_to_cpu(a->data.resident.value_offset), val, val_len))) { ntfs_debug("Done, found."); return 0; }do_next_attr: /* Proceed to the next attribute in the current mft record. */ a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length)); goto do_next_attr_loop; } if (!err) { ntfs_error(vol->sb, "Base inode 0x%lx contains corrupt " "attribute list attribute.%s", base_ni->mft_no, es); err = -EIO; } if (ni != base_ni) { unmap_extent_mft_record(ni); ctx->ntfs_ino = base_ni; ctx->mrec = ctx->base_mrec; ctx->attr = ctx->base_attr; } if (err != -ENOMEM) NVolSetErrors(vol); return err;not_found: /* * If we were looking for AT_END, we reset the search context @ctx and * use ntfs_attr_find() to seek to the end of the base mft record. */ if (type == AT_END) { ntfs_attr_reinit_search_ctx(ctx); return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len, ctx); } /* * The attribute was not found. Before we return, we want to ensure * @ctx->mrec and @ctx->attr indicate the position at which the * attribute should be inserted in the base mft record. Since we also * want to preserve @ctx->al_entry we cannot reinitialize the search * context using ntfs_attr_reinit_search_ctx() as this would set * @ctx->al_entry to NULL. Thus we do the necessary bits manually (see * ntfs_attr_init_search_ctx() below). Note, we _only_ preserve * @ctx->al_entry as the remaining fields (base_*) are identical to * their non base_ counterparts and we cannot set @ctx->base_attr * correctly yet as we do not know what @ctx->attr will be set to by * the call to ntfs_attr_find() below. */ if (ni != base_ni) unmap_extent_mft_record(ni); ctx->mrec = ctx->base_mrec; ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + le16_to_cpu(ctx->mrec->attrs_offset)); ctx->is_first = TRUE; ctx->ntfs_ino = base_ni; ctx->base_ntfs_ino = NULL; ctx->base_mrec = NULL; ctx->base_attr = NULL; /* * In case there are multiple matches in the base mft record, need to * keep enumerating until we get an attribute not found response (or * another error), otherwise we would keep returning the same attribute * over and over again and all programs using us for enumeration would * lock up in a tight loop. */ do { err = ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx); } while (!err); ntfs_debug("Done, not found."); return err;}/** * ntfs_attr_lookup - find an attribute in an ntfs inode * @type: attribute type to find * @name: attribute name to find (optional, i.e. NULL means don't care) * @name_len: attribute name length (only needed if @name present) * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only) * @val: attribute value to find (optional, resident attributes only) * @val_len: attribute value length * @ctx: search context with mft record and attribute to search from * * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must * be the base mft record and @ctx must have been obtained from a call to * ntfs_attr_get_search_ctx(). * * This function transparently handles attribute lists and @ctx is used to * continue searches where they were left off at. * * After finishing with the attribute/mft record you need to call * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any * mapped inodes, etc). * * Return 0 if the search was successful and -errno if not. * * When 0, @ctx->attr is the found attribute and it is in mft record * @ctx->mrec. If an attribute list attribute is present, @ctx->al_entry is * the attribute list entry of the found attribute. * * When -ENOENT, @ctx->attr is the attribute which collates just after the * attribute being searched for, i.e. if one wants to add the attribute to the * mft record this is the correct place to insert it into. If an attribute * list attribute is present, @ctx->al_entry is the attribute list entry which * collates just after the attribute list entry of the attribute being searched * for, i.e. if one wants to add the attribute to the mft record this is the * correct place to insert its attribute list entry into. * * When -errno != -ENOENT, an error occured during the lookup. @ctx->attr is * then undefined and in particular you should not rely on it not changing. */int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, const u32 name_len, const IGNORE_CASE_BOOL ic, const VCN lowest_vcn, const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx){ ntfs_inode *base_ni; ntfs_debug("Entering."); if (ctx->base_ntfs_ino) base_ni = ctx->base_ntfs_ino; else base_ni = ctx->ntfs_ino; /* Sanity check, just for debugging really. */ BUG_ON(!base_ni); if (!NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST) return ntfs_attr_find(type, name, name_len, ic, val, val_len, ctx); return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn, val, val_len, ctx);}/** * ntfs_attr_init_search_ctx - initialize an attribute search context * @ctx: attribute search context to initialize * @ni: ntfs inode with which to initialize the search context * @mrec: mft record with which to initialize the search context * * Initialize the attribute search context @ctx with @ni and @mrec. */static inline void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx, ntfs_inode *ni, MFT_RECORD *mrec){ ctx->mrec = mrec; /* Sanity checks are performed elsewhere. */ ctx->attr = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset)); ctx->is_first = TRUE; ctx->ntfs_ino = ni; ctx->al_entry = NULL; ctx->base_ntfs_ino = NULL; ctx->base_mrec = NULL; ctx->base_attr = NULL;}/** * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context * @ctx: attribute search context to reinitialize * * Reinitialize the attribute search context @ctx, unmapping an associated * extent mft record if present, and initialize the search context again. * * This is used when a search for a new attribute is being started to reset * the search context to the beginning. */void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx){ if (likely(!ctx->base_ntfs_ino)) { /* No attribute list. */ ctx->is_first = TRUE; /* Sanity checks are performed elsewhere. */ ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + le16_to_cpu(ctx->mrec->attrs_offset)); /* * This needs resetting due to ntfs_external_attr_find() which * can leave it set despite having zeroed ctx->base_ntfs_ino. */ ctx->al_entry = NULL; return; } /* Attribute list. */ if (ctx->ntfs_ino != ctx->base_ntfs_ino) unmap_extent_mft_record(ctx->ntfs_ino); ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec); return;}/** * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context * @ni: ntfs inode with which to initialize the search context * @mrec: mft record with which to initialize the search context * * Allocate a new attribute search context, initialize it with @ni and @mrec, * and return it. Return NULL if allocation failed. */ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec){ ntfs_attr_search_ctx *ctx; ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, SLAB_NOFS); if (ctx) ntfs_attr_init_search_ctx(ctx, ni, mrec); return ctx;}/** * ntfs_attr_put_search_ctx - release an attribute search context * @ctx: attribute search context to free * * Release the attribute search context @ctx, unmapping an associated extent * mft record if present. */void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx){ if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino) unmap_extent_mft_record(ctx->ntfs_ino); kmem_cache_free(ntfs_attr_ctx_cache, ctx); return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?