示例#1
0
static void check_access(
  rtems_filesystem_eval_path_context_t *ctx,
  int eval_flags
)
{
  const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc;
  const rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry;

  if ((eval_flags & RTEMS_FS_PERMS_WRITE) == 0 || mt_entry->writeable) {
    struct stat st;
    int rv;

    st.st_mode = 0;
    st.st_uid = 0;
    st.st_gid = 0;
    rv = (*currentloc->handlers->fstat_h)(currentloc, &st);
    if (rv == 0) {
      bool access_ok = rtems_filesystem_check_access(
        eval_flags,
        st.st_mode,
        st.st_uid,
        st.st_gid
      );

      if (!access_ok) {
        rtems_filesystem_eval_path_error(ctx, EACCES);
      }
    } else {
      rtems_filesystem_eval_path_error(ctx, 0);
    }
  } else {
    rtems_filesystem_eval_path_error(ctx, EROFS);
  }
}
示例#2
0
void rtems_filesystem_eval_path_continue(
  rtems_filesystem_eval_path_context_t *ctx
)
{
  int eval_flags;

  while (ctx->pathlen > 0) {
    (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
  }

  eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
  if (rtems_filesystem_eval_path_has_token(ctx)) {
    bool make = (eval_flags & RTEMS_FS_MAKE) != 0;

    if (make) {
      check_access(ctx, RTEMS_FS_PERMS_WRITE);
    } else {
      rtems_filesystem_eval_path_error(ctx, ENOENT);
    }
  } else {
    bool exclusive = (eval_flags & RTEMS_FS_EXCLUSIVE) != 0;

    if (!exclusive) {
      check_access(ctx, ctx->flags);
    } else {
      rtems_filesystem_eval_path_error(ctx, EEXIST);
    }
  }
}
示例#3
0
void rtems_filesystem_eval_path_recursive(
  rtems_filesystem_eval_path_context_t *ctx,
  const char *path,
  size_t pathlen
)
{
  if (pathlen > 0) {
    if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) {
      const char *saved_path = ctx->path;
      size_t saved_pathlen = ctx->pathlen;

      if (rtems_filesystem_is_delimiter(path [0])) {
        rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc);
      }

      ctx->path = path;
      ctx->pathlen = pathlen;

      ++ctx->recursionlevel;
      while (ctx->pathlen > 0) {
        (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
      }
      --ctx->recursionlevel;

      ctx->path = saved_path;
      ctx->pathlen = saved_pathlen;
    } else {
      rtems_filesystem_eval_path_error(ctx, ELOOP);
    }
  } else {
    rtems_filesystem_eval_path_error(ctx, ENOENT);
  }
}
示例#4
0
static void
rtems_rfs_rtems_eval_path (rtems_filesystem_eval_path_context_t *ctx)
{
  rtems_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_get_currentloc (ctx);
  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
  rtems_rfs_ino ino = rtems_rfs_rtems_get_pathloc_ino (currentloc);
  rtems_rfs_inode_handle inode;
  int rc;

  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
  if (rc == 0) {
    rtems_filesystem_eval_path_generic (
      ctx,
      &inode,
      &rtems_rfs_rtems_eval_config
    );
    rc = rtems_rfs_inode_close (fs, &inode);
    if (rc != 0) {
      rtems_filesystem_eval_path_error (
        ctx,
        rtems_rfs_rtems_error ("eval_path: closing inode", rc)
      );
    }
  } else {
    rtems_filesystem_eval_path_error (
      ctx,
      rtems_rfs_rtems_error ("eval_path: opening inode", rc)
    );
  }
}
示例#5
0
文件: unlink.c 项目: AoLaD/rtems
/**
 *  POSIX 1003.1b - 5.5.1 - Remove an existing link
 */
