Description
The current output of casync mtree
is not really compliant with any implementation, and I've mostly opened this issue so I can get an answer on what kind of patch you'd like me to send to correct this. The short version of the problem is that the handling of directory nesting is currently incorrect (namely, casync mtree
spits out the full path of every file it finds as a single node -- which means that FreeBSD's mtree
will reject output from casync
because mtree doesn't allow slashes in node names).
There are two solutions I can see:
-
Append a
..
after eachtype=dir
entry. This is the simplest solution, and it means thatgomtree
will now happily verifycasync mtree
's output -- so there is at least some compatibility with another implementation. However, this still runs afoul of the canonical FreeBSDmtree
implementation -- which doesn't permit slashes in node names at all (you need to use the mtree hierarchy to represent directory paths). -
Output a proper directory tree to match the format of FreeBSD's
mtree
(and the output format ofgomtree
). The downside of this is that it could be a pain to do in C, and unless it was done directory-by-directory you could end up with a lot of repeated nodes (wasting space). But if we wanted to be completely compatible with FreeBSD'smtree
this is the only real option.
Here's a motivating example:
% mkdir -p a/b/c ; touch a/b/c/yyy a/zzz
% mtree -c -p a # freebsd
# .
/set type=file uid=1000 gid=100 mode=0644 nlink=1 flags=none
. type=dir mode=0755 size=8 time=1536913982.248903967
zzz size=0 time=1536913976.024857903
# ./b
/set type=file uid=1000 gid=100 mode=0755 nlink=1 flags=none
b type=dir size=2 time=1536913900.968302555
# ./b/c
/set type=file uid=1000 gid=100 mode=0644 nlink=1 flags=none
c type=dir mode=0755 size=6 time=1536914006.385082603
yyy size=0 time=1536913917.660426048
# ./b/c
..
# ./b
..
..
% gomtree -c -p a
# .
/set type=file nlink=1 mode=0664 uid=1000 gid=100
. size=8 type=dir mode=0755 time=1536913982.248903967
zzz size=0 mode=0644 time=1536913976.024857903
# b
b size=2 type=dir mode=0755 time=1536913900.968302555
# b/c
c size=6 type=dir mode=0755 time=1536914006.385082603
yyy size=0 mode=0644 time=1536913917.660426048
..
..
..
% casync mtree a
. type=dir mode=0755 uid=1000 gid=100 uname=cyphar gname=users time=1536913982.248903967
b type=dir mode=0755 uid=1000 gid=100 uname=cyphar gname=users time=1536913900.968302555
b/c type=dir mode=0755 uid=1000 gid=100 uname=cyphar gname=users time=1536914006.385082603
b/c/yyy type=file mode=0644 size=0 uid=1000 gid=100 uname=cyphar gname=users time=1536913917.660426048 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
zzz type=file mode=0644 size=0 uid=1000 gid=100 uname=cyphar gname=users time=1536913976.024857903 sha512256digest=c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
If you were to interpret the specification that both gomtree
and mtree
implement, you would have to treat the node zzz
as though it were a child of b/c
and thus rather than being treated as /zzz
it would be treated as /b/c/zzz
(which is wrong and results in validation errors).
I'm not suggesting that we make use of /set
or /unset
-- just that we need to handle nested paths properly.