Ejemplo n.º 1
0
/*
 * Mount the file system.  Obtain the root inode and send back its details.
 */
int
fs_mount(dev_t __unused dev, unsigned int flags,
         struct fsdriver_node * root_node, unsigned int * res_flags)
{
    struct inode *root;

    /* VTreeFS must not be mounted as a root file system. */
    if (flags & REQ_ISROOT)
        return EINVAL;

    /* Get the root inode and increase its reference count. */
    root = get_root_inode();
    ref_inode(root);

    /* The system is now mounted.  Call the initialization hook. */
    if (vtreefs_hooks->init_hook != NULL)
        vtreefs_hooks->init_hook();

    /* Return the root inode's properties. */
    root_node->fn_ino_nr = get_inode_number(root);
    root_node->fn_mode = root->i_stat.mode;
    root_node->fn_size = root->i_stat.size;
    root_node->fn_uid = root->i_stat.uid;
    root_node->fn_gid = root->i_stat.gid;
    root_node->fn_dev = NO_DEV;

    *res_flags = RES_NOFLAGS;

    return OK;
}
Ejemplo n.º 2
0
Archivo: path.c Proyecto: Hooman3/minix
/*
 * Resolve a path string to an inode.
 */
int
fs_lookup(ino_t dir_nr, char * name, struct fsdriver_node * node_details,
	int * is_mountpt)
{
	struct inode *node, *child;
	int r;

	if ((node = find_inode(dir_nr)) == NULL)
		return EINVAL;

	if (!S_ISDIR(node->i_stat.mode))
		return ENOTDIR;

	if (strlen(name) > PNAME_MAX)
		return ENAMETOOLONG;

	if (!strcmp(name, ".")) {
		/* Stay in the given directory. */
		child = node;
	} else if (!strcmp(name, "..")) {
		/* Progress into the parent directory. */
		if ((child = get_parent_inode(node)) == NULL)
			return ENOENT;	/* deleted? should not be possible */
	} else {
		/* Progress into a directory entry.  Call the lookup hook, if
		 * present, before doing the actual lookup.
		 */
		if (!is_inode_deleted(node) &&
		    vtreefs_hooks->lookup_hook != NULL) {
			r = vtreefs_hooks->lookup_hook(node, name,
			    get_inode_cbdata(node));
			if (r != OK) return r;
		}

		if ((child = get_inode_by_name(node, name)) == NULL)
			return ENOENT;
	}

	/* On success, open the resulting file and return its details. */
	ref_inode(child);

	node_details->fn_ino_nr = get_inode_number(child);
	node_details->fn_mode = child->i_stat.mode;
	node_details->fn_size = child->i_stat.size;
	node_details->fn_uid = child->i_stat.uid;
	node_details->fn_gid = child->i_stat.gid;
	node_details->fn_dev = child->i_stat.dev;

	*is_mountpt = FALSE;

	return OK;
}
Ejemplo n.º 3
0
/*===========================================================================*
 *				fs_stat					     *
 *===========================================================================*/
PUBLIC int fs_stat(void)
{
	/* Retrieve file status.
	 */
	char path[PATH_MAX];
	struct stat statbuf;
	time_t cur_time;
	struct inode *node;
	int r;

	if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL)
		return EINVAL;

	memset(&statbuf, 0, sizeof(struct stat));

	/* Fill in the basic info. */
	statbuf.st_dev = fs_dev;
	statbuf.st_ino = get_inode_number(node);
	statbuf.st_mode = node->i_stat.mode;
	statbuf.st_nlink = !is_inode_deleted(node);
	statbuf.st_uid = node->i_stat.uid;
	statbuf.st_gid = node->i_stat.gid;
	statbuf.st_rdev = (dev_t) node->i_stat.dev;
	statbuf.st_size = node->i_stat.size;

	/* If it is a symbolic link, return the size of the link target. */
	if (S_ISLNK(node->i_stat.mode) && vtreefs_hooks->rdlink_hook != NULL) {
		r = vtreefs_hooks->rdlink_hook(node, path, sizeof(path),
			get_inode_cbdata(node));

		if (r == OK)
			statbuf.st_size = strlen(path);
	}

	/* Take the current time as file time for all files. */
	cur_time = time(NULL);
	statbuf.st_atime = cur_time;
	statbuf.st_mtime = cur_time;
	statbuf.st_ctime = cur_time;

	/* Copy the struct to user space. */
	return sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
		(vir_bytes) &statbuf, (phys_bytes) sizeof(statbuf), D);
}
Ejemplo n.º 4
0
/*===========================================================================*
 *				fs_stat					     *
 *===========================================================================*/
int fs_stat(ino_t ino_nr, struct stat *buf)
{
	/* Retrieve file status.
	 */
	char path[PATH_MAX];
	time_t cur_time;
	struct inode *node;
	int r;

	if ((node = find_inode(ino_nr)) == NULL)
		return EINVAL;

	/* Fill in the basic info. */
	buf->st_dev = fs_dev;
	buf->st_ino = get_inode_number(node);
	buf->st_mode = node->i_stat.mode;
	buf->st_nlink = !is_inode_deleted(node);
	buf->st_uid = node->i_stat.uid;
	buf->st_gid = node->i_stat.gid;
	buf->st_rdev = (dev_t) node->i_stat.dev;
	buf->st_size = node->i_stat.size;

	/* If it is a symbolic link, return the size of the link target. */
	if (S_ISLNK(node->i_stat.mode) && vtreefs_hooks->rdlink_hook != NULL) {
		r = vtreefs_hooks->rdlink_hook(node, path, sizeof(path),
			get_inode_cbdata(node));

		if (r == OK)
			buf->st_size = strlen(path);
	}

	/* Take the current time as file time for all files. */
	cur_time = clock_time(NULL);
	buf->st_atime = cur_time;
	buf->st_mtime = cur_time;
	buf->st_ctime = cur_time;

	return OK;
}
Ejemplo n.º 5
0
/*===========================================================================*
 *				fs_readsuper				     *
 *===========================================================================*/
int fs_readsuper(void)
{
	/* This function gets the root inode and sends back its details.
	 */
	struct inode *root;

	/* Get the device number, for stat requests. */
	fs_dev = fs_m_in.REQ_DEV;

	/* The VTreeFS must not be mounted as a root file system. */
	if (fs_m_in.REQ_FLAGS & REQ_ISROOT)
		return EINVAL;

	/* Get the root inode and increase its reference count. */
	root = get_root_inode();
	ref_inode(root);

	/* The system is now mounted. Call the initialization hook. */
	if (vtreefs_hooks->init_hook != NULL)
		vtreefs_hooks->init_hook();

	/* Return the root inode's properties. */
	fs_m_out.RES_INODE_NR = get_inode_number(root);
	fs_m_out.RES_MODE = root->i_stat.mode;
	fs_m_out.RES_FILE_SIZE_HI = 0;
	fs_m_out.RES_FILE_SIZE_LO = root->i_stat.size;
	fs_m_out.RES_UID = root->i_stat.uid;
	fs_m_out.RES_GID = root->i_stat.gid;
	fs_m_out.RES_DEV = NO_DEV;

	fs_m_out.RES_CONREQS = 1;/* We can handle only 1 request at a time */

	fs_mounted = TRUE;

	return OK;
}
Ejemplo n.º 6
0
/*===========================================================================*
 *				fs_getdents				     *
 *===========================================================================*/
ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
	off_t *posp)
{
	/* Retrieve directory entries.
	 */
	struct fsdriver_dentry fsdentry;
	struct inode *node, *child;
	const char *name;
	off_t pos;
	int r, skip, get_next, indexed;
	static char buf[GETDENTS_BUFSIZ];

	if (*posp >= ULONG_MAX)
		return EIO;

	if ((node = find_inode(ino_nr)) == NULL)
		return EINVAL;

	indexed = node->i_indexed;
	get_next = FALSE;
	child = NULL;

	/* Call the getdents hook, if any, to "refresh" the directory. */
	if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) {
		r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node));
		if (r != OK) return r;
	}

	fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf));

	do {
		/* Determine which inode and name to use for this entry. */
		pos = (*posp)++;

		if (pos == 0) {
			/* The "." entry. */
			child = node;
			name = ".";
		}
		else if (pos == 1) {
			/* The ".." entry. */
			child = get_parent_inode(node);
			if (child == NULL)
				child = node;
			name = "..";
		}
		else if (pos - 2 < indexed) {
			/* All indexed entries. */
			child = get_inode_by_index(node, pos - 2);

			/* If there is no inode with this particular index,
			 * continue with the next index number.
			 */
			if (child == NULL) continue;

			name = child->i_name;
		}
		else {
			/* All non-indexed entries. */

			/* If this is the first loop iteration, first get to
			 * the non-indexed child identified by the current
			 * position.
			 */
			if (get_next == FALSE) {
				skip = pos - indexed - 2;
				child = get_first_inode(node);

				/* Skip indexed children. */
				while (child != NULL &&
						child->i_index != NO_INDEX)
					child = get_next_inode(child);

				/* Skip to the right position. */
				while (child != NULL && skip-- > 0)
					child = get_next_inode(child);

				get_next = TRUE;
			}
			else {
				child = get_next_inode(child);
			}

			/* No more children? Then stop. */
			if (child == NULL)
				break;

			assert(!is_inode_deleted(child));

			name = child->i_name;
		}

		/* Add the directory entry to the output. */
		r = fsdriver_dentry_add(&fsdentry,
			(ino_t) get_inode_number(child), name, strlen(name),
			IFTODT(child->i_stat.mode));
		if (r < 0)
			return r;
	} while (r > 0);

	return fsdriver_dentry_finish(&fsdentry);
}
Ejemplo n.º 7
0
Archivo: read.c Proyecto: Sciumo/minix
/*===========================================================================*
 *				fs_getdents				     *
 *===========================================================================*/