int unlink( const char *path )
{
  int rv = 0;
  rtems_filesystem_eval_path_context_t ctx;
  int eval_flags = RTEMS_FS_REJECT_TERMINAL_DOT;
  rtems_filesystem_location_info_t parentloc;
  int parent_eval_flags = RTEMS_FS_PERMS_WRITE
    | RTEMS_FS_PERMS_EXEC
    | RTEMS_FS_FOLLOW_LINK;
  const rtems_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_start_with_parent(
      &ctx,
      path,
      eval_flags,
      &parentloc,
      parent_eval_flags
    );

  if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) {
    const rtems_filesystem_operations_table *ops = currentloc->mt_entry->ops;

    rv = (*ops->rmnod_h)( &parentloc, currentloc );
  } else {
    rtems_filesystem_eval_path_error( &ctx, EBUSY );
    rv = -1;
  }

  rtems_filesystem_eval_path_cleanup_with_parent( &ctx, &parentloc );

  return rv;
}
示例#6
0
static rtems_filesystem_eval_path_generic_status msdos_eval_token(
  rtems_filesystem_eval_path_context_t *ctx,
  void *arg,
  const char *token,
  size_t tokenlen
)
{
  rtems_filesystem_eval_path_generic_status status =
    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;

  if (rtems_filesystem_is_current_directory(token, tokenlen)) {
    rtems_filesystem_eval_path_clear_token(ctx);
    status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
  } else {
    rtems_filesystem_location_info_t *currentloc =
      rtems_filesystem_eval_path_get_currentloc(ctx);
    int rc = msdos_find_name(currentloc, token, tokenlen);

    if (rc == RC_OK) {
      rtems_filesystem_eval_path_clear_token(ctx);
      msdos_set_handlers(currentloc);
      if (rtems_filesystem_eval_path_has_path(ctx)) {
        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
      }
    } else if (rc == MSDOS_NAME_NOT_FOUND_ERR) {
      status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
    } else {
      rtems_filesystem_eval_path_error(ctx, 0);
    }
  }

  return status;
}
示例#7
0
文件: open.c 项目: AoLaD/rtems
static void create_regular_file(
  rtems_filesystem_eval_path_context_t *ctx,
  mode_t mode
)
{
  int rv = 0;
  const rtems_filesystem_location_info_t *currentloc = 
    rtems_filesystem_eval_path_get_currentloc( ctx );
  const char *token = rtems_filesystem_eval_path_get_token( ctx );
  size_t tokenlen = rtems_filesystem_eval_path_get_tokenlen( ctx );

  rv = rtems_filesystem_mknod(
    currentloc,
    token,
    tokenlen,
    S_IFREG | mode,
    0
  );

  if ( rv == 0 ) {
    /* The mode only applies to future accesses of the newly created file */
    rtems_filesystem_eval_path_set_flags( ctx, 0 );

    rtems_filesystem_eval_path_set_path( ctx, token, tokenlen );
    rtems_filesystem_eval_path_continue( ctx );
  } else {
    rtems_filesystem_eval_path_error( ctx, 0 );
  }
}
示例#8
0
static void rtems_ftpfs_eval_path(
  rtems_filesystem_eval_path_context_t *self
)
{
  rtems_filesystem_eval_path_eat_delimiter(self);

  if (rtems_filesystem_eval_path_has_path(self)) {
    const char *path = rtems_filesystem_eval_path_get_path(self);
    size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
    char *pathdup = malloc(pathlen + 1);

    rtems_filesystem_eval_path_clear_path(self);

    if (pathdup != NULL) {
      rtems_filesystem_location_info_t *currentloc =
        rtems_filesystem_eval_path_get_currentloc(self);

      memcpy(pathdup, path, pathlen);
      pathdup [pathlen] = '\0';
      currentloc->node_access = pathdup;
      currentloc->handlers = &rtems_ftpfs_handlers;
    } else {
      rtems_filesystem_eval_path_error(self, ENOMEM);
    }
  }
}
示例#9
0
static void rtems_rfs_rtems_follow_link(
  rtems_filesystem_eval_path_context_t* ctx,
  rtems_rfs_file_system* fs,
  rtems_rfs_ino ino
)
{
  size_t len = MAXPATHLEN;
  char *link = malloc(len + 1);

  if (link != NULL) {
    int rc = rtems_rfs_symlink_read (fs, ino, link, len, &len);

    if (rc == 0) {
      rtems_filesystem_eval_path_recursive (ctx, link, len);
    } else {
      rtems_filesystem_eval_path_error (ctx, 0);
    }

    free(link);
  } else {
    rtems_filesystem_eval_path_error (ctx, ENOMEM);
  }
}
示例#10
0
static void rtems_tfs_eval_path(rtems_filesystem_eval_path_context_t *self)
{
    int eval_flags = rtems_filesystem_eval_path_get_flags(self);

    if ((eval_flags & RTEMS_FS_MAKE) == 0) {
        int rw = RTEMS_FS_PERMS_READ | RTEMS_FS_PERMS_WRITE;

        if ((eval_flags & rw) != rw) {
            rtems_filesystem_location_info_t *currentloc =
                rtems_filesystem_eval_path_get_currentloc(self);
            char *current = currentloc->node_access;
            size_t currentlen = strlen(current);
            const char *path = rtems_filesystem_eval_path_get_path(self);
            size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
            size_t len = currentlen + pathlen;

            rtems_filesystem_eval_path_clear_path(self);

            current = realloc(current, len + 1);
            if (current != NULL) {
                memcpy(current + currentlen, path, pathlen);
                current [len] = '\0';
                if (!rtems_tfs_is_directory(current, len)) {
                    fixPath (current);
                }
                currentloc->node_access = current;
            } else {
                rtems_filesystem_eval_path_error(self, ENOMEM);
            }
        } else {
            rtems_filesystem_eval_path_error(self, EINVAL);
        }
    } else {
        rtems_filesystem_eval_path_error(self, EIO);
    }
}
示例#11
0
bool rtems_filesystem_eval_path_check_access(
  rtems_filesystem_eval_path_context_t *ctx,
  int eval_flags,
  mode_t node_mode,
  uid_t node_uid,
  gid_t node_gid
)
{
  bool access_ok = rtems_filesystem_check_access(
    eval_flags,
    node_mode,
    node_uid,
    node_gid
  );

  if (!access_ok) {
    rtems_filesystem_eval_path_error(ctx, EACCES);
  }

  return access_ok;
}
示例#12
0
ssize_t readlink( const char *path, char *buf, size_t bufsize )
{
  ssize_t rv = 0;
  rtems_filesystem_eval_path_context_t ctx;
  int eval_flags = RTEMS_FS_FOLLOW_HARD_LINK;
  const rtems_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
  const rtems_filesystem_operations_table *ops = currentloc->mt_entry->ops;
  rtems_filesystem_node_types_t type = (*ops->node_type_h)( currentloc );

  if ( type == RTEMS_FILESYSTEM_SYM_LINK ) {
    rv = (*ops->readlink_h)( currentloc, buf, bufsize );
  } else {
    rtems_filesystem_eval_path_error( &ctx, EINVAL );
    rv = -1;
  }

  rtems_filesystem_eval_path_cleanup( &ctx );

  return rv;
}
示例#13
0
文件: mount.c 项目: chch1028/rtems
static int register_subordinate_file_system(
  rtems_filesystem_mount_table_entry_t *mt_entry,
  const char *target
)
{
  int rv = 0;
  rtems_filesystem_eval_path_context_t ctx;
  int eval_flags = RTEMS_FS_PERMS_RWX
    | RTEMS_FS_FOLLOW_LINK;
  rtems_filesystem_location_info_t *currentloc =
    rtems_filesystem_eval_path_start( &ctx, target, eval_flags );

  if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) {
    rtems_filesystem_location_info_t targetloc;
    rtems_filesystem_global_location_t *mt_point_node;

    rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc );
    mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc );
    mt_entry->mt_point_node = mt_point_node;
    rv = (*mt_point_node->location.mt_entry->ops->mount_h)( mt_entry );
    if ( rv == 0 ) {
      rtems_filesystem_mt_lock();
      rtems_chain_append_unprotected(
        &rtems_filesystem_mount_table,
        &mt_entry->mt_node
      );
      rtems_filesystem_mt_unlock();
    } else {
      rtems_filesystem_global_location_release( mt_point_node );
    }
  } else {
    rtems_filesystem_eval_path_error( &ctx, EBUSY );
    rv = -1;
  }

  rtems_filesystem_eval_path_cleanup( &ctx );

  return rv;
}
示例#14
0
static rtems_filesystem_eval_path_generic_status rtems_jffs2_eval_token(
	rtems_filesystem_eval_path_context_t *ctx,
	void *arg,
	const char *token,
	size_t tokenlen
)
{
	rtems_filesystem_eval_path_generic_status status =
		RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
	rtems_filesystem_location_info_t *currentloc =
		rtems_filesystem_eval_path_get_currentloc(ctx);
	struct _inode *dir_i = rtems_jffs2_get_inode_by_location(currentloc);
	bool access_ok = rtems_filesystem_eval_path_check_access(
		ctx,
		RTEMS_FS_PERMS_EXEC,
		dir_i->i_mode,
		dir_i->i_uid,
		dir_i->i_gid
	);

	if (access_ok) {
		struct _inode *entry_i;

		if (rtems_filesystem_is_current_directory(token, tokenlen)) {
			entry_i = dir_i;
			++entry_i->i_count;
		} else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
			entry_i = dir_i->i_parent;
			++entry_i->i_count;
		} else {
			entry_i = jffs2_lookup(dir_i, token, (int) tokenlen);
		}

		if (IS_ERR(entry_i)) {
			rtems_filesystem_eval_path_error(ctx, PTR_ERR(entry_i));
		} else if (entry_i != NULL) {
			bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
			int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
			bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;

			rtems_filesystem_eval_path_clear_token(ctx);

			if (S_ISLNK(entry_i->i_mode) && (follow_sym_link || !terminal)) {
				struct jffs2_inode_info *f = JFFS2_INODE_INFO(entry_i);
				const char *target = f->target;

				rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));

				jffs2_iput(entry_i);
			} else {
				if (S_ISDIR(entry_i->i_mode) && entry_i->i_parent == NULL) {
					entry_i->i_parent = dir_i;
					++dir_i->i_count;
				}

				jffs2_iput(dir_i);
				rtems_jffs2_set_location(currentloc, entry_i);

				if (rtems_filesystem_eval_path_has_path(ctx)) {
					status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
				}
			}
		} else {
			status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
		}
	}

	return status;
}
示例#15
0
static rtems_filesystem_eval_path_generic_status
rtems_rfs_rtems_eval_token(
  rtems_filesystem_eval_path_context_t *ctx,
  void *arg,
  const char *token,
  size_t tokenlen
)
{
  rtems_filesystem_eval_path_generic_status status =
    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
  rtems_rfs_inode_handle* inode = arg;
  bool access_ok = rtems_rfs_rtems_eval_perms (ctx, RTEMS_FS_PERMS_EXEC, inode);

  if (access_ok) {
    if (rtems_filesystem_is_current_directory (token, tokenlen)) {
      rtems_filesystem_eval_path_clear_token (ctx);
    } else {
      rtems_filesystem_location_info_t *currentloc =
        rtems_filesystem_eval_path_get_currentloc( ctx );
      rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (currentloc);
      rtems_rfs_ino entry_ino;
      uint32_t entry_doff;
      int rc = rtems_rfs_dir_lookup_ino (
        fs,
        inode,
        token,
        tokenlen,
        &entry_ino,
        &entry_doff
      );

      if (rc == 0) {
        rc = rtems_rfs_inode_close (fs, inode);
        if (rc == 0) {
          rc = rtems_rfs_inode_open (fs, entry_ino, inode, true);
        }

        if (rc != 0) {
          /*
           * This prevents the rtems_rfs_inode_close() from doing something in
           * rtems_rfs_rtems_eval_path().
           */
          memset (inode, 0, sizeof(*inode));
        }
      } else {
        status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
        rc = -1;
      }

      if (rc == 0) {
        bool is_sym_link = rtems_rfs_rtems_node_type_by_inode (inode)
          == RTEMS_FILESYSTEM_SYM_LINK;
        int eval_flags = rtems_filesystem_eval_path_get_flags (ctx);
        bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
        bool terminal = !rtems_filesystem_eval_path_has_path (ctx);

        rtems_filesystem_eval_path_clear_token (ctx);

        if (is_sym_link && (follow_sym_link || !terminal)) {
          rtems_rfs_rtems_follow_link (ctx, fs, entry_ino);
        } else {
          rc = rtems_rfs_rtems_set_handlers (currentloc, inode) ? 0 : EIO;
          if (rc == 0) {
            rtems_rfs_rtems_set_pathloc_ino (currentloc, entry_ino);
            rtems_rfs_rtems_set_pathloc_doff (currentloc, entry_doff);

            if (!terminal) {
              status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
            }
          } else {
            rtems_filesystem_eval_path_error (
              ctx,
              rtems_rfs_rtems_error ("eval_path: set handlers", rc)
            );
          }
        }
      }
    }
  }

  return status;
}
示例#16
0
int IMFS_make_generic_node(
  const char *path,
  mode_t mode,
  const IMFS_node_control *node_control,
  void *context
)
{
  int rv = 0;

  mode &= ~rtems_filesystem_umask;

  switch (mode & S_IFMT) {
    case S_IFBLK:
    case S_IFCHR:
    case S_IFIFO:
    case S_IFREG:
      break;
    default:
      errno = EINVAL;
      rv = -1;
      break;
  }
  
  if ( rv == 0 ) {
    if ( node_control->imfs_type == IMFS_GENERIC ) {
      rtems_filesystem_eval_path_context_t ctx;
      int eval_flags = RTEMS_FS_FOLLOW_LINK
        | RTEMS_FS_MAKE
        | RTEMS_FS_EXCLUSIVE;
      const rtems_filesystem_location_info_t *currentloc =
        rtems_filesystem_eval_path_start( &ctx, path, eval_flags );

      if ( IMFS_is_imfs_instance( currentloc ) ) {
        IMFS_types_union info;
        IMFS_jnode_t *new_node;

        info.generic.context = context;
        new_node = IMFS_create_node_with_control(
          currentloc,
          node_control,
          rtems_filesystem_eval_path_get_token( &ctx ),
          rtems_filesystem_eval_path_get_tokenlen( &ctx ),
          mode,
          &info
        );

        if ( new_node != NULL ) {
          IMFS_jnode_t *parent = currentloc->node_access;

          IMFS_update_ctime( parent );
          IMFS_update_mtime( parent );
        } else {
          rv = -1;
        }
      } else {
        rtems_filesystem_eval_path_error( &ctx, ENOTSUP );
        rv = -1;
      }

      rtems_filesystem_eval_path_cleanup( &ctx );
    } else {
      errno = EINVAL;
      rv = -1;
    }
  }

  return rv;
}
示例#17
0
文件: open.c 项目: AoLaD/rtems
static int do_open(
  rtems_libio_t *iop,
  const char *path,
  int oflag,
  mode_t mode
)
{
  int rv = 0;
  int fd = rtems_libio_iop_to_descriptor( iop );
  int rwflag = oflag + 1;
  bool read_access = (rwflag & _FREAD) == _FREAD;
  bool write_access = (rwflag & _FWRITE) == _FWRITE;
  bool make = (oflag & O_CREAT) == O_CREAT;
  bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
  bool truncate = (oflag & O_TRUNC) == O_TRUNC;
  int eval_flags = RTEMS_FS_FOLLOW_LINK
    | (read_access ? RTEMS_FS_PERMS_READ : 0)
    | (write_access ? RTEMS_FS_PERMS_WRITE : 0)
    | (make ? RTEMS_FS_MAKE : 0)
    | (exclusive ?  RTEMS_FS_EXCLUSIVE : 0);
  rtems_filesystem_eval_path_context_t ctx;

  rtems_filesystem_eval_path_start( &ctx, path, eval_flags );

  if ( rtems_filesystem_eval_path_has_token( &ctx ) ) {
    create_regular_file( &ctx, mode );
  }

  if ( write_access ) {
    const rtems_filesystem_location_info_t *currentloc =
      rtems_filesystem_eval_path_get_currentloc( &ctx );
    mode_t type = rtems_filesystem_location_type( currentloc );

    if ( S_ISDIR( type ) ) {
      rtems_filesystem_eval_path_error( &ctx, EISDIR );
    }
  }

  iop->flags |= rtems_libio_fcntl_flags( oflag );
  rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo );
  rtems_filesystem_eval_path_cleanup( &ctx );

  rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode );

  if ( rv == 0 ) {
    if ( truncate ) {
      rv = ftruncate( fd, 0 );
      if ( rv != 0 ) {
        (*iop->pathinfo.handlers->close_h)( iop );
      }
    }

    if ( rv == 0 ) {
      rv = fd;
    } else {
      rv = -1;
    }
  }

  if ( rv < 0 ) {
    rtems_libio_free( iop );
  }

  return rv;
}