* Quieted down success output.
* Added non-interactive (external commands) support. The BeOS implementation needs some more work; well, the whole FS shell will probably have build issues on BeOS ATM. * Added reasonably complete argument processing in main(). Options are similar to the old FS shell. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20894 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,6 +11,18 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers build os support ] : true ;
|
||||
UsePrivateHeaders fs_shell ;
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
# platform specific sources
|
||||
local fsShellCommandSources ;
|
||||
local externalCommandsSources ;
|
||||
if $(HOST_PLATFORM_BEOS_COMPATIBLE) {
|
||||
fsShellCommandSources = fs_shell_command_beos.cpp ;
|
||||
externalCommandsSources = external_commands_beos.cpp ;
|
||||
} else {
|
||||
fsShellCommandSources = fs_shell_command_unix.cpp ;
|
||||
externalCommandsSources = external_commands_unix.cpp ;
|
||||
}
|
||||
|
||||
|
||||
BuildPlatformStaticLibrary <build2>fs_shell.a :
|
||||
atomic.cpp
|
||||
block_cache.cpp
|
||||
@@ -39,5 +51,11 @@ BuildPlatformStaticLibrary <build2>fs_shell.a :
|
||||
unistd.cpp
|
||||
vfs.cpp
|
||||
|
||||
$(externalCommandsSources)
|
||||
|
||||
fssh.cpp
|
||||
;
|
||||
|
||||
BuildPlatformMain <build2>fs_shell_command
|
||||
: fs_shell_command.cpp $(fsShellCommandSources)
|
||||
: $(HOST_LIBSUPC++) ;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _FSSH_EXTERNAL_COMMANDS_H
|
||||
#define _FSSH_EXTERNAL_COMMANDS_H
|
||||
|
||||
|
||||
namespace FSShell {
|
||||
|
||||
|
||||
bool get_external_command(char* input, int len);
|
||||
void reply_to_external_command(int result);
|
||||
void external_command_cleanup();
|
||||
|
||||
|
||||
} // namespace FSShell
|
||||
|
||||
|
||||
#endif // _FSSH_EXTERNAL_COMMANDS_H
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include "external_commands.h"
|
||||
#include "fs_shell_command_beos.h"
|
||||
|
||||
static port_id sReplyPort = -1;
|
||||
|
||||
static port_id
|
||||
get_command_port()
|
||||
{
|
||||
static port_id port = -1;
|
||||
static bool initialized = false;
|
||||
|
||||
if (!initialized) {
|
||||
port = create_port(10, kFSShellCommandPort);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
get_external_command(char *input, int len)
|
||||
{
|
||||
// get/create the port
|
||||
port_id port = get_command_port();
|
||||
if (port < 0) {
|
||||
fprintf(stderr, "Failed to create command port: %s\n", strerror(port));
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// read a message
|
||||
external_command_message message;
|
||||
ssize_t bytesRead;
|
||||
do {
|
||||
int32 code;
|
||||
bytesRead = read_port(port, &code, &message, sizeof(message));
|
||||
} while (bytesRead == B_INTERRUPTED);
|
||||
|
||||
if (bytesRead < 0) {
|
||||
fprintf(stderr, "Reading from port failed: %s\n",
|
||||
strerror(bytesRead));
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the len of the command
|
||||
int commandLen = (char*)&message + bytesRead - message.command;
|
||||
if (commandLen <= 1) {
|
||||
fprintf(stderr, "No command given.\n");
|
||||
continue;
|
||||
}
|
||||
if (commandLen > len) {
|
||||
fprintf(stderr, "Command too long. Ignored.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy the command
|
||||
memcpy(input, message.command, commandLen);
|
||||
input[len - 1] = '\0'; // always NULL-terminate
|
||||
sReplyPort = message.reply_port;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
reply_to_external_command(int result)
|
||||
{
|
||||
if (sReplyPort >= 0) {
|
||||
// prepare the message
|
||||
external_command_reply reply;
|
||||
reply.error = result;
|
||||
|
||||
// send the reply
|
||||
status_t error;
|
||||
do {
|
||||
error = write_port(sReplyPort, 0, &reply, sizeof(reply));
|
||||
} while (error == B_INTERRUPTED);
|
||||
sReplyPort = -1;
|
||||
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Failed to send command result to reply port: %s\n",
|
||||
strerror(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
external_command_cleanup()
|
||||
{
|
||||
// The port will be deleted automatically when the team exits.
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "external_commands.h"
|
||||
#include "fs_shell_command_unix.h"
|
||||
|
||||
|
||||
static int sClientConnection = -1;
|
||||
|
||||
|
||||
static int
|
||||
get_command_socket()
|
||||
{
|
||||
static int fd = -1;
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
// get the listener socket
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// bind it to the port
|
||||
sockaddr_un addr;
|
||||
unlink(kFSShellCommandSocketAddress);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, kFSShellCommandSocketAddress);
|
||||
int addrLen = addr.sun_path + strlen(addr.sun_path) + 1 - (char*)&addr;
|
||||
if (bind(fd, (sockaddr*)&addr, addrLen) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// start listening
|
||||
if (listen(fd, 1) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_client_connection()
|
||||
{
|
||||
if (sClientConnection >= 0)
|
||||
return sClientConnection;
|
||||
|
||||
// get the listener socket
|
||||
int commandFD = get_command_socket();
|
||||
if (commandFD < 0)
|
||||
return -1;
|
||||
|
||||
// accept a connection
|
||||
do {
|
||||
sockaddr_un addr;
|
||||
socklen_t addrLen = sizeof(addr);
|
||||
sClientConnection = accept(commandFD, (sockaddr*)&addr, &addrLen);
|
||||
} while (sClientConnection < 0 && errno == EINTR);
|
||||
|
||||
return sClientConnection;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
close_client_connection()
|
||||
{
|
||||
if (sClientConnection >= 0) {
|
||||
close(sClientConnection);
|
||||
sClientConnection = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
read_data(int fd, void* _buffer, size_t toRead)
|
||||
{
|
||||
char* buffer = (char*)_buffer;
|
||||
|
||||
ssize_t bytesRead = 0;
|
||||
while (toRead > 0 && !(bytesRead < 0 && errno != EINTR)) {
|
||||
bytesRead = read(fd, buffer, toRead);
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
if (bytesRead > 0) {
|
||||
buffer += bytesRead;
|
||||
toRead -= bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
return (toRead == 0);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FSShell::get_external_command(char *input, int len)
|
||||
{
|
||||
do {
|
||||
// get a connection
|
||||
int connection = get_client_connection();
|
||||
if (connection < 0)
|
||||
return false;
|
||||
|
||||
// read command message
|
||||
external_command_message message;
|
||||
if (!read_data(connection, &message, sizeof(message))) {
|
||||
// that usually means the connection was closed
|
||||
close_client_connection();
|
||||
continue;
|
||||
}
|
||||
|
||||
// check command length
|
||||
if (message.command_length >= (unsigned)len) {
|
||||
fprintf(stderr, "Error: Command too long!\n");
|
||||
close_client_connection();
|
||||
continue;
|
||||
}
|
||||
|
||||
// read the command
|
||||
if (!read_data(connection, input, message.command_length)) {
|
||||
fprintf(stderr, "Error: Reading from connection failed: "
|
||||
"%s\n", strerror(errno));
|
||||
close_client_connection();
|
||||
continue;
|
||||
}
|
||||
|
||||
// null-terminate
|
||||
input[message.command_length] = '\0';
|
||||
|
||||
return true;
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FSShell::reply_to_external_command(int result)
|
||||
{
|
||||
if (sClientConnection < 0)
|
||||
return;
|
||||
|
||||
// prepare the reply
|
||||
external_command_reply reply;
|
||||
reply.error = result;
|
||||
|
||||
// send the reply
|
||||
int toWrite = sizeof(reply);
|
||||
char *replyBuffer = (char*)&reply;
|
||||
ssize_t bytesWritten;
|
||||
do {
|
||||
bytesWritten = write(sClientConnection, replyBuffer, toWrite);
|
||||
if (bytesWritten > 0) {
|
||||
replyBuffer += bytesWritten;
|
||||
toWrite -= bytesWritten;
|
||||
}
|
||||
} while (toWrite > 0 && !(bytesWritten < 0 && errno != EINTR));
|
||||
|
||||
// connection may be broken: discard it
|
||||
if (bytesWritten < 0)
|
||||
close_client_connection();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FSShell::external_command_cleanup()
|
||||
{
|
||||
unlink(kFSShellCommandSocketAddress);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "fs_shell_command.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void
|
||||
add_char(char *&buffer, int &bufferSize, char c)
|
||||
{
|
||||
if (bufferSize <= 0) {
|
||||
fprintf(stderr, "Error: Command line too long\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*buffer = c;
|
||||
buffer++;
|
||||
bufferSize--;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
prepare_command_string(const char *const *argv, int argc, char *buffer,
|
||||
int bufferSize)
|
||||
{
|
||||
for (int argi = 0; argi < argc; argi++) {
|
||||
const char *arg = argv[argi];
|
||||
|
||||
if (argi > 0)
|
||||
add_char(buffer, bufferSize, ' ');
|
||||
|
||||
while (*arg) {
|
||||
if (strchr(" \\", *arg))
|
||||
add_char(buffer, bufferSize, '\\');
|
||||
add_char(buffer, bufferSize, *arg);
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
|
||||
add_char(buffer, bufferSize, '\0');
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char *const *argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Error: No command given.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// prepare the command string
|
||||
char command[102400];
|
||||
prepare_command_string(argv + 1, argc - 1, command, sizeof(command));
|
||||
|
||||
// send the command
|
||||
int result;
|
||||
if (!send_external_command(command, &result))
|
||||
exit(1);
|
||||
|
||||
// evaluate result
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "Error: Command failed: %s\n", strerror(result));
|
||||
fprintf(stderr, "Error: Command was:\n %s\n", command);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _FSSH_FS_SHELL_COMMAND_H
|
||||
#define _FSSH_FS_SHELL_COMMAND_H
|
||||
|
||||
|
||||
bool send_external_command(const char* command, int* result);
|
||||
|
||||
|
||||
#endif // _FSSH_FS_SHELL_COMMAND_H
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "fs_shell_command_beos.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include "fs_shell_command.h"
|
||||
|
||||
|
||||
bool
|
||||
send_external_command(const char *command, int *result)
|
||||
{
|
||||
external_command_message message;
|
||||
strncpy(message.command, command, sizeof(message.command));
|
||||
|
||||
// find the command port
|
||||
port_id commandPort = find_port(kFSShellCommandPort);
|
||||
if (commandPort < 0) {
|
||||
fprintf(stderr, "Error: Couldn't find fs_shell command port.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a reply port
|
||||
port_id replyPort = create_port(1, "fs shell reply port");
|
||||
if (replyPort < 0) {
|
||||
fprintf(stderr, "Error: Failed to create a reply port: %s\n",
|
||||
strerror(replyPort));
|
||||
return false;
|
||||
}
|
||||
message.reply_port = replyPort;
|
||||
|
||||
// send the command message
|
||||
status_t error;
|
||||
do {
|
||||
error = write_port(commandPort, 0, &message, sizeof(message));
|
||||
} while (error == B_INTERRUPTED);
|
||||
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to send command: %s\n", strerror(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for the reply
|
||||
external_command_reply reply;
|
||||
ssize_t bytesRead;
|
||||
do {
|
||||
int32 code;
|
||||
bytesRead = read_port(replyPort, &code, &reply, sizeof(reply));
|
||||
} while (bytesRead == B_INTERRUPTED);
|
||||
|
||||
if (bytesRead < 0) {
|
||||
fprintf(stderr, "Error: Failed to read reply from fs_shell: %s\n",
|
||||
strerror(bytesRead));
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = reply.error;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef FS_SHELL_COMMAND_BEOS_H
|
||||
#define FS_SHELL_COMMAND_BEOS_H
|
||||
|
||||
static const char *kFSShellCommandPort = "fs shell command port";
|
||||
|
||||
struct external_command_message {
|
||||
port_id reply_port;
|
||||
char command[20480];
|
||||
// TODO: Increase command size and transmit only as much as necessary.
|
||||
};
|
||||
|
||||
struct external_command_reply {
|
||||
int error;
|
||||
};
|
||||
|
||||
#endif // FS_SHELL_COMMAND_BEOS_H
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "fs_shell_command_unix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "fs_shell_command.h"
|
||||
|
||||
|
||||
static bool
|
||||
write_data(int fd, const void* _buffer, size_t toWrite)
|
||||
{
|
||||
const char* buffer = (const char*)_buffer;
|
||||
|
||||
ssize_t bytesWritten;
|
||||
do {
|
||||
bytesWritten = write(fd, buffer, toWrite);
|
||||
if (bytesWritten > 0) {
|
||||
buffer += bytesWritten;
|
||||
toWrite -= bytesWritten;
|
||||
}
|
||||
} while (toWrite > 0 && !(bytesWritten < 0 && errno != EINTR));
|
||||
|
||||
return (bytesWritten >= 0);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
send_external_command(const char *command, int *result)
|
||||
{
|
||||
external_command_message message;
|
||||
message.command_length = strlen(command);
|
||||
|
||||
// create a socket
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error: Failed to open unix socket: %s\n",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// connect to the fs_shell
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, kFSShellCommandSocketAddress);
|
||||
int addrLen = addr.sun_path + strlen(addr.sun_path) + 1 - (char*)&addr;
|
||||
if (connect(fd, (sockaddr*)&addr, addrLen) < 0) {
|
||||
fprintf(stderr, "Error: Failed to open connection to FS shell: %s\n",
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// send the command message and the command
|
||||
if (!write_data(fd, &message, sizeof(message))
|
||||
|| !write_data(fd, command, message.command_length)) {
|
||||
fprintf(stderr, "Error: Writing to fs_shell failed: %s\n",
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the reply
|
||||
external_command_reply reply;
|
||||
int toRead = sizeof(reply);
|
||||
char *replyBuffer = (char*)&reply;
|
||||
while (toRead > 0) {
|
||||
int bytesRead = read(fd, replyBuffer, toRead);
|
||||
if (bytesRead < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "Error: Failed to read reply from fs_shell: "
|
||||
"%s\n", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesRead == 0) {
|
||||
fprintf(stderr, "Error: Unexpected end of fs_shell reply. Was "
|
||||
"still expecting %d bytes\n", toRead);
|
||||
return false;
|
||||
}
|
||||
|
||||
replyBuffer += bytesRead;
|
||||
toRead -= bytesRead;
|
||||
}
|
||||
|
||||
*result = reply.error;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _FSSH_FS_SHELL_COMMAND_UNIX_H
|
||||
#define _FSSH_FS_SHELL_COMMAND_UNIX_H
|
||||
|
||||
|
||||
static const char *kFSShellCommandSocketAddress = "/tmp/fs_shell_commands";
|
||||
|
||||
struct external_command_message {
|
||||
unsigned command_length;
|
||||
};
|
||||
|
||||
struct external_command_reply {
|
||||
int error;
|
||||
};
|
||||
|
||||
|
||||
#endif // _FSSH_FS_SHELL_COMMAND_UNIX_H
|
||||
+128
-45
@@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "command_cp.h"
|
||||
#include "external_commands.h"
|
||||
#include "fd.h"
|
||||
#include "fssh_dirent.h"
|
||||
#include "fssh_errno.h"
|
||||
@@ -38,6 +39,10 @@ extern fssh_file_system_module_info gRootFileSystem;
|
||||
|
||||
const char* kMountPoint = "/myfs";
|
||||
|
||||
// command line args
|
||||
static int sArgc;
|
||||
static const char* const* sArgv;
|
||||
|
||||
|
||||
static fssh_status_t
|
||||
init_kernel()
|
||||
@@ -49,8 +54,7 @@ init_kernel()
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "module_init() failed: %s\n", fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("module_init() succeeded!\n");
|
||||
}
|
||||
|
||||
// register built-in modules, i.e. the rootfs and the client FS
|
||||
register_builtin_module(&gRootFileSystem.info);
|
||||
@@ -62,8 +66,7 @@ init_kernel()
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "initializing VFS failed: %s\n", fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("VFS initialized successfully!\n");
|
||||
}
|
||||
|
||||
// init kernel IO context
|
||||
gKernelIOContext = (io_context*)vfs_new_io_context(NULL);
|
||||
@@ -77,16 +80,14 @@ init_kernel()
|
||||
if (rootDev < 0) {
|
||||
fprintf(stderr, "mounting rootfs failed: %s\n", fssh_strerror(rootDev));
|
||||
return rootDev;
|
||||
} else
|
||||
printf("mounted rootfs successfully!\n");
|
||||
}
|
||||
|
||||
// set cwd to "/"
|
||||
error = _kern_setcwd(-1, "/");
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "setting cwd failed: %s\n", fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("set cwd successfully!\n");
|
||||
}
|
||||
|
||||
// create mount point for the client FS
|
||||
error = _kern_create_dir(-1, kMountPoint, 0775);
|
||||
@@ -94,8 +95,7 @@ init_kernel()
|
||||
fprintf(stderr, "creating mount point failed: %s\n",
|
||||
fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("mount point created successfully!\n");
|
||||
}
|
||||
|
||||
return FSSH_B_OK;
|
||||
}
|
||||
@@ -1036,15 +1036,20 @@ read_command_line(char* buffer, int bufferSize)
|
||||
|
||||
|
||||
static void
|
||||
input_loop()
|
||||
input_loop(bool interactive)
|
||||
{
|
||||
static const int kInputBufferSize = 100 * 1024;
|
||||
char* inputBuffer = new char[kInputBufferSize];
|
||||
|
||||
for (;;) {
|
||||
// read command line
|
||||
if (!read_command_line(inputBuffer, kInputBufferSize))
|
||||
break;
|
||||
if (interactive) {
|
||||
if (!read_command_line(inputBuffer, kInputBufferSize))
|
||||
break;
|
||||
} else {
|
||||
if (!get_external_command(inputBuffer, kInputBufferSize))
|
||||
break;
|
||||
}
|
||||
|
||||
// construct argv vector
|
||||
ArgVector argVector;
|
||||
@@ -1062,14 +1067,79 @@ input_loop()
|
||||
}
|
||||
|
||||
int result = command->Do(argc, argv);
|
||||
if (result == COMMAND_RESULT_EXIT)
|
||||
if (result == COMMAND_RESULT_EXIT) {
|
||||
reply_to_external_command(0);
|
||||
break;
|
||||
}
|
||||
|
||||
reply_to_external_command(fssh_to_host_error(result));
|
||||
}
|
||||
|
||||
if (!interactive)
|
||||
external_command_cleanup();
|
||||
|
||||
delete[] inputBuffer;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
standard_session(const char* device, const char* fsName, bool interactive)
|
||||
{
|
||||
// mount FS
|
||||
fssh_dev_t fsDev = _kern_mount(kMountPoint, device, fsName, 0, NULL, 0);
|
||||
if (fsDev < 0) {
|
||||
fprintf(stderr, "Error: Mounting FS failed: %s\n",
|
||||
fssh_strerror(fsDev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// register commands
|
||||
register_commands();
|
||||
|
||||
// process commands
|
||||
input_loop(interactive);
|
||||
|
||||
// unmount FS
|
||||
_kern_setcwd(-1, "/"); // avoid a "busy" vnode
|
||||
fssh_status_t error = _kern_unmount(kMountPoint, 0);
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "Error: Unmounting FS failed: %s\n",
|
||||
fssh_strerror(error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
initialization_session(const char* device, const char* fsName,
|
||||
const char* initParameters)
|
||||
{
|
||||
fprintf(stderr, "initialization not implemented yet\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_usage(bool error)
|
||||
{
|
||||
fprintf((error ? stderr : stdout),
|
||||
"Usage: %s [-n] <device>\n"
|
||||
" %s --initialize [-n] <device> [ <init parameters> ]\n",
|
||||
sArgv[0], sArgv[0]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_usage_and_exit(bool error)
|
||||
{
|
||||
print_usage(error);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace FSShell
|
||||
|
||||
|
||||
@@ -1079,16 +1149,46 @@ using namespace FSShell;
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: ...\n");
|
||||
return 1;
|
||||
sArgc = argc;
|
||||
sArgv = argv;
|
||||
|
||||
// process arguments
|
||||
bool interactive = true;
|
||||
bool initialize = false;
|
||||
const char* device = NULL;
|
||||
const char* initParameters = NULL;
|
||||
|
||||
// eat options
|
||||
int argi = 1;
|
||||
while (argi < argc && argv[argi][0] == '-') {
|
||||
const char* arg = argv[argi++];
|
||||
if (strcmp(arg, "--help") == 0) {
|
||||
print_usage_and_exit(false);
|
||||
} else if (strcmp(arg, "--initialize") == 0) {
|
||||
initialize = true;
|
||||
} else if (strcmp(arg, "-n") == 0) {
|
||||
interactive = false;
|
||||
} else {
|
||||
print_usage_and_exit(true);
|
||||
}
|
||||
}
|
||||
|
||||
const char* device = argv[1];
|
||||
// get device
|
||||
if (argi >= argc)
|
||||
print_usage_and_exit(true);
|
||||
device = argv[argi++];
|
||||
|
||||
// get init parameters
|
||||
if (initialize && argi < argc)
|
||||
initParameters = argv[argi++];
|
||||
|
||||
// if more parameters are excess
|
||||
if (argi < argc)
|
||||
print_usage_and_exit(true);
|
||||
|
||||
// get FS module
|
||||
if (!modules[0]) {
|
||||
fprintf(stderr, "Couldn't find FS module!\n");
|
||||
fprintf(stderr, "Error: Couldn't find FS module!\n");
|
||||
return 1;
|
||||
}
|
||||
const char* fsName = modules[0]->name;
|
||||
@@ -1098,34 +1198,17 @@ main(int argc, const char* const* argv)
|
||||
// init kernel
|
||||
error = init_kernel();
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "initializing kernel failed: %s\n",
|
||||
fprintf(stderr, "Error: Initializing kernel failed: %s\n",
|
||||
fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("kernel initialized successfully!\n");
|
||||
}
|
||||
|
||||
// mount FS
|
||||
fssh_dev_t fsDev = _kern_mount(kMountPoint, device, fsName, 0, NULL, 0);
|
||||
if (fsDev < 0) {
|
||||
fprintf(stderr, "mounting FS failed: %s\n", fssh_strerror(fsDev));
|
||||
return 1;
|
||||
} else
|
||||
printf("mounted FS successfully!\n");
|
||||
// start the action
|
||||
int result;
|
||||
if (initialize)
|
||||
result = initialization_session(device, fsName, initParameters);
|
||||
else
|
||||
result = standard_session(device, fsName, interactive);
|
||||
|
||||
// register commands
|
||||
register_commands();
|
||||
|
||||
// process commands
|
||||
input_loop();
|
||||
|
||||
// unmount FS
|
||||
_kern_setcwd(-1, "/"); // avoid a "busy" vnode
|
||||
error = _kern_unmount(kMountPoint, 0);
|
||||
if (error != FSSH_B_OK) {
|
||||
fprintf(stderr, "unmounting FS failed: %s\n", fssh_strerror(error));
|
||||
return error;
|
||||
} else
|
||||
printf("FS unmounted successfully!\n");
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user