#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Application.h>
#include <Message.h>
#include "NetFSServerRoster.h"
#include "Permissions.h"
static const uint32 kMountPermission = MOUNT_SHARE_PERMISSION;
static const uint32 kQueryPermission = QUERY_SHARE_PERMISSION;
static const uint32 kReadPermission
= READ_PERMISSION | READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION;
static const uint32 kWritePermission
= WRITE_PERMISSION | WRITE_DIR_PERMISSION;
static const char* kUsage =
"Usage: netfs_server_prefs -h | --help\n"
" netfs_server_prefs <command>\n"
"options:\n"
" -h, --help - print this text\n"
"\n"
"commands:\n"
" launch\n"
" launches the server\n"
" terminate\n"
" terminates the server\n"
" save\n"
" saves the server settings\n"
" l, list\n"
" list all users and all shares\n"
" add share <name> <path>\n"
" add a new share with the name <name> and path <path>\n"
" remove share <name>\n"
" remove the share named <name>\n"
" add user <name> [ <password> ]\n"
" add a new user with the name <name> and, if supplied, \n"
" password <password>\n"
" remove user <name>\n"
" remove the user named <name>\n"
" permissions <user> <share> [ m ] [ r ] [ w ] [ q ]\n"
" set the permissions of user <user> for share <share> to m(ount),\n"
" r(ead), w(rite), and/or q(uery).\n"
;
static
void
print_usage(bool error)
{
fputs(kUsage, (error ? stderr : stdout));
}
static
void
print_usage_and_exit(bool error)
{
print_usage(error);
exit(error ? 1 : 0);
}
static
void
get_permissions_string(uint32 permissions, char* str)
{
str[0] = (permissions & kMountPermission ? 'm' : '-');
str[1] = (permissions & kReadPermission ? 'r' : '-');
str[2] = (permissions & kWritePermission ? 'w' : '-');
str[3] = (permissions & kQueryPermission ? 'q' : '-');
str[4] = '\0';
}
static
bool
get_permissions(const char* str, uint32* permissions)
{
*permissions = 0;
if (!str)
return true;
while (*str) {
switch (*str) {
case 'm':
*permissions |= kMountPermission;
break;
case 'r':
*permissions |= kReadPermission;
break;
case 'w':
*permissions |= kWritePermission;
break;
case 'q':
*permissions |= kQueryPermission;
break;
default:
return false;
}
str++;
}
return true;
}
static
void
assert_server_running()
{
NetFSServerRoster roster;
if (!roster.IsServerRunning()) {
fprintf(stderr, "Server is not running.\n");
exit(1);
}
}
static
void
list()
{
assert_server_running();
NetFSServerRoster roster;
BMessage users;
status_t error = roster.GetUsers(&users);
if (error == B_OK) {
printf("users\n");
printf("-----\n");
const char* user;
for (int32 i = 0; users.FindString("users", i, &user) == B_OK; i++)
printf("%s\n", user);
printf("\n");
} else
fprintf(stderr, "Failed to get users: %s\n", strerror(error));
BMessage shares;
error = roster.GetShares(&shares);
if (error == B_OK) {
printf("shares\n");
printf("------\n");
const char* share;
for (int32 i = 0; shares.FindString("shares", i, &share) == B_OK; i++) {
const char* path;
if (shares.FindString("paths", i, &path) != B_OK)
path = "<invalid path>\n";
BMessage shareUsers;
roster.GetShareUsers(share, &shareUsers);
BMessage statistics;
roster.GetShareStatistics(share, &statistics);
printf("%s:\n", share);
printf(" path: %s\n", path);
printf(" mountable by: ");
const char* user;
for (int32 k = 0;
shareUsers.FindString("users", k, &user) == B_OK;
k++) {
if (k > 0)
printf(", ");
printf("%s", user);
uint32 permissions = 0;
roster.GetUserPermissions(share, user, &permissions);
char permissionsString[8];
get_permissions_string(permissions, permissionsString);
printf(" (%s)", permissionsString);
}
printf("\n");
printf(" mounted by: ");
for (int32 k = 0;
statistics.FindString("mounted by", k, &user) == B_OK;
k++) {
if (k > 0)
printf(", ");
printf("%s", user);
}
printf("\n");
printf("\n");
}
} else
fprintf(stderr, "Failed to get users: %s\n", strerror(error));
}
static
void
add_share(const char* name, const char* path)
{
assert_server_running();
NetFSServerRoster roster;
BMessage statistics;
if (roster.GetShareStatistics(name, &statistics) == B_OK) {
fprintf(stderr, "A share `%s' does already exist.\n", name);
exit(1);
}
status_t error = roster.AddShare(name, path);
if (error != B_OK) {
fprintf(stderr, "Failed to add share: %s\n", strerror(error));
exit(1);
}
}
static
void
remove_share(const char* name)
{
assert_server_running();
NetFSServerRoster roster;
BMessage statistics;
if (roster.GetShareStatistics(name, &statistics) != B_OK) {
fprintf(stderr, "A share `%s' does not exist.\n", name);
exit(1);
}
status_t error = roster.RemoveShare(name);
if (error != B_OK) {
fprintf(stderr, "Failed to remove share: %s\n", strerror(error));
exit(1);
}
}
static
void
add_user(const char* name, const char* password)
{
assert_server_running();
NetFSServerRoster roster;
BMessage statistics;
if (roster.GetUserStatistics(name, &statistics) == B_OK) {
fprintf(stderr, "A user `%s' does already exist.\n", name);
exit(1);
}
status_t error = roster.AddUser(name, password);
if (error != B_OK) {
fprintf(stderr, "Failed to add user: %s\n", strerror(error));
exit(1);
}
}
static
void
remove_user(const char* name)
{
assert_server_running();
NetFSServerRoster roster;
BMessage statistics;
if (roster.GetUserStatistics(name, &statistics) != B_OK) {
fprintf(stderr, "A user `%s' does not exist.\n", name);
exit(1);
}
status_t error = roster.RemoveUser(name);
if (error != B_OK) {
fprintf(stderr, "Failed to remove user: %s\n", strerror(error));
exit(1);
}
}
static
void
set_user_permissions(const char* user, const char* share, uint32 permissions)
{
assert_server_running();
NetFSServerRoster roster;
BMessage statistics;
if (roster.GetUserStatistics(user, &statistics) != B_OK) {
fprintf(stderr, "A user `%s' does not exist.\n", user);
exit(1);
}
if (roster.GetShareStatistics(share, &statistics) != B_OK) {
fprintf(stderr, "A share `%s' does not exist.\n", share);
exit(1);
}
status_t error = roster.SetUserPermissions(share, user, permissions);
if (error != B_OK) {
fprintf(stderr, "Failed to set permissions: %s\n", strerror(error));
exit(1);
}
}
static
void
launch_server()
{
NetFSServerRoster roster;
if (roster.IsServerRunning()) {
fprintf(stderr, "Server is already running.\n");
exit(1);
}
status_t error = roster.LaunchServer();
if (error != B_OK) {
fprintf(stderr, "Failed to launch server: %s\n", strerror(error));
exit(1);
}
}
static
void
terminate_server()
{
assert_server_running();
NetFSServerRoster roster;
status_t error = roster.TerminateServer();
if (error != B_OK) {
fprintf(stderr, "Failed to terminate server: %s\n", strerror(error));
exit(1);
}
}
static
void
save_server_setttings()
{
assert_server_running();
NetFSServerRoster roster;
status_t error = roster.SaveServerSettings();
if (error != B_OK) {
fprintf(stderr, "Failed to save settings: %s\n", strerror(error));
exit(1);
}
}
static
const char*
next_arg(int argc, char** argv, int& argi, bool dontFail = false)
{
if (argi >= argc) {
if (dontFail)
return NULL;
print_usage_and_exit(true);
}
return argv[argi++];
}
static
void
no_more_args(int argc, int argi)
{
if (argi < argc)
print_usage_and_exit(true);
}
int
main(int argc, char** argv)
{
BApplication app("application/x-vnd.haiku-netfs_server_prefs");
int argi = 1;
const char* arg = next_arg(argc, argv, argi);
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
print_usage_and_exit(false);
if (strcmp(arg, "launch") == 0) {
no_more_args(argc, argi);
launch_server();
} else if (strcmp(arg, "terminate") == 0) {
no_more_args(argc, argi);
terminate_server();
} else if (strcmp(arg, "save") == 0) {
no_more_args(argc, argi);
save_server_setttings();
} else if (strcmp(arg, "l") == 0 || strcmp(arg, "list") == 0) {
no_more_args(argc, argi);
list();
} else if (strcmp(arg, "add") == 0) {
arg = next_arg(argc, argv, argi);
if (strcmp(arg, "share") == 0) {
const char* name = next_arg(argc, argv, argi);
const char* path = next_arg(argc, argv, argi);
no_more_args(argc, argi);
add_share(name, path);
} else if (strcmp(arg, "user") == 0) {
const char* name = next_arg(argc, argv, argi);
const char* password = next_arg(argc, argv, argi, true);
no_more_args(argc, argi);
add_user(name, password);
} else
print_usage_and_exit(true);
} else if (strcmp(arg, "remove") == 0) {
arg = next_arg(argc, argv, argi);
if (strcmp(arg, "share") == 0) {
const char* name = next_arg(argc, argv, argi);
no_more_args(argc, argi);
remove_share(name);
} else if (strcmp(arg, "user") == 0) {
const char* name = next_arg(argc, argv, argi);
no_more_args(argc, argi);
remove_user(name);
} else
print_usage_and_exit(true);
} else if (strcmp(arg, "permissions") == 0) {
const char* user = next_arg(argc, argv, argi);
const char* share = next_arg(argc, argv, argi);
uint32 permissions = 0;
while (argi < argc) {
uint32 perms = 0;
arg = next_arg(argc, argv, argi);
if (!get_permissions(arg, &perms))
print_usage_and_exit(true);
permissions |= perms;
}
set_user_permissions(user, share, permissions);
} else {
print_usage_and_exit(true);
}
return 0;
}