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:
Ingo Weinhold 2008-03-09 17:41:42 +00:00
parent 0006905bfb
commit 45eb999ec8
3 changed files with 270 additions and 12 deletions

View File

@ -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. * 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 static fssh_status_t
command_help(int argc, const char* const* argv) 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)); "%s\n", file, fd, fssh_strerror(error));
continue; continue;
} }
} else } else
list_entry(file); 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 static fssh_status_t
command_mkindex(int argc, const char* const* argv) 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]; const char* indexName = argv[1];
// get the device ID // get the volume ID
struct fssh_stat st; fssh_dev_t volumeID = get_volume_id();
fssh_status_t error = _kern_read_stat(-1, kMountPoint, false, &st, if (volumeID < 0)
sizeof(st)); return volumeID;
if (error != FSSH_B_OK) {
fprintf(stderr, "Error: Failed to stat() mount point: %s\n",
fssh_strerror(error));
return error;
}
// create the index // 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) { if (error != FSSH_B_OK) {
fprintf(stderr, "Error: Failed to create index \"%s\": %s\n", fprintf(stderr, "Error: Failed to create index \"%s\": %s\n",
indexName, fssh_strerror(error)); 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 static fssh_status_t
command_quit(int argc, const char* const* argv) command_quit(int argc, const char* const* argv)
{ {
@ -866,12 +1013,14 @@ register_commands()
{ {
CommandManager::Default()->AddCommands( CommandManager::Default()->AddCommands(
command_cd, "cd", "change current directory", command_cd, "cd", "change current directory",
command_chmod, "chmod", "change file permissions",
command_cp, "cp", "copy files and directories", command_cp, "cp", "copy files and directories",
command_help, "help", "list supported commands", command_help, "help", "list supported commands",
command_ln, "ln", "create a hard or symbolic link", command_ln, "ln", "create a hard or symbolic link",
command_ls, "ls", "list files or directories", command_ls, "ls", "list files or directories",
command_mkdir, "mkdir", "create directories", command_mkdir, "mkdir", "create directories",
command_mkindex, "mkindex", "create an index", command_mkindex, "mkindex", "create an index",
command_query, "query", "query for files",
command_quit, "quit/exit", "quit the shell", command_quit, "quit/exit", "quit the shell",
command_rm, "rm", "remove files and directories", command_rm, "rm", "remove files and directories",
command_sync, "sync", "syncs the file system", command_sync, "sync", "syncs the file system",

View File

@ -6,6 +6,7 @@
#define _FSSH_SYSCALLS_H #define _FSSH_SYSCALLS_H
#include "fssh_defs.h" #include "fssh_defs.h"
#include "fssh_os.h"
struct fssh_iovec; 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, fssh_status_t _kern_write_fs_info(fssh_dev_t device,
const struct fssh_fs_info *info, int mask); const struct fssh_fs_info *info, int mask);
fssh_status_t _kern_sync(void); 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); fssh_dev_t _kern_next_device(int32_t *_cookie);
int _kern_open_entry_ref(fssh_dev_t device, fssh_ino_t inode, int _kern_open_entry_ref(fssh_dev_t device, fssh_ino_t inode,
const char *name, int openMode, int perms); 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 *partition, const char *name,
const char *parameters); 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 // defined in fd.cpp
fssh_ssize_t _kern_read(int fd, fssh_off_t pos, void *buffer, fssh_ssize_t _kern_read(int fd, fssh_off_t pos, void *buffer,
fssh_size_t length); fssh_size_t length);

View File

@ -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. /** 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 static fssh_status_t
query_close(struct file_descriptor *descriptor) query_close(struct file_descriptor *descriptor)
{ {
@ -5502,4 +5587,21 @@ _kern_initialize_volume(const char* fsName, const char *partition,
return status; 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 } // namespace FSShell