Hi, my development snapshot of xorriso is now able to record and restore extattr on NetBSD.
Main work was to make it tolerate the error ENOENT that is thrown by extattr_list_link(2) if the filesystem does not support extattr. Else it is much like FreeBSD. I will have to compare the behavior of both in more detail. I think getextattr(1) needs mending. See at end of this mail: "getextattr(1) has problems" ----------------------------------------------------------- One peculiarity shows up: extattr_get_link(2) et.al. return the attribute content with a trailing 0-byte. This 0-byte seems to be a bug-or-feature of setextattr(1). I overwrote an extattr in the ISO filesystem by xorriso means without a trailing 0-byte. Then i extracted it into the FFSv1 filesystem and recorded it by xorriso again. No 0-byte appeared. So the extattr_*(2) functions and xorriso are not the ones who created those 0s. Neither FreeBSD nor Linux show trailing 0-bytes with their cleartext extattr/xattr. I care for portability of attributes in namespace "user". So it would be interesting to know whether the convention on NetBSD is to have a 0-byte at the end of attribute content. extattr(9) specifies "nul-terminated character string" for names. But content is usually regarded as binary data, governed by the length value and not by a terminating character. If the 0-byte is convention, then i would consider to strip it when recording and to add it when restoring. But that would be feasible only if namespace "user" is reserved for C character strings rather than byte arrays. ----------------------------------------------------------- Demo with current development snapshot http://scdbackup.webframe.org/xorriso-1.3.7.tar.gz MD5 117954392e6359d5be8a2fcc0a965447 Version timestamp : 2014.06.20.065402 (in xorriso/xorriso_timestamp.h or in output of xorriso -version) ------------------------------------------------------------ # Create files with extattr in suitable filesystem /mnt/ffs1 echo x > /mnt/ffs1/x echo y > /mnt/ffs1/y setextattr user bla xbla /mnt/ffs1/x setextattr user bla YYYbla /mnt/ffs1/y getextattr user bla /mnt/ffs1/x getextattr user bla /mnt/ffs1/y # yields: # /mnt/ffs1/x xbla # /mnt/ffs1/y YYYbla # Record in an ISO 9660 filesystem image (/tmp/extattr_test.iso), # or in disk device (/dev/wd2f), or on optical medium (/dev/rcd0d). # I avoid the directory /mnt/ffs1/.attributes which is not readable # for the common user. drive=/tmp/extattr_test.iso xorriso \ -for_backup \ -outdev "$drive" \ -blank as_needed \ -add /mnt/ffs1/* -- # Inspect ISO xorriso \ -for_backup \ -indev "$drive" \ -getfattr_r / -- # yields: # # file: mnt/ffs1/x # user.bla="xbla\000" # # file: mnt/ffs1/y # user.bla="YYYbla\000" # Restore /mnt/ffs1 from ISO into a new directory /mnt/ffs1/xorriso_extracted xorriso \ -for_backup \ -indev "$drive" \ -osirrox on \ -extract /mnt/ffs1 /mnt/ffs1/xorriso_extracted # Inspect in FFSv1 getextattr user bla /mnt/ffs1/xorriso_extracted/* # yields: # /mnt/ffs1/xorriso_extracted/x xbla # /mnt/ffs1/xorriso_extracted/y YYYbla ------------------------------------------------------------ getextattr(1) has problems: ------------------------------------------------------------ echo a > /mnt/ffs1/a setextattr user bla AAAAAAAAAAAAAAAA /mnt/ffs1/a getextattr user bla /mnt/ffs1/* # yields: # /mnt/ffs1/a AAAAAAAAAAAAAAAA # /mnt/ffs1/x xblaAAAAAAAAAAA # getextattr: /mnt/ffs1/xorriso_extracted: failed: No message available # Note that the content of ./x is shown mangled and ./y is not listed. getextattr user bla /mnt/ffs1/x # yields: # /mnt/ffs1/x xbla getextattr user bla /mnt/ffs1/y # yields: # /mnt/ffs1/y YYYbla # Note that all three files were treated with setextattr(1) # and not created by xorriso. I am not to blame (TM). ------------------------------------------------------------ The problem with the mangled values is in /usr/src/usr.bin/extattr/extattr.c In line 370 it asks for the size of the attribute if (flag_nofollow) error = extattr_get_link(argv[arg_counter], attrnamespace, attrname, NULL, 0); else error = extattr_get_file(argv[arg_counter], attrnamespace, attrname, NULL, 0); if (error < 0) break; submits it to the local function mkbuf(&buf, &buflen, error); which leaves buflen unchanged if the new demand "error" is smaller than the previous one. In line 409 it uses buflen as the length of the value fwrite(buf, buflen, 1, stdout); The small patch would be - fwrite(buf, buflen, 1, stdout); + fwrite(buf, error, 1, stdout); But actually i think one should put the length into "val_len" and not use "error" in non-error situations. (I suspect the reason for this bug is that "buflen" is too luring to the tired programmer if only "error" is the alternative.) ------------------------------------------------------------ The problem with the early abort after the first error is in line 376: if (error < 0) break; I think that a warning and "continue" is the more appropriate reaction. (The "break" is for "switch", not for "for".) if (error < 0) { warn("%s: failed", argv[arg_counter]); continue; } ------------------------------------------------------------ After changing what i deem to be needy, i get $ ./getextattr user bla /mnt/ffs1/* /mnt/ffs1/a AAAAAAAAAAAAAAAA /mnt/ffs1/x xbla getextattr: /mnt/ffs1/xorriso_extracted: failed: No message available /mnt/ffs1/y YYYbla ------------------------------------------------------------ What advise do you have for a PR and patch ? Shall i try to keep the change minimal, or shall i remove the inappropriate use of variable "error" in favor of "val_len" ? Have a nice day :) Thomas