[haiku-development] mkfs utility for haiku

  • From: Marco Minutoli <mminutoli@xxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Mon, 5 May 2008 22:40:18 +0200

Hello.

This is a new CL file system initialization utility for haiku. It use
the new device interface.

This is only a first version and I will be happy to improve it with
your feedback.

Actually It initializes only BFS Volume but as soon as other
initialization routines are written I will do the necessary changes.

The syntax is quite simple:
$ mkfs -t bfs [-v] -o <FsOptions> <DeviceName> <VolumeName>

Cheers,
Marco
diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage
index 7b0ad68..c4c8889 100644
--- a/build/jam/HaikuImage
+++ b/build/jam/HaikuImage
@@ -35,7 +35,7 @@ BEOS_BIN = "[" addattr alert arp base64 basename bc beep 
bootman bzip2 cal cat
        ideinfo idestatus ifconfig <bin>install installsound iroster isvolume 
join
        keymap kill less lessecho lesskey link listarea listattr listdev 
listimage
        listport listres listsem ln locate logger login logname ls lsindex m4 
make
-       makebootable md5sum merge mimeset mkdos mkdir mkfifo mkindex modifiers 
mount
+       makebootable md5sum merge mimeset mkdos mkdir mkfifo mkfs mkindex 
modifiers mount
        mount_nfs mountvolume mv nc netstat nl nohup od open passwd paste patch
        pathchk pc ping play playfile playsound playwav pr prio printenv printf 
ps
        ptx pwd query quit readlink release renice rescan rlog rm rmattr rmindex
diff --git a/src/bin/Jamfile b/src/bin/Jamfile
index 208ff4e..ccbe218 100644
--- a/src/bin/Jamfile
+++ b/src/bin/Jamfile
@@ -181,6 +181,7 @@ SubInclude HAIKU_TOP src bin make ;
 SubInclude HAIKU_TOP src bin makebootable ;
 #SubInclude HAIKU_TOP src bin makeudfimage ;
 SubInclude HAIKU_TOP src bin mkdos ;
+SubInclude HAIKU_TOP src bin mkfs ;
 SubInclude HAIKU_TOP src bin multiuser ;
 SubInclude HAIKU_TOP src bin patch ;
 SubInclude HAIKU_TOP src bin pc ;
