Beispiel #1
0
int
attr_sf_entry_size(
	void			*obj,
	int			startoff,
	int			idx)
{
	xfs_attr_sf_entry_t	*e;
	int			i;
	xfs_attr_shortform_t	*sf;

	ASSERT(bitoffs(startoff) == 0);
	sf = (xfs_attr_shortform_t *)((char *)obj + byteize(startoff));
	e = &sf->list[0];
	for (i = 0; i < idx; i++)
		e = XFS_ATTR_SF_NEXTENTRY(e);
	return bitize((int)XFS_ATTR_SF_ENTSIZE(e));
}
Beispiel #2
0
int
xfs_attr_sf_entsize(xfs_attr_sf_entry_t *sfep)
{
    return XFS_ATTR_SF_ENTSIZE(sfep);
}
Beispiel #3
0
/*
 * this routine validates the attributes in shortform format.
 * a non-zero return repair value means certain attributes are bogus
 * and were cleared if possible. Warnings do not generate error conditions
 * if you cannot modify the structures. repair is set to 1, if anything
 * was fixed.
 */
static int
process_shortform_attr(
	struct xfs_mount *mp,
	xfs_ino_t	ino,
	xfs_dinode_t	*dip,
	int		*repair)
{
	xfs_attr_shortform_t	*asf;
	xfs_attr_sf_entry_t	*currententry, *nextentry, *tempentry;
	int			i, junkit;
	int			currentsize, remainingspace;

	*repair = 0;

	asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR(dip);

	/* Assumption: hdr.totsize is less than a leaf block and was checked
	 * by lclinode for valid sizes. Check the count though.
	*/
	if (asf->hdr.count == 0)
		/* then the total size should just be the header length */
		if (be16_to_cpu(asf->hdr.totsize) != sizeof(xfs_attr_sf_hdr_t)) {
			/* whoops there's a discrepancy. Clear the hdr */
			if (!no_modify) {
				do_warn(
	_("there are no attributes in the fork for inode %" PRIu64 "\n"),
					ino);
				asf->hdr.totsize =
					cpu_to_be16(sizeof(xfs_attr_sf_hdr_t));
				*repair = 1;
				return(1);
			} else {
				do_warn(
	_("would junk the attribute fork since count is 0 for inode %" PRIu64 "\n"),
					ino);
				return(1);
			}
		}

	currentsize = sizeof(xfs_attr_sf_hdr_t);
	remainingspace = be16_to_cpu(asf->hdr.totsize) - currentsize;
	nextentry = &asf->list[0];
	for (i = 0; i < asf->hdr.count; i++)  {
		currententry = nextentry;
		junkit = 0;

		/* don't go off the end if the hdr.count was off */
		if ((currentsize + (sizeof(xfs_attr_sf_entry_t) - 1)) >
						be16_to_cpu(asf->hdr.totsize))
			break; /* get out and reset count and totSize */

		/* if the namelen is 0, can't get to the rest of the entries */
		if (currententry->namelen == 0) {
			do_warn(_("zero length name entry in attribute fork,"));
			if (!no_modify) {
				do_warn(
	_(" truncating attributes for inode %" PRIu64 " to %d\n"), ino, i);
				*repair = 1;
				break;	/* and then update hdr fields */
			} else {
				do_warn(
	_(" would truncate attributes for inode %" PRIu64 " to %d\n"), ino, i);
				break;
			}
		} else {
			/* It's okay to have a 0 length valuelen, but do a
			 * rough check to make sure we haven't gone outside of
			 * totsize.
			 */
			if (remainingspace < currententry->namelen ||
					((remainingspace - currententry->
					namelen) < currententry->valuelen)) {
				do_warn(
	_("name or value attribute lengths are too large,\n"));
				if (!no_modify) {
					do_warn(
	_(" truncating attributes for inode %" PRIu64 " to %d\n"),
						ino, i);
					*repair = 1;
					break; /* and then update hdr fields */
				} else {
					do_warn(
	_(" would truncate attributes for inode %" PRIu64 " to %d\n"),
						ino, i);
					break;
				}
			}
		}

		/* namecheck checks for / and null terminated for file names.
		 * attributes names currently follow the same rules.
		*/
		if (namecheck((char *)&currententry->nameval[0],
						currententry->namelen))  {
			do_warn(
	_("entry contains illegal character in shortform attribute name\n"));
			junkit = 1;
		}

		if (currententry->flags & XFS_ATTR_INCOMPLETE) {
			do_warn(
	_("entry has INCOMPLETE flag on in shortform attribute\n"));
			junkit = 1;
		}

		/* Only check values for root security attributes */
		if (currententry->flags & XFS_ATTR_ROOT)
		       junkit |= valuecheck(mp,
					(char *)&currententry->nameval[0],
					NULL, currententry->namelen,
					currententry->valuelen);

		remainingspace = remainingspace -
					XFS_ATTR_SF_ENTSIZE(currententry);

		if (junkit) {
			if (!no_modify) {
				/* get rid of only this entry */
				do_warn(
	_("removing attribute entry %d for inode %" PRIu64 "\n"),
					i, ino);
				tempentry = (xfs_attr_sf_entry_t *)
					((intptr_t) currententry +
					 XFS_ATTR_SF_ENTSIZE(currententry));
				memmove(currententry,tempentry,remainingspace);
				asf->hdr.count -= 1;
				i--; /* no worries, it will wrap back to 0 */
				*repair = 1;
				continue; /* go back up now */
			} else {
				do_warn(
	_("would remove attribute entry %d for inode %" PRIu64 "\n"),
					i, ino);
			}
		}

		/* Let's get ready for the next entry... */
		nextentry = (xfs_attr_sf_entry_t *)((intptr_t) nextentry +
			 		XFS_ATTR_SF_ENTSIZE(currententry));
		currentsize = currentsize + XFS_ATTR_SF_ENTSIZE(currententry);

	} /* end the loop */

	if (asf->hdr.count != i)  {
		if (no_modify)  {
			do_warn(
	_("would have corrected attribute entry count in inode %" PRIu64 " from %d to %d\n"),
				ino, asf->hdr.count, i);
		} else  {
			do_warn(
	_("corrected attribute entry count in inode %" PRIu64 ", was %d, now %d\n"),
				ino, asf->hdr.count, i);
			asf->hdr.count = i;
			*repair = 1;
		}
	}

	/* ASSUMPTION: currentsize <= totsize */
	if (be16_to_cpu(asf->hdr.totsize) != currentsize)  {
		if (no_modify)  {
			do_warn(
	_("would have corrected attribute totsize in inode %" PRIu64 " from %d to %d\n"),
				ino, be16_to_cpu(asf->hdr.totsize),
				currentsize);
		} else  {
			do_warn(
	_("corrected attribute entry totsize in inode %" PRIu64 ", was %d, now %d\n"),
				ino, be16_to_cpu(asf->hdr.totsize),
				currentsize);
			asf->hdr.totsize = cpu_to_be16(currentsize);
			*repair = 1;
		}
	}

	return(*repair);
}