fs/udf/directory.c

Source file repositories/reference/linux-study-clean/fs/udf/directory.c

File Facts

System
Linux kernel
Corpus path
fs/udf/directory.c
Extension
.c
Size
14427 bytes
Lines
544
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

sizeof(struct tag) + le16_to_cpu(iter->fi.descTag.descCRCLength)) {
		udf_err(iter->dir->i_sb,
			"directory (ino %llu) has entry where CRC length (%u) does not match entry length (%u)\n",
			iter->dir->i_ino,
			(unsigned)le16_to_cpu(iter->fi.descTag.descCRCLength),
			(unsigned)(udf_dir_entry_len(&iter->fi) -
							sizeof(struct tag)));
		return -EFSCORRUPTED;
	}
	return 0;
}

static int udf_copy_fi(struct udf_fileident_iter *iter)
{
	struct udf_inode_info *iinfo = UDF_I(iter->dir);
	u32 blksize = 1 << iter->dir->i_blkbits;
	u32 off, len, nameoff;
	int err;

	/* Skip copying when we are at EOF */
	if (iter->pos >= iter->dir->i_size) {
		iter->name = NULL;
		return 0;
	}
	if (iter->dir->i_size < iter->pos + sizeof(struct fileIdentDesc)) {
		udf_err(iter->dir->i_sb,
			"directory (ino %llu) has entry straddling EOF\n",
			iter->dir->i_ino);
		return -EFSCORRUPTED;
	}
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		memcpy(&iter->fi, iinfo->i_data + iinfo->i_lenEAttr + iter->pos,
		       sizeof(struct fileIdentDesc));
		err = udf_verify_fi(iter);
		if (err < 0)
			return err;
		iter->name = iinfo->i_data + iinfo->i_lenEAttr + iter->pos +
			sizeof(struct fileIdentDesc) +
			le16_to_cpu(iter->fi.lengthOfImpUse);
		return 0;
	}

	off = iter->pos & (blksize - 1);
	len = min_t(u32, sizeof(struct fileIdentDesc), blksize - off);
	memcpy(&iter->fi, iter->bh[0]->b_data + off, len);
	if (len < sizeof(struct fileIdentDesc))
		memcpy((char *)(&iter->fi) + len, iter->bh[1]->b_data,
		       sizeof(struct fileIdentDesc) - len);
	err = udf_verify_fi(iter);
	if (err < 0)
		return err;

	/* Handle directory entry name */
	nameoff = off + sizeof(struct fileIdentDesc) +
				le16_to_cpu(iter->fi.lengthOfImpUse);
	if (off + udf_dir_entry_len(&iter->fi) <= blksize) {
		iter->name = iter->bh[0]->b_data + nameoff;
	} else if (nameoff >= blksize) {
		iter->name = iter->bh[1]->b_data + (nameoff - blksize);
	} else {
		iter->name = iter->namebuf;
		len = blksize - nameoff;
		memcpy(iter->name, iter->bh[0]->b_data + nameoff, len);
		memcpy(iter->name + len, iter->bh[1]->b_data,
		       iter->fi.lengthFileIdent - len);
	}
	return 0;
}

/* Readahead 8k once we are at 8k boundary */
static void udf_readahead_dir(struct udf_fileident_iter *iter)
{
	unsigned int ralen = 16 >> (iter->dir->i_blkbits - 9);
	struct buffer_head *tmp, *bha[16];
	int i, num;
	udf_pblk_t blk;

	if (iter->loffset & (ralen - 1))
		return;

	if (iter->loffset + ralen > (iter->elen >> iter->dir->i_blkbits))
		ralen = (iter->elen >> iter->dir->i_blkbits) - iter->loffset;
	num = 0;
	for (i = 0; i < ralen; i++) {
		blk = udf_get_lb_pblock(iter->dir->i_sb, &iter->eloc,
					iter->loffset + i);
		tmp = sb_getblk(iter->dir->i_sb, blk);
		if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
			bha[num++] = tmp;
		else

Annotation

Implementation Notes