// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/adfs/dir_f.c * * Copyright (C) 1997-1999 Russell King * * E and F format directory handling
*/ #include"adfs.h" #include"dir_f.h"
/* * Read an (unaligned) value of length 1..4 bytes
*/ staticinlineunsignedint adfs_readval(unsignedchar *p, int len)
{ unsignedint val = 0;
switch (len) { case 4: val |= p[3] << 24;
fallthrough; case 3: val |= p[2] << 16;
fallthrough; case 2: val |= p[1] << 8;
fallthrough; default: val |= p[0];
} return val;
}
staticinlinevoid adfs_writeval(unsignedchar *p, int len, unsignedint val)
{ switch (len) { case 4: p[3] = val >> 24;
fallthrough; case 3: p[2] = val >> 16;
fallthrough; case 2: p[1] = val >> 8;
fallthrough; default: p[0] = val;
}
}
/* * There are some algorithms that are nice in * assembler, but a bitch in C... This is one * of them.
*/ static u8
adfs_dir_checkbyte(conststruct adfs_dir *dir)
{ struct buffer_head * const *bh = dir->bh; constint blocksize_bits = dir->sb->s_blocksize_bits; union { __le32 *ptr32; u8 *ptr8; } ptr, end;
u32 dircheck = 0; int last = 5 - 26; int i = 0;
/* * Accumulate each word up to the last whole * word of the last directory entry. This * can spread across several buffer heads.
*/ do {
last += 26; do {
dircheck = le32_to_cpu(dir_u32(i)) ^ ror13(dircheck);
i += sizeof(u32);
} while (i < (last & ~3));
} while (dir_u8(last) != 0);
/* * Accumulate the last few bytes. These * bytes will be within the same bh.
*/ if (i != last) {
ptr.ptr8 = bufoff(bh, i);
end.ptr8 = ptr.ptr8 + last - i;
do {
dircheck = *ptr.ptr8++ ^ ror13(dircheck);
} while (ptr.ptr8 < end.ptr8);
}
/* * The directory tail is in the final bh * Note that contary to the RISC OS PRMs, * the first few bytes are NOT included * in the check. All bytes are in the * same bh.
*/
ptr.ptr8 = bufoff(bh, 2008);
end.ptr8 = ptr.ptr8 + 36;
do {
__le32 v = *ptr.ptr32++;
dircheck = le32_to_cpu(v) ^ ror13(dircheck);
} while (ptr.ptr32 < end.ptr32);
/* * convert a Linux ADFS directory entry to a disk-based directory entry
*/ staticinlinevoid
adfs_obj2dir(struct adfs_direntry *de, struct object_info *obj)
{
adfs_writeval(de->dirinddiscadd, 3, obj->indaddr);
adfs_writeval(de->dirload, 4, obj->loadaddr);
adfs_writeval(de->direxec, 4, obj->execaddr);
adfs_writeval(de->dirlen, 4, obj->size);
de->newdiratts = obj->attr;
}
/* * get a directory entry. Note that the caller is responsible * for holding the relevant locks.
*/ staticint
__adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
{ struct adfs_direntry de; int ret;
ret = adfs_dir_copyfrom(&de, dir, pos, 26); if (ret) return ret;
/* Make sure the directory still validates correctly */
ret = adfs_f_validate(dir); if (ret)
adfs_msg(dir->sb, KERN_ERR, "error: update broke directory");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.