diff --git a/src/bin/mkfs/FsCreator.cpp b/src/bin/mkfs/FsCreator.cpp
new file mode 100644
index 0000000..6115611
--- /dev/null
+++ b/src/bin/mkfs/FsCreator.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2008 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Marco Minutoli, mminutoli@xxxxxxxxx
+ */
+
+#include "FsCreator.h"
+
+#include <iostream>
+
+#include <DiskSystem.h>
+
+
+FsCreator::FsCreator(const char* devPath, BString& type,
+       BString& volumeName, const char* fsOpt, bool verbose)
+       :fVolumeName(volumeName),fFsOptions(fsOpt), fVerbose(verbose)
+{
+       BDiskDeviceRoster roster;
+
+       if (type == "bfs" || type == "Be File System")
+               fType = "Be File System";
+
+       status_t ret = roster.GetDeviceForPath(devPath, &fDevice);
+       if (ret != B_OK) {
+               std::cerr << "Error: Failed to get disk device for path "
+                                 << devPath << ": " << strerror(ret);
+       }
+}
+
+
+bool
+FsCreator::Run()
+{
+       // check that the device is writable
+       if (fDevice.IsReadOnly()) {
+               std::cerr << "Error: Can't Inizialize the device."
+                       "It is read only!!\n";
+               return false;
+       }
+
+       // check if the device is mounted
+       if (fDevice.IsMounted()) {
+               std::cerr << "Error: The device have to be unmounted before.\n";
+               return false;
+       }
+
+       BDiskSystem diskSystem;
+       BDiskDeviceRoster dDRoster;
+       bool found = false;
+       while (dDRoster.GetNextDiskSystem(&diskSystem) == B_OK) {
+               if (diskSystem.IsFileSystem() && 
diskSystem.SupportsInitializing()) {
+                       if (diskSystem.PrettyName() == fType) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
+       if (!found) {
+               std::cerr << "Error: Invalid file system type.\n";
+               return false;
+       }
+
+       // prepare the device for modifications
+       status_t ret = fDevice.PrepareModifications();
+       if (ret != B_OK) {
+               std::cerr << "Error: A problem occurred preparing the device 
for the"
+                       "modifications\n";
+               return false;
+       }
+       if (fVerbose)
+               std::cout << "Preparing for modifications...\n\n";
+
+       // validate parameters
+       BString name(fVolumeName);
+       if (fDevice.ValidateInitialize(fType.String(),
+                       &fVolumeName, fFsOptions) != B_OK) {
+               std::cerr << "Error: Parameters validation failed. "
+                       "Check what you wrote\n";
+               std::cerr << ret;
+               return false;
+       }
+       if (fVerbose)
+               std::cout << "Parameters Validation...\n\n";
+       if (name != fVolumeName)
+               std::cout << "Volume name was adjusted to "
+                                 << fVolumeName.String() << std::endl;
+
+       // Initialize the partition
+       ret = fDevice.Initialize(fType.String(), fVolumeName.String(), 
fFsOptions);
+       if (ret != B_OK) {
+               std::cerr << "Initialization failed: " <<  strerror(ret) << 
std::endl;
+               return false;
+       }
+
+       std::cout << "\nAre you sure you want to do this now?"
+               "\nAll YOUR DATA in this partition will be lost forever\n";
+       BString reply="";
+       do {
+               std::cout << "Continue? [yes|no]: ";
+               reply = _ReadLine();
+       } while (reply != "yes" && reply != "no");
+
+       if (reply == "yes") {
+               ret = fDevice.CommitModifications();
+               if (ret == B_OK) {
+                       if (fVerbose) {
+                               std::cout << "Volume " << fDevice.ContentName()
+                                                 << " has been initialized 
successfully!\n";
+                       }
+               } else {
+                       std::cout << "Error: Initialization of " << 
fDevice.ContentName()
+                                         << " failed !!\n";
+                       return false;
+               }
+       }
+       return true;
+}
+
+
+inline BString
+FsCreator::_ReadLine() {
+       char line[255];
+
+       cin.getline(line, sizeof(line), '\n');
+
+       return line;
+}
diff --git a/src/bin/mkfs/FsCreator.h b/src/bin/mkfs/FsCreator.h
new file mode 100644
index 0000000..f1e281f
--- /dev/null
+++ b/src/bin/mkfs/FsCreator.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Marco Minutoli, mminutoli@xxxxxxxxx
+ */
+#ifndef _FSCREATOR_H_
+#define _FSCREATOR_H_
+
+#include <String.h>
+
+#include <DiskDevice.h>
+#include <DiskDeviceRoster.h>
+
+class FsCreator {
+public:
+       FsCreator(const char* devPath, BString& type, BString& volumeName,
+               const char* fsOpt, bool verbose);
+
+       bool Run();
+private:
+       inline BString _ReadLine();
+
+       BString fType;
+       BString& fVolumeName;
+       const char* fFsOptions;
+       BDiskDevice fDevice;
+       BPartition* fPartition;
+       const bool fVerbose;
+};
+
+#endif // _FSCREATOR_H_
diff --git a/src/bin/mkfs/Jamfile b/src/bin/mkfs/Jamfile
new file mode 100644
index 0000000..112c398
--- /dev/null
+++ b/src/bin/mkfs/Jamfile
@@ -0,0 +1,9 @@
+SubDir HAIKU_TOP src bin mkfs ;
+
+UsePrivateHeaders shared ;
+UsePrivateHeaders storage ;
+
+BinCommand mkfs :
+          main.cpp
+          FsCreator.cpp
+          : be libstdc++ ;
diff --git a/src/bin/mkfs/main.cpp b/src/bin/mkfs/main.cpp
new file mode 100644
index 0000000..f0b4c45
--- /dev/null
+++ b/src/bin/mkfs/main.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2004-2008 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Marco Minutoli, mminutoli@xxxxxxxxx
+ */
+
+#include <stdio.h>
+#include <iostream>
+#include <stdlib.h>
+#include <String.h>
+#include <getopt.h>
+#include "FsCreator.h"
+
+extern "C" const char* __progname;
+static const char* kProgramName = __progname;
+
+static const char* kUsage = 
+"Usage: %s -t <fs> <options> <device> <volume name>\n"
+"\n"
+"Options:\n"
+"  -t, --type       <fs>   - set type of filesystem to create\n\n"
+"  -h, --help              - print this help text\n"
+"  -o, --options    <opt>  - set fs specific options\n"
+"  -v, --verbose           - set verbose output\n"
+;
+
+
+/*
+ * Print program help on the right stream
+ */
+inline void
+print_help(bool out)
+{
+       fprintf(out ? stdout : stderr, kUsage, kProgramName, kProgramName);
+}
+
+
+/*
+ * Print program help and exit
+ */
+inline void
+print_help_exit(bool out)
+{
+       print_help(out);
+       exit(out ? 0 : 1);
+}
+
+
+int
+main(int argc, char* const* argv)
+{
+       const struct option longOptions[] = {
+               { "help", 0, NULL, 'h' },
+               { "options", 0, NULL, 'o' },
+               { "type", 1, NULL, 't' },
+               { "verbose", 0, NULL, 'v' },
+               { NULL, 0, NULL, 0 }
+       };
+       const char *shortOptions = "t:o:hv";
+
+       // parse argument list
+       int32 nextOption;
+       BString fsType;
+       BString fsOptions;
+       bool verbose = false;
+
+       nextOption = getopt_long(argc, argv, shortOptions, longOptions, NULL);
+       if (nextOption == 't')
+               fsType = optarg;
+       else
+               print_help_exit(nextOption == 'h' ? true : false);
+
+       do {
+               nextOption = getopt_long(argc, argv, shortOptions, longOptions, 
NULL);
+
+               switch (nextOption) {
+                       case 't':       // -t or --type again?
+                               print_help_exit(false);
+                               break;
+                       case 'h':       // -h or --help
+                               print_help_exit(true);
+                               break;
+                       case 'v':       // -v or --verbose
+                               verbose = true;
+                               break;
+                       case 'o':       // -o or --options
+                               fsOptions << optarg;
+                               break;
+                       case '?':       // invalid option
+                               break;
+                       case -1:        // done with options
+                               break;
+                       default:        // everything else
+                               print_help(false);
+                               abort();
+               }
+       } while (nextOption != -1);
+
+       // the device name should be the first non-option element
+       // right before the VolumeName
+       if (optind != argc - 2)
+               print_help_exit(false);
+       const char* devPath = argv[optind];
+       BString volName = argv[argc-1];
+
+       FsCreator* creator = new FsCreator(devPath, fsType, volName,
+               fsOptions.String(), verbose);
+       if (creator == NULL) {
+               std::cerr << "Error: FsCreator can't be allocated\n";
+               abort();
+       }
+
+       return creator->Run();
+}

Other related posts: