diff options
-rw-r--r-- | doc/mscp.1.in | 12 | ||||
-rw-r--r-- | doc/mscp.rst | 33 | ||||
-rw-r--r-- | src/checkpoint.c | 42 |
3 files changed, 48 insertions, 39 deletions
diff --git a/doc/mscp.1.in b/doc/mscp.1.in index a56e26c..b50d6bc 100644 --- a/doc/mscp.1.in +++ b/doc/mscp.1.in @@ -139,7 +139,7 @@ determined as an attack. The default value is 0. .TP .B \-W \fICHECKPOINT\fR -Specifies a checkpoint file path to save the state of a failed +Specifies a checkpoint file to save the state of a failed transfer. When transferring fails due to, for example, connection disruption or user interrupt, .B mscp @@ -153,7 +153,7 @@ option with .TP .B \-R \fICHECKPOINT\fR -Specifies a checkpoint file path to resume a transfer. When this +Specifies a checkpoint file to resume a transfer. When this option with a checkpoint file is passed, .B mscp loads a remote host, copy direction, and files and their chunks to be @@ -163,14 +163,12 @@ can resume a past failed transfer from the checkpoint. Resumeing with a checkpoint does not require .I source ... target arguments. Other options for establishing SSH connections, for -example, username, port number, config file, should be specified as +example, login_name, port number, config file, should be specified as with the failed run. In addition, checkpoint files contain files as relative paths. Thus, you must run .B mscp -in the same working directory as the failed run. - - -You can see contents of a checkpoint file with +in the same working directory as the failed run. You can see contents +of a checkpoint file with .B mscp .I \-vvv \-D \-R CHECKOPOINT command. diff --git a/doc/mscp.rst b/doc/mscp.rst index a183dde..99dabfd 100644 --- a/doc/mscp.rst +++ b/doc/mscp.rst @@ -2,7 +2,7 @@ MSCP ==== -:Date: v0.1.4-19-g5f628b6 +:Date: v0.1.4-20-g19c73af NAME ==== @@ -71,27 +71,24 @@ OPTIONS determined as an attack. The default value is 0. **-W CHECKPOINT** - Specifies a checkpoint file path to save the state of a failed - transfer. When transferring fails due to, for example, connection - disruption or user interrupt, **mscp** writes the information about - remaining files and chunks to the specified checkpoint file. **-W** - option with **-D** (dry-run mode) only writes a checkpoint file and - exits. + Specifies a checkpoint file to save the state of a failed transfer. + When transferring fails due to, for example, connection disruption or + user interrupt, **mscp** writes the information about remaining files + and chunks to the specified checkpoint file. **-W** option with + **-D** (dry-run mode) only writes a checkpoint file and exits. **-R CHECKPOINT** - Specifies a checkpoint file path to resume a transfer. When this - option with a checkpoint file is passed, **mscp** loads a remote - host, copy direction, and files and their chunks to be transferred - from the checkpoint file. Namely, **mscp** can resume a past failed - transfer from the checkpoint. Resumeing with a checkpoint does not - require *source ... target* arguments. Other options for establishing - SSH connections, for example, username, port number, config file, + Specifies a checkpoint file to resume a transfer. When this option + with a checkpoint file is passed, **mscp** loads a remote host, copy + direction, and files and their chunks to be transferred from the + checkpoint file. Namely, **mscp** can resume a past failed transfer + from the checkpoint. Resumeing with a checkpoint does not require + *source ... target* arguments. Other options for establishing SSH + connections, for example, login_name, port number, config file, should be specified as with the failed run. In addition, checkpoint files contain files as relative paths. Thus, you must run **mscp** in - the same working directory as the failed run. - -You can see contents of a checkpoint file with **mscp** *-vvv -D -R -CHECKOPOINT* command. + the same working directory as the failed run. You can see contents of + a checkpoint file with **mscp** *-vvv -D -R CHECKOPOINT* command. **-s MIN_CHUNK_SIZE** Specifies the minimum chunk size. **mscp** divides a file into chunks diff --git a/src/checkpoint.c b/src/checkpoint.c index efa1926..906b02f 100644 --- a/src/checkpoint.c +++ b/src/checkpoint.c @@ -11,6 +11,10 @@ #include <checkpoint.h> +#define MSCP_CHECKPOINT_MAGIC 0x6d736370UL /* mscp in UTF-8 */ +#define MSCP_CHECKPOINT_VERSION 0x1 + + enum { OBJ_TYPE_META = 0x0A, OBJ_TYPE_PATH = 0x0B, @@ -23,8 +27,6 @@ struct checkpoint_obj_hdr { uint16_t len; /* length of an object including this hdr */ } __attribute__((packed)); -#define MSCP_CHECKPOINT_MAGIC 0x6d736370UL /* mscp in UTF-8 */ -#define MSCP_CHECKPOINT_VERSION 0x1 struct checkpoint_obj_meta { struct checkpoint_obj_hdr hdr; @@ -41,17 +43,24 @@ struct checkpoint_obj_path { struct checkpoint_obj_hdr hdr; uint32_t idx; - uint16_t src_off; /* offset to the src path - * string (including \0) from - * the head of this object. */ - - uint16_t dst_off; /* offset to the dst path - * string (including \0) from - * the head of this object */ + uint16_t src_off; /* offset to the src path string (including + * \0) from the head of this object. */ + uint16_t dst_off; /* offset to the dst path string (including + * \0) from the head of this object */ } __attribute__((packed)); -#define obj_path_src(obj) ((char *)(obj) + ntohs(obj->src_off)) -#define obj_path_dst(obj) ((char *)(obj) + ntohs(obj->dst_off)) +#define obj_path_src(o) ((char *)(o) + ntohs(o->src_off)) +#define obj_path_dst(o) ((char *)(o) + ntohs(o->dst_off)) + +#define obj_path_src_len(o) (ntohs(o->dst_off) - ntohs(o->src_off)) +#define obj_path_dst_len(o) (ntohs(o->hdr.len) - ntohs(o->dst_off)) + +#define obj_path_validate(o) \ + ((ntohs(o->hdr.len) > ntohs(o->dst_off)) && \ + (ntohs(o->dst_off) > ntohs(o->src_off)) && \ + (obj_path_src_len(o) < PATH_MAX) && \ + (obj_path_dst_len(o) < PATH_MAX)) \ + struct checkpoint_obj_chunk { struct checkpoint_obj_hdr hdr; @@ -213,12 +222,17 @@ static int checkpoint_load_path(struct checkpoint_obj_hdr *hdr, pool *path_pool) struct path *p; char *s, *d; - if (!(s = strdup(obj_path_src(path)))) { + if (!obj_path_validate(path)) { + priv_set_errv("invalid path object"); + return -1; + } + + if (!(s = strndup(obj_path_src(path), obj_path_src_len(path)))) { priv_set_errv("strdup: %s", strerrno()); return -1; } - if (!(d = strdup(obj_path_dst(path)))) { + if (!(d = strndup(obj_path_dst(path), obj_path_dst_len(path)))) { priv_set_errv("strdup: %s", strerrno()); free(s); return -1; @@ -235,7 +249,7 @@ static int checkpoint_load_path(struct checkpoint_obj_hdr *hdr, pool *path_pool) return -1; } - pr_info("checkpoint:path: %s -> %s", p->path, p->dst_path); + pr_info("checkpoint:file: %s -> %s", p->path, p->dst_path); return 0; } |