* 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 fs_shell ;
|
||||||
UsePrivateHeaders shared ;
|
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 :
|
BuildPlatformStaticLibrary <build2>fs_shell.a :
|
||||||
atomic.cpp
|
atomic.cpp
|
||||||
block_cache.cpp
|
block_cache.cpp
|
||||||
@@ -39,5 +51,11 @@ BuildPlatformStaticLibrary <build2>fs_shell.a :
|
|||||||
unistd.cpp
|
unistd.cpp
|
||||||
vfs.cpp
|
vfs.cpp
|
||||||
|
|
||||||
|
$(externalCommandsSources)
|
||||||
|
|
||||||
fssh.cpp
|
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 <vector>
|
||||||
|
|
||||||
#include "command_cp.h"
|
#include "command_cp.h"
|
||||||
|
#include "external_commands.h"
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
#include "fssh_dirent.h"
|
#include "fssh_dirent.h"
|
||||||
#include "fssh_errno.h"
|
#include "fssh_errno.h"
|
||||||
@@ -38,6 +39,10 @@ extern fssh_file_system_module_info gRootFileSystem;
|
|||||||
|
|
||||||
const char* kMountPoint = "/myfs";
|
const char* kMountPoint = "/myfs";
|
||||||
|
|
||||||
|
// command line args
|
||||||
|
static int sArgc;
|
||||||
|
static const char* const* sArgv;
|
||||||
|
|
||||||
|
|
||||||
static fssh_status_t
|
static fssh_status_t
|
||||||
init_kernel()
|
init_kernel()
|
||||||
@@ -49,8 +54,7 @@ init_kernel()
|
|||||||
if (error != FSSH_B_OK) {
|
if (error != FSSH_B_OK) {
|
||||||
fprintf(stderr, "module_init() failed: %s\n", fssh_strerror(error));
|
fprintf(stderr, "module_init() failed: %s\n", fssh_strerror(error));
|
||||||
return error;
|
return error;
|
||||||
} else
|
}
|
||||||
printf("module_init() succeeded!\n");
|
|
||||||
|
|
||||||
// register built-in modules, i.e. the rootfs and the client FS
|
// register built-in modules, i.e. the rootfs and the client FS
|
||||||
register_builtin_module(&gRootFileSystem.info);
|
register_builtin_module(&gRootFileSystem.info);
|
||||||
@@ -62,8 +66,7 @@ init_kernel()
|
|||||||
if (error != FSSH_B_OK) {
|
if (error != FSSH_B_OK) {
|
||||||
fprintf(stderr, "initializing VFS failed: %s\n", fssh_strerror(error));
|
fprintf(stderr, "initializing VFS failed: %s\n", fssh_strerror(error));
|
||||||
return error;
|
return error;
|
||||||
} else
|
}
|
||||||
printf("VFS initialized successfully!\n");
|
|
||||||
|
|
||||||
// init kernel IO context
|
// init kernel IO context
|
||||||
gKernelIOContext = (io_context*)vfs_new_io_context(NULL);
|
gKernelIOContext = (io_context*)vfs_new_io_context(NULL);
|
||||||
@@ -77,16 +80,14 @@ init_kernel()
|
|||||||
if (rootDev < 0) {
|
if (rootDev < 0) {
|
||||||
fprintf(stderr, "mounting rootfs failed: %s\n", fssh_strerror(rootDev));
|
fprintf(stderr, "mounting rootfs failed: %s\n", fssh_strerror(rootDev));
|
||||||
return rootDev;
|
return rootDev;
|
||||||
} else
|
}
|
||||||
printf("mounted rootfs successfully!\n");
|
|
||||||
|
|
||||||
// set cwd to "/"
|
// set cwd to "/"
|
||||||
error = _kern_setcwd(-1, "/");
|
error = _kern_setcwd(-1, "/");
|
||||||
if (error != FSSH_B_OK) {
|
if (error != FSSH_B_OK) {
|
||||||
fprintf(stderr, "setting cwd failed: %s\n", fssh_strerror(error));
|
fprintf(stderr, "setting cwd failed: %s\n", fssh_strerror(error));
|
||||||
return error;
|
return error;
|
||||||
} else
|
}
|
||||||
printf("set cwd successfully!\n");
|
|
||||||
|
|
||||||
// create mount point for the client FS
|
// create mount point for the client FS
|
||||||
error = _kern_create_dir(-1, kMountPoint, 0775);
|
error = _kern_create_dir(-1, kMountPoint, 0775);
|
||||||
@@ -94,8 +95,7 @@ init_kernel()
|
|||||||
fprintf(stderr, "creating mount point failed: %s\n",
|
fprintf(stderr, "creating mount point failed: %s\n",
|
||||||
fssh_strerror(error));
|
fssh_strerror(error));
|
||||||
return error;
|
return error;
|
||||||
} else
|
}
|
||||||
printf("mount point created successfully!\n");
|
|
||||||
|
|
||||||
return FSSH_B_OK;
|
return FSSH_B_OK;
|
||||||
}
|
}
|
||||||
@@ -1036,15 +1036,20 @@ read_command_line(char* buffer, int bufferSize)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_loop()
|
input_loop(bool interactive)
|
||||||
{
|
{
|
||||||
static const int kInputBufferSize = 100 * 1024;
|
static const int kInputBufferSize = 100 * 1024;
|
||||||
char* inputBuffer = new char[kInputBufferSize];
|
char* inputBuffer = new char[kInputBufferSize];
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// read command line
|
// read command line
|
||||||
if (!read_command_line(inputBuffer, kInputBufferSize))
|
if (interactive) {
|
||||||
break;
|
if (!read_command_line(inputBuffer, kInputBufferSize))
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!get_external_command(inputBuffer, kInputBufferSize))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// construct argv vector
|
// construct argv vector
|
||||||
ArgVector argVector;
|
ArgVector argVector;
|
||||||
@@ -1062,14 +1067,79 @@ input_loop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int result = command->Do(argc, argv);
|
int result = command->Do(argc, argv);
|
||||||
if (result == COMMAND_RESULT_EXIT)
|
if (result == COMMAND_RESULT_EXIT) {
|
||||||
|
reply_to_external_command(0);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply_to_external_command(fssh_to_host_error(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!interactive)
|
||||||
|
external_command_cleanup();
|
||||||
|
|
||||||
delete[] inputBuffer;
|
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
|
} // namespace FSShell
|
||||||
|
|
||||||
|
|
||||||
@@ -1079,16 +1149,46 @@ using namespace FSShell;
|
|||||||
int
|
int
|
||||||
main(int argc, const char* const* argv)
|
main(int argc, const char* const* argv)
|
||||||
{
|
{
|
||||||
if (argc != 2) {
|
sArgc = argc;
|
||||||
fprintf(stderr, "Usage: ...\n");
|
sArgv = argv;
|
||||||
return 1;
|
|
||||||
|
// 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
|
// get FS module
|
||||||
if (!modules[0]) {
|
if (!modules[0]) {
|
||||||
fprintf(stderr, "Couldn't find FS module!\n");
|
fprintf(stderr, "Error: Couldn't find FS module!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const char* fsName = modules[0]->name;
|
const char* fsName = modules[0]->name;
|
||||||
@@ -1098,34 +1198,17 @@ main(int argc, const char* const* argv)
|
|||||||
// init kernel
|
// init kernel
|
||||||
error = init_kernel();
|
error = init_kernel();
|
||||||
if (error != FSSH_B_OK) {
|
if (error != FSSH_B_OK) {
|
||||||
fprintf(stderr, "initializing kernel failed: %s\n",
|
fprintf(stderr, "Error: Initializing kernel failed: %s\n",
|
||||||
fssh_strerror(error));
|
fssh_strerror(error));
|
||||||
return error;
|
return error;
|
||||||
} else
|
}
|
||||||
printf("kernel initialized successfully!\n");
|
|
||||||
|
|
||||||
// mount FS
|
// start the action
|
||||||
fssh_dev_t fsDev = _kern_mount(kMountPoint, device, fsName, 0, NULL, 0);
|
int result;
|
||||||
if (fsDev < 0) {
|
if (initialize)
|
||||||
fprintf(stderr, "mounting FS failed: %s\n", fssh_strerror(fsDev));
|
result = initialization_session(device, fsName, initParameters);
|
||||||
return 1;
|
else
|
||||||
} else
|
result = standard_session(device, fsName, interactive);
|
||||||
printf("mounted FS successfully!\n");
|
|
||||||
|
|
||||||
// register commands
|
return result;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user