isofs: use libdriver
Change-Id: I5ced800eec92f651f31d9c77c3129fe837ca4614
This commit is contained in:
parent
3e08d38e8e
commit
e2dc2c8954
17 changed files with 316 additions and 1029 deletions
|
@ -1,11 +1,11 @@
|
|||
# Makefile for ISO9660 fs
|
||||
PROG= isofs
|
||||
SRCS= main.c table.c mount.c super.c inode.c \
|
||||
link.c utility.c misc.c path.c read.c susp.c susp_rock_ridge.c stadir.c
|
||||
link.c utility.c path.c read.c susp.c susp_rock_ridge.c stadir.c
|
||||
|
||||
DPADD+= ${LIBBDEV} ${LIBSYS}
|
||||
LDADD+= -lbdev -lsys -lc -lminixfs
|
||||
DPADD+= ${LIBFSDRIVER} ${LIBBDEV} ${LIBSYS} ${LIBMINIXFS}
|
||||
LDADD+= -lfsdriver -lbdev -lsys -lc -lminixfs
|
||||
|
||||
CPPFLAGS+= -DNR_BUFS=100 -Wall
|
||||
CPPFLAGS+= -DNR_BUFS=100
|
||||
|
||||
.include <minix.service.mk>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#define GETDENTS_BUFSIZ 1024
|
||||
|
||||
#define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 file systems */
|
||||
#define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 FS */
|
||||
|
||||
#define NR_INODE_RECORDS 64
|
||||
#define NR_DIR_EXTENT_RECORDS NR_INODE_RECORDS * 16
|
||||
|
@ -43,9 +43,6 @@
|
|||
#define ISO9660_MAX_FILE_ID_LEN 32
|
||||
#define ISO9660_RRIP_MAX_FILE_ID_LEN 256
|
||||
|
||||
#define END_OF_FILE (-104) /* eof detected */
|
||||
|
||||
/* Miscellaneous constants */
|
||||
#define SYS_UID ((uid_t) 0) /* uid_t for processes PM and INIT */
|
||||
#define SYS_GID ((gid_t) 0) /* gid_t for processes PM and INIT */
|
||||
|
||||
|
|
|
@ -4,32 +4,8 @@
|
|||
#define EXTERN
|
||||
#endif
|
||||
|
||||
#include <minix/optset.h>
|
||||
|
||||
/* The following variables are used for returning results to the caller. */
|
||||
|
||||
EXTERN int err_code; /* temporary storage for error number */
|
||||
EXTERN int rdwt_err; /* status of last disk i/o request */
|
||||
|
||||
EXTERN int(*fs_call_vec[]) (void);
|
||||
|
||||
EXTERN message fs_m_in; /* contains the input message of the request */
|
||||
EXTERN message fs_m_out; /* contains the output message of the request */
|
||||
EXTERN int FS_STATE;
|
||||
|
||||
EXTERN uid_t caller_uid;
|
||||
EXTERN gid_t caller_gid;
|
||||
|
||||
EXTERN int req_nr; /* request number to the server */
|
||||
|
||||
EXTERN short path_processed; /* number of characters processed */
|
||||
EXTERN char user_path[PATH_MAX+1]; /* pathname to be processed */
|
||||
EXTERN char *vfs_slink_storage;
|
||||
EXTERN int symloop;
|
||||
|
||||
EXTERN int unmountdone;
|
||||
|
||||
EXTERN dev_t fs_dev; /* the device that is handled by this FS proc */
|
||||
EXTERN char fs_dev_label[16]; /* Name of the device driver that is handled */
|
||||
|
||||
EXTERN struct opt opt; /* global mount options */
|
||||
|
||||
extern struct fsdriver isofs_table; /* function call table */
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
#include <minix/sysutil.h>
|
||||
#include <minix/bitmap.h>
|
||||
|
||||
#include <minix/fsdriver.h>
|
||||
#include <minix/libminixfs.h>
|
||||
#include <minix/bdev.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -32,8 +36,11 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/dirent.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define b_data(bp) ((char *) (bp->data))
|
||||
|
||||
#include "const.h"
|
||||
#include "proto.h"
|
||||
#include "super.h"
|
||||
#include "glo.h"
|
||||
|
|
|
@ -5,32 +5,25 @@
|
|||
*/
|
||||
|
||||
#include "inc.h"
|
||||
#include <minix/vfsif.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static struct inode inodes[NR_INODE_RECORDS];
|
||||
static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset);
|
||||
|
||||
int fs_putnode()
|
||||
int fs_putnode(ino_t ino_nr, unsigned int count)
|
||||
{
|
||||
/*
|
||||
* Find the inode specified by the request message and decrease its
|
||||
* counter.
|
||||
*/
|
||||
int count = fs_m_in.m_vfs_fs_putnode.count;
|
||||
struct inode *i_node = find_inode(fs_m_in.m_vfs_fs_putnode.inode);
|
||||
struct inode *i_node;
|
||||
|
||||
if (i_node == NULL) {
|
||||
printf("put_inode: trying to free unused inode\n");
|
||||
panic("fs_putnode failed");
|
||||
}
|
||||
if (count <= 0) {
|
||||
printf("put_inode: bad value for count: %d\n", count);
|
||||
panic("fs_putnode failed");
|
||||
if ((i_node = find_inode(ino_nr)) == NULL) {
|
||||
printf("ISOFS: trying to free unused inode\n");
|
||||
return EINVAL;
|
||||
}
|
||||
if (count > i_node->i_count) {
|
||||
printf("put_inode: count too high: %d > %d\n", count, i_node->i_count);
|
||||
panic("fs_putnode failed");
|
||||
printf("ISOFS: put_node count too high\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
i_node->i_count -= count - 1;
|
||||
|
@ -38,7 +31,7 @@ int fs_putnode()
|
|||
return OK;
|
||||
}
|
||||
|
||||
struct inode* alloc_inode()
|
||||
struct inode* alloc_inode(void)
|
||||
{
|
||||
/*
|
||||
* Return a free inode from the pool.
|
||||
|
@ -112,7 +105,8 @@ struct inode* get_inode(ino_t i)
|
|||
extent->location = i / v_pri.logical_block_size_l;
|
||||
extent->length = 1;
|
||||
|
||||
if (read_inode(i_node, extent, i % v_pri.logical_block_size_l, NULL) != OK) {
|
||||
if (read_inode(i_node, extent, i % v_pri.logical_block_size_l,
|
||||
NULL) != OK) {
|
||||
free_extent(extent);
|
||||
put_inode(i_node);
|
||||
return NULL;
|
||||
|
@ -127,16 +121,14 @@ void put_inode(struct inode *i_node)
|
|||
if (i_node == NULL)
|
||||
return;
|
||||
|
||||
if (i_node->i_count <= 0)
|
||||
panic("put_inode: i_count already below 1: %d", i_node->i_count);
|
||||
assert(i_node->i_count > 0);
|
||||
|
||||
i_node->i_count--;
|
||||
}
|
||||
|
||||
void dup_inode(struct inode *i_node)
|
||||
{
|
||||
if (i_node == NULL)
|
||||
panic("dup_inode: trying to duplicate NULL inode");
|
||||
assert(i_node != NULL);
|
||||
|
||||
i_node->i_count++;
|
||||
}
|
||||
|
@ -163,8 +155,9 @@ static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset)
|
|||
break;
|
||||
}
|
||||
|
||||
put_block(bp);
|
||||
bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
bp = read_extent_block(extent, *offset /
|
||||
v_pri.logical_block_size_l);
|
||||
}
|
||||
|
||||
return bp;
|
||||
|
@ -185,8 +178,9 @@ int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
|
|||
v_pri.logical_block_size_l);
|
||||
|
||||
/* Parse basic ISO 9660 specs. */
|
||||
if (check_dir_record(dir_rec, offset % v_pri.logical_block_size_l) != OK) {
|
||||
put_block(bp);
|
||||
if (check_dir_record(dir_rec,
|
||||
offset % v_pri.logical_block_size_l) != OK) {
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
|
@ -199,18 +193,20 @@ int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
|
|||
read_inode_iso9660(i_node, dir_rec);
|
||||
|
||||
/* Parse extensions. */
|
||||
read_inode_susp(i_node, dir_rec, bp, offset % v_pri.logical_block_size_l);
|
||||
read_inode_susp(i_node, dir_rec, bp,
|
||||
offset % v_pri.logical_block_size_l);
|
||||
|
||||
offset += dir_rec->length;
|
||||
read_inode_extents(i_node, dir_rec, extent, &offset);
|
||||
|
||||
put_block(bp);
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
if (new_offset != NULL)
|
||||
*new_offset = offset;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_rec)
|
||||
void read_inode_iso9660(struct inode *i,
|
||||
const struct iso9660_dir_record *dir_rec)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
|
@ -233,7 +229,8 @@ void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_re
|
|||
|
||||
if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) {
|
||||
i->i_stat.st_mode = S_IFDIR;
|
||||
i->i_stat.st_ino = i->extent->location * v_pri.logical_block_size_l;
|
||||
i->i_stat.st_ino =
|
||||
i->extent->location * v_pri.logical_block_size_l;
|
||||
}
|
||||
else
|
||||
i->i_stat.st_mode = S_IFREG;
|
||||
|
@ -259,11 +256,13 @@ void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_re
|
|||
/* Initialize stat. */
|
||||
i->i_stat.st_dev = fs_dev;
|
||||
i->i_stat.st_blksize = v_pri.logical_block_size_l;
|
||||
i->i_stat.st_blocks = dir_rec->data_length_l / v_pri.logical_block_size_l;
|
||||
i->i_stat.st_blocks =
|
||||
dir_rec->data_length_l / v_pri.logical_block_size_l;
|
||||
i->i_stat.st_nlink = 1;
|
||||
}
|
||||
|
||||
void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
||||
void read_inode_extents(struct inode *i,
|
||||
const struct iso9660_dir_record *dir_rec,
|
||||
struct dir_extent *extent, size_t *offset)
|
||||
{
|
||||
struct buf *bp;
|
||||
|
@ -275,7 +274,8 @@ void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_re
|
|||
* No need to search extents if file is empty or has final directory
|
||||
* record flag set.
|
||||
*/
|
||||
if (cur_extent == NULL || ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0))
|
||||
if (cur_extent == NULL ||
|
||||
((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0))
|
||||
return;
|
||||
|
||||
while (!done) {
|
||||
|
@ -283,18 +283,21 @@ void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_re
|
|||
if (bp == NULL)
|
||||
return;
|
||||
|
||||
bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
|
||||
extent_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
|
||||
v_pri.logical_block_size_l);
|
||||
bp = read_extent_block(extent,
|
||||
*offset / v_pri.logical_block_size_l);
|
||||
extent_rec = (struct iso9660_dir_record*)(b_data(bp) +
|
||||
*offset % v_pri.logical_block_size_l);
|
||||
|
||||
if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l) != OK) {
|
||||
put_block(bp);
|
||||
if (check_dir_record(dir_rec,
|
||||
*offset % v_pri.logical_block_size_l) != OK) {
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extent entries should share the same name. */
|
||||
if ((dir_rec->length_file_id == extent_rec->length_file_id) &&
|
||||
(memcmp(dir_rec->file_id, extent_rec->file_id, dir_rec->length_file_id) == 0)) {
|
||||
(memcmp(dir_rec->file_id, extent_rec->file_id,
|
||||
dir_rec->length_file_id) == 0)) {
|
||||
/* Add the extent at the end of the linked list. */
|
||||
cur_extent->next = alloc_extent();
|
||||
cur_extent->next->location = dir_rec->loc_extent_l +
|
||||
|
@ -317,7 +320,7 @@ void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_re
|
|||
if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)
|
||||
done = TRUE;
|
||||
|
||||
put_block(bp);
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,11 +339,12 @@ void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
|||
if(dir_rec->length - susp_offset >= 4) {
|
||||
susp_size = dir_rec->length - susp_offset;
|
||||
|
||||
/* Initialize rrii_dir_record structure with known, sane data. */
|
||||
/* Initialize record with known, sane data. */
|
||||
memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
|
||||
memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
|
||||
memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
|
||||
memcpy(rrii_data.birthtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
|
||||
memcpy(rrii_data.birthtime, dir_rec->rec_date,
|
||||
ISO9660_SIZE_DATE7);
|
||||
|
||||
rrii_data.d_mode = i->i_stat.st_mode;
|
||||
rrii_data.uid = 0;
|
||||
|
@ -349,7 +353,8 @@ void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
|||
rrii_data.file_id_rrip[0] = '\0';
|
||||
rrii_data.slink_rrip[0] = '\0';
|
||||
|
||||
parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size);
|
||||
parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset,
|
||||
susp_size);
|
||||
|
||||
/* Copy back data from rrii_dir_record structure. */
|
||||
i->i_stat.st_atime = date7_to_time_t(rrii_data.atime);
|
||||
|
@ -363,9 +368,11 @@ void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
|||
i->i_stat.st_rdev = rrii_data.rdev;
|
||||
|
||||
if (rrii_data.file_id_rrip[0] != '\0')
|
||||
strlcpy(i->i_name, rrii_data.file_id_rrip, ISO9660_RRIP_MAX_FILE_ID_LEN);
|
||||
strlcpy(i->i_name, rrii_data.file_id_rrip,
|
||||
sizeof(i->i_name));
|
||||
if (rrii_data.slink_rrip[0] != '\0')
|
||||
strlcpy(i->s_link, rrii_data.slink_rrip, ISO9660_RRIP_MAX_FILE_ID_LEN);
|
||||
strlcpy(i->s_link, rrii_data.slink_rrip,
|
||||
sizeof(i->s_link));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,4 +388,3 @@ int check_dir_record(const struct iso9660_dir_record *d, size_t offset)
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,36 +1,24 @@
|
|||
#include "inc.h"
|
||||
#include <minix/com.h>
|
||||
#include <minix/vfsif.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef __NBSD_LIBC
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#include "proto.h"
|
||||
|
||||
int fs_rdlink()
|
||||
ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes)
|
||||
{
|
||||
struct inode *i_node; /* target inode */
|
||||
int r; /* return value */
|
||||
size_t copylen;
|
||||
struct inode *i_node;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
/* Try to get inode according to its index */
|
||||
i_node = find_inode(fs_m_in.m_vfs_fs_rdlink.inode);
|
||||
if (i_node == NULL)
|
||||
if ((i_node = find_inode(ino_nr)) == NULL)
|
||||
return EINVAL; /* no inode found */
|
||||
|
||||
if (!S_ISLNK(i_node->i_stat.st_mode))
|
||||
r = EACCES;
|
||||
else {
|
||||
/* Passed all checks */
|
||||
copylen = MIN( (size_t) fs_m_in.m_vfs_fs_rdlink.mem_size, NAME_MAX);
|
||||
return EACCES;
|
||||
|
||||
r = sys_safecopyto(VFS_PROC_NR,
|
||||
(cp_grant_id_t) fs_m_in.m_vfs_fs_rdlink.grant,
|
||||
(vir_bytes) 0,
|
||||
(vir_bytes) i_node->s_link,
|
||||
copylen);
|
||||
}
|
||||
len = strlen(i_node->s_link);
|
||||
if (len > bytes)
|
||||
len = bytes;
|
||||
|
||||
if ((r = fsdriver_copyout(data, 0, i_node->s_link, len)) != OK)
|
||||
return r;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -4,88 +4,17 @@
|
|||
*/
|
||||
|
||||
#include "inc.h"
|
||||
#include <minix/vfsif.h>
|
||||
#include <assert.h>
|
||||
#include "const.h"
|
||||
#include "glo.h"
|
||||
|
||||
/* Declare some local functions. */
|
||||
static void get_work(message *m_in);
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||
static void sef_cb_signal_handler(int signo);
|
||||
#include <minix/optset.h>
|
||||
|
||||
static struct optset optset_table[] = {
|
||||
{ "norock", OPT_BOOL, &opt.norock, TRUE },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
endpoint_t who_e;
|
||||
int ind, error, transid;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
while (TRUE) {
|
||||
/* Wait for request message. */
|
||||
get_work(&fs_m_in);
|
||||
|
||||
transid = TRNS_GET_ID(fs_m_in.m_type);
|
||||
fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
|
||||
if (fs_m_in.m_type == 0) {
|
||||
assert(!IS_VFS_FS_TRANSID(transid));
|
||||
fs_m_in.m_type = transid; /* Backwards compat. */
|
||||
transid = 0;
|
||||
}
|
||||
else
|
||||
assert(IS_VFS_FS_TRANSID(transid));
|
||||
|
||||
error = OK;
|
||||
|
||||
caller_uid = -1; /* To trap errors */
|
||||
caller_gid = -1;
|
||||
|
||||
who_e = fs_m_in.m_source; /* source of the request */
|
||||
|
||||
if (who_e != VFS_PROC_NR) { /* If the message is not for us just
|
||||
* continue */
|
||||
continue;
|
||||
}
|
||||
|
||||
req_nr = fs_m_in.m_type;
|
||||
|
||||
if (req_nr < FS_BASE) {
|
||||
fs_m_in.m_type += FS_BASE;
|
||||
req_nr = fs_m_in.m_type;
|
||||
}
|
||||
|
||||
ind = req_nr - FS_BASE;
|
||||
|
||||
if (ind < 0 || ind >= NREQS)
|
||||
error = EINVAL;
|
||||
else
|
||||
error = (*fs_call_vec[ind])(); /* Process the request calling
|
||||
* the appropriate function. */
|
||||
|
||||
fs_m_out.m_type = error;
|
||||
if (IS_VFS_FS_TRANSID(transid)) {
|
||||
/* If a transaction ID was set, reset it */
|
||||
fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
|
||||
}
|
||||
reply(who_e, &fs_m_out); /* returns the response to VFS */
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
static void sef_local_startup()
|
||||
static int sef_cb_init_fresh(int __unused type,
|
||||
sef_init_info_t * __unused info)
|
||||
{
|
||||
/* Initialize the Minix file server. */
|
||||
/* Initialize the iso9660fs server. */
|
||||
int i;
|
||||
|
||||
/* Defaults */
|
||||
|
@ -96,6 +25,23 @@ static void sef_local_startup()
|
|||
if (!strcmp(env_argv[i], "-o"))
|
||||
optset_parse(optset_table, env_argv[++i]);
|
||||
|
||||
setenv("TZ","",1); /* Used to calculate the time */
|
||||
|
||||
lmfs_buf_pool(NR_BUFS);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void sef_cb_signal_handler(int signo)
|
||||
{
|
||||
/* Only check for termination signal, ignore anything else. */
|
||||
if (signo != SIGTERM) return;
|
||||
|
||||
fsdriver_terminate();
|
||||
}
|
||||
|
||||
static void sef_local_startup(void)
|
||||
{
|
||||
/* Register init callbacks. */
|
||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||
sef_setcb_init_restart(sef_cb_init_fail);
|
||||
|
@ -107,42 +53,15 @@ static void sef_local_startup()
|
|||
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
|
||||
lmfs_buf_pool(10);
|
||||
}
|
||||
|
||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Initialize the iso9660fs server. */
|
||||
setenv("TZ","",1); /* Used to calculate the time */
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
return OK;
|
||||
fsdriver_task(&isofs_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sef_cb_signal_handler(int signo)
|
||||
{
|
||||
/* Only check for termination signal, ignore anything else. */
|
||||
if (signo != SIGTERM) return;
|
||||
|
||||
/* No need to do a sync, as this is a read-only file system. */
|
||||
|
||||
/*
|
||||
* If the file system has already been unmounted, exit immediately.
|
||||
* We might not get another message.
|
||||
*/
|
||||
if (unmountdone) exit(0);
|
||||
}
|
||||
|
||||
static void get_work(message *m_in)
|
||||
{
|
||||
int s; /* receive status */
|
||||
if (OK != (s = sef_receive(ANY, m_in))) /* wait for message */
|
||||
panic("sef_receive failed: %d", s);
|
||||
}
|
||||
|
||||
void reply(int who, message *m_out)
|
||||
{
|
||||
if (OK != ipc_send(who, m_out)) /* send the message */
|
||||
printf("ISOFS(%d) was unable to send reply\n", sef_self());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
#include "inc.h"
|
||||
#include <fcntl.h>
|
||||
#include <minix/vfsif.h>
|
||||
#include <minix/bdev.h>
|
||||
|
||||
int fs_sync()
|
||||
{
|
||||
/* Always mounted read only, so nothing to sync */
|
||||
return OK; /* sync() can't fail */
|
||||
}
|
||||
|
||||
int fs_new_driver(void)
|
||||
{
|
||||
/* Set a new driver endpoint for this device. */
|
||||
dev_t dev;
|
||||
cp_grant_id_t label_gid;
|
||||
size_t label_len;
|
||||
char label[sizeof(fs_dev_label)];
|
||||
int r;
|
||||
|
||||
dev = fs_m_in.m_vfs_fs_new_driver.device;
|
||||
label_gid = fs_m_in.m_vfs_fs_new_driver.grant;
|
||||
label_len = fs_m_in.m_vfs_fs_new_driver.path_len;
|
||||
|
||||
if (label_len > sizeof(label))
|
||||
return EINVAL;
|
||||
|
||||
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
|
||||
(vir_bytes) label, label_len);
|
||||
|
||||
if (r != OK) {
|
||||
printf("ISOFS: fs_new_driver safecopyfrom failed (%d)\n", r);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
bdev_driver(dev, label);
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -1,35 +1,16 @@
|
|||
#include "inc.h"
|
||||
#include <minix/vfsif.h>
|
||||
#include <minix/bdev.h>
|
||||
#include "const.h"
|
||||
#include "glo.h"
|
||||
|
||||
int fs_readsuper() {
|
||||
cp_grant_id_t label_gid;
|
||||
size_t label_len;
|
||||
int r = OK;
|
||||
int fs_mount(dev_t dev, unsigned int __unused flags,
|
||||
struct fsdriver_node *root_node, unsigned int *res_flags)
|
||||
{
|
||||
int r;
|
||||
|
||||
fs_dev = fs_m_in.m_vfs_fs_readsuper.device;
|
||||
label_gid = fs_m_in.m_vfs_fs_readsuper.grant;
|
||||
label_len = fs_m_in.m_vfs_fs_readsuper.path_len;
|
||||
|
||||
if (label_len > sizeof(fs_dev_label))
|
||||
return EINVAL;
|
||||
|
||||
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
|
||||
label_len);
|
||||
if (r != OK) {
|
||||
printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Map the driver label for this major */
|
||||
bdev_driver(fs_dev, fs_dev_label);
|
||||
fs_dev = dev;
|
||||
|
||||
/* Open the device the file system lives on in read only mode */
|
||||
if (bdev_open(fs_dev, BDEV_R_BIT) != OK) {
|
||||
if (bdev_open(fs_dev, BDEV_R_BIT) != OK)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Read the superblock */
|
||||
r = read_vds(&v_pri, fs_dev);
|
||||
|
@ -39,51 +20,44 @@ int fs_readsuper() {
|
|||
}
|
||||
|
||||
/* Return some root inode properties */
|
||||
fs_m_out.m_fs_vfs_readsuper.inode = v_pri.inode_root->i_stat.st_ino;
|
||||
fs_m_out.m_fs_vfs_readsuper.mode = v_pri.inode_root->i_stat.st_mode;
|
||||
fs_m_out.m_fs_vfs_readsuper.file_size = v_pri.inode_root->i_stat.st_size;
|
||||
fs_m_out.m_fs_vfs_readsuper.uid = SYS_UID; /* Always root */
|
||||
fs_m_out.m_fs_vfs_readsuper.gid = SYS_GID; /* operator */
|
||||
fs_m_out.m_fs_vfs_readsuper.flags = RES_NOFLAGS;
|
||||
root_node->fn_ino_nr = v_pri.inode_root->i_stat.st_ino;
|
||||
root_node->fn_mode = v_pri.inode_root->i_stat.st_mode;
|
||||
root_node->fn_size = v_pri.inode_root->i_stat.st_size;
|
||||
root_node->fn_uid = SYS_UID; /* Always root */
|
||||
root_node->fn_gid = SYS_GID; /* operator */
|
||||
root_node->fn_dev = NO_DEV;
|
||||
|
||||
*res_flags = RES_NOFLAGS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fs_mountpoint()
|
||||
int fs_mountpt(ino_t ino_nr)
|
||||
{
|
||||
/*
|
||||
* This function looks up the mount point, it checks the condition
|
||||
* whether the partition can be mounted on the inode or not.
|
||||
*/
|
||||
|
||||
struct inode *rip;
|
||||
int r = OK;
|
||||
|
||||
/* Temporarily open the file. */
|
||||
if ((rip = find_inode(fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL)
|
||||
if ((rip = find_inode(ino_nr)) == NULL)
|
||||
return EINVAL;
|
||||
|
||||
if (rip->i_mountpoint)
|
||||
r = EBUSY;
|
||||
return EBUSY;
|
||||
|
||||
/* If the inode is not a dir returns error */
|
||||
/* The inode must be a directory. */
|
||||
if ((rip->i_stat.st_mode & I_TYPE) != I_DIRECTORY)
|
||||
r = ENOTDIR;
|
||||
return ENOTDIR;
|
||||
|
||||
put_inode(rip);
|
||||
|
||||
if (r == OK)
|
||||
rip->i_mountpoint = TRUE;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fs_unmount(void)
|
||||
{
|
||||
release_vol_pri_desc(&v_pri); /* Release the super block */
|
||||
bdev_close(fs_dev);
|
||||
unmountdone = TRUE;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void fs_unmount(void)
|
||||
{
|
||||
release_vol_pri_desc(&v_pri); /* Release the super block */
|
||||
|
||||
bdev_close(fs_dev);
|
||||
}
|
||||
|
|
|
@ -1,92 +1,14 @@
|
|||
#include "inc.h"
|
||||
#include <string.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/vfsif.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static char *get_name(char *name, char string[NAME_MAX+1]);
|
||||
static int ltraverse(struct inode *rip, char *suffix);
|
||||
static int parse_path(ino_t dir_ino, ino_t root_ino, int flags, struct
|
||||
inode **res_inop, size_t *offsetp, int *symlinkp);
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* fs_lookup *
|
||||
*===========================================================================*/
|
||||
int fs_lookup() {
|
||||
cp_grant_id_t grant;
|
||||
int r, len, flags, symlinks = 0;
|
||||
size_t offset = 0;
|
||||
ino_t dir_ino, root_ino;
|
||||
struct inode *dir = 0;
|
||||
|
||||
grant = fs_m_in.m_vfs_fs_lookup.grant_path;
|
||||
len = fs_m_in.m_vfs_fs_lookup.path_len; /* including terminating nul */
|
||||
dir_ino = fs_m_in.m_vfs_fs_lookup.dir_ino;
|
||||
root_ino = fs_m_in.m_vfs_fs_lookup.root_ino;
|
||||
flags = fs_m_in.m_vfs_fs_lookup.flags;
|
||||
caller_uid = fs_m_in.m_vfs_fs_lookup.uid;
|
||||
caller_gid = fs_m_in.m_vfs_fs_lookup.gid;
|
||||
|
||||
/* Check length. */
|
||||
if(len > sizeof(user_path))
|
||||
return E2BIG; /* too big for buffer */
|
||||
if(len < 1)
|
||||
return EINVAL; /* too small */
|
||||
|
||||
/* Copy the pathname and set up caller's user and group id */
|
||||
r = sys_safecopyfrom(VFS_PROC_NR, grant, 0, (vir_bytes) user_path,
|
||||
(phys_bytes) len);
|
||||
if (r != OK) {
|
||||
printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
|
||||
__FILE__, __LINE__, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Verify this is a null-terminated path. */
|
||||
if(user_path[len-1] != '\0')
|
||||
return EINVAL;
|
||||
|
||||
/* Lookup inode */
|
||||
r = parse_path(dir_ino, root_ino, flags, &dir, &offset, &symlinks);
|
||||
|
||||
if(r == ELEAVEMOUNT || r == ESYMLINK) {
|
||||
/* Report offset and the error */
|
||||
fs_m_out.m_fs_vfs_lookup.offset = offset;
|
||||
fs_m_out.m_fs_vfs_lookup.symloop = symlinks;
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r != OK && r != EENTERMOUNT)
|
||||
return r;
|
||||
|
||||
fs_m_out.m_fs_vfs_lookup.inode = dir->i_stat.st_ino;
|
||||
fs_m_out.m_fs_vfs_lookup.mode = dir->i_stat.st_mode;
|
||||
fs_m_out.m_fs_vfs_lookup.file_size = dir->i_stat.st_size;
|
||||
fs_m_out.m_fs_vfs_lookup.device = dir->i_stat.st_rdev;
|
||||
fs_m_out.m_fs_vfs_lookup.symloop = 0;
|
||||
fs_m_out.m_fs_vfs_lookup.uid = dir->i_stat.st_uid;
|
||||
fs_m_out.m_fs_vfs_lookup.gid = dir->i_stat.st_gid;
|
||||
|
||||
if (r == EENTERMOUNT) {
|
||||
fs_m_out.m_fs_vfs_lookup.offset = offset;
|
||||
put_inode(dir);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* The search dir actually performs the operation of searching for the
|
||||
* compoent ``string" in ldir_ptr. It returns the response and the number of
|
||||
* the inode in numb. */
|
||||
/*===========================================================================*
|
||||
* search_dir *
|
||||
*===========================================================================*/
|
||||
int search_dir(
|
||||
static int search_dir(
|
||||
struct inode *ldir_ptr, /* dir record parent */
|
||||
char string[NAME_MAX], /* component to search for */
|
||||
ino_t *numb /* pointer to new dir record */
|
||||
) {
|
||||
/* The search_dir function performs the operation of searching for the
|
||||
* component ``string" in ldir_ptr. It returns the response and the
|
||||
* number of the inode in numb.
|
||||
*/
|
||||
struct inode *dir_tmp;
|
||||
size_t pos = 0;
|
||||
int r;
|
||||
|
@ -109,7 +31,8 @@ int search_dir(
|
|||
* inodes stay consistent.
|
||||
*/
|
||||
if (strcmp(string, "..") == 0) {
|
||||
if (ldir_ptr->i_stat.st_ino == v_pri.inode_root->i_stat.st_ino) {
|
||||
if (ldir_ptr->i_stat.st_ino ==
|
||||
v_pri.inode_root->i_stat.st_ino) {
|
||||
*numb = v_pri.inode_root->i_stat.st_ino;
|
||||
return OK;
|
||||
}
|
||||
|
@ -141,8 +64,10 @@ int search_dir(
|
|||
}
|
||||
|
||||
if ((strcmp(dir_tmp->i_name, string) == 0) ||
|
||||
(strcmp(dir_tmp->i_name, "..") && strcmp(string, "..") == 0)) {
|
||||
if (dir_tmp->i_stat.st_ino == v_pri.inode_root->i_stat.st_ino) {
|
||||
(strcmp(dir_tmp->i_name, "..") &&
|
||||
strcmp(string, "..") == 0)) {
|
||||
if (dir_tmp->i_stat.st_ino ==
|
||||
v_pri.inode_root->i_stat.st_ino) {
|
||||
*numb = v_pri.inode_root->i_stat.st_ino;
|
||||
put_inode(dir_tmp);
|
||||
return OK;
|
||||
|
@ -157,295 +82,37 @@ int search_dir(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* parse_path *
|
||||
*===========================================================================*/
|
||||
static int parse_path(
|
||||
ino_t dir_ino,
|
||||
ino_t root_ino,
|
||||
int flags,
|
||||
struct inode **res_inop,
|
||||
size_t *offsetp,
|
||||
int *symlinkp
|
||||
) {
|
||||
int r;
|
||||
char string[NAME_MAX+1];
|
||||
char *cp, *ncp;
|
||||
struct inode *start_dir = 0, *old_dir = 0;
|
||||
|
||||
/* Find starting inode inode according to the request message */
|
||||
if ((start_dir = find_inode(dir_ino)) == NULL) {
|
||||
printf("ISOFS: couldn't find starting inode %llu\n", dir_ino);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
cp = user_path;
|
||||
dup_inode(start_dir);
|
||||
|
||||
/* Scan the path component by component. */
|
||||
while (TRUE) {
|
||||
if (cp[0] == '\0') {
|
||||
/* Empty path */
|
||||
*res_inop = start_dir;
|
||||
*offsetp += cp-user_path;
|
||||
|
||||
/* Return EENTERMOUNT if we are at a mount point */
|
||||
if (start_dir->i_mountpoint)
|
||||
return EENTERMOUNT;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (cp[0] == '/') {
|
||||
/*
|
||||
* Special case code. If the remaining path consists of
|
||||
* just slashes, we need to look up '.'
|
||||
*/
|
||||
while(cp[0] == '/')
|
||||
cp++;
|
||||
if (cp[0] == '\0') {
|
||||
strlcpy(string, ".", NAME_MAX + 1);
|
||||
ncp = cp;
|
||||
}
|
||||
else
|
||||
ncp = get_name(cp, string);
|
||||
}
|
||||
else
|
||||
/* Just get the first component */
|
||||
ncp = get_name(cp, string);
|
||||
|
||||
/* Special code for '..'. A process is not allowed to leave a chrooted
|
||||
* environment. A lookup of '..' at the root of a mounted filesystem
|
||||
* has to return ELEAVEMOUNT.
|
||||
*/
|
||||
if (strcmp(string, "..") == 0) {
|
||||
|
||||
/* This condition is not necessary since it will never be the root filesystem */
|
||||
/* if (start_dir == v_pri.inode_root) { */
|
||||
/* cp = ncp; */
|
||||
/* continue; /\* Just ignore the '..' at a process' */
|
||||
/* * root. */
|
||||
/* *\/ */
|
||||
/* } */
|
||||
|
||||
if (start_dir == v_pri.inode_root) {
|
||||
/* Climbing up mountpoint. */
|
||||
put_inode(start_dir);
|
||||
*res_inop = NULL;
|
||||
*offsetp += cp-user_path;
|
||||
return ELEAVEMOUNT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Only check for a mount point if we are not looking for '..'. */
|
||||
if (start_dir->i_mountpoint) {
|
||||
*res_inop = start_dir;
|
||||
*offsetp += cp-user_path;
|
||||
return EENTERMOUNT;
|
||||
}
|
||||
}
|
||||
|
||||
/* There is more path. Keep parsing. */
|
||||
old_dir = start_dir;
|
||||
|
||||
r = advance(old_dir, string, &start_dir);
|
||||
|
||||
if (r != OK) {
|
||||
put_inode(old_dir);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* The call to advance() succeeded. Fetch next component. */
|
||||
if (S_ISLNK(start_dir->i_stat.st_mode)) {
|
||||
|
||||
if (ncp[0] == '\0' && (flags & PATH_RET_SYMLINK)) {
|
||||
put_inode(old_dir);
|
||||
*res_inop = start_dir;
|
||||
*offsetp += ncp - user_path;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Extract path name from the symlink file */
|
||||
r = ltraverse(start_dir, ncp);
|
||||
ncp = user_path;
|
||||
*offsetp = 0;
|
||||
|
||||
/* Symloop limit reached? */
|
||||
if (++(*symlinkp) > _POSIX_SYMLOOP_MAX)
|
||||
r = ELOOP;
|
||||
|
||||
if (r != OK) {
|
||||
put_inode(old_dir);
|
||||
put_inode(start_dir);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ncp[0] == '/') {
|
||||
put_inode(old_dir);
|
||||
put_inode(start_dir);
|
||||
return ESYMLINK;
|
||||
}
|
||||
|
||||
put_inode(start_dir);
|
||||
dup_inode(old_dir);
|
||||
start_dir = old_dir;
|
||||
}
|
||||
|
||||
put_inode(old_dir);
|
||||
cp = ncp;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* ltraverse *
|
||||
*===========================================================================*/
|
||||
static int ltraverse(
|
||||
struct inode *rip, /* symbolic link */
|
||||
char *suffix) /* current remaining path. Has to point in the
|
||||
* user_path buffer
|
||||
*/
|
||||
int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
|
||||
int *is_mountpt)
|
||||
{
|
||||
/* Traverse a symbolic link. Copy the link text from the inode and insert
|
||||
* the text into the path. Return error code or report success. Base
|
||||
* directory has to be determined according to the first character of the
|
||||
* new pathname.
|
||||
/* Given a directory and a component of a path, look up the component
|
||||
* in the directory, find the inode, open it, and return its details.
|
||||
*/
|
||||
|
||||
size_t llen; /* length of link */
|
||||
size_t slen; /* length of suffix */
|
||||
char *sp; /* start of link text */
|
||||
|
||||
llen = strlen(rip->s_link);
|
||||
sp = rip->s_link;
|
||||
slen = strlen(suffix);
|
||||
|
||||
/* The path we're parsing looks like this:
|
||||
* /already/processed/path/<link> or
|
||||
* /already/processed/path/<link>/not/yet/processed/path
|
||||
* After expanding the <link>, the path will look like
|
||||
* <expandedlink> or
|
||||
* <expandedlink>/not/yet/processed
|
||||
* In both cases user_path must have enough room to hold <expandedlink>.
|
||||
* However, in the latter case we have to move /not/yet/processed to the
|
||||
* right place first, before we expand <link>. When strlen(<expandedlink>) is
|
||||
* smaller than strlen(/already/processes/path), we move the suffix to the
|
||||
* left. Is strlen(<expandedlink>) greater then we move it to the right. Else
|
||||
* we do nothing.
|
||||
*/
|
||||
|
||||
if (slen > 0) { /* Do we have path after the link? */
|
||||
/* For simplicity we require that suffix starts with a slash */
|
||||
if (suffix[0] != '/') {
|
||||
panic("ltraverse: suffix does not start with a slash");
|
||||
}
|
||||
|
||||
/* To be able to expand the <link>, we have to move the 'suffix'
|
||||
* to the right place.
|
||||
*/
|
||||
if (slen + llen + 1 > sizeof(user_path))
|
||||
return ENAMETOOLONG;/* <expandedlink>+suffix+\0 does not fit*/
|
||||
if ((unsigned) (suffix - user_path) != llen) {
|
||||
/* Move suffix left or right */
|
||||
memmove(&user_path[llen], suffix, slen+1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (llen + 1 > sizeof(user_path))
|
||||
return ENAMETOOLONG; /* <expandedlink> + \0 does not fix */
|
||||
|
||||
/* Set terminating nul */
|
||||
user_path[llen]= '\0';
|
||||
}
|
||||
|
||||
/* Everything is set, now copy the expanded link to user_path */
|
||||
memmove(user_path, sp, llen);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* advance *
|
||||
*===========================================================================*/
|
||||
int advance(
|
||||
struct inode *dirp, /* inode for directory to be searched */
|
||||
char string[NAME_MAX], /* component name to look for */
|
||||
struct inode **resp) /* resulting inode */
|
||||
{
|
||||
/* Given a directory and a component of a path, look up the component in
|
||||
* the directory, find the inode, open it, and return a pointer to its inode
|
||||
* slot.
|
||||
*/
|
||||
|
||||
struct inode *rip = NULL;
|
||||
struct inode *dirp, *rip;
|
||||
ino_t ino_nr;
|
||||
int r;
|
||||
ino_t numb;
|
||||
|
||||
/* If 'string' is empty, yield same inode straight away. */
|
||||
if (string[0] == '\0')
|
||||
return ENOENT;
|
||||
|
||||
/* Check for NULL. */
|
||||
if (dirp == NULL)
|
||||
/* Find the starting inode. */
|
||||
if ((dirp = find_inode(dir_nr)) == NULL)
|
||||
return EINVAL;
|
||||
|
||||
/* If 'string' is not present in the directory, signal error. */
|
||||
if ( (r = search_dir(dirp, string, &numb)) != OK)
|
||||
/* Look up the directory entry. */
|
||||
if ((r = search_dir(dirp, name, &ino_nr)) != OK)
|
||||
return r;
|
||||
|
||||
/* The component has been found in the directory. Get inode. */
|
||||
if ( (rip = get_inode((int) numb)) == NULL)
|
||||
return err_code;
|
||||
/* The component has been found in the directory. Get the inode. */
|
||||
if ((rip = get_inode(ino_nr)) == NULL)
|
||||
return EIO; /* FIXME: this could have multiple causes */
|
||||
|
||||
/* Return its details to the caller. */
|
||||
node->fn_ino_nr = rip->i_stat.st_ino;
|
||||
node->fn_mode = rip->i_stat.st_mode;
|
||||
node->fn_size = rip->i_stat.st_size;
|
||||
node->fn_uid = rip->i_stat.st_uid;
|
||||
node->fn_gid = rip->i_stat.st_gid;
|
||||
node->fn_dev = rip->i_stat.st_rdev;
|
||||
|
||||
*is_mountpt = rip->i_mountpoint;
|
||||
|
||||
*resp= rip;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_name *
|
||||
*===========================================================================*/
|
||||
static char *get_name(
|
||||
char *path_name, /* path name to parse */
|
||||
char string[NAME_MAX+1]) /* component extracted from 'old_name' */
|
||||
{
|
||||
/* Given a pointer to a path name in fs space, 'path_name', copy the first
|
||||
* component to 'string' (truncated if necessary, always nul terminated).
|
||||
* A pointer to the string after the first component of the name as yet
|
||||
* unparsed is returned. Roughly speaking,
|
||||
* 'get_name' = 'path_name' - 'string'.
|
||||
*
|
||||
* This routine follows the standard convention that /usr/ast, /usr//ast,
|
||||
* //usr///ast and /usr/ast/ are all equivalent.
|
||||
*/
|
||||
size_t len;
|
||||
char *cp, *ep;
|
||||
|
||||
cp = path_name;
|
||||
|
||||
/* Skip leading slashes */
|
||||
while (cp[0] == '/')
|
||||
cp++;
|
||||
|
||||
/* Find the end of the first component */
|
||||
ep = cp;
|
||||
while(ep[0] != '\0' && ep[0] != '/')
|
||||
ep++;
|
||||
|
||||
len = ep-cp;
|
||||
|
||||
/* Truncate the amount to be copied if it exceeds NAME_MAX */
|
||||
if (len > NAME_MAX)
|
||||
len = NAME_MAX;
|
||||
|
||||
/* Special case of the string at cp is empty */
|
||||
if (len == 0)
|
||||
/* Return "." */
|
||||
strlcpy(string, ".", NAME_MAX + 1);
|
||||
else {
|
||||
memcpy(string, cp, len);
|
||||
string[len]= '\0';
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,19 +7,10 @@ struct iso9660_dir_record;
|
|||
struct iso9660_vol_pri_desc;
|
||||
struct inode;
|
||||
|
||||
#include <minix/libminixfs.h>
|
||||
|
||||
#define get_block(n) lmfs_get_block(fs_dev, n, NORMAL)
|
||||
#define put_block(n) lmfs_put_block(n, FULL_DATA_BLOCK)
|
||||
|
||||
/* main.c */
|
||||
int main(int argc, char *argv[]);
|
||||
void reply(int who, message *m_out);
|
||||
|
||||
/* inode.c */
|
||||
int fs_putnode(void);
|
||||
int fs_putnode(ino_t ino_nr, unsigned int count);
|
||||
|
||||
struct inode* alloc_inode();
|
||||
struct inode* alloc_inode(void);
|
||||
struct inode* find_inode(ino_t i);
|
||||
void put_inode(struct inode *i);
|
||||
void dup_inode(struct inode *i_node);
|
||||
|
@ -27,49 +18,41 @@ struct inode* get_inode(ino_t i);
|
|||
|
||||
int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
|
||||
size_t *new_offset);
|
||||
void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_rec);
|
||||
void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
||||
struct dir_extent *extent, size_t *offset);
|
||||
void read_inode_iso9660(struct inode *i,
|
||||
const struct iso9660_dir_record *dir_rec);
|
||||
void read_inode_extents(struct inode *i,
|
||||
const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
|
||||
size_t *offset);
|
||||
void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
|
||||
struct buf *bp, size_t offset);
|
||||
|
||||
int check_dir_record(const struct iso9660_dir_record *d, size_t offset);
|
||||
|
||||
/* link.c */
|
||||
int fs_rdlink(void);
|
||||
|
||||
/* misc.c */
|
||||
int fs_sync(void);
|
||||
int fs_new_driver(void);
|
||||
ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes);
|
||||
|
||||
/* mount.c */
|
||||
int fs_readsuper(void);
|
||||
int fs_mountpoint(void);
|
||||
int fs_unmount(void);
|
||||
int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
|
||||
unsigned int *res_flags);
|
||||
int fs_mountpt(ino_t ino_nr);
|
||||
void fs_unmount(void);
|
||||
|
||||
/* path.c */
|
||||
int fs_lookup(void);
|
||||
int advance(struct inode *dirp, char string[NAME_MAX], struct
|
||||
inode **resp);
|
||||
int search_dir(struct inode *ldir_ptr, char string [NAME_MAX], ino_t *numb);
|
||||
int fs_lookup(ino_t ino_nr, char *name, struct fsdriver_node *node,
|
||||
int *is_mountpt);
|
||||
|
||||
/* read.c */
|
||||
int fs_read(void);
|
||||
int fs_bread(void);
|
||||
int fs_getdents(void);
|
||||
int read_chunk(struct inode *rip, u64_t position, unsigned off, int
|
||||
chunk, unsigned left, cp_grant_id_t gid, unsigned buf_off, int
|
||||
block_size, int *completed, int rw);
|
||||
|
||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t pos, int call);
|
||||
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t *pos);
|
||||
|
||||
/* stadir.c */
|
||||
int fs_stat(void);
|
||||
int fs_statvfs(void);
|
||||
int fs_stat(ino_t ino_nr, struct stat *statbuf);
|
||||
int fs_statvfs(struct statvfs *st);
|
||||
|
||||
/* super.c */
|
||||
int release_vol_pri_desc(struct iso9660_vol_pri_desc *v_pri);
|
||||
int create_vol_pri_desc(struct iso9660_vol_pri_desc *v_pri, char *buf,
|
||||
size_t address);
|
||||
int read_vds(struct iso9660_vol_pri_desc *v_pri, dev_t dev);
|
||||
|
||||
/* susp.c */
|
||||
|
@ -77,16 +60,14 @@ int parse_susp(struct rrii_dir_record *dir, char *buffer);
|
|||
void parse_susp_buffer(struct rrii_dir_record *dir, char *buffer, u32_t size);
|
||||
|
||||
/* susp_rock_ridge.c */
|
||||
void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length);
|
||||
void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer,
|
||||
int length);
|
||||
int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer);
|
||||
|
||||
/* utility.c */
|
||||
struct dir_extent* alloc_extent();
|
||||
struct dir_extent* alloc_extent(void);
|
||||
void free_extent(struct dir_extent *extent);
|
||||
struct buf* read_extent_block(struct dir_extent *e, size_t block);
|
||||
size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block);
|
||||
|
||||
time_t date7_to_time_t(const u8_t *date);
|
||||
int do_noop(void);
|
||||
int no_sys(void);
|
||||
|
||||
|
|
|
@ -1,168 +1,97 @@
|
|||
#include "inc.h"
|
||||
#include <minix/com.h>
|
||||
#include <minix/vfsif.h>
|
||||
#include <minix/minlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static char getdents_buf[GETDENTS_BUFSIZ];
|
||||
|
||||
int fs_read(void)
|
||||
ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t pos, int __unused call)
|
||||
{
|
||||
int r = OK, chunk, block_size, completed, rw;
|
||||
size_t nrbytes, off, cum_io;
|
||||
cp_grant_id_t gid;
|
||||
off_t position, f_size, bytes_left;
|
||||
size_t off, chunk, block_size, cum_io;
|
||||
off_t f_size;
|
||||
struct inode *i_node;
|
||||
|
||||
switch(fs_m_in.m_type) {
|
||||
case REQ_READ: rw = READING; break;
|
||||
case REQ_PEEK: rw = PEEKING; break;
|
||||
default: panic("odd m_type");
|
||||
}
|
||||
struct buf *bp;
|
||||
int r;
|
||||
|
||||
/* Try to get inode according to its index. */
|
||||
i_node = find_inode(fs_m_in.m_vfs_fs_readwrite.inode);
|
||||
if (i_node == NULL)
|
||||
if ((i_node = find_inode(ino_nr)) == NULL)
|
||||
return EINVAL; /* No inode found. */
|
||||
|
||||
position = fs_m_in.m_vfs_fs_readwrite.seek_pos;
|
||||
nrbytes = fs_m_in.m_vfs_fs_readwrite.nbytes; /* Number of bytes to read. */
|
||||
block_size = v_pri.logical_block_size_l;
|
||||
gid = fs_m_in.m_vfs_fs_readwrite.grant;
|
||||
f_size = i_node->i_stat.st_size;
|
||||
rdwt_err = OK; /* Set to EIO if disk error occurs. */
|
||||
if (pos >= f_size)
|
||||
return 0; /* EOF */
|
||||
|
||||
/* Limit the request to the remainder of the file size. */
|
||||
if ((off_t)bytes > f_size - pos)
|
||||
bytes = (size_t)(f_size - pos);
|
||||
|
||||
block_size = v_pri.logical_block_size_l;
|
||||
cum_io = 0;
|
||||
|
||||
lmfs_reset_rdwt_err();
|
||||
r = OK;
|
||||
|
||||
/* Split the transfer into chunks that don't span two blocks. */
|
||||
while (nrbytes != 0) {
|
||||
off = position % block_size;
|
||||
while (bytes > 0) {
|
||||
off = pos % block_size;
|
||||
|
||||
chunk = MIN(nrbytes, block_size - off);
|
||||
if (chunk < 0)
|
||||
chunk = block_size - off;
|
||||
if (chunk > bytes)
|
||||
chunk = bytes;
|
||||
|
||||
bytes_left = f_size - position;
|
||||
if (position >= f_size)
|
||||
break; /* We are beyond EOF. */
|
||||
if (chunk > bytes_left)
|
||||
chunk = (int32_t) bytes_left;
|
||||
/* Read 'chunk' bytes. */
|
||||
bp = read_extent_block(i_node->extent, pos / block_size);
|
||||
if (bp == NULL)
|
||||
panic("bp not valid in rw_chunk; this can't happen");
|
||||
|
||||
/* Read or write 'chunk' bytes. */
|
||||
r = read_chunk(i_node, position, off, chunk,
|
||||
(uint32_t) nrbytes, gid, cum_io, block_size,
|
||||
&completed, rw);
|
||||
r = fsdriver_copyout(data, cum_io, b_data(bp)+off, chunk);
|
||||
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
|
||||
if (r != OK)
|
||||
break; /* EOF reached. */
|
||||
if (rdwt_err < 0)
|
||||
if (lmfs_rdwt_err() < 0)
|
||||
break;
|
||||
|
||||
/* Update counters and pointers. */
|
||||
nrbytes -= chunk; /* Bytes yet to be read. */
|
||||
bytes -= chunk; /* Bytes yet to be read. */
|
||||
cum_io += chunk; /* Bytes read so far. */
|
||||
position += chunk; /* Position within the file. */
|
||||
pos += chunk; /* Position within the file. */
|
||||
}
|
||||
|
||||
fs_m_out.m_fs_vfs_readwrite.seek_pos = position;
|
||||
|
||||
if (rdwt_err != OK)
|
||||
r = rdwt_err; /* Check for disk error. */
|
||||
if (rdwt_err == END_OF_FILE)
|
||||
if (lmfs_rdwt_err() != OK)
|
||||
r = lmfs_rdwt_err(); /* Check for disk error. */
|
||||
if (lmfs_rdwt_err() == END_OF_FILE)
|
||||
r = OK;
|
||||
|
||||
fs_m_out.m_fs_vfs_readwrite.nbytes = cum_io;
|
||||
return r;
|
||||
return (r == OK) ? cum_io : r;
|
||||
}
|
||||
|
||||
int fs_bread(void)
|
||||
{
|
||||
int r = OK, rw_flag, chunk, block_size, completed;
|
||||
size_t nrbytes, off, cum_io;
|
||||
cp_grant_id_t gid;
|
||||
off_t position;
|
||||
struct inode *i_node;
|
||||
|
||||
r = OK;
|
||||
|
||||
rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
|
||||
gid = fs_m_in.m_vfs_fs_breadwrite.grant;
|
||||
position = fs_m_in.m_vfs_fs_breadwrite.seek_pos;
|
||||
nrbytes = fs_m_in.m_vfs_fs_breadwrite.nbytes;
|
||||
block_size = v_pri.logical_block_size_l;
|
||||
i_node = v_pri.inode_root;
|
||||
|
||||
if(rw_flag == WRITING)
|
||||
return EIO; /* Not supported */
|
||||
|
||||
rdwt_err = OK; /* set to EIO if disk error occurs */
|
||||
|
||||
cum_io = 0;
|
||||
/* Split the transfer into chunks that don't span two blocks. */
|
||||
while (nrbytes != 0) {
|
||||
off = (unsigned int)(position % block_size); /* offset in blk*/
|
||||
|
||||
chunk = MIN(nrbytes, block_size - off);
|
||||
if (chunk < 0)
|
||||
chunk = block_size - off;
|
||||
|
||||
/* Read 'chunk' bytes. */
|
||||
r = read_chunk(i_node, position, off, chunk, (unsigned) nrbytes,
|
||||
gid, cum_io, block_size, &completed, READING);
|
||||
|
||||
if (r != OK)
|
||||
break; /* EOF reached */
|
||||
if (rdwt_err < 0)
|
||||
break;
|
||||
|
||||
/* Update counters and pointers. */
|
||||
nrbytes -= chunk; /* bytes yet to be read */
|
||||
cum_io += chunk; /* bytes read so far */
|
||||
position += chunk; /* position within the file */
|
||||
}
|
||||
|
||||
fs_m_out.m_fs_vfs_breadwrite.seek_pos = position;
|
||||
|
||||
if (rdwt_err != OK)
|
||||
r = rdwt_err; /* check for disk error */
|
||||
if (rdwt_err == END_OF_FILE)
|
||||
r = OK;
|
||||
|
||||
fs_m_out.m_fs_vfs_breadwrite.nbytes = cum_io;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fs_getdents(void)
|
||||
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
|
||||
off_t *pos)
|
||||
{
|
||||
struct fsdriver_dentry fsdentry;
|
||||
struct inode *i_node, *i_node_tmp;
|
||||
ino_t ino;
|
||||
cp_grant_id_t gid;
|
||||
size_t old_pos = 0, cur_pos, new_pos, tmpbuf_off = 0, userbuf_off = 0, grant_size;
|
||||
struct dirent *dirp;
|
||||
int r, len, reclen;
|
||||
size_t cur_pos, new_pos;
|
||||
int r, len;
|
||||
char *cp;
|
||||
|
||||
/* Get input parameters */
|
||||
ino = fs_m_in.m_vfs_fs_getdents.inode;
|
||||
gid = fs_m_in.m_vfs_fs_getdents.grant;
|
||||
cur_pos = fs_m_in.m_vfs_fs_getdents.seek_pos;
|
||||
grant_size = fs_m_in.m_vfs_fs_getdents.mem_size;
|
||||
|
||||
//memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
|
||||
|
||||
if ((i_node = get_inode(ino)) == NULL)
|
||||
if ((i_node = find_inode(ino_nr)) == NULL)
|
||||
return EINVAL;
|
||||
|
||||
while (TRUE) {
|
||||
if (*pos < 0 || *pos > SSIZE_MAX)
|
||||
return EINVAL;
|
||||
|
||||
fsdriver_dentry_init(&fsdentry, data, bytes, getdents_buf,
|
||||
sizeof(getdents_buf));
|
||||
|
||||
r = OK;
|
||||
|
||||
for (cur_pos = (size_t)*pos; ; cur_pos = new_pos) {
|
||||
i_node_tmp = alloc_inode();
|
||||
r = read_inode(i_node_tmp, i_node->extent, cur_pos, &new_pos);
|
||||
if ((r != OK) || (new_pos >= i_node->i_stat.st_size)) {
|
||||
put_inode(i_node);
|
||||
put_inode(i_node_tmp);
|
||||
break;
|
||||
}
|
||||
cur_pos = new_pos;
|
||||
|
||||
/* Compute the length of the name */
|
||||
cp = memchr(i_node_tmp->i_name, '\0', NAME_MAX);
|
||||
|
@ -171,91 +100,18 @@ int fs_getdents(void)
|
|||
else
|
||||
len = cp - i_node_tmp->i_name;
|
||||
|
||||
/* Compute record length; also does alignment. */
|
||||
reclen = _DIRENT_RECLEN(dirp, len);
|
||||
r = fsdriver_dentry_add(&fsdentry, i_node_tmp->i_stat.st_ino,
|
||||
i_node_tmp->i_name, len,
|
||||
IFTODT(i_node_tmp->i_stat.st_mode));
|
||||
|
||||
/* If the new record does not fit, then copy the buffer
|
||||
* and start from the beginning. */
|
||||
if (tmpbuf_off + reclen > GETDENTS_BUFSIZ ||
|
||||
userbuf_off + tmpbuf_off + reclen > grant_size) {
|
||||
r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
|
||||
(vir_bytes)getdents_buf, tmpbuf_off);
|
||||
|
||||
if (r != OK)
|
||||
panic("fs_getdents: sys_safecopyto failed: %d", r);
|
||||
|
||||
/* Check if the user grant buffer is filled. */
|
||||
if (userbuf_off + tmpbuf_off + reclen > grant_size) {
|
||||
fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off + tmpbuf_off;
|
||||
fs_m_out.m_fs_vfs_getdents.seek_pos = old_pos;
|
||||
return OK;
|
||||
}
|
||||
|
||||
userbuf_off += tmpbuf_off;
|
||||
tmpbuf_off = 0;
|
||||
}
|
||||
|
||||
/* The standard data structure is created using the
|
||||
* data in the buffer. */
|
||||
dirp = (struct dirent *) &getdents_buf[tmpbuf_off];
|
||||
dirp->d_fileno = i_node_tmp->i_stat.st_ino;
|
||||
dirp->d_reclen = reclen;
|
||||
dirp->d_type = fs_mode_to_type(i_node_tmp->i_stat.st_mode);
|
||||
dirp->d_namlen = len;
|
||||
|
||||
memcpy(dirp->d_name, i_node_tmp->i_name, len);
|
||||
dirp->d_name[len]= '\0';
|
||||
|
||||
tmpbuf_off += reclen;
|
||||
put_inode(i_node_tmp);
|
||||
|
||||
old_pos = cur_pos;
|
||||
if (r <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmpbuf_off != 0) {
|
||||
r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
|
||||
(vir_bytes) getdents_buf, tmpbuf_off);
|
||||
if (r >= 0 && (r = fsdriver_dentry_finish(&fsdentry)) >= 0)
|
||||
*pos = cur_pos;
|
||||
|
||||
if (r != OK)
|
||||
panic("fs_getdents: sys_safecopyto failed: %d", r);
|
||||
|
||||
userbuf_off += tmpbuf_off;
|
||||
}
|
||||
|
||||
fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off;
|
||||
fs_m_out.m_fs_vfs_getdents.seek_pos = cur_pos;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int read_chunk(
|
||||
struct inode *i_node, /* pointer to inode for file to be rd/wr */
|
||||
u64_t position, /* position within file to read or write */
|
||||
unsigned off, /* off within the current block */
|
||||
int chunk, /* number of bytes to read or write */
|
||||
unsigned left, /* max number of bytes wanted after position */
|
||||
cp_grant_id_t gid, /* grant */
|
||||
unsigned buf_off, /* offset in grant */
|
||||
int block_size, /* block size of FS operating on */
|
||||
int *completed, /* number of bytes copied */
|
||||
int rw) /* READING or PEEKING */
|
||||
{
|
||||
struct buf *bp;
|
||||
int r = OK;
|
||||
|
||||
*completed = 0;
|
||||
|
||||
bp = read_extent_block(i_node->extent, position / block_size);
|
||||
if (bp == NULL)
|
||||
panic("bp not valid in rw_chunk; this can't happen");
|
||||
|
||||
if(rw == READING) {
|
||||
r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
|
||||
(vir_bytes) (b_data(bp)+off),
|
||||
(phys_bytes) chunk);
|
||||
}
|
||||
|
||||
put_block(bp);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,46 +1,29 @@
|
|||
#include "inc.h"
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <minix/com.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
int fs_stat()
|
||||
int fs_stat(ino_t ino_nr, struct stat *statbuf)
|
||||
{
|
||||
int r = EINVAL; /* return value */
|
||||
struct inode *dir;
|
||||
struct inode *rip;
|
||||
|
||||
if ((dir = get_inode(fs_m_in.m_vfs_fs_stat.inode)) != NULL) {
|
||||
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant,
|
||||
0, (vir_bytes) &dir->i_stat,
|
||||
(phys_bytes) sizeof(dir->i_stat));
|
||||
put_inode(dir);
|
||||
if ((rip = find_inode(ino_nr)) == NULL)
|
||||
return EINVAL;
|
||||
|
||||
*statbuf = rip->i_stat;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int fs_statvfs()
|
||||
int fs_statvfs(struct statvfs *st)
|
||||
{
|
||||
int r;
|
||||
struct statvfs st;
|
||||
st->f_flag = ST_NOTRUNC;
|
||||
st->f_bsize = v_pri.logical_block_size_l;
|
||||
st->f_frsize = st->f_bsize;
|
||||
st->f_iosize = st->f_bsize;
|
||||
st->f_blocks = v_pri.volume_space_size_l;
|
||||
st->f_namemax = NAME_MAX;
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
|
||||
st.f_bsize = v_pri.logical_block_size_l;
|
||||
st.f_frsize = st.f_bsize;
|
||||
st.f_iosize = st.f_bsize;
|
||||
st.f_blocks = v_pri.volume_space_size_l;
|
||||
st.f_namemax = NAME_MAX;
|
||||
|
||||
/* Copy the struct to user space. */
|
||||
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, 0,
|
||||
(vir_bytes) &st, (phys_bytes) sizeof(st));
|
||||
|
||||
return r;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void fs_blockstats(u64_t *blocks, u64_t *free, u64_t *used)
|
||||
|
@ -48,4 +31,3 @@ void fs_blockstats(u64_t *blocks, u64_t *free, u64_t *used)
|
|||
*used = *blocks = v_pri.volume_space_size_l;
|
||||
*free = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ int release_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri)
|
|||
return OK;
|
||||
}
|
||||
|
||||
int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
||||
size_t address)
|
||||
static int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
||||
size_t __unused address)
|
||||
{
|
||||
/*
|
||||
* This function fullfill the super block data structure using the
|
||||
|
@ -38,7 +38,8 @@ int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
|||
memcpy(vol_pri, buf, 2048);
|
||||
|
||||
/* Check various fields for consistency. */
|
||||
if ((memcmp(vol_pri->standard_id, "CD001", ISO9660_SIZE_STANDARD_ID) != 0) ||
|
||||
if ((memcmp(vol_pri->standard_id, "CD001",
|
||||
ISO9660_SIZE_STANDARD_ID) != 0) ||
|
||||
(vol_pri->vd_version != 1) ||
|
||||
(vol_pri->logical_block_size_l < 2048) ||
|
||||
(vol_pri->file_struct_ver != 1))
|
||||
|
@ -51,8 +52,10 @@ int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
|||
root = alloc_inode();
|
||||
extent = alloc_extent();
|
||||
|
||||
extent->location = root_record->loc_extent_l + root_record->ext_attr_rec_length;
|
||||
extent->length = root_record->data_length_l / vol_pri->logical_block_size_l;
|
||||
extent->location =
|
||||
root_record->loc_extent_l + root_record->ext_attr_rec_length;
|
||||
extent->length =
|
||||
root_record->data_length_l / vol_pri->logical_block_size_l;
|
||||
if (root_record->data_length_l % vol_pri->logical_block_size_l)
|
||||
extent->length++;
|
||||
|
||||
|
@ -72,8 +75,8 @@ int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
|
|||
int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
|
||||
{
|
||||
/*
|
||||
* This function reads from a ISO9660 filesystem (in the device dev) the
|
||||
* super block and saves it in vol_pri.
|
||||
* This function reads from a ISO9660 filesystem (in the device dev)
|
||||
* the super block and saves it in vol_pri.
|
||||
*/
|
||||
size_t offset;
|
||||
int vol_ok = FALSE, vol_pri_flag = FALSE;
|
||||
|
@ -81,10 +84,12 @@ int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
|
|||
static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
|
||||
int i = 0;
|
||||
|
||||
for(offset = ISO9660_SUPER_BLOCK_POSITION; !vol_ok && i++ < MAX_ATTEMPTS;
|
||||
for(offset = ISO9660_SUPER_BLOCK_POSITION;
|
||||
!vol_ok && i++ < MAX_ATTEMPTS;
|
||||
offset += ISO9660_MIN_BLOCK_SIZE) {
|
||||
/* Read the sector of the super block. */
|
||||
r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE, BDEV_NOFLAGS);
|
||||
r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE,
|
||||
BDEV_NOFLAGS);
|
||||
|
||||
if (r != ISO9660_MIN_BLOCK_SIZE) {
|
||||
/* Damaged sector or what? */
|
||||
|
@ -109,4 +114,3 @@ int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
|
|||
else
|
||||
return OK; /* otherwise. */
|
||||
}
|
||||
|
||||
|
|
|
@ -44,13 +44,13 @@ int parse_susp(struct rrii_dir_record *dir, char *buffer)
|
|||
ca_length = v_pri.logical_block_size_l - ca_offset;
|
||||
}
|
||||
|
||||
ca_bp = get_block(ca_block_nr);
|
||||
ca_bp = lmfs_get_block(fs_dev, ca_block_nr, NORMAL);
|
||||
if (ca_bp == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
parse_susp_buffer(dir, b_data(ca_bp) + ca_offset, ca_length);
|
||||
put_block(ca_bp);
|
||||
lmfs_put_block(ca_bp, FULL_DATA_BLOCK);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -8,40 +8,25 @@
|
|||
|
||||
#include "inc.h"
|
||||
|
||||
int (*fs_call_vec[])(void) = {
|
||||
no_sys, /* 0: not used */
|
||||
no_sys, /* 1: not used */
|
||||
fs_putnode, /* 2 */
|
||||
no_sys, /* 3: not used */
|
||||
no_sys, /* 4: not used */
|
||||
no_sys, /* 5: not used */
|
||||
no_sys, /* 6: not used */
|
||||
do_noop, /* 7 */
|
||||
fs_stat, /* 8 */
|
||||
no_sys, /* 9: not used */
|
||||
fs_statvfs, /* 10 */
|
||||
fs_bread, /* 11 */
|
||||
no_sys, /* 12: not used */
|
||||
no_sys, /* 13: not used */
|
||||
no_sys, /* 14: not used */
|
||||
fs_unmount, /* 15 */
|
||||
fs_sync, /* 16 */
|
||||
fs_new_driver, /* 17 */
|
||||
no_sys, /* 18: not_used */
|
||||
fs_read, /* 19 */
|
||||
no_sys, /* 20: not used */
|
||||
no_sys, /* 21: not used */
|
||||
no_sys, /* 22: not used */
|
||||
no_sys, /* 23: not used */
|
||||
no_sys, /* 24: not used */
|
||||
no_sys, /* 25: not used */
|
||||
fs_lookup, /* 26 */
|
||||
fs_mountpoint, /* 27 */
|
||||
fs_readsuper, /* 28 */
|
||||
no_sys, /* 29: not used */
|
||||
fs_rdlink, /* 30 */
|
||||
fs_getdents, /* 31 */
|
||||
no_sys, /* 32 */
|
||||
no_sys, /* 33 */
|
||||
struct fsdriver isofs_table = {
|
||||
.fdr_mount = fs_mount,
|
||||
.fdr_unmount = fs_unmount,
|
||||
.fdr_lookup = fs_lookup,
|
||||
.fdr_putnode = fs_putnode,
|
||||
.fdr_read = fs_read,
|
||||
#if 0 /* FIXME: isofs uses subpage block sizes */
|
||||
.fdr_peek = fs_read,
|
||||
#endif
|
||||
.fdr_getdents = fs_getdents,
|
||||
.fdr_rdlink = fs_rdlink,
|
||||
.fdr_stat = fs_stat,
|
||||
.fdr_mountpt = fs_mountpt,
|
||||
.fdr_statvfs = fs_statvfs,
|
||||
.fdr_driver = lmfs_driver,
|
||||
.fdr_bread = lmfs_bio,
|
||||
.fdr_bwrite = lmfs_bio,
|
||||
#if 0 /* FIXME: isofs uses subpage block sizes */
|
||||
.fdr_bpeek = lmfs_bio,
|
||||
#endif
|
||||
.fdr_bflush = lmfs_bflush
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
#include "inc.h"
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
static struct dir_extent dir_extents[NR_DIR_EXTENT_RECORDS];
|
||||
|
||||
struct dir_extent* alloc_extent()
|
||||
struct dir_extent* alloc_extent(void)
|
||||
{
|
||||
/* Return a free extent from the pool. */
|
||||
int i;
|
||||
|
@ -46,7 +41,7 @@ struct buf* read_extent_block(struct dir_extent *e, size_t block)
|
|||
if (block_id == 0 || block_id >= v_pri.volume_space_size_l)
|
||||
return NULL;
|
||||
|
||||
return get_block(block_id);
|
||||
return lmfs_get_block(fs_dev, block_id, NORMAL);
|
||||
}
|
||||
|
||||
size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block)
|
||||
|
@ -70,7 +65,9 @@ size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block)
|
|||
|
||||
time_t date7_to_time_t(const u8_t *date)
|
||||
{
|
||||
/* This function converts from the ISO 9660 7-byte time format to a time_t. */
|
||||
/* This function converts from the ISO 9660 7-byte time format to a
|
||||
* time_t.
|
||||
*/
|
||||
struct tm ltime;
|
||||
signed char time_zone = (signed char)date[6];
|
||||
|
||||
|
@ -88,16 +85,3 @@ time_t date7_to_time_t(const u8_t *date)
|
|||
|
||||
return mktime(<ime);
|
||||
}
|
||||
|
||||
int do_noop(void)
|
||||
{
|
||||
/* Do not do anything. */
|
||||
return OK;
|
||||
}
|
||||
|
||||
int no_sys(void)
|
||||
{
|
||||
/* Somebody has used an illegal system call number */
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue