Ejemplo n.º 1
0
/*===========================================================================*
 *				verify_path				     *
 *===========================================================================*/
int verify_path(char path[PATH_MAX], struct inode *ino,
	struct sffs_attr *attr, int *stale)
{
/* Given a path, and the inode associated with that path, verify if the inode
 * still matches the real world. Obtain the attributes of the file identified
 * by the given path, and see if they match. If not, possibly mark the inode
 * as deleted and return an error. Only upon success is the inode guaranteed
 * to be usable.
 *
 * The caller must set the a_mask field of the passed attr struct.
 * If 'stale' is not NULL, the value it points to must be initialized to 0,
 * and will be set to 1 if the path was valid but the inode wasn't.
 */
  int r;

  attr->a_mask |= SFFS_ATTR_MODE;

  r = sffs_table->t_getattr(path, attr);

  dprintf(("%s: verify_path: getattr('%s') returned %d\n",
	sffs_name, path, r));

  if (r != OK) {
	/* If we are told that the path does not exist, delete the inode */
	if (r == ENOENT || r == ENOTDIR)
		del_dentry(ino);

	return r; /* path isn't valid */
  }

  /* If the file type (reg, dir) isn't what we thought, delete the inode */
  if ((ino->i_flags & I_DIR) != MODE_TO_DIRFLAG(attr->a_mode)) {
	del_dentry(ino);

	if (stale != NULL) *stale = 1;
	return ENOENT; /* path is valid, inode wasn't */
  }

  return OK; /* path and inode are valid */
}
Ejemplo n.º 2
0
/*===========================================================================*
 *				do_mkdir				     *
 *===========================================================================*/
PUBLIC int do_mkdir()
{
/* Make a new directory.
 */
  char path[PATH_MAX], name[NAME_MAX+1];
  struct inode *parent, *ino;
  int r;

  /* We cannot create directories on a read-only file system. */
  if (state.read_only)
	return EROFS;

  /* Get the path string and possibly an inode for the given path. */
  if ((r = get_name(m_in.REQ_GRANT, m_in.REQ_PATH_LEN, name)) != OK)
	return r;

  if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST;

  if ((parent = find_inode(m_in.REQ_INODE_NR)) == NULL)
	return EINVAL;

  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
	return r;

  /* Perform the actual mkdir call. */
  r = hgfs_mkdir(path, m_in.REQ_MODE);

  if (r != OK) {
	if (ino != NULL)
		put_inode(ino);

	return r;
  }

  /* If we thought the new dentry already existed, it was apparently gone
   * already. Delete it.
   */
  if (ino != NULL) {
	del_dentry(ino);

	put_inode(ino);
  }

  return OK;
}
Ejemplo n.º 3
0
/*===========================================================================*
 *				do_create				     *
 *===========================================================================*/
PUBLIC int do_create()
{
/* Create a new file.
 */
  char path[PATH_MAX], name[NAME_MAX+1];
  struct inode *parent, *ino;
  struct hgfs_attr attr;
  hgfs_file_t handle;
  int r;

  /* We cannot create files on a read-only file system. */
  if (state.read_only)
	return EROFS;

  /* Get path, name, parent inode and possibly inode for the given path. */
  if ((r = get_name(m_in.REQ_GRANT, m_in.REQ_PATH_LEN, name)) != OK)
	return r;

  if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST;

  if ((parent = find_inode(m_in.REQ_INODE_NR)) == NULL)
	return EINVAL;

  if ((r = verify_dentry(parent, name, path, &ino)) != OK)
	return r;

  /* Are we going to need a new inode upon success?
   * Then make sure there is one available before trying anything.
   */
  if (ino == NULL || ino->i_ref > 1 || HAS_CHILDREN(ino)) {
	if (!have_free_inode()) {
		if (ino != NULL)
			put_inode(ino);

		return ENFILE;
	}
  }

  /* Perform the actual create call. */
  r = hgfs_open(path, O_CREAT | O_EXCL | O_RDWR, m_in.REQ_MODE, &handle);

  if (r != OK) {
	/* Let's not try to be too clever with error codes here. If something
	 * is wrong with the directory, we'll find out later anyway.
	 */

	if (ino != NULL)
		put_inode(ino);

	return r;
  }

  /* Get the created file's attributes. */
  attr.a_mask = HGFS_ATTR_MODE | HGFS_ATTR_SIZE;
  r = hgfs_getattr(path, &attr);

  /* If this fails, or returns a directory, we have a problem. This
   * scenario is in fact possible with race conditions.
   * Simulate a close and return a somewhat appropriate error.
   */
  if (r != OK || S_ISDIR(attr.a_mode)) {
	printf("HGFS: lost file after creation!\n");

	hgfs_close(handle);

	if (ino != NULL) {
		del_dentry(ino);

		put_inode(ino);
	}

	return (r == OK) ? EEXIST : r;
  }

  /* We do assume that the HGFS open(O_CREAT|O_EXCL) did its job.
   * If we previousy found an inode, get rid of it now. It's old.
   */
  if (ino != NULL) {
	del_dentry(ino);

	put_inode(ino);
  }

  /* Associate the open file handle with an inode, and reply with its details.
   */
  ino = get_free_inode();

  assert(ino != NULL); /* we checked before whether we had a free one */

  ino->i_file = handle;
  ino->i_flags = I_HANDLE;

  add_dentry(parent, name, ino);

  m_out.RES_INODE_NR = INODE_NR(ino);
  m_out.RES_MODE = get_mode(ino, attr.a_mode);
  m_out.RES_FILE_SIZE_HI = ex64hi(attr.a_size);
  m_out.RES_FILE_SIZE_LO = ex64lo(attr.a_size);
  m_out.RES_UID = opt.uid;
  m_out.RES_GID = opt.gid;
  m_out.RES_DEV = NO_DEV;

  return OK;
}