Added "query" and "chmod" (octal, non-recursive only) commands.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24331 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0006905bfb
commit
45eb999ec8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
||||
* Copyright 2007-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -278,6 +278,87 @@ command_cd(int argc, const char* const* argv)
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
get_permissions(const char* modeString, fssh_mode_t& _permissions)
|
||||
{
|
||||
// currently only octal mode is supported
|
||||
if (strlen(modeString) != 3)
|
||||
return false;
|
||||
|
||||
fssh_mode_t permissions = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
char c = modeString[i];
|
||||
if (c < '0' || c > '7')
|
||||
return false;
|
||||
permissions = (permissions << 3) | (c - '0');
|
||||
}
|
||||
|
||||
_permissions = permissions;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
command_chmod(int argc, const char* const* argv)
|
||||
{
|
||||
bool recursive = false;
|
||||
|
||||
// parse parameters
|
||||
int argi = 1;
|
||||
for (argi = 1; argi < argc; argi++) {
|
||||
const char *arg = argv[argi];
|
||||
if (arg[0] != '-')
|
||||
break;
|
||||
|
||||
if (arg[1] == '\0') {
|
||||
fprintf(stderr, "Error: Invalid option \"-\"\n");
|
||||
return FSSH_B_BAD_VALUE;
|
||||
}
|
||||
|
||||
for (int i = 1; arg[i]; i++) {
|
||||
switch (arg[i]) {
|
||||
case 'R':
|
||||
recursive = true;
|
||||
fprintf(stderr, "Sorry, recursive mode not supported "
|
||||
"yet.\n");
|
||||
return FSSH_B_BAD_VALUE;
|
||||
default:
|
||||
fprintf(stderr, "Error: Unknown option \"-%c\"\n", arg[i]);
|
||||
return FSSH_B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get mode
|
||||
fssh_mode_t permissions;
|
||||
if (argi + 1 >= argc || !get_permissions(argv[argi++], permissions)) {
|
||||
printf("Usage: %s [ -R ] <octal mode> <file>...\n", argv[0]);
|
||||
return FSSH_B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fssh_struct_stat st;
|
||||
st.fssh_st_mode = permissions;
|
||||
|
||||
// chmod loop
|
||||
for (; argi < argc; argi++) {
|
||||
const char *file = argv[argi];
|
||||
if (strlen(file) == 0) {
|
||||
fprintf(stderr, "Error: An empty path is not a valid argument!\n");
|
||||
return FSSH_B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fssh_status_t error = _kern_write_stat(-1, file, false, &st, sizeof(st),
|
||||
FSSH_FS_WRITE_STAT_MODE);
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Failed to change mode of \"%s\"!\n", file);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return FSSH_B_OK;
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
command_help(int argc, const char* const* argv)
|
||||
{
|
||||
@ -539,7 +620,6 @@ command_ls(int argc, const char* const* argv)
|
||||
"%s\n", file, fd, fssh_strerror(error));
|
||||
continue;
|
||||
}
|
||||
|
||||
} else
|
||||
list_entry(file);
|
||||
}
|
||||
@ -667,6 +747,22 @@ command_mkdir(int argc, const char* const* argv)
|
||||
}
|
||||
|
||||
|
||||
static fssh_dev_t
|
||||
get_volume_id()
|
||||
{
|
||||
struct fssh_stat st;
|
||||
fssh_status_t error = _kern_read_stat(-1, kMountPoint, false, &st,
|
||||
sizeof(st));
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Failed to stat() mount point: %s\n",
|
||||
fssh_strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
return st.fssh_st_dev;
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
command_mkindex(int argc, const char* const* argv)
|
||||
{
|
||||
@ -677,18 +773,14 @@ command_mkindex(int argc, const char* const* argv)
|
||||
|
||||
const char* indexName = argv[1];
|
||||
|
||||
// get the device ID
|
||||
struct fssh_stat st;
|
||||
fssh_status_t error = _kern_read_stat(-1, kMountPoint, false, &st,
|
||||
sizeof(st));
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Failed to stat() mount point: %s\n",
|
||||
fssh_strerror(error));
|
||||
return error;
|
||||
}
|
||||
// get the volume ID
|
||||
fssh_dev_t volumeID = get_volume_id();
|
||||
if (volumeID < 0)
|
||||
return volumeID;
|
||||
|
||||
// create the index
|
||||
error =_kern_create_index(st.fssh_st_dev, indexName, FSSH_B_STRING_TYPE, 0);
|
||||
fssh_status_t error =_kern_create_index(volumeID, indexName,
|
||||
FSSH_B_STRING_TYPE, 0);
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Failed to create index \"%s\": %s\n",
|
||||
indexName, fssh_strerror(error));
|
||||
@ -699,6 +791,61 @@ command_mkindex(int argc, const char* const* argv)
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
command_query(int argc, const char* const* argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <query string>\n", argv[0]);
|
||||
return FSSH_B_BAD_VALUE;
|
||||
}
|
||||
|
||||
const char* query = argv[1];
|
||||
|
||||
// get the volume ID
|
||||
fssh_dev_t volumeID = get_volume_id();
|
||||
if (volumeID < 0)
|
||||
return volumeID;
|
||||
|
||||
// open query
|
||||
int fd = _kern_open_query(volumeID, query, strlen(query), 0, -1, -1);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error: Failed to open query: %s\n", fssh_strerror(fd));
|
||||
return fd;
|
||||
}
|
||||
|
||||
// iterate through the entries
|
||||
fssh_status_t error = FSSH_B_OK;
|
||||
char buffer[sizeof(fssh_dirent) + FSSH_B_FILE_NAME_LENGTH];
|
||||
fssh_dirent* entry = (fssh_dirent*)buffer;
|
||||
fssh_ssize_t entriesRead = 0;
|
||||
while ((entriesRead = _kern_read_dir(fd, entry, sizeof(buffer), 1)) == 1) {
|
||||
char path[FSSH_B_PATH_NAME_LENGTH];
|
||||
error = _kern_entry_ref_to_path(volumeID, entry->d_pino, entry->d_name,
|
||||
path, sizeof(path));
|
||||
if (error == FSSH_B_OK) {
|
||||
printf(" %s\n", path);
|
||||
} else {
|
||||
fprintf(stderr, " failed to resolve entry (%8lld, \"%s\")\n",
|
||||
entry->d_pino, entry->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (entriesRead < 0) {
|
||||
fprintf(stderr, "Error: reading query failed: %s\n",
|
||||
fssh_strerror(entriesRead));
|
||||
}
|
||||
|
||||
// close query
|
||||
error = _kern_close(fd);
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Closing query (fd: %d) failed: %s\n",
|
||||
fd, fssh_strerror(error));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
command_quit(int argc, const char* const* argv)
|
||||
{
|
||||
@ -866,12 +1013,14 @@ register_commands()
|
||||
{
|
||||
CommandManager::Default()->AddCommands(
|
||||
command_cd, "cd", "change current directory",
|
||||
command_chmod, "chmod", "change file permissions",
|
||||
command_cp, "cp", "copy files and directories",
|
||||
command_help, "help", "list supported commands",
|
||||
command_ln, "ln", "create a hard or symbolic link",
|
||||
command_ls, "ls", "list files or directories",
|
||||
command_mkdir, "mkdir", "create directories",
|
||||
command_mkindex, "mkindex", "create an index",
|
||||
command_query, "query", "query for files",
|
||||
command_quit, "quit/exit", "quit the shell",
|
||||
command_rm, "rm", "remove files and directories",
|
||||
command_sync, "sync", "syncs the file system",
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define _FSSH_SYSCALLS_H
|
||||
|
||||
#include "fssh_defs.h"
|
||||
#include "fssh_os.h"
|
||||
|
||||
|
||||
struct fssh_iovec;
|
||||
@ -24,6 +25,8 @@ fssh_status_t _kern_read_fs_info(fssh_dev_t device,
|
||||
fssh_status_t _kern_write_fs_info(fssh_dev_t device,
|
||||
const struct fssh_fs_info *info, int mask);
|
||||
fssh_status_t _kern_sync(void);
|
||||
fssh_status_t _kern_entry_ref_to_path(fssh_dev_t device, fssh_ino_t inode,
|
||||
const char *leaf, char *userPath, fssh_size_t pathLength);
|
||||
fssh_dev_t _kern_next_device(int32_t *_cookie);
|
||||
int _kern_open_entry_ref(fssh_dev_t device, fssh_ino_t inode,
|
||||
const char *name, int openMode, int perms);
|
||||
@ -73,6 +76,10 @@ fssh_status_t _kern_initialize_volume(const char* fileSystem,
|
||||
const char *partition, const char *name,
|
||||
const char *parameters);
|
||||
|
||||
extern int _kern_open_query(fssh_dev_t device, const char* query,
|
||||
fssh_size_t queryLength, uint32_t flags, fssh_port_id port,
|
||||
int32_t token);
|
||||
|
||||
// defined in fd.cpp
|
||||
fssh_ssize_t _kern_read(int fd, fssh_off_t pos, void *buffer,
|
||||
fssh_size_t length);
|
||||
|
@ -2587,6 +2587,49 @@ vfs_get_vnode_name(void *_vnode, char *name, fssh_size_t nameSize)
|
||||
}
|
||||
|
||||
|
||||
fssh_status_t
|
||||
vfs_entry_ref_to_path(fssh_dev_t device, fssh_ino_t inode, const char *leaf,
|
||||
char *path, fssh_size_t pathLength)
|
||||
{
|
||||
struct vnode *vnode;
|
||||
fssh_status_t status;
|
||||
|
||||
// filter invalid leaf names
|
||||
if (leaf != NULL && (leaf[0] == '\0' || fssh_strchr(leaf, '/')))
|
||||
return FSSH_B_BAD_VALUE;
|
||||
|
||||
// get the vnode matching the dir's node_ref
|
||||
if (leaf && (fssh_strcmp(leaf, ".") == 0 || fssh_strcmp(leaf, "..") == 0)) {
|
||||
// special cases "." and "..": we can directly get the vnode of the
|
||||
// referenced directory
|
||||
status = entry_ref_to_vnode(device, inode, leaf, &vnode);
|
||||
leaf = NULL;
|
||||
} else
|
||||
status = get_vnode(device, inode, &vnode, false);
|
||||
if (status < FSSH_B_OK)
|
||||
return status;
|
||||
|
||||
// get the directory path
|
||||
status = dir_vnode_to_path(vnode, path, pathLength);
|
||||
put_vnode(vnode);
|
||||
// we don't need the vnode anymore
|
||||
if (status < FSSH_B_OK)
|
||||
return status;
|
||||
|
||||
// append the leaf name
|
||||
if (leaf) {
|
||||
// insert a directory separator if this is not the file system root
|
||||
if ((fssh_strcmp(path, "/") && fssh_strlcat(path, "/", pathLength)
|
||||
>= pathLength)
|
||||
|| fssh_strlcat(path, leaf, pathLength) >= pathLength) {
|
||||
return FSSH_B_NAME_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
return FSSH_B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** If the given descriptor locked its vnode, that lock will be released.
|
||||
*/
|
||||
|
||||
@ -4283,6 +4326,48 @@ out:
|
||||
}
|
||||
|
||||
|
||||
/*! ToDo: the query FS API is still the pretty much the same as in R5.
|
||||
It would be nice if the FS would find some more kernel support
|
||||
for them.
|
||||
For example, query parsing should be moved into the kernel.
|
||||
*/
|
||||
static int
|
||||
query_open(fssh_dev_t device, const char *query, uint32_t flags,
|
||||
fssh_port_id port, int32_t token, bool kernel)
|
||||
{
|
||||
struct fs_mount *mount;
|
||||
fssh_fs_cookie cookie;
|
||||
|
||||
FUNCTION(("query_open(device = %ld, query = \"%s\", kernel = %d)\n", device, query, kernel));
|
||||
|
||||
fssh_status_t status = get_mount(device, &mount);
|
||||
if (status < FSSH_B_OK)
|
||||
return status;
|
||||
|
||||
if (FS_MOUNT_CALL(mount, open_query) == NULL) {
|
||||
status = FSSH_EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = FS_MOUNT_CALL(mount, open_query)(mount->cookie, query, flags, port, token, &cookie);
|
||||
if (status < FSSH_B_OK)
|
||||
goto out;
|
||||
|
||||
// get fd for the index directory
|
||||
status = get_new_fd(FDTYPE_QUERY, mount, NULL, cookie, 0, kernel);
|
||||
if (status >= 0)
|
||||
goto out;
|
||||
|
||||
// something went wrong
|
||||
FS_MOUNT_CALL(mount, close_query)(mount->cookie, cookie);
|
||||
FS_MOUNT_CALL(mount, free_query_cookie)(mount->cookie, cookie);
|
||||
|
||||
out:
|
||||
put_mount(mount);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
query_close(struct file_descriptor *descriptor)
|
||||
{
|
||||
@ -5502,4 +5587,21 @@ _kern_initialize_volume(const char* fsName, const char *partition,
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
fssh_status_t
|
||||
_kern_entry_ref_to_path(fssh_dev_t device, fssh_ino_t inode, const char *leaf,
|
||||
char* path, fssh_size_t pathLength)
|
||||
{
|
||||
return vfs_entry_ref_to_path(device, inode, leaf, path, pathLength);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_kern_open_query(fssh_dev_t device, const char *query, fssh_size_t queryLength,
|
||||
uint32_t flags, fssh_port_id port, int32_t token)
|
||||
{
|
||||
return query_open(device, query, flags, port, token, false);
|
||||
}
|
||||
|
||||
|
||||
} // namespace FSShell
|
||||
|
Loading…
Reference in New Issue
Block a user