* Unmounting a volume now actually works, this fixes bug #3671.

* Added -u as an alias for -unmount. Added -readonly as an alias for -ro.
* Made the volume/fs column width depending on the terminal size.
* Now lists the volumes (-l) when invoked without any arguments instead of
  showing the help text.
* Improved output of not mounted volumes.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30972 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-06-05 09:49:43 +00:00
parent bc84e16481
commit 4a8250546b
+87 -64
View File
@@ -1,15 +1,22 @@
/* /*
* Copyright 2005-2007, Ingo Weinhold, [email protected]. All rights reserved. * Copyright 2005-2007, Ingo Weinhold, [email protected]. All rights reserved.
* Copyright 2005-2009, Axel Dörfler, [email protected].
*
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <set>
#include <string>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <termios.h>
#include <set> #include <Path.h>
#include <string> #include <String.h>
#include <fs_volume.h>
#include <DiskDevice.h> #include <DiskDevice.h>
#include <DiskDevicePrivate.h> #include <DiskDevicePrivate.h>
@@ -18,20 +25,17 @@
#include <DiskDeviceList.h> #include <DiskDeviceList.h>
#include <Partition.h> #include <Partition.h>
#include <Path.h>
#include <fs_volume.h>
using std::set; using std::set;
using std::string; using std::string;
extern const char *__progname; extern const char* __progname;
typedef set<string> StringSet; typedef set<string> StringSet;
// usage // usage
static const char *kUsage = static const char* kUsage =
"%s <options> [ <volume name> ... ]\n" "Usage: %s <options> [ <volume name> ... ]\n\n"
"Mounts the volume with name <volume name>, if given. Lists info about\n" "Mounts the volume with name <volume name>, if given. Lists info about\n"
"mounted and mountable volumes and mounts/unmounts volumes.\n" "mounted and mountable volumes and mounts/unmounts volumes.\n"
"\n" "\n"
@@ -40,51 +44,53 @@ static const char *kUsage =
"\n" "\n"
"Options:\n" "Options:\n"
"[general]\n" "[general]\n"
" -s - silent; don't print info about (un)mounting\n" " -s - silent; don't print info about (un)mounting\n"
" -h, --help - print this info text\n" " -h, --help - print this info text\n"
"\n" "\n"
"[mounting]\n" "[mounting]\n"
" -all - mount all mountable volumes\n" " -all - mount all mountable volumes\n"
" -allbfs - mount all mountable BFS volumes\n" " -allbfs - mount all mountable BFS volumes\n"
" -allhfs - mount all mountable HFS volumes\n" " -allhfs - mount all mountable HFS volumes\n"
" -alldos - mount all mountable DOS volumes\n" " -alldos - mount all mountable DOS volumes\n"
" -ro - mount volumes read-only\n" " -ro, -readonly - mount volumes read-only\n"
" -unmount <volume> - unmount the volume with the name <volume>\n" " -u, -unmount <volume> - unmount the volume with the name <volume>\n"
"\n" "\n"
"[info]\n" "[info]\n"
" -p, -l - list all mounted and mountable volumes\n" " -p, -l - list all mounted and mountable volumes\n"
" -lh - list all existing volumes (incl. not-mountable ones)\n" " -lh - list all existing volumes (incl. not-mountable "
" -dd - list all disk existing devices\n" "ones)\n"
" -dd - list all disk existing devices\n"
"\n" "\n"
"[obsolete]\n" "[obsolete]\n"
" -r - ignored\n" " -r - ignored\n"
" -publishall - ignored\n" " -publishall - ignored\n"
" -publishbfs - ignored\n" " -publishbfs - ignored\n"
" -publishhfs - ignored\n" " -publishhfs - ignored\n"
" -publishdos - ignored\n"; " -publishdos - ignored\n";
// application name
const char *kAppName = __progname;
// print_usage const char* kAppName = __progname;
static
void static int sVolumeNameWidth = B_OS_NAME_LENGTH;
static int sFSNameWidth = 25;
static void
print_usage(bool error) print_usage(bool error)
{ {
fprintf(error ? stderr : stdout, kUsage, kAppName); fprintf(error ? stderr : stdout, kUsage, kAppName);
} }
// print_usage_and_exit
static static void
void
print_usage_and_exit(bool error) print_usage_and_exit(bool error)
{ {
print_usage(error); print_usage(error);
exit(error ? 0 : 1); exit(error ? 0 : 1);
} }
static const char *
static const char*
size_string(int64 size) size_string(int64 size)
{ {
double blocks = size; double blocks = size;
@@ -93,7 +99,7 @@ size_string(int64 size)
if (size < 1024) if (size < 1024)
sprintf(string, "%Ld", size); sprintf(string, "%Ld", size);
else { else {
char *units[] = {"K", "M", "G", NULL}; char* units[] = {"K", "M", "G", NULL};
int32 i = -1; int32 i = -1;
do { do {
@@ -113,27 +119,28 @@ size_string(int64 size)
struct MountVisitor : public BDiskDeviceVisitor { struct MountVisitor : public BDiskDeviceVisitor {
MountVisitor() MountVisitor()
: silent(false), :
mountAll(false), silent(false),
mountBFS(false), mountAll(false),
mountHFS(false), mountBFS(false),
mountDOS(false), mountHFS(false),
readOnly(false) mountDOS(false),
readOnly(false)
{ {
} }
virtual bool Visit(BDiskDevice *device) virtual bool Visit(BDiskDevice* device)
{ {
return Visit(device, 0); return Visit(device, 0);
} }
virtual bool Visit(BPartition *partition, int32 level) virtual bool Visit(BPartition* partition, int32 level)
{ {
// get name and type // get name and type
const char *name = partition->ContentName(); const char* name = partition->ContentName();
if (!name) if (!name)
name = partition->Name(); name = partition->Name();
const char *type = partition->ContentType(); const char* type = partition->ContentType();
// check whether to mount // check whether to mount
bool mount = false; bool mount = false;
@@ -165,7 +172,7 @@ struct MountVisitor : public BDiskDeviceVisitor {
bool unmount = false; bool unmount = false;
if (name && toUnmount.find(name) != toUnmount.end()) { if (name && toUnmount.find(name) != toUnmount.end()) {
toUnmount.erase(name); toUnmount.erase(name);
if (!partition->IsMounted()) { if (partition->IsMounted()) {
unmount = true; unmount = true;
mount = false; mount = false;
} else if (!silent) } else if (!silent)
@@ -180,7 +187,8 @@ struct MountVisitor : public BDiskDeviceVisitor {
if (error >= B_OK) { if (error >= B_OK) {
BPath mountPoint; BPath mountPoint;
partition->GetMountPoint(&mountPoint); partition->GetMountPoint(&mountPoint);
printf("Volume `%s' mounted successfully at '%s'.\n", name, mountPoint.Path()); printf("Volume `%s' mounted successfully at '%s'.\n", name,
mountPoint.Path());
} else { } else {
fprintf(stderr, "Failed to mount volume `%s': %s\n", fprintf(stderr, "Failed to mount volume `%s': %s\n",
name, strerror(error)); name, strerror(error));
@@ -224,15 +232,15 @@ struct PrintPartitionsVisitor : public BDiskDeviceVisitor {
return listMountablePartitions || listAllPartitions; return listMountablePartitions || listAllPartitions;
} }
virtual bool Visit(BDiskDevice *device) virtual bool Visit(BDiskDevice* device)
{ {
return Visit(device, 0); return Visit(device, 0);
} }
virtual bool Visit(BPartition *partition, int32 level) virtual bool Visit(BPartition* partition, int32 level)
{ {
// get name and type // get name and type
const char *name = partition->ContentName(); const char* name = partition->ContentName();
if (name == NULL || name[0] == '\0') { if (name == NULL || name[0] == '\0') {
name = partition->Name(); name = partition->Name();
if (name == NULL || name[0] == '\0') { if (name == NULL || name[0] == '\0') {
@@ -242,7 +250,7 @@ struct PrintPartitionsVisitor : public BDiskDeviceVisitor {
name = ""; name = "";
} }
} }
const char *type = partition->ContentType(); const char* type = partition->ContentType();
if (type == NULL) if (type == NULL)
type = "<unknown>"; type = "<unknown>";
@@ -264,9 +272,10 @@ struct PrintPartitionsVisitor : public BDiskDeviceVisitor {
if (partition->IsMounted()) if (partition->IsMounted())
partition->GetMountPoint(&mountPoint); partition->GetMountPoint(&mountPoint);
printf("%-14s %-20s %8s %s (%s)\n", printf("%-*s %-*s %8s %s%s(%s)\n", sVolumeNameWidth, name,
name, type, size_string(partition->Size()), sFSNameWidth, type, size_string(partition->Size()),
partition->IsMounted() ? mountPoint.Path() : "", partition->IsMounted() ? mountPoint.Path() : "",
partition->IsMounted() ? " " : "",
path.Path() + skip); path.Path() + skip);
return false; return false;
} }
@@ -280,19 +289,19 @@ struct PrintPartitionsVisitor : public BDiskDeviceVisitor {
int int
main(int argc, char **argv) main(int argc, char** argv)
{ {
if (argc < 2)
print_usage_and_exit(true);
MountVisitor mountVisitor; MountVisitor mountVisitor;
PrintPartitionsVisitor printPartitionsVisitor; PrintPartitionsVisitor printPartitionsVisitor;
bool listAllDevices = false; bool listAllDevices = false;
if (argc < 2)
printPartitionsVisitor.listMountablePartitions = true;
// parse arguments // parse arguments
for (int argi = 1; argi < argc; argi++) { for (int argi = 1; argi < argc; argi++) {
const char *arg = argv[argi]; const char* arg = argv[argi];
if (arg[0] != '\0' && arg[0] != '-') { if (arg[0] != '\0' && arg[0] != '-') {
mountVisitor.toMount.insert(arg); mountVisitor.toMount.insert(arg);
@@ -308,9 +317,9 @@ main(int argc, char **argv)
mountVisitor.mountHFS = true; mountVisitor.mountHFS = true;
} else if (strcmp(arg, "-alldos") == 0) { } else if (strcmp(arg, "-alldos") == 0) {
mountVisitor.mountDOS = true; mountVisitor.mountDOS = true;
} else if (strcmp(arg, "-ro") == 0) { } else if (strcmp(arg, "-ro") == 0 || strcmp(arg, "-readonly") == 0) {
mountVisitor.readOnly = true; mountVisitor.readOnly = true;
} else if (strcmp(arg, "-unmount") == 0) { } else if (strcmp(arg, "-u") == 0 || strcmp(arg, "-unmount") == 0) {
argi++; argi++;
if (argi >= argc) if (argi >= argc)
print_usage_and_exit(true); print_usage_and_exit(true);
@@ -399,8 +408,8 @@ main(int argc, char **argv)
} }
for (StringSet::iterator it = mountVisitor.toUnmount.begin(); for (StringSet::iterator it = mountVisitor.toUnmount.begin();
it != mountVisitor.toUnmount.end(); it++) { it != mountVisitor.toUnmount.end(); it++) {
fprintf(stderr, "Failed to unmount volume `%s': Volume not found.\n", fprintf(stderr, "Failed to unmount volume `%s': Volume not "
(*it).c_str()); "found.\n", (*it).c_str());
} }
} }
@@ -418,9 +427,23 @@ main(int argc, char **argv)
// TODO // TODO
} }
// determine width of the terminal in order to shrink the columns if needed
if (isatty(STDOUT_FILENO)) {
winsize size;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size, sizeof(winsize)) == 0) {
if (size.ws_col < 95) {
sVolumeNameWidth -= (95 - size.ws_col) / 2;
sFSNameWidth -= (95 - size.ws_col) / 2;
}
}
}
if (printPartitionsVisitor.IsUsed()) { if (printPartitionsVisitor.IsUsed()) {
puts("Volume File System Size Mounted At (Device)"); printf("%-*s %-*s Size Mounted At (Device)\n",
puts("---------------------------------------------------------------------"); sVolumeNameWidth, "Volume", sFSNameWidth, "File System");
BString separator;
separator.SetTo('-', sVolumeNameWidth + sFSNameWidth + 35);
puts(separator.String());
if (printPartitionsVisitor.listAllPartitions) if (printPartitionsVisitor.listAllPartitions)
deviceList.VisitEachPartition(&printPartitionsVisitor); deviceList.VisitEachPartition(&printPartitionsVisitor);