int fs_getdents(void)
{
	/* Retrieve directory entries.
	 */
	struct inode *node, *child = NULL;
	struct dirent *dent;
	char *name;
	size_t len, off, user_off, user_left;
	off_t pos;
	int r, skip, get_next, indexed;
	static char buf[GETDENTS_BUFSIZ];

	if (fs_m_in.REQ_SEEK_POS_HI != 0)
		return EIO;

	if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL)
		return EINVAL;

	off = 0;
	user_off = 0;
	user_left = fs_m_in.REQ_MEM_SIZE;
	indexed = node->i_indexed;
	get_next = FALSE;
	child = NULL;

	/* Call the getdents hook, if any, to "refresh" the directory. */
	if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) {
		r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node));
		if (r != OK) return r;
	}

	for (pos = fs_m_in.REQ_SEEK_POS_LO; ; pos++) {
		/* Determine which inode and name to use for this entry. */
		if (pos == 0) {
			/* The "." entry. */
			child = node;
			name = ".";
		}
		else if (pos == 1) {
			/* The ".." entry. */
			child = get_parent_inode(node);
			if (child == NULL)
				child = node;
			name = "..";
		}
		else if (pos - 2 < indexed) {
			/* All indexed entries. */
			child = get_inode_by_index(node, pos - 2);

			/* If there is no inode with this particular index,
			 * continue with the next index number.
			 */
			if (child == NULL) continue;

			name = child->i_name;
		}
		else {
			/* All non-indexed entries. */

			/* If this is the first loop iteration, first get to
			 * the non-indexed child identified by the current
			 * position.
			 */
			if (get_next == FALSE) {
				skip = pos - indexed - 2;
				child = get_first_inode(node);

				/* Skip indexed children. */
				while (child != NULL &&
						child->i_index != NO_INDEX)
					child = get_next_inode(child);

				/* Skip to the right position. */
				while (child != NULL && skip-- > 0)
					child = get_next_inode(child);

				get_next = TRUE;
			}
			else {
				child = get_next_inode(child);
			}

			/* No more children? Then stop. */
			if (child == NULL)
				break;

			assert(!is_inode_deleted(child));

			name = child->i_name;
		}

		len = DWORD_ALIGN(sizeof(struct dirent) + strlen(name));

		/* Is the user buffer too small to store another record? */
		if (user_off + off + len > user_left) {
			/* Is the user buffer too small for even a single
			 * record?
			 */
			if (user_off == 0 && off == 0)
				return EINVAL;

			break;
		}

		/* If our own buffer cannot contain the new record, copy out
		 * first.
		 */
		if (off + len > sizeof(buf)) {
			r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT,
				user_off, (vir_bytes) buf, off, D);
			if (r != OK) return r;

			user_off += off;
			user_left -= off;
			off = 0;
		}

		/* Fill in the actual directory entry. */
		dent = (struct dirent *) &buf[off];
		dent->d_ino = get_inode_number(child);
		dent->d_off = pos;
		dent->d_reclen = len;
		strcpy(dent->d_name, name);

		off += len;
	}

	/* If there is anything left in our own buffer, copy that out now. */
	if (off > 0) {
		r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT,
			user_off, (vir_bytes) buf, off, D);
		if (r != OK)
			return r;

		user_off += off;
	}

	fs_m_out.RES_SEEK_POS_HI = 0;
	fs_m_out.RES_SEEK_POS_LO = pos;
	fs_m_out.RES_NBYTES = user_off;

	return OK;
}