summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2017-05-05 11:28:51 +0200
committerLudovic Pouzenc <ludovic@pouzenc.fr>2017-05-05 11:28:51 +0200
commit604f3d64764270c052cfb43081ec522237bbdb75 (patch)
treeb3db80e35399412693c7a986b3021435b2914fe4
parentf7f175cb29192682f3ece9479f24a40672a3d74d (diff)
downloadeficast-604f3d64764270c052cfb43081ec522237bbdb75.tar.gz
eficast-604f3d64764270c052cfb43081ec522237bbdb75.tar.bz2
eficast-604f3d64764270c052cfb43081ec522237bbdb75.zip
Massive add for all draft stuff to keep it in sync
-rw-r--r--.gitignore51
-rw-r--r--TODO3
-rw-r--r--draft/fuse-examples/cusexmp.c294
-rw-r--r--draft/fuse-examples/fioc.c211
-rw-r--r--draft/fuse-examples/fioc.h32
-rw-r--r--draft/fuse-examples/fioclient.c122
-rw-r--r--draft/fuse-examples/fsel.c278
-rw-r--r--draft/fuse-examples/fselclient.c72
-rw-r--r--draft/fuse-examples/fusexmp.c412
-rw-r--r--draft/fuse-examples/fusexmp_fh.c567
-rw-r--r--draft/fuse-examples/hello.c96
-rw-r--r--draft/fuse-examples/hello_ll.c181
-rw-r--r--draft/fuse-examples/null.c95
-rw-r--r--draft/mcastseed/AUTHORS (renamed from mcastseed/AUTHORS)0
-rw-r--r--draft/mcastseed/COPYING (renamed from mcastseed/COPYING)0
-rw-r--r--draft/mcastseed/ChangeLog (renamed from mcastseed/ChangeLog)0
-rw-r--r--draft/mcastseed/Makefile.am (renamed from mcastseed/Makefile.am)0
-rw-r--r--draft/mcastseed/NEWS (renamed from mcastseed/NEWS)0
l---------draft/mcastseed/README (renamed from mcastseed/README)0
-rw-r--r--draft/mcastseed/README.md (renamed from mcastseed/README.md)0
-rw-r--r--draft/mcastseed/configure.ac (renamed from mcastseed/configure.ac)0
-rw-r--r--draft/mcastseed/lib/Makefile.am (renamed from mcastseed/lib/Makefile.am)0
-rw-r--r--draft/mcastseed/lib/gl_anyrbtree_list1.h (renamed from mcastseed/lib/gl_anyrbtree_list1.h)0
-rw-r--r--draft/mcastseed/lib/gl_anyrbtree_list2.h (renamed from mcastseed/lib/gl_anyrbtree_list2.h)0
-rw-r--r--draft/mcastseed/lib/gl_anytree_list1.h (renamed from mcastseed/lib/gl_anytree_list1.h)0
-rw-r--r--draft/mcastseed/lib/gl_anytree_list2.h (renamed from mcastseed/lib/gl_anytree_list2.h)0
-rw-r--r--draft/mcastseed/lib/gl_list.c (renamed from mcastseed/lib/gl_list.c)0
-rw-r--r--draft/mcastseed/lib/gl_list.h (renamed from mcastseed/lib/gl_list.h)0
-rw-r--r--draft/mcastseed/lib/gl_rbtree_list.c (renamed from mcastseed/lib/gl_rbtree_list.c)0
-rw-r--r--draft/mcastseed/lib/gl_rbtree_list.h (renamed from mcastseed/lib/gl_rbtree_list.h)0
-rw-r--r--draft/mcastseed/lib/stdbool.in.h (renamed from mcastseed/lib/stdbool.in.h)0
-rw-r--r--draft/mcastseed/m4/00gnulib.m4 (renamed from mcastseed/m4/00gnulib.m4)0
-rw-r--r--draft/mcastseed/m4/extern-inline.m4 (renamed from mcastseed/m4/extern-inline.m4)0
-rw-r--r--draft/mcastseed/m4/gnulib-cache.m4 (renamed from mcastseed/m4/gnulib-cache.m4)0
-rw-r--r--draft/mcastseed/m4/gnulib-common.m4 (renamed from mcastseed/m4/gnulib-common.m4)0
-rw-r--r--draft/mcastseed/m4/gnulib-comp.m4 (renamed from mcastseed/m4/gnulib-comp.m4)0
-rw-r--r--draft/mcastseed/m4/gnulib-tool.m4 (renamed from mcastseed/m4/gnulib-tool.m4)0
-rw-r--r--draft/mcastseed/m4/stdbool.m4 (renamed from mcastseed/m4/stdbool.m4)0
-rw-r--r--draft/mcastseed/src/Makefile.am (renamed from mcastseed/src/Makefile.am)0
-rw-r--r--draft/mcastseed/src/dgrambuf.c (renamed from mcastseed/src/dgrambuf.c)0
-rw-r--r--draft/mcastseed/src/dgrambuf.h (renamed from mcastseed/src/dgrambuf.h)0
-rw-r--r--draft/mcastseed/src/dgrambuf_test.c (renamed from mcastseed/src/dgrambuf_test.c)0
-rw-r--r--draft/mcastseed/src/mcastleech.c (renamed from mcastseed/src/mcastleech.c)0
-rw-r--r--draft/mcastseed/src/mcastseed.c (renamed from mcastseed/src/mcastseed.c)0
-rw-r--r--draft/mcastseed/src/random_speed_dd.c (renamed from mcastseed/src/random_speed_dd.c)0
-rw-r--r--draft/mcastseed/src/sockets.c (renamed from mcastseed/src/sockets.c)0
-rw-r--r--draft/mcastseed/src/sockets.h (renamed from mcastseed/src/sockets.h)0
-rw-r--r--draft/other-tools/clonezilla/drbl-ocs.conf414
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-expand-gpt-pt386
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-expand-mbr-pt369
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-restore-ebr119
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-restore-mbr131
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-sr1465
-rw-r--r--draft/other-tools/fog/fog-notes.txt148
-rwxr-xr-xdraft/other-tools/fog/fog.download261
-rwxr-xr-xdraft/other-tools/fog/fog.upload216
-rw-r--r--draft/other-tools/fog/funcs.sh2196
-rw-r--r--draft/other-tools/fog/partition-funcs.sh811
-rw-r--r--draft/other-tools/fog/procsfdisk.awk361
-rw-r--r--draft/other-tools/to-see.txt14
-rwxr-xr-xdraft/uftp-push.sh8
-rw-r--r--draft/uftp/bug-ts.txt495
-rw-r--r--draft/uftp/notes.txt42
-rwxr-xr-xdraft/uftp/sinkcat.sh39
-rwxr-xr-xdraft/uftp/sinkdo.sh57
-rw-r--r--draft/uftp/trace-lost-buf.txt485
66 files changed, 10406 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore
index e4f292e..cfbddab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,28 +1,29 @@
-downloads/
-out/
-work/
-mcastseed/src/.deps
-mcastseed/aclocal.m4
-mcastseed/autom4te.cache
-mcastseed/ar-lib
-mcastseed/compile
-mcastseed/config.guess
-mcastseed/config.h
-mcastseed/config.h.in
-mcastseed/config.log
-mcastseed/config.status
-mcastseed/config.sub
-mcastseed/configure
-mcastseed/depcomp
-mcastseed/INSTALL
-mcastseed/install-sh
-mcastseed/Makefile
-mcastseed/Makefile.in
-mcastseed/missing
-mcastseed/stamp-h1
-mcastseed/src/mcastseed
-mcastseed/src/mcastleech
-mcastseed/src/random_speed_dd
+/downloads/
+/out/
+/test/images/
+/test/ovmf/
+/work/
+/draft/mcastseed/aclocal.m4
+/draft/mcastseed/autom4te.cache
+/draft/mcastseed/ar-lib
+/draft/mcastseed/compile
+/draft/mcastseed/config.guess
+/draft/mcastseed/config.h
+/draft/mcastseed/config.h.in
+/draft/mcastseed/config.log
+/draft/mcastseed/config.status
+/draft/mcastseed/config.sub
+/draft/mcastseed/configure
+/draft/mcastseed/depcomp
+/draft/mcastseed/INSTALL
+/draft/mcastseed/install-sh
+/draft/mcastseed/Makefile
+/draft/mcastseed/Makefile.in
+/draft/mcastseed/missing
+/draft/mcastseed/stamp-h1
+/draft/mcastseed/src/mcastseed
+/draft/mcastseed/src/mcastleech
+/draft/mcastseed/src/random_speed_dd
Makefile
Makefile.in
*~
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..e664585
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+
+Désactiver la veille de l'écran en mode console (param kernel)
+
diff --git a/draft/fuse-examples/cusexmp.c b/draft/fuse-examples/cusexmp.c
new file mode 100644
index 0000000..01fcdf7
--- /dev/null
+++ b/draft/fuse-examples/cusexmp.c
@@ -0,0 +1,294 @@
+/*
+ CUSE example: Character device in Userspace
+ Copyright (C) 2008-2009 SUSE Linux Products GmbH
+ Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp
+*/
+
+#define FUSE_USE_VERSION 29
+
+#include <cuse_lowlevel.h>
+#include <fuse_opt.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "fioc.h"
+
+static void *cusexmp_buf;
+static size_t cusexmp_size;
+
+static const char *usage =
+"usage: cusexmp [options]\n"
+"\n"
+"options:\n"
+" --help|-h print this help message\n"
+" --maj=MAJ|-M MAJ device major number\n"
+" --min=MIN|-m MIN device minor number\n"
+" --name=NAME|-n NAME device name (mandatory)\n"
+"\n";
+
+static int cusexmp_resize(size_t new_size)
+{
+ void *new_buf;
+
+ if (new_size == cusexmp_size)
+ return 0;
+
+ new_buf = realloc(cusexmp_buf, new_size);
+ if (!new_buf && new_size)
+ return -ENOMEM;
+
+ if (new_size > cusexmp_size)
+ memset(new_buf + cusexmp_size, 0, new_size - cusexmp_size);
+
+ cusexmp_buf = new_buf;
+ cusexmp_size = new_size;
+
+ return 0;
+}
+
+static int cusexmp_expand(size_t new_size)
+{
+ if (new_size > cusexmp_size)
+ return cusexmp_resize(new_size);
+ return 0;
+}
+
+static void cusexmp_open(fuse_req_t req, struct fuse_file_info *fi)
+{
+ fuse_reply_open(req, fi);
+}
+
+static void cusexmp_read(fuse_req_t req, size_t size, off_t off,
+ struct fuse_file_info *fi)
+{
+ (void)fi;
+
+ if (off >= cusexmp_size)
+ off = cusexmp_size;
+ if (size > cusexmp_size - off)
+ size = cusexmp_size - off;
+
+ fuse_reply_buf(req, cusexmp_buf + off, size);
+}
+
+static void cusexmp_write(fuse_req_t req, const char *buf, size_t size,
+ off_t off, struct fuse_file_info *fi)
+{
+ (void)fi;
+
+ if (cusexmp_expand(off + size)) {
+ fuse_reply_err(req, ENOMEM);
+ return;
+ }
+
+ memcpy(cusexmp_buf + off, buf, size);
+ fuse_reply_write(req, size);
+}
+
+static void fioc_do_rw(fuse_req_t req, void *addr, const void *in_buf,
+ size_t in_bufsz, size_t out_bufsz, int is_read)
+{
+ const struct fioc_rw_arg *arg;
+ struct iovec in_iov[2], out_iov[3], iov[3];
+ size_t cur_size;
+
+ /* read in arg */
+ in_iov[0].iov_base = addr;
+ in_iov[0].iov_len = sizeof(*arg);
+ if (!in_bufsz) {
+ fuse_reply_ioctl_retry(req, in_iov, 1, NULL, 0);
+ return;
+ }
+ arg = in_buf;
+ in_buf += sizeof(*arg);
+ in_bufsz -= sizeof(*arg);
+
+ /* prepare size outputs */
+ out_iov[0].iov_base =
+ addr + (unsigned long)&(((struct fioc_rw_arg *)0)->prev_size);
+ out_iov[0].iov_len = sizeof(arg->prev_size);
+
+ out_iov[1].iov_base =
+ addr + (unsigned long)&(((struct fioc_rw_arg *)0)->new_size);
+ out_iov[1].iov_len = sizeof(arg->new_size);
+
+ /* prepare client buf */
+ if (is_read) {
+ out_iov[2].iov_base = arg->buf;
+ out_iov[2].iov_len = arg->size;
+ if (!out_bufsz) {
+ fuse_reply_ioctl_retry(req, in_iov, 1, out_iov, 3);
+ return;
+ }
+ } else {
+ in_iov[1].iov_base = arg->buf;
+ in_iov[1].iov_len = arg->size;
+ if (arg->size && !in_bufsz) {
+ fuse_reply_ioctl_retry(req, in_iov, 2, out_iov, 2);
+ return;
+ }
+ }
+
+ /* we're all set */
+ cur_size = cusexmp_size;
+ iov[0].iov_base = &cur_size;
+ iov[0].iov_len = sizeof(cur_size);
+
+ iov[1].iov_base = &cusexmp_size;
+ iov[1].iov_len = sizeof(cusexmp_size);
+
+ if (is_read) {
+ size_t off = arg->offset;
+ size_t size = arg->size;
+
+ if (off >= cusexmp_size)
+ off = cusexmp_size;
+ if (size > cusexmp_size - off)
+ size = cusexmp_size - off;
+
+ iov[2].iov_base = cusexmp_buf + off;
+ iov[2].iov_len = size;
+ fuse_reply_ioctl_iov(req, size, iov, 3);
+ } else {
+ if (cusexmp_expand(arg->offset + in_bufsz)) {
+ fuse_reply_err(req, ENOMEM);
+ return;
+ }
+
+ memcpy(cusexmp_buf + arg->offset, in_buf, in_bufsz);
+ fuse_reply_ioctl_iov(req, in_bufsz, iov, 2);
+ }
+}
+
+static void cusexmp_ioctl(fuse_req_t req, int cmd, void *arg,
+ struct fuse_file_info *fi, unsigned flags,
+ const void *in_buf, size_t in_bufsz, size_t out_bufsz)
+{
+ int is_read = 0;
+
+ (void)fi;
+
+ if (flags & FUSE_IOCTL_COMPAT) {
+ fuse_reply_err(req, ENOSYS);
+ return;
+ }
+
+ switch (cmd) {
+ case FIOC_GET_SIZE:
+ if (!out_bufsz) {
+ struct iovec iov = { arg, sizeof(size_t) };
+
+ fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
+ } else
+ fuse_reply_ioctl(req, 0, &cusexmp_size,
+ sizeof(cusexmp_size));
+ break;
+
+ case FIOC_SET_SIZE:
+ if (!in_bufsz) {
+ struct iovec iov = { arg, sizeof(size_t) };
+
+ fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
+ } else {
+ cusexmp_resize(*(size_t *)in_buf);
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case FIOC_READ:
+ is_read = 1;
+ case FIOC_WRITE:
+ fioc_do_rw(req, arg, in_buf, in_bufsz, out_bufsz, is_read);
+ break;
+
+ default:
+ fuse_reply_err(req, EINVAL);
+ }
+}
+
+struct cusexmp_param {
+ unsigned major;
+ unsigned minor;
+ char *dev_name;
+ int is_help;
+};
+
+#define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 }
+
+static const struct fuse_opt cusexmp_opts[] = {
+ CUSEXMP_OPT("-M %u", major),
+ CUSEXMP_OPT("--maj=%u", major),
+ CUSEXMP_OPT("-m %u", minor),
+ CUSEXMP_OPT("--min=%u", minor),
+ CUSEXMP_OPT("-n %s", dev_name),
+ CUSEXMP_OPT("--name=%s", dev_name),
+ FUSE_OPT_KEY("-h", 0),
+ FUSE_OPT_KEY("--help", 0),
+ FUSE_OPT_END
+};
+
+static int cusexmp_process_arg(void *data, const char *arg, int key,
+ struct fuse_args *outargs)
+{
+ struct cusexmp_param *param = data;
+
+ (void)outargs;
+ (void)arg;
+
+ switch (key) {
+ case 0:
+ param->is_help = 1;
+ fprintf(stderr, "%s", usage);
+ return fuse_opt_add_arg(outargs, "-ho");
+ default:
+ return 1;
+ }
+}
+
+static const struct cuse_lowlevel_ops cusexmp_clop = {
+ .open = cusexmp_open,
+ .read = cusexmp_read,
+ .write = cusexmp_write,
+ .ioctl = cusexmp_ioctl,
+};
+
+int main(int argc, char **argv)
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ struct cusexmp_param param = { 0, 0, NULL, 0 };
+ char dev_name[128] = "DEVNAME=";
+ const char *dev_info_argv[] = { dev_name };
+ struct cuse_info ci;
+
+ if (fuse_opt_parse(&args, &param, cusexmp_opts, cusexmp_process_arg)) {
+ printf("failed to parse option\n");
+ return 1;
+ }
+
+ if (!param.is_help) {
+ if (!param.dev_name) {
+ fprintf(stderr, "Error: device name missing\n");
+ return 1;
+ }
+ strncat(dev_name, param.dev_name, sizeof(dev_name) - 9);
+ }
+
+ memset(&ci, 0, sizeof(ci));
+ ci.dev_major = param.major;
+ ci.dev_minor = param.minor;
+ ci.dev_info_argc = 1;
+ ci.dev_info_argv = dev_info_argv;
+ ci.flags = CUSE_UNRESTRICTED_IOCTL;
+
+ return cuse_lowlevel_main(args.argc, args.argv, &ci, &cusexmp_clop,
+ NULL);
+}
diff --git a/draft/fuse-examples/fioc.c b/draft/fuse-examples/fioc.c
new file mode 100644
index 0000000..bee40b9
--- /dev/null
+++ b/draft/fuse-examples/fioc.c
@@ -0,0 +1,211 @@
+/*
+ FUSE fioc: FUSE ioctl example
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc
+*/
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+#include "fioc.h"
+
+#define FIOC_NAME "fioc"
+
+enum {
+ FIOC_NONE,
+ FIOC_ROOT,
+ FIOC_FILE,
+};
+
+static void *fioc_buf;
+static size_t fioc_size;
+
+static int fioc_resize(size_t new_size)
+{
+ void *new_buf;
+
+ if (new_size == fioc_size)
+ return 0;
+
+ new_buf = realloc(fioc_buf, new_size);
+ if (!new_buf && new_size)
+ return -ENOMEM;
+
+ if (new_size > fioc_size)
+ memset(new_buf + fioc_size, 0, new_size - fioc_size);
+
+ fioc_buf = new_buf;
+ fioc_size = new_size;
+
+ return 0;
+}
+
+static int fioc_expand(size_t new_size)
+{
+ if (new_size > fioc_size)
+ return fioc_resize(new_size);
+ return 0;
+}
+
+static int fioc_file_type(const char *path)
+{
+ if (strcmp(path, "/") == 0)
+ return FIOC_ROOT;
+ if (strcmp(path, "/" FIOC_NAME) == 0)
+ return FIOC_FILE;
+ return FIOC_NONE;
+}
+
+static int fioc_getattr(const char *path, struct stat *stbuf)
+{
+ stbuf->st_uid = getuid();
+ stbuf->st_gid = getgid();
+ stbuf->st_atime = stbuf->st_mtime = time(NULL);
+
+ switch (fioc_file_type(path)) {
+ case FIOC_ROOT:
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ break;
+ case FIOC_FILE:
+ stbuf->st_mode = S_IFREG | 0644;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = fioc_size;
+ break;
+ case FIOC_NONE:
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static int fioc_open(const char *path, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ if (fioc_file_type(path) != FIOC_NONE)
+ return 0;
+ return -ENOENT;
+}
+
+static int fioc_do_read(char *buf, size_t size, off_t offset)
+{
+ if (offset >= fioc_size)
+ return 0;
+
+ if (size > fioc_size - offset)
+ size = fioc_size - offset;
+
+ memcpy(buf, fioc_buf + offset, size);
+
+ return size;
+}
+
+static int fioc_read(const char *path, char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ if (fioc_file_type(path) != FIOC_FILE)
+ return -EINVAL;
+
+ return fioc_do_read(buf, size, offset);
+}
+
+static int fioc_do_write(const char *buf, size_t size, off_t offset)
+{
+ if (fioc_expand(offset + size))
+ return -ENOMEM;
+
+ memcpy(fioc_buf + offset, buf, size);
+
+ return size;
+}
+
+static int fioc_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ if (fioc_file_type(path) != FIOC_FILE)
+ return -EINVAL;
+
+ return fioc_do_write(buf, size, offset);
+}
+
+static int fioc_truncate(const char *path, off_t size)
+{
+ if (fioc_file_type(path) != FIOC_FILE)
+ return -EINVAL;
+
+ return fioc_resize(size);
+}
+
+static int fioc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) fi;
+ (void) offset;
+
+ if (fioc_file_type(path) != FIOC_ROOT)
+ return -ENOENT;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+ filler(buf, FIOC_NAME, NULL, 0);
+
+ return 0;
+}
+
+static int fioc_ioctl(const char *path, int cmd, void *arg,
+ struct fuse_file_info *fi, unsigned int flags, void *data)
+{
+ (void) arg;
+ (void) fi;
+ (void) flags;
+
+ if (fioc_file_type(path) != FIOC_FILE)
+ return -EINVAL;
+
+ if (flags & FUSE_IOCTL_COMPAT)
+ return -ENOSYS;
+
+ switch (cmd) {
+ case FIOC_GET_SIZE:
+ *(size_t *)data = fioc_size;
+ return 0;
+
+ case FIOC_SET_SIZE:
+ fioc_resize(*(size_t *)data);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static struct fuse_operations fioc_oper = {
+ .getattr = fioc_getattr,
+ .readdir = fioc_readdir,
+ .truncate = fioc_truncate,
+ .open = fioc_open,
+ .read = fioc_read,
+ .write = fioc_write,
+ .ioctl = fioc_ioctl,
+};
+
+int main(int argc, char *argv[])
+{
+ return fuse_main(argc, argv, &fioc_oper, NULL);
+}
diff --git a/draft/fuse-examples/fioc.h b/draft/fuse-examples/fioc.h
new file mode 100644
index 0000000..ec1a39d
--- /dev/null
+++ b/draft/fuse-examples/fioc.h
@@ -0,0 +1,32 @@
+/*
+ FUSE-ioctl: ioctl support for FUSE
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+
+enum {
+ FIOC_GET_SIZE = _IOR('E', 0, size_t),
+ FIOC_SET_SIZE = _IOW('E', 1, size_t),
+
+ /*
+ * The following two ioctls don't follow usual encoding rules
+ * and transfer variable amount of data.
+ */
+ FIOC_READ = _IO('E', 2),
+ FIOC_WRITE = _IO('E', 3),
+};
+
+struct fioc_rw_arg {
+ off_t offset;
+ void *buf;
+ size_t size;
+ size_t prev_size; /* out param for previous total size */
+ size_t new_size; /* out param for new total size */
+};
diff --git a/draft/fuse-examples/fioclient.c b/draft/fuse-examples/fioclient.c
new file mode 100644
index 0000000..5f05525
--- /dev/null
+++ b/draft/fuse-examples/fioclient.c
@@ -0,0 +1,122 @@
+/*
+ FUSE fioclient: FUSE ioctl example client
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fioclient.c -o fioclient
+*/
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include "fioc.h"
+
+const char *usage =
+"Usage: fioclient FIOC_FILE COMMAND\n"
+"\n"
+"COMMANDS\n"
+" s [SIZE] : get size if SIZE is omitted, set size otherwise\n"
+" r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
+" w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
+"\n";
+
+static int do_rw(int fd, int is_read, size_t size, off_t offset,
+ size_t *prev_size, size_t *new_size)
+{
+ struct fioc_rw_arg arg = { .offset = offset };
+ ssize_t ret;
+
+ arg.buf = calloc(1, size);
+ if (!arg.buf) {
+ fprintf(stderr, "failed to allocated %zu bytes\n", size);
+ return -1;
+ }
+
+ if (is_read) {
+ arg.size = size;
+ ret = ioctl(fd, FIOC_READ, &arg);
+ if (ret >= 0)
+ fwrite(arg.buf, 1, ret, stdout);
+ } else {
+ arg.size = fread(arg.buf, 1, size, stdin);
+ fprintf(stderr, "Writing %zu bytes\n", arg.size);
+ ret = ioctl(fd, FIOC_WRITE, &arg);
+ }
+
+ if (ret >= 0) {
+ *prev_size = arg.prev_size;
+ *new_size = arg.new_size;
+ } else
+ perror("ioctl");
+
+ free(arg.buf);
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ size_t param[2] = { };
+ size_t size, prev_size = 0, new_size = 0;
+ char cmd;
+ int fd, i, rc;
+
+ if (argc < 3)
+ goto usage;
+
+ fd = open(argv[1], O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ cmd = tolower(argv[2][0]);
+ argc -= 3;
+ argv += 3;
+
+ for (i = 0; i < argc; i++) {
+ char *endp;
+ param[i] = strtoul(argv[i], &endp, 0);
+ if (endp == argv[i] || *endp != '\0')
+ goto usage;
+ }
+
+ switch (cmd) {
+ case 's':
+ if (!argc) {
+ if (ioctl(fd, FIOC_GET_SIZE, &size)) {
+ perror("ioctl");
+ return 1;
+ }
+ printf("%zu\n", size);
+ } else {
+ size = param[0];
+ if (ioctl(fd, FIOC_SET_SIZE, &size)) {
+ perror("ioctl");
+ return 1;
+ }
+ }
+ return 0;
+
+ case 'r':
+ case 'w':
+ rc = do_rw(fd, cmd == 'r', param[0], param[1],
+ &prev_size, &new_size);
+ if (rc < 0)
+ return 1;
+ fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
+ rc, prev_size, new_size);
+ return 0;
+ }
+
+ usage:
+ fprintf(stderr, "%s", usage);
+ return 1;
+}
diff --git a/draft/fuse-examples/fsel.c b/draft/fuse-examples/fsel.c
new file mode 100644
index 0000000..9cf0221
--- /dev/null
+++ b/draft/fuse-examples/fsel.c
@@ -0,0 +1,278 @@
+/*
+ FUSE fsel: FUSE select example
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel
+*/
+
+#define FUSE_USE_VERSION 29
+
+#include <fuse.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+#include <poll.h>
+
+/*
+ * fsel_open_mask is used to limit the number of opens to 1 per file.
+ * This is to use file index (0-F) as fh as poll support requires
+ * unique fh per open file. Lifting this would require proper open
+ * file management.
+ */
+static unsigned fsel_open_mask;
+static const char fsel_hex_map[] = "0123456789ABCDEF";
+static struct fuse *fsel_fuse; /* needed for poll notification */
+
+#define FSEL_CNT_MAX 10 /* each file can store upto 10 chars */
+#define FSEL_FILES 16
+
+static pthread_mutex_t fsel_mutex; /* protects notify_mask and cnt array */
+static unsigned fsel_poll_notify_mask; /* poll notification scheduled? */
+static struct fuse_pollhandle *fsel_poll_handle[FSEL_FILES]; /* poll notify handles */
+static unsigned fsel_cnt[FSEL_FILES]; /* nbytes stored in each file */
+
+static int fsel_path_index(const char *path)
+{
+ char ch = path[1];
+
+ if (strlen(path) != 2 || path[0] != '/' || !isxdigit(ch) || islower(ch))
+ return -1;
+ return ch <= '9' ? ch - '0' : ch - 'A' + 10;
+}
+
+static int fsel_getattr(const char *path, struct stat *stbuf)
+{
+ int idx;
+
+ memset(stbuf, 0, sizeof(struct stat));
+
+ if (strcmp(path, "/") == 0) {
+ stbuf->st_mode = S_IFDIR | 0555;
+ stbuf->st_nlink = 2;
+ return 0;
+ }
+
+ idx = fsel_path_index(path);
+ if (idx < 0)
+ return -ENOENT;
+
+ stbuf->st_mode = S_IFREG | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = fsel_cnt[idx];
+ return 0;
+}
+
+static int fsel_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ char name[2] = { };
+ int i;
+
+ (void) offset;
+ (void) fi;
+
+ if (strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ for (i = 0; i < FSEL_FILES; i++) {
+ name[0] = fsel_hex_map[i];
+ filler(buf, name, NULL, 0);
+ }
+
+ return 0;
+}
+
+static int fsel_open(const char *path, struct fuse_file_info *fi)
+{
+ int idx = fsel_path_index(path);
+
+ if (idx < 0)
+ return -ENOENT;
+ if ((fi->flags & 3) != O_RDONLY)
+ return -EACCES;
+ if (fsel_open_mask & (1 << idx))
+ return -EBUSY;
+ fsel_open_mask |= (1 << idx);
+
+ /*
+ * fsel files are nonseekable somewhat pipe-like files which
+ * gets filled up periodically by producer thread and consumed
+ * on read. Tell FUSE as such.
+ */
+ fi->fh = idx;
+ fi->direct_io = 1;
+ fi->nonseekable = 1;
+
+ return 0;
+}
+
+static int fsel_release(const char *path, struct fuse_file_info *fi)
+{
+ int idx = fi->fh;
+
+ (void) path;
+
+ fsel_open_mask &= ~(1 << idx);
+ return 0;
+}
+
+static int fsel_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int idx = fi->fh;
+
+ (void) path;
+ (void) offset;
+
+ pthread_mutex_lock(&fsel_mutex);
+ if (fsel_cnt[idx] < size)
+ size = fsel_cnt[idx];
+ printf("READ %X transferred=%zu cnt=%u\n", idx, size, fsel_cnt[idx]);
+ fsel_cnt[idx] -= size;
+ pthread_mutex_unlock(&fsel_mutex);
+
+ memset(buf, fsel_hex_map[idx], size);
+ return size;
+}
+
+static int fsel_poll(const char *path, struct fuse_file_info *fi,
+ struct fuse_pollhandle *ph, unsigned *reventsp)
+{
+ static unsigned polled_zero;
+ int idx = fi->fh;
+
+ (void) path;
+
+ /*
+ * Poll notification requires pointer to struct fuse which
+ * can't be obtained when using fuse_main(). As notification
+ * happens only after poll is called, fill it here from
+ * fuse_context.
+ */
+ if (!fsel_fuse) {
+ struct fuse_context *cxt = fuse_get_context();
+ if (cxt)
+ fsel_fuse = cxt->fuse;
+ }
+
+ pthread_mutex_lock(&fsel_mutex);
+
+ if (ph != NULL) {
+ struct fuse_pollhandle *oldph = fsel_poll_handle[idx];
+
+ if (oldph)
+ fuse_pollhandle_destroy(oldph);
+
+ fsel_poll_notify_mask |= (1 << idx);
+ fsel_poll_handle[idx] = ph;
+ }
+
+ if (fsel_cnt[idx]) {
+ *reventsp |= POLLIN;
+ printf("POLL %X cnt=%u polled_zero=%u\n",
+ idx, fsel_cnt[idx], polled_zero);
+ polled_zero = 0;
+ } else
+ polled_zero++;
+
+ pthread_mutex_unlock(&fsel_mutex);
+ return 0;
+}
+
+static struct fuse_operations fsel_oper = {
+ .getattr = fsel_getattr,
+ .readdir = fsel_readdir,
+ .open = fsel_open,
+ .release = fsel_release,
+ .read = fsel_read,
+ .poll = fsel_poll,
+};
+
+static void *fsel_producer(void *data)
+{
+ const struct timespec interval = { 0, 250000000 };
+ unsigned idx = 0, nr = 1;
+
+ (void) data;
+
+ while (1) {
+ int i, t;
+
+ pthread_mutex_lock(&fsel_mutex);
+
+ /*
+ * This is the main producer loop which is executed
+ * ever 500ms. On each iteration, it fills one byte
+ * to 1, 2 or 4 files and sends poll notification if
+ * requested.
+ */
+ for (i = 0, t = idx; i < nr;
+ i++, t = (t + FSEL_FILES / nr) % FSEL_FILES) {
+ if (fsel_cnt[t] == FSEL_CNT_MAX)
+ continue;
+
+ fsel_cnt[t]++;
+ if (fsel_fuse && (fsel_poll_notify_mask & (1 << t))) {
+ struct fuse_pollhandle *ph;
+
+ printf("NOTIFY %X\n", t);
+ ph = fsel_poll_handle[t];
+ fuse_notify_poll(ph);
+ fuse_pollhandle_destroy(ph);
+ fsel_poll_notify_mask &= ~(1 << t);
+ fsel_poll_handle[t] = NULL;
+ }
+ }
+
+ idx = (idx + 1) % FSEL_FILES;
+ if (idx == 0)
+ nr = (nr * 2) % 7; /* cycle through 1, 2 and 4 */
+
+ pthread_mutex_unlock(&fsel_mutex);
+
+ nanosleep(&interval, NULL);
+ }
+
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t producer;
+ pthread_attr_t attr;
+ int ret;
+
+ errno = pthread_mutex_init(&fsel_mutex, NULL);
+ if (errno) {
+ perror("pthread_mutex_init");
+ return 1;
+ }
+
+ errno = pthread_attr_init(&attr);
+ if (errno) {
+ perror("pthread_attr_init");
+ return 1;
+ }
+
+ errno = pthread_create(&producer, &attr, fsel_producer, NULL);
+ if (errno) {
+ perror("pthread_create");
+ return 1;
+ }
+
+ ret = fuse_main(argc, argv, &fsel_oper, NULL);
+
+ pthread_cancel(producer);
+ pthread_join(producer, NULL);
+
+ return ret;
+}
diff --git a/draft/fuse-examples/fselclient.c b/draft/fuse-examples/fselclient.c
new file mode 100644
index 0000000..7c4b837
--- /dev/null
+++ b/draft/fuse-examples/fselclient.c
@@ -0,0 +1,72 @@
+/*
+ FUSE fselclient: FUSE select example client
+ Copyright (C) 2008 SUSE Linux Products GmbH
+ Copyright (C) 2008 Tejun Heo <teheo@suse.de>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fselclient.c -o fselclient
+*/
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define FSEL_FILES 16
+
+int main(void)
+{
+ static const char hex_map[FSEL_FILES] = "0123456789ABCDEF";
+ int fds[FSEL_FILES];
+ int i, nfds;
+
+ for (i = 0; i < FSEL_FILES; i++) {
+ char name[] = { hex_map[i], '\0' };
+ fds[i] = open(name, O_RDONLY);
+ if (fds[i] < 0) {
+ perror("open");
+ return 1;
+ }
+ }
+ nfds = fds[FSEL_FILES - 1] + 1;
+
+ while (1) {
+ static char buf[4096];
+ fd_set rfds;
+ int rc;
+
+ FD_ZERO(&rfds);
+ for (i = 0; i < FSEL_FILES; i++)
+ FD_SET(fds[i], &rfds);
+
+ rc = select(nfds, &rfds, NULL, NULL, NULL);
+
+ if (rc < 0) {
+ perror("select");
+ return 1;
+ }
+
+ for (i = 0; i < FSEL_FILES; i++) {
+ if (!FD_ISSET(fds[i], &rfds)) {
+ printf("_: ");
+ continue;
+ }
+ printf("%X:", i);
+ rc = read(fds[i], buf, sizeof(buf));
+ if (rc < 0) {
+ perror("read");
+ return 1;
+ }
+ printf("%02d ", rc);
+ }
+ printf("\n");
+ }
+}
diff --git a/draft/fuse-examples/fusexmp.c b/draft/fuse-examples/fusexmp.c
new file mode 100644
index 0000000..dca8a46
--- /dev/null
+++ b/draft/fuse-examples/fusexmp.c
@@ -0,0 +1,412 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp
+*/
+
+#define FUSE_USE_VERSION 26
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef linux
+/* For pread()/pwrite()/utimensat() */
+#define _XOPEN_SOURCE 700
+#endif
+
+#include <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/time.h>
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+
+static int xmp_getattr(const char *path, struct stat *stbuf)
+{
+ int res;
+
+ res = lstat(path, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_access(const char *path, int mask)
+{
+ int res;
+
+ res = access(path, mask);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_readlink(const char *path, char *buf, size_t size)
+{
+ int res;
+
+ res = readlink(path, buf, size - 1);
+ if (res == -1)
+ return -errno;
+
+ buf[res] = '\0';
+ return 0;
+}
+
+
+static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ DIR *dp;
+ struct dirent *de;
+
+ (void) offset;
+ (void) fi;
+
+ dp = opendir(path);
+ if (dp == NULL)
+ return -errno;
+
+ while ((de = readdir(dp)) != NULL) {
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ st.st_ino = de->d_ino;
+ st.st_mode = de->d_type << 12;
+ if (filler(buf, de->d_name, &st, 0))
+ break;
+ }
+
+ closedir(dp);
+ return 0;
+}
+
+static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+ int res;
+
+ /* On Linux this could just be 'mknod(path, mode, rdev)' but this
+ is more portable */
+ if (S_ISREG(mode)) {
+ res = open(path, O_CREAT | O_EXCL | O_WRONLY, mode);
+ if (res >= 0)
+ res = close(res);
+ } else if (S_ISFIFO(mode))
+ res = mkfifo(path, mode);
+ else
+ res = mknod(path, mode, rdev);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_mkdir(const char *path, mode_t mode)
+{
+ int res;
+
+ res = mkdir(path, mode);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_unlink(const char *path)
+{
+ int res;
+
+ res = unlink(path);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_rmdir(const char *path)
+{
+ int res;
+
+ res = rmdir(path);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_symlink(const char *from, const char *to)
+{
+ int res;
+
+ res = symlink(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_rename(const char *from, const char *to)
+{
+ int res;
+
+ res = rename(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_link(const char *from, const char *to)
+{
+ int res;
+
+ res = link(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_chmod(const char *path, mode_t mode)
+{
+ int res;
+
+ res = chmod(path, mode);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_chown(const char *path, uid_t uid, gid_t gid)
+{
+ int res;
+
+ res = lchown(path, uid, gid);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_truncate(const char *path, off_t size)
+{
+ int res;
+
+ res = truncate(path, size);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#ifdef HAVE_UTIMENSAT
+static int xmp_utimens(const char *path, const struct timespec ts[2])
+{
+ int res;
+
+ /* don't use utime/utimes since they follow symlinks */
+ res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+#endif
+
+static int xmp_open(const char *path, struct fuse_file_info *fi)
+{
+ int res;
+
+ res = open(path, fi->flags);
+ if (res == -1)
+ return -errno;
+
+ close(res);
+ return 0;
+}
+
+static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int fd;
+ int res;
+
+ (void) fi;
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return -errno;
+
+ res = pread(fd, buf, size, offset);
+ if (res == -1)
+ res = -errno;
+
+ close(fd);
+ return res;
+}
+
+static int xmp_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ int fd;
+ int res;
+
+ (void) fi;
+ fd = open(path, O_WRONLY);
+ if (fd == -1)
+ return -errno;
+
+ res = pwrite(fd, buf, size, offset);
+ if (res == -1)
+ res = -errno;
+
+ close(fd);
+ return res;
+}
+
+static int xmp_statfs(const char *path, struct statvfs *stbuf)
+{
+ int res;
+
+ res = statvfs(path, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_release(const char *path, struct fuse_file_info *fi)
+{
+ /* Just a stub. This method is optional and can safely be left
+ unimplemented */
+
+ (void) path;
+ (void) fi;
+ return 0;
+}
+
+static int xmp_fsync(const char *path, int isdatasync,
+ struct fuse_file_info *fi)
+{
+ /* Just a stub. This method is optional and can safely be left
+ unimplemented */
+
+ (void) path;
+ (void) isdatasync;
+ (void) fi;
+ return 0;
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+static int xmp_fallocate(const char *path, int mode,
+ off_t offset, off_t length, struct fuse_file_info *fi)
+{
+ int fd;
+ int res;
+
+ (void) fi;
+
+ if (mode)
+ return -EOPNOTSUPP;
+
+ fd = open(path, O_WRONLY);
+ if (fd == -1)
+ return -errno;
+
+ res = -posix_fallocate(fd, offset, length);
+
+ close(fd);
+ return res;
+}
+#endif
+
+#ifdef HAVE_SETXATTR
+/* xattr operations are optional and can safely be left unimplemented */
+static int xmp_setxattr(const char *path, const char *name, const char *value,
+ size_t size, int flags)
+{
+ int res = lsetxattr(path, name, value, size, flags);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+
+static int xmp_getxattr(const char *path, const char *name, char *value,
+ size_t size)
+{
+ int res = lgetxattr(path, name, value, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int xmp_listxattr(const char *path, char *list, size_t size)
+{
+ int res = llistxattr(path, list, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int xmp_removexattr(const char *path, const char *name)
+{
+ int res = lremovexattr(path, name);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+#endif /* HAVE_SETXATTR */
+
+static struct fuse_operations xmp_oper = {
+ .getattr = xmp_getattr,
+ .access = xmp_access,
+ .readlink = xmp_readlink,
+ .readdir = xmp_readdir,
+ .mknod = xmp_mknod,
+ .mkdir = xmp_mkdir,
+ .symlink = xmp_symlink,
+ .unlink = xmp_unlink,
+ .rmdir = xmp_rmdir,
+ .rename = xmp_rename,
+ .link = xmp_link,
+ .chmod = xmp_chmod,
+ .chown = xmp_chown,
+ .truncate = xmp_truncate,
+#ifdef HAVE_UTIMENSAT
+ .utimens = xmp_utimens,
+#endif
+ .open = xmp_open,
+ .read = xmp_read,
+ .write = xmp_write,
+ .statfs = xmp_statfs,
+ .release = xmp_release,
+ .fsync = xmp_fsync,
+#ifdef HAVE_POSIX_FALLOCATE
+ .fallocate = xmp_fallocate,
+#endif
+#ifdef HAVE_SETXATTR
+ .setxattr = xmp_setxattr,
+ .getxattr = xmp_getxattr,
+ .listxattr = xmp_listxattr,
+ .removexattr = xmp_removexattr,
+#endif
+};
+
+int main(int argc, char *argv[])
+{
+ umask(0);
+ return fuse_main(argc, argv, &xmp_oper, NULL);
+}
diff --git a/draft/fuse-examples/fusexmp_fh.c b/draft/fuse-examples/fusexmp_fh.c
new file mode 100644
index 0000000..1ba9dbc
--- /dev/null
+++ b/draft/fuse-examples/fusexmp_fh.c
@@ -0,0 +1,567 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh
+*/
+
+#define FUSE_USE_VERSION 26
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <fuse.h>
+#include <ulockmgr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/time.h>
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+#include <sys/file.h> /* flock(2) */
+
+static int xmp_getattr(const char *path, struct stat *stbuf)
+{
+ int res;
+
+ res = lstat(path, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_fgetattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+
+ res = fstat(fi->fh, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_access(const char *path, int mask)
+{
+ int res;
+
+ res = access(path, mask);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_readlink(const char *path, char *buf, size_t size)
+{
+ int res;
+
+ res = readlink(path, buf, size - 1);
+ if (res == -1)
+ return -errno;
+
+ buf[res] = '\0';
+ return 0;
+}
+
+struct xmp_dirp {
+ DIR *dp;
+ struct dirent *entry;
+ off_t offset;
+};
+
+static int xmp_opendir(const char *path, struct fuse_file_info *fi)
+{
+ int res;
+ struct xmp_dirp *d = malloc(sizeof(struct xmp_dirp));
+ if (d == NULL)
+ return -ENOMEM;
+
+ d->dp = opendir(path);
+ if (d->dp == NULL) {
+ res = -errno;
+ free(d);
+ return res;
+ }
+ d->offset = 0;
+ d->entry = NULL;
+
+ fi->fh = (unsigned long) d;
+ return 0;
+}
+
+static inline struct xmp_dirp *get_dirp(struct fuse_file_info *fi)
+{
+ return (struct xmp_dirp *) (uintptr_t) fi->fh;
+}
+
+static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ struct xmp_dirp *d = get_dirp(fi);
+
+ (void) path;
+ if (offset != d->offset) {
+ seekdir(d->dp, offset);
+ d->entry = NULL;
+ d->offset = offset;
+ }
+ while (1) {
+ struct stat st;
+ off_t nextoff;
+
+ if (!d->entry) {
+ d->entry = readdir(d->dp);
+ if (!d->entry)
+ break;
+ }
+
+ memset(&st, 0, sizeof(st));
+ st.st_ino = d->entry->d_ino;
+ st.st_mode = d->entry->d_type << 12;
+ nextoff = telldir(d->dp);
+ if (filler(buf, d->entry->d_name, &st, nextoff))
+ break;
+
+ d->entry = NULL;
+ d->offset = nextoff;
+ }
+
+ return 0;
+}
+
+static int xmp_releasedir(const char *path, struct fuse_file_info *fi)
+{
+ struct xmp_dirp *d = get_dirp(fi);
+ (void) path;
+ closedir(d->dp);
+ free(d);
+ return 0;
+}
+
+static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+ int res;
+
+ if (S_ISFIFO(mode))
+ res = mkfifo(path, mode);
+ else
+ res = mknod(path, mode, rdev);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_mkdir(const char *path, mode_t mode)
+{
+ int res;
+
+ res = mkdir(path, mode);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_unlink(const char *path)
+{
+ int res;
+
+ res = unlink(path);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_rmdir(const char *path)
+{
+ int res;
+
+ res = rmdir(path);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_symlink(const char *from, const char *to)
+{
+ int res;
+
+ res = symlink(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_rename(const char *from, const char *to)
+{
+ int res;
+
+ res = rename(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_link(const char *from, const char *to)
+{
+ int res;
+
+ res = link(from, to);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_chmod(const char *path, mode_t mode)
+{
+ int res;
+
+ res = chmod(path, mode);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_chown(const char *path, uid_t uid, gid_t gid)
+{
+ int res;
+
+ res = lchown(path, uid, gid);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_truncate(const char *path, off_t size)
+{
+ int res;
+
+ res = truncate(path, size);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_ftruncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+
+ res = ftruncate(fi->fh, size);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#ifdef HAVE_UTIMENSAT
+static int xmp_utimens(const char *path, const struct timespec ts[2])
+{
+ int res;
+
+ /* don't use utime/utimes since they follow symlinks */
+ res = utimensat(0, path, ts, AT_SYMLINK_NOFOLLOW);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+#endif
+
+static int xmp_create(const char *path, mode_t mode, struct fuse_file_info *fi)
+{
+ int fd;
+
+ fd = open(path, fi->flags, mode);
+ if (fd == -1)
+ return -errno;
+
+ fi->fh = fd;
+ return 0;
+}
+
+static int xmp_open(const char *path, struct fuse_file_info *fi)
+{
+ int fd;
+
+ fd = open(path, fi->flags);
+ if (fd == -1)
+ return -errno;
+
+ fi->fh = fd;
+ return 0;
+}
+
+static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+ res = pread(fi->fh, buf, size, offset);
+ if (res == -1)
+ res = -errno;
+
+ return res;
+}
+
+static int xmp_read_buf(const char *path, struct fuse_bufvec **bufp,
+ size_t size, off_t offset, struct fuse_file_info *fi)
+{
+ struct fuse_bufvec *src;
+
+ (void) path;
+
+ src = malloc(sizeof(struct fuse_bufvec));
+ if (src == NULL)
+ return -ENOMEM;
+
+ *src = FUSE_BUFVEC_INIT(size);
+
+ src->buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
+ src->buf[0].fd = fi->fh;
+ src->buf[0].pos = offset;
+
+ *bufp = src;
+
+ return 0;
+}
+
+static int xmp_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+ res = pwrite(fi->fh, buf, size, offset);
+ if (res == -1)
+ res = -errno;
+
+ return res;
+}
+
+static int xmp_write_buf(const char *path, struct fuse_bufvec *buf,
+ off_t offset, struct fuse_file_info *fi)
+{
+ struct fuse_bufvec dst = FUSE_BUFVEC_INIT(fuse_buf_size(buf));
+
+ (void) path;
+
+ dst.buf[0].flags = FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK;
+ dst.buf[0].fd = fi->fh;
+ dst.buf[0].pos = offset;
+
+ return fuse_buf_copy(&dst, buf, FUSE_BUF_SPLICE_NONBLOCK);
+}
+
+static int xmp_statfs(const char *path, struct statvfs *stbuf)
+{
+ int res;
+
+ res = statvfs(path, stbuf);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_flush(const char *path, struct fuse_file_info *fi)
+{
+ int res;
+
+ (void) path;
+ /* This is called from every close on an open file, so call the
+ close on the underlying filesystem. But since flush may be
+ called multiple times for an open file, this must not really
+ close the file. This is important if used on a network
+ filesystem like NFS which flush the data/metadata on close() */
+ res = close(dup(fi->fh));
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int xmp_release(const char *path, struct fuse_file_info *fi)
+{
+ (void) path;
+ close(fi->fh);
+
+ return 0;
+}
+
+static int xmp_fsync(const char *path, int isdatasync,
+ struct fuse_file_info *fi)
+{
+ int res;
+ (void) path;
+
+#ifndef HAVE_FDATASYNC
+ (void) isdatasync;
+#else
+ if (isdatasync)
+ res = fdatasync(fi->fh);
+ else
+#endif
+ res = fsync(fi->fh);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+static int xmp_fallocate(const char *path, int mode,
+ off_t offset, off_t length, struct fuse_file_info *fi)
+{
+ (void) path;
+
+ if (mode)
+ return -EOPNOTSUPP;
+
+ return -posix_fallocate(fi->fh, offset, length);
+}
+#endif
+
+#ifdef HAVE_SETXATTR
+/* xattr operations are optional and can safely be left unimplemented */
+static int xmp_setxattr(const char *path, const char *name, const char *value,
+ size_t size, int flags)
+{
+ int res = lsetxattr(path, name, value, size, flags);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+
+static int xmp_getxattr(const char *path, const char *name, char *value,
+ size_t size)
+{
+ int res = lgetxattr(path, name, value, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int xmp_listxattr(const char *path, char *list, size_t size)
+{
+ int res = llistxattr(path, list, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int xmp_removexattr(const char *path, const char *name)
+{
+ int res = lremovexattr(path, name);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+#endif /* HAVE_SETXATTR */
+
+static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
+ struct flock *lock)
+{
+ (void) path;
+
+ return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
+ sizeof(fi->lock_owner));
+}
+
+static int xmp_flock(const char *path, struct fuse_file_info *fi, int op)
+{
+ int res;
+ (void) path;
+
+ res = flock(fi->fh, op);
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static struct fuse_operations xmp_oper = {
+ .getattr = xmp_getattr,
+ .fgetattr = xmp_fgetattr,
+ .access = xmp_access,
+ .readlink = xmp_readlink,
+ .opendir = xmp_opendir,
+ .readdir = xmp_readdir,
+ .releasedir = xmp_releasedir,
+ .mknod = xmp_mknod,
+ .mkdir = xmp_mkdir,
+ .symlink = xmp_symlink,
+ .unlink = xmp_unlink,
+ .rmdir = xmp_rmdir,
+ .rename = xmp_rename,
+ .link = xmp_link,
+ .chmod = xmp_chmod,
+ .chown = xmp_chown,
+ .truncate = xmp_truncate,
+ .ftruncate = xmp_ftruncate,
+#ifdef HAVE_UTIMENSAT
+ .utimens = xmp_utimens,
+#endif
+ .create = xmp_create,
+ .open = xmp_open,
+ .read = xmp_read,
+ .read_buf = xmp_read_buf,
+ .write = xmp_write,
+ .write_buf = xmp_write_buf,
+ .statfs = xmp_statfs,
+ .flush = xmp_flush,
+ .release = xmp_release,
+ .fsync = xmp_fsync,
+#ifdef HAVE_POSIX_FALLOCATE
+ .fallocate = xmp_fallocate,
+#endif
+#ifdef HAVE_SETXATTR
+ .setxattr = xmp_setxattr,
+ .getxattr = xmp_getxattr,
+ .listxattr = xmp_listxattr,
+ .removexattr = xmp_removexattr,
+#endif
+ .lock = xmp_lock,
+ .flock = xmp_flock,
+
+ .flag_nullpath_ok = 1,
+#if HAVE_UTIMENSAT
+ .flag_utime_omit_ok = 1,
+#endif
+};
+
+int main(int argc, char *argv[])
+{
+ umask(0);
+ return fuse_main(argc, argv, &xmp_oper, NULL);
+}
diff --git a/draft/fuse-examples/hello.c b/draft/fuse-examples/hello.c
new file mode 100644
index 0000000..bcb6b4c
--- /dev/null
+++ b/draft/fuse-examples/hello.c
@@ -0,0 +1,96 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
+*/
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+static const char *hello_str = "Hello World!\n";
+static const char *hello_path = "/hello";
+
+static int hello_getattr(const char *path, struct stat *stbuf)
+{
+ int res = 0;
+
+ memset(stbuf, 0, sizeof(struct stat));
+ if (strcmp(path, "/") == 0) {
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ } else if (strcmp(path, hello_path) == 0) {
+ stbuf->st_mode = S_IFREG | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = strlen(hello_str);
+ } else
+ res = -ENOENT;
+
+ return res;
+}
+
+static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) offset;
+ (void) fi;
+
+ if (strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+ filler(buf, hello_path + 1, NULL, 0);
+
+ return 0;
+}
+
+static int hello_open(const char *path, struct fuse_file_info *fi)
+{
+ if (strcmp(path, hello_path) != 0)
+ return -ENOENT;
+
+ if ((fi->flags & 3) != O_RDONLY)
+ return -EACCES;
+
+ return 0;
+}
+
+static int hello_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ size_t len;
+ (void) fi;
+ if(strcmp(path, hello_path) != 0)
+ return -ENOENT;
+
+ len = strlen(hello_str);
+ if (offset < len) {
+ if (offset + size > len)
+ size = len - offset;
+ memcpy(buf, hello_str + offset, size);
+ } else
+ size = 0;
+
+ return size;
+}
+
+static struct fuse_operations hello_oper = {
+ .getattr = hello_getattr,
+ .readdir = hello_readdir,
+ .open = hello_open,
+ .read = hello_read,
+};
+
+int main(int argc, char *argv[])
+{
+ return fuse_main(argc, argv, &hello_oper, NULL);
+}
diff --git a/draft/fuse-examples/hello_ll.c b/draft/fuse-examples/hello_ll.c
new file mode 100644
index 0000000..1405441
--- /dev/null
+++ b/draft/fuse-examples/hello_ll.c
@@ -0,0 +1,181 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll
+*/
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse_lowlevel.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+
+static const char *hello_str = "Hello World!\n";
+static const char *hello_name = "hello";
+
+static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
+{
+ stbuf->st_ino = ino;
+ switch (ino) {
+ case 1:
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ break;
+
+ case 2:
+ stbuf->st_mode = S_IFREG | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = strlen(hello_str);
+ break;
+
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi)
+{
+ struct stat stbuf;
+
+ (void) fi;
+
+ memset(&stbuf, 0, sizeof(stbuf));
+ if (hello_stat(ino, &stbuf) == -1)
+ fuse_reply_err(req, ENOENT);
+ else
+ fuse_reply_attr(req, &stbuf, 1.0);
+}
+
+static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
+{
+ struct fuse_entry_param e;
+
+ if (parent != 1 || strcmp(name, hello_name) != 0)
+ fuse_reply_err(req, ENOENT);
+ else {
+ memset(&e, 0, sizeof(e));
+ e.ino = 2;
+ e.attr_timeout = 1.0;
+ e.entry_timeout = 1.0;
+ hello_stat(e.ino, &e.attr);
+
+ fuse_reply_entry(req, &e);
+ }
+}
+
+struct dirbuf {
+ char *p;
+ size_t size;
+};
+
+static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name,
+ fuse_ino_t ino)
+{
+ struct stat stbuf;
+ size_t oldsize = b->size;
+ b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
+ b->p = (char *) realloc(b->p, b->size);
+ memset(&stbuf, 0, sizeof(stbuf));
+ stbuf.st_ino = ino;
+ fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf,
+ b->size);
+}
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
+ off_t off, size_t maxsize)
+{
+ if (off < bufsize)
+ return fuse_reply_buf(req, buf + off,
+ min(bufsize - off, maxsize));
+ else
+ return fuse_reply_buf(req, NULL, 0);
+}
+
+static void hello_ll_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
+ off_t off, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ if (ino != 1)
+ fuse_reply_err(req, ENOTDIR);
+ else {
+ struct dirbuf b;
+
+ memset(&b, 0, sizeof(b));
+ dirbuf_add(req, &b, ".", 1);
+ dirbuf_add(req, &b, "..", 1);
+ dirbuf_add(req, &b, hello_name, 2);
+ reply_buf_limited(req, b.p, b.size, off, size);
+ free(b.p);
+ }
+}
+
+static void hello_ll_open(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi)
+{
+ if (ino != 2)
+ fuse_reply_err(req, EISDIR);
+ else if ((fi->flags & 3) != O_RDONLY)
+ fuse_reply_err(req, EACCES);
+ else
+ fuse_reply_open(req, fi);
+}
+
+static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
+ off_t off, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ assert(ino == 2);
+ reply_buf_limited(req, hello_str, strlen(hello_str), off, size);
+}
+
+static struct fuse_lowlevel_ops hello_ll_oper = {
+ .lookup = hello_ll_lookup,
+ .getattr = hello_ll_getattr,
+ .readdir = hello_ll_readdir,
+ .open = hello_ll_open,
+ .read = hello_ll_read,
+};
+
+int main(int argc, char *argv[])
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ struct fuse_chan *ch;
+ char *mountpoint;
+ int err = -1;
+
+ if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
+ (ch = fuse_mount(mountpoint, &args)) != NULL) {
+ struct fuse_session *se;
+
+ se = fuse_lowlevel_new(&args, &hello_ll_oper,
+ sizeof(hello_ll_oper), NULL);
+ if (se != NULL) {
+ if (fuse_set_signal_handlers(se) != -1) {
+ fuse_session_add_chan(se, ch);
+ err = fuse_session_loop(se);
+ fuse_remove_signal_handlers(se);
+ fuse_session_remove_chan(ch);
+ }
+ fuse_session_destroy(se);
+ }
+ fuse_unmount(mountpoint, ch);
+ }
+ fuse_opt_free_args(&args);
+
+ return err ? 1 : 0;
+}
diff --git a/draft/fuse-examples/null.c b/draft/fuse-examples/null.c
new file mode 100644
index 0000000..b72cf4d
--- /dev/null
+++ b/draft/fuse-examples/null.c
@@ -0,0 +1,95 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+
+ gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null
+*/
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+
+static int null_getattr(const char *path, struct stat *stbuf)
+{
+ if(strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ stbuf->st_mode = S_IFREG | 0644;
+ stbuf->st_nlink = 1;
+ stbuf->st_uid = getuid();
+ stbuf->st_gid = getgid();
+ stbuf->st_size = (1ULL << 32); /* 4G */
+ stbuf->st_blocks = 0;
+ stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL);
+
+ return 0;
+}
+
+static int null_truncate(const char *path, off_t size)
+{
+ (void) size;
+
+ if(strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ return 0;
+}
+
+static int null_open(const char *path, struct fuse_file_info *fi)
+{
+ (void) fi;
+
+ if(strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ return 0;
+}
+
+static int null_read(const char *path, char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) buf;
+ (void) offset;
+ (void) fi;
+
+ if(strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ if (offset >= (1ULL << 32))
+ return 0;
+
+ return size;
+}
+
+static int null_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void) buf;
+ (void) offset;
+ (void) fi;
+
+ if(strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ return size;
+}
+
+static struct fuse_operations null_oper = {
+ .getattr = null_getattr,
+ .truncate = null_truncate,
+ .open = null_open,
+ .read = null_read,
+ .write = null_write,
+};
+
+int main(int argc, char *argv[])
+{
+ return fuse_main(argc, argv, &null_oper, NULL);
+}
diff --git a/mcastseed/AUTHORS b/draft/mcastseed/AUTHORS
index c338cf6..c338cf6 100644
--- a/mcastseed/AUTHORS
+++ b/draft/mcastseed/AUTHORS
diff --git a/mcastseed/COPYING b/draft/mcastseed/COPYING
index d60c31a..d60c31a 100644
--- a/mcastseed/COPYING
+++ b/draft/mcastseed/COPYING
diff --git a/mcastseed/ChangeLog b/draft/mcastseed/ChangeLog
index e69de29..e69de29 100644
--- a/mcastseed/ChangeLog
+++ b/draft/mcastseed/ChangeLog
diff --git a/mcastseed/Makefile.am b/draft/mcastseed/Makefile.am
index b07663c..b07663c 100644
--- a/mcastseed/Makefile.am
+++ b/draft/mcastseed/Makefile.am
diff --git a/mcastseed/NEWS b/draft/mcastseed/NEWS
index e69de29..e69de29 100644
--- a/mcastseed/NEWS
+++ b/draft/mcastseed/NEWS
diff --git a/mcastseed/README b/draft/mcastseed/README
index 42061c0..42061c0 120000
--- a/mcastseed/README
+++ b/draft/mcastseed/README
diff --git a/mcastseed/README.md b/draft/mcastseed/README.md
index 98ddff0..98ddff0 100644
--- a/mcastseed/README.md
+++ b/draft/mcastseed/README.md
diff --git a/mcastseed/configure.ac b/draft/mcastseed/configure.ac
index e9e292f..e9e292f 100644
--- a/mcastseed/configure.ac
+++ b/draft/mcastseed/configure.ac
diff --git a/mcastseed/lib/Makefile.am b/draft/mcastseed/lib/Makefile.am
index 38faabe..38faabe 100644
--- a/mcastseed/lib/Makefile.am
+++ b/draft/mcastseed/lib/Makefile.am
diff --git a/mcastseed/lib/gl_anyrbtree_list1.h b/draft/mcastseed/lib/gl_anyrbtree_list1.h
index 0ae0715..0ae0715 100644
--- a/mcastseed/lib/gl_anyrbtree_list1.h
+++ b/draft/mcastseed/lib/gl_anyrbtree_list1.h
diff --git a/mcastseed/lib/gl_anyrbtree_list2.h b/draft/mcastseed/lib/gl_anyrbtree_list2.h
index a0e2e43..a0e2e43 100644
--- a/mcastseed/lib/gl_anyrbtree_list2.h
+++ b/draft/mcastseed/lib/gl_anyrbtree_list2.h
diff --git a/mcastseed/lib/gl_anytree_list1.h b/draft/mcastseed/lib/gl_anytree_list1.h
index 675f107..675f107 100644
--- a/mcastseed/lib/gl_anytree_list1.h
+++ b/draft/mcastseed/lib/gl_anytree_list1.h
diff --git a/mcastseed/lib/gl_anytree_list2.h b/draft/mcastseed/lib/gl_anytree_list2.h
index 7e6fe45..7e6fe45 100644
--- a/mcastseed/lib/gl_anytree_list2.h
+++ b/draft/mcastseed/lib/gl_anytree_list2.h
diff --git a/mcastseed/lib/gl_list.c b/draft/mcastseed/lib/gl_list.c
index 8793298..8793298 100644
--- a/mcastseed/lib/gl_list.c
+++ b/draft/mcastseed/lib/gl_list.c
diff --git a/mcastseed/lib/gl_list.h b/draft/mcastseed/lib/gl_list.h
index c9d05b0..c9d05b0 100644
--- a/mcastseed/lib/gl_list.h
+++ b/draft/mcastseed/lib/gl_list.h
diff --git a/mcastseed/lib/gl_rbtree_list.c b/draft/mcastseed/lib/gl_rbtree_list.c
index 5d621f1..5d621f1 100644
--- a/mcastseed/lib/gl_rbtree_list.c
+++ b/draft/mcastseed/lib/gl_rbtree_list.c
diff --git a/mcastseed/lib/gl_rbtree_list.h b/draft/mcastseed/lib/gl_rbtree_list.h
index 8cb9d11..8cb9d11 100644
--- a/mcastseed/lib/gl_rbtree_list.h
+++ b/draft/mcastseed/lib/gl_rbtree_list.h
diff --git a/mcastseed/lib/stdbool.in.h b/draft/mcastseed/lib/stdbool.in.h
index 7ecf203..7ecf203 100644
--- a/mcastseed/lib/stdbool.in.h
+++ b/draft/mcastseed/lib/stdbool.in.h
diff --git a/mcastseed/m4/00gnulib.m4 b/draft/mcastseed/m4/00gnulib.m4
index bb37e32..bb37e32 100644
--- a/mcastseed/m4/00gnulib.m4
+++ b/draft/mcastseed/m4/00gnulib.m4
diff --git a/mcastseed/m4/extern-inline.m4 b/draft/mcastseed/m4/extern-inline.m4
index 1e578f3..1e578f3 100644
--- a/mcastseed/m4/extern-inline.m4
+++ b/draft/mcastseed/m4/extern-inline.m4
diff --git a/mcastseed/m4/gnulib-cache.m4 b/draft/mcastseed/m4/gnulib-cache.m4
index d75ad4f..d75ad4f 100644
--- a/mcastseed/m4/gnulib-cache.m4
+++ b/draft/mcastseed/m4/gnulib-cache.m4
diff --git a/mcastseed/m4/gnulib-common.m4 b/draft/mcastseed/m4/gnulib-common.m4
index f8454c8..f8454c8 100644
--- a/mcastseed/m4/gnulib-common.m4
+++ b/draft/mcastseed/m4/gnulib-common.m4
diff --git a/mcastseed/m4/gnulib-comp.m4 b/draft/mcastseed/m4/gnulib-comp.m4
index b809eea..b809eea 100644
--- a/mcastseed/m4/gnulib-comp.m4
+++ b/draft/mcastseed/m4/gnulib-comp.m4
diff --git a/mcastseed/m4/gnulib-tool.m4 b/draft/mcastseed/m4/gnulib-tool.m4
index 0d2ee44..0d2ee44 100644
--- a/mcastseed/m4/gnulib-tool.m4
+++ b/draft/mcastseed/m4/gnulib-tool.m4
diff --git a/mcastseed/m4/stdbool.m4 b/draft/mcastseed/m4/stdbool.m4
index a556153..a556153 100644
--- a/mcastseed/m4/stdbool.m4
+++ b/draft/mcastseed/m4/stdbool.m4
diff --git a/mcastseed/src/Makefile.am b/draft/mcastseed/src/Makefile.am
index 2f2a735..2f2a735 100644
--- a/mcastseed/src/Makefile.am
+++ b/draft/mcastseed/src/Makefile.am
diff --git a/mcastseed/src/dgrambuf.c b/draft/mcastseed/src/dgrambuf.c
index 5d4c302..5d4c302 100644
--- a/mcastseed/src/dgrambuf.c
+++ b/draft/mcastseed/src/dgrambuf.c
diff --git a/mcastseed/src/dgrambuf.h b/draft/mcastseed/src/dgrambuf.h
index a83647b..a83647b 100644
--- a/mcastseed/src/dgrambuf.h
+++ b/draft/mcastseed/src/dgrambuf.h
diff --git a/mcastseed/src/dgrambuf_test.c b/draft/mcastseed/src/dgrambuf_test.c
index 6f9ef22..6f9ef22 100644
--- a/mcastseed/src/dgrambuf_test.c
+++ b/draft/mcastseed/src/dgrambuf_test.c
diff --git a/mcastseed/src/mcastleech.c b/draft/mcastseed/src/mcastleech.c
index 3345665..3345665 100644
--- a/mcastseed/src/mcastleech.c
+++ b/draft/mcastseed/src/mcastleech.c
diff --git a/mcastseed/src/mcastseed.c b/draft/mcastseed/src/mcastseed.c
index 48f8869..48f8869 100644
--- a/mcastseed/src/mcastseed.c
+++ b/draft/mcastseed/src/mcastseed.c
diff --git a/mcastseed/src/random_speed_dd.c b/draft/mcastseed/src/random_speed_dd.c
index 4d94bc0..4d94bc0 100644
--- a/mcastseed/src/random_speed_dd.c
+++ b/draft/mcastseed/src/random_speed_dd.c
diff --git a/mcastseed/src/sockets.c b/draft/mcastseed/src/sockets.c
index 6aea016..6aea016 100644
--- a/mcastseed/src/sockets.c
+++ b/draft/mcastseed/src/sockets.c
diff --git a/mcastseed/src/sockets.h b/draft/mcastseed/src/sockets.h
index 86f7c5b..86f7c5b 100644
--- a/mcastseed/src/sockets.h
+++ b/draft/mcastseed/src/sockets.h
diff --git a/draft/other-tools/clonezilla/drbl-ocs.conf b/draft/other-tools/clonezilla/drbl-ocs.conf
new file mode 100644
index 0000000..f204029
--- /dev/null
+++ b/draft/other-tools/clonezilla/drbl-ocs.conf
@@ -0,0 +1,414 @@
+# drbl-ocs (Clonezilla) setting
+# Do NOT modify if you are not sure what you are doing!
+OCSMGRD_PORT="6461"
+
+# Create image volumes with a size of X,
+# Annoying...
+# in the past, its unit is KB (for partimage 0.6.2).
+# MB (for partimage 0.6.4)
+# Since we use partimage 0.6.4 now, it's MB.
+# NOTE:
+# If you are using partimage 0.6.5 beta 3, the maximum is 2000 MB, you can not set it larger than 2000. Otherwise it will fails to get the correct set.
+# For other version of partimage, no such problem.
+# Ref:http://www.partimage.org/forums/viewtopic.php?t=481
+# http://sourceforge.net/forum/message.php?msg_id=3761573
+# "0" is also "no split" for clonezilla. Before clonezilla 2.1, if split, the image name will like: hda1.000, hda1.000... which is done by partimage.
+# Without split, the image is like: hda1 (not hda1.000, i.e. without ".000")
+# From clonezilla 2.1 or later, we do not let partimage built function to split it, we use program split to do that.
+# Unit for clonezilla split: MB, by default we set it as 100 GB, no more use unlimite (0) because the reason:
+# 2009/11/05, on Ubuntu 9.10 with upstart 0.6.3 or later, the "/sbin/init" won't accept the boot parameters as an option, it will always read /proc/cmdline, therefore if we use "0", the option will be shown in /proc/cmdline as "ocs_opt=... -i 0" and in /tftpboot/node_root/sbin/init we can not make it by removing "ocs_opt=... -i 0" anymore.
+# The volume limit to split an partition image file.
+# This is for those file systems could support large file, like ext4 a single file size limit is 16 TiB. Here we set it as 1TB
+# Unit: MB (1000*1000)
+VOL_LIMIT_DEFAULT="1000000"
+# Assign VOL_LIMIT_IN_INTERACTIVE as 4096 MB, since some cases when
+# using ocs-sr -x, it's in FAT16B/FAT32, the limitation is
+# 4,294,967,295 bytes (4 GiB - 1)
+# Unit: MB (1000*1000)
+# Ref: http://en.wikipedia.org/wiki/File_Allocation_Table
+# http://en.wikipedia.org/wiki/Megabyte
+VOL_LIMIT_IN_INTERACTIVE="4096"
+
+# Specify the suffix length for spliting the image file of a partition or LV. By default it's 2, i.e. aa, ab, ac...
+# Integer must >= 2.
+split_suf_len="2"
+
+# multicast setting
+# From udpcast menu:
+# --mcast-all-addr address
+# Uses a non-standard multicast address for the control
+# connection (which is used by the sender and receivers to
+# "find" each other). This is not the address that is used to
+# transfer the data.
+# By default mcast-all-addr is the Ethernet broadcast address
+# if ttl is 1, and 224.0.0.1 otherwise. This setting should not
+# be used except in very special situations, such as when
+# 224.0.0.1 cannot be used for policy reasons.
+# Note! It's better to keep 224.0.0.1, For example, if $eth_for_multicast is eth1. In Debian sarge, for different clients in eth2 or eth3, will not be able to connect eth1 to get the multicast packets
+MULTICAST_ALL_ADDR="224.0.0.1"
+MULTICAST_PORT="2232"
+TIME_TO_LIVE_OPT="--ttl 1"
+
+# You can assign extra option for udp-sender, e.g.
+# (1) "--max-bitrate 150m" (150 megabits/sec). See "man udp-sender" for more info.
+# Thanks to Mike Taylor for this idea. Ref: https://sourceforge.net/forum/message.php?msg_id=5281039
+# (2) "--fec 8x16/64"
+# Thanks to Pretzel for this idea. Ref: https://sourceforge.net/p/clonezilla/discussion/Clonezilla_server_edition/thread/6e1e87d4/
+# (3) "--retries-until-drop 50", for example, if you want to reduce the waiting time if some clients fail to continue then udp-sender drops them. By default it will take about 3 to 4 mins, with "--retries-until-drop 50", the time is reduced to about 40 secs. Thanks to Yitzon Belandria <yitzon _at_ gmail com> for sharing this result. Ref: https://sourceforge.net/p/drbl/discussion/250176/thread/70d6fd5e/?limit=25#4496
+udp_sender_extra_opt_default=""
+
+# You can assign extra option for udp-receiver here (very seldom)
+udp_receiver_extra_opt_default=""
+
+# The time to wait when multicast restoring more then 2 partitions.
+# For the first partition, we will ask user. This PART_PREPARE_TIME is for the wait time before next partition (2nd, 3rd... to start)
+# Not! It can not be too short!!! 30 secs is a good number.
+PART_PREPARE_TIME="30"
+# Time to prepare the next partition, like hda1 -> hda2
+SLEEP_TIME_AFTER_PART_CLONED="15"
+
+# time to wait default: sec
+TIME_TO_WAIT_DEFAULT="120"
+MAX_TIME_TO_WAIT_DEFAULT="300"
+#
+# ignore the MBR by using -M, we will ignore the error caused by devfs style
+# in /proc/partitions
+# now use -z0 and --volume=0 in DEFAULT_PARTIMAGE_SAVE_OPT, we will use partimage stdout and pipe it to use gzip/bzip2/lzop to compress it, not the compression function in partimge. --volume=0 is a must for stdout.
+DEFAULT_PARTIMAGE_SAVE_OPT="-M -f3 -o -d -b -c -z0 --volume=0"
+DEFAULT_PARTIMAGE_RESTORE_OPT="-M -f3 -b"
+
+# Extra gzip/lzma/xz option. This is used when using gzip/lzma/xz/lzip/lrzip (non-parallel) to save an image.
+# Adding "--rsyncable" to be friendly to rsync (https://sourceforge.net/p/clonezilla/discussion/Open_discussion/thread/8d5f80a6)
+# //NOTE// Option "--rsyncable" is not an official option for gzip, it's patched by some distributions. (https://sourceforge.net/p/clonezilla/discussion/Open_discussion/thread/8d5f80a6/?limit=25#89e2)
+rsyncable_opt_gzip=""
+if [ -n "$(LC_ALL=C gzip --help 2>&1 | grep -Ew -- "--rsyncable")" ]; then
+ rsyncable_opt_gzip="--rsyncable"
+fi
+extra_gzip_opt="--fast $rsyncable_opt_gzip"
+# -1 (fatest), -2, ... -9 (best compression)
+extra_bzip2_opt="-3"
+extra_lzop_opt="-3"
+extra_lzma_opt="-3"
+extra_xz_opt="-3"
+extra_lzip_opt="-3"
+extra_lrzip_opt="-L 3"
+
+# Use parallel gzip/pbzip2 when restoring
+use_parallel_decompression="yes"
+
+# Available programs for parallel bzip2: pbzip2, lbzip2
+# Default to use lbzip2 since pbzip2 1.0.5 has an issue about memory usage
+# https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/3517181
+parallel_bzip2_prog="lbzip2"
+
+# Extra pigz option. This is used when using pigz to save an image. For pigz, normally "-b 1024" (1024=1024K) is enough, although you can assign more like "-p 16" (16 threads).
+# Adding "-R" (--rsyncable) to be friendly to rsync (https://sourceforge.net/p/clonezilla/discussion/Open_discussion/thread/8d5f80a6)
+# //NOTE// Option "--rsyncable" is only for newer pigz, it's patched by some distributions. (https://sourceforge.net/p/clonezilla/discussion/Open_discussion/thread/8d5f80a6/?limit=25#89e2)
+rsyncable_opt_pigz=""
+if [ -n "$(LC_ALL=C pigz --help 2>&1 | grep -Ew -- "--rsyncable")" ]; then
+ rsyncable_opt_pigz="--rsyncable"
+fi
+extra_pigz_opt="--fast -b 1024 -p 16 $rsyncable_opt_pigz"
+# Extra pbzip2 option. This is used when using pbzip2 to save an image. For pbzip2, normally "-b9" (9=900K, the default value. It's different from pigz) is enough, although you can assign more like "-p16" (16 processors). Ref: https://sourceforge.net/tracker/?func=detail&atid=671650&aid=3324096&group_id=115473
+extra_pbzip2_opt="-3"
+extra_lbzip2_opt="-3"
+#
+extra_pixz_opt="-3"
+extra_plzip_opt="-3"
+
+# ntfsclone options, for saving and restoring, respectively. These variables will be appended when running ntfsclone.
+ntfsclone_save_extra_opt_def=""
+ntfsclone_restore_extra_opt_def=""
+
+# supported filesystem in partimage
+# ///NOTE/// FAT12 is not supported by partimage.
+partimage_support_fs="ext2 ext3 reiserfs xfs jfs fat16 fat32 vfat hpfs ufs hfs ntfs"
+
+# Supported filesystems in partclone
+# Although now partclone has the following programs:
+# clone.extfs clone.reiser4 clone.xfs clone.hfsp clone.reiserfs
+# This file system name is the same as we get from "parted -s /dev/[hsv]dx? print"
+# 2009/07/15 Since there is an issue when restoring vfat, remove fat*/vfat in the following list
+# partclone_support_fs="hfs+ hfsplus reiser4 xfs reiserfs ext2 ext3 ext4 ext4dev ntfs"
+# partclone 0.1.1-16 has fixed the issue about FAT. Turn it on:
+#partclone_support_fs="hfs+ hfsplus reiser4 xfs reiserfs ext2 ext3 ext4 ext4dev fat12 fat16 fat32 vfat ntfs"
+# 2009/09/12 partclone.xfs v0.1.1 (Rev:304M) is buggy. remove xfs in the following list.
+# 2009/09/18 partclone.xfs v0.1.9 was fixed. No more xfs problem. Add xfs in the following.
+# 2012/01/18 partclone.fstype from version 0.2.45 will tell vmfs3 and vmfs5. Therefore no more VMFS_volume_member and vmfs, we use vmfs3 and vmfs5. Since vmfs5 support in partclone 0.2.45 is still buggy due to libvmfs not supported well yet, we won't enable it until it's fully supported.
+# 2012/04/05 Enable vmfs5 since partclone 0.2.46 now works for vmfs5.
+# 2013/03/01 Enable minix since partclone 0.2.59 now works for minix.
+# 2014/12/01 Temporarily disabled vmfs3 and vmfs5 due to this issue:
+# https://github.com/glandium/vmfs-tools/issues/12
+# 2015/07/06 Enabled vmfs3 and vmfs5 since partclone >= 0.2.79 fixed this issue.
+partclone_support_fs="hfs+ hfsplus reiser4 reiserfs xfs jfs ext2 ext3 ext4 ext4dev fat12 fat16 fat32 vfat ntfs ufs btrfs exfat minix vmfs3 vmfs5 f2fs nilfs2"
+# Options to be appended in the partclone command, for save and restore.
+# For example, for restoring, if you want to ignore device size checking, "-C" can be put, like:
+# PARTCLONE_RESTORE_OPT_INIT="-C"
+# From Partclone 0.2.61, we switch to use "-z" instead of "-m":
+PARTCLONE_SAVE_OPT_INIT="-z 10485760"
+PARTCLONE_RESTORE_OPT_INIT="-z 10485760"
+PARTCLONE_RESTORE_ONTHEFLY_OPT_INIT="-z 10485760"
+
+# The debug_level for partimage
+# it's better we turn off the debug mode by default, this will reduce the server's loading.
+# It seems in partiamge 0.6.5-beta2, when using --debug=0 to save NTFS partition
+# partimage will crash. However, 0.6.5-beta1 works without this problem.
+# To avoid this, we set debug_level=1 as default value.
+debug_level="1"
+#
+MAX_DIALOG_HEIGHT="10"
+# dialog width for showing images
+RESTORE_DIA_WIDTH="70"
+#
+POSTACTION_DEF="reboot"
+# The poweroff/reboot options, which are used when clone finishes.
+# If you are impatient, you can set it as "-f -n" so it will force halt or reboot, don't call shutdown sequence, and do not sync. i.e. poweroff/reboot immediately. Note! This might fail your wake-on-LAN since it's not a normal soft-shutdown.
+# In some case (clonezilla live), we might overwrite this option to let it do normal poweroff/reboot.
+HALT_REBOOT_OPT=""
+# To avoid all the clients notify at almost same time, we use random sleep before send info. This is the maximun time limit (in secs).
+NOTIFY_OCS_SERVER_TIME_LIMIT="20"
+
+# OCS_PRERUN_DIR & OCS_POSTRUN_DIR
+# Run the script in the direcoty $OCS_POSTRUN_DIR before clone starts and finishes. The command will be run before that assigned in -p or --postaction."
+OCS_PRERUN_DIR="$DRBL_SCRIPT_PATH/prerun/ocs/"
+OCS_POSTRUN_DIR="$DRBL_SCRIPT_PATH/postrun/ocs/"
+
+# PREFIX for M$ windows hostname
+WIN_HOSTNAME_PREFIX="PC"
+
+# The way to trigger clonezilla client to start ocs-sr, 3 options:
+# (1) ocs-run.param: the ocs_opt is put in client's /etc/ocs/ocs-run.param
+# (2) proc-cmdline: the ocs_opt is put in client's /proc/cmdline, which is actually from server's pxelinux config /tftpboot/nbi_img/pxelinux.cfg/default or others.
+# (3) both: ocs_opt will be put both in /etc/ocs/ocs-run.param and server's pxelinux config /tftpboot/nbi_img/pxelinux.cfg/default or others. However, when ocs-run is run in client, it will use the ocs_opt from /tftpboot/nbi_img/pxelinux.cfg/default (i.e. /proc/cmdline)
+# We choose to use ocs_opt from proc-cmdline if it's both so that we can always put "ocs_client_trig_type=both" in this file. If we want to interactively debug clonezilla in client, just use "/etc/init.d/ocs-run -p start".
+# Note: SET IT AS "both" ONLY, other modes are only for backward compatibility testing.
+ocs_client_trig_type="both"
+
+# modify client's /etc/inittab when start clonezilla service.
+# If yes, both client's inittab and pxelinux config will be modified.
+# If no, just put "1" in pxelinux config so it will show in client's /proc/cmdline.
+# Available value: yes/no
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+modify_client_etc_inittab="no"
+
+# When use use drbl-ocs stop to stop clonezilla, do we want to clean the ocs related services (ssh, arm-wol...).
+# Available value: yes/no
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+clean_client_all_ocs_related_srv="no"
+
+# clean dhcpd lease in the server when it's clonezilla box mode.
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+clean_dhcpd_lease_in_clone_box_mode="no"
+
+# flag to regenerate the DRBL SSI template tarball
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+regen_drbl_ssi_template_tarball="no"
+
+# flag to re-put ocs related files in client's rc1.d (ocs-functions)
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+re_put_ocs_related_srv_in_client_rc1d="no"
+
+# flag to re-put S19ocs-run and all other services from template node's
+# client's rc1.d to /tftpboot/node_root/etc/drbl_ssi/rc1.d/ (drbl-ocs)
+# Note: Do NOT set it as "yes", it's only for backward compatibility testing.
+copy_rc1d_for_drbl_ssi_clone_box="no"
+
+# Flag to use dd or partclone in ocs (not ocs-onthefly)
+# Sector to sector copy program in ocs (not ocs-onthefly). Available progs are: dd, partclone
+S2S_IMAGE_PROG_IN_OCS="partclone"
+
+# Since dd does not report status with any option, we have to send SIGUSR1 to tell dd to report every some secs when using dd to save or restore an image. This will only take effect when S2S_IMAGE_PROG_IN_OCS = dd
+# dd report interval (secs)
+dd_report_interval="20"
+
+# Flag to use ntfsclone, dd, or partclone in ocs-onthefly
+# ///NOTE/// 2008/May/11 by Steven Shiau: local part to remote part still has a problem with partclone: e.g. local hda1 to remote hda3, due to the filesystem of source partition can not be informed to target machine in the current mechanism, it will fail if the filesystem is not the same with the list on $src_pt_info.
+# Something like: partclone.reiserfs can't restore from the image which filesystem is XFS not REISERFS
+USE_NTFSCLONE_IN_OCS_ONTHEFLY="no"
+USE_PARTCLONE_IN_OCS_ONTHEFLY="yes"
+# Sector to sector copy program. Available progs are: dd, partclone
+S2S_CLONE_PROG_IN_OCS_ONTHEFLY="partclone"
+
+# Hidden data space size limit. This is the max hidden data space size limit, if it's larger than
+# this, we won't create the file (e.g. sda-hidden-data-after-mbr).
+# Unit: MB
+hidden_data_after_mbr_limit="1024"
+
+# some presettings about clonezilla when running dcs
+# The prompt for user to input the disk when saving
+savedisk_preset="sda"
+# The prompt for user to input the partitions when saving
+saveparts_preset="sda1 sda2"
+
+# Options for encryption of image dir. We use ecryptfs to mount that. Therefore the options are from ecryptfs.
+# Run "man ecryptfs" for more details.
+ocs_ecryptfs_cipher="aes"
+ocs_ecryptfs_key_bytes="16"
+
+# checksum algorithm for files in the partition.
+# This is used to create the checksum for all the regular files in a partition or LV.
+# Available command: md5sum, sha1sum, sha256sum, sha512sum
+chksum_cmd_for_files_in_dev="md5sum"
+
+# Option for mounting file system for image repository ($ocsroot)
+# Ref: https://sourceforge.net/tracker/?func=detail&atid=671653&aid=2949613&group_id=115473
+# For cifs, noatime and nodiratime won't be honored, but cifs won't exit with error. It just ignores nodiratime.
+# For sshfs, nodiratime is not honored, and sshfs will exit with error.
+# For nfs, both noatime and nodiratime are honored.
+# Therefore we put noatime only, and add "nodiratime" for nfs, hfsplus and other fs.
+ocsroot_def_mnt_opt="noatime"
+
+# For davfs2 config. Do not modify unless you know what you are doing.
+davfs2_buf_size="10240" #KiByte maybe more
+davfs2_use_locks="0"
+davfs2_use_expect100="1"
+davfs2_use_compression="1"
+davfs2_cache_size_def="64" # MiByte. This is default value if appropriate free memory size can not be decided.
+davfs2_delay_upload="0"
+# The ratio for the cache size to free disk space (RAM disk actually) in Clonezilla live env.
+# Value must between 0 and 1. Default:0.2. Better not to be larger than 0.5
+# ///NOTE/// The cache mechanism of davfs2 is a problem (ref: https://sourceforge.net/forum/forum.php?thread_id=2248597&forum_id=82589). Although we use ratio_davfs2_cache_2_free_disk and free ramdisk space to set the cache size of davfs2, according to "man davfs2.conf":
+# cache_size: The amount of disk space in MiByte that may be used. mount.davfs will always take enough space to cache open files, ignoring this value if necessary.
+# Therefore the cache_size get in ocs-tune-conf-for-webdav is actually applied to VOL_LIMIT_DEFAULT and VOL_LIMIT_IN_INTERACTIVE, too, so that single file won't be over size.
+ratio_davfs2_cache_2_free_disk="0.2"
+# When webdav is the image repository, we need longer suffix length for "split" command, i.e. the option "-a" of split.
+# When "3" is used, Clonezilla live in a machine with 1 GB RAM could have 0.8 GB ramdisk size, so:
+# 26*26*26*0.8/5=2812 GB
+davfs2_split_suf_len_def="3"
+
+# This part is for DRBL/Clonezilla/GParted live
+# Settings
+# Debian Repository when creating debian live. It's better to use http://httpredir.debian.org/debian. However, some mirror site seems to be not so stable, and we might encounter the error like:
+# W: Failed to fetch http://httpredir.debian.org/debian/dists/sid/main/binary-i386/Packages Hash Sum mismatch
+# Therefore we use http://free.nchc.org.tw which can be fixed by Clonezilla team if something goes wrong.
+debian_mirror_url_def="http://free.nchc.org.tw/debian"
+debian_mirror_security_url_def="http://security.debian.org/debian-security"
+# Ubuntu repository when creating ubuntu live
+ubuntu_mirror_url_def="http://free.nchc.org.tw/ubuntu"
+ubuntu_mirror_security_url_def="http://free.nchc.org.tw/ubuntu"
+# DRBL repository
+DRBL_REPOSITORY_URL_def="http://free.nchc.org.tw/drbl-core"
+# URL to the repository key
+DRBL_GPG_KEY_URL="http://drbl.org/GPG-KEY-DRBL"
+
+# Clonezilla live iso template file name. By default we use debian-live-for-ocs.iso as the template file name in ocs-iso and ocs-live-dev.
+DEBIAN_ISO_DEF="debian-live-for-ocs.iso"
+# http://free.nchc.org.tw/drbl-core/iso/MD5SUMS
+md5_file="MD5SUMS"
+uni_font_file="unifont.bgf"
+syslinux_exe_file="syslinux.exe"
+makeboot_exe_file="MakeBoot.exe"
+wget_opt="-r -l1 --no-parent --passive-ftp -e robots=off -q -nd --retr-symlinks"
+CD_FILE_LIMIT="650" # unit: MB
+FILE_LIMIT="4500" # unit: MB
+# The kernel and initrd files are used just in case, normally ocs-iso or ocs-live-dev will search them.
+kernel_file="vmlinuz1"
+initrd_file="initrd1.img"
+# Client framebuffer mode
+VGA_MODE_DEF="788"
+BG_MODE_DEF="graphic"
+# Default console columns for adjust font and its size in live cd. This only will affect KMS mode, not other framebuffer mode.
+console_prefer_font="TerminusBold"
+# We want to show 100 characters in the screen (width)
+console_prefer_cols="100"
+# //NOTE// Generally this variable BOOT_PARAM_DEFAULT will be overwritten by the function get_live_boot_param in ocs-functions.
+BOOT_PARAM_DEFAULT="boot=live union=overlay"
+# Common boot parameters that Clonezilla live (iso/zip) need.
+# //NOTE// "nomodeset" is required for framebuffer mode (vga=788... or video=uvesafb:....). If no "nomodeset", it will enter kernel mode setting (KMS) mode. Then framebuffer mode will only take effect in the early booting. It won't work when we use Clonezilla. Therefore here we keep "nomodeset"
+supp_boot_param_ocs_live_iso="noswap edd=on nomodeset"
+# For Clonezilla live USB, we add "noeject" so by default we do not ask user to remove the USB flash drive when rebooting/halting.
+supp_boot_param_ocs_live_dev="$supp_boot_param_ocs_live_iso noeject"
+# Possible live media path (when live CD/USB-disk boots, the reall live media is mounted as...)
+# casper 1.77+debian-7 uses /live_media, 1.110 uses /cdrom
+# live-initramfs uses /live/image.
+# For Debian Live 3.x, rootfs is in /lib/live/mount/medium/live/filesystem.squashfs
+live_media_path_chklist="/lib/live/mount/medium /lib/live/image /live/image /live_media /cdrom"
+# Possible kernel/initrd paths in live CD/USB-disk are /casper (created by casper), /live (created by live-initramfs) or /isolinux (created by live pacakge with casper), or "/" (when using toram="filesystem.squashfs", filesystem.squashfs will be copied to / in the ram disk).
+live_sys_files_dir_list="live / isolinux casper"
+# For live-package, it's "/usr/share/make-live/hooks", for live-helper...
+live_pkg_hook_dir="/usr/share/make-live/hooks"
+# Some locales (especially CJK) need bterm to show
+locale_need_bterm="zh_TW zh_CN zh_HK zh_SG ja_JP ko_KR"
+# unifont.bgf path is required by bterm in clonezilla live.
+uni_font="$DRBL_SCRIPT_PATH/lib/unifont.bgf"
+# fb_term is either bterm or jfbterm. If not assigned, clonezilla live will try to use jfbterm first, then bterm. However, due to a bug of jfbterm in Ubuntu intrepid, bterm will be used in intrepid anyway.
+fb_term=""
+# Live build and debootstrap minimal version to create debian/gparted/drbl live, i.e. >= this
+lh_ver_required="3.0.5-1"
+debootstrap_ver_required="1.0.52"
+
+# Use RawCHS from EDD (sysfs interface to BIOS EDD information) for partclone.ntfsfixboot
+use_RawCHS_from_EDD_for_ntfsreloc="yes"
+
+# Use RawCHS from sfdisk for partclone.ntfsfixboot
+use_RawCHS_from_sfdisk_for_ntfsreloc="yes"
+
+# The run_grub2_from_restored_os_mode is for us to decide to run grub2 from the restored OS. Possible values are "yes", "no" or "". If "yes", Clonezilla will chroot and run grub-install. If "no", use the grub in the running system to run grub-install --root-directory=.... If "", then we will test in ocs-functions to use "yes" mode first, if fails, then "no" mode.
+# //NOTE// The OS arch in the running environment must be the same as that in the restored OS, otherwise, e.g. running OS is i386, and restored OS is x86-64, if this option is "yes", you will get error messages when run grub2 install:
+# "cannot run command" "Exec format error"
+run_grub2_from_restored_os_mode=""
+
+# A mounting point for temporary (middle) use.
+pre_ocsroot_path="/tmp/ocsroot_bind_root"
+
+# Log files for the output of clonezilla and related files.
+OCS_LOGFILE="/var/log/clonezilla.log" ; export OCS_LOGFILE
+OCS_NETCFG_LOG="/var/log/ocs-netcfg.log" ; export OCS_NETCFG_LOG
+OCS_MOUNT_LOG="/var/log/ocs-mount.log" ; export OCS_MOUNT_LOG
+
+
+###################################################
+### Settings about Clonezilla-live based client ###
+###################################################
+# The flag to use NFSRoot-based or Clonezilla-live-based system in the client
+# Available name: nfsroot, clonezilla-live
+diskless_client_os="nfsroot"
+
+# If diskless_client_os is clonezilla-live, the URL to download the clonezilla live. e.g.
+# http://downloads.sourceforge.net/clonezilla/clonezilla-live-1.2.5-6-i486.iso
+# http://sourceforge.net/projects/clonezilla/files/clonezilla_live_testing/clonezilla-live-1.2.5-6-i486.iso
+# Or
+# http://free.nchc.org.tw/clonezilla-live/testing/clonezilla-live-1.2.5-6-i486.iso
+# If you want to use a local copy, you can make it like:
+# iso_url_for_pxe_ocs_live_default="file://tmp/clonezilla-live-20130902-saucy-amd64.iso"
+iso_url_for_pxe_ocs_live_default=""
+
+# Flags when running drbl-ocs, shall we remove some boot parameters from pxelinux config file for Clonezilla live. (only takes effect when diskless_client_os="clonezilla-live"
+# Available flag for remove_some_boot_param_for_pxe_ocs_live: yes, no
+remove_some_boot_param_for_pxe_ocs_live="yes"
+
+# If remove_some_boot_param_for_pxe_ocs_live is yes, what shall we remove:
+# By default we remove quiet, splash, vga and video, we want it to be more verbose when booting clients
+boot_param_2_be_removed_in_pxe_ocs_live="quiet splash vga video"
+
+# Boot parameters to preseed: ocs_live_keymap, ocs_lang, ocs_daemonon, ocs_prerun,
+# Available keymaps: "NONE" (won't change the default layout), "/usr/share/keymaps/i386/azerty/fr-latin9.kmap.gz" (French keyboard)...
+ocs_live_keymap_for_pxe_ocs_live="NONE"
+
+# Available languages: en_US.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 ja_JP.UTF-8 zh_CN.UTF-8 zh_TW.UTF-8
+# However, the CJK might have problem to be shown on the screen because in the PXE client we do not always enter jfbterm unless it's Clonezilla live mode. Therefore it's better to keep it as "en_US.UTF-8"
+ocs_lang_for_pxe_ocs_live="en_US.UTF-8"
+
+# The daemon to be started, e.g. ssh (the file name in /etc/init.d/)
+ocs_daemonon_for_pxe_ocs_live="ssh"
+
+# The account and password for the Clonezilla live clients of Clonezilla SE.
+# //NOTE// These variables are not used to assign the default username and password of Clonezilla live when creating it by create-debian-live or create-ubuntu-live. They are only used for ssh login by drbl-doit. Therefore if someday Debian live changes its default username and password, we have to change here, too.
+ocs_live_username="user"
+ocs_live_passwd="live"
+
+# Prompt messages preference. Could be "tui" or "cmd". If not assigned, cmd is the default.
+# //NOTE// Not all the messages are supported to be shown in dialog/whiptail
+ocs_prompt_mode=""
+
+# The command to run before ocs_live_run command is executed. E.g. "mount -t nfs 192.168.120.254:/home/partimag/ /home/partimag". If not assigned, by default we will use:
+# mount -t nfs $IP:/home/partimag/ /home/partimag
+# where $IP is the 1st IP address on DRBL server.
+ocs_prerun_for_pxe_ocs_live=""
+
+### EFI network booting on Clonezilla SE ###
+# The option to decide if the EFI network booting is set as 1st priority
+# in the boot order in EFI NVRAM after the image is restored by Clonezilla SE
+# Values: yes, no
+efi_netboot_1st_in_nvram="yes"
+###################################################
diff --git a/draft/other-tools/clonezilla/ocs-expand-gpt-pt b/draft/other-tools/clonezilla/ocs-expand-gpt-pt
new file mode 100755
index 0000000..191bc06
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-expand-gpt-pt
@@ -0,0 +1,386 @@
+#!/bin/bash
+# Author: Steven Shiau <steven _at_ nchc org tw>
+# License: GPL
+# A script to expand the GPT partition table by disk size ratio.
+# ///NOTE/// This program only works for GPT partition table, not for MBR.
+
+# Load DRBL setting and functions
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Settings
+# Flag to check target disk size before creating partition table
+chk_tgt_disk_size_bf_mk_pt="yes"
+
+#
+cmd_name="$(basename $0)"
+#
+USAGE() {
+ echo "$cmd_name: To create a proportional MBR partition table (not GPT) in a disk based on a existing partition table (sfdisk format)"
+ echo "Usage:"
+ echo " $cmd_name [OPTION] PARTITION_TABLE_FILE TARGET_DEVICE"
+ echo
+ echo "OPTION:"
+ echo " -b, --batch Run $cmd_name in batch mode, i.e. without any prompt or wait to press enter. VERY DANGEROUS!"
+ echo "$cmd_name will honor experimental variable EXTRA_SFDISK_OPT and use it as the option for sfdisk."
+ echo " -icds, --ignore-chk-dsk-size-pt Skip checking destination disk size before creating the partition table on it. By default it will be checked and if the size is smaller than the source disk, quit."
+ echo "Example:"
+ echo " To create a proportional partition table on disk /dev/sda based on /home/partimag/IMAGE/sda-pt.sf, use:"
+ echo "$cmd_name /home/partimag/IMAGE/sda-pt.sf /dev/sda"
+}
+
+# Parse command-line options
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b|--batch)
+ batch_mode="yes"
+ shift;;
+ -icds|--ignore-chk-dsk-size-pt)
+ chk_tgt_disk_size_bf_mk_pt="no"
+ shift;;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+done
+
+# Original sfdisk format file
+orig_sf=$1 # orig_sf is like: /home/partimag/IMAGE/sda-pt.sf
+target_disk=$2 # target_disk is like: /dev/sda
+
+#
+ask_and_load_lang_set $specified_lang
+
+#
+if [ -z "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No source partition table file was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+if [ ! -f "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Source partition table file \"$orig_sf\" was _NOT_ found"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+if [ -z "$target_disk" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No target disk was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ USAGE
+ exit 1
+fi
+
+#
+if [ "$batch_mode" != "yes" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "This program will create a partition table in $target_disk"
+ echo "ALL THE DATA IN THE TARGET DEVICE WILL BE ERASED!!!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_are_u_sure_u_want_to_continue ? (y/N) "
+ read continue_confirm_ans
+ case "$continue_confirm_ans" in
+ y|Y|[yY][eE][sS])
+ echo "$msg_ok_let_do_it!"
+ ;;
+ *)
+ echo "$msg_program_stop!"
+ exit 1
+ esac
+fi
+
+# Check if GPT disk, if yes, exit
+if `is_mbr_partitition_table_disk $target_disk`; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Disk $target_disk is MBR format. This program only works for GPT format."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# Check if the format of sfdisk is created by sfdisk >= 2.26
+if [ -z "$(LC_ALL=C grep -E "^label: gpt" $orig_sf)" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Partition table file \"$orig_sf\" does not contain GPT info."
+ echo "Make sure it's GPT format and outputted by sfdisk >= 2.26."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# No size info in sda-pt.sf, we have to use sda-pt.parted.
+orig_parted_tab="${orig_sf/.sf/.parted}"
+orig_parted_dir="$(dirname $orig_sf)"
+if [ ! -e "$orig_parted_tab" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "$orig_parted_tab was not found! It is required so that we know the original disk size! Maybe your Clonezilla image is too old ? You can try to create such an file in your source machine by: \"parted -s /dev/$SOURCE_DEV unit s print > $orig_parted_tab\" (Replace $SOURCE_DEV with your device name)"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# parted output format example:
+# Disk /dev/sda: 16777215s
+# Sector size (logical/physical): 512B/512B
+# Partition Table: msdos
+#
+# Number Start End Size Type File system Flags
+# 1 63s 586844s 586782s primary boot
+# 2 586845s 978074s 391230s primary
+# 3 978075s 1955204s 977130s primary
+# 4 1955205s 16776584s 14821380s extended
+# 5 1955268s 2151764s 196497s logical
+# 6 2151828s 2542994s 391167s logical
+# 7 2543058s 16776584s 14233527s logical
+
+ori_disk_size="$(LC_ALL=C grep -E "^Disk /dev" $orig_parted_tab | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+# If nothing in target disk, parted will show like this:
+# sudo parted -s /dev/sda unit s print
+# Error: Unable to open /dev/sda - unrecognised disk label.
+
+if ! LC_ALL=C parted -s $target_disk unit s print &>/dev/null; then
+ # Try to create a partition table so that we can read the size via parted -s $dev unit s print
+ echo "No initial GPT table on disk $target_disk. Create one now by:" | tee --append $OCS_LOGFILE
+ echo "parted -s $target_disk mklabel gpt" | tee --append $OCS_LOGFILE
+ LC_ALL=C parted -s $target_disk mklabel gpt | tee --append $OCS_LOGFILE
+fi
+tgt_disk_size="$(LC_ALL=C parted -s $target_disk unit s print | grep -E "^Disk /dev" | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+
+#
+ratio=$(echo "scale=10; $tgt_disk_size / $ori_disk_size" | bc -l) || exit 1
+echo "The ratio for target disk size to original disk size is $ratio."
+if [ "$chk_tgt_disk_size_bf_mk_pt" = "yes" ]; then
+ if [ "$(LC_ALL=C echo "$ratio < 1" | bc -l)" = "1" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The target disk (size=$tgt_disk_size sectors) is smaller than the source disk (size=$ori_disk_size sectors)!"
+ echo "Clonezilla won't be able to restore a partition image to smaller partition!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "Program terminated!"
+ exit 1
+ fi
+fi
+
+new_sf="$(mktemp /tmp/new_sf.XXXXXX)" || exit 1
+new_sf_tmp="$(mktemp /tmp/new_sf_tmp.XXXXXX)" || exit 1
+# Increase. Example for sfdisk format:
+# =====================================
+# label: gpt
+# label-id: ADC40CC4-77D7-4858-8F0E-8BC2447052AE
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 409600, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=E8D785ED-A65F-4EA1-ADF0-CC61E75677EB
+# /dev/sda2 : start= 411648, size= 1024000, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=AB72A495-4141-4500-AE48-B7AC492160B4
+# /dev/sda3 : start= 1435648, size= 40505344, type=E6D6D379-F507-44C2-A23C-238F2A3DF928, uuid=C7A87C41-72FD-41DB-9B10-DF3568A4089D
+# =====================================
+# label: gpt
+# label-id: D4165706-2FAD-491E-82CA-7866982D196B
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 614400, type=DE94BBA4-06D1-4D40-A16A-BFD50179D6AC, uuid=0802BFF4-2549-4CD4-A1CA-93D54AEE26F0, name="Basic data partition", attrs="RequiredPartiton GUID:63"
+# /dev/sda2 : start= 616448, size= 202752, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=C9C164D5-5E0F-476D-B2EA-A4D818A266CF, name="EFI system partition", attrs="GUID:63"
+# /dev/sda3 : start= 819200, size= 262144, type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE, uuid=15D5A869-5C6E-4F2C-B234-7D6B91B58555, name="Microsoft reserved partition", attrs="GUID:63"
+# /dev/sda4 : start= 1081344, size= 124745728, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=E53DEA7E-2639-4AE9-9DFD-DDD2406C3EC0, name="Basic data partition"
+# =====================================
+
+# We only need those required info
+grep -E "^/dev" $orig_sf > $new_sf_tmp
+# start=291579750 or size=291563622 is not a good format for us to parse, we need a space between "=" and "number"
+# i.e.
+# No good:
+# /dev/sda1 : start= 63, size=291563622, Id= 7, bootable
+# /dev/sda2 : start=291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+#
+# Good:
+# /dev/sda1 : start= 63, size= 291563622, Id= 7, bootable
+# /dev/sda2 : start= 291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+
+# //NOTE// For partitions number >=10, it looks like:
+# label: gpt
+# label-id: 56C0DC13-942C-493F-B141-F9903658453B
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=4F5FF221-D350-4CE7-BADA-20022DA453CC, name="Linux filesystem"
+# /dev/sda2 : start= 2099200, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=975A9722-E2ED-46CC-B0E1-995095A6BB66, name="Linux filesystem"
+# /dev/sda3 : start= 4196352, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A27C9E16-70B1-48D0-9A3F-915AFBA8FCC7, name="Linux filesystem"
+# /dev/sda4 : start= 6293504, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=3E134963-5B14-49C1-9F83-9BAF9C5F61C9, name="Linux filesystem"
+# /dev/sda5 : start= 8390656, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=FB1FB744-E6DC-48FA-9891-256AD0F3CF7C, name="Linux filesystem"
+# /dev/sda6 : start= 10487808, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=BB764A64-35BF-4415-A8D6-84642339FB3F, name="Linux filesystem"
+# /dev/sda7 : start= 12584960, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B0D77252-85AB-4AFB-8866-38C21605DB7B, name="Linux filesystem"
+# /dev/sda8 : start= 14682112, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=79E8897A-B821-4C5D-A481-5F8628C57D2E, name="Linux filesystem"
+# /dev/sda9 : start= 16779264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2CA8A44E-9A2B-475A-BFC8-1E6295847F6A, name="Linux filesystem"
+# /dev/sda10 : start= 18876416, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B454EC36-562F-4844-B8D9-28C5C1C111C9, name="Linux filesystem"
+# /dev/sda11 : start= 20973568, size= 104855519, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=FA55D210-62EE-4948-A853-FDD4360CDCB5, name="Linux filesystem"
+
+# Therefore we force to put a space no matter there is already space or not
+perl -pi -e "s/start=/start= /g" $new_sf_tmp
+perl -pi -e "s/size=/size= /g" $new_sf_tmp
+# Remove ":" in the temp file, since it's only for parsing, won't be used for sfdisk /dev/... < $new_sf_tmp ...
+perl -pi -e "s/://g" $new_sf_tmp
+
+# Get the line number of "last-lba:"
+header_line="$(LC_ALL=C grep -E -n "^last-lba:" $orig_sf | awk -F":" '{print $1}')"
+if [ -z "$header_line" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Failed to find the line \"last-lba:\" in $orig_sf!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+# We do not output the line "last-lba:" in the generated line. Otherwise we have to calculate the last-lba number.
+LC_ALL=C head -n "$((header_line -1))" $orig_sf > $new_sf
+echo "" >> $new_sf
+start_no_keep=""
+size_no_keep=""
+append_to_next="0"
+# Initial gap for the 1st partition. After this, it should be 0.
+logical_part_gap="2"
+while read dev start start_no size size_no type uuid name attrs; do
+ pt_no="$(LC_ALL=C get_part_number $dev | sed -r -e "s|^[^[:digit:]]*||g")"
+ if `is_partition $dev` ; then
+ [ -z "$start_no_keep" ] && start_no_keep=${start_no/,/} # The 1st one
+ [ -z "$size_no_keep" ] && size_no_keep=0
+ if [ "${size_no/,/}" -eq 0 ]; then
+ start_no=0
+ size_no=0
+ else
+ # If we found the partition is EFI System partition, keep the size.
+ # EFI System partition: C12A7328-F81F-11D2-BA4B-00A0C93EC93B,
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ expand="true"
+ if [ -n "$(echo $type | grep -iE "type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"EFI System partition\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # If we found the partition is MS Windows "system reserved partition", keep the size.
+ # Microsoft Reserved Partition (MSR): E3C9E316-0B5C-4DB8-817D-F92DF00215AE
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ if [ -n "$(echo $type | grep -iE "type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"Microsoft Reserved Partition (MSR)\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # If we found the partition is MS Windows "system reserved partition", keep the size.
+ # Windows Recovery Environment DE94BBA4-06D1-4D40-A16A-BFD50179D6AC
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ if [ -n "$(echo $type | grep -iE "type=DE94BBA4-06D1-4D40-A16A-BFD50179D6AC")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"Windows Recovery Environment\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # For newer Clonezilla (>=2.4.36-1drbl), a tag file (sda1.info) might exist
+ if [ -e "$orig_parted_dir/$(to_filename ${dev}).info" ]; then
+ . $orig_parted_dir/$(to_filename ${dev}).info
+ if [ "$PARTITION_TYPE" = "Win_boot_reserved" ]; then
+ expand="false"
+ fi
+ fi
+ # For Linux Swap partition
+ if [ -n "$(echo $type | grep -iE "type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$type\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ expand="false"
+ fi
+
+ if [ "$expand" = "true" ]; then
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="$(LC_ALL=C printf "%.0f" "$(echo "${size_no/,/}*$ratio + $append_to_next" | bc -l)")"
+ # Reset the space append_to_next.
+ append_to_next="0"
+ else
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="${size_no/,/}"
+ # Since we do not expand this "system reserved partition" or "swap partition",
+ # we append the space to the next partition.
+ # It's possible that there are more than one partition which will be
+ # kept as original size, e.g.
+ # Number Start End Size File system Name Flags
+ # 1 1049kB 106MB 105MB EFI system partition boot, esp
+ # 2 106MB 240MB 134MB Microsoft reserved partition msftres
+ # 3 240MB 128GB 128GB Basic data partition msftdata
+ # In the above, partition 1 and 2 will not be expanded. Therefore we
+ # might need to add the previous $append_to_next
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "$append_to_next + ${size_no}*$ratio - ${size_no}" | bc -l)")"
+ fi
+ fi
+ if [ "$size_no" -lt 0 ]; then
+ # append_to_next might be nagtive when "-icds" is enabled and ration is < 1, therefore
+ # we have to check the size_no.
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The calculated size of $dev is < 0!"
+ echo "Unable to create a smaller partitions layout."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+ fi
+ echo $dev : $start $start_no, $size $size_no, $type $uuid $name $attrs >> $new_sf
+ [ "$start_no" -ne 0 ] && start_no_keep="${start_no/,/}"
+ [ "$size_no" -ne 0 ] && size_no_keep="${size_no/,/}"
+ fi
+done < $new_sf_tmp
+
+echo "The partition table to write in $target_disk:"
+echo "*****************************************"
+cat $new_sf
+echo "*****************************************"
+
+# EXTRA_SFDISK_OPT is environment variable
+# If not --force, we force to append it since by default if sfdisk find some CHS it does not like, it won't do it without --force
+if [ -z "$(echo $EXTRA_SFDISK_OPT | grep -Ew -- "--force")" ]; then
+ EXTRA_SFDISK_OPT="$EXTRA_SFDISK_OPT --force"
+fi
+echo "Running: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+LC_ALL=C sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf
+echo "Partition table was created by: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+
+# Use parted to fill the last partitition to the end of disk because
+# there might be some resudial in the calculation.
+# Thanks to Conan for this suggestion.
+# Ref: https://sourceforge.net/p/clonezilla/discussion/
+# Clonezilla_live/thread/c5e92d87/?limit=25#080c
+if [ -n "$(LC_ALL=C parted -h | grep -w resizepart)" ]; then
+ # Find the last partition number.
+ # Firstly we get the line number for "Number Start End Size
+ # File system Name Flags"
+ line_after="$(LC_ALL=C parted -s $target_disk print | \
+ grep -n -Ew "^Number[[:space:]]+Start[[:space:]]+End.*" | \
+ awk -F":" '{print $1}')"
+ line_after="$((line_after +1))"
+ last_part_no="$(LC_ALL=C parted -s $target_disk print | \
+ tail -n +${line_after} | awk -F" " '{print $1}' | sort -V | tail -n 1)"
+ if [ -n "$last_part_no" ]; then
+ echo "Trying to extend the last partition to the end of disk by:"
+ echo "parted -s $target_disk resizepart $last_part_no 100%"
+ LC_ALL=C parted -s $target_disk resizepart $last_part_no 100%
+ fi
+fi
+
+[ -e "$new_sf" ] && rm -f $new_sf
+[ -e "$new_sf_tmp" ] && rm -f $new_sf_tmp
diff --git a/draft/other-tools/clonezilla/ocs-expand-mbr-pt b/draft/other-tools/clonezilla/ocs-expand-mbr-pt
new file mode 100755
index 0000000..eeb9759
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-expand-mbr-pt
@@ -0,0 +1,369 @@
+#!/bin/bash
+# Author: Steven Shiau <steven _at_ nchc org tw>
+# License: GPL
+# A script to expand the partition table by disk size ratio.
+# ///NOTE/// This program only works for MBR partition table, not for GPT.
+
+# Load DRBL setting and functions
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Settings
+# Flag to check target disk size before creating partition table
+chk_tgt_disk_size_bf_mk_pt="yes"
+
+#
+cmd_name="$(basename $0)"
+#
+USAGE() {
+ echo "$cmd_name: To create a proportional MBR partition table (not GPT) in a disk based on a existing partition table (sfdisk format)"
+ echo "Usage:"
+ echo " $cmd_name [OPTION] PARTITION_TABLE_FILE TARGET_DEVICE"
+ echo
+ echo "OPTION:"
+ echo " -b, --batch Run $cmd_name in batch mode, i.e. without any prompt or wait to press enter. VERY DANGEROUS!"
+ echo "$cmd_name will honor experimental variable EXTRA_SFDISK_OPT and use it as the option for sfdisk."
+ echo " -icds, --ignore-chk-dsk-size-pt Skip checking destination disk size before creating the partition table on it. By default it will be checked and if the size is smaller than the source disk, quit."
+ echo "Example:"
+ echo " To create a proportional partition table on disk /dev/sda based on /home/partimag/IMAGE/sda-pt.sf, use:"
+ echo "$cmd_name /home/partimag/IMAGE/sda-pt.sf /dev/sda"
+}
+
+# Parse command-line options
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b|--batch)
+ batch_mode="yes"
+ shift;;
+ -icds|--ignore-chk-dsk-size-pt)
+ chk_tgt_disk_size_bf_mk_pt="no"
+ shift;;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+done
+
+# Original sfdisk format file
+orig_sf=$1 # orig_sf is like: /home/partimag/IMAGE/sda-pt.sf
+target_disk=$2 # target_disk is like: /dev/sda
+
+#
+ask_and_load_lang_set $specified_lang
+
+#
+if [ -z "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No source partition table file was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+if [ ! -f "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Source partition table file \"$orig_sf\" was _NOT_ found"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+if [ -z "$target_disk" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No target disk was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ USAGE
+ exit 1
+fi
+
+#
+if [ "$batch_mode" != "yes" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "This program will create a partition table in $target_disk"
+ echo "ALL THE DATA IN THE TARGET DEVICE WILL BE ERASED!!!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_are_u_sure_u_want_to_continue ? (y/N) "
+ read continue_confirm_ans
+ case "$continue_confirm_ans" in
+ y|Y|[yY][eE][sS])
+ echo "$msg_ok_let_do_it!"
+ ;;
+ *)
+ echo "$msg_program_stop!"
+ exit 1
+ esac
+fi
+
+# Check if GPT disk, if yes, exit
+if `is_gpt_partitition_table_disk $target_disk`; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Disk $target_disk is GPT format. This program only works for MBR format."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# No size info in sda-pt.sf, we have to use sda-pt.parted.
+orig_parted_tab="${orig_sf/.sf/.parted}"
+orig_parted_dir="$(dirname $orig_sf)"
+if [ ! -e "$orig_parted_tab" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "$orig_parted_tab was not found! It is required so that we know the original disk size! Maybe your Clonezilla image is too old ? You can try to create such an file in your source machine by: \"parted -s /dev/$SOURCE_DEV unit s print > $orig_parted_tab\" (Replace $SOURCE_DEV with your device name)"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# parted output format example:
+# Disk /dev/sda: 16777215s
+# Sector size (logical/physical): 512B/512B
+# Partition Table: msdos
+#
+# Number Start End Size Type File system Flags
+# 1 63s 586844s 586782s primary boot
+# 2 586845s 978074s 391230s primary
+# 3 978075s 1955204s 977130s primary
+# 4 1955205s 16776584s 14821380s extended
+# 5 1955268s 2151764s 196497s logical
+# 6 2151828s 2542994s 391167s logical
+# 7 2543058s 16776584s 14233527s logical
+
+ori_disk_size="$(LC_ALL=C grep -E "^Disk /dev" $orig_parted_tab | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+# If nothing in target disk, parted will show like this:
+# sudo parted -s /dev/sda unit s print
+# Error: Unable to open /dev/sda - unrecognised disk label.
+
+if ! LC_ALL=C parted -s $target_disk unit s print &>/dev/null; then
+ # Try to create a partition table so that we can read the size via parted -s $dev unit s print
+ echo -n "No partition table exists in target disk $target_disk, try to initialize one so that we can get the disk size by sfdisk... "
+ echo 1,,83 | sfdisk -f $target_disk &>/dev/null
+ echo "done!"
+fi
+tgt_disk_size="$(LC_ALL=C parted -s $target_disk unit s print | grep -E "^Disk /dev" | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+
+# If target_disk size is larger than 2 TiB (~2.2 TB = 2,199,023,255,040 bytes), exit. It's over the MBR's limitation.
+check_mbr_disk_size_gt_2TiB $target_disk exit
+
+#
+ratio=$(echo "scale=10; $tgt_disk_size / $ori_disk_size" | bc -l) || exit 1
+echo "The ratio for target disk size to original disk size is $ratio."
+if [ "$chk_tgt_disk_size_bf_mk_pt" = "yes" ]; then
+ if [ "$(LC_ALL=C echo "$ratio < 1" | bc -l)" = "1" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The target disk (size=$tgt_disk_size sectors) is smaller than the source disk (size=$ori_disk_size sectors)!"
+ echo "Clonezilla won't be able to restore a partition image to smaller partition!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "Program terminated!"
+ exit 1
+ fi
+fi
+
+new_sf="$(mktemp /tmp/new_sf.XXXXXX)" || exit 1
+new_sf_tmp="$(mktemp /tmp/new_sf_tmp.XXXXXX)" || exit 1
+# Increase. Example for sfdisk format:
+# # partition table of /dev/sda
+# unit: sectors
+#
+# /dev/sda1 : start= 63, size= 586782, Id=83, bootable
+# /dev/sda2 : start= 586845, size= 391230, Id=82
+# /dev/sda3 : start= 978075, size= 977130, Id=83
+# /dev/sda4 : start= 1955205, size= 14821380, Id= 5
+# /dev/sda5 : start= 1955268, size= 196497, Id=83
+# /dev/sda6 : start= 2151828, size= 391167, Id=83
+# /dev/sda7 : start= 2543058, size= 14233527, Id=83
+#
+# Or
+# /dev/sda1 : start= 63, size= 196497, Id=83
+# /dev/sda2 : start= 196560, size= 16580025, Id= 5
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+# /dev/sda5 : start= 196623, size= 16579962, Id=83
+
+# We only need those required info
+grep -E "^/dev" $orig_sf > $new_sf_tmp
+# Format the output, since something like "Id= 5" is not a good idea for us to parse
+perl -pi -e "s/Id=[[:space:]]+/Id=/g" $new_sf_tmp
+# start=291579750 or size=291563622 is not a good format for us to parse, we need a space between "=" and "number"
+# i.e.
+# No good:
+# /dev/sda1 : start= 63, size=291563622, Id= 7, bootable
+# /dev/sda2 : start=291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+#
+# Good:
+# /dev/sda1 : start= 63, size= 291563622, Id= 7, bootable
+# /dev/sda2 : start= 291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+
+# //NOTE// For partitions number >=10, it looks like:
+## partition table of /dev/sda
+#unit: sectors
+#
+#/dev/sda1 : start= 63, size= 976562, Id=83
+#/dev/sda2 : start= 976625, size= 1171875, Id=83
+#/dev/sda3 : start= 2148500, size= 1367187, Id=83
+#/dev/sda4 : start= 3515687, size= 13256173, Id= f
+#/dev/sda5 : start= 3515750, size= 195312, Id=83
+#/dev/sda6 : start= 3711063, size= 390624, Id=83
+#/dev/sda7 : start= 4101688, size= 585936, Id=83
+#/dev/sda8 : start= 4687625, size= 781249, Id=83
+#/dev/sda9 : start= 5468875, size= 976561, Id=83
+#/dev/sda10: start= 6445437, size= 976561, Id=83 <-- No space before ":"
+#/dev/sda11: start= 7421999, size= 976561, Id=83
+
+# Therefore we force to put a space no matter there is already space or not
+perl -pi -e "s/start=/start= /g" $new_sf_tmp
+perl -pi -e "s/size=/size= /g" $new_sf_tmp
+# Remove ":" in the temp file, since it's only for parsing, won't be used for sfdisk /dev/... < $new_sf_tmp ...
+perl -pi -e "s/://g" $new_sf_tmp
+
+#
+echo "unit: sectors" > $new_sf
+echo "" >> $new_sf
+start_no_keep=""
+size_no_keep=""
+extended_part=""
+flag_1st_logic_drv="off"
+append_to_next="0"
+# Initial gap for the 1st partition. After this, it should be 0.
+logical_part_gap="2"
+while read dev start start_no size size_no id flag; do
+ pt_no="$(LC_ALL=C get_part_number $dev | sed -r -e "s|^[^[:digit:]]*||g")"
+ if `is_partition $dev` && [ "$pt_no" -le 4 ]; then
+ # primary/extended partitions
+ [ -z "$start_no_keep" ] && start_no_keep=${start_no/,/} # The 1st one
+ [ -z "$size_no_keep" ] && size_no_keep=0
+ if [ "${size_no/,/}" -eq 0 ]; then
+ start_no=0
+ size_no=0
+ else
+ # If we found the partition is MS Windows (Vista, 7) "system reserved partition", i.e. size is about 100 MB (204800) or 200 MB (409600 sectors), and Id=7, and flag is bootable, not to expand it. i.e.:
+ # /dev/sda1 : start= 2048, size= 204800, Id= 7, bootable
+ # The files and dirs in MS Windows (Vista, 7) "system reserved partition"
+ # drwxrwxrwx 1 root root 4.0K 2011-07-20 06:22 Boot/
+ # -rwxrwxrwx 1 root root 375K 2009-07-14 01:38 bootmgr*
+ # -rwxrwxrwx 1 root root 8.0K 2011-07-20 06:22 BOOTSECT.BAK*
+ # drwxrwxrwx 1 root root 0 2011-07-20 06:31 System Volume Information/
+ # //NOTE// The above files and dirs will be shown after restoring, not the time when creating partition table. Therefore we can not mount the partition and parse them.
+ # Ref: http://windows7forums.com/windows-7-discussion/15629-hack-remove-100-mb-system-reserved-partition-when-installing-windows-7-a.html
+ expand="true"
+ if [ "${size_no/,/}" -eq "409600" -o "${size_no/,/}" -eq "204800" ]; then
+ if [ -n "$(echo $id | grep -iE "(id|type)=7")" -a \
+ -n "$(echo $flag | grep -iE "bootable")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "MS Windows (Vista or 7) \"system reserved partition\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ fi
+ # For newer Clonezilla (>=2.4.36-1drbl), a tag file (sda1.info) might exist
+ if [ -e "$orig_parted_dir/$(to_filename ${dev}).info" ]; then
+ . $orig_parted_dir/$(to_filename ${dev}).info
+ if [ "$PARTITION_TYPE" = "Win_boot_reserved" ]; then
+ expand="false"
+ fi
+ fi
+ # For Linux Swap partition
+ if [ -n "$(echo $id | grep -iE "(id|type)=82")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$id\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ expand="false"
+ fi
+
+ if [ "$expand" = "true" ]; then
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="$(LC_ALL=C printf "%.0f" "$(echo "${size_no/,/}*$ratio + $append_to_next" | bc -l)")"
+ # Reset the space append_to_next.
+ append_to_next="0"
+ else
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="${size_no/,/}"
+ # Since we do not expand this "system reserved partition" or "swap partition",
+ # we append the space to the next partition.
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "${size_no}*$ratio - ${size_no}" | bc -l)")"
+ fi
+ fi
+ if [ "$size_no" -lt 0 ]; then
+ # append_to_next might be nagtive when "-icds" is enabled and ration is < 1, therefore
+ # we have to check the size_no.
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The calculated size of $dev is < 0!"
+ echo "Unable to create a smaller partitions layout."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+ fi
+ if [ -n "$(echo $id | grep -iE "((id|type)=5|(id|type)=f)")" ]; then
+ # keep the extended partition, we need it for logical partitions.
+ extended_part="$dev"
+ extended_start_no="$start_no"
+ extended_size_no="$size_no"
+ fi
+ echo $dev : $start $start_no, $size $size_no, $id $flag >> $new_sf
+ [ "$start_no" -ne 0 ] && start_no_keep="${start_no/,/}"
+ [ "$size_no" -ne 0 ] && size_no_keep="${size_no/,/}"
+ else
+ # logical partitions
+ if [ "$flag_1st_logic_drv" = "off" ]; then
+ start_no_keep="$((extended_start_no))"
+ size_no_keep="0"
+ flag_1st_logic_drv="on"
+ fi
+ if [ "${size_no/,/}" -eq 0 ]; then
+ start_no=0
+ size_no=0
+ else
+ expand="true"
+ # For Linux Swap partition
+ if [ -n "$(echo $id | grep -iE "(id|type)=82")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$id\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ expand="false"
+ fi
+
+ if [ "$expand" = "true" ]; then
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep+$size_no_keep+$logical_part_gap)" | bc -l)")"
+ size_no="$(LC_ALL=C printf "%.0f" "$(echo "${size_no/,/}*$ratio + $append_to_next" | bc -l)")"
+ logical_part_gap="0"
+ # Reset the space append_to_next.
+ append_to_next="0"
+ else
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep+$size_no_keep+$logical_part_gap)" | bc -l)")"
+ size_no="${size_no/,/}"
+ # Since we do not expand the "swap partition", we append the space to the next partition.
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "${size_no}*$ratio - ${size_no}" | bc -l)")"
+ fi
+ fi
+ echo $dev : $start $start_no, $size $size_no, $id $flag >> $new_sf
+ [ "$start_no" -ne 0 ] && start_no_keep="${start_no/,/}"
+ [ "$size_no" -ne 0 ] && size_no_keep="${size_no/,/}"
+ fi
+done < $new_sf_tmp
+# For sfdisk <= 0.25, only "Id=" is accepted, not "type=".
+perl -pi -e "s/type=/Id=/g" $new_sf
+
+echo "The partition table to write in $target_disk:"
+echo "*****************************************"
+cat $new_sf
+echo "*****************************************"
+
+# EXTRA_SFDISK_OPT is environment variable
+# If not --force, we force to append it since by default if sfdisk find some CHS it does not like, it won't do it without --force
+if [ -z "$(echo $EXTRA_SFDISK_OPT | grep -Ew -- "--force")" ]; then
+ EXTRA_SFDISK_OPT="$EXTRA_SFDISK_OPT --force"
+fi
+echo "Running: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+LC_ALL=C sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf
+echo "Partition table was created by: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+
+[ -e "$new_sf" ] && rm -f $new_sf
+[ -e "$new_sf_tmp" ] && rm -f $new_sf_tmp
diff --git a/draft/other-tools/clonezilla/ocs-restore-ebr b/draft/other-tools/clonezilla/ocs-restore-ebr
new file mode 100755
index 0000000..6912c9a
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-restore-ebr
@@ -0,0 +1,119 @@
+#!/bin/bash
+#!/bin/bash
+# License: GPL
+# Author: Steven Shiau <steven _at_ clonezilla org>
+# Reinstall executable code area (first 446 bytes in EBR)
+# Ref: https://en.wikipedia.org/wiki/Extended_boot_record
+# Extended boot record (EBR) is the 512-byte boot sector:
+# 446 bytes (executable code area) + 64 bytes (table of primary partitions) + 2 bytes (EBR signature; # 0xAA55) = 512 bytes.
+# EBRs have essentially the same structure as the MBR.
+#
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Load the config in ocs-live.conf. This is specially for Clonezilla live. It will overwrite some settings of /etc/drbl/drbl-ocs.conf, such as $DIA...
+[ -e "/etc/ocs/ocs-live.conf" ] && . /etc/ocs/ocs-live.conf
+
+#
+USAGE() {
+ echo "$ocs - To restore the EBR (Extended boot record) from an image to device"
+ echo "Usage:"
+ echo "To run $ocs:"
+ echo "$ocs [OPTION] IMAGE_NAME DEVICE"
+ echo "Options:"
+ echo "-or, --ocsroot DIR Specify DIR (absolute path) as directory ocsroot (i.e. overwrite the ocsroot assigned in drbl.conf)"
+ echo "IMAGE_NAME is the image dir name, not absolute path"
+ echo "DEVICE is the device name, e.g. sda1, sda2..."
+ echo "Ex:"
+ echo "To restore the the EBR saved in the image \"my-image\" to device sda4, run:"
+ echo " $ocs my-image sda4"
+ echo
+} # end of USAGE
+
+
+####################
+### Main program ###
+####################
+
+ocs_file="$0"
+ocs=`basename $ocs_file`
+#
+#
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -or|--ocsroot)
+ # overwrite the ocsroot in drbl.conf
+ shift;
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ ocsroot="$1"
+ shift;
+ fi
+ [ -z "$ocsroot" ] && USAGE && exit 1
+ ;;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+done
+
+target_dir="$1"
+shift
+target_part="$*"
+
+# Fedora Core 1 seems to use dumb for rc1, we have to force it use linux.
+# otherwise setterm will complain.
+[ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="linux"
+echo "Setting the TERM as $TERM"
+export TERM="$TERM"
+
+#
+check_if_root
+ask_and_load_lang_set
+
+if [ -z "$target_dir" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No image was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+if [ -z "$target_part" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No destination partition was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+#
+target_dir_fullpath="$ocsroot/$target_dir"
+
+for ipart in $target_part; do
+ # 1st, check if this partition on a MBR disk, not GPT one.
+ dsk_pt="$target_dir_fullpath/$(to_filename $(get_diskname ${ipart}))-pt.parted"
+ if ! `is_mbr_partitition_table_file $dsk_pt`; then
+ echo "Partition $ipart is not on MBR disk. Maybe it's on GPT one. No need to restore the EBR data."
+ continue
+ fi
+ # 2nd, check if $ipart is extended partition
+ # For cciss partition, e.g. /dev/cciss/c0d0p2 will be "p2" which is got from $(get_part_number /dev/cciss/c0d0p2)", here the part_index we want is only number, hence we need to trip the leading characters.
+ index="$(LC_ALL=C get_part_number $ipart | sed -r -e "s|^[^[:digit:]]*||g")" # index is like 2
+ part_type="$(LC_ALL=C grep -Ew "^[[:space:]]*$index" ${dsk_pt} | grep -iw "extended")"
+ if [ -z "$part_type" ]; then
+ # Not extended partition
+ echo "Partition $ipart is not extended partition. No need to restore the EBR data."
+ continue
+ fi
+
+ #
+ echo -n "Restoring the first 446 bytes of EBR data for extended partition $ipart... "
+ dd if=$target_dir_fullpath/$(to_filename ${ipart})-ebr of=/dev/$ipart bs=446 count=1 &>/dev/null
+ echo "done."
+ echo $msg_delimiter_star_line
+done
diff --git a/draft/other-tools/clonezilla/ocs-restore-mbr b/draft/other-tools/clonezilla/ocs-restore-mbr
new file mode 100755
index 0000000..08fc697
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-restore-mbr
@@ -0,0 +1,131 @@
+#!/bin/bash
+
+# Reinstall executable code area (first 446 bytes in MBR)
+
+# Ref: http://en.wikipedia.org/wiki/Master_boot_record
+# Master Boot Record (MBR) is the 512-byte boot sector:
+# 446 bytes (executable code area) + 64 bytes (table of primary partitions) + 2 bytes (MBR signature; # 0xAA55) = 512 bytes.
+# However, some people also call executable code area (first 446 bytes in MBR) as MBR.
+#
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Load the config in ocs-live.conf. This is specially for Clonezilla live. It will overwrite some settings of /etc/drbl/drbl-ocs.conf, such as $DIA...
+[ -e "/etc/ocs/ocs-live.conf" ] && . /etc/ocs/ocs-live.conf
+
+# Setings
+# By default we do not restore the prebuild mbr from syslinux.
+restore_prebuild_mbr="no"
+
+#
+USAGE() {
+ echo "$ocs - To restore the MBR from an image to device"
+ echo "Usage:"
+ echo "To run $ocs:"
+ echo "$ocs [OPTION] IMAGE_NAME DEVICE"
+ echo "Options:"
+ echo "-p, --prebuild_mbr Use the prebuild bootloader from syslinux (For Windows only), not from the saved image"
+ echo "-or, --ocsroot DIR Specify DIR (absolute path) as directory ocsroot (i.e. overwrite the ocsroot assigned in drbl.conf)"
+ echo "IMAGE_NAME is the image dir name, not absolute path"
+ echo "DEVICE is the device name, e.g. sda, sda..."
+ echo "Ex:"
+ echo "To restore the the mbr saved in the image \"my-image\" to device sda, run:"
+ echo " $ocs my-image sda"
+ echo
+} # end of USAGE
+
+
+####################
+### Main program ###
+####################
+
+ocs_file="$0"
+ocs=`basename $ocs_file`
+#
+#
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -p|--prebuild_mbr)
+ restore_prebuild_mbr="yes"
+ shift;
+ ;;
+ -or|--ocsroot)
+ # overwrite the ocsroot in drbl.conf
+ shift;
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ ocsroot="$1"
+ shift;
+ fi
+ [ -z "$ocsroot" ] && USAGE && exit 1
+ ;;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+done
+
+target_dir="$1"
+shift
+target_hd="$*"
+
+# Fedora Core 1 seems to use dumb for rc1, we have to force it use linux.
+# otherwise setterm will complain.
+[ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="linux"
+echo "Setting the TERM as $TERM"
+export TERM="$TERM"
+
+#
+check_if_root
+ask_and_load_lang_set
+
+if [ -z "$target_dir" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No image was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+if [ -z "$target_hd" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No destination disk was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+#
+target_dir_fullpath="$ocsroot/$target_dir"
+
+for ihd in $target_hd; do
+ # No matter it's msdos partition table or GPT one, here we restore the MBR.
+ # If it's GPT format, this could make GPT one as "valid GPT with protective MBR",
+ # and it's still GPT format.
+ # Some OS (e.g. VMware ESXi 5.5.0) need protective MBR even it's GPT partition table.
+ # Ref:
+ # https://sourceforge.net/p/clonezilla/discussion/Clonezilla_live/thread/30662778/
+ # https://sourceforge.net/p/clonezilla/discussion/Clonezilla_live/thread/ca825570/
+
+ # Install MBR which displays a failure message on boot. This is for fault tolerance. If all the partitions are cloned successfully, the correcting MBR will be restored later. For more info, please check https://sourceforge.net/tracker/?func=detail&atid=671653&aid=2793248&group_id=115473
+ cat /usr/share/partclone/fail-mbr.bin > /dev/$ihd
+ if [ "$restore_prebuild_mbr" = "yes" ]; then
+ # For M$ Windows system, sometimes it will fail if we restore the mbr from the one we saved (Ex. hda-mbr). Another option is to use mbr.bin from syslinux
+ cat_cmd="cat $pxelinux_binsrc_dir/bios/mbr.bin > /dev/$ihd"
+ echo "Restoring the mbr.bin from syslinux to /dev/$ihd by:"
+ echo "$cmd_cmd"
+ eval $cat_cmd
+ echo "done."
+ else
+ dd_cmd="dd if=$target_dir_fullpath/$(to_filename ${ihd})-mbr of=/dev/$ihd bs=446 count=1 &>/dev/null"
+ echo "Restoring the first 446 bytes of MBR data (executable code area) for $ihd by:"
+ echo "$dd_cmd"
+ eval $dd_cmd
+ echo "done."
+ fi
+ echo $msg_delimiter_star_line
+done
diff --git a/draft/other-tools/clonezilla/ocs-sr b/draft/other-tools/clonezilla/ocs-sr
new file mode 100755
index 0000000..7ea1d9f
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-sr
@@ -0,0 +1,1465 @@
+#!/bin/bash
+#
+# License: GPL
+# Original author: Blake, Kuo-Lien Huang
+# Description:
+# 2003/04/11 the first version, only work on /dev/hda1 & PXE
+# 2003/06/01 disk to disk mode & etherboot support
+# (the etherboot lzdsk images are located in
+# /tftpboot/etherboot-5.0.7 after DRBLCD installed)
+# 2003/07/18 `checkInodeForDevice`
+#
+# Author: Steven Shiau <steven _at_ nchc org tw>
+# 2003/07/21 the first version for Redhat, modified from Blake's version,
+# only work on /dev/hda1 & PXE
+# 2004/02/04 add the multicast function
+# 2005/01/21 add code to save/restore some partitions (not entire disk).
+# 2005/11/06 Many thanks to Christian Treczoks for providing "dd skip=1" method
+# 2006/05/06 Remove save & restore hda1, since we can use save & restore partitions.
+# 2006/12/07 Rewrite drbl-ocs to drbl-ocs + ocs-sr + ocs-functions.
+
+# input parameters:
+# save/savedisk/saveparts/restore/restoredisk/restoreparts/multicast_restore/multicast_restoredisk IMAGE-NAME DEVICES
+
+# Notes:
+# task_restorexxx/savexxx function will always use $ocsroot (/home/partimag) as mount point to do the save/restore, so it might overwrite the /home/partimag by mounting $ocsroot from server:/home2 (for example).
+# The mount action is done in function task_preprocessing
+
+ocs_file="$0"
+ocs=`basename $ocs_file`
+ocs_myself_id="$$"
+# we need ocs_ppid for ocs-functions
+ocs_ppid="$PPID"
+# log file for sfdisk when restoring
+# RESTORE_SFDISK_LOG is loaded from drbl.conf
+
+# Some initial setting
+confirm_before_clone="no"
+ocs_sr_mode=""
+gen_md5sum="no"
+gen_sha1sum="no"
+check_md5sum="no"
+check_sha1sum="no"
+gen_chksum_for_files_in_dev="no"
+chk_chksum_for_files_in_dev="no"
+chk_img_restoreable_mod_save_def="yes"
+chk_img_restoreable_mod_restore_def="yes"
+# Flag to save restoring error log
+save_restore_error_log="no"
+# Flag to check target disk size before creating partition table
+chk_tgt_disk_size_bf_mk_pt="yes"
+# Flag to update EFI NVRAM after restoring a disk
+update_efi_nvram=""
+
+# Load DRBL setting and functions
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Load the config in ocs-live.conf. This is specially for Clonezilla live. It will overwrite some settings of /etc/drbl/drbl-ocs.conf, such as $DIA...
+[ -e "/etc/ocs/ocs-live.conf" ] && . /etc/ocs/ocs-live.conf
+
+# Fedora Core 1 seems to use dumb for rc1, we have to force it use linux.
+# otherwise setterm will complain.
+[ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="linux"
+echo "Setting the TERM as $TERM"
+export TERM="$TERM"
+
+#
+check_if_root
+
+#
+USAGE() {
+ echo "Usage:"
+ echo "To save or restore image"
+ echo "$ocs [OPTION] {savedisk|saveparts|restoredisk|restoreparts} IMAGE_NAME DEVICE"
+ echo
+ echo " Options for saving:"
+ USAGE_common_save
+ echo " -i, --image-size SIZE Set the split image file volume size SIZE (MB). When $ocs is run with -x, the default SIZE is set as $VOL_LIMIT_IN_INTERACTIVE, if without -x, we will not split it."
+ USAGE_reserved_word_for_save
+ echo
+ echo " Options for restoring:"
+ USAGE_common_restore
+ echo " --mcast-port NO Assign the udp port number for multicast restore. This is used by clonezilla server. Normally it's not necessary to manually assign this option."
+ USAGE_reserved_word_for_restore
+ echo
+ echo " General options:"
+ USAGE_common_general
+ dialog_like_prog_help_prompt
+ echo " -x, --interactive Interactive mode to save or restore."
+ echo
+ echo "Example:"
+ echo " To save or restore image in client (Only that DRBL client will join, and its local partitions is NOT mounted). NOTE!!! You should run the command in DRBL client or you have to make sure the target device is NOT busy!."
+ echo " To save all the data in local first IDE harddrive 'hda' as image 'IMAGE1', use ntfsclone instead of partimage, and lzop compression (NOTE!!! You should run the command in DRBL client or make sure hda is NOT busy/mounted!):"
+ echo " $ocs --use-ntfsclone -z3 savedisk IMAGE1 hda"
+ echo
+ echo " To save the data in first and second partitions in local first IDE harddrive 'hda' as image 'IMAGE2', use ntfsclone instead of partimage, and lzop compression (NOTE!!! You should run the command in DRBL client, or make sure hda is NOT busy/mounted!):"
+ echo " $ocs" '--use-ntfsclone -z3 saveparts IMAGE2 "hda1 hda2"'
+ echo
+ echo " To restore image "IMAGE1" to local hda. grub-install will be run after cloning (image IMAGE1 is already in DRBL server. NOTE!!! You should run the command in DRBL client or make sure hda is NOT busy/mounted!):"
+ echo " $ocs -g auto restoredisk IMAGE1 hda"
+ echo
+ echo " To restore image first and second partitions from "IMAGE2" to local hda1 and hda2. grub-install will be run after cloning (image IMAGE2 is already in DRBL server. NOTE!!! You should run the command in DRBL client or make sure hda is NOT busy/mounted!):"
+ echo " $ocs" '-g auto restoreparts IMAGE2 "hda1 hda2"'
+ echo
+ echo " To save disk(s)/partitition(s) as an image or restore an image to disk(s)/partitition(s) interactively, use:"
+ echo " $ocs -x"
+}
+#
+parse_ocs_sr_cmd_options_with_dash() {
+ # Parse command-line options
+ # It's UGLY to use "shift; n_shift=$((n_shift+1))"
+ # However, we want to reuse the parse_ocs_sr_cmd_options_with_dash,
+ # a problem here:
+ # The parameters (-b -g auto --nogui --max-time-to-wait 300 --language 0 multicast_restoreparts sarge-base "hda1 hda3" 2232), when put it as $*, it will
+ # become (-b -g auto --nogui --max-time-to-wait 300 --language 0 multicast_restoreparts sarge-base hda1 hda3 2232), you see, "hda1 hda3" -> hda1 hda3
+ # Then everyting is in a mess... so now the best solution I can find is to
+ # calculate the n_shift, then parse it to original shell, not in the function.
+
+ n_shift=0
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ -l|--language)
+ shift; n_shift=$((n_shift+1))
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ specified_lang="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$specified_lang" ] && USAGE && exit 1
+ ;;
+ -g|--grub-install)
+ install_grub="on"
+ shift; n_shift=$((n_shift+1))
+ # skip the -xx option, in case
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ grub_partition=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$grub_partition" ] && USAGE && exit 1
+ ;;
+ -f|--from-part-in-img)
+ shift; n_shift=$((n_shift+1))
+ # skip the -xx option, in case
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ source_part=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$source_part" ] && USAGE && exit 1
+ ;;
+ -a|--no-force-dma-on)
+ force_dma_on="no"
+ shift; n_shift=$((n_shift+1));;
+ -k|--no-fdisk|--no-create-partition)
+ create_part="no"
+ shift; n_shift=$((n_shift+1));;
+ -k1|--fdisk-proportion)
+ create_part="yes"
+ create_part_type="proportion"
+ shift; n_shift=$((n_shift+1));;
+ -k2|--fdisk-manual)
+ create_part="yes"
+ create_part_type="manual"
+ shift; n_shift=$((n_shift+1));;
+ -t|--no-restore-mbr)
+ restore_mbr="no"
+ shift; n_shift=$((n_shift+1));;
+ -t1|--restore-raw-mbr)
+ # The flag to restore syslinux mbr.bin to M$ windows system.
+ restore_prebuild_mbr="yes"
+ shift; n_shift=$((n_shift+1));;
+ -t2|--no-restore-ebr)
+ restore_ebr="no"
+ shift; n_shift=$((n_shift+1));;
+ -u|--select-img-in-client)
+ select_img_in_client="yes"
+ shift; n_shift=$((n_shift+1));;
+ -e|--load-geometry)
+ load_HD_CHS_from_img="yes"
+ shift; n_shift=$((n_shift+1));;
+ -e1|--change-geometry)
+ change_ntfs_boot_chs="on"
+ shift; n_shift=$((n_shift+1))
+ # skip the -xx option, in case
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ ntfs_boot_partition=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$ntfs_boot_partition" ] && USAGE && exit 1
+ ;;
+ -e2|--load-geometry-from-edd)
+ use_HD_CHS_from_EDD_pref="yes"
+ shift; n_shift=$((n_shift+1));;
+ -y|-y0|--always-restore|--always-restore-default-local)
+ always_restore="yes"
+ pxe_menu_default_mode="local"
+ shift; n_shift=$((n_shift+1));;
+ -y1|--always-restore-default-clone)
+ always_restore="yes"
+ pxe_menu_default_mode="clone"
+ shift; n_shift=$((n_shift+1));;
+ -y2|--always-restore-default-drbl)
+ always_restore="yes"
+ pxe_menu_default_mode="drbl"
+ shift; n_shift=$((n_shift+1));;
+ -c|--confirm)
+ confirm_before_clone="yes"
+ shift; n_shift=$((n_shift+1));;
+ -sc|-scs|--skip-check-restorable|--skip-check-restorable-s)
+ # Flag to check if the image is restorable
+ chk_img_restoreable_mod_save="no"
+ shift; n_shift=$((n_shift+1));;
+ -scr|--skip-check-restorable-r)
+ # Flag to check if the image is restorable
+ chk_img_restoreable_mod_restore="no"
+ shift; n_shift=$((n_shift+1));;
+ -srel|--save-restore-error-log)
+ # Flag to save restoring log
+ save_restore_error_log="yes"
+ shift; n_shift=$((n_shift+1));;
+ -w|--wait-time)
+ shift; n_shift=$((n_shift+1))
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ TIME_to_wait="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ ;;
+ --debug=?*)
+ debug_level=${1#--debug=}
+ shift; n_shift=$((n_shift+1));;
+ -b|-batch|--batch)
+ ocs_batch_mode="on"
+ shift; n_shift=$((n_shift+1));;
+ -d|--debug-mode)
+ debug_mode="on"
+ shift; n_shift=$((n_shift+1));;
+ -d0|--dialog)
+ DIA="dialog"
+ shift;;
+ -d1|--Xdialog)
+ DIA="Xdialog"
+ shift;;
+ -d2|--whiptail)
+ DIA="whiptail"
+ shift;;
+ -d3|--gdialog)
+ DIA="gdialog"
+ shift;;
+ -d4|--kdialog)
+ DIA="kdialog"
+ shift;;
+ -enc|--enc-ocs-img)
+ encrypt_ocs_img="yes"
+ shift; n_shift=$((n_shift+1));;
+ -senc|--skip-enc-ocs-img)
+ encrypt_ocs_img="no"
+ shift; n_shift=$((n_shift+1));;
+ -m|--module)
+ shift; n_shift=$((n_shift+1))
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ module_to_load=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$module_to_load" ] && USAGE && exit 1
+ ;;
+ -r|--resize-partition)
+ resize_partition="on"
+ shift; n_shift=$((n_shift+1));;
+ -v|--verbose)
+ verbose="on"
+ shift; n_shift=$((n_shift+1));;
+ -z0|--no-compress)
+ IMG_CLONE_CMP="cat"
+ shift; n_shift=$((n_shift+1));;
+ -z1|--gzip-compress)
+ IMG_CLONE_CMP="gzip -c $extra_gzip_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z1p|--smp-gzip-compress)
+ IMG_CLONE_CMP="pigz -c $extra_pigz_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z2|--bz2-compress)
+ IMG_CLONE_CMP="bzip2 -c $extra_bzip2_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z2p|--smp-bzip2-compress)
+ if [ "$parallel_bzip2_prog" = "pbzip2" ]; then
+ IMG_CLONE_CMP="pbzip2 -c $extra_pbzip2_opt"
+ elif [ "$parallel_bzip2_prog" = "lbzip2" ]; then
+ IMG_CLONE_CMP="lbzip2 -c $extra_lbzip2_opt"
+ fi
+ shift; n_shift=$((n_shift+1));;
+ -z3|--lzo-compress)
+ # Now only for ntfsclone, partimage not yet.
+ IMG_CLONE_CMP="lzop -c $extra_lzop_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z4|--lzma-compress)
+ IMG_CLONE_CMP="lzma -c $extra_lzma_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z5|--xz-compress)
+ IMG_CLONE_CMP="xz -c $extra_xz_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z5p|--smp-xz-compress)
+ IMG_CLONE_CMP="pixz $extra_pixz_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z6|--lzip-compress)
+ IMG_CLONE_CMP="lzip -c $extra_lzip_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z6p|--smp-lzip-compress)
+ IMG_CLONE_CMP="plzip -c $extra_plzip_opt"
+ shift; n_shift=$((n_shift+1));;
+ -z7|--lrzip-compress)
+ # The option for lrzip is different from that of gzip (not -c)
+ # Although lrzip uses "-p value Set processor count to override number of threads" to assign the CPU number, however, from the manual of lrzip:
+ # -p value
+ # Set the number of processor count to determine the number of
+ # threads to run. Normally lrzip will scale according to the num‐
+ # ber of CPUs it detects. Using this will override the value in
+ # case you wish to use less CPUs to either decrease the load on
+ # your machine, or to improve compression. Setting it to 1 will
+ # maximise compression but will not attempt to use more than one
+ # CPU.
+ # Therefore there is no need to assign a parallel version of lrzip.
+ IMG_CLONE_CMP="lrzip -q - $extra_lrzip_opt"
+ shift; n_shift=$((n_shift+1));;
+ -nogui|--nogui)
+ # -nogui is for backward compatable, better to use --nogui
+ nogui="on"
+ shift; n_shift=$((n_shift+1));;
+ -ntfs-ok|--ntfs-ok)
+ # if ntfs integrity is assumed OK, do not check
+ ntfs_integrity_check="no"
+ shift; n_shift=$((n_shift+1));;
+ -rm-win-swap-hib|--rm-win-swap-hib)
+ # Remove page and hibernation files in M$ windows
+ rm_win_swap_hib="yes"
+ shift; n_shift=$((n_shift+1));;
+ -rescue|--rescue)
+ rescue_mode="on"
+ shift; n_shift=$((n_shift+1));;
+ -sfsck|--skip-fsck-src-part)
+ fsck_src_part_intr="no"
+ fsck_src_part_auto="no"
+ shift; n_shift=$((n_shift+1));;
+ -fsck-src-part|--fsck-src-part|-fsck)
+ fsck_src_part_intr="yes"
+ shift; n_shift=$((n_shift+1));;
+ -fsck-src-part-y|--fsck-src-part-y|-fsck-y)
+ fsck_src_part_auto="yes"
+ shift; n_shift=$((n_shift+1));;
+ -mp|--mount-point)
+ shift; n_shift=$((n_shift+1));
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ mount_point=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$mount_point" ] && USAGE && exit 1
+ ;;
+ -or|--ocsroot)
+ # overwrite the ocsroot in drbl.conf
+ shift; n_shift=$((n_shift+1));
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ ocsroot="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$ocsroot" ] && USAGE && exit 1
+ ;;
+ -i|--image-size)
+ shift; n_shift=$((n_shift+1))
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ VOL_LIMIT=$1
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$VOL_LIMIT" ] && USAGE && exit 1
+ ;;
+ --max-time-to-wait)
+ # ocs-sr need to know the --max-time-to-wait so that when sleeping
+ # between partitions restoring clone won't timeout.
+ shift; n_shift=$((n_shift+1))
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ mcast_max_wait_time="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$mcast_max_wait_time" ] && USAGE && exit 1
+ ;;
+ -q|--use-ntfsclone)
+ USE_NTFSCLONE="yes"
+ shift; n_shift=$((n_shift+1));;
+ -q1|--force-to-use-dd)
+ FORCE_TO_USE_DD="yes"
+ shift; n_shift=$((n_shift+1));;
+ -q2|--use-partclone)
+ USE_PARTCLONE="yes"
+ shift; n_shift=$((n_shift+1));;
+ -j|--create-part-by-sfdisk)
+ # We leave this option for backward compatability.
+ create_part_by_sfdisk="yes"
+ shift; n_shift=$((n_shift+1));;
+ -j0|--create-part-by-dd)
+ create_part_by_sfdisk="no"
+ shift; n_shift=$((n_shift+1));;
+ -j1|--dump-mbr-in-the-end)
+ dump_mbr_in_the_end="yes"
+ shift; n_shift=$((n_shift+1));;
+ -j2|--clone-hidden-data)
+ clone_hidden_data="yes"
+ shift; n_shift=$((n_shift+1));;
+ -icrc|--icrc)
+ do_partclone_crc_check="no"
+ shift; n_shift=$((n_shift+1));;
+ -irvd|--irvd)
+ rm_ntfs_vol_dirty_flag="no"
+ shift; n_shift=$((n_shift+1));;
+ -irhr|--irhr)
+ do_rm_hardware_record="no"
+ shift; n_shift=$((n_shift+1));;
+ -ius|--ius)
+ do_update_syslinux="no"
+ shift; n_shift=$((n_shift+1));;
+ -hn0)
+ shift; n_shift=$((n_shift+1))
+ change_win_hostname="By_IP"
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ win_hostname_prefix="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$win_hostname_prefix" ] && USAGE && exit 1
+ ;;
+ -hn1)
+ shift; n_shift=$((n_shift+1))
+ change_win_hostname="By_MAC"
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ win_hostname_prefix="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$win_hostname_prefix" ] && USAGE && exit 1
+ ;;
+ -o|-o1|--run-postrun-dir)
+ # -o is for backward compatability
+ run_postrun_dir="yes"
+ shift; n_shift=$((n_shift+1));;
+ -o0|--run-prerun-dir)
+ run_prerun_dir="yes"
+ shift; n_shift=$((n_shift+1));;
+ -ns|--ntfs-progress-in-image-dir)
+ ntfsclone_progress="image_dir"
+ shift; n_shift=$((n_shift+1));;
+ -gm|--gen-md5sum)
+ gen_md5sum="yes"
+ shift; n_shift=$((n_shift+1));;
+ -gs|--gen-sha1sum)
+ gen_sha1sum="yes"
+ shift; n_shift=$((n_shift+1));;
+ -cm|--check-md5sum)
+ check_md5sum="yes"
+ shift; n_shift=$((n_shift+1));;
+ -cs|--check-sha1sum)
+ check_sha1sum="yes"
+ shift; n_shift=$((n_shift+1));;
+ -gmf|--gen-chksum-for-files-in-dev)
+ gen_chksum_for_files_in_dev="yes"
+ shift; n_shift=$((n_shift+1));;
+ -cmf|--chk-chksum-for-files-in-dev)
+ chk_chksum_for_files_in_dev="yes"
+ shift; n_shift=$((n_shift+1));;
+ -x|--interactive)
+ ocs_sr_mode="interactive"
+ shift; n_shift=$((n_shift+1));;
+ --mcast-port)
+ shift; n_shift=$((n_shift+1));
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ ocs_sr_mcast_port="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$ocs_sr_mcast_port" ] && USAGE && exit 1
+ ;;
+ -p|--postaction)
+ shift; n_shift=$((n_shift+1));
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ # skip the -xx option, in case
+ postaction="$1"
+ shift; n_shift=$((n_shift+1))
+ fi
+ [ -z "$postaction" ] && USAGE && exit 1
+ ;;
+ --restore-only)
+ ocs_x_mode="restore_only"
+ shift; n_shift=$((n_shift+1));;
+ --save-only)
+ ocs_x_mode="save_only"
+ shift; n_shift=$((n_shift+1));;
+ -um|--user-mode)
+ shift; n_shift=$((n_shift+1));
+ # skip the -xx option, in case
+ if [ -z "$(echo $1 |grep ^-.)" ]; then
+ ocs_user_mode="$1"
+ shift; n_shift=$((n_shift+1));
+ fi
+ [ -z "$ocs_user_mode" ] && USAGE && exit 1
+ ;;
+ -icds|--ignore-chk-dsk-size-pt)
+ chk_tgt_disk_size_bf_mk_pt="no"
+ shift; n_shift=$((n_shift+1));;
+ -iefi|--ignore-update-efi-nvram)
+ update_efi_nvram="no"
+ shift; n_shift=$((n_shift+1));;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+ done
+} # end of parse_ocs_sr_cmd_options_with_dash
+#
+save_only_dia_des() {
+ savedisk_msg_1="savedisk"
+ savedisk_msg_2="$(rep_whspc_w_udrsc "$msg_clonezilla_save_local_disk")"
+ saveparts_msg_1="saveparts"
+ saveparts_msg_2="$(rep_whspc_w_udrsc "$msg_clonezilla_save_local_parts")"
+}
+#
+restore_only_dia_des() {
+ restoredisk_msg_1="restoredisk"
+ restoredisk_msg_2="$(rep_whspc_w_udrsc "$msg_clonezilla_restore_local_disk")"
+ restoreparts_msg_1="restoreparts"
+ restoreparts_msg_2="$(rep_whspc_w_udrsc "$msg_clonezilla_restore_local_parts")"
+}
+recovery_clonezilla_live_dia_des() {
+ recovery_clonezilla_live_msg_1="recovery-iso-zip"
+ recovery_clonezilla_live_msg_2="$(rep_whspc_w_udrsc "$msg_recovery_clonezilla_live")"
+}
+chk_img_restorable_dia_des() {
+ chk_img_restorable_msg_1="chk-img-restorable"
+ chk_img_restorable_msg_2="$(rep_whspc_w_udrsc "$msg_check_if_image_restorable")"
+}
+convert_img_compression_dia_des() {
+ convert_img_compression_msg_1="cvt-img-compression"
+ convert_img_compression_msg_2="$(rep_whspc_w_udrsc "$msg_convert_img_compression")"
+}
+encrypt_img_dia_des() {
+ encrypt_img_msg_1="encrypt-img"
+ encrypt_img_msg_2="$(rep_whspc_w_udrsc "$msg_encrypt_existing_img")"
+}
+decrypt_img_dia_des() {
+ decrypt_img_msg_1="decrypt-img"
+ decrypt_img_msg_2="$(rep_whspc_w_udrsc "$msg_decrypt_existing_img")"
+}
+p2v_img_dia_des() {
+ p2v_img_msg_1="p2v-img"
+ p2v_img_msg_2="$(rep_whspc_w_udrsc "$msg_p2v_existing_img")"
+}
+one_image_to_multiple_disks_dia_des() {
+ one_2_m_disks_msg_1="1-2-mdisks"
+ one_2_m_disks_msg_2="$(rep_whspc_w_udrsc "$msg_restore_1_image_to_multiple_local_disks")"
+}
+# functions to process options.
+wrap_up_opt() {
+ [ -z "$VOL_LIMIT" ] && VOL_LIMIT=$VOL_LIMIT_DEFAULT
+
+ # change to other mount point for extra harddisk
+ # Note: functions get_existing_disk_image, get_existing_parts_image and get_existing_partitions_from_img will use $imagedir
+ if [ -n "$mount_point" ]; then
+ echo "Option -mp|--mount-point is assigned."
+ echo "Using the image root directory $mount_point instead of $ocsroot."
+ imagedir="$mount_point"
+ else
+ imagedir="$ocsroot"
+ fi
+
+ check_ocs_input_params
+
+ # Set/Reset init values
+ PARTIMAGE_SAVE_OPT="$PARTIMAGE_SAVE_OPT_INIT --debug=$debug_level"
+ PARTIMAGE_RESTORE_OPT="$PARTIMAGE_RESTORE_OPT_INIT --debug=$debug_level"
+ PARTCLONE_SAVE_OPT="$PARTCLONE_SAVE_OPT_INIT"
+ PARTCLONE_RESTORE_OPT="$PARTCLONE_RESTORE_OPT_INIT"
+ if [ "$nogui" = "on" ]; then
+ # Partimage default uses TUI, if noguid, we have to run it with -B gui=no
+ PARTIMAGE_SAVE_OPT="$PARTIMAGE_SAVE_OPT -B gui=no"
+ PARTIMAGE_RESTORE_OPT="$PARTIMAGE_RESTORE_OPT -B gui=no"
+ fi
+ if [ "$nogui" = "off" ]; then
+ # TUI is on.
+ # Use the TUI mode for partclone (i.e. run with -N, otherwise by default partclone runs only text output)
+ # //NOTE// From Partclone 0.2.52, if -N is set for partclone in save mode, the ncurse interface is able to be shown in stderr.
+ PARTCLONE_SAVE_OPT="$PARTCLONE_SAVE_OPT -N"
+ PARTCLONE_RESTORE_OPT="$PARTCLONE_RESTORE_OPT_INIT -N"
+ fi
+ if [ "$rescue_mode" = "on" ]; then
+ PARTCLONE_SAVE_OPT="$PARTCLONE_SAVE_OPT --rescue"
+ fi
+ if [ "$do_partclone_crc_check" = "no" ]; then
+ PARTCLONE_RESTORE_OPT="$PARTCLONE_RESTORE_OPT --ignore_crc"
+ fi
+
+ echo $msg_delimiter_star_line
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ [ "$create_part" = "no" ] && echo "$msg_do_not_create_part"
+ [ "$restore_mbr" = "no" ] && echo "$msg_do_not_restore_mbr"
+ [ "$select_img_in_client" = "yes" ] && echo "$msg_you_have_to_input_image_names_in_client"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+
+ # Append postaction, since we did not ask that in set_ocs_sr_extra_param and we might already set that.
+ if [ -n "$postaction" -a \
+ -z "$(echo $OCS_OPTS | grep -Ewo -- "-p")" ]
+ then
+ OCS_OPTS="$OCS_OPTS -p $postaction"
+ fi
+ if [ "$verbose" = "on" ]; then
+ PARTCLONE_SAVE_OPT="$PARTCLONE_SAVE_OPT -d"
+ PARTCLONE_RESTORE_OPT="$PARTCLONE_RESTORE_OPT -d"
+ echo "OCS_OPTS: $OCS_OPTS"
+ echo "PARTIMAGE_SAVE_OPT: $PARTIMAGE_SAVE_OPT"
+ echo "PARTIMAGE_RESTORE_OPT: $PARTIMAGE_RESTORE_OPT"
+ echo "PARTCLONE_SAVE_OPT: $PARTCLONE_SAVE_OPT"
+ echo "PARTCLONE_RESTORE_OPT: $PARTCLONE_RESTORE_OPT"
+ # The default output for udpcast stderr is surpressed, now turn it on
+ udpcast_stderr="/dev/stderr"
+ fi
+ # If VOL_LIMIT is too large, split won't work. Check and fix it if required.
+ check_and_fix_vol_limit_if_required
+} # end of wrap_up_opt
+#
+wrap_up_opt_after_interactive_selection() {
+ wrap_up_opt
+ # For case when interactive mode the option "-scr" or "-scs" is used.
+ # i.e. command like: "ocs-sr -x -scr" or "ocs-sr -x "-scs"
+ if [ -z "$chk_img_restoreable_mod_save" ]; then
+ chk_img_restoreable_mod_save="$chk_img_restoreable_mod_save_def"
+ fi
+ if [ -z "$chk_img_restoreable_mod_restore" ]; then
+ chk_img_restoreable_mod_restore="$chk_img_restoreable_mod_restore_def"
+ fi
+ # Shall we set default postaction if empty here?
+ #[ -z "$postaction" ] && postaction="$POSTACTION_DEF"
+
+} # end of wrap_up_opt_after_interactive_selection
+#
+run_ocs_sr_again_prompt() {
+ local img dev
+ # OCS_OPTS is a global variable
+ img="$1"
+ dev="$2"
+ if [ "$ocs_sr_mode" = "interactive" ]; then
+ run_again_fname="/tmp/ocs-$img-`date +%F-%H-%M`"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+ echo PS. $msg_run_drbl_ocs_again_cmd | tee --append ${OCS_LOGFILE}
+ echo $0 $OCS_OPTS $ocs_sr_type $img $dev >> ${OCS_LOGFILE}
+ echo $0 $OCS_OPTS $ocs_sr_type $img $dev | tee $run_again_fname
+ echo "$msg_ocs_sr_again_command_saved_filename: $run_again_fname"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ [ -e "$run_again_fname" ] && chmod 755 $run_again_fname
+ echo $msg_delimiter_star_line | tee --append ${OCS_LOGFILE}
+ if [ "$ocs_batch_mode" != "on" ]; then
+ echo -n "$msg_press_enter_to_continue "
+ read
+ fi
+ fi
+} # end of run_ocs_sr_again_prompt
+#
+save_ocs_sr_related_vars() {
+ # Function to save ocs-related variables so that some customized program can use.
+ # The old one will be overwritten
+ mkdir -p /var/lib/clonezilla/
+ echo "ocs_cmd=\"$ocs\"" > /var/lib/clonezilla/ocs-vars
+ echo "target_dir=\"$target_dir\"" >> /var/lib/clonezilla/ocs-vars
+ echo "target_hd=\"$target_hd\"" >> /var/lib/clonezilla/ocs-vars
+ echo "postaction=\"$postaction\"" >> /var/lib/clonezilla/ocs-vars
+ echo "ocs_sr_mode=\"$ocs_sr_mode\"" >> /var/lib/clonezilla/ocs-vars
+} # end of save_ocs_related_var
+#
+create_clonezilla_live_recovery_iso_zip() {
+ # Target command Ex:
+ # ocs-iso -g en -t -k NONE -e "-b -c restoredisk sarge-r5 hda" sarge-r5
+ # ocs-live-dev -c -g en -t -k NONE -e "-b -c restoredisk sarge-r5 hda" sarge-r5
+ local REC_TMP ans_
+ REC_TMP=`mktemp /tmp/ocs_recovery_tmp.XXXXXX`
+ trap "[ -f "$REC_TMP" ] && rm -f $REC_TMP" HUP INT QUIT TERM EXIT
+
+ # Ask image name first (disk or parts image)
+ if [ "$ocs_sr_img_name" = "ask_user" ]; then
+ # Since get_target_dir_name_when_restoring_parts can search disk and parts image, we use this function instead of get_target_dir_name_when_restoring_disk
+ get_target_dir_name_when_restoring_parts # get $target_dir
+ else
+ target_dir="$ocs_sr_img_name"
+ fi
+ check_input_target_image "$ocsroot/$target_dir"
+ # Check if the image is disk or parts
+ if [ -e "$ocsroot/$target_dir/disk" ]; then
+ rec_dev_action=restoredisk
+ else
+ rec_dev_action=restoreparts
+ fi
+
+ # ask target disk/parts
+ case "$rec_dev_action" in
+ "restoredisk")
+ dev_prompt_and_example="$msg_input_device_name_for_recovery_iso_zip ($msg_ex: 'hda' $msg_or 'sda' $msg_or 'hda hdb' $msg_or 'sda sdb') \n$msg_linux_disk_MS_mapping\n$msg_prompt_to_use_ask_user_for_later_choose"
+ # savedisk_preset is borrowed from drbl-ocs.conf
+ dev_preset="$(get_disk_list_from_img $ocsroot/$target_dir)"
+ ;;
+ "restoreparts")
+ dev_prompt_and_example="$msg_input_device_name_for_recovery_iso_zip ($msg_ex: 'hda1 hda2' $msg_or 'sda1 sda2') \n$msg_linux_parts_MS_mapping\n$msg_prompt_to_use_ask_user_for_later_choose"
+ # saveparts_preset is borrowed from drbl-ocs.conf
+ dev_preset="$(get_parts_list_from_img $ocsroot/$target_dir)"
+ ;;
+ esac
+ ASK_DEV_NAME=1
+ while [ "$ASK_DEV_NAME" -ne 0 ]; do
+ $DIA --backtitle "$msg_nchc_free_software_labs" --title "$msg_nchc_clonezilla | $msg_mode: $ocs_mode_prompt" \
+ --inputbox "$dev_prompt_and_example" 0 0 "$dev_preset" 2> $REC_TMP
+ rec_dev_name="$(cat $REC_TMP)"
+ if [ -z "$rec_dev_name" ]; then
+ $DIA --backtitle "$msg_nchc_free_software_labs" --title "$msg_nchc_clonezilla" \
+ --yesno "$msg_you_must_input_device_name_to_be_restored! $msg_do_u_want_to_do_it_again" 0 0
+ ans_="$?"
+ case "$ans_" in
+ 0) # yes is chosen
+ ASK_DEV_NAME=1;;
+ 1) # no is chosen
+ echo "$msg_program_stop!"
+ [ -f "$REC_TMP" ] && rm -f $REC_TMP
+ exit 1;;
+ esac
+ else
+ ASK_DEV_NAME=0
+ fi
+ done
+ echo > $REC_TMP # clean REC_TMP
+
+ # ask if want to set ocs extra param for recovery iso/zip
+ set_ocs_sr_extra_param restore $REC_TMP $ocs_sr_type
+ OCS_OPTS="$(cat $REC_TMP)"
+ parse_ocs_sr_cmd_options_with_dash $OCS_OPTS
+ OCS_OPTS="$(echo $OCS_OPTS)" # make it in a line
+ echo > $REC_TMP # clean REC_TMP
+
+ # Ask language to be used in live iso/zip
+ # $DRBL_SCRIPT_PATH/lang/bash/$lang
+ get_existing_language $REC_TMP
+ rec_lang="$(cat $REC_TMP)"
+
+ # Ask keymap
+ ASK_KEYMAP_FILE=1
+ while [ "$ASK_KEYMAP_FILE" -ne 0 ]; do
+ $DIA --backtitle "$msg_nchc_free_software_labs" --title "$msg_nchc_clonezilla | $msg_mode: $ocs_mode_prompt" \
+ --inputbox "$keymap_file_prompt_and_example" 0 0 "NONE" 2> $REC_TMP
+ rec_keymap_file="$(cat $REC_TMP)"
+ if [ -z "$rec_keymap_file" ]; then
+ $DIA --backtitle "$msg_nchc_free_software_labs" --title "$msg_nchc_clonezilla | $msg_mode: $ocs_mode_prompt" \
+ --yesno "$msg_you_must_input_keymap_file! $msg_do_u_want_to_do_it_again" 0 0
+ ans_="$?"
+ case "$ans_" in
+ 0) # yes is chosen
+ ASK_KEYMAP_FILE=1;;
+ 1) # no is chosen
+ echo "$msg_program_stop!"
+ [ -f "$REC_TMP" ] && rm -f $REC_TMP
+ exit 1;;
+ esac
+ else
+ ASK_KEYMAP_FILE=0
+ fi
+ done
+ echo > $REC_TMP # clean REC_TMP
+
+ # Generage iso, zip or both ?
+ $DIA --backtitle "$msg_nchc_free_software_labs" --title "$msg_nchc_clonezilla | $msg_mode: $ocs_mode_prompt" \
+ --menu "$msg_recovery_clonezilla_file_type $msg_choose_file_type" \
+ 0 0 0 \
+ "iso" "$msg_create_recovery_clonezilla_live_iso" \
+ "zip" "$msg_create_recovery_clonezilla_live_zip" \
+ "both" "$msg_create_recovery_clonezilla_live_iso_and_zip" \
+ 2> $REC_TMP
+ rec_file_type="$(cat $REC_TMP)"
+
+ [ -f "$REC_TMP" ] && rm -f $REC_TMP
+
+ # Run ocs-iso/ocs-live-dev
+ # Ex:ocs-iso -g en -t -k NONE -e "-b -c restoredisk sarge-r5 hda" sarge-r5
+ # ocs-live-dev -c -g en -t -k NONE -e "-b -c restoredisk sarge-r5 hda" sarge-r5
+ (cd $ocsroot
+ case "$rec_file_type" in
+ iso)
+ run_again_fname="/tmp/ocs-iso-zip-`date +%F-%H-%M`"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+ echo PS. $msg_run_drbl_ocs_again_cmd | tee --append ${OCS_LOGFILE}
+ echo ocs-iso -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir >> ${OCS_LOGFILE}
+ echo ocs-iso -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir | tee $run_again_fname
+ [ -e "$run_again_fname" ] && chmod 755 $run_again_fname
+ echo "$msg_ocs_sr_again_command_saved_filename: $run_again_fname"
+ echo "$msg_the_output_file_is_in_dir: $ocsroot"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_press_enter_to_continue"
+ read
+ ocs-iso -g $rec_lang -t -k $rec_keymap_file -e "$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name" $target_dir
+ ;;
+ zip)
+ run_again_fname="/tmp/ocs-iso-zip-`date +%F-%H-%M`"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+ echo PS. $msg_run_drbl_ocs_again_cmd | tee --append ${OCS_LOGFILE}
+ echo ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir >> ${OCS_LOGFILE}
+ echo ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir | tee $run_again_fname
+ [ -e "$run_again_fname" ] && chmod 755 $run_again_fname
+ echo "$msg_ocs_sr_again_command_saved_filename: $run_again_fname"
+ echo "$msg_the_output_file_is_in_dir: $ocsroot"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_press_enter_to_continue"
+ read
+ ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e "$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name" $target_dir
+ ;;
+ both)
+ run_again_fname="/tmp/ocs-iso-zip-`date +%F-%H-%M`"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+ echo PS. $msg_run_drbl_ocs_again_cmd | tee --append ${OCS_LOGFILE}
+ echo ocs-iso -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir >> ${OCS_LOGFILE}
+ echo ocs-iso -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir | tee $run_again_fname
+ echo ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir >> ${OCS_LOGFILE}
+ echo ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e \"$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name\" $target_dir | tee -a $run_again_fname
+ [ -e "$run_again_fname" ] && chmod 755 $run_again_fname
+ echo "$msg_ocs_sr_again_command_saved_filename: $run_again_fname"
+ echo "$msg_the_output_file_is_in_dir: $ocsroot"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_press_enter_to_continue"
+ read
+ ocs-iso -g $rec_lang -t -k $rec_keymap_file -e "$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name" $target_dir
+ ocs-live-dev -c -g $rec_lang -t -k $rec_keymap_file -e "$OCS_OPTS $rec_dev_action $target_dir $rec_dev_name" $target_dir
+ ;;
+ esac
+ )
+} # end of create_clonezilla_live_recovery_iso_zip
+#
+get_extra_param_when_type_is_ask_user_and_interactive_mode() {
+ if [ "$ocs_sr_type_assign" = "ask_user" -o \
+ "$ocs_sr_mode" = "interactive" ]; then
+ # since this ocs-sr asks for ocs_sr type, this means the option maybe not parsed.
+ case "$ocs_sr_type" in
+ save*)
+ # ask if want to set ocs extra param
+ OCS_PARAM_TMP=`mktemp /tmp/ocs_sr_param_tmp.XXXXXX`
+ trap "[ -f "$OCS_PARAM_TMP" ] && rm -f $OCS_PARAM_TMP" HUP INT QUIT TERM EXIT
+ set_ocs_sr_extra_param save $OCS_PARAM_TMP $ocs_sr_type
+ # In interactive mode, we reset OCS_OPTS instead of appending it. Later wrap_up_opt will process more.
+ OCS_OPTS="$(cat $OCS_PARAM_TMP)"
+ [ -f "$OCS_PARAM_TMP" ] && rm -f $OCS_PARAM_TMP
+ ;;
+ restore*)
+ # Skip the multicast_restore*, since it's spawned by drbl-ocs, not from ocs-sr
+ # ask if want to set ocs extra param
+ OCS_PARAM_TMP=`mktemp /tmp/ocs_sr_param_tmp.XXXXXX`
+ trap "[ -f "$OCS_PARAM_TMP" ] && rm -f $OCS_PARAM_TMP" HUP INT QUIT TERM EXIT
+ set_ocs_sr_extra_param restore $OCS_PARAM_TMP $ocs_sr_type
+ # In interactive mode, we reset OCS_OPTS instead of appending it. Later wrap_up_opt will process more.
+ OCS_OPTS="$(cat $OCS_PARAM_TMP)"
+ [ -f "$OCS_PARAM_TMP" ] && rm -f $OCS_PARAM_TMP
+ ;;
+ exit)
+ echo "To use it again, run \"$ocs -x\"."
+ exit 2
+ ;;
+ esac
+ # Some options might be assigned in in /etc/ocs/ocs-live.conf. Here we have to add that.
+ if [ -n "$ocs_sr_save_extra_opt" -o -n "$ocs_sr_restore_extra_opt" ]; then
+ case "$ocs_sr_type" in
+ *save*) OCS_OPTS="$OCS_OPTS $ocs_sr_save_extra_opt" ;;
+ *restore*) OCS_OPTS="$OCS_OPTS $ocs_sr_restore_extra_opt" ;;
+ esac
+ fi
+ parse_ocs_sr_cmd_options_with_dash $OCS_OPTS
+ fi
+} # end of get_extra_param_when_type_is_ask_user_and_interactive_mode
+
+# OCS_OPT is for drbl-ocs using, will not put into the partimage command options
+# PARTIMAGE_RESTORE_OPT & PARTIMAGE_SAVE_OPT will put into partimage command options
+PARTIMAGE_SAVE_OPT_INIT=""
+PARTIMAGE_RESTORE_OPT_INIT=""
+OCS_OPT=""
+report_msg=""
+# Set some default values,
+nfs_restart="no"
+always_restore="no"
+pxe_menu_default_mode=""
+mcast_loop="1"
+USE_NTFSCLONE="no"
+nogui="off" # Default to turn on TUI
+FORCE_TO_USE_DD="no"
+force_dma_on="yes"
+create_part="yes"
+restore_mbr="yes"
+restore_ebr="yes"
+restore_prebuild_mbr="no"
+rm_win_swap_hib="no"
+rescue_mode="off"
+select_img_in_client="no"
+# If create_part_by_sfdisk=no, then we will use "dd if=$tgt_dir/mbr of=$sfdisk_target_hd skip=446 seek=446 bs=1 count=66" to dump the partition table.
+create_part_by_sfdisk="yes"
+# we want to make sfdisk --force if sfdisk is used.
+sfdisk_opt="--force"
+# Normally we do not dump MBR again when everything is done. However, This is an insurance for some hard drive has different numbers of cylinder, head and sector between image was saved and restored.". If the option is "yes", we will use dd to dump the MBR (total 512 Bytes, i.e. 446 bytes (executable code area) + 64 bytes (table of primary partitions) + 2 bytes (MBR signature; # 0xAA55) = 512 bytes) after disk was restored.
+dump_mbr_in_the_end="no"
+# The flag to save or restore the hidden data between MBR and 1st partition.
+clone_hidden_data="no"
+# default output for udpcast stderr is surpressed.
+# NOTE! Do not redirect it to standard output (stdin), otherwise partimage/ntfsclone pipe will get wrong image!
+udpcast_stderr="/dev/null"
+# default not to run those scripts in $OCS_PRERUN_DIR $OCS_POSTRUN_DIR
+run_prerun_dir="no"
+run_postrun_dir="no"
+# default to put the ntfsclone progress in local /tmp/ (tmpfs)
+ntfsclone_progress="local_tmp"
+# Default to do CRC checking of partclone when restoring
+do_partclone_crc_check="yes"
+# Default to remove the Linux udev MAC address records on the restored GNU/Linux
+do_rm_hardware_record="yes"
+# Default to run ocs-update-syslinux to update the syslinux files (ldlinux.sys, *.c32 and *.bin)
+do_update_syslinux="yes"
+# Default not to put yes or no for encrypting the image dir
+encrypt_ocs_img=""
+# Default to remove the ntfs volume dirty flag after it's restored.
+rm_ntfs_vol_dirty_flag="yes"
+
+# The parameters, example:
+# (-b -g auto --nogui --max-time-to-wait 300 --language 0 multicast_restoreparts sarge-base "hda1 hda3" 2232) ->
+# (multicast_restoreparts sarge-base "hda1 hda3" 2232)
+parse_ocs_sr_cmd_options_with_dash $*
+shift ${n_shift}
+ocs_sr_type_assign="$1"
+ocs_sr_img_name="$2"
+shift 2
+ocs_sr_dev="$*"
+# If the inputted dev is: "hda hdb", convert it to hda hdb (so it won't be ""hda hdb"")
+ocs_sr_dev="$(echo $ocs_sr_dev | tr -d \")"
+
+# Rotate the log file
+ocs_log_rotate $OCS_LOGFILE
+ocs_log_rotate /var/log/partclone.log
+
+#
+echo "Starting $0 at "$(LC_ALL=C date +%F' '%T' '%Z)"..." | tee --append ${OCS_LOGFILE}
+
+#
+ask_and_load_lang_set $specified_lang
+
+# check DIA
+check_DIA_set_ESC $DIA
+
+##############
+#### MAIN ####
+##############
+
+# ocs root
+if [ ! -d "$ocsroot" ]; then
+ echo "Please make sure your $ocsroot is a directory!!!"
+ # The common error is user try to create a ocsroot as /home/partimage, the default is /home/partimag (without e)
+ if [ "$ocsroot" = "/home/partimag" -a -d "/home/partimage" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "$msg_home_partimag_not_home_partimage"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ echo "We can NOT go on! Press \"c\" to enter command prompt or any other key to quit the program..."
+ read fail_answer
+ case "$fail_answer" in
+ [cC]) sulogin ;;
+ *) exit 1 ;;
+ esac
+fi
+
+#
+if [ "$ocs_sr_type_assign" = "ask_user" -o \
+ "$ocs_sr_mode" = "interactive" ]; then
+ ASK_OCS_SR_TYPE=1
+ case "$ocs_x_mode" in
+ "save_only")
+ save_only_dia_des
+ ;;
+ "restore_only")
+ restore_only_dia_des
+ ;;
+ *) # Both when image exists, or only save menu
+ save_only_dia_des
+ if check_if_any_image_exists; then
+ restore_only_dia_des
+ fi
+ ;;
+ esac
+ if [ "$ocs_sr_extra_restore_mode" != "no" ]; then
+ # If there is any image in $ocsroot, we can create recovery clonezilla live iso/zip and check the image.
+ if check_if_any_image_exists; then
+ recovery_clonezilla_live_dia_des
+ chk_img_restorable_dia_des
+ one_image_to_multiple_disks_dia_des
+ convert_img_compression_dia_des
+ encrypt_img_dia_des
+ decrypt_img_dia_des
+ if type qemu-img &>/dev/null && type kvm &>/dev/null; then
+ p2v_img_dia_des
+ fi
+ fi
+ fi
+
+ #
+ [ -z "$ocs_user_mode" ] && ask_if_beginner_or_expert_mode
+
+ # Clean the previous saved env so if ocs-onthefly is cancelled, won't read the previous env and reboot/poweroff.
+ rm -f /var/lib/clonezilla/ocs-vars
+
+ #
+ echo "Choose the mode for ocs-sr"
+ TMP="$(mktemp /tmp/menu-ocs.XXXXXX)"
+ trap "[ -f "$TMP" ] && rm -f $TMP" HUP INT QUIT TERM EXIT
+ while [ "$ASK_OCS_SR_TYPE" -ne 0 ]; do
+ $DIA --backtitle "$msg_nchc_free_software_labs" \
+ --title "$msg_nchc_clonezilla: $msg_choose_mode" \
+ --menu "$msg_clonezilla_is_free_and_no_warranty\n$msg_overwrite_data_on_disk_when_restoring\n$msg_hint_multiple_choice_select_by_space\n$msg_choose_mode_ocs_sr" \
+ 0 0 0 \
+ $savedisk_msg_1 $savedisk_msg_2 \
+ $saveparts_msg_1 $saveparts_msg_2 \
+ $restoredisk_msg_1 $restoredisk_msg_2 \
+ $restoreparts_msg_1 $restoreparts_msg_2 \
+ $one_2_m_disks_msg_1 $one_2_m_disks_msg_2 \
+ $recovery_clonezilla_live_msg_1 $recovery_clonezilla_live_msg_2 \
+ $chk_img_restorable_msg_1 $chk_img_restorable_msg_2 \
+ $convert_img_compression_msg_1 $convert_img_compression_msg_2 \
+ $encrypt_img_msg_1 $encrypt_img_msg_2 \
+ $decrypt_img_msg_1 $decrypt_img_msg_2 \
+ $p2v_img_msg_1 $p2v_img_msg_2 \
+ "exit" "$msg_exit. $msg_enter_cml" \
+ 2> $TMP
+ ocs_sr_type="$(cat $TMP)"
+ if [ -z "$ocs_sr_type" ]; then
+ ASK_OCS_SR_TYPE=1
+ else
+ ASK_OCS_SR_TYPE=0
+ fi
+ done
+ [ -e "$TMP" ] && rm -f $TMP
+ [ "$ocs_sr_type" = "exit" ] && exit 0
+ [ -z "$ocs_sr_type" ] && echo "You must specify the action! Program terminated!!!" && exit 1
+ # If ocs_sr_type from ask_user, then we should let ocs_sr_img_name & ocs_sr_dev as ask_user, too
+ ocs_sr_img_name="ask_user"
+ ocs_sr_dev="ask_user"
+ # Overwrite the default HALT_REBOOT_OPT (-f -n) so that if user choose to halt/reboot, it will use normal halt/reboot sequence, then mounted device will be unmounted.
+ HALT_REBOOT_OPT=""
+ VOL_LIMIT="$VOL_LIMIT_IN_INTERACTIVE"
+else
+ ocs_sr_type="$ocs_sr_type_assign"
+fi
+
+# ocs_mode_prompt is to be shown in the title of dialog menu later
+ocs_mode_prompt="$ocs_sr_type"
+
+echo $msg_delimiter_star_line | tee --append $OCS_LOGFILE
+# Clonezilla image home
+[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+echo "Clonezilla image dir: $ocsroot" | tee --append $OCS_LOGFILE
+[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+[ ! -d "$ocsroot" ] && mkdir -p $ocsroot
+
+# Some options might be assigned in in /etc/ocs/ocs-live.conf. Here we have to add that.
+if [ -n "$ocs_sr_save_extra_opt" -o -n "$ocs_sr_restore_extra_opt" ]; then
+ case "$ocs_sr_type" in
+ *save*) OCS_OPTS="$OCS_OPTS $ocs_sr_save_extra_opt" ;;
+ *restore*) OCS_OPTS="$OCS_OPTS $ocs_sr_restore_extra_opt" ;;
+ esac
+ parse_ocs_sr_cmd_options_with_dash $OCS_OPTS
+fi
+
+# Decide the mode for update_efi_nvram if it's not assigned. The EFI NVRAM is only updated when the mode is restoredisk or multicast_restoredisk
+if [ -z "$update_efi_nvram" ]; then
+ case "$ocs_sr_type" in
+ *restoredisk) update_efi_nvram="yes";;
+ *) update_efi_nvram="no";;
+ esac
+fi
+
+# Process options. //NOTE// There might be twice of wrap_up_opt, one is for the command options assigned, the other one is the command options got from interactive mode.
+wrap_up_opt
+
+# Before starting, we turn off swap and LVM2, unlock the busy partitions.
+turn_off_swap_and_LVM2
+
+# Boot parameter ocs_overwrite_postaction has higher priority than the action assigned by option "-p".
+overwrite_postaction_if_assigned $ocs_sr_type
+
+#
+case "$ocs_sr_type" in
+ "savedisk")
+ task_preprocessing "$ocs_sr_type"
+ MULTIPATH_INFODIR="$(mktemp -d /tmp/multipath_info.XXXXXX)"
+
+ if [ "$ocs_sr_img_name" = "ask_user" ]; then
+ get_target_dir_name_when_saving # get $target_dir
+ elif [ "$ocs_sr_img_name" = "autoname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/799287/topic/4815557
+ # We need something unique, so MAC address is a good choice
+ for i in `LC_ALL=C get-nic-devs`; do
+ prefix_mac="$(LC_ALL=C drbl-get-macadd $i)"
+ if [ -n "$prefix_mac" ]; then
+ prefix_mac="$(LC_ALL=C echo $prefix_mac | sed -e 's/://g')"
+ break
+ fi
+ done
+ # If not found, use UUID from MB manufacture
+ [ -z "$prefix_mac" ] && prefix_mac="$(LC_ALL=C dmidecode | grep -io "UUID: .*$" | head -n 1 | sed -e "s/^UUID: //g")"
+ target_dir="${prefix_mac}-$(LC_ALL=C date '+%Y-%m-%d-%H%M')-img"
+ elif [ "$ocs_sr_img_name" = "autohostname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ ip=""
+ for i in `LC_ALL=C get-nic-devs`; do
+ ip="$(drbl-get-ipadd $i)"
+ if [ -n "$ip" ]; then
+ break
+ fi
+ done
+ # If not found, give it a default name based on time.
+ if [ -z "ip" ]; then
+ prefix_host="autohostname-$(LC_ALL=C date '+%Y-%m-%d-%H%M')"
+ else
+ if LC_ALL=C host $ip &>/dev/null; then
+ # FQDN found
+ prefix_host="$(LC_ALL=C host $ip | sed -r -e "s/^.*name pointer//g" -e "s/^[[:space:]]*//g" -e "s|\.$||g")"
+ prefix_host="${prefix_host}-$(LC_ALL=C date '+%Y-%m-%d-%H%M')"
+ else
+ # FQDN not found. Give it a default name based on IP address and time.
+ prefix_host="autohostname-${ip}-$(LC_ALL=C date '+%Y-%m-%d-%H%M')"
+ fi
+ fi
+ target_dir="${prefix_host}-img"
+ elif [ "$ocs_sr_img_name" = "autoproductname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ target_dir="$(get_vendor_product_name)-img"
+ else
+ target_dir="$ocs_sr_img_name"
+ fi
+
+ if [ "$ocs_sr_dev" = "ask_user" ]; then
+ # To get $target_hd
+ get_target_hd_name_from_local_machine "$msg_local_source_disk \n$msg_linux_disk_naming $msg_press_space_to_mark_selection"
+ target_hd="$(select_VG "$target_hd")"
+ elif [ "$ocs_sr_dev" = "all" ]; then
+ get_not_busy_disks_or_parts harddisk "" "" # we will get dev_list
+ target_hd="$dev_list"
+ else
+ target_hd="$ocs_sr_dev"
+ fi
+ # check if the device exists
+ ANS_TMP=`mktemp /tmp/ocs_chkdev.XXXXXX`
+ trap "[ -f "$ANS_TMP" ] && rm -f $ANS_TMP" HUP INT QUIT TERM EXIT
+ check_if_input_device_exist $ANS_TMP $target_hd
+ target_hd="$(cat $ANS_TMP | tr -d \")"
+ [ -f "$ANS_TMP" ] && rm -f $ANS_TMP
+ get_extra_param_when_type_is_ask_user_and_interactive_mode
+ wrap_up_opt_after_interactive_selection # Since extra param inputed again, wrap up again
+
+ task_processing_after_parameters_checked
+
+ save_ocs_sr_related_vars
+ run_ocs_sr_again_prompt "$target_dir" "$target_hd"
+
+ # //NOTE// If encrypt_ocs_img="yes", after this step, ocsroot and target_dir will be changed
+ # The original ones will be kept as ocsroot_orig and target_dir_orig.
+ prepare_ecryptfs_mount_point_if_necessary
+
+ ocs-run-boot-param ocs_savedisk_prerun
+ task_savedisk "$target_dir" "$target_hd"
+ rc_savedisk="$?"
+ ocs-run-boot-param ocs_savedisk_postrun
+
+ #
+ if [ -d "$MULTIPATH_INFODIR" -a \
+ -n "$(echo $MULTIPATH_INFODIR | grep -w "multipath_info")" ]; then
+ rm -rf "$MULTIPATH_INFODIR"
+ fi
+
+ if [ "$rc_savedisk" -eq 0 -a "$chk_img_restoreable_mod_save" = "yes" ]; then
+ check_image_if_restorable "$ocsroot"
+ rc_chkimg="$?"
+ if [ "$rc_chkimg" -ne 0 ]; then
+ echo "$msg_program_stop!"
+ my_ocs_exit 1
+ fi
+ fi
+ echo $0 $OCS_OPTS $ocs_sr_type "$target_dir" "$target_hd" > $ocsroot/$target_dir/Info-saved-by-cmd.txt
+
+ task_postprocessing "$ocs_sr_type" "$target_dir"
+ ;;
+ "restoredisk")
+ task_preprocessing "$ocs_sr_type"
+ MULTIPATH_INFODIR="$(mktemp -d /tmp/multipath_info.XXXXXX)"
+
+ if [ "$ocs_sr_img_name" = "ask_user" ]; then
+ get_target_dir_name_when_restoring_disk # get $target_dir
+ elif [ "$ocs_sr_img_name" = "autoproductname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ target_dir="$(get_vendor_product_name)-img"
+ else
+ target_dir="$ocs_sr_img_name"
+ fi
+
+ check_input_target_image "$ocsroot/$target_dir"
+ source_dsk_no="$(get_disk_list_from_img $ocsroot/$target_dir | sed -e "s/ *$//g" | wc -w | awk '{print $1}')"
+
+ if [ "$ocs_sr_dev" = "ask_user" ]; then
+ if [ "$source_dsk_no" -eq 1 ]; then
+ dia_sel_opt="menu"
+ else
+ dia_sel_opt="checklist"
+ fi
+ # To get $target_hd
+ get_target_hd_name_from_local_machine "$msg_choose_the_disks_to_restore \n$msg_linux_disk_naming $msg_press_space_to_mark_selection" $dia_sel_opt
+ elif [ "$ocs_sr_dev" = "all" ]; then
+ target_hd="$(get_disk_list_from_img $ocsroot/$target_dir)"
+ else
+ target_hd="$ocs_sr_dev"
+ fi
+ get_extra_param_when_type_is_ask_user_and_interactive_mode
+ wrap_up_opt_after_interactive_selection # Since extra param inputed again, wrap up again
+
+ task_processing_after_parameters_checked
+
+ save_ocs_sr_related_vars
+ run_ocs_sr_again_prompt "$target_dir" "$target_hd"
+
+ # //NOTE// If encrypt_ocs_img="yes", after this step, ocsroot and target_dir will be changed
+ # The original ones will be kept as ocsroot_orig and target_dir_orig.
+ prepare_ecryptfs_mount_point_if_necessary
+
+ if [ -d "$ocsroot/$target_dir" -a "$chk_img_restoreable_mod_restore" = "yes" ]; then
+ check_image_if_restorable "$ocsroot"
+ rc_chkimg="$?"
+ if [ "$rc_chkimg" -ne 0 ]; then
+ echo "$msg_program_stop!"
+ my_ocs_exit 1
+ fi
+ fi
+
+ ocs-run-boot-param ocs_restoredisk_prerun
+ task_restoredisk "$target_dir" "$target_hd"
+ ocs-run-boot-param ocs_restoredisk_postrun
+
+ #
+ if [ -d "$MULTIPATH_INFODIR" -a \
+ -n "$(echo $MULTIPATH_INFODIR | grep -w "multipath_info")" ]; then
+ rm -rf "$MULTIPATH_INFODIR"
+ fi
+
+ task_postprocessing "$ocs_sr_type" "$target_dir"
+ ;;
+ "saveparts")
+ task_preprocessing "$ocs_sr_type"
+
+ if [ "$ocs_sr_img_name" = "ask_user" ]; then
+ get_target_dir_name_when_saving # get $target_dir
+ elif [ "$ocs_sr_img_name" = "autoname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/799287/topic/4815557
+ # We need something unique, so MAC address is a good choice
+ for i in `LC_ALL=C get-nic-devs`; do
+ prefix_mac="$(LC_ALL=C drbl-get-macadd $i)"
+ if [ -n "$prefix_mac" ]; then
+ prefix_mac="$(LC_ALL=C echo $prefix_mac | sed -e 's/://g')"
+ break
+ fi
+ done
+ # If not found, use UUID from MB manufacture
+ [ -z "$prefix_mac" ] && prefix_mac="$(LC_ALL=C dmidecode | grep -io "UUID: .*$" | head -n 1 | sed -e "s/^UUID: //g")"
+ target_dir="${prefix_mac}-$(LC_ALL=C date '+%Y-%m-%d-%H%M')-img"
+ elif [ "$ocs_sr_img_name" = "autohostname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ ip=""
+ for i in `LC_ALL=C get-nic-devs`; do
+ ip="$(drbl-get-ipadd $i)"
+ if [ -n "$ip" ]; then
+ break
+ fi
+ done
+ # If not found, give it a default name based on time.
+ if [ -z "ip" ]; then
+ prefix_host="autohostname-$(LC_ALL=C date '+%Y-%m-%d-%H%M')"
+ else
+ if LC_ALL=C host $ip &>/dev/null; then
+ # FQDN found
+ prefix_host="$(LC_ALL=C host $ip | sed -r -e "s/^.*name pointer//g" -e "s/^[[:space:]]*//g" -e "s|\.$||g")"
+ else
+ # FQDN not found. Give it a default name based on IP address and time.
+ prefix_host="autohostname-${ip}-$(LC_ALL=C date '+%Y-%m-%d-%H%M')"
+ fi
+ fi
+ target_dir="${prefix_host}-img"
+ elif [ "$ocs_sr_img_name" = "autoproductname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ target_dir="$(get_vendor_product_name)-img"
+ else
+ target_dir="$ocs_sr_img_name"
+ fi
+
+ if [ "$ocs_sr_dev" = "ask_user" ]; then
+ get_target_parts_name_from_local_machine # get $target_parts
+ elif [ "$ocs_sr_dev" = "all" ]; then
+ get_not_busy_disks_or_parts partition "" "" # we will get dev_list
+ target_parts="$dev_list"
+ else
+ target_parts="$ocs_sr_dev"
+ fi
+
+ # check if the device exists
+ ANS_TMP=`mktemp /tmp/ocs_chkdev.XXXXXX`
+ trap "[ -f "$ANS_TMP" ] && rm -f $ANS_TMP" HUP INT QUIT TERM EXIT
+ check_if_input_device_exist $ANS_TMP $target_parts
+ # we have to remove " (comes with checklist in dialog) so that for loop
+ # will work (Specially for FC3/4...)
+ target_parts="$(cat $ANS_TMP | tr -d \")"
+ [ -f "$ANS_TMP" ] && rm -f $ANS_TMP
+ get_extra_param_when_type_is_ask_user_and_interactive_mode
+ wrap_up_opt_after_interactive_selection # Since extra param inputed again, wrap up again
+
+ task_processing_after_parameters_checked
+
+ save_ocs_sr_related_vars
+ run_ocs_sr_again_prompt "$target_dir" "$target_parts"
+
+ # //NOTE// If encrypt_ocs_img="yes", after this step, ocsroot and target_dir will be changed
+ # The original ones will be kept as ocsroot_orig and target_dir_orig.
+ prepare_ecryptfs_mount_point_if_necessary
+
+ ocs-run-boot-param ocs_saveparts_prerun
+ task_saveparts "$target_dir" "$target_parts"
+ rc_saveparts="$?"
+ ocs-run-boot-param ocs_saveparts_postrun
+
+ #
+ if [ -d "$MULTIPATH_INFODIR" -a \
+ -n "$(echo $MULTIPATH_INFODIR | grep -w "multipath_info")" ]; then
+ rm -rf "$MULTIPATH_INFODIR"
+ fi
+
+ if [ "$rc_saveparts" -eq 0 -a "$chk_img_restoreable_mod_save" = "yes" ]; then
+ check_image_if_restorable "$ocsroot"
+ rc_chkimg="$?"
+ if [ "$rc_chkimg" -ne 0 ]; then
+ echo "$msg_program_stop!"
+ my_ocs_exit 1
+ fi
+ fi
+ echo $0 $OCS_OPTS $ocs_sr_type "$target_dir" "$target_parts" > $ocsroot/$target_dir/Info-saved-by-cmd.txt
+
+ task_postprocessing "$ocs_sr_type" "$target_dir"
+ ;;
+ "restoreparts")
+ task_preprocessing "$ocs_sr_type"
+
+ if [ "$ocs_sr_img_name" = "ask_user" ]; then
+ get_target_dir_name_when_restoring_parts # get $target_dir
+ elif [ "$ocs_sr_img_name" = "autoproductname" ]; then
+ # Ref: https://sourceforge.net/projects/clonezilla/forums/forum/663168/topic/5103006
+ target_dir="$(get_vendor_product_name)-img"
+ else
+ target_dir="$ocs_sr_img_name"
+ fi
+ check_input_target_image "$ocsroot/$target_dir"
+
+ if [ "$ocs_sr_dev" = "ask_user" ]; then
+ if [ -z "$source_part" ]; then
+ ANS_TMP=`mktemp /tmp/ocs_ans.XXXXXX`
+ trap "[ -f "$ANS_TMP" ] && rm -f $ANS_TMP" HUP INT QUIT TERM EXIT
+ get_existing_partitions_from_img $ANS_TMP $ocsroot/$target_dir no select_from_img
+ # we have to remove " (comes with checklist in dialog)
+ # so that for loop will work (Specially for FC3/4...)
+ source_part="$(cat $ANS_TMP | tr -d \")"
+ [ -f "$ANS_TMP" ] && rm -f $ANS_TMP
+ fi
+ # target name exists, but file "parts" is empty ?
+ check_target_parts $ocsroot/$target_dir/parts "$source_part"
+ src_parts_no="$(LC_ALL=C echo $source_part | wc -w)"
+ if [ "$src_parts_no" -eq 1 ]; then
+ dia_sel_opt="menu"
+ get_target_parts_name_from_local_machine "$msg_choose_the_parts_to_restore \n$msg_linux_parts_MS_mapping" $dia_sel_opt # Obtain target_parts
+ else
+ # In this case, it's too complicated to restore partitions to different partitions on destination disk.
+ # Therefore we only allow original partitions to partitions, i.e. e.g., sda1, sda2 from image -> sda1, sda2 on destination disk. Therefore "source_part" is reset to none.
+ target_parts="$source_part"
+ source_part=""
+ if [ "$ocs_batch_mode" != "on" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "$msg_2_or_more_parts_only_same_parts_on_dest"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_press_enter_to_continue"
+ read
+ fi
+ fi
+ elif [ "$ocs_sr_dev" = "all" -o \
+ "$ocs_sr_dev" = "unmounted_disk" ]; then
+ target_parts="$(get_parts_list_from_img $ocsroot/$target_dir)"
+ else
+ target_parts="$ocs_sr_dev"
+ fi
+ #
+ get_extra_param_when_type_is_ask_user_and_interactive_mode
+ wrap_up_opt_after_interactive_selection # Since extra param inputed again, wrap up again
+ # Append the option if restoring to different partition on the destination disk.
+ if [ -n "$source_part" ]; then
+ OCS_OPTS="$OCS_OPTS -f $source_part"
+ fi
+
+ save_ocs_sr_related_vars
+ run_ocs_sr_again_prompt "$target_dir" "$target_parts"
+
+ # //NOTE// If encrypt_ocs_img="yes", after this step, ocsroot and target_dir will be changed
+ # The original ones will be kept as ocsroot_orig and target_dir_orig.
+ prepare_ecryptfs_mount_point_if_necessary
+
+ task_processing_after_parameters_checked
+
+ if [ -d "$ocsroot/$target_dir" -a "$chk_img_restoreable_mod_restore" = "yes" ]; then
+ check_image_if_restorable "$ocsroot"
+ rc_chkimg="$?"
+ if [ "$rc_chkimg" -ne 0 ]; then
+ echo "$msg_program_stop!"
+ my_ocs_exit 1
+ fi
+ fi
+
+ ocs-run-boot-param ocs_restoreparts_prerun
+ task_restoreparts "$target_dir" "$target_parts"
+ ocs-run-boot-param ocs_restoreparts_postrun
+
+ task_postprocessing "$ocs_sr_type" "$target_dir"
+ ;;
+ "recovery-iso-zip") create_clonezilla_live_recovery_iso_zip ;;
+ "chk-img-restorable") ocs-chkimg ;;
+ "cvt-img-compression") ocs-cvtimg-comp ;;
+ "encrypt-img") ocs-encrypt-img ;;
+ "decrypt-img") ocs-decrypt-img ;;
+ "p2v-img") ocs-img-2-vdk ;;
+ "1-2-mdisks") ocs-restore-mdisks -um $ocs_user_mode ;;
+ "multicast_restoredisk")
+ task_preprocessing "$ocs_sr_type"
+ task_processing_after_parameters_checked
+
+ task_multicast_restoredisk "$ocs_sr_img_name" "$ocs_sr_dev" "$ocs_sr_mcast_port"
+ task_postprocessing "$ocs_sr_type" ""
+ ;;
+ "multicast_restoreparts")
+ task_preprocessing "$ocs_sr_type"
+ task_processing_after_parameters_checked
+
+ task_multicast_restoreparts "$ocs_sr_img_name" "$ocs_sr_dev" "$ocs_sr_mcast_port"
+ task_postprocessing "$ocs_sr_type" ""
+ ;;
+ *)
+ USAGE
+ exit 2
+ ;;
+esac
+
+echo "Ending $0 at $(LC_ALL=C date +%F' '%T' '%Z)..." | tee --append ${OCS_LOGFILE}
+exit 0
diff --git a/draft/other-tools/fog/fog-notes.txt b/draft/other-tools/fog/fog-notes.txt
new file mode 100644
index 0000000..61a7d12
--- /dev/null
+++ b/draft/other-tools/fog/fog-notes.txt
@@ -0,0 +1,148 @@
+
+
+./src/buildroot/package/fog/scripts/usr/share/fog/lib/funcs.sh
+
+
+ pigz $PIGZ_COMP < $fifo | split -a 3 -d -b 200m - ${file}. &
+
+
+ mainuuidfilename="$imagePath/d${disk_number}.original.uuids"
+ swapuuidfilename="$imagePath/d${disk_number}.original.swapuuids"
+ sfdiskoriginalpartitionfilename="$imagePath/d${disk_number}.partitions"
+ sfdisklegacyoriginalpartitionfilename="$imagePath/d${disk_number}.original.partitions"
+ sfdiskminimumpartitionfilename="$imagePath/d${disk_number}.minimum.partitions"
+ sgdiskoriginalpartitionfilename="$imagePath/d${disk_number}.sgdisk.original.partitions"
+ fixed_size_file="$imagePath/d${disk_number}.fixed_size_partitions"
+ hasgrubfilename="$imagePath/d${disk_number}.has_grub"
+ [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr"
+ [[ -n $sgdisk && $hasGRUB -eq 1 ]] && \
+ mbr="$imagePath/d${disk_number}.grub.mbr" || \
+ mbr="$imagePath/d${disk_number}.mbr"
+ ebrfilename="$path/d${disk_number}p${part_number}.ebr"
+
+# Save enough MBR and embedding area to capture all of GRUB
+# Strategy is to capture EVERYTHING before the first partition.
+# Then, leave a marker that this is a GRUB MBR for restoration.
+# We could get away with less storage, but more details are required
+# to parse the information correctly. It would make the process
+# more complicated.
+
+# $1 is the disk
+# $2 is the disk number
+# $3 is the image path to save the file to.
+# $4 is the determinator of sgdisk use or not
+saveGRUB() {
+
+
+ # Determine the number of sectors to copy
+ # Hack Note: print $4+0 causes the column to be interpretted as a number
+ # so the comma is tossed
+ local count=$(sfdisk -d $disk 2>/dev/null | awk /start=\ *[1-9]/'{print $4+0}' | sort -n | head -n1)
+
+
+ local has_grub=$(dd if=$disk bs=512 count=1 2>&1 | grep -i 'grub')
+
+ # Ensure that no more than 1MiB of data is copied (already have this size used elsewhere)
+ [[ $count -gt 2048 ]] && count=2048
+ local mbrfilename=""
+ MBRFileName "$imagePath" "$disk_number" "mbrfilename" "$sgdisk"
+ dd if=$disk of=$mbrfilename count=$count bs=512 >/dev/null 2>&1
+
+}
+
+
+
+hasGrubFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ local sgdisk="$3"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ hasgrubfilename="$imagePath/d${disk_number}.has_grub"
+ [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr"
+}
+
+savePartitionTablesAndBootLoaders() {
+
+ case $hasgpt in
+ 0)
+ strdots="Saving Partition Tables (MBR)"
+ case $osid in
+ 4|50|51)
+ [[ $disk_number -eq 1 ]] && strdots="Saving Partition Tables and GRUB (MBR)"
+ ;;
+ esac
+ dots "$strdots"
+ saveGRUB "$disk" "$disk_number" "$imagePath"
+ sfdisk -d $disk 2>/dev/null > $sfdiskfilename
+ [[ $have_extended_partition -ge 1 ]] && saveAllEBRs "$disk" "$disk_number" "$imagePath"
+ echo "Done"
+ ;;
+ 1)
+ dots "Saving Partition Tables (GPT)"
+ saveGRUB "$disk" "$disk_number" "$imagePath" "true"
+ sgdisk -b "$imagePath/d${disk_number}.mbr" $disk >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Error trying to save GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ sfdisk -d $disk 2>/dev/null > $sfdiskfilename
+ echo "Done"
+ ;;
+ esac
+}o
+
+clearPartitionTables() {
+ sgdisk -Z $disk >/dev/null 2>&1
+}
+
+restorePartitionTablesAndBootLoaders() {
+ if [[ $table_type == GPT ]]; then
+ dots "Restoring Partition Tables (GPT)"
+ restoreGRUB "$disk" "$disk_number" "$imagePath" "true"
+ sgdisk -gel $tmpMBR $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Error trying to restore GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*"
+ global_gptcheck="yes"
+ echo "Done"
+ else
+ [big cheat for MBR, dd, sfdisk for EBRs]
+ fi
+}
+
+
+savePartition() {
+ case $fstype in
+ swap)
+ echo " * Saving swap partition UUID"
+ swapUUIDFileName "$imagePath" "$disk_number"
+ saveSwapUUID "$swapuuidfilename" "$part"
+ ;;
+ *)
+ case $parttype in
+ 0x5|0xf)
+ echo " * Not capturing content of extended partition"
+ debugPause
+ EBRFileName "$imagePath" "$disk_number" "$part_number"
+ touch "$ebrfilename"
+ ;;
+ *)
+ echo " * Using partclone.$fstype"
+ debugPause
+ imgpart="$imagePath/d${disk_number}p${part_number}.img"
+ uploadFormat "$fifoname" "$imgpart"
+ partclone.$fstype -fsck-src-part -c -s $part -O $fifoname -N -f 1
+ case $? in
+ 0)
+ mv ${imgpart}.000 $imgpart >/dev/null 2>&1
+ echo " * Image Captured"
+ ;;
+ *)
+ handleError "Failed to complete capture (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+
diff --git a/draft/other-tools/fog/fog.download b/draft/other-tools/fog/fog.download
new file mode 100755
index 0000000..7190ebb
--- /dev/null
+++ b/draft/other-tools/fog/fog.download
@@ -0,0 +1,261 @@
+#!/bin/bash
+. /usr/share/fog/lib/funcs.sh
+. /bin/fog.donate
+. /bin/fog.checkin
+. /bin/fog.mount
+. /bin/fog.checkmount
+. /bin/fog.checkimgvar
+hd=""
+disks=""
+disk=""
+parts=""
+part=""
+imagePath="/images/$img"
+origmac=$mac
+mac=$(getMACAddresses | base64)
+. /bin/fog.inventory "true"
+mac="$origmac"
+origmac=""
+layPartSize="-1s"
+fog.statusreporter "$mac" "$web" & disown
+statusReporter="$!"
+fixed_size_partitions=""
+echo " * Using Image: $img"
+preparePartitions() {
+ echo " * Preparing Partition layout"
+ case $imgType in
+ [Nn])
+ case $osid in
+ 4|50|51)
+ [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*"
+ prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ ;;
+ [1-2])
+ [[ ! -f $imagePath && ! -f $imagePath/$img && ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*"
+ [[ -d $imagePath && -f $imagePath/$img ]] && imagePath="$imagePath/$img"
+ if [[ -d $imagePath ]]; then
+ prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ else
+ startsector="63s"
+ restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ dots "Removing partition"
+ parted -s $hd rm 1 >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not remove old partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ echo " * Attempting to expand/fill partitions"
+ dots "Recreating partition"
+ parted -s $hd mkpart primary ntfs 63s -- $layPartSize >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Could not create partition to fill disk ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Setting boot partition"
+ parted -s $hd set 1 boot on >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not make partition bootable ($0)\n Args Passed: $*"
+ fi
+ runPartprobe "$hd"
+ echo "Done"
+ debugPause
+ getPartitions "$hd"
+ for part in $parts; do
+ [[ -e $part ]] && break
+ done
+ fi
+ ;;
+ [5-7]|9)
+ [[ ! -d $imagePath && ! -f $imagePath/sys.img.000 ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*"
+ if [[ ! -f $imagePath/sys.img.000 ]]; then
+ prepareResizeDownloadPartitions "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ else
+ echo " * Using legacy style partition setup"
+ win7partcnt=1
+ dots "Windows Boot Partition Exists"
+ if [[ ! -f $imagePath/gpt.bak && ! -f $imagePath/rec1.img.000 && ! -f $imagePath/rec.img.000 ]]; then
+ echo "No"
+ else
+ echo "Yes"
+ [[ -f $imagePath/rec.img.000 ]] && win7partcnt=2
+ [[ -f $imagePath/rec.img.001 || -f $imagePath/gpt.bak ]] && win7partcnt=3
+ fi
+ debugPause
+ echo " * Attempting to expand/fill partitions"
+ do_fill=0
+ fillDiskWithPartitionsIsOK "$hd" "$imagePath" 1
+ case $do_fill in
+ 1)
+ fillDiskWithPartitions "$hd" "$imagePath" 1
+ echo "Done"
+ ;;
+ *)
+ startsector="2048s"
+ restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ case $win7partcnt in
+ 1)
+ dots "Removing partition"
+ parted -s $hd rm 1 >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not remove old partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Creating main partition"
+ parted -s $hd mkpart primary ntfs $startsector -- $layPartSize >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not recreate first partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Setting boot partition"
+ parted -s $hd set 1 boot on >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not make partition bootable ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ ;;
+ 2)
+ dots "Removing main partition"
+ parted -s $hd rm 1 >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not remove old main partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Recreating recovery partition"
+ parted -s $hd mkpart primary ntfs $startsector 206847s >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not create recovery partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Recreating main partition"
+ parted -s $hd mkpart primary ntfs $defaultpart2start -- $layPartSize >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not recreate main partition ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Setting boot partition"
+ parted -s $hd set 1 boot on >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not make partition bootable ($0)\nArgsPassed: $*"
+ fi
+ echo "Done"
+ ;;
+ 3)
+ dots "Removing partition data"
+ sgdisk -Z $hd >/dev/null 2>&1
+ sgdisk -gel $imagePath/gpt.bak $hd >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not recreate partitions ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ dots "Recreating sized out partitions"
+ sgdisk -x 3:$(sgdisk -E $hd) $hd >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not resize partitions ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ ;;
+ esac
+ ;;
+ esac
+ debugPause
+ runPartprobe "$hd"
+ dots "Setting up partition variables"
+ getPartitions "$hd"
+ restoreparts=""
+ part_number=0
+ for part in $parts; do
+ getPartitionNumber "$part"
+ [[ $part_number -le $win7partcnt ]] && restoreparts="$restoreparts $part"
+ done
+ echo "Done"
+ debugPause
+ fi
+ ;;
+ esac
+ ;;
+ mps)
+ [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*"
+ restorePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ runPartprobe "$hd"
+ gptcheck="$global_gptcheck"
+ ;;
+ mpa)
+ [[ ! -d $imagePath ]] && handleError "Unable to locate image store ($0)\n Args Passed: $*"
+ getHardDisk "true"
+ disk_number=1
+ for disk in $disks; do
+ restorePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType"
+ runPartprobe "$disk"
+ gptcheck="$global_gptcheck"
+ let disk_number+=1
+ done
+ ;;
+ esac
+}
+putDataBack() {
+ runPartprobe "$hd"
+ getPartitions "$hd"
+ [[ -z $parts ]] && echo -e " * Seems like you are trying to restore to an empty disk. Be aware this will most probably cause trouble.\n"
+ echo " +--------------------------------+"
+ echo " | Attempting to deploy image |"
+ echo " +--------------------------------+"
+ [[ $imgFormat -eq 1 || $imgLegacy -eq 1 ]] && echo " | Using Partimage |" || echo " | Using Partclone |"
+ echo " +--------------------------------+"
+ [[ $mc == yes ]] && usleep 10000000 || usleep 3000000
+ case $imgType in
+ dd)
+ restorePartition "$hd" 1 "$imagePath/$img.*" "$mc"
+ ;;
+ n|mps|mpa)
+ [[ $imgType == +(n|mps) ]] && disks="$hd"
+ case $osid in
+ [1-2])
+ [[ ! -f $imagePath && ! -d $imagePath ]] && handleError "Fatal Error: Could not locate file ($0)\n Args Passed: $*"
+ ;;
+ [5-7]|9)
+ [[ ! -d $imagePath && ! -f $imagePath/sys.img.000 ]] && handleError "Fatal Error: Could not locate file ($0)\n Args Passed: $*"
+ ;;
+ 4|50|51)
+ [[ ! -d $imagePath ]] && handleError "Fatal Error: could not locate file ($0)\n Args Passed: $*"
+ ;;
+ esac
+ performRestore "$disks" "$imagePath" "$imgPartitionType" "$mc"
+ ;;
+ esac
+}
+findHDDInfo
+[[ $nombr -eq 1 ]] && echo " * Skipping partition layout (Single Partition restore)" || preparePartitions
+[[ $imgPartitionType != mbr ]] && putDataBack || echo " * Skipping partition restore (MBR Only)"
+completeTasking
diff --git a/draft/other-tools/fog/fog.upload b/draft/other-tools/fog/fog.upload
new file mode 100755
index 0000000..8a80ae8
--- /dev/null
+++ b/draft/other-tools/fog/fog.upload
@@ -0,0 +1,216 @@
+#!/bin/bash
+. /usr/share/fog/lib/funcs.sh
+. /bin/fog.checkin
+. /bin/fog.mount
+. /bin/fog.checkmount
+. /bin/fog.checkimgvar
+imagePath="/images/$macWinSafe"
+parts=""
+part=""
+disks=""
+disk=""
+hd=""
+echo " * Preparing to send image file to server"
+percent="$pct"
+[[ $pct -lt 5 || $pct -ge 100 ]] && percent=5
+[[ $pct -lt 10 ]] && percent="0$pct"
+fog.statusreporter "$mac" "$web" & disown
+statusReporter="$!"
+prepareUploadLocation "$imagePath"
+echo " * Using Image: $img"
+# resizable image type
+# discover windows partitions
+# remove pagefile and hibernate file
+# validate XP partition location
+# save original partition table
+# save MBR
+# shrink filesystems and partitions
+# save GRUB
+# save shrunken partition table
+# clone filesystems
+# restore original MBR and partition table
+# expand filesystems
+beginUpload() {
+ case $imgType in
+ [Nn])
+ validResizeOS
+ runPartprobe "$hd"
+ getPartitions "$hd"
+ [[ $osid == @([1-2]|[4-7]|9) ]] && win7partcnt=$(echo $parts | wc -w)
+ dots "Checking for fixed partitions"
+ part_number=0
+ for part in $parts; do
+ fsTypeSetting "$part"
+ getPartitionNumber "$part"
+ case $fstype in
+ ntfs|extfs)
+ continue
+ ;;
+ *)
+ fixed_size_partitions="$fixed_size_partitions:$part_number"
+ ;;
+ esac
+ done
+ echo "Done"
+ debugPause
+ dots "Getting Windows/Linux Partition Count"
+ countPartTypes "$hd" "ntfs" "ntfscnt"
+ countPartTypes "$hd" "extfs" "extfscnt"
+ if [[ $ntfscnt -eq 0 && $extfscnt -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "No resizable partitions found ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ echo " * NTFS Partition count of: $ntfscnt"
+ debugPause
+ echo " * EXTFS Partition count of: $extfscnt"
+ debugPause
+ case $osid in
+ [4-7]|9|50|51)
+ echo " * Setting up any additional fixed parts"
+ [[ $((ntfscnt + extfscnt)) -gt 0 && $part_number -gt 1 ]] && fixed_size_partitions="$fixed_size_partitions:1"
+ part_number=0
+ for part in $parts; do
+ getPartitionNumber "$part"
+ fsTypeSetting "$part"
+ [[ $fstype != ntfs ]] && continue
+ dots "Mounting partition ($part)"
+ if [[ ! -d /bcdstore ]]; then
+ mkdir -p /bcdstore >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not create mount location ($0->${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ ntfs-3g -o remove_hiberfile,rw $part /bcdstore >/tmp/ntfs-mount-output 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not mount $part ($0->${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)"
+ ;;
+ esac
+ dots "BCD exists on $part in /bcdstore"
+ if [[ ! -f /bcdstore/Boot/BCD ]]; then
+ umount /bcdstore >/dev/null 2>&1
+ echo "No"
+ debugPause
+ else
+ umount /bcdstore >/dev/null 2>&1
+ echo "Yes"
+ debugPause
+ if [[ $part_number -gt 1 ]]; then
+ for ((increment=1; increment < $part_number; increment++)); do
+ fixed_size_partitions="$fixed_size_partitions:$increment"
+ done
+ fi
+ fi
+ done
+ ;;
+ esac
+ # All:
+ # save the list of fixed size partitions
+ fixed_size_partitions=$(echo $fixed_size_partitions | tr ':' '\n' | uniq | tr '\n' ':' | sed 's/:$//g')
+ echo "$fixed_size_partitions" > "$imagePath/d1.fixed_size_partitions"
+ # Windows 2000/XP, Vista, 7, 8, 8.1, Linux:
+ # Save unmodified partition table for download use
+ # Start filesytem type record
+ dots "Saving original partition table"
+ saveOriginalPartitions "$hd" "$imagePath" 1
+ swapuuidfilename=""
+ swapUUIDFileName "$imagePath" 1
+ mainuuidfilename=""
+ mainUUIDFileName "$imagePath" 1
+ echo -n "" > "$imagePath/d1.original.fstypes"
+ echo -n "" > $swapuuidfilename
+ echo "Done"
+ debugPause
+ echo " * Saving original disk/parts UUIDs"
+ debugPause
+ saveUUIDInformation "$hd" "$mainuuidfilename"
+ echo " * Shrinking Partitions on disk"
+ debugPause
+ for part in $parts; do
+ clearMountedDevices "$part"
+ removePageFile "$part"
+ shrinkPartition "$part" "$imagePath/d1.original.fstypes" "$fixed_size_partitions"
+ done
+ echo " * Saving shrunken partition table"
+ debugPause
+ sfdiskminimumpartitionfilename=""
+ sfdiskMinimumPartitionFileName "$imagePath" 1
+ savePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType" "$sfdiskminimumpartitionfilename"
+ echo " * Processing Hard Disk: $hd"
+ for part in $parts; do
+ savePartition "$part" 1 "$imagePath" "$imgPartitionType"
+ done
+ dots "Restoring Original Partition Layout"
+ restoreOriginalPartitions "$hd" "$imagePath" 1
+ runPartprobe "$hd"
+ echo "Done"
+ debugPause
+ [[ $osid -eq 2 ]] && correctVistaMBR "$hd"
+ getPartitions "$hd"
+ for part in $parts; do
+ expandPartition "$part" "$fixed_size_partitions"
+ done
+ ;;
+ mps)
+ echo " * Processing Hard Disk: $hd"
+ echo " * Saving original disk/parts UUIDs"
+ debugPause
+ mainuuidfilename=""
+ mainUUIDFileName "$imagePath" 1
+ saveUUIDInformation "$hd" "$mainuuidfilename"
+ savePartitionTablesAndBootLoaders "$hd" 1 "$imagePath" "$osid" "$imgPartitionType"
+ getPartitions "$hd"
+ for part in $parts; do
+ savePartition "$part" 1 "$imagePath" "$imgPartitionType"
+ done
+ ;;
+ mpa)
+ disk_number=1
+ for disk in $disks; do
+ debugPause
+ echo " * Processing Hard Disk: $disk"
+ echo " * Saving original disk/parts UUIDs"
+ debugPause
+ mainuuidfilename=""
+ mainUUIDFileName "$imagePath" $disk_number
+ saveUUIDInformation "$disk" "$mainuuidfilename"
+ savePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType"
+ runPartprobe "$disk"
+ getPartitions "$disk"
+ for part in $parts; do
+ savePartition "$part" "$disk_number" "$imagePath" "$imgPartitionType"
+ done
+ echo " * Disk $disk complete"
+ let disk_number+=1
+ done
+ ;;
+ dd)
+ imgpart="$imagePath/$img"
+ mkfifo /tmp/pigz1 >/dev/null 2>&1
+ uploadFormat "/tmp/pigz1" "$imgpart"
+ partclone.imager -c -s "$hd" -O /tmp/pigz1 -N -f 1
+ rm /tmp/pigz1 >/dev/null 2>&1
+ clearScreen
+ ;;
+ esac
+}
+findHDDInfo
+echo " * Now FOG will attempt to capture the image using Partclone"
+debugPause
+beginUpload
+completeTasking
diff --git a/draft/other-tools/fog/funcs.sh b/draft/other-tools/fog/funcs.sh
new file mode 100644
index 0000000..e6f574c
--- /dev/null
+++ b/draft/other-tools/fog/funcs.sh
@@ -0,0 +1,2196 @@
+#!/bin/bash
+. /usr/share/fog/lib/partition-funcs.sh
+REG_LOCAL_MACHINE_XP="/ntfs/WINDOWS/system32/config/system"
+REG_LOCAL_MACHINE_7="/ntfs/Windows/System32/config/SYSTEM"
+# 1 to turn on massive debugging of partition table restoration
+ismajordebug=0
+#If a sub shell gets invoked and we lose kernel vars this will reimport them
+oIFS=$IFS
+for var in $(cat /proc/cmdline); do
+ IFS=$oIFS
+ read name value <<< $(echo "$var" | grep =.* | awk -F= '{name=$1;$1="";gsub(/[ \t]+$/,"",$0);gsub(/^[ \t]+/,"",$0); gsub(/[+][_][+]/," ",$0); value=$0; print name; print value;}')
+ IFS=$'\n'
+ [[ -z $value ]] && continue
+ value=$(echo $value | sed 's/\"//g')
+ printf -v "$name" -- "$value"
+done
+IFS=$oIFS
+### If USB Boot device we need a way to get the kernel args properly
+[[ $boottype == usb && -f /tmp/hinfo.txt ]] && . /tmp/hinfo.txt
+# Below Are non parameterized functions
+# These functions will run without any arguments
+#
+# Clears thes creen unless its a debug task
+clearScreen() {
+ case $isdebug in
+ [Yy][Ee][Ss]|[Yy])
+ clear
+ ;;
+ esac
+}
+# Displays the nice banner along with the running version
+displayBanner() {
+ version=$(wget -qO - http://${web}service/getversion.php 2>/dev/null)
+ echo " +------------------------------------------+"
+ echo " | ..#######:. ..,#,.. .::##::. |"
+ echo " |.:###### .:;####:......;#;.. |"
+ echo " |...##... ...##;,;##::::.##... |"
+ echo " | ,# ...##.....##:::## ..:: |"
+ echo " | ## .::###,,##. . ##.::#.:######::.|"
+ echo " |...##:::###::....#. .. .#...#. #...#:::. |"
+ echo " |..:####:.. ..##......##::## .. # |"
+ echo " | # . ...##:,;##;:::#: ... ##.. |"
+ echo " | .# . .:;####;::::.##:::;#:.. |"
+ echo " | # ..:;###.. |"
+ echo " | |"
+ echo " +------------------------------------------+"
+ echo " | Free Computer Imaging Solution |"
+ echo " +------------------------------------------+"
+ echo " | Credits: http://fogproject.org/Credits |"
+ echo " | http://fogproject.org/Credits |"
+ echo " | Released under GPL Version 3 |"
+ echo " +------------------------------------------+"
+ echo " Version: $version"
+}
+# Gets all system mac addresses except for loopback
+getMACAddresses() {
+ read ifaces <<< $(/sbin/ip -4 -o addr | awk -F'([ /])+' '/global/ {print $2}' | tr '[:space:]' '|' | sed -e 's/^[|]//g' -e 's/[|]$//g')
+ read mac_addresses <<< $(/sbin/ip -0 -o addr | awk "/$ifaces/ {print \$11}" | tr '[:space:]' '|' | sed -e 's/^[|]//g' -e 's/[|]$//g')
+ echo $mac_addresses
+}
+# Verifies that there is a network interface
+verifyNetworkConnection() {
+ dots "Verifying network interface configuration"
+ local count=$(/sbin/ip addr | awk -F'[ /]+' '/global/{print $3}' | wc -l)
+ if [[ -z $count || $count -lt 1 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "No network interfaces found (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+}
+# Verifies that the OS is valid for resizing
+validResizeOS() {
+ [[ $osid != @([1-2]|4|[5-7]|9|50|51) ]] && handleError " * Invalid operating system id: $osname ($osid) (${FUNCNAME[0]})\n Args Passed: $*"
+}
+# Gets the information from the system for inventory
+doInventory() {
+ sysman=$(dmidecode -s system-manufacturer)
+ sysproduct=$(dmidecode -s system-product-name)
+ sysversion=$(dmidecode -s system-version)
+ sysserial=$(dmidecode -s system-serial-number)
+ systype=$(dmidecode -t 3 | grep Type:)
+ biosversion=$(dmidecode -s bios-version)
+ biosvendor=$(dmidecode -s bios-vendor)
+ biosdate=$(dmidecode -s bios-release-date)
+ mbman=$(dmidecode -s baseboard-manufacturer)
+ mbproductname=$(dmidecode -s baseboard-product-name)
+ mbversion=$(dmidecode -s baseboard-version)
+ mbserial=$(dmidecode -s baseboard-serial-number)
+ mbasset=$(dmidecode -s baseboard-asset-tag)
+ cpuman=$(dmidecode -s processor-manufacturer)
+ cpuversion=$(dmidecode -s processor-version)
+ cpucurrent=$(dmidecode -t 4 | grep 'Current Speed:' | head -n1)
+ cpumax=$(dmidecode -t 4 | grep 'Max Speed:' | head -n1)
+ mem=$(cat /proc/meminfo | grep MemTotal)
+ hdinfo=$(hdparm -i $hd 2>/dev/null | grep Model=)
+ caseman=$(dmidecode -s chassis-manufacturer)
+ casever=$(dmidecode -s chassis-version)
+ caseserial=$(dmidecode -s chassis-serial-number)
+ casesasset=$(dmidecode -s chassis-asset-tag)
+ sysman64=$(echo $sysman | base64)
+ sysproduct64=$(echo $sysproduct | base64)
+ sysversion64=$(echo $sysversion | base64)
+ sysserial64=$(echo $sysserial | base64)
+ systype64=$(echo $systype | base64)
+ biosversion64=$(echo $biosversion | base64)
+ biosvendor64=$(echo $biosvendor | base64)
+ biosdate64=$(echo $biosdate | base64)
+ mbman64=$(echo $mbman | base64)
+ mbproductname64=$(echo $mbproductname | base64)
+ mbversion64=$(echo $mbversion | base64)
+ mbserial64=$(echo $mbserial | base64)
+ mbasset64=$(echo $mbasset | base64)
+ cpuman64=$(echo $cpuman | base64)
+ cpuversion64=$(echo $cpuversion | base64)
+ cpucurrent64=$(echo $cpucurrent | base64)
+ cpumax64=$(echo $cpumax | base64)
+ mem64=$(echo $mem | base64)
+ hdinfo64=$(echo $hdinfo | base64)
+ caseman64=$(echo $caseman | base64)
+ casever64=$(echo $casever | base64)
+ caseserial64=$(echo $caseserial | base64)
+ casesasset64=$(echo $casesasset | base64)
+}
+# Gets the location of the SAM registry if found
+getSAMLoc() {
+ local path=""
+ local paths="/ntfs/WINDOWS/system32/config/SAM /ntfs/Windows/System32/config/SAM"
+ for path in $paths; do
+ [[ ! -f $path ]] && continue
+ sam="$path" && break
+ done
+}
+# Appends dots to the end of string up to 50 characters.
+# Makes the output more aligned and organized.
+#
+# $1 String to append dots to
+dots() {
+ local str="$*"
+ [[ -z $str ]] && handleError "No string passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local pad=$(printf "%0.1s" "."{1..50})
+ printf " * %s%*.*s" "$str" 0 $((50-${#str})) "$pad"
+}
+# Enables write caching on the disk passed
+# If the disk does not support write caching this does nothing
+#
+# $1 is the drive
+enableWriteCache() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ wcache=$(hdparm -W $disk 2>/dev/null | tr -d '[[:space:]]' | awk -F= '/.*write-caching=/{print $2}')
+ if [[ -z $wcache || $wcache == notsupported ]]; then
+ echo " * Write caching not supported"
+ debugPause
+ return
+ fi
+ dots "Enabling write cache"
+ hdparm -W1 $disk >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Enabled"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleWarning "Could not set caching status (${FUNCNAME[0]})"
+ return
+ ;;
+ esac
+ debugPause
+}
+# Expands partitions, as needed/capable
+#
+# $1 is the partition
+# $2 is the fixed size partitions (can be empty)
+expandPartition() {
+ local part="$1"
+ local fixed="$2"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ local part_number=0
+ getDiskFromPartition "$part"
+ getPartitionNumber "$part"
+ local is_fixed=$(echo $fixed | awk "/(^$part_number:|:$part_number:|:$part_number$|^$part_number$)/{print 1}")
+ if [[ $is_fixed -eq 1 ]]; then
+ echo " * Not expanding ($part) fixed size"
+ debugPause
+ return
+ fi
+ local fstype=""
+ fsTypeSetting $part
+ case $fstype in
+ ntfs)
+ dots "Resizing $fstype volume ($part)"
+ ntfsresize $part -f -b -P </usr/share/fog/lib/EOFNTFSRESTORE >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not resize $part (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+ resetFlag "$part"
+ ;;
+ extfs)
+ dots "Resizing $fstype volume ($part)"
+ e2fsck -fp $part >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not check before resize (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ resize2fs $part >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not resize $part (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ e2fsck -fp $part >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not check after resize (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ ;;
+ *)
+ echo " * Not expanding ($part -- $fstype)"
+ debugPause
+ ;;
+ esac
+ debugPause
+ runPartprobe "$disk"
+}
+# Gets the filesystem type of the partition passed
+#
+# $1 is the partition
+fsTypeSetting() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local blk_fs=$(blkid -po udev $part | awk -F= /FS_TYPE=/'{print $2}')
+ case $blk_fs in
+ btrfs)
+ fstype="btrfs"
+ ;;
+ ext[2-4])
+ fstype="extfs"
+ ;;
+ hfsplus)
+ fstype="hfsp"
+ ;;
+ ntfs)
+ fstype="ntfs"
+ ;;
+ swap)
+ fstype="swap"
+ ;;
+ vfat)
+ fstype="fat"
+ ;;
+ xfs)
+ fstype="xfs"
+ ;;
+ *)
+ fstype="imager"
+ ;;
+ esac
+}
+# Gets the disk part table UUID
+#
+# $1 is the disk
+getDiskUUID() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ diskuuid=$(blkid -po udev $disk | awk -F= '/PART_TABLE_UUID=/{print $2}')
+}
+# Gets the partition entry name
+#
+# $1 is the partition
+getPartName() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ partname=$(blkid -po udev $part | awk -F= '/PART_ENTRY_NAME=/{print $2}')
+}
+# Gets the partition entry type
+#
+# $1 is the partition
+getPartType() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ parttype=$(blkid -po udev $part | awk -F= '/PART_ENTRY_TYPE=/{print $2}')
+}
+# Gets the partition fs UUID
+#
+# $1 is the partition
+getPartFSUUID() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ partfsuuid=$(blkid -po udev $part | awk -F= '/FS_UUID=/{print $2}')
+}
+# Gets the partition entry UUID
+#
+# $1 is the partition
+getPartUUID() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ partuuid=$(blkid -po udev $part | awk -F= '/PART_ENTRY_UUID=/{print $2}')
+}
+# Gets the entry schemed (dos, gpt, etc...)
+#
+# $1 is the partition
+getPartitionEntryScheme() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ scheme=$(blkid -po udev $part | awk -F= '/PART_ENTRY_SCHEME=/{print $2}')
+}
+# Checks if the partition is dos extended (mbr with logical parts)
+#
+# $1 is the partition
+partitionIsDosExtended() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local scheme=""
+ getPartitionEntryScheme "$part"
+ debugEcho "scheme = $scheme" 1>&2
+ case $scheme in
+ dos)
+ echo "no"
+ ;;
+ *)
+ local parttype=""
+ getPartType "$part"
+ debugEcho "parttype = $parttype" 1>&2
+ [[ $parttype == +(0x5|0xf) ]] && echo "yes" || echo "no"
+ ;;
+ esac
+ debugPause
+}
+# Returns the block size of a partition
+#
+# $1 is the partition
+# $2 is the variable to set
+getPartBlockSize() {
+ local part="$1"
+ local varVar="$2"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*"
+ printf -v "$varVar" $(blockdev --getpbsz $part)
+}
+# Prepares location info for uploads
+#
+# $1 is the image path
+prepareUploadLocation() {
+ local imagePath="$1"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ dots "Preparing backup location"
+ if [[ ! -d $imagePath ]]; then
+ mkdir -p $imagePath >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Failed to create image capture path (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ echo "Done"
+ debugPause
+ dots "Setting permission on $imagePath"
+ chmod -R 777 $imagePath >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Failed to set permissions (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+ dots "Removing any pre-existing files"
+ rm -Rf $imagePath/* >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not clean files (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+}
+# Shrinks partitions for upload (resizable images only)
+#
+# $1 is the partition
+# $2 is the fstypes file location
+# $3 is the fixed partition numbers empty ok
+shrinkPartition() {
+ local part="$1"
+ local fstypefile="$2"
+ local fixed="$3"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $fstypefile ]] && handleError "No type file passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ local part_number=0
+ getDiskFromPartition "$part"
+ getPartitionNumber "$part"
+ local is_fixed=$(echo $fixed | awk "/(^$part_number:|:$part_number:|:$part_number$|^$part_number$)/{print 1}")
+ if [[ $is_fixed -eq 1 ]]; then
+ echo " * Not shrinking ($part) fixed size"
+ debugPause
+ return
+ fi
+ local fstype=""
+ fsTypeSetting "$part"
+ echo "$part $fstype" >> $fstypefile
+ local size=0
+ local tmpoutput=""
+ local sizentfsresize=0
+ local sizeextresize=0
+ local sizefd=0
+ local tmp_success=""
+ local test_string=""
+ local do_resizefs=0
+ local do_resizepart=0
+ local extminsize=0
+ local block_size=0
+ local sizeextresize=0
+ local adjustedfdsize=0
+ local part_block_size=0
+ case $fstype in
+ ntfs)
+ ntfsresize -f -i -v -P $part >/tmp/tmpoutput.txt 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ handleError " * (${FUNCNAME[0]})\n Args Passed: $*\n\nFatal Error, unable to find size data out on $part. Cmd: ntfsresize -f -i -v -P $part"
+ fi
+ tmpoutput=$(cat /tmp/tmpoutput.txt)
+ size=$(cat /tmp/tmpoutput.txt | grep "You might resize" | cut -d" " -f5)
+ [[ -z $size ]] && handleError " * (${FUNCNAME[0]})\n Args Passed: $*\n\nFatal Error, Unable to determine possible ntfs size\n * To better help you debug we will run the ntfs resize\n\t but this time with full output, please wait!\n\t $(cat /tmp/tmpoutput.txt)"
+ rm /tmp/tmpoutput.txt >/dev/null 2>&1
+ sizentfsresize=$((size / 1000))
+ let sizentfsresize+=300000
+ sizentfsresize=$((sizentfsresize * 1${percent} / 100))
+ sizefd=$((sizentfsresize * 103 / 100))
+ echo " * Possible resize partition size: $sizentfsresize k"
+ dots "Running resize test $part"
+ ntfsresize -f -n -s ${sizentfsresize}k $part </usr/share/fog/lib/EOFNTFSRESTORE >/tmp/tmpoutput.txt 2>&1
+ local ntfsstatus="$?"
+ tmpoutput=$(cat /tmp/tmpoutput.txt)
+ test_string=$(cat /tmp/tmpoutput.txt | egrep -io "(ended successfully|bigger than the device size|volume size is already OK)" | tr -d '[[:space:]]')
+ echo "Done"
+ debugPause
+ rm /tmp/tmpoutput.txt >/dev/null 2>&1
+ case $test_string in
+ endedsuccessfully)
+ echo " * Resize test was successful"
+ do_resizefs=1
+ do_resizepart=1
+ ntfsstatus=0
+ ;;
+ biggerthanthedevicesize)
+ echo " * Not resizing filesystem $part (part too small)"
+ ntfsstatus=0
+ ;;
+ volumesizeisalreadyOK)
+ echo " * Not resizing filesystem $part (already OK)"
+ do_resizepart=1
+ ntfsstatus=0
+ ;;
+ esac
+ [[ ! $ntfsstatus -eq 0 ]] && handleError "Resize test failed!\n $tmpoutput\n (${FUNCNAME[0]})\n Args Passed: $*"
+ if [[ $do_resizefs -eq 1 ]]; then
+ debugPause
+ dots "Resizing filesystem"
+ ntfsresize -f -s ${sizentfsresize}k $part < /usr/share/fog/lib/EOFNTFS >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not resize disk (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ if [[ $do_resizepart -eq 1 ]]; then
+ debugPause
+ dots "Resizing partition $part"
+ getPartBlockSize "$part" "part_block_size"
+ case $osid in
+ [1-2]|4)
+ resizePartition "$part" "$sizentfsresize" "$imagePath"
+ [[ $osid -eq 2 ]] && correctVistaMBR "$disk"
+ ;;
+ [5-7]|9)
+ [[ $part_number -eq $win7partcnt ]] && part_start=$(blkid -po udev $part 2>/dev/null | awk -F= '/PART_ENTRY_OFFSET=/{printf("%.0f\n",$2*'$part_block_size'/1000)}') || part_start=1048576
+ if [[ -z $part_start || $part_start -lt 1 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Unable to determine disk start location (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ adjustedfdsize=$((sizefd + part_start))
+ resizePartition "$part" "$adjustedfdsize" "$imagePath"
+ ;;
+ esac
+ echo "Done"
+ fi
+ resetFlag "$part"
+ ;;
+ extfs)
+ dots "Checking $fstype volume ($part)"
+ e2fsck -fp $part >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "e2fsck failed to check $part (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+ extminsize=$(resize2fs -P $part 2>/dev/null | awk -F': ' '{print $2}')
+ block_size=$(dumpe2fs -h $part 2>/dev/null | awk /^Block\ size:/'{print $3}')
+ size=$((extminsize * block_size))
+ sizeextresize=$((size * 103 / 100 / 1024))
+ [[ -z $sizeextresize || $sizeextresize -lt 1 ]] && handleError "Error calculating the new size of extfs ($part) (${FUNCNAME[0]})\n Args Passed: $*"
+ dots "Shrinking $fstype volume ($part)"
+ resize2fs $part -M >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not shrink $fstype volume ($part) (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+ dots "Shrinking $part partition"
+ resizePartition "$part" "$sizeextresize" "$imagePath"
+ echo "Done"
+ debugPause
+ dots "Resizing $fstype volume ($part)"
+ resize2fs $part >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could resize $fstype volume ($part) (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ e2fsck -fp $part >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not check expanded volume ($part) (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ ;;
+ *)
+ echo " * Not shrinking ($part $fstype)"
+ ;;
+ esac
+ debugPause
+}
+# Resets the dirty bits on a partition
+#
+# $1 is the part
+resetFlag() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local fstype=""
+ fsTypeSetting "$part"
+ case $fstype in
+ ntfs)
+ dots "Clearing ntfs flag"
+ ntfsfix -b -d $part >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ ;;
+ esac
+ ;;
+ esac
+}
+# Counts the partitions containing the fs type as passed
+#
+# $1 is the disk
+# $2 is the part type to look for
+# $3 is the variable to store the count into. This is
+# a variable variable
+countPartTypes() {
+ local disk="$1"
+ local parttype="$2"
+ local varVar="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $parttype ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local count=0
+ local fstype=""
+ local parts=""
+ local part=""
+ getPartitions "$disk"
+ for part in $parts; do
+ fsTypeSetting "$part"
+ case $fstype in
+ $parttype)
+ let count+=1
+ ;;
+ esac
+ done
+ printf -v "$varVar" "$count"
+}
+# Writes the image to the disk
+#
+# $1 = Source File
+# $2 = Target
+# $3 = mc task or not (not required)
+writeImage() {
+ local file="$1"
+ local target="$2"
+ local mc="$3"
+ [[ -z $target ]] && handleError "No target to place image passed (${FUNCNAME[0]})\n Args Passed: $*"
+ mkfifo /tmp/pigz1
+ case $mc in
+ yes)
+ udp-receiver --nokbd --portbase $port --ttl 32 --mcast-rdv-address $storageip 2>/dev/null >/tmp/pigz1 &
+ ;;
+ *)
+ [[ -z $file ]] && handleError "No source file passed (${FUNCNAME[0]})\n Args Passed: $*"
+ cat $file >/tmp/pigz1 &
+ ;;
+ esac
+ if [[ $imgFormat -eq 1 || $imgLegacy -eq 1 ]]; then
+ echo " * Imaging using Partimage"
+ pigz -d -c </tmp/pigz1 | partimage restore $target stdin -f3 -b 2>/tmp/status.fog
+ else
+ echo " * Imaging using Partclone"
+ pigz -d -c </tmp/pigz1 | partclone.restore --ignore_crc -O $target -N -f 1
+ fi
+ [[ ! $? -eq 0 ]] && handleError "Image failed to restore and exited with exit code $? (${FUNCNAME[0]})\n Args Passed: $*"
+ rm -rf /tmp/pigz1 >/dev/null 2>&1
+}
+# Gets the valid restore parts. They're only
+# valid if the partition data exists for
+# the partitions on the server
+#
+# $1 = Disk (e.g. /dev/sdb)
+# $2 = Disk number (e.g. 1)
+# $3 = ImagePath (e.g. /net/foo)
+getValidRestorePartitions() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local setrestoreparts="$4"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local valid_parts=""
+ local parts=""
+ local part=""
+ local imgpart=""
+ local part_number=0
+ getPartitions "$disk"
+ for part in $parts; do
+ getPartitionNumber "$part"
+ [[ $imgPartitionType != all && $imgPartitionType != $part_number ]] && continue
+ case $osid in
+ [1-2])
+ [[ ! -f $imagePath ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*" || imgpart="$imagePath"
+ ;;
+ 4|[5-7]|9)
+ [[ ! -f $imagePath/sys.img.000 ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*"
+ if [[ -z $imgpart ]]; then
+ case $win7partcnt in
+ 1)
+ [[ $part_number -eq 1 ]] && imgpart="$imagePath/sys.img.*"
+ ;;
+ 2)
+ [[ $part_number -eq 1 ]] && imgpart="$imagePath/rec.img.000"
+ [[ $part_number -eq 2 ]] && imgpart="$imagePath/sys.img.*"
+ ;;
+ 3)
+ [[ $part_number -eq 1 ]] && imgpart="$imagePath/rec.img.000"
+ [[ $part_number -eq 2 ]] && imgpart="$imagePath/rec.img.001"
+ [[ $part_number -eq 3 ]] && imgpart="$imagePath/sys.img.*"
+ ;;
+ esac
+ fi
+ ;;
+ *)
+ imgpart="$imagePath/d${disk_number}p${part_number}.img*"
+ ;;
+ esac
+ ls $imgpart >/dev/null 2>&1
+ [[ $? -eq 0 ]] && valid_parts="$valid_parts $part"
+ done
+ [[ -z $setrestoreparts ]] && restoreparts=$(echo $valid_parts | uniq | sort -V) || restoreparts="$(echo $setrestoreparts | uniq | sort -V)"
+}
+# Makes all swap partitions and sets uuid's in linux setups
+#
+# $1 = Disk (e.g. /dev/sdb)
+# $2 = Disk number (e.g. 1)
+# $3 = ImagePath (e.g. /net/foo)
+# $4 = ImagePartitionType (e.g. all, mbr, 1, 2, 3, etc.)
+makeAllSwapSystems() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local imgPartitionType="$4"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No image partition type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local swapuuidfilename=""
+ swapUUIDFileName "$imagePath" "$disk_number"
+ local parts=""
+ local part=""
+ local part_number=0
+ getPartitions "$disk"
+ for part in $parts; do
+ getPartitionNumber "$part"
+ [[ $imgPartitionType == all || $imgPartitionType -eq $part_number ]] && makeSwapSystem "$swapuuidfilename" "$part"
+ done
+ runPartprobe "$disk"
+}
+# Changes the hostname on windows systems
+#
+# $1 = Partition
+changeHostname() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $hostname || $hostearly -eq 0 ]] && return
+ REG_HOSTNAME_KEY1="\ControlSet001\Services\Tcpip\Parameters\NV Hostname"
+ REG_HOSTNAME_KEY2="\ControlSet001\Services\Tcpip\Parameters\Hostname"
+ REG_HOSTNAME_KEY3="\ControlSet001\Services\Tcpip\Parameters\NV HostName"
+ REG_HOSTNAME_KEY4="\ControlSet001\Services\Tcpip\Parameters\HostName"
+ REG_HOSTNAME_KEY5="\ControlSet001\Control\ComputerName\ActiveComputerName\ComputerName"
+ REG_HOSTNAME_KEY6="\ControlSet001\Control\ComputerName\ComputerName\ComputerName"
+ REG_HOSTNAME_KEY7="\ControlSet001\services\Tcpip\Parameters\NV Hostname"
+ REG_HOSTNAME_KEY8="\ControlSet001\services\Tcpip\Parameters\Hostname"
+ REG_HOSTNAME_KEY9="\ControlSet001\services\Tcpip\Parameters\NV HostName"
+ REG_HOSTNAME_KEY10="\ControlSet001\services\Tcpip\Parameters\HostName"
+ REG_HOSTNAME_KEY11="\CurrentControlSet\Services\Tcpip\Parameters\NV Hostname"
+ REG_HOSTNAME_KEY12="\CurrentControlSet\Services\Tcpip\Parameters\Hostname"
+ REG_HOSTNAME_KEY13="\CurrentControlSet\Services\Tcpip\Parameters\NV HostName"
+ REG_HOSTNAME_KEY14="\CurrentControlSet\Services\Tcpip\Parameters\HostName"
+ REG_HOSTNAME_KEY15="\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName"
+ REG_HOSTNAME_KEY16="\CurrentControlSet\Control\ComputerName\ComputerName\ComputerName"
+ REG_HOSTNAME_KEY17="\CurrentControlSet\services\Tcpip\Parameters\NV Hostname"
+ REG_HOSTNAME_KEY18="\CurrentControlSet\services\Tcpip\Parameters\Hostname"
+ REG_HOSTNAME_KEY19="\CurrentControlSet\services\Tcpip\Parameters\NV HostName"
+ REG_HOSTNAME_KEY20="\CurrentControlSet\services\Tcpip\Parameters\HostName"
+ dots "Mounting directory"
+ if [[ ! -d /ntfs ]]; then
+ mkdir -p /ntfs >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ fi
+ umount /ntfs >/dev/null 2>&1
+ ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)"
+ ;;
+ esac
+ if [[ ! -f /usr/share/fog/lib/EOFREG ]]; then
+ key1="$REG_HOSTNAME_KEY1"
+ key2="$REG_HOSTNAME_KEY2"
+ key3="$REG_HOSTNAME_KEY3"
+ key4="$REG_HOSTNAME_KEY4"
+ key5="$REG_HOSTNAME_KEY5"
+ key6="$REG_HOSTNAME_KEY6"
+ key7="$REG_HOSTNAME_KEY7"
+ key8="$REG_HOSTNAME_KEY8"
+ key9="$REG_HOSTNAME_KEY9"
+ key10="$REG_HOSTNAME_KEY10"
+ key11="$REG_HOSTNAME_KEY11"
+ key12="$REG_HOSTNAME_KEY12"
+ key13="$REG_HOSTNAME_KEY13"
+ key14="$REG_HOSTNAME_KEY14"
+ key15="$REG_HOSTNAME_KEY15"
+ key16="$REG_HOSTNAME_KEY16"
+ key17="$REG_HOSTNAME_KEY17"
+ key18="$REG_HOSTNAME_KEY18"
+ key19="$REG_HOSTNAME_KEY19"
+ key20="$REG_HOSTNAME_KEY20"
+ case $osid in
+ 1)
+ regfile="$REG_LOCAL_MACHINE_XP"
+ ;;
+ 2|4|[5-7]|9)
+ regfile="$REG_LOCAL_MACHINE_7"
+ ;;
+ esac
+ echo "ed $key1" >/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key2" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key3" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key4" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key5" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key6" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key7" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key8" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key9" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key10" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key11" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key12" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key13" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key14" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key15" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key16" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key17" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key18" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key19" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "ed $key20" >>/usr/share/fog/lib/EOFREG
+ echo "$hostname" >>/usr/share/fog/lib/EOFREG
+ echo "q" >> /usr/share/fog/lib/EOFREG
+ echo "y" >> /usr/share/fog/lib/EOFREG
+ echo >> /usr/share/fog/lib/EOFREG
+ fi
+ if [[ -e $regfile ]]; then
+ dots "Changing hostname"
+ reged -e $regfile < /usr/share/fog/lib/EOFREG >/dev/null 2>&1
+ case $? in
+ [0-2])
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ umount /ntfs >/dev/null 2>&1
+ echo " * Failed to change hostname"
+ return
+ ;;
+ esac
+ fi
+ rm -rf /usr/share/fog/lib/EOFREG
+ umount /ntfs >/dev/null 2>&1
+}
+# Fixes windows 7/8 boot, though may need
+# to be updated to only impact windows 7
+# in which case we need a more dynamic method
+#
+# $1 is the partition
+fixWin7boot() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ $osid != [5-7] ]] && return
+ local fstype=""
+ fsTypeSetting "$part"
+ [[ $fstype != ntfs ]] && return
+ dots "Mounting partition"
+ if [[ ! -d /bcdstore ]]; then
+ mkdir -p /bcdstore >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ ntfs-3g -o remove_hiberfile,rw $part /bcdstore >/tmp/ntfs-mount-output 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)"
+ ;;
+ esac
+ if [[ ! -f /bcdstore/Boot/BCD ]]; then
+ umount /bcdstore >/dev/null 2>&1
+ return
+ fi
+ dots "Backing up and replacing BCD"
+ mv /bcdstore/Boot/BCD{,.bak} >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ umount /bcdstore >/dev/null 2>&1
+ echo " * Could not create backup"
+ return
+ ;;
+ esac
+ cp /usr/share/fog/BCD /bcdstore/Boot/BCD >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ umount /bcdstore >/dev/null 2>&1
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ umount /bcdstore >/dev/null 2>&1
+ echo " * Could not copy our bcd file"
+ return
+ ;;
+ esac
+ umount /bcdstore >/dev/null 2>&1
+}
+# Clears out windows hiber and page files
+#
+# $1 is the partition
+clearMountedDevices() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ if [[ ! -d /ntfs ]]; then
+ mkdir -p /ntfs >/dev/null 2>&1
+ case $? in
+ 0)
+ umount /ntfs >/dev/null 2>&1
+ ;;
+ *)
+ handleError "Could not create mount point /ntfs (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ case $osid in
+ 4|[5-7]|9)
+ local fstype=""
+ fsTypeSetting "$part"
+ REG_HOSTNAME_MOUNTED_DEVICES_7="\MountedDevices"
+ if [[ ! -f /usr/share/fog/lib/EOFMOUNT ]]; then
+ echo "cd $REG_HOSTNAME_MOUNTED_DEVICES_7" >/usr/share/fog/lib/EOFMOUNT
+ echo "dellallv" >>/usr/share/fog/lib/EOFMOUNT
+ echo "q" >>/usr/share/fog/lib/EOFMOUNT
+ echo "y" >>/usr/share/fog/lib/EOFMOUNT
+ echo >> /usr/share/fog/lib/EOFMOUNT
+ fi
+ case $fstype in
+ ntfs)
+ dots "Clearing part ($part)"
+ ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)"
+ ;;
+ esac
+ if [[ ! -f $REG_LOCAL_MACHINE_7 ]]; then
+ echo "Reg file not found"
+ debugPause
+ umount /ntfs >/dev/null 2>&1
+ return
+ fi
+ reged -e $REG_LOCAL_MACHINE_7 </usr/share/fog/lib/EOFMOUNT >/dev/null 2>&1
+ case $? in
+ [0-2])
+ echo "Done"
+ debugPause
+ umount /ntfs >/dev/null 2>&1
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ /umount /ntfs >/dev/null 2>&1
+ echo " * Could not clear partition $part"
+ return
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+}
+# Only removes the page file
+#
+# $1 is the device name of the windows system partition
+removePageFile() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local fstype=""
+ fsTypeSetting "$part"
+ [[ ! $ignorepg -eq 1 ]] && return
+ case $osid in
+ [1-2]|4|[5-7]|[9]|50|51)
+ case $fstype in
+ ntfs)
+ dots "Mounting partition ($part)"
+ if [[ ! -d /ntfs ]]; then
+ mkdir -p /ntfs >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not create mount location (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fi
+ umount /ntfs >/dev/null 2>&1
+ ntfs-3g -o remove_hiberfile,rw $part /ntfs >/tmp/ntfs-mount-output 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError " * Could not mount $part (${FUNCNAME[0]})\n Args Passed: $*\n Reason: $(cat /tmp/ntfs-mount-output)"
+ ;;
+ esac
+ if [[ -f /ntfs/pagefile.sys ]]; then
+ dots "Removing page file"
+ rm -rf /ntfs/pagefile.sys >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ echo " * Could not delete the page file"
+ ;;
+ esac
+ fi
+ if [[ -f /ntfs/hiberfil.sys ]]; then
+ dots "Removing hibernate file"
+ rm -rf /ntfs/hiberfil.sys >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ umount /ntfs >/dev/null 2>&1
+ echo " * Could not delete the hibernate file"
+ ;;
+ esac
+ fi
+ umount /ntfs >/dev/null 2>&1
+ ;;
+ esac
+ ;;
+ esac
+}
+# Sets OS mbr, as needed, and returns the Name
+# based on the OS id passed.
+#
+# $1 the osid to determine the os and mbr
+determineOS() {
+ local osid="$1"
+ [[ -z $osid ]] && handleError "No os id passed (${FUNCNAME[0]})\n Args Passed: $*"
+ case $osid in
+ 1)
+ osname="Windows XP"
+ mbrfile="/usr/share/fog/mbr/xp.mbr"
+ ;;
+ 2)
+ osname="Windows Vista"
+ mbrfile="/usr/share/fog/mbr/vista.mbr"
+ ;;
+ 3)
+ osname="Windows 98"
+ mbrfile=""
+ ;;
+ 4)
+ osname="Windows (Other)"
+ mbrfile=""
+ ;;
+ 5)
+ osname="Windows 7"
+ mbrfile="/usr/share/fog/mbr/win7.mbr"
+ defaultpart2start="105906176B"
+ ;;
+ 6)
+ osname="Windows 8"
+ mbrfile="/usr/share/fog/mbr/win8.mbr"
+ defaultpart2start="368050176B"
+ ;;
+ 7)
+ osname="Windows 8.1"
+ mbrfile="/usr/share/fog/mbr/win8.mbr"
+ defaultpart2start="368050176B"
+ ;;
+ 8)
+ osname="Apple Mac OS"
+ mbrfile=""
+ ;;
+ 9)
+ osname="Windows 10"
+ mbrfile=""
+ ;;
+ 50)
+ osname="Linux"
+ mbrfile=""
+ ;;
+ 51)
+ osname="Chromium OS"
+ mbrfile=""
+ ;;
+ 99)
+ osname="Other OS"
+ mbrfile=""
+ ;;
+ *)
+ handleError " * Invalid OS ID ($osid) (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+}
+# Converts the string (seconds) passed to human understanding
+#
+# $1 the seconds to convert
+sec2string() {
+ local T="$1"
+ [[ -z $T ]] && handleError "No string passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local d=$((T/60/60/24))
+ local H=$((T/60/60%24))
+ local i=$((T/60%60))
+ local s=$((T%60))
+ local dayspace=''
+ local hourspace=''
+ local minspace=''
+ [[ $H > 0 ]] && dayspace=' '
+ [[ $i > 0 ]] && hourspace=':'
+ [[ $s > 0 ]] && minspace=':'
+ (($d > 0)) && printf '%d day%s' "$d" "$dayspace"
+ (($H > 0)) && printf '%d%s' "$H" "$hourspace"
+ (($i > 0)) && printf '%d%s' "$i" "$minspace"
+ (($s > 0)) && printf '%d' "$s"
+}
+# Returns the disk based off the partition passed
+#
+# $1 is the partition to grab the disk from
+getDiskFromPartition() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ disk=$(echo $part | sed 's/p\?[0-9]\+$//g')
+}
+# Returns the number of the partition passed
+#
+# $1 is the partition to get the partition number for
+getPartitionNumber() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ part_number=$(echo $part | grep -o '[0-9]*$')
+}
+# $1 is the partition to search for.
+getPartitions() {
+ local disk="$1"
+ [[ -z $disk ]] && disk="$hd"
+ [[ -z $disk ]] && handleError "No disk found (${FUNCNAME[0]})\n Args Passed: $*"
+ parts=$(lsblk -I 3,8,9,179,259 -lpno KNAME,TYPE $disk | awk '{if ($2 ~ /part/ || $2 ~ /md/) print $1}' | sort -V | uniq)
+}
+# Gets the hard drive on the host
+# Note: This function makes a best guess
+getHardDisk() {
+ [[ -n $fdrive ]] && hd=$(echo $fdrive)
+ [[ -n $hd ]] && return
+ local devs=$(lsblk -dpno KNAME -I 3,8,9,179,259 | uniq | sort -V)
+ disks=$(echo $devs)
+ [[ -z $disks ]] && handleError "Cannot find disk on system (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ $1 == true ]] && return
+ for hd in $disks; do
+ break
+ done
+}
+# Finds the hard drive info and set's up the type
+findHDDInfo() {
+ case $imgType in
+ [Nn]|mps|dd)
+ dots "Looking for Hard Disk"
+ getHardDisk
+ if [[ -z $hd ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Could not find hard disk ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ case $type in
+ down)
+ diskSize=$(lsblk --bytes -dplno SIZE -I 3,8,9,179,259 $hd)
+ [[ $diskSize -gt 2199023255552 ]] && layPartSize="2tB"
+ echo " * Using Disk: $hd"
+ [[ $imgType == +([nN]) ]] && validResizeOS
+ enableWriteCache "$hd"
+ ;;
+ up)
+ dots "Reading Partition Tables"
+ runPartprobe "$hd"
+ getPartitions "$hd"
+ if [[ -z $parts ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Could not find partitions ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ ;;
+ esac
+ echo " * Using Hard Disk: $hd"
+ ;;
+ mpa)
+ dots "Looking for Hard Disks"
+ getHardDisk "true"
+ if [[ -z $disks ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Could not find any disks ($0)\n Args Passed: $*"
+ fi
+ echo "Done"
+ debugPause
+ case $type in
+ up)
+ for disk in $disks; do
+ dots "Reading Partition Tables on $disk"
+ getPartitions "$disk"
+ if [[ -z $parts ]]; then
+ echo "Failed"
+ debugPause
+ echo " * No partitions for disk $disk"
+ debugPause
+ continue
+ fi
+ echo "Done"
+ debugPause
+ done
+ ;;
+ esac
+ echo " * Using Disks: $disks"
+ ;;
+ esac
+}
+
+# Imaging complete
+completeTasking() {
+ case $type in
+ up)
+ chmod -R 777 "$imagePath" >/dev/null 2>&1
+ killStatusReporter
+ . /bin/fog.imgcomplete
+ ;;
+ down)
+ killStatusReporter
+ if [[ -f /images/postdownloadscripts/fog.postdownload ]]; then
+ postdownpath="/images/postdownloadscripts/"
+ . ${postdownpath}fog.postdownload
+ fi
+ [[ $capone -eq 1 ]] && exit 0
+ if [[ $osid == +([1-2]|4|[5-7]|9) ]]; then
+ for disk in $disks; do
+ getPartitions "$disk"
+ for part in $parts; do
+ fsTypeSetting "$part"
+ [[ $fstype == ntfs ]] && changeHostname "$part"
+ done
+ done
+ fi
+ . /bin/fog.imgcomplete
+ ;;
+ esac
+}
+# Corrects mbr layout for Vista OS
+#
+# $1 is the disk to correct for
+correctVistaMBR() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ dots "Correcting Vista MBR"
+ dd if=$disk of=/tmp.mbr count=1 bs=512 >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not create backup (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ xxd /tmp.mbr /tmp.mbr.txt >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "xxd command failed (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ rm /tmp.mbr >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Couldn't remove /tmp.mbr file (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ fogmbrfix /tmp.mbr.txt /tmp.mbr.fix.txt >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "fogmbrfix failed to operate (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ rm /tmp.mbr.txt >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not remove the text file (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ xxd -r /tmp.mbr.fix.txt /mbr.mbr >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not run second xxd command (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ rm /tmp.mbr.fix.txt >/dev/null 2>&1
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not remove the fix file (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ dd if=/mbr.mbr of="$disk" count=1 bs=512 >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not apply fixed MBR (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+}
+# Prints an error with visible information
+#
+# $1 is the string to inform what went wrong
+handleError() {
+ local str="$1"
+ local parts=""
+ local part=""
+ echo "##############################################################################"
+ echo "# #"
+ echo "# An error has been detected! #"
+ echo "# #"
+ echo "##############################################################################"
+ echo -e "$str"
+ #
+ # expand the file systems in the restored partitions
+ #
+ # Windows 7, 8, 8.1:
+ # Windows 2000/XP, Vista:
+ # Linux:
+ if [[ -n $2 ]]; then
+ case $osid in
+ [1-2]|4|[5-7]|9|50|51)
+ if [[ -n "$hd" ]]; then
+ getPartitions "$hd"
+ for part in $parts; do
+ expandPartition "$part"
+ done
+ fi
+ ;;
+ esac
+ fi
+ if [[ -z $isdebug ]]; then
+ echo "##############################################################################"
+ echo "# #"
+ echo "# Computer will reboot in 1 minute #"
+ echo "# #"
+ echo "##############################################################################"
+ usleep 60000000
+ else
+ debugPause
+ fi
+ exit 1
+}
+# Prints a visible banner describing an issue but not breaking
+#
+# $1 The string to inform the user what the problem is
+handleWarning() {
+ local str="$1"
+ echo "##############################################################################"
+ echo "# #"
+ echo "# A warning has been detected! #"
+ echo "# #"
+ echo "##############################################################################"
+ echo -e "$str"
+ echo "##############################################################################"
+ echo "# #"
+ echo "# Will continue in 1 minute #"
+ echo "# #"
+ echo "##############################################################################"
+ usleep 60000000
+ debugPause
+}
+# Re-reads the partition table of the disk passed
+#
+# $1 is the disk
+runPartprobe() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ umount /ntfs /bcdstore >/dev/null 2>&1
+ udevadm settle
+ blockdev --rereadpt $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to read back partitions (${FUNCNAME[0]})\n Args Passed: $*"
+}
+# Sends a command list to a file for use when debugging
+#
+# $1 The string of the command needed to run.
+debugCommand() {
+ local str="$1"
+ case $isdebug in
+ [Yy][Ee][Ss]|[Yy])
+ echo -e "$str" >> /tmp/cmdlist
+ ;;
+ esac
+}
+# Escapes the passed item where needed
+#
+# $1 the item that needs to be escaped
+escapeItem() {
+ local item="$1"
+ echo $item | sed -r 's%/%\\/%g'
+}
+# uploadFormat
+# Description:
+# Tells the system what format to upload in, whether split or not.
+# Expects first argument to be the fifo to send to.
+# Expects part of the filename in the case of resizable
+# will append 000 001 002 automatically
+#
+# $1 The fifo name (file in file out)
+# $2 The file to upload into on the server
+uploadFormat() {
+ local fifo="$1"
+ local file="$2"
+ [[ -z $fifo ]] && handleError "Missing file in file out (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "Missing file name to store (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ ! -e $fifo ]] && mkfifo $fifo >/dev/null 2>&1
+ case $imgFormat in
+ 2)
+ pigz $PIGZ_COMP < $fifo | split -a 3 -d -b 200m - ${file}. &
+ ;;
+ *)
+ pigz $PIGZ_COMP < $fifo > ${file}.000 &
+ ;;
+ esac
+}
+# Thank you, fractal13 Code Base
+#
+# Save enough MBR and embedding area to capture all of GRUB
+# Strategy is to capture EVERYTHING before the first partition.
+# Then, leave a marker that this is a GRUB MBR for restoration.
+# We could get away with less storage, but more details are required
+# to parse the information correctly. It would make the process
+# more complicated.
+#
+# See the discussion about the diskboot.img and the sector list
+# here: http://banane-krumm.de/bootloader/grub2.html
+#
+# Expects:
+# the device name (e.g. /dev/sda) as the first parameter,
+# the disk number (e.g. 1) as the second parameter
+# the directory to store images in (e.g. /image/dev/xyz) as the third parameter
+#
+# $1 is the disk
+# $2 is the disk number
+# $3 is the image path to save the file to.
+# $4 is the determinator of sgdisk use or not
+saveGRUB() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local sgdisk="$4"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ # Determine the number of sectors to copy
+ # Hack Note: print $4+0 causes the column to be interpretted as a number
+ # so the comma is tossed
+ local count=$(sfdisk -d $disk 2>/dev/null | awk /start=\ *[1-9]/'{print $4+0}' | sort -n | head -n1)
+ local has_grub=$(dd if=$disk bs=512 count=1 2>&1 | grep -i 'grub')
+ local hasgrubfilename=""
+ if [[ -n $has_grub ]]; then
+ hasGrubFileName "$imagePath" "$disk_number" "$sgdisk"
+ touch $hasgrubfilename
+ fi
+ # Ensure that no more than 1MiB of data is copied (already have this size used elsewhere)
+ [[ $count -gt 2048 ]] && count=2048
+ local mbrfilename=""
+ MBRFileName "$imagePath" "$disk_number" "mbrfilename" "$sgdisk"
+ dd if=$disk of=$mbrfilename count=$count bs=512 >/dev/null 2>&1
+}
+# Checks for the existence of the grub embedding area in the image directory.
+# Echos 1 for true, and 0 for false.
+#
+# Expects:
+# the device name (e.g. /dev/sda) as the first parameter,
+# the disk number (e.g. 1) as the second parameter
+# the directory images stored in (e.g. /image/xyz) as the third parameter
+# $1 is the disk
+# $2 is the disk number
+# $3 is the image path
+# $4 is the sgdisk determinator
+hasGRUB() {
+ local disk_number="$1"
+ local imagePath="$2"
+ local sgdisk="$3"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local hasgrubfilename=""
+ hasGrubFileName "$imagePath" "$disk_number" "$sgdisk"
+ hasGRUB=0
+ [[ -e $hasgrubfilename ]] && hasGRUB=1
+}
+# Restore the grub boot record and all of the embedding area data
+# necessary for grub2.
+#
+# Expects:
+# the device name (e.g. /dev/sda) as the first parameter,
+# the disk number (e.g. 1) as the second parameter
+# the directory images stored in (e.g. /image/xyz) as the third parameter
+# $1 is the disk
+# $2 is the disk number
+# $3 is the image path
+# $4 is the sgdisk determinator
+restoreGRUB() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local sgdisk="$4"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local tmpMBR=""
+ MBRFileName "$imagePath" "$disk_number" "tmpMBR" "$sgdisk"
+ local count=$(du -B 512 $tmpMBR | awk '{print $1}')
+ [[ $count -eq 8 ]] && count=1
+ dd if=$tmpMBR of=$disk bs=512 count=$count >/dev/null 2>&1
+ runPartprobe "$disk"
+}
+# Waits for enter if system is debug type
+debugPause() {
+ case $isdebug in
+ [Yy][Ee][Ss]|[Yy])
+ echo " * Press [Enter] key to continue"
+ read -p "$*"
+ ;;
+ *)
+ return
+ ;;
+ esac
+}
+debugEcho() {
+ local str="$*"
+ case $isdebug in
+ [Yy][Ee][Ss]|[Yy])
+ echo "$str"
+ ;;
+ *)
+ return
+ ;;
+ esac
+}
+majorDebugEcho() {
+ [[ $ismajordebug -gt 1 ]] && echo "$*"
+}
+majorDebugPause() {
+ [[ ! $ismajordebug -gt 0 ]] && return
+ echo " * Press [Enter] key to continue"
+ read -p "$*"
+}
+swapUUIDFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ swapuuidfilename="$imagePath/d${disk_number}.original.swapuuids"
+}
+mainUUIDFileName() {
+ local imagePath="$1"
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ mainuuidfilename="$imagePath/d${disk_number}.original.uuids"
+}
+sfdiskPartitionFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdiskoriginalpartitionfilename="$imagePath/d${disk_number}.partitions"
+}
+sfdiskLegacyOriginalPartitionFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdisklegacyoriginalpartitionfilename="$imagePath/d${disk_number}.original.partitions"
+}
+sfdiskMinimumPartitionFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdiskminimumpartitionfilename="$imagePath/d${disk_number}.minimum.partitions"
+}
+sfdiskOriginalPartitionFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdiskPartitionFileName "$imagePath" "$disk_number"
+}
+sgdiskOriginalPartitionFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sgdiskoriginalpartitionfilename="$imagePath/d${disk_number}.sgdisk.original.partitions"
+}
+fixedSizePartitionsFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ fixed_size_file="$imagePath/d${disk_number}.fixed_size_partitions"
+}
+hasGrubFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ local sgdisk="$3"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ hasgrubfilename="$imagePath/d${disk_number}.has_grub"
+ [[ -n $sgdisk ]] && hasgrubfilename="$imagePath/d${disk_number}.grub.mbr"
+}
+MBRFileName() {
+ local imagePath="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ local varVar="$3"
+ local sgdisk="$4"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $varVar ]] && handleError "No variable to set passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local mbr=""
+ local hasGRUB=0
+ hasGRUB "$disk_number" "$imagePath" "$sgdisk"
+ [[ -n $sgdisk && $hasGRUB -eq 1 ]] && mbr="$imagePath/d${disk_number}.grub.mbr" || mbr="$imagePath/d${disk_number}.mbr"
+ case $type in
+ down)
+ [[ ! -f $mbr && -n $mbrfile ]] && mbr="$mbrfile"
+ printf -v "$varVar" "$mbr"
+ [[ -z $mbr ]] && handleError "Image store corrupt, unable to locate MBR, no default file specified (${FUNCNAME[0]})\n Args Passed: $*\n $varVar Variable set to: ${!varVar}"
+ [[ ! -f $mbr ]] && handleError "Image store corrupt, unable to locate MBR, no file found (${FUNCNAME[0]})\n Args Passed: $*\n Variable set to: ${!varVar}\n $varVar Variable set to: ${!varVar}"
+ ;;
+ up)
+ printf -v "$varVar" "$mbr"
+ ;;
+ esac
+}
+EBRFileName() {
+ local path="$1" # e.g. /net/dev/foo
+ local disk_number="$2" # e.g. 1
+ local part_number="$3" # e.g. 5
+ [[ -z $path ]] && handleError "No path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $part_number ]] && handleError "No partition number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ ebrfilename="$path/d${disk_number}p${part_number}.ebr"
+}
+tmpEBRFileName() {
+ local disk_number="$1"
+ local part_number="$2"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $part_number ]] && handleError "No partition number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local ebrfilename=""
+ EBRFileName "/tmp" "$disk_number" "$disk_number"
+ tmpebrfilename="$ebrfilename"
+}
+#
+# Works for MBR/DOS or GPT style partition tables
+# Only saves PT information if the type is "all" or "mbr"
+#
+# For MBR/DOS style PT
+# Saves the MBR as everything before the start of the first partition (512+ bytes)
+# This includes the DOS MBR or GRUB. Don't know about other bootloaders
+# This includes the 4 primary partitions
+# The EBR of extended and logical partitions is actually the first 512 bytes of
+# the partition, so we don't need to save/restore them here.
+#
+#
+savePartitionTablesAndBootLoaders() {
+ local disk="$1" # e.g. /dev/sda
+ local disk_number="$2" # e.g. 1
+ local imagePath="$3" # e.g. /net/dev/foo
+ local osid="$4" # e.g. 50
+ local imgPartitionType="$5"
+ local sfdiskfilename="$6"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No img part type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ if [[ -z $sfdiskfilename ]]; then
+ sfdiskPartitionFileName "$imagePath" "$disk_number"
+ sfdiskfilename="$sfdiskoriginalpartitionfilename"
+ fi
+ local hasgpt=0
+ hasGPT "$disk"
+ local have_extended_partition=0 # e.g. 0 or 1-n (extended partition count)
+ local strdots=""
+ [[ $hasgpt -eq 0 ]] && have_extended_partition=$(sfdisk -l $disk 2>/dev/null | egrep "^${disk}.* (Extended|W95 Ext'd \(LBA\))$" | wc -l)
+ runPartprobe "$disk"
+ case $hasgpt in
+ 0)
+ strdots="Saving Partition Tables (MBR)"
+ case $osid in
+ 4|50|51)
+ [[ $disk_number -eq 1 ]] && strdots="Saving Partition Tables and GRUB (MBR)"
+ ;;
+ esac
+ dots "$strdots"
+ saveGRUB "$disk" "$disk_number" "$imagePath"
+ sfdisk -d $disk 2>/dev/null > $sfdiskfilename
+ [[ $have_extended_partition -ge 1 ]] && saveAllEBRs "$disk" "$disk_number" "$imagePath"
+ echo "Done"
+ ;;
+ 1)
+ dots "Saving Partition Tables (GPT)"
+ saveGRUB "$disk" "$disk_number" "$imagePath" "true"
+ sgdisk -b "$imagePath/d${disk_number}.mbr" $disk >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Error trying to save GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ sfdisk -d $disk 2>/dev/null > $sfdiskfilename
+ echo "Done"
+ ;;
+ esac
+ runPartprobe "$disk"
+ debugPause
+}
+clearPartitionTables() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ $nombr -eq 1 ]] && return
+ dots "Erasing current MBR/GPT Tables"
+ sgdisk -Z $disk >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ 2)
+ echo "Done, but cleared corrupted partition."
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Error trying to erase partition tables (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ runPartprobe "$disk"
+ debugPause
+}
+# Restores the partition tables and boot loaders
+#
+# $1 is the disk
+# $2 is the disk number
+# $3 is the image path
+# $4 is the osid
+# $5 is the image partition type
+restorePartitionTablesAndBootLoaders() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local osid="$4"
+ local imgPartitionType="$5"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No image part type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local tmpMBR=""
+ local strdots=""
+ if [[ $nombr -eq 1 ]]; then
+ echo " * Skipping partition tables and MBR"
+ debugPause
+ return
+ fi
+ clearPartitionTables "$disk"
+ majorDebugEcho "Partition table should be empty now."
+ majorDebugShowCurrentPartitionTable "$disk" "$disk_number"
+ majorDebugPause
+ MBRFileName "$imagePath" "$disk_number" "tmpMBR"
+ [[ ! -f $tmpMBR ]] && handleError "Image Store Corrupt: Unable to locate MBR (${FUNCNAME[0]})\n Args Passed: $*"
+ local table_type=""
+ getDesiredPartitionTableType "$imagePath" "$disk_number"
+ majorDebugEcho "Trying to restore to $table_type partition table."
+ if [[ $table_type == GPT ]]; then
+ dots "Restoring Partition Tables (GPT)"
+ restoreGRUB "$disk" "$disk_number" "$imagePath" "true"
+ sgdisk -gel $tmpMBR $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Error trying to restore GPT partition tables (${FUNCNAME[0]})\n Args Passed: $*"
+ global_gptcheck="yes"
+ echo "Done"
+ else
+ case $osid in
+ 50|51)
+ strdots="Restoring Partition Tables and GRUB (MBR)"
+ ;;
+ *)
+ strdots="Restoring Partition Tables (MBR)"
+ ;;
+ esac
+ dots "$strdots"
+ restoreGRUB "$disk" "$disk_number" "$imagePath"
+ echo "Done"
+ debugPause
+ majorDebugShowCurrentPartitionTable "$disk" "$disk_number"
+ majorDebugPause
+ ebrcount=$(ls -1 $imagePath/*.ebr 2>/dev/null | wc -l)
+ [[ $ebrcount -gt 0 ]] && restoreAllEBRs "$disk" "$disk_number" "$imagePath" "$imgPartitionType"
+ local sfdiskoriginalpartitionfilename=""
+ local sfdisklegacyoriginalpartitionfilename=""
+ sfdiskPartitionFileName "$imagePath" "$disk_number"
+ sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number"
+ if [[ -r $sfdiskoriginalpartitionfilename ]]; then
+ dots "Inserting Extended partitions"
+ sfdisk $disk < $sfdiskoriginalpartitionfilename >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ ;;
+ esac
+ elif [[ -e $sfdisklegacyoriginalpartitionfilename ]]; then
+ dots "Extended partitions (legacy)"
+ sfdisk $disk < $sfdisklegacyoriginalpartitionfilename >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ ;;
+ esac
+ else
+ echo " * No extended partitions"
+ fi
+ fi
+ debugPause
+ runPartprobe "$disk"
+ majorDebugShowCurrentPartitionTable "$disk" "$disk_number"
+ majorDebugPause
+}
+savePartition() {
+ local part="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local part_number=0
+ getPartitionNumber "$part"
+ local fstype=""
+ local parttype=""
+ local imgpart=""
+ local fifoname="/tmp/pigz1"
+ if [[ $imgPartitionType != all && $imgPartitionType != $part_number ]]; then
+ echo " * Skipping partition $part ($part_number)"
+ debugPause
+ return
+ fi
+ echo " * Processing Partition: $part ($part_number)"
+ debugPause
+ fsTypeSetting "$part"
+ getPartType "$part"
+ local ebrfilename=""
+ local swapuuidfilename=""
+ case $fstype in
+ swap)
+ echo " * Saving swap partition UUID"
+ swapUUIDFileName "$imagePath" "$disk_number"
+ saveSwapUUID "$swapuuidfilename" "$part"
+ ;;
+ *)
+ case $parttype in
+ 0x5|0xf)
+ echo " * Not capturing content of extended partition"
+ debugPause
+ EBRFileName "$imagePath" "$disk_number" "$part_number"
+ touch "$ebrfilename"
+ ;;
+ *)
+ echo " * Using partclone.$fstype"
+ debugPause
+ imgpart="$imagePath/d${disk_number}p${part_number}.img"
+ uploadFormat "$fifoname" "$imgpart"
+ partclone.$fstype -fsck-src-part -c -s $part -O $fifoname -N -f 1
+ case $? in
+ 0)
+ mv ${imgpart}.000 $imgpart >/dev/null 2>&1
+ echo " * Image Captured"
+ ;;
+ *)
+ handleError "Failed to complete capture (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ rm -rf $fifoname >/dev/null 2>&1
+ debugPause
+}
+restorePartition() {
+ local part="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local mc="$4"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ if [[ $imgPartitionType != all && $imgPartitionType != $part_number ]]; then
+ echo " * Skipping partition: $part ($part_number)"
+ debugPause
+ return
+ fi
+ local imgpart=""
+ local ebrfilename=""
+ local disk=""
+ local part_number=0
+ getDiskFromPartition "$part"
+ getPartitionNumber "$part"
+ echo " * Processing Partition: $part ($part_number)"
+ debugPause
+ case $imgType in
+ dd)
+ imgpart="$imagePath"
+ ;;
+ n|mps|mpa)
+ case $osid in
+ [1-2])
+ [[ -f $imagePath ]] && imgpart="$imagePath" || imgpart="$imagePath/d${disk_number}p${part_number}.img*"
+ ;;
+ 4|8|50|51)
+ imgpart="$imagePath/d${disk_number}p${part_number}.img*"
+ ;;
+ [5-7]|9)
+ [[ ! -f $imagePath/sys.img.000 ]] && imgpart="$imagePath/d${disk_number}p${part_number}.img*"
+ if [[ -z $imgpart ]] ;then
+ case $win7partcnt in
+ 1)
+ imgpart="$imagePath/sys.img.*"
+ ;;
+ 2)
+ case $part_number in
+ 1)
+ imgpart="$imagePath/rec.img.000"
+ ;;
+ 2)
+ imgpart="$imagePath/sys.img.*"
+ ;;
+ esac
+ ;;
+ 3)
+ case $part_number in
+ 1)
+ imgpart="$imagePath/rec.img.000"
+ ;;
+ 2)
+ imgpart="$imagePath/rec.img.001"
+ ;;
+ 3)
+ imgpart="$imagePath/sys.img.*"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ handleError "Invalid Image Type $imgType (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ ls $imgpart >/dev/null 2>&1
+ if [[ ! $? -eq 0 ]]; then
+ EBRFileName "$imagePath" "$disk_number" "$part_number"
+ [[ -e $ebrfilename ]] && echo " * Not deploying content of extended partition" || echo " * Partition File Missing: $imgpart"
+ runPartprobe "$disk"
+ return
+ fi
+ writeImage "$imgpart" "$part" "$mc"
+ runPartprobe "$disk"
+ resetFlag "$part"
+}
+runFixparts() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ dots "Attempting fixparts"
+ fixparts $disk </usr/share/fog/lib/EOFFIXPARTS >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not fix partition layout (${FUNCNAME[0]})\n Args Passed: $*" "yes"
+ ;;
+ esac
+ debugPause
+ runPartprobe "$disk"
+}
+killStatusReporter() {
+ dots "Stopping FOG Status Reporter"
+ kill -9 $statusReporter >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ ;;
+ esac
+ debugPause
+}
+prepareResizeDownloadPartitions() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local osid="$4"
+ local imgPartitionType="$5"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $osid ]] && handleError "No osid passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No image partition type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ if [[ $nombr -eq 1 ]]; then
+ echo -e " * Skipping partition preperation\n"
+ debugPause
+ return
+ fi
+ restorePartitionTablesAndBootLoaders "$disk" "$disk_number" "$imagePath" "$osid" "$imgPartitionType"
+ local do_fill=0
+ fillDiskWithPartitionsIsOK "$disk" "$imagePath" "$disk_number"
+ majorDebugEcho "Filling disk = $do_fill"
+ dots "Attempting to expand/fill partitions"
+ if [[ $do_fill -eq 0 ]]; then
+ echo "Failed"
+ debugPause
+ handleError "Fatal Error: Could not resize partitions (${FUNCNAME[0]})\n Args Passed: $*"
+ fi
+ fillDiskWithPartitions "$disk" "$imagePath" "$disk_number"
+ echo "Done"
+ debugPause
+ runPartprobe "$disk"
+}
+# $1 is the disks
+# $2 is the image path
+# $3 is the image partition type (either all or partition number)
+# $4 is the flag to say whether this is multicast or not
+performRestore() {
+ local disks="$1"
+ local disk=""
+ local imagePath="$2"
+ local imgPartitionType="$3"
+ local mc="$4"
+ [[ -z $disks ]] && handleError "No disks passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk_number=1
+ local part_number=0
+ local restoreparts=""
+ local mainuuidfilename=""
+ [[ $imgType =~ [Nn] ]] && local tmpebrfilename=""
+ for disk in $disks; do
+ mainuuidfilename=""
+ mainUUIDFileName "$imagePath" "$disk_number"
+ getValidRestorePartitions "$disk" "$disk_number" "$imagePath" "$restoreparts"
+ [[ -z $restoreparts ]] && handleError "No image file(s) found that would match the partition(s) to be restored (${FUNCNAME[0]})\n Args Passed: $*"
+ for restorepart in $restoreparts; do
+ getPartitionNumber "$restorepart"
+ [[ $imgType =~ [Nn] ]] && tmpEBRFileName "$disk_number" "$part_number"
+ restorePartition "$restorepart" "$disk_number" "$imagePath" "$mc"
+ [[ $imgType =~ [Nn] ]] && restoreEBR "$restorepart" "$tmpebrfilename"
+ [[ $imgType =~ [Nn] ]] && expandPartition "$restorepart" "$fixed_size_partitions"
+ [[ $osid == +([5-7]) && $imgType =~ [Nn] ]] && fixWin7boot "$restorepart"
+ done
+ restoreparts=""
+ echo " * Resetting UUIDs for $disk"
+ debugPause
+ restoreUUIDInformation "$disk" "$mainuuidfilename"
+ echo " * Resettings swap systems"
+ debugPause
+ makeAllSwapSystems "$disk" "$disk_number" "$imagePath" "$imgPartitionType"
+ let disk_number+=1
+ done
+}
diff --git a/draft/other-tools/fog/partition-funcs.sh b/draft/other-tools/fog/partition-funcs.sh
new file mode 100644
index 0000000..8d77ec5
--- /dev/null
+++ b/draft/other-tools/fog/partition-funcs.sh
@@ -0,0 +1,811 @@
+#!/bin/bash
+#
+# These functions are for dealing with resizing of partitions.
+# They currently work for MBR and Extended partition tables.
+# THE DO NOT WORK FOR GPT.
+# It is assumed that at most 1 extended partition will exist,
+# with any number of logical partitions.
+# Requires the sfdisk tool.
+# Assumes that sfdisk's "unit: sectors" means 512 byte sectors.
+#
+# $1 is the name of the disk drive
+# $2 is name of file to save to.
+saveSfdiskPartitions() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to save to (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdisk -d $disk 2>/dev/null > $file
+ [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})"
+}
+# $1 is the name of the disk drive
+# $2 is name of file to save to.
+saveUUIDInformation() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to save to passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local hasgpt=0
+ hasGPT "$disk"
+ [[ $hasgpt -eq 0 ]] && return
+ rm -f $file
+ touch $file
+ local diskuuid=""
+ local partuuid=""
+ local partfsuuid=""
+ local parts=""
+ local part=""
+ local part_number=""
+ local strtoadd=""
+ local is_swap=0
+ getDiskUUID "$disk"
+ echo "$disk $diskuuid" >> $file
+ getPartitions "$disk"
+ for part in $parts; do
+ getPartitionNumber "$part"
+ partitionIsSwap "$part"
+ [[ $is_swap -gt 0 ]] && continue
+ getPartUUID "$part"
+ getPartFSUUID "$part"
+ [[ -n $partfsuuid ]] && strtoadd="$part $part_number:$partfsuuid"
+ [[ -n $partuuid ]] && strtoadd="$strtoadd $part_number:$partuuid"
+ echo "$strtoadd" >> $file
+ strtoadd=""
+ done
+}
+# $1 is the name of the disk drive
+# $2 is name of file to restore from
+restoreUUIDInformation() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to load from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ ! -r $file ]] && return
+ local diskuuid=""
+ local partuuid=""
+ local escape_disk=$(escapeItem $disk)
+ local escape_part=""
+ local is_swap=0
+ diskuuid=$(awk "/^$escape_disk\ /{print \$2}" $file)
+ [[ -n $diskuuid ]] && sgdisk -U $diskuuid $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to set disk guid (sgdisk -U) (${FUNCNAME[0]})\n Args Passed: $*"
+ getPartitions "$disk"
+ for part in $parts; do
+ partitionIsSwap "$part"
+ [[ $is_swap -gt 0 ]] && continue
+ escape_part=$(escapeItem $part)
+ local oIFS=$IFS
+ local IFS=$'\n'
+ read partuuid parttype <<< $(awk "/^$escape_part\ /{printf(\"%s\n%s\",\$2,\$3)}" $file)
+ IFS=$oIFS
+ [[ -n $parttype ]] && sgdisk -t $parttype $disk >/dev/null 2>&1 || true
+ [[ ! $? -eq 0 ]] && handleError " Failed to set partition type (sgdisk -t) (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -n $partuuid ]] && sgdisk -u $partuuid $disk >/dev/null 2>&1 || true
+ [[ ! $? -eq 0 ]] && handleError "Failed to set partition guid (sgdisk -u) (${FUNCNAME[0]})\n Args Passed: $*"
+ done
+}
+# $1 is the name of the disk drive
+# $2 is name of file to load from.
+applySfdiskPartitions() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdisk $disk < $file >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})"
+}
+# $1 is the name of the disk drive
+# $2 is the name of file to load from.
+applySgdiskPartitions() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local escape_disk=$(escapeItem $disk)
+ local diskguid=$(awk -F: "/^$escape_disk:/{print \$3}" $file)
+ sgdisk -Z $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partitions (sgdisk -Z) (${FUNCNAME[0]})\n Args Passed: $*"
+ sgdisk -U $diskguid $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partitions (sgdisk -U) (${FUNCNAME[0]})\n Args Passed: $*"
+ local parts=""
+ local part=""
+ local part_number=""
+ local escape_part=""
+ local partstart=""
+ local partend=""
+ local parttype=""
+ local partcode=""
+ local partname=""
+ local awk_part_vars=""
+ getPartitions "$disk"
+ for part in $parts; do
+ escape_part=$(escapeItem $part)
+ getParititionNumber "$part"
+ awk_part_vars=$(awk -F: "/^$escape_part:/{printf(\"%d %d %d %d\",\$3,\$4,\$5,\$6)}" $file)
+ read partcode partstart partend partname <<< $awk_part_vars
+ parttype=$(awk -F: "/^part:$part_number:/{print \$5}" $file)
+ sgdisk -n $part_number:$partstart:$partend $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -n) (${FUNCNAME[0]})\n Args Passed: $*"
+ sgdisk -c $part_number:$partname $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -c) (${FUNCNAME[0]})\n Args Passed: $*"
+ sgdisk -t $part_number:$parttype $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -t) (${FUNCNAME[0]})\n Args Passed: $*"
+ sgdisk -u $part_number:$partcode $disk >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && handleError "Failed to restore partition (sgdisk -u) (${FUNCNAME[0]})\n Args Passed: $*"
+ done
+}
+# $1 is the name of the disk drive
+# $2 is name of file to load from.
+restoreSfdiskPartitions() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ applySfdiskPartitions "$disk" "$file"
+ fdisk $disk < /usr/share/fog/lib/EOFRESTOREPART >/dev/null 2>&1
+ [[ ! $? -eq 0 ]] && majorDebugEcho "fdisk failed in (${FUNCNAME[0]})"
+}
+# $1 is the name of the disk drive
+# $2 is name of file to restore from.
+restoreSgdiskPartitions() {
+ local disk="$1"
+ local file="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to restore from (${FUNCNAME[0]})\n Args Passed: $*"
+ applySgdiskPartitions "$disk" "$file"
+}
+# $1 is the name of the disk drive
+hasExtendedPartition() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ sfdisk -d $disk 2>/dev/null | egrep '(Id|type)=\ *[5f]' | wc -l
+ [[ ! $? -eq 0 ]] && majorDebugEcho "sfdisk failed in (${FUNCNAME[0]})"
+}
+# $1 is the name of the partition device (e.g. /dev/sda3)
+partitionHasEBR() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local part_number=0
+ local disk=""
+ local parttype=""
+ getDiskFromPartition "$part"
+ getPartitionNumber "$part"
+ getPartType "$part"
+ hasEBR=0
+ [[ $part_number -ge 5 ]] && hasEBR=1
+ [[ $parttype == +(0x5|0xf) ]] && hasEBR=1
+}
+# $1 is the name of the partition device (e.g. /dev/sda3)
+# $2 is the name of the file to save to (e.g. /net/dev/foo/d1p4.ebr)
+saveEBR() {
+ local part="$1"
+ local file="$2"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ getDiskFromPartition "$part"
+ local table_type=""
+ getPartitionTableType "$disk"
+ [[ $table_type != MBR ]] && return
+ local hasEBR=0
+ partitionHasEBR "$part"
+ [[ ! $hasEBR -gt 0 ]] && return
+ dots "Saving EBR for ($part)"
+ dd if=$part of=$file bs=512 count=1 >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not backup EBR (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+}
+# $1 = DriveName (e.g. /dev/sdb)
+# $2 = DriveNumber (e.g. 1)
+# $3 = ImagePath (e.g. /net/foo)
+saveAllEBRs() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local parts=""
+ local part=""
+ local part_number=0
+ local ebrfilename=""
+ getPartitions "$disk"
+ for part in $parts; do
+ getPartitionNumber "$part"
+ EBRFileName "$imagePath" "$disk_number" "$part_number"
+ saveEBR "$part" "$ebrfilename"
+ done
+}
+# $1 is the name of the partition device (e.g. /dev/sda3)
+# $2 is the name of the file to restore from (e.g. /net/foo/d1p4.ebr)
+restoreEBR() {
+ local part="$1"
+ local file="$2"
+ [[ -z $part ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to restore from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ local table_type=""
+ getDiskFromPartition "$part"
+ getPartitionTableType "$disk"
+ [[ $table_type != MBR ]] && return
+ local hasEBR=0
+ partitionHasEBR "$part"
+ [[ ! $hasEBR -gt 0 ]] && return
+ [[ ! -e $file ]] && return
+ dots "Restoring EBR for ($part)"
+ dd of=$part if=$file bs=512 count=1 >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ debugPause
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not reload EBR data (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+}
+# $1 = DriveName (e.g. /dev/sdb)
+# $2 = DriveNumber (e.g. 1)
+# $3 = ImagePath (e.g. /net/foo)
+# $4 = ImagePartitionType (e.g. all, mbr, 1, 2, 3, etc.)
+restoreAllEBRs() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ local imgPartitionType="$4"
+ local ebffilename=""
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imgPartitionType ]] && handleError "No partition type passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local parts=""
+ local part=""
+ local part_number=0
+ local ebrfilename=""
+ getPartitions "$disk"
+ for part in $parts; do
+ getPartitionNumber "$part"
+ [[ $imgPartitionType != all && $imgPartitionType != $part_number ]] && continue
+ EBRFileName "$imagePath" "$disk_number" "$part_number"
+ restoreEBR "$part" "$ebrfilename"
+ done
+ runPartprobe "$disk"
+}
+# $1 is the name of the partition device (e.g. /dev/sda3)
+partitionIsSwap() {
+ local part="$1"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local fstype=""
+ fsTypeSetting "$part"
+ is_swap=0
+ [[ $fstype == swap ]] && is_swap=1
+}
+# $1 is the location of the file to store uuids in
+# $2 is the partition device name
+saveSwapUUID() {
+ local file="$1"
+ local part="$2"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to receive from passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local is_swap=0
+ partitionIsSwap "$part"
+ [[ $is_swap -eq 0 ]] && return
+ local uuid=$(blkid -s UUID $2 | cut -d\" -f2)
+ [[ -z $uuid ]] && return
+ echo " * Saving UUID ($uuid) for ($part)"
+ echo "$part $uuid" >> $file
+}
+# Linux swap partition strategy:
+#
+# Upload:
+#
+# In "n" mode, the empty swapUUIDFileName is created first. Then as each
+# partition is saved, if it is swap then saveSwapUUID is called.
+# In "mps" and "mpa" mode, savePartition is called for each partition.
+# savePartition then calles saveSwapUUID if the partition is swap.
+#
+# When uploading an image, the swapUUIDFileName (e.g. /images/foo/d1.original.swapuuids)
+# is created. For $imgPartitionType == "all", all swap partition UUIDs are saved.
+# For $imgPartitionType == "$partnum", the partition's UUID is saved, if it is a swap partition.
+# For all others, the swapUUIDFileName will not exist, or will be empty.
+#
+#
+# Download:
+#
+# When downloading an image, makeAllSwapSystems will be called.
+# In "n" mode this is done for those images without special configurations,
+# after normal partition restoration.
+# In "mps" mode this is always done
+# In "mpa" mode this is always done, for all disks.
+# makeAllSwapSystems will determine using
+# $imagePartitionType == "all" or == "$partnum" whether to
+# process the swapUUIDFileName contents. For each matching partition,
+# mkswap is used, and the UUID is set appropriately.
+#
+# Relevant functions:
+# swapUUIDFileName ImagePath DriveNumber
+# echos the standardized name for the UUID filename
+# partitionIsSwap PartitionName
+# echos 1 or 0 if fsTypeSetting says partition is or is not a swap partition.
+# makeSwapSystem SwapUUIDFileName PartitionName
+# if it finds partition in UUID file, then calls mkswap
+# makeAllSwapSystems DriveName DriveNumber ImagePath ImagePartitionType
+# checks ImagePartitionType for a match before calling makeSwapSystem
+# saveSwapUUID SwapUUIDFileName PartitionName
+# checks if paritionIsSwap, if so, obtains UUID and saves it
+# saveAllSwapUUIDs DriveName DriveNumber ImagePath
+# checks all partitions if partitionIsSwap, calles saveSwapUUID
+# savePartition:
+# calls saveSwapUUID for swap partitions
+#
+#
+# $1 = DriveName (e.g. /dev/sdb)
+# $2 = DriveNumber (e.g. 1)
+# $3 = ImagePath (e.g. /net/foo)
+saveAllSwapUUIDs() {
+ local disk="$1"
+ local disk_number="$2"
+ local imagePath="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local swapuuidfilename=""
+ swapUUIDFileName "$imagePath" "$disk_number"
+ local parts=""
+ local part=""
+ local is_swap=0
+ getPartitions "$disk"
+ for part in $parts; do
+ partitionIsSwap "$part"
+ [[ $is_swap -eq 0 ]] && continue
+ saveSwapUUID "$swapuuidfilename" "$part"
+ done
+}
+# $1 is the location of the file uuids are stored in
+# $2 is the partition device name
+makeSwapSystem() {
+ local file="$1"
+ local part="$2"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local uuid=""
+ local option=""
+ local disk=""
+ getDiskFromPartition "$part"
+ local parttype=0
+ local hasgpt=""
+ local escape_part=$(escapeItem $part)
+ hasGPT "$disk"
+ case $hasgpt in
+ 1)
+ uuid=$(awk "/^$escape_part/{print \$2}" $file)
+ [[ -n $uuid ]] && parttype=82
+ ;;
+ 0)
+ parttype=$(sfdisk -d $disk 2>/dev/null | awk -F[,=] "/^$escape_part/{print \$6}")
+ ;;
+ esac
+ [[ ! $parttype -eq 82 ]] && return
+ [[ -n $uuid ]] && option="-U $uuid"
+ dots "Restoring swap partition"
+ mkswap $option $part >/dev/null 2>&1
+ case $? in
+ 0)
+ echo "Done"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Could not create swap on $part (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ debugPause
+}
+# $1 is the partition device (e.g. /dev/sda1)
+# $2 is the new desired size in 1024 (1k) blocks
+# $3 is the image path (e.g. /net/dev/foo)
+resizeSfdiskPartition() {
+ local part="$1"
+ local size="$2"
+ local imagePath="$3"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $size ]] && handleError "No desired size passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ getDiskFromPartition "$part"
+ local tmp_file="/tmp/sfdisk.$$"
+ local tmp_file2="/tmp/sfdisk2.$$"
+ saveSfdiskPartitions "$disk" "$tmp_file"
+ processSfdisk "$tmp_file" resize "$part" "$size" > "$tmp_file2"
+ if [[ $ismajordebug -gt 0 ]]; then
+ majorDebugEcho "Trying to fill the disk with these partitions:"
+ cat $tmp_file2
+ majorDebugPause
+ fi
+ applySfdiskPartitions "$disk" "$tmp_file2"
+ local sfdiskminimumpartitionfilename=""
+ sfdiskMinimumPartitionFileName "$imagePath" 1
+ saveSfdiskPartitions "$disk" "$imagePath"
+}
+# $1 is the disk device (e.g. /dev/sda)
+# $2 is the name of the original sfdisk -d output file used as a template
+# $3 is the : separated list of fixed size partitions (e.g. 1:2)
+# swap partitions are automatically added. Empty string is
+# ok.
+fillSfdiskWithPartitions() {
+ local disk="$1"
+ local file="$2"
+ local fixed="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $file ]] && handleError "No file to use passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk_size=$(blockdev --getsize64 $disk | awk '{printf("%d\n",$1/1024);}')
+ local tmp_file2="/tmp/sfdisk2.$$"
+ processSfdisk "$file" filldisk "$disk" "$disk_size" "$fixed" > "$tmp_file2"
+ if [[ $ismajordebug -gt 0 ]]; then
+ majorDebugEcho "Trying to fill with the disk with these partititions:"
+ cat $tmp_file2
+ majorDebugPause
+ fi
+ [[ $? -eq 0 ]] && applySfdiskPartitions "$disk" "$tmp_file2"
+ runPartprobe "$disk"
+ rm -f $tmp_file2
+ majorDebugEcho "Applied the preceding table."
+ majorDebugShowCurrentPartitionTable "$disk" 1
+ majorDebugPause
+}
+#
+# processSfdisk() processes the output of sfdisk -d
+# and creates a new sfdisk -d like output, applying
+# the requested action. Read below to see the actions
+#
+# $1 the name of a file that is the output of sfdisk -d
+# $2 is the action "resize|other?"
+# $3 is the first parameter
+# $4 is the second parameter
+# ...
+#
+# actions:
+# processSfdisk foo.sfdisk resize /dev/sda1 100000
+# foo.sfdisk = sfdisk -d output
+# resize = action
+# /dev/sda1 = partition to modify
+# 100000 = 1024 byte blocks size to make it
+# output: new sfdisk -d like output
+#
+# processSfdisk foo.sfdisk move /dev/sda1 100000
+# foo.sfdisk = sfdisk -d output
+# move = action
+# /dev/sda1 = partition to modify
+# 100000 = 1024 byte blocks size to move it to
+# output: new sfdisk -d like output
+#
+# processSfdisk foo.sfdisk filldisk /dev/sda 100000 1:3:6
+# foo.sfdisk = sfdisk -d output
+# filldisk = action
+# /dev/sda = disk to modify
+# 100000 = 1024 byte blocks size of disk
+# 1:3:6 = partition numbers that are fixed in size, : separated
+# output: new sfdisk -d like output
+#
+# example file data
+# /dev/sda1 : start= 2048, size= 204800, Id= 7, bootable
+# /dev/sda2 : start= 206848, size= 50573312, Id= 7
+# /dev/sda3 : start= 50780160, size= 2048, Id=83
+# /dev/sda4 : start= 50784254, size= 16322562, Id= 5
+# /dev/sda5 : start= 50784256, size= 7811072, Id=83
+# /dev/sda6 : start= 58597376, size= 8509440, Id=82
+#
+processSfdisk() {
+ local data="$1"
+ local action="$2"
+ local target="$3"
+ local size="$4"
+ local fixed="$5"
+ [[ -z $data ]] && handleError "No data passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $action ]] && handleError "No action passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $target ]] && handleError "Device (disk or partition) not passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $size ]] && handleError "No desired size passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local minstart=$(awk -F'[ ,]+' '/start/{if ($4) print $4}' $data | sort -n | head -1)
+ local chunksize=""
+ getPartBlockSize "$disk" "chunksize"
+ case $osid in
+ [1-2])
+ [[ -z $minstart ]] && chunksize=512
+ [[ -z $minstart ]] && minstart=63
+ ;;
+ esac
+ local awkArgs="-v CHUNK_SIZE=$chunksize -v MIN_START=$minstart"
+ awkArgs="$awkArgs -v action=$action -v target=$target -v sizePos=$size"
+ [[ -n $fixed ]] && awkArgs="$awkArgs -v fixedList=$fixed"
+ # process with external awk script
+ /usr/share/fog/lib/procsfdisk.awk $awkArgs $data
+}
+#
+# GPT Functions below
+#
+# $1 : device name of drive
+getPartitionTableType() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local mbr=$(yes '' | gdisk -l $disk | awk '/^\ *MBR:/{print $2}')
+ local gpt=$(yes '' | gdisk -l $disk | awk '/^\ *GPT:/{print $2}')
+ local type=""
+ local mbrtype=""
+ local gpttype=""
+ case $mbr in
+ present|MBR)
+ mbrtype="MBR"
+ ;;
+ hybrid)
+ mbrtype="HYBRID"
+ ;;
+ protective|not)
+ mbrtype=""
+ ;;
+ esac
+ case $gpt in
+ present|damaged)
+ gpttype="GPT"
+ ;;
+ not)
+ gpttype=""
+ ;;
+ esac
+ [[ -z $gpttype && -z $mbrtype ]] && handleError "Cannot determine partition type (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -n $gpttype && -n $mbrtype ]] && table_type="$gpttype-$mbrtype"
+ [[ -n $gpttype && -z $mbrtype ]] && table_type="$gpttype"
+ [[ -z $gpttype && -n $mbrtype ]] && table_type="$mbrtype"
+}
+#
+# Detect the desired partition table type,
+# using the available files in imagePath, don't rely
+# on the actual disk.
+#
+# Assumes GPT or MBR. Uses first 8 bytes of second block
+# which should hold "EFI PART". (https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_table_header_.28LBA_1.29)
+#
+# $1 : imagePath (e.g. /images/foo)
+# $2 : disk number (e.g. 1)
+getDesiredPartitionTableType() {
+ local imagePath="$1"
+ local disk_number="$2"
+ [[ -z $disk_number ]] && handleError "No drive number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ table_type="MBR"
+ local mbrfilename=""
+ MBRFileName "$imagePath" "$disk_number" "mbrfilename"
+ [[ ! -r $mbrfilename ]] && return
+ local tmpfile="/tmp/gptsig"
+ dd skip=512 bs=1 if=$mbrfilename of=$tmpfile count=8 >/dev/null 2>&1
+ touch $tmpfile
+ local gptsig=$(cat $tmpfile)
+ [[ $gptsig == "EFI PART" ]] && table_type="GPT"
+}
+# $1 : device name of drive
+hasHybridMBR() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local mbr=$(gdisk -l $disk | awk '/^\ *MBR:/{print $2}')
+ [[ $mbr == hybrid ]] && echo 1 || echo 0
+}
+# $1 : device name of drive
+hasGPT() {
+ local disk="$1"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local gpt=$(gdisk -l $disk | awk -F'[(: )]' '/GPT:/ {print $5}')
+ [[ $gpt == present ]] && hasgpt=1
+ [[ $gpt == not ]] && hasgpt=0
+}
+#
+# Detect the partition table type, then call the correct
+# resizePartition function
+#
+# $1 is the partition device (e.g. /dev/sda1)
+# $2 is the new desired size in 1024 (1k) blocks
+# $3 is the image path (e.g. /net/dev/foo)
+resizePartition() {
+ local part="$1"
+ local size="$2"
+ local imagePath="$3"
+ [[ -z $part ]] && handleError "No partition passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $size ]] && handleError "No size passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local disk=""
+ local table_type=""
+ getDiskFromPartition "$part"
+ getPartitionTableType "$disk"
+ case $table_type in
+ MBR|GPT)
+ local sfdiskoriginalpartitionfilename=""
+ local sfdisklegacyoriginalpartitionfilename=""
+ resizeSfdiskPartition "$part" "$size" "$imagePath"
+ ;;
+ *)
+ handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ # make sure kernel knows about the changes
+ runPartprobe "$disk"
+}
+#
+# Detect the partition table type, then save all relevant
+# partition information
+#
+# $1 : device name of the drive
+# $2 : imagePath
+# $3 : disk number
+saveOriginalPartitions() {
+ local disk="$1"
+ local imagePath="$2"
+ local disk_number="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local table_type=""
+ getPartitionTableType "$disk"
+ case $table_type in
+ MBR|GPT)
+ local sfdiskoriginalpartitionfilename=""
+ sfdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ saveSfdiskPartitions "$disk" "$sfdiskoriginalpartitionfilename"
+ ;;
+ GPT-MBR)
+ echo "Failed"
+ debugPause
+ runFixparts "$disk"
+ dots "Retrying to save partition table"
+ saveOriginalPartitions "$disk" "$imagePath" "$disk_number"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ runPartprobe "$disk"
+}
+#
+# Detect the partition table type, then restore partition
+# sizes, using saved partition information
+#
+# $1 : device name of the drive
+# $2 : imagePath
+# $3 : disk number
+restoreOriginalPartitions() {
+ local disk="$1"
+ local imagePath="$2"
+ local disk_number="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local table_type=""
+ getPartitionTableType "$disk"
+ case $table_type in
+ MBR|GPT)
+ local sfdiskoriginalpartitionfilename=""
+ local sfdisklegacyoriginalpartitionfilename=""
+ local sgdiskoriginalpartitionfilename=""
+ local cmdtorun='restoreSfdiskPartitions'
+ sfdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number"
+ sgdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ local filename="$sfdiskoriginalpartitionfilename"
+ [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename"
+ [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename" && cmdtorun='restoreSgdiskPartitions'
+ [[ ! -r $filename ]] && handleError "Failed to find a restore file (${FUNCNAME[0]})\n Args Passed: $*"
+ $cmdtorun "$disk" "$filename"
+ ;;
+ *)
+ handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ # make sure kernel knows about the changes
+ runPartprobe "$disk"
+}
+#
+# Detect the partition table type, the fill the disk with
+# the partitions, using the correct routine.
+#
+# $1 : the disk device (e.g. /dev/sda)
+# $2 : imagePath (e.g. /images/foo)
+# $3 : disk number (e.g. 1)
+fillDiskWithPartitions() {
+ local disk="$1"
+ local imagePath="$2"
+ local disk_number="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local fixed_size_file=""
+ fixedSizePartitionsFileName "$imagePath" "$disk_number"
+ [[ -r $fixed_size_file ]] && fixed_size_partitions=$(cat $fixed_size_file)
+ local table_type=""
+ getDesiredPartitionTableType "$imagePath" "$disk_number"
+ local sfdiskoriginalpartitionfilename=""
+ local sfdisklegacyoriginalpartitionfilename=""
+ local sgdiskoriginalpartitionfilename=""
+ case $table_type in
+ MBR|GPT)
+ sfdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number"
+ sgdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ local filename="$sfdiskoriginalpartitionfilename"
+ local cmdtorun='fillSfdiskWithPartitions'
+ [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename"
+ [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename"
+ [[ $filename == $sgdiskoriginalpartitionfilename ]] && cmdtorun='fillSgdiskWithPartitions'
+ [[ ! -r $filename ]] && handleError "Failed to find a restore file (${FUNCNAME[0]})\n Args Passed: $*"
+ $cmdtorun "$disk" "$filename" "$fixed_size_partitions"
+ ;;
+ *)
+ echo "Failed"
+ debugPause
+ handleError "Unexpected partition table type: $table_type (${FUNCNAME[0]})\n Args Passed: $*"
+ ;;
+ esac
+ # make sure kernel knows about the changes
+ runPartprobe "$disk"
+}
+#
+# Check if it will be ok to call fillDiskWithPartitions
+#
+# $1 : the disk device (e.g. /dev/sda)
+# $2 : imagePath (e.g. /images/foo)
+# $3 : disk number (e.g. 1)
+fillDiskWithPartitionsIsOK() {
+ local disk="$1"
+ local imagePath="$2"
+ local disk_number="$3"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $imagePath ]] && handleError "No image path passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local table_type=""
+ getDesiredPartitionTableType "$imagePath" "$disk_number"
+ local filename=""
+ local sfdiskoriginalpartitionfilename=""
+ local sfdisklegacyoriginalpartitionfilename=""
+ local sgdiskoriginalpartitionfilename=""
+ do_fill=1
+ case $table_type in
+ MBR|GPT)
+ sfdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ sfdiskLegacyOriginalPartitionFileName "$imagePath" "$disk_number"
+ sgdiskOriginalPartitionFileName "$imagePath" "$disk_number"
+ filename="$sfdiskoriginalpartitionfilename"
+ [[ ! -r $filename ]] && filename="$sfdisklegacyoriginalpartitionfilename"
+ [[ ! -r $filename ]] && filename="$sgdiskoriginalpartitionfilename"
+ [[ ! -r $filename ]] && do_fill=0
+ ;;
+ esac
+}
+#
+# Show the current partition table
+#
+# $1 : the disk device (e.g. /dev/sda)
+# $2 : disk number (e.g. 1)
+majorDebugShowCurrentPartitionTable() {
+ [[ $ismajordebug -le 0 ]] && return
+ local disk="$1"
+ local disk_number="$2"
+ [[ -z $disk ]] && handleError "No disk passed (${FUNCNAME[0]})\n Args Passed: $*"
+ [[ -z $disk_number ]] && handleError "No disk number passed (${FUNCNAME[0]})\n Args Passed: $*"
+ local table_type=""
+ getDesiredPartitionTableType "$imagePath" "$disk_number"
+ echo "Current partition table:"
+ case $table_type in
+ MBR|GPT)
+ sfdisk -d $disk
+ ;;
+ esac
+}
diff --git a/draft/other-tools/fog/procsfdisk.awk b/draft/other-tools/fog/procsfdisk.awk
new file mode 100644
index 0000000..ac18749
--- /dev/null
+++ b/draft/other-tools/fog/procsfdisk.awk
@@ -0,0 +1,361 @@
+#!/usr/bin/awk -f
+
+#$data is the filename of the output of sfdisk -d
+
+#cat $data | awk -F, '\
+
+# For readability, function parameters are on the first line. Locally scoped
+# variables are on the following lines.
+
+function display_output(partition_names, partitions, \
+ pName) {
+ if (!unit) {
+ unit = "sectors";
+ }
+ if (!label) {
+ type = "Id=";
+ } else {
+ type = "type=";
+ }
+ if (label && labelid && device) {
+ printf("label: %s\n", label);
+ printf("label-id: %s\n", labelid);
+ printf("device: %s\n", device);
+ }
+ printf("unit: %s\n\n", unit);
+ for(pName in partition_names) {
+ printf("%s : start=%10d, size=%10d, %s%2s", partitions[pName, "device"], partitions[pName, "start"], partitions[pName, "size"],
+ type, partitions[pName, "type"]);
+ if(label == "dos") {
+ if(partitions[pName, "flags"] != "") {
+ printf("%s", partitions[pName, "flags"]);
+ }
+ } else if (label == "gpt") {
+ if(partitions[pName, "uuid"] != "") {
+ printf(", uuid=%s", partitions[pName, "uuid"]);
+ }
+ if(partitions[pName, "name"] != "") {
+ printf(", name=%s", partitions[pName, "name"]);
+ }
+ if(partitions[pName, "attrs"] != "") {
+ printf(", attrs=%s", partitions[pName, "attrs"]);
+ }
+ } else {
+ if(partitions[pName, "flags"] != "") {
+ printf("%s", partitions[pName, "flags"]);
+ }
+ }
+ printf("\n");
+ }
+}
+
+function check_overlap(partition_names, partitions, new_part_name, new_start, new_size, \
+ extended_margin, new_type, new_part_number, pName, p_type, p_start, p_size, p_part_number) {
+ extended_margin = 2;
+ new_type = partitions[new_part_name, "type"];
+ new_start = new_start + 0;
+ new_size = new_size + 0;
+ new_part_number = partitions[new_part_name, "number"] + 0;
+ for(pName in partition_names) {
+ p_type = partitions[pName, "type"];
+ p_start = partitions[pName, "start"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ p_part_number = partitions[pName, "number"] + 0;
+ # no overlap with self
+ if(new_part_name == pName) { continue; }
+ # ignore empty partitions
+ if(p_size == 0) { continue; }
+ # extended partitions must overlap logical partitions, but leave room for the extended partition table
+ if((p_type == "5" || p_type == "f") && (new_part_number >= 5)) {
+ # new_start is outside of [p_start+margin, p_start + p_size) OR
+ # new_start + new_size is outside of (p_start+margin, p_start + p_size]
+ if((new_start < p_start + extended_margin || new_start >= p_start + p_size) || (new_start + new_size <= p_start + extended_margin || new_start + new_size > p_start + p_size)) {
+ return 1;
+ }
+ }
+ # extended partitions must overlap logical partitions, but leave room for the extended partition table
+ else if((new_type == "5" || new_type == "f") && (p_part_number >= 5)) {
+ # logical partition must be contained in extended partition
+ # p_start is outside of [new_start+margin, new_start + new_size) OR
+ # p_start + p_size is outside of (new_start+margin, new_start + new_size]
+ if((p_start < new_start + extended_margin || p_start >= new_start + new_size) || (p_start + p_size <= new_start + extended_margin || p_start + p_size > new_start + new_size)) {
+ return 1;
+ }
+ }
+ # all other overlap possibilities
+ else {
+ # new_start is inside of [p_start, p_start + p_size) OR
+ # new_start + new_size is inside of (p_start, p_start + p_size]
+ if((new_start >= p_start && new_start < p_start + p_size) || (new_start + new_size > p_start && new_start + new_size <= p_start + p_size)) {
+ return 1;
+ }
+ # p_start is inside of [new_start, new_start + new_size) OR
+ # p_start + p_size is inside of (new_start, new_start + new_size]
+ if((p_start >= new_start && p_start < new_start + new_size) || (p_start + p_size > new_start && p_start + p_size <= new_start + new_size)) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+function check_all_partitions(partition_names, partitions, \
+ pName, p_start, p_size) {
+ for(pName in partition_names) {
+ p_start = partitions[pName, "start"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ if(check_overlap(partition_names, partitions, pName, p_start, p_size) != 0) {
+ printf("ERROR in new partition table, quitting.\n");
+ printf("ERROR: %s has an overlap.\n", pName);
+ #exit(1);
+ }
+ }
+ printf("# Partition table is consistent.\n");
+}
+
+function resize_partition(partition_names, partitions, args, \
+ pName, new_start, new_size) {
+ for(pName in partition_names) {
+ if(pName == target) {
+ if(unit == "sectors") {
+ new_start = partitions[pName, "start"];
+ new_size = sizePos*2;
+ if(check_overlap(partition_names, partitions, target, new_start, new_size) == 0) {
+ partitions[target, "start"] = new_start;
+ partitions[target, "size"] = new_size;
+ }
+ }
+ }
+ }
+}
+
+function move_partition(partition_names, partitions, args, \
+ pName, new_start, new_size) {
+ for(pName in partition_names) {
+ if(pName == target) {
+ if(unit == "sectors") {
+ new_start = (sizePos*2);
+ new_start = new_start - new_start % CHUNK_SIZE;
+ if(new_start < MIN_START) { new_start = MIN_START; }
+ new_size = partitions[pName, "size"];
+ if(check_overlap(partition_names, partitions, target, new_start, new_size) == 0) {
+ partitions[target, "start"] = new_start;
+ partitions[target, "size"] = new_size;
+ }
+ }
+ }
+ }
+}
+
+function fill_disk(partition_names, partitions, args, \
+ disk, disk_size, n, fixed_partitions, original_variable, \
+ original_fixed, new_variable, new_fixed, new_logical, pName, \
+ p_type, p_number, p_size, found, i, partition_starts, \
+ ordered_starts, old_sorted_in, curr_start) {
+ # processSfdisk foo.sfdisk filldisk /dev/sda 100000 1:3:6
+ # foo.sfdisk = sfdisk -d output
+ # filldisk = action
+ # /dev/sda = disk to modify
+ # 100000 = 1024 byte blocks size of disk
+ # 1:3:6 = partition numbers that are fixed in size, : separated
+ disk = target;
+ disk_size = sizePos*2;
+ # add swap partitions to the fixed list
+ for(pName in partition_names) {
+ p_type = partitions[pName, "type"];
+ p_number = partitions[pName, "number"] + "";
+ if(p_type == "82") {
+ fixedList = fixedList ":" p_number;
+ }
+ }
+ n = split(fixedList, fixed_partitions, ":");
+ #
+ # Find the total fixed and variable space
+ #
+ original_variable = 0;
+ original_fixed = MIN_START;
+ for(pName in partition_names) {
+ p_type = partitions[pName, "type"];
+ p_number = partitions[pName, "number"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ partition_starts[partitions[pName, "start"] + 0] = pName;
+ # skip extended partition, only count its logicals and the CHUNK for its partition table
+ if(p_type == "5" || p_type == "f") {
+ original_fixed += CHUNK_SIZE;
+ continue;
+ }
+ # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist)
+ if(p_number >= 5) {
+ original_fixed += CHUNK_SIZE;
+ }
+ if(p_size == 0) { fixed_partitions[pName] = p_number; };
+ found = 0; for(i in fixed_partitions) { if(fixed_partitions[i] == p_number) { found = 1; } };
+ if(found) {
+ original_fixed += partitions[pName, "size"];
+ } else {
+ original_variable += partitions[pName, "size"];
+ }
+ }
+ #
+ # Assign the new sizes to partitions
+ #
+ new_fixed = original_fixed;
+ new_variable = disk_size - original_fixed;
+ new_logical = 0;
+ for(pName in partition_names) {
+ p_type = partitions[pName, "type"];
+ p_number = partitions[pName, "number"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ found = 0;
+ for(i in fixed_partitions) {
+ if(fixed_partitions[i] == p_number) {
+ found = 1;
+ }
+ };
+ if(p_type == "5" || p_type == "f") {
+ partitions[pName, "newsize"] = CHUNK_SIZE;
+ partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE;
+ } else if(found) {
+ partitions[pName, "newsize"] = p_size;
+ partitions[pName, "size"] = partitions[pName, "newsize"];
+ } else {
+ partitions[pName, "newsize"] = (new_variable*p_size/original_variable);
+ partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE;
+ }
+ if(p_number >= 5) {
+ # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist)
+ new_logical += partitions[pName, "size"] + CHUNK_SIZE;
+ }
+ }
+ #
+ # Assign the new size to the extended partition
+ #
+ for(pName in partition_names) {
+ p_type = partitions[pName, "type"];
+ p_number = partitions[pName, "number"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ if(p_type == "5" || p_type == "f") {
+ partitions[pName, "newsize"] += new_logical;
+ partitions[pName, "size"] = partitions[pName, "newsize"] - partitions[pName, "newsize"] % CHUNK_SIZE;
+ }
+ }
+ #
+ # Assign the new start positions
+ #
+ asort(partition_starts, ordered_starts, "@ind_num_asc");
+ old_sorted_in = PROCINFO["sorted_in"];
+ PROCINFO["sorted_in"] = "@ind_num_asc";
+ curr_start = MIN_START;
+ for(i in ordered_starts) {
+ pName = ordered_starts[i];
+ p_type = partitions[pName, "type"];
+ p_number = partitions[pName, "number"] + 0;
+ p_size = partitions[pName, "size"] + 0;
+ p_start = partitions[pName, "start"] + 0;
+ for (j in fixed_partitions) {
+ if (fixed_partitions[j] == p_number) {
+ curr_start = p_start;
+ }
+ }
+ if(p_size > 0) {
+ partitions[pName, "start"] = curr_start;
+ }
+ if(p_type == "5" || p_type == "f") {
+ curr_start += CHUNK_SIZE;
+ } else {
+ curr_start += p_size;
+ }
+ # + CHUNK_SIZE to allow for margin after each logical partition (required if 2 or more logical partitions exist)
+ if(p_number >= 5) {
+ curr_start += CHUNK_SIZE;
+ }
+ }
+ PROCINFO["sorted_in"] = old_sorted_in;
+ check_all_partitions(partition_names, partitions);
+}
+
+BEGIN{
+ #Arguments - Use "-v var=val" when calling this script
+ #CHUNK_SIZE;
+ #MIN_START;
+ #action;
+ #target;
+ #sizePos;
+ #fixedList;
+ label = "";
+ unit = "";
+ partitions[0] = "";
+ partition_names[0] = "";
+}
+
+/^label:/{ label = $2 }
+/^label-id:/{ labelid = $2 }
+/^device:/{ device = $2 }
+/^unit:/{ unit = $2; }
+
+/start=/{
+ # Get Partition Name
+ part_name=$1
+ partitions[part_name, "device"] = part_name
+ partition_names[part_name] = part_name
+
+ # Isolate Partition Number
+ # The regex can handle devices like mmcblk0p3
+ part_number = gensub(/^[^0-9]*[0-9]*[^0-9]+/, "", 1, part_name)
+ partitions[part_name, "number"] = part_number
+
+ # Separate attributes
+ split($0, fields, ",")
+
+ # Get start value
+ gsub(/.*start= */, "", fields[1])
+ partitions[part_name, "start"] = fields[1]
+ # Get size value
+ gsub(/.*size= */, "", fields[2])
+ partitions[part_name, "size"] = fields[2]
+ # Get type/id value
+ gsub(/.*(type|Id)= */, "", fields[3])
+ partitions[part_name, "type"] = fields[3]
+
+ if ( label == "dos" )
+ {
+ split($0, typeList, "type=")
+ part_flags = gensub(/^[^\,$]*/, "",1,typeList[2])
+ partitions[part_name, "flags"] = part_flags;
+ }
+ # GPT elements
+ else if ( label == "gpt" )
+ {
+ # Get uuid value
+ gsub(/.*uuid= */, "", fields[4])
+ partitions[part_name, "uuid"] = fields[4]
+ # Get name value
+ gsub(/.*name= */, "", fields[5])
+ partitions[part_name, "name"] = fields[5]
+ # Get attrs value
+ if (fields[6])
+ {
+ gsub(/.*attrs= */, "", fields[6])
+ partitions[part_name, "attrs"] = fields[6]
+ }
+ }
+ else
+ {
+ split($0, typeList, "Id=")
+ part_flags = gensub(/^[^\,$]*/, "",1,typeList[2])
+ partitions[part_name, "flags"] = part_flags;
+ }
+}
+
+END{
+ delete partitions[0];
+ delete partition_names[0];
+ if(action == "resize") {
+ resize_partition(partition_names, partitions, args);
+ } else if(action == "move") {
+ move_partition(partition_names, partitions, args);
+ } else if(action == "filldisk") {
+ fill_disk(partition_names, partitions, args);
+ }
+ display_output(partition_names, partitions);
+}
diff --git a/draft/other-tools/to-see.txt b/draft/other-tools/to-see.txt
new file mode 100644
index 0000000..926e036
--- /dev/null
+++ b/draft/other-tools/to-see.txt
@@ -0,0 +1,14 @@
+
+http://www.drbl-winroll.org/
+https://wiki.archlinux.org/index.php/Fdisk
+sfdisk -d /dev/sda > sda.dump
+sfdisk /dev/sda < sda.dump
+
+sgdisk -b=sgdisk-sda.bak
+sgdisk -l=sgdisk-sda.bak
+
+If both drives will be in the same computer, you need to randomize the GUID's:
+# sgdisk -G /dev/sdc
+
+
+
diff --git a/draft/uftp-push.sh b/draft/uftp-push.sh
new file mode 100755
index 0000000..ca82c13
--- /dev/null
+++ b/draft/uftp-push.sh
@@ -0,0 +1,8 @@
+IMGDIR=/home/lpouzenc/git/eficast/testimage2
+#RATE_OPTS="-R90000 -W 400 -s 20"
+RATE_OPTS="-C tfmcc -s 20"
+LOG_OPTS="-x2 -S /tmp/uftpd.csv"
+ADDR_OPTS="-M ff02::42 -P ff02::43 -I 3/6" # -I 3/6 is br1 ipv6
+cd /tmp/
+/home/lpouzenc/git/eficast/work/uftp/uftp -f $RATE_OPTS $LOG_OPTS $ADDR_OPTS -- $IMGDIR/*
+
diff --git a/draft/uftp/bug-ts.txt b/draft/uftp/bug-ts.txt
new file mode 100644
index 0000000..304865b
--- /dev/null
+++ b/draft/uftp/bug-ts.txt
@@ -0,0 +1,495 @@
+lpouzenc@lud-x200s:~/git/eficast/uftp/uftp-4.9.2$ ./uftp -f -C tfmcc -s 20 -x2 -S /tmp/uftpd.csv -M ff02::42 -P ff02::43 -I 3/6 -- /home/lpouzenc/git/eficast/testimage/10-restore-mbr.00.sh /home/lpouzenc/git/eficast/testimage/10-restore-mbr.aa /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.00.sh /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.aa /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ab /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ac /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ad /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ae /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.af /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ag /home/lpouzenc/git/eficast/testimage/20-partclone-sda2.img.ah /home/lpouzenc/git/eficast/testimage/99-end
+
+
+UFTP version 4.9.2 Copyright (C) 2001-2016 Dennis A. Bush
+Starting at Mon Dec 19 14:41:09 2016
+Transfer rate: dynamic via TFMCC
+Using private multicast address ff02::43 Group ID: 1AAE76CE
+Initializing group
+Sending ANNOUNCE 1
+Received REGISTER from client 0x7AECB2FE
+Sending REG_CONF 2.1
+Sending ANNOUNCE 2
+Sending ANNOUNCE 3
+Sending ANNOUNCE 4
+Sending ANNOUNCE 5
+Sending ANNOUNCE 6
+Sending ANNOUNCE 7
+Sending ANNOUNCE 8
+Sending ANNOUNCE 9
+Sending ANNOUNCE 10
+Sending ANNOUNCE 11
+Sending ANNOUNCE 12
+Sending ANNOUNCE 13
+Sending ANNOUNCE 14
+Sending ANNOUNCE 15
+Sending ANNOUNCE 16
+Sending ANNOUNCE 17
+Sending ANNOUNCE 18
+Sending ANNOUNCE 19
+Sending ANNOUNCE 20
+----- 10-restore-mbr.00.sh -----
+File ID: 0001 Name: 10-restore-mbr.00.sh
+ sending as: 10-restore-mbr.00.sh
+Bytes: 50 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.016 seconds
+Total elapsed time: 0.016 seconds
+Overall throughput: 2.99 KB/s
+----- 10-restore-mbr.aa -----
+File ID: 0002 Name: 10-restore-mbr.aa
+ sending as: 10-restore-mbr.aa
+Bytes: 512 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.078 seconds
+Total elapsed time: 0.078 seconds
+Overall throughput: 6.39 KB/s
+----- 20-partclone-sda2.img.00.sh -----
+File ID: 0003 Name: 20-partclone-sda2.img.00.sh
+ sending as: 20-partclone-sda2.img.00.sh
+Bytes: 112 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.134 seconds
+Total elapsed time: 0.134 seconds
+Overall throughput: 0.81 KB/s
+----- 20-partclone-sda2.img.aa -----
+File ID: 0004 Name: 20-partclone-sda2.img.aa
+ sending as: 20-partclone-sda2.img.aa
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 412 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Sending section 3
+Got 181 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 192 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 233 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 584 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 32 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 192 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 2
+Sending section 3
+Sending section 4
+Sending section 5
+Got 46 NAKs for section 0 from client 0x7AECB2FE
+Got 104 NAKs for section 3 from client 0x7AECB2FE
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got 120 NAKs for section 4 from client 0x7AECB2FE
+Got 13 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 0
+Sending section 3
+Sending section 4
+Sending section 7
+Sending DONE 1.1
+Got 87 NAKs for section 2 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 2
+Sending DONE 1.1
+Got 348 NAKs for section 5 from client 0x7AECB2FE
+Got 21 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 5
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Sending DONE 2.1
+Got 158 NAKs for section 5 from client 0x7AECB2FE
+Got 21 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 3.1
+Starting pass 6
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 24.500 seconds
+Total elapsed time: 24.500 seconds
+Overall throughput: 4179.58 KB/s
+----- 20-partclone-sda2.img.ab -----
+File ID: 0005 Name: 20-partclone-sda2.img.ab
+ sending as: 20-partclone-sda2.img.ab
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 217 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 81 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 16 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 337 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 60 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 116 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 274 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 215 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Sending section 5
+Sending section 6
+Got 19 NAKs for section 3 from client 0x7AECB2FE
+Sending section 7
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 3
+Sending section 3
+Sending DONE 1.1
+Got 21 NAKs for section 4 from client 0x7AECB2FE
+Got 1 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 4
+Sending section 5
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 19.133 seconds
+Total elapsed time: 19.133 seconds
+Overall throughput: 5351.90 KB/s
+----- 20-partclone-sda2.img.ac -----
+File ID: 0006 Name: 20-partclone-sda2.img.ac
+ sending as: 20-partclone-sda2.img.ac
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 109 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 47 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 477 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 397 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 169 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 273 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 40 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 277 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Got 283 NAKs for section 2 from client 0x7AECB2FE
+Sending section 5
+Got 142 NAKs for section 3 from client 0x7AECB2FE
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 3
+Sending section 2
+Sending section 3
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 18.411 seconds
+Total elapsed time: 18.411 seconds
+Overall throughput: 5562.02 KB/s
+----- 20-partclone-sda2.img.ad -----
+File ID: 0007 Name: 20-partclone-sda2.img.ad
+ sending as: 20-partclone-sda2.img.ad
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 652 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Sending section 3
+Got 509 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 143 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 303 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 58 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 244 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 2
+Sending section 3
+Sending section 4
+Got 245 NAKs for section 0 from client 0x7AECB2FE
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Got 316 NAKs for section 2 from client 0x7AECB2FE
+Got 204 NAKs for section 4 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 0
+Sending section 2
+Got 191 NAKs for section 6 from client 0x7AECB2FE
+Sending section 4
+Sending section 6
+Sending DONE 1.1
+Got 31 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 5
+Sending DONE 1.1
+Got 37 NAKs for section 2 from client 0x7AECB2FE
+Got 99 NAKs for section 3 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 5
+Sending section 2
+Sending section 3
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 20.795 seconds
+Total elapsed time: 20.795 seconds
+Overall throughput: 4924.27 KB/s
+----- 20-partclone-sda2.img.ae -----
+File ID: 0008 Name: 20-partclone-sda2.img.ae
+ sending as: 20-partclone-sda2.img.ae
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 81 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 235 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Sending section 4
+Got 684 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Sending section 6
+Got 273 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 411 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 75 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 3
+Got 21 NAKs for section 1 from client 0x7AECB2FE
+Sending section 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got 474 NAKs for section 3 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 1
+Sending section 3
+Got 34 NAKs for section 7 from client 0x7AECB2FE
+Sending section 7
+Sending DONE 1.1
+Got 24 NAKs for section 3 from client 0x7AECB2FE
+Got 174 NAKs for section 5 from client 0x7AECB2FE
+Got 253 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 3
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 18.859 seconds
+Total elapsed time: 18.859 seconds
+Overall throughput: 5429.67 KB/s
+----- 20-partclone-sda2.img.af -----
+File ID: 0009 Name: 20-partclone-sda2.img.af
+ sending as: 20-partclone-sda2.img.af
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 54 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 359 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 174 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 191 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 260 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 259 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 27 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 225 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Got 15 NAKs for section 2 from client 0x7AECB2FE
+Sending section 5
+Sending section 6
+Sending section 7
+Got 45 NAKs for section 4 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 40 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 2
+Sending section 4
+Sending section 5
+Sending DONE 1.1
+Got 58 NAKs for section 3 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 3
+Sending DONE 1.1
+Got 2 NAKs for section 6 from client 0x7AECB2FE
+Got 34 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 19.850 seconds
+Total elapsed time: 19.850 seconds
+Overall throughput: 5158.63 KB/s
+----- 20-partclone-sda2.img.ag -----
+File ID: 000A Name: 20-partclone-sda2.img.ag
+ sending as: 20-partclone-sda2.img.ag
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 493 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 54 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 573 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Sending section 5
+Got 319 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 37 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 212 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 43 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 4
+Sending section 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got 238 NAKs for section 2 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 2
+Sending DONE 1.1
+Got 27 NAKs for section 7 from client 0x7AECB2FE
+Got 145 NAKs for section 4 from client 0x7AECB2FE
+Got 26 NAKs for section 5 from client 0x7AECB2FE
+Got 124 NAKs for section 6 from client 0x7AECB2FE
+Got 27 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 4
+Sending section 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 19.665 seconds
+Total elapsed time: 19.665 seconds
+Overall throughput: 5207.31 KB/s
+----- 20-partclone-sda2.img.ah -----
+File ID: 000B Name: 20-partclone-sda2.img.ah
+ sending as: 20-partclone-sda2.img.ah
+Bytes: 23054408 Blocks: 17735 Sections: 2
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 82 NAKs for section 0 from client 0x7AECB2FE
+Sending DONE 1.1
+<-------------- 100% CPU and no activity on network. Attached ddd, tried to save session but it fails to save the core file.
+ Abandon
+lpouzenc@lud-x200s:~/git/eficast/uftp/uftp-4.9.2$
+
diff --git a/draft/uftp/notes.txt b/draft/uftp/notes.txt
new file mode 100644
index 0000000..25ee4b0
--- /dev/null
+++ b/draft/uftp/notes.txt
@@ -0,0 +1,42 @@
+
+SRCPART=/dev/sda2
+DESTDIR=/home
+PARTCLONE_EXTRAOPTS="-N"
+SPLIT_SIZE=1G
+
+partclone.imager -c -s $SRCPART -o - $PARTCLONE_EXTRAOPTS | split -b$SPLIT_SIZE - $DESTDIR/partclone-sda2.img.
+
+
+
+----------------
+
+PARTCLONE_EXTRAOPTS="-N"
+DSTPART=/dev/sda2
+./sinkcat.sh /dev/shm/sink | partclone.restore $PARTCLONE_EXTRAOPTS -o $DSTPART
+
+----------------------
+
+# setsockopt(3, SOL_IPV6, 0x2a /* IPV6_??? */, "\2\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\377\3\0\0\0\0\0\0\0\0\0\1\0\2\0\3"..., 136) = -1 EADDRINUSE (Address already in use)
+#write(2, "Error joining multicast group", 29Error joining multicast group) = 29
+#write(2, ": Address already in use", 24: Address already in use) = 24
+
+ADDR_OPTS="-M ff02::42 -I 2/6" # Bug si IP multiples sur même interface
+LOG_OPTS="-x3 -S /tmp/uftpd.csv -L /dev/shm/uftpd.log "
+DIR_OPTS="-T /dev/shm/tmp -D /dev/shm/uftpd -i"
+mkdir /dev/shm/{tmp,uftpd}
+
+./uftpd -q -B 2097152 $LOG_OPTS $ADDR_OPTS $DIR_OPTS
+[ $? -eq 0 ] && netstat -nlu | grep -q ':1044 ' && echo -e '\033[42m' ----- UFTPD ready ----- '\033[40m'
+
+./sinkdo.sh /dev/shm/uftpd /dev/shm/sink
+
+
+---------------------------------------------------
+
+IMGDIR=/home/lpouzenc/git/eficast/testimage
+#RATE_OPTS="-R90000 -W 400 -s 20"
+RATE_OPTS="-C tfmcc -s 20"
+LOG_OPTS="-x2 -S /tmp/uftpd.csv"
+ADDR_OPTS="-M ff02::42 -P ff02::43 -I 3/6" # -I 3/6 is virbr0 ipv6
+
+./uftp -f $RATE_OPTS $LOG_OPTS $ADDR_OPTS -- $IMGDIR/*
diff --git a/draft/uftp/sinkcat.sh b/draft/uftp/sinkcat.sh
new file mode 100755
index 0000000..20ac948
--- /dev/null
+++ b/draft/uftp/sinkcat.sh
@@ -0,0 +1,39 @@
+#!/bin/busybox sh
+
+if [ $# -ne 1 ]
+then cat <<EOT
+Usage: $(basename $0) <sink-dir>
+ Concatenate then delete files as soon they appear in sink-dir to stdout.
+ If multiple files are found in sink, the first in alphabetical order is choosen.
+ <sink-dir> must not exists, this program must create it (avoiding mistakes).
+ Dropping an empty file in dir-sink will clean exit this program.
+EOT
+ exit 1
+fi
+
+SINKDIR=$1
+mkdir "$SINKDIR" && cd "$SINKDIR"
+if [ $? -ne 0 ]
+then echo "Cannot mkdir/chdir to '$SINKDIR'" >&2
+ exit 2
+fi
+
+while true
+do
+ f=$(ls | head -n1)
+ if [ -n "$f" ]
+ then if [ -f "$f" -a -r "$f" ]
+ then size=$(stat -c'%s' -- "$f")
+ # Do the actual work on the following line
+ cat -- "$f" && rm -v -- "$f" >&2
+ # Normal exit condition
+ if [ $size -eq 0 ]
+ then cd / && rmdir -v -- "$SINKDIR" >&2
+ exit 0
+ fi
+ else echo "'$SINKDIR/$f' is not a readable file" >&2
+ exit 3
+ fi
+ fi
+ sleep 1
+done
diff --git a/draft/uftp/sinkdo.sh b/draft/uftp/sinkdo.sh
new file mode 100755
index 0000000..1b46437
--- /dev/null
+++ b/draft/uftp/sinkdo.sh
@@ -0,0 +1,57 @@
+#!/bin/busybox sh
+
+if [ $# -ne 2 ]
+then cat <<EOT
+Usage: $(basename $0) <land-dir> <sink-dir>
+EOT
+ exit 1
+fi
+
+LANDDIR=$1
+SINKDIR=$2
+cd "$LANDDIR" || exit 2
+
+curtask="(start)"
+while true
+do
+ f=$(ls | head -n1)
+ if [ -z "$f" ]
+ then sleep 1
+ continue
+ fi
+ if [ ! -f "$f" -o ! -r "$f" ]
+ then echo "'$LANDDIR/$f' is not a readable file" >&2
+ exit 2
+ fi
+ size=$(stat -c'%s' -- "$f")
+ task=${f:0:2}
+ if [ "$curtask" == "$task" ]
+ then # Next file of an already started task
+ mv "$f" "$SINKDIR/"
+ else # Switch to the next task
+ if [ -d "$SINKDIR" ]
+ then # Inform sinkcat about end-of-data
+ touch -- "$SINKDIR/zz"
+ wait
+ # sinkcat always rmdir "$SINKDIR" on normal exit
+ if [ -d "$SINKDIR" ]
+ then echo "Task $task has ran into troubles" >&2
+ exit 3
+ fi
+ fi
+ echo "Switching from task $curtask to $task" >&2
+ curtask=$task
+ if [ "$task" == "99" ]
+ then # Normal exit condition
+ rm -v "$f" >&2
+ reset
+ echo "All task completed sucessfully" >&2
+ exit 0
+ else # Start a new task
+ chmod +x -- "$f" # XXX Checks on $f (is a script ?)
+ sinkcat.sh $SINKDIR | "./$f" &
+ while [ ! -d "$SINKDIR" ]; do sleep 1; done
+ rm -v "$f" >&2
+ fi
+ fi
+done
diff --git a/draft/uftp/trace-lost-buf.txt b/draft/uftp/trace-lost-buf.txt
new file mode 100644
index 0000000..38d737e
--- /dev/null
+++ b/draft/uftp/trace-lost-buf.txt
@@ -0,0 +1,485 @@
+UFTP version 4.9.2 Copyright (C) 2001-2016 Dennis A. Bush
+--25769-- REDIR: 0x57d3ff0 (libc.so.6:__GI_memcmp) redirected to 0x4c2eca0 (__GI_memcmp)
+--25769-- REDIR: 0x57cf200 (libc.so.6:__GI_strcmp) redirected to 0x4c2d220 (__GI_strcmp)
+--25769-- REDIR: 0x57d0dd0 (libc.so.6:strnlen) redirected to 0x4c2c120 (strnlen)
+Starting at Mon Dec 19 17:26:27 2016
+Transfer rate: dynamic via TFMCC
+Using private multicast address ff02::43 Group ID: ED047C7C
+Initializing group
+--25769-- REDIR: 0xffffffffff600000 (???:???) redirected to 0x380bd803 (vgPlain_amd64_linux_REDIR_FOR_vgettimeofday)
+Sending ANNOUNCE 1
+Received REGISTER from client 0x7AECB2FE
+Sending REG_CONF 2.1
+Sending ANNOUNCE 2
+Sending ANNOUNCE 3
+Sending ANNOUNCE 4
+Sending ANNOUNCE 5
+Sending ANNOUNCE 6
+Sending ANNOUNCE 7
+Sending ANNOUNCE 8
+Sending ANNOUNCE 9
+Sending ANNOUNCE 10
+Sending ANNOUNCE 11
+Sending ANNOUNCE 12
+Sending ANNOUNCE 13
+Sending ANNOUNCE 14
+Sending ANNOUNCE 15
+Sending ANNOUNCE 16
+Sending ANNOUNCE 17
+Sending ANNOUNCE 18
+Sending ANNOUNCE 19
+Sending ANNOUNCE 20
+--25769-- REDIR: 0x57d1030 (libc.so.6:strncmp) redirected to 0x4a23730 (_vgnU_ifunc_wrapper)
+--25769-- REDIR: 0x586e9f0 (libc.so.6:__strncmp_sse42) redirected to 0x4c2ca30 (__strncmp_sse42)
+----- 10-restore-mbr.00.sh -----
+File ID: 0001 Name: 10-restore-mbr.00.sh
+ sending as: 10-restore-mbr.00.sh
+Bytes: 50 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.212 seconds
+Total elapsed time: 0.212 seconds
+Overall throughput: 0.23 KB/s
+----- 10-restore-mbr.aa -----
+File ID: 0002 Name: 10-restore-mbr.aa
+ sending as: 10-restore-mbr.aa
+Bytes: 512 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.045 seconds
+Total elapsed time: 0.045 seconds
+Overall throughput: 11.01 KB/s
+----- 20-partclone-sda2.img.00.sh -----
+File ID: 0003 Name: 20-partclone-sda2.img.00.sh
+ sending as: 20-partclone-sda2.img.00.sh
+Bytes: 112 Blocks: 1 Sections: 1
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.100 seconds
+Total elapsed time: 0.100 seconds
+Overall throughput: 1.10 KB/s
+----- 20-partclone-sda2.img.aa -----
+File ID: 0004 Name: 20-partclone-sda2.img.aa
+ sending as: 20-partclone-sda2.img.aa
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 468 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Sending section 3
+Got 363 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 525 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 157 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 40 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 133 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 45 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 2
+Got 15 NAKs for section 0 from client 0x7AECB2FE
+Sending section 3
+Sending section 4
+Sending section 5
+Got 213 NAKs for section 3 from client 0x7AECB2FE
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 3
+Sending section 0
+Sending section 3
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 25.278 seconds
+Total elapsed time: 25.278 seconds
+Overall throughput: 4051.00 KB/s
+----- 20-partclone-sda2.img.ab -----
+File ID: 0005 Name: 20-partclone-sda2.img.ab
+ sending as: 20-partclone-sda2.img.ab
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 85 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 141 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 86 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 511 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 35 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 785 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Sending DONE 1.1
+Got 238 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Sending section 5
+Got 129 NAKs for section 3 from client 0x7AECB2FE
+Sending section 7
+Sending DONE 1.1
+Got 354 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 3
+Sending section 5
+Sending DONE 1.1
+Got 28 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 5
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 23.408 seconds
+Total elapsed time: 23.408 seconds
+Overall throughput: 4374.56 KB/s
+----- 20-partclone-sda2.img.ac -----
+File ID: 0006 Name: 20-partclone-sda2.img.ac
+ sending as: 20-partclone-sda2.img.ac
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 10 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 158 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 254 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 162 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 482 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 152 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 273 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 195 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Sending section 5
+Sending section 6
+Got 240 NAKs for section 4 from client 0x7AECB2FE
+Sending section 7
+Sending DONE 1.1
+Got 2 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 4
+Sending section 6
+Sending DONE 1.1
+Got 25 NAKs for section 4 from client 0x7AECB2FE
+Got 53 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 4
+Sending section 5
+Sending DONE 1.1
+Got 52 NAKs for section 3 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 5
+Sending section 3
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 21.765 seconds
+Total elapsed time: 21.765 seconds
+Overall throughput: 4704.82 KB/s
+----- 20-partclone-sda2.img.ad -----
+File ID: 0007 Name: 20-partclone-sda2.img.ad
+ sending as: 20-partclone-sda2.img.ad
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 202 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 116 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 341 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Sending section 5
+Got 744 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Sending section 7
+Got 634 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 422 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 4
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 21.724 seconds
+Total elapsed time: 21.724 seconds
+Overall throughput: 4713.78 KB/s
+----- 20-partclone-sda2.img.ae -----
+File ID: 0008 Name: 20-partclone-sda2.img.ae
+ sending as: 20-partclone-sda2.img.ae
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 197 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 28 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 784 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 140 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 203 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 257 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 279 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 104 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 3
+Sending section 4
+Got 400 NAKs for section 2 from client 0x7AECB2FE
+Sending section 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 3
+Sending section 2
+Sending DONE 1.1
+Got 32 NAKs for section 5 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 4
+Sending section 5
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 21.747 seconds
+Total elapsed time: 21.747 seconds
+Overall throughput: 4708.69 KB/s
+----- 20-partclone-sda2.img.af -----
+File ID: 0009 Name: 20-partclone-sda2.img.af
+ sending as: 20-partclone-sda2.img.af
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 310 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Got 162 NAKs for section 1 from client 0x7AECB2FE
+Sending section 3
+Got 326 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Sending section 5
+Got 59 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 502 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 308 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending section 2
+Sending section 4
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Got 122 NAKs for section 5 from client 0x7AECB2FE
+Got 40 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 3
+Sending section 5
+Sending section 6
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 23.670 seconds
+Total elapsed time: 23.670 seconds
+Overall throughput: 4326.17 KB/s
+----- 20-partclone-sda2.img.ag -----
+File ID: 000A Name: 20-partclone-sda2.img.ag
+ sending as: 20-partclone-sda2.img.ag
+Bytes: 104857600 Blocks: 80660 Sections: 8
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 337 NAKs for section 0 from client 0x7AECB2FE
+Sending section 2
+Sending section 3
+Got 1629 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Got 289 NAKs for section 3 from client 0x7AECB2FE
+Sending section 5
+Got 372 NAKs for section 4 from client 0x7AECB2FE
+Sending section 6
+Got 33 NAKs for section 5 from client 0x7AECB2FE
+Sending section 7
+Got 525 NAKs for section 6 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 157 NAKs for section 7 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 2
+Got 26 NAKs for section 0 from client 0x7AECB2FE
+Sending section 3
+Got 4 NAKs for section 2 from client 0x7AECB2FE
+Sending section 4
+Sending section 5
+Sending section 6
+Sending section 7
+Sending DONE 1.1
+Sending DONE 2.1
+Starting pass 3
+Sending section 0
+Sending section 2
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 21.727 seconds
+Total elapsed time: 21.727 seconds
+Overall throughput: 4712.95 KB/s
+----- 20-partclone-sda2.img.ah -----
+File ID: 000B Name: 20-partclone-sda2.img.ah
+ sending as: 20-partclone-sda2.img.ah
+Bytes: 23054408 Blocks: 17735 Sections: 2
+Sending FILEINFO 1.1
+Rejecting COMPLETE from 0x7AECB2FE: invalid file ID 000A, expected 000B
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending section 0
+Sending section 1
+Got 194 NAKs for section 0 from client 0x7AECB2FE
+Sending DONE 1.1
+Got 81 NAKs for section 1 from client 0x7AECB2FE
+Sending DONE 2.1
+Starting pass 2
+Sending section 0
+Sending section 1
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 9.598 seconds
+Total elapsed time: 9.598 seconds
+Overall throughput: 2345.77 KB/s
+----- 99-end -----
+File ID: 000C Name: 99-end
+ sending as: 99-end
+Bytes: 0 Blocks: 0 Sections: 0
+Sending FILEINFO 1.1
+Received FILEINFO_ACK from client 0x7AECB2FE
+Sending file
+Starting pass 1
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Transfer status:
+Host: 0x7AECB2FE Status: Completed time: 0.007 seconds
+Total elapsed time: 0.007 seconds
+Overall throughput: 0.00 KB/s
+-----------------------------
+Finishing group
+Sending DONE 1.1
+Got COMPLETE from client 0x7AECB2FE
+Late completions:
+Sending DONE_CONF 2.1
+Group complete
+uftp: Finishing at Mon Dec 19 17:29:20 2016
+==25769==
+==25769== HEAP SUMMARY:
+==25769== in use at exit: 1,300 bytes in 1 blocks
+==25769== total heap usage: 20,607 allocs, 20,606 frees, 3,601,627,892 bytes allocated
+==25769==
+==25769== Searching for pointers to 1 not-freed blocks
+==25769== Checked 25,760,600 bytes
+==25769==
+==25769== 1,300 bytes in 1 blocks are definitely lost in loss record 1 of 1
+==25769== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
+==25769== by 0x407C1C: safe_calloc (uftp_common.c:2058)
+==25769== by 0x40FE89: create_cc_list (server_transfer.c:129)
+==25769== by 0x418FD1: transfer_receive_thread (server_phase.c:859)
+==25769== by 0x41A9AC: transfer_phase (server_phase.c:1186)
+==25769== by 0x414420: send_file (server_send.c:199)
+==25769== by 0x415A60: send_files (server_send.c:588)
+==25769== by 0x4214D9: main (server_main.c:42)
+==25769==
+==25769== LEAK SUMMARY:
+==25769== definitely lost: 1,300 bytes in 1 blocks
+==25769== indirectly lost: 0 bytes in 0 blocks
+==25769== possibly lost: 0 bytes in 0 blocks
+==25769== still reachable: 0 bytes in 0 blocks
+==25769== suppressed: 0 bytes in 0 blocks
+==25769==
+==25769== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
+==25769== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)