From b7c1e03ff78fb3b326a37e4eecf163c1bb385307 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 3 Nov 2024 19:17:32 +0100 Subject: [PATCH] New API calls iso_node_get_projid(), iso_node_set_projid(), iso_local_get_projid(), iso_local_set_projid() --- Makefile.am | 3 +- configure.ac | 17 ++++ doc/susp_aaip_isofs_names.txt | 22 +++++ libisofs/aaip-os-dummy.c | 23 ++++- libisofs/aaip-os-freebsd.c | 25 ++++- libisofs/aaip-os-linux.c | 171 +++++++++++++++++++++++++++++++++- libisofs/aaip_0_2.c | 4 +- libisofs/aaip_0_2.h | 46 ++++++++- libisofs/builder.c | 3 +- libisofs/fs_local.c | 97 ++++++++++++++++--- libisofs/image.c | 7 +- libisofs/image.h | 14 ++- libisofs/libisofs.h | 142 ++++++++++++++++++++++++++-- libisofs/libisofs.ver | 4 + libisofs/messages.c | 8 ++ libisofs/node.c | 57 +++++++++++- libisofs/rockridge.c | 4 +- 17 files changed, 603 insertions(+), 44 deletions(-) diff --git a/Makefile.am b/Makefile.am index 7160b48..3a87897 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,8 +26,9 @@ libisofs_libisofs_la_LDFLAGS = \ # ts A90409: Enabling use of zlib. # ts B00927: Enabling use of libjte (Jigdo Template Extraction) # ts C40713: Enabling system adapter for Linux chattr(1) flags +# ts C41009: Enabling system adapter for project id of XFS-style quota libisofs_libisofs_la_CFLAGS = $(LIBACL_DEF) $(XATTR_DEF) $(LFA_DEF) \ - $(ZLIB_DEF) $(LIBJTE_DEF) + $(PROJID_DEF) $(ZLIB_DEF) $(LIBJTE_DEF) # ts A90114 : added aaip_0_2.* diff --git a/configure.ac b/configure.ac index 96e0fcb..725713f 100644 --- a/configure.ac +++ b/configure.ac @@ -302,6 +302,23 @@ else fi AC_SUBST(LFA_DEF) +dnl ts C41009 +PROJID_DEF= +AC_ARG_ENABLE(projid, +[ --enable-projid Enable processing of XFS-style project id, default=yes], + , enable_projid=yes) +if test x"$enable_projid" = xyes; then + AC_CHECK_HEADER(linux/fs.h, PROJID_DEF="-DLibisofs_with_aaip_projiD", + PROJID_DEF=) +fi +if test x"$PROJID_DEF" = x; then + echo "disabled XFS-style project id" +else + echo "enabled XFS-style project id" +fi +AC_SUBST(PROJID_DEF) + + dnl ts A90409 AC_ARG_ENABLE(zlib, [ --enable-zlib Enable use of zlib by libisofs, default=yes], diff --git a/doc/susp_aaip_isofs_names.txt b/doc/susp_aaip_isofs_names.txt index a0578fb..8d14aa2 100644 --- a/doc/susp_aaip_isofs_names.txt +++ b/doc/susp_aaip_isofs_names.txt @@ -176,6 +176,7 @@ Format of Value: Example: (FS_SECRM_FL|FS_APPEND_FL|FS_NOCOMP_FL) = 0x421 { 4 , 33 } + Registered: 12 Jul 2024 by Thomas Schmitt for libisofs. @@ -250,6 +251,27 @@ Registered: ------------------------------------------------------------------------------- +Name: + isofs.pi + +Purpose: + Records the project id for XFS-style quota management. + See man xfs_quota(8). + Missing isofs.pi is defaulted to project id 0. + +Format of Value: + A byte string which begins with the most significant byte. + Up to four bytes are permissible. + +Example: + Project id 258 + { 1, 2 } + +Registered: + 09 Oct 2024 by Thomas Schmitt for libisofs. + +------------------------------------------------------------------------------- + Name: isofs.st diff --git a/libisofs/aaip-os-dummy.c b/libisofs/aaip-os-dummy.c index a2457e2..3d65b41 100644 --- a/libisofs/aaip-os-dummy.c +++ b/libisofs/aaip-os-dummy.c @@ -47,7 +47,9 @@ Bitfield corresponding to flag. bit0= ACL adapter is enabled bit1= xattr adapter is enabled - bit2 - bit7= Reserved for future types. + bit2= Linux-like file attribute flags (chattr) adapter is enabled + bit3= inquire availability of XFS-style project id + bit4 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) @@ -95,6 +97,16 @@ int aaip_get_lfa_flags(char *path, uint64_t *lfa_flags, int *max_bit, } +/* Obtain the project id for XFS-style quota management. +*/ +int aaip_get_projid(char *path, uint32_t *projid, int *os_errno, int flag) +{ + *projid= 0; + *os_errno= 0; + return(0); +} + + /* ------------------------------ Setters --------------------------------- */ @@ -155,3 +167,12 @@ int aaip_set_lfa_flags(char *path, uint64_t lfa_flags, int max_bit, } +/* Set the project id for XFS-style quota management. +*/ +int aaip_set_projid(char *path, uint32_t projid, int *os_errno, int flag) +{ + *os_errno= 0; + return(0); +} + + diff --git a/libisofs/aaip-os-freebsd.c b/libisofs/aaip-os-freebsd.c index 08303e1..7457747 100644 --- a/libisofs/aaip-os-freebsd.c +++ b/libisofs/aaip-os-freebsd.c @@ -57,7 +57,9 @@ Bitfield corresponding to flag. bit0= ACL adapter is enabled bit1= xattr adapter is enabled - bit2 - bit7= Reserved for future types. + bit2= Linux-like file attribute flags (chattr) adapter is enabled + bit3= inquire availability of XFS-style project id + bit4 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) @@ -391,6 +393,8 @@ static int get_single_attr(char *path, char *name, size_t *value_length, bit6= do not obtain Linux style file attribute flags (chattr). This obtaining is not implemented here anyways. + bit8= do not obtain XFS-style project id. + This obtaining is not implemented here anyways. bit15= free memory of names, value_lengths, values @return 1 ok 2 ok, no permission to inspect non-user namespaces @@ -725,6 +729,16 @@ int aaip_get_lfa_flags(char *path, uint64_t *lfa_flags, int *max_bit, } +/* Obtain the project id for XFS-style quota management. +*/ +int aaip_get_projid(char *path, uint32_t *projid, int *os_errno, int flag) +{ + *projid= 0; + *os_errno= 0; + return(0); +} + + /* ------------------------------ Setters --------------------------------- */ @@ -1123,3 +1137,12 @@ int aaip_set_lfa_flags(char *path, uint64_t lfa_flags, int max_bit, } +/* Set the project id for XFS-style quota management. +*/ +int aaip_set_projid(char *path, uint32_t projid, int *os_errno, int flag) +{ + *os_errno= 0; + return(0); +} + + diff --git a/libisofs/aaip-os-linux.c b/libisofs/aaip-os-linux.c index c484254..611f6c6 100644 --- a/libisofs/aaip-os-linux.c +++ b/libisofs/aaip-os-linux.c @@ -56,7 +56,8 @@ bit0= inquire availability of ACL bit1= inquire availability of xattr bit2= inquire availability of Linux-like file attribute flags - bit3 - bit7= Reserved for future types. + bit3= inquire availability of XFS-style project id + bit4 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return @@ -64,7 +65,8 @@ bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2= Linux-like file attribute flags adapter is enabled - bit3 - bit7= Reserved for future types. + bit3= XFS-style project id is enabled + bit4 - bit7= Reserved for future types. bit8 and higher: reserved, do not interpret these */ int aaip_local_attr_support(int flag) @@ -88,6 +90,15 @@ int aaip_local_attr_support(int flag) ret|= 4; #endif #endif +#endif + +#ifdef Libisofs_with_aaip_projiD +#ifdef FS_IOC_FSGETXATTR +#ifdef FS_IOC_FSSETXATTR + if(flag & 8) + ret|= 8; +#endif +#endif #endif return(ret); @@ -283,6 +294,7 @@ static int get_single_attr(char *path, char *name, size_t *value_length, (chattr) bit7= Without bit6: Ignore non-settable flags and do not record "isofs.fa" if all flags are zero + bit8= do not obtain XFS-style project id bit15= free memory of names, value_lengths, values @return 1 ok (reserved for FreeBSD: 2 ok, no permission to inspect @@ -316,6 +328,9 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, int max_bit, os_errno, lfa_length; unsigned char lfa_value[8]; #endif +#ifdef Libisofs_with_aaip_projiD + uint32_t projid; +#endif if(flag & (1 << 15)) { /* Free memory */ {ret= 1; goto ex;} @@ -386,6 +401,16 @@ ex:; #endif +#ifdef Libisofs_with_aaip_projiD + + if(!(flag & 256)) { + ret= iso_local_get_projid(path, &projid, &os_errno, 0); + if(ret > 0 && projid != 0) + num_names++; + } + +#endif /* Libisofs_with_aaip_projiD */ + if(num_names == 0) {ret= 1; goto ex;} (*names)= calloc(num_names, sizeof(char *)); @@ -463,7 +488,7 @@ try_lfa_flags:; ret= 4; } if(ret == 1 || ret == 2) { - ret= aaip_encode_lfa_flags(lfa_flags, lfa_value, &lfa_length, 0); + ret= aaip_encode_uint64(lfa_flags, lfa_value, &lfa_length, 0); if(ret > 0) { (*names)[*num_attrs]= strdup("isofs.fa"); if((*names)[*num_attrs] == NULL) @@ -480,6 +505,29 @@ try_lfa_flags:; #endif /* Libisofs_with_aaip_lfa_flagS */ +#ifdef Libisofs_with_aaip_projiD + + if(!(flag & 256)) { + ret= iso_local_get_projid(path, &projid, &os_errno, 0); + if(ret > 0 && projid != 0) { + /* Encode as big-endian number with no trailing 0-bytes */ + ret= aaip_encode_uint64((uint64_t) projid, lfa_value, &lfa_length, 0); + if(ret > 0) { + (*names)[*num_attrs]= strdup("isofs.pi"); + if((*names)[*num_attrs] == NULL) + {ret= -1; goto ex;} + (*values)[*num_attrs]= calloc(lfa_length, 1); + if((*values)[*num_attrs] == NULL) + {ret= -1; goto ex;} + memcpy((*values)[*num_attrs], (char *) lfa_value, lfa_length); + (*value_lengths)[*num_attrs]= lfa_length; + (*num_attrs)++; + } + } + } + +#endif /* Libisofs_with_aaip_projiD */ + ret= 1; ex:; #ifdef Libisofs_with_aaip_acL @@ -530,6 +578,7 @@ ex:; @param lfa_flags Will get filled with the FS_*_FL @param max_bit Will tell the highest bit that is possibly set (-1 = surely no bit is valid) + @param os_errno Will get filled with errno in case of error. @param flag Bitfield for control purposes. bit0= consider ENOTTY from FS_IOC_GETFLAGS an error (else return 4 on ENOTTY) @@ -606,6 +655,64 @@ int aaip_get_lfa_flags(char *path, uint64_t *lfa_flags, int *max_bit, } +/* Obtain the project id for XFS-style quota management. + See man xfs_quota(8). + @param path Path to the file. + @param projid Will get filled with the project id. + @param os_errno Will get filled with errno in case of error. + @param flag Bitfield for control purposes. + bit2= do not issue own error messages with operating + system errors + @return 1= ok, *projid is valid + 0= local project id retrieval not enabled at compile + time + <0 error with system calls: + -1= error with open(2) + -2= error with ioctl(2) +*/ +int aaip_get_projid(char *path, uint32_t *projid, int *os_errno, int flag) +{ + int ret= 0; + +#ifdef Libisofs_with_aaip_projiD +#ifdef FS_IOC_FSGETXATTR + + int fd; + struct fsxattr ioctl_result; + +#endif +#endif + + *projid= 0; + +#ifdef Libisofs_with_aaip_projiD +#ifdef FS_IOC_FSGETXATTR + + fd= open(path, O_RDONLY | O_NDELAY); + if(fd == -1) { + aaip_local_error("open", path, errno, 0); + *os_errno= errno; + return(-1); + } + ret= ioctl(fd, FS_IOC_FSGETXATTR, &ioctl_result); + close(fd); + if(ret == -1) { + if(!(flag & 4)) + aaip_local_error("ioctl(FS_IOC_FSGETXATTR)", path, errno, 0); + *os_errno= errno; + return(-2); + } + *projid= ioctl_result.fsx_projid; + ret= 1; + +#endif /* FS_IOC_FSGETXATTR */ +#endif /* Libisofs_with_aaip_lfa_flagS */ + + return(ret); +} + + + /* ------------------------------ Setters --------------------------------- */ @@ -960,3 +1067,61 @@ int aaip_set_lfa_flags(char *path, uint64_t lfa_flags, int max_bit, return(ret); } + +/* Set the project id for XFS-style quota management. + @param path Path to the file. + @param projid Contains the project id for the file. + @param os_errno Will get filled with errno in case of error. + @param flag Bitfield for control purposes. + bit2= do not issue own error messages with operating + system errors + @return 1= ok, projid was written + 0= local flags setting not enabled at compile time + -1= error with open(2) + -2= error with ioctl(FS_IOC_FSGETXATTR) + -3= error with ioctl(FS_IOC_FSSETXATTR) +*/ +int aaip_set_projid(char *path, uint32_t projid, int *os_errno, int flag) +{ + int ret= 0; + +#ifdef Libisofs_with_aaip_projiD +#ifdef FS_IOC_FSGETXATTR +#ifdef FS_IOC_FSSETXATTR + + int fd; + struct fsxattr ioctl_arg; + + fd= open(path, O_RDONLY | O_NDELAY); + if(fd == -1) { + if(!(flag & 4)) + aaip_local_error("open", path, errno, 0); + *os_errno= errno; + return(-1); + } + ret= ioctl(fd, FS_IOC_FSGETXATTR, &ioctl_arg); + if(ret == -1) { + if(!(flag & 4)) + aaip_local_error("ioctl(FS_IOC_FSGETXATTR)", path, errno, 0); + *os_errno= errno; + close(fd); + return(-2); + } + ioctl_arg.fsx_projid= projid; + ret= ioctl(fd, FS_IOC_FSSETXATTR, &ioctl_arg); + close(fd); + if(ret == -1) { + if(!(flag & 4)) + aaip_local_error("ioctl(FS_IOC_FSSETXATTR)", path, errno, 0); + *os_errno= errno; + return(-3); + } + ret= 1; + +#endif /* FS_IOC_FSSETXATTR */ +#endif /* FS_IOC_FSGETXATTR */ +#endif /* Libisofs_with_aaip_lfa_flagS */ + + return(ret); +} + diff --git a/libisofs/aaip_0_2.c b/libisofs/aaip_0_2.c index 9699341..8f91d32 100644 --- a/libisofs/aaip_0_2.c +++ b/libisofs/aaip_0_2.c @@ -900,8 +900,8 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag) } -int aaip_encode_lfa_flags(uint64_t lfa_flags, unsigned char value[8], - int *length, int flag) +int aaip_encode_uint64(uint64_t lfa_flags, unsigned char value[8], + int *length, int flag) { int i, l; diff --git a/libisofs/aaip_0_2.h b/libisofs/aaip_0_2.h index 1d54c5c..d73cb0b 100644 --- a/libisofs/aaip_0_2.h +++ b/libisofs/aaip_0_2.h @@ -162,8 +162,8 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag); @param length Will return the number of filled-in value bytes @return <0 failure */ -int aaip_encode_lfa_flags(uint64_t lfa_flags, unsigned char value[8], - int *length, int flag); +int aaip_encode_uint64(uint64_t lfa_flags, unsigned char value[8], + int *length, int flag); /* ------ OS interface ------ */ @@ -174,7 +174,8 @@ int aaip_encode_lfa_flags(uint64_t lfa_flags, unsigned char value[8], bit0= inquire availability of ACL bit1= inquire availability of xattr bit2= inquire availability of Linux-like file attribute flags - bit3 - bit7= Reserved for future types. + bit3= inquire availability of XFS-style project id + bit4 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, submit 0 @return @@ -182,7 +183,8 @@ int aaip_encode_lfa_flags(uint64_t lfa_flags, unsigned char value[8], bit0= ACL adapter is enabled bit1= xattr adapter is enabled bit2= Linux-like file attribute flags adapter is enabled - bit3 - bit7= Reserved for future types. + bit3= XFS-style project id is enabled + bit4 - bit7= Reserved for future types. It is permissibile to set them to 1 already now. bit8 and higher: reserved, do not interpret these */ @@ -227,6 +229,9 @@ int aaip_get_acl_text(char *path, char **text, int flag); bit5= in case of symbolic link: inquire link target bit6= do not obtain Linux style file attribute flags (chattr) + bit7= Without bit6: Ignore non-settable flags and do + not record "isofs.fa" if all flags are zero + bit8= do not obtain XFS-style project id bit15= free memory of names, value_lengths, values @return >0 ok <=0 error @@ -265,6 +270,24 @@ int aaip_get_lfa_flags(char *path, uint64_t *lfa_flags, int *max_bit, int *os_errno, int flag); +/* Obtain the project id for XFS-style quota management. + See man xfs_quota(8). + @param path Path to the file. + @param projid Will get filled with the project id. + @param os_errno Will get filled with errno in case of error. + @param flag Bitfield for control purposes. + bit2= do not issue own error messages with operating + system errors + @return 1= ok, *projid is valid + 0= local project id retrieval not enabled at compile + time + <0 error with system calls: + -1= error with open(2) + -2= error with ioctl(2) +*/ +int aaip_get_projid(char *path, uint32_t *projid, int *os_errno, int flag); + + /* --------------------------------- Decoder ---------------------------- */ /* @@ -591,5 +614,20 @@ int aaip_set_lfa_flags(char *path, uint64_t lfa_flags, int max_bit, int *os_errno, int flag); +/* Set the project id for XFS-style quota management. + @param path Path to the file. + @param projid Contains the project id for the file. + @param os_errno Will get filled with errno in case of error. + @param flag Bitfield for control purposes. + bit2= do not issue own error messages with operating + system errors + @return 1= ok, projid was written + 0= local flags setting not enabled at compile time + -1= error with open(2) + -2= error with ioctl(FS_IOC_FSGETXATTR) + -3= error with ioctl(FS_IOC_FSSETXATTR) +*/ +int aaip_set_projid(char *path, uint32_t projid, int *os_errno, int flag); + #endif /* ! Aaip_h_is_includeD */ diff --git a/libisofs/builder.c b/libisofs/builder.c index bad1bc2..812df02 100644 --- a/libisofs/builder.c +++ b/libisofs/builder.c @@ -255,7 +255,8 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image, (image->builder_ignore_ea << 2) | (image->builder_take_all_ea << 3) | ((!image->builder_ignore_lfa_flags) << 4) | - (image->builder_ignore_ro_lfa_flags << 5) ); + (image->builder_ignore_ro_lfa_flags << 5) | + ((!image->builder_ignore_projid) << 6)); if(ret == 2) image->blind_on_local_get_attrs = 1; if (ret > 0 && aa_string != NULL) { diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index 536dddb..4dd5563 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -507,14 +507,14 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) *aa_string = NULL; - if ((flag & (2 | 4 | 16) ) == (2 | 4)) { + if ((flag & (2 | 4 | 16 | 64) ) == (2 | 4)) { /* Neither ACL nor xattr shall be read, lfa_flags are not wanted */ ret = 1; goto ex; } /* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according to AAIP ACL representation. Clean out st_mode ACL entries. - Obtain Linux style attribute flags. + Obtain Linux style attribute flags and XFS-style project id. */ path = iso_file_source_get_path(src); if (path == NULL) { @@ -524,7 +524,8 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) ret = aaip_get_attr_list(path, &num_attrs, &names, &value_lengths, &values, (!(flag & 2)) | 2 | (flag & 4) | (flag & 8) | 16 | - ((!(flag & 16)) << 6) | ((!!(flag & 32)) << 7)); + ((!(flag & 16)) << 6) | ((!!(flag & 32)) << 7) | + ((!(flag & 64)) << 8)); if (ret <= 0) { if (ret == -2) ret = ISO_AAIP_NO_GET_LOCAL; @@ -866,13 +867,14 @@ int iso_local_set_acl_text(char *disk_path, char *text, int flag) int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag) { - int ret, lfa; + int ret, lfa, prj; lfa = (flag & 64) ^ 64; + prj = (flag & (1 << 8)) ^ (1 << 8); ret = aaip_get_attr_list(disk_path, num_attrs, names, value_lengths, values, - (flag & (1 | 4 | 8 | 32 | (1 << 15))) | - 2 | 16 | lfa); + (flag & (1 | 4 | 8 | 32 | 256 | (1 << 15))) | + 2 | 16 | lfa | prj); if (ret <= 0) return ISO_AAIP_NO_GET_LOCAL; return 1 + (ret == 2); @@ -958,7 +960,6 @@ int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag) * 4= ok, file did not bear attribute flags. E.g. because not S_IFDIR or * S_IFREG, or because unsuitable filesystem. * lfa_flags is set to 0 - * 0= local flags retrieval not enabled at compile time * <0= error with system calls */ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, @@ -976,7 +977,7 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, ret = lstat(disk_path, &stbuf); if (ret == -1) { *os_errno = errno; - return -1; + return ISO_FILE_DOESNT_EXIST; } if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32)) return 3; @@ -987,7 +988,7 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, if(ret == -1) return ISO_LFA_NO_OPEN_LOCAL; if(ret < 0) - return ISO_LFA_NO_SET_LOCAL; + return ISO_LFA_NO_GET_LOCAL; return ret; } @@ -997,7 +998,7 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, * bit0= do not try to change known superuser flags * bit1= change only known chattr settable flags * bit2= do not issue own error messages with operating system errors - * bit5= in case of symbolic link: inquire link target + * bit5= in case of symbolic link: operate on link target * @return * 1 = ok, all lfa_flags bits were written * 2 = ok, but some FS_*_FL bits could not be mapped to local flags @@ -1018,7 +1019,7 @@ int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit, ret = lstat(disk_path, &stbuf); if (ret == -1) { *os_errno = errno; - return -1; + return ISO_FILE_DOESNT_EXIST; } if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32)) return 3; @@ -1050,3 +1051,77 @@ int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit, } +/* + * @param flag + * Bitfield for control purposes + * bit2= do not issue own error messages with operating system errors + * bit5= in case of symbolic link: inquire link target + * @return + * 1= ok, projid is valid + * 3 = ok, symbolic link encountered, flag bit5 not set, projid set to 0 + * <0= error with system calls + */ +int iso_local_get_projid(char *disk_path, uint32_t *projid, int *os_errno, + int flag) +{ + int ret; + struct stat stbuf; + + *projid = 0; + *os_errno = 0; + if (flag & 32) + ret = stat(disk_path, &stbuf); + else + ret = lstat(disk_path, &stbuf); + if (ret == -1) { + *os_errno = errno; + return ISO_FILE_DOESNT_EXIST; + } + ret = aaip_get_projid(disk_path, projid, os_errno, flag & 4); + if(ret == 0) + return ISO_PROJID_NOT_ENABLED; + if(ret == -1) + return ISO_PROJID_NO_OPEN_LOCAL; + if(ret < 0) + return ISO_PROJID_NO_SET_LOCAL; + return ret; +} + + +/* + * @param flag Bitfield for control purposes + * bit2= do not issue own error messages with operating system errors + * bit5= in case of symbolic link: manipulate link target + * @return + * 1 = ok, projid was written + * 3 = ok, symbolic link encountered, flag bit5 not set, nothing done + * <0 = error + */ +int iso_local_set_projid(char *disk_path, uint32_t projid, int *os_errno, + int flag) +{ + int ret; + struct stat stbuf; + + *os_errno = 0; + if (flag & 32) + ret = stat(disk_path, &stbuf); + else + ret = lstat(disk_path, &stbuf); + if (ret == -1) { + *os_errno = errno; + return ISO_FILE_DOESNT_EXIST; + } + if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32)) + return 3; + ret = aaip_set_projid(disk_path, projid, os_errno, flag & 4); + if(ret == 0) + return ISO_PROJID_NOT_ENABLED; + if (ret == -1) + return ISO_PROJID_NO_OPEN_LOCAL; + if(ret < 0) + return ISO_PROJID_NO_SET_LOCAL; + return ret; +} + + diff --git a/libisofs/image.c b/libisofs/image.c index da1f64b..b517aa4 100644 --- a/libisofs/image.c +++ b/libisofs/image.c @@ -202,6 +202,7 @@ int iso_image_new(const char *name, IsoImage **image) img->builder_ignore_ea = 1; img->builder_ignore_lfa_flags = 1; img->builder_ignore_ro_lfa_flags = 0; + img->builder_ignore_projid = 1; img->truncate_mode = 1; img->truncate_length = LIBISOFS_NODE_NAME_MAX; img->truncate_buffer[0] = 0; @@ -631,9 +632,10 @@ void iso_image_set_ignore_aclea(IsoImage *image, int what) { image->builder_ignore_acl = (what & 1); image->builder_ignore_ea = !!(what & 2); - image->builder_ignore_lfa_flags= !(what & 4); + image->builder_ignore_lfa_flags = !(what & 4); image->builder_take_all_ea = !!(what & 8); image->builder_ignore_ro_lfa_flags = !!(what & 32); + image->builder_ignore_projid = !!(what & 64); } @@ -643,7 +645,8 @@ int iso_image_get_ignore_aclea(IsoImage *image) (image->builder_ignore_ea << 1) | ((!image->builder_ignore_lfa_flags) << 2) | (image->builder_take_all_ea << 3) | - (image->builder_ignore_ro_lfa_flags << 5); + (image->builder_ignore_ro_lfa_flags << 5) | + ((!image->builder_ignore_projid) << 6); } diff --git a/libisofs/image.h b/libisofs/image.h index 8d0bd12..072f71d 100644 --- a/libisofs/image.h +++ b/libisofs/image.h @@ -145,6 +145,12 @@ struct Iso_Image */ unsigned int builder_ignore_ea : 1; + /** + * If not builder_ignore_ea : import all xattr namespaces from local + * filesystem, not only "user. + */ + unsigned int builder_take_all_ea : 1; + /** * Whether to ignore Linux style file attribute flags (chattr). * Not in effect with loading a complete ISO image but only with image @@ -160,11 +166,11 @@ struct Iso_Image */ unsigned int builder_ignore_ro_lfa_flags : 1; - /** - * If not builder_ignore_ea : import all xattr namespaces from local - * filesystem, not only "user. + /* Whether to ignore XFS-style project id. + * Not in effect with loading a complete ISO image but only with image + * manipulation. */ - unsigned int builder_take_all_ea : 1; + unsigned int builder_ignore_projid : 1; /** * Files to exclude. Wildcard support is included. diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index b961c04..0915001 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -874,6 +874,8 @@ struct IsoFileSource_Iface * attribute flags and do not record "isofs.fa" * if the other flags are all zero * @since 1.5.8 + * bit6= Try to get XFS-style project id as "isofs.pi" + * @since 1.5.8 * @param aa_string Returns a pointer to the AAIP string data. If no AAIP * string is available, *aa_string becomes NULL. * (See doc/susp_aaip_*_*.txt for the meaning of AAIP and @@ -1328,6 +1330,10 @@ int iso_image_new(const char *name, IsoImage **image); * bit5= with bit2: Ignore non-settable Linux-like file attribute flags * and do not record "isofs.fa" if the other flags are all zero * @since 1.5.8 + * bit6= read XFS-style project from the file object id and record + * "isofs.pi" if it is not 0. + * (I.e. a do-not-ignore, because ignoring was default before) + * @since 1.5.8 * all other bits are reserved * * @since 0.6.14 @@ -7296,6 +7302,8 @@ int iso_file_source_readlink(IsoFileSource *src, char *buf, size_t bufsiz); * attribute flags and do not record "isofs.fa" * if the other flags are all zero * @since 1.5.8 + * bit6= Try to get XFS-style project id as "isofs.pi" + * @since 1.5.8 * @return 1 means success (*aa_string == NULL is possible) * <0 means failure and must b a valid libisofs error code * (e.g. ISO_FILE_ERROR if no better one can be found). @@ -7860,13 +7868,51 @@ int iso_node_get_lfa_flags(IsoNode *node, uint64_t *lfa_flags, int *max_bit, int iso_node_set_lfa_flags(IsoNode *node, uint64_t lfa_flags, int flag); -/* ----- This is an interface to ACL and xattr of the local filesystem ----- */ +/** + * Obtain the XFS-style project id of the given node. + * The result is 0 if no project id information is associated with the node. + * + * @param node + * The node that is to be inquired. + * @param projid + * Will get filled with the project id + * @param flag + * Bitfield for control purposes. Submit 0. + * @return + * 1 = ok, projid is valid + * < 0 = error + * + * @since 1.5.8 + */ +int iso_node_get_projid(IsoNode *node, uint32_t *projid, int flag); + /** - * libisofs has an internal system dependent adapter to ACL and xattr - * operations. For the sake of completeness and simplicity it exposes this - * functionality to its applications which might want to get and set ACLs - * from local files. + * Set the Linux-like XFS-style project id of the given node. + * + * @param node + * The node that is to be manipulated. + * @param projid + * The project id to be set. + * @param flag + * Bitfield for control purposes. Submit 0. + * @return + * 1 = ok + * < 0 = error + * + * @since 1.5.8 + */ +int iso_node_set_projid(IsoNode *node, uint32_t projid, int flag); + + +/* ---- This is an interface to file attributes of the local filesystem ---- */ + +/** + * libisofs has an internal system dependent adapter to perform operations on + * ACL, xattr, Linux-like file attribute flags, and XFS-style project ids. + * For the sake of completeness and simplicity it exposes this functionality + * to its applications which might want to get and set such attributes from + * local files. */ /** @@ -7879,7 +7925,11 @@ int iso_node_set_lfa_flags(IsoNode *node, uint64_t lfa_flags, int flag); * Bitfield for control purposes * bit0= inquire availability of ACL * bit1= inquire availability of xattr - * bit2 - bit7= Reserved for future types. + * bit2= inquire availability of Linux-like file attribute flags + * @since 1.5.8 + * bit3= inquire availability of XFS-style project id + * @since 1.5.8 + * bit4 - bit7= Reserved for future types. * It is permissibile to set them to 1 already now. * bit8 and higher: reserved, submit 0 * @return @@ -7888,7 +7938,9 @@ int iso_node_set_lfa_flags(IsoNode *node, uint64_t lfa_flags, int flag); * bit1= xattr adapter is enabled * bit2= Linux-like file attribute flags (chattr) adapter is enabled * @since 1.5.8 - * bit3 - bit7= Reserved for future types. + * bit3= XFS-style project ids are enabled + * @since 1.5.8 + * bit4 - bit7= Reserved for future types. * It is permissibile to set them to 1 already now. * bit8 and higher: reserved, do not interpret these * @@ -7896,6 +7948,7 @@ int iso_node_set_lfa_flags(IsoNode *node, uint64_t lfa_flags, int flag); */ int iso_local_attr_support(int flag); + /** * Get an ACL of the given file in the local filesystem in long text form. * @@ -7971,8 +8024,9 @@ int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag); /** - * Get xattr, non-trivial ACLs, and possible Linux-like file attribute flags - * (chattr) of the given file in the local filesystem. + * Get xattr, non-trivial ACLs, possible Linux-like file attribute flags + * (chattr), and XFS-style project id of the given file in the local + * filesystem. * The resulting data has finally to be disposed by a call to this function * with flag bit15 set. * @@ -7998,6 +8052,9 @@ int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag); * I.e. those with a name which does not begin by "user." * bit5= in case of symbolic link: inquire link target * bit6= obtain Linux-like file attribute flags (chattr) as "isofs.fa" + * @since 1.5.8 + * bit8= obtain XFS-style non-zero project id as "isofs.pi" + * @since 1.5.8 * bit15= free memory * @return * 1 ok @@ -8238,6 +8295,55 @@ void iso_util_get_lfa_masks(uint64_t *user_settable, uint64_t *su_settable, */ uint64_t iso_util_get_effective_lfa_mask(uint64_t change_mask, int flag); + +/** + * Obtain the XFS-style project id of the given file. + * + * @param disk_path + * Path to the file + * @param projid + * Will get filled with the project id number. + * @param os_errno + * Will get filled with errno if a system call fails. + * Else it will be filled with 0. + * @param flag + * Bitfield for control purposes + * bit2= do not issue own error messages with operating system errors + * bit5= in case of symbolic link: inquire link target + * @return + * 1 = ok, projid is valid + * 3 = ok, symbolic link encountered, flag bit5 not set, projid set to 0 + * <0 = error with system calls + * + * @since 1.5.8 + */ +int iso_local_get_projid(char *disk_path, uint32_t *projid, int *os_errno, + int flag); + + +/** + * Bring the given XFS-style project id into effect with the given file. + * + * @param disk_path + * Path to the file + * @param projid + * Project id + * @param os_errno + * Will get filled with errno if a system call fails. + * Else it will be filled with 0. + * @param flag + * Bitfield for control purposes + * bit2= do not issue own error messages with system call errors + * bit5= in case of symbolic link: operate on link target + * @return + * 1 = ok, projid was written + * 3 = ok, symbolic link encountered, flag bit5 not set, nothing done + * <0 = error + * + * @since 1.5.8 + */ +int iso_local_set_projid(char *disk_path, uint32_t projid, int *os_errno, + int flag); /* Default in case that the compile environment has no macro PATH_MAX. @@ -9742,10 +9848,26 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len, (SORRY,HIGH, -434) */ #define ISO_LFA_NO_SET_LOCAL 0xE030FE4E -/** Failure to open local file for setting Linux-like file attributes +/** Failure to open local file for Linux-like file attributes (SORRY,HIGH, -435) */ #define ISO_LFA_NO_OPEN_LOCAL 0xE030FE4D +/** Local XFS-style file project id processing not enabled at compile time + (SORRY,HIGH, -436) */ +#define ISO_PROJID_NOT_ENABLED 0xE030FE4C + +/** Error with getting XFS-style project id of local file + (SORRY,HIGH, -437) */ +#define ISO_PROJID_NO_GET_LOCAL 0xE030FE4B + +/** Error with setting XFS-style project id of local file + (SORRY,HIGH, -438) */ +#define ISO_PROJID_NO_SET_LOCAL 0xE030FE4A + +/** Failure to open local file for XFS-style project id + (SORRY,HIGH, -439) */ +#define ISO_PROJID_NO_OPEN_LOCAL 0xE030FE49 + /* Internal developer note: diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index b93d455..87af30b 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -387,9 +387,13 @@ local: *; LIBISOFS6_1.5.8 { iso_local_get_lfa_flags; +iso_local_get_projid; iso_local_set_lfa_flags; +iso_local_set_projid; iso_node_get_lfa_flags; +iso_node_get_projid; iso_node_set_lfa_flags; +iso_node_set_projid; iso_util_decode_lfa_flags; iso_util_encode_lfa_flags; iso_util_get_effective_lfa_mask; diff --git a/libisofs/messages.c b/libisofs/messages.c index 7d8a525..5b8e2d4 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -585,6 +585,14 @@ const char *iso_error_to_msg(int errcode) return "Error with setting Linux-like file attributes of local file"; case ISO_LFA_NO_OPEN_LOCAL: return "Failure to open local file for Linux-like file attributes"; + case ISO_PROJID_NOT_ENABLED: + return "Local XFS-style file project id processing not enabled at compile time"; + case ISO_PROJID_NO_GET_LOCAL: + return "Error with getting XFS-style project id of local file"; + case ISO_PROJID_NO_SET_LOCAL: + return "Error with setting XFS-style project id of local file"; + case ISO_PROJID_NO_OPEN_LOCAL: + return "Failure to open local file for XFS-style project id"; default: return "Unknown error"; } diff --git a/libisofs/node.c b/libisofs/node.c index 5fa8996..4a5b61a 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -2058,6 +2058,7 @@ ex:; /* @param flag bit0= delete ACL, too bit1= delete file attribute flags (isofs.fa), too + bit2= delete XFS-style project id (isofs.pi), too */ int iso_node_remove_fattr(IsoNode *node, int flag) { @@ -2074,7 +2075,8 @@ int iso_node_remove_fattr(IsoNode *node, int flag) w = 0; for (i = 0; i < num_attrs; i++) { if (strncmp(names[i], "isofs.", 6) != 0 || - ((flag & 2) && strcmp(names[i], "isofs.fa") == 0)) { + ((flag & 2) && strcmp(names[i], "isofs.fa") == 0) || + ((flag & 4) && strcmp(names[i], "isofs.pi") == 0)) { free(names[i]); names[i] = NULL; free(values[i]); @@ -2462,7 +2464,7 @@ int iso_node_set_lfa_flags(IsoNode *node, uint64_t lfa_flags, int flag) char *valuept; int ret, l; - ret = aaip_encode_lfa_flags(lfa_flags, value, &l, 0); + ret = aaip_encode_uint64(lfa_flags, value, &l, 0); if (ret < 0) return ret; value_lengths[0] = l; @@ -2501,6 +2503,57 @@ int iso_node_get_lfa_flags(IsoNode *node, uint64_t *lfa_flags, int *max_bit, } +int iso_node_set_projid(IsoNode *node, uint32_t projid, int flag) +{ + static char *names = "isofs.pi"; + static size_t value_lengths[1]; + unsigned char value[8]; + char *valuept = NULL; + int ret, l; + + value_lengths[0] = 0; + if(projid == 0) { + /* Delete isofs.pi */ + ret = iso_node_set_attrs(node, (size_t) 1, &names, + value_lengths, &valuept, 2 | 4 | 8); + return ret; + } + ret = aaip_encode_uint64((uint64_t) projid, value, &l, 0); + if (ret < 0) + return ret; + value_lengths[0] = l; + valuept= (char *) value; + ret = iso_node_set_attrs(node, (size_t) 1, + &names, value_lengths, &valuept, 2 | 8); + return ret; +} + + +int iso_node_get_projid(IsoNode *node, uint32_t *projid, int flag) +{ + int ret, i; + size_t value_len; + char *value = NULL; + + *projid = 0; + + ret = iso_node_lookup_attr(node, "isofs.pi", &value_len, &value, 0); + if (ret < 0) + return ret; + if (ret == 0) + return 1; + if (value_len <= 0) + return 1; + if (value_len > 4) { + value += value_len - 4; + value_len = 4; + } + for (i = 0; i < (int) value_len; i++) + *projid = (*projid << 8) | ((unsigned char *) value)[i]; + return 1; +} + + /* Function to identify and manage ZF parameters. * data is supposed to be a pointer to struct zisofs_zf_info */ diff --git a/libisofs/rockridge.c b/libisofs/rockridge.c index f432e9f..8e6bc23 100644 --- a/libisofs/rockridge.c +++ b/libisofs/rockridge.c @@ -1600,10 +1600,10 @@ try_again: } } else if (retry == 2) { if ((t->opts->max_ce_drop_attr & 15) >= 2) { - ret = iso_node_remove_fattr(n->node, 1 | 2); + ret = iso_node_remove_fattr(n->node, 1 | 2 | 4); if (ret > 0) { iso_msg_submit(t->image->id, ISO_CE_REMOVING_ATTR, 0, - "Removed ACL and attribute flags"); + "Removed ACL, attribute flags, project id"); goto try_again; } }