/* * Lookup/Create a block at offset 'block' into 'inode'. We currently do * not support creation of new blocks, so we return -EIO for this case.
*/ staticint
adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int create)
{ if (!create) { if (block >= inode->i_blocks) goto abort_toobig;
block = __adfs_block_map(inode->i_sb, ADFS_I(inode)->indaddr,
block); if (block)
map_bh(bh, inode->i_sb, block); return 0;
} /* don't support allocation of blocks yet */ return -EIO;
/* * Convert Linux permission to ADFS attribute. We try to do the reverse * of atts2mode, but there is not a 1:1 translation.
*/ staticint adfs_mode2atts(struct super_block *sb, struct inode *inode,
umode_t ia_mode)
{ struct adfs_sb_info *asb = ADFS_SB(sb);
umode_t mode; int attr;
/* FIXME: should we be able to alter a link? */ if (S_ISLNK(inode->i_mode)) return ADFS_I(inode)->attr;
/* Directories do not have read/write permissions on the media */ if (S_ISDIR(inode->i_mode)) return ADFS_NDA_DIRECTORY;
/* * Convert an ADFS time to Unix time. ADFS has a 40-bit centi-second time * referenced to 1 Jan 1900 (til 2248) so we need to discard 2208988800 seconds * of time to convert from RISC OS epoch to Unix epoch.
*/ staticvoid
adfs_adfs2unix_time(struct timespec64 *tv, struct inode *inode)
{ unsignedint high, low; /* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since * 01 Jan 1900 00:00:00 (RISC OS epoch)
*/
s64 nsec;
if (!adfs_inode_is_stamped(inode)) goto cur_time;
high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */
low = ADFS_I(inode)->execaddr; /* bottom 32 bits of timestamp */
/* convert 40-bit centi-seconds to 32-bit seconds * going via nanoseconds to retain precision
*/
nsec = (((s64) high << 32) | (s64) low) * 10000000; /* cs to ns */
/* Files dated pre 01 Jan 1970 00:00:00. */ if (nsec < nsec_unix_epoch_diff_risc_os_epoch) goto too_early;
/* convert from RISC OS to Unix epoch */
nsec -= nsec_unix_epoch_diff_risc_os_epoch;
/* Convert an Unix time to ADFS time for an entry that is already stamped. */ staticvoid adfs_unix2adfs_time(struct inode *inode, conststruct timespec64 *ts)
{
s64 cs, nsec = timespec64_to_ns(ts);
/* convert from Unix to RISC OS epoch */
nsec += nsec_unix_epoch_diff_risc_os_epoch;
/* convert from nanoseconds to centiseconds */
cs = div_s64(nsec, 10000000);
/* * Fill in the inode information from the object information. * * Note that this is an inode-less filesystem, so we can't use the inode * number to reference the metadata on the media. Instead, we use the * inode number to hold the object ID, which in turn will tell us where * the data is held. We also save the parent object ID, and with these * two, we can locate the metadata. * * This does mean that we rely on an objects parent remaining the same at * all times - we cannot cope with a cross-directory rename (yet).
*/ struct inode *
adfs_iget(struct super_block *sb, struct object_info *obj)
{ struct inode *inode; struct timespec64 ts;
/* * we need to save the parent directory ID so that * write_inode can update the directory information * for this file. This will need special handling * for cross-directory renames.
*/
ADFS_I(inode)->parent_id = obj->parent_id;
ADFS_I(inode)->indaddr = obj->indaddr;
ADFS_I(inode)->loadaddr = obj->loadaddr;
ADFS_I(inode)->execaddr = obj->execaddr;
ADFS_I(inode)->attr = obj->attr;
/* * Validate and convert a changed access mode/time to their ADFS equivalents. * adfs_write_inode will actually write the information back to the directory * later.
*/ int
adfs_notify_change(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr)
{ struct inode *inode = d_inode(dentry); struct super_block *sb = inode->i_sb; unsignedint ia_valid = attr->ia_valid; int error;
/* * we can't change the UID or GID of any file - * we have a global UID/GID in the superblock
*/ if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, ADFS_SB(sb)->s_uid)) ||
(ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, ADFS_SB(sb)->s_gid)))
error = -EPERM;
if (error) goto out;
/* XXX: this is missing some actual on-disk truncation.. */ if (ia_valid & ATTR_SIZE)
truncate_setsize(inode, attr->ia_size);
/* * FIXME: should we make these == to i_mtime since we don't * have the ability to represent them in our filesystem?
*/ if (ia_valid & ATTR_ATIME)
inode_set_atime_to_ts(inode, attr->ia_atime); if (ia_valid & ATTR_CTIME)
inode_set_ctime_to_ts(inode, attr->ia_ctime); if (ia_valid & ATTR_MODE) {
ADFS_I(inode)->attr = adfs_mode2atts(sb, inode, attr->ia_mode);
inode->i_mode = adfs_atts2mode(sb, inode);
}
/* * FIXME: should we be marking this inode dirty even if * we don't have any metadata to write back?
*/ if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
mark_inode_dirty(inode);
out: return error;
}
/* * write an existing inode back to the directory, and therefore the disk. * The adfs-specific inode data has already been updated by * adfs_notify_change()
*/ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{ struct super_block *sb = inode->i_sb; struct object_info obj;
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.