@@ -493,8 +493,8 @@ XrdMgmOfs::_attr_rem(const char* path, XrdOucErrInfo& error,
493493 eos::IContainerMD::XAttrMap attr_map = cmd->getAttributes ();
494494 Acl acl (attr_map, vid);
495495
496- if (vid.token || (!cmd->access (vid.uid , vid.gid , X_OK | W_OK) &&
497- !acl.AllowXAttrUpdate (skey, vid))) {
496+ if (vid.token || (!cmd->access (vid.uid , vid.gid , X_OK | W_OK) &&
497+ !acl.AllowXAttrUpdate (skey, vid))) {
498498 errno = EPERM;
499499 } else {
500500 if (!cmd->hasAttribute (skey)) {
@@ -527,108 +527,151 @@ XrdMgmOfs::_attr_rem(const char* path, XrdOucErrInfo& error,
527527}
528528
529529// ----------------------------------------------------------------------------
530- // ! List Attributes high-level function merging space and namespace attributes
530+ // List attributes high-level function merging space and namespace attributes
531531// ----------------------------------------------------------------------------
532-
533532void
534- XrdMgmOfs::mergeSpaceAttributes (eos::IContainerMD::XAttrMap& out, bool prefix, bool existing){
533+ XrdMgmOfs::mergeSpaceAttributes (eos::IContainerMD::XAttrMap& out, bool prefix,
534+ bool existing)
535+ {
535536 std::string space = " default" ;
537+
536538 if (out.count (" sys.forced.space" )) {
537539 space = out[" sys.forced.space" ];
538540 }
539- std::map<std::string,std::string> attr;
541+
542+ std::map<std::string, std::string> attr;
543+
540544 if (gOFS ->mSpaceAttributes .count (space)) {
541- // retrieve space arguments
542- std::unique_lock<std::mutex> lock (gOFS ->mSpaceAttributesMutex );
543- attr = gOFS ->mSpaceAttributes [space];
544- }
545- // loop over arguments
546- for ( auto x:attr ) {
547- if (x.first == " sys.forced.space" ) {
548- // we ignore this
545+ // retrieve space arguments
546+ std::unique_lock<std::mutex> lock (gOFS ->mSpaceAttributesMutex );
547+ attr = gOFS ->mSpaceAttributes [space];
548+ }
549+
550+ // loop over arguments
551+ for (const auto & x : attr) {
552+ if (x.first == " sys.forced.space" ) {
553+ // we ignore this
554+ continue ;
555+ } else {
556+ if (existing && !out.count (x.first )) {
557+ // merge only existing attributes
558+ continue ;
559+ }
560+
561+ std::string inkey = x.first ;
562+ std::string outkey = (prefix ? (std::string (" sys.space." ) + x.first ) : x.first );
563+
564+ if (x.first == " sys.acl" ) {
565+ // Special meaning of the first char:
566+ // > append acl to the existing ones
567+ // < prepend acl to the existing ones
568+ // | add only if acls not set at all
569+ // none of the above means overwrite existring acls
570+ char op = ' \0 ' ;
571+
572+ if (!x.second .empty ()) {
573+ op = x.second [0 ];
574+ }
575+
576+ std::string old_acls = out[" sys.acl" ];
577+ std::string space_acls = x.second ;
578+
579+ if ((op == ' >' ) || (op == ' <' ) || (op == ' |' )) {
580+ space_acls = space_acls.erase (0 , 1 );
581+ }
582+
583+ // ACL handling
584+ if (((op != ' >' ) && (op != ' <' ) && (op != ' |' )) || // Full overwrite
585+ ((op == ' |' ) && old_acls.empty ())) { // Overwrite if empty
586+ out[outkey] = space_acls;
587+ } else {
588+ // If existing acls already include the space acls then
589+ // remove them to avoid duplicates.
590+ auto pos = old_acls.find (space_acls);
591+
592+ if ((pos != std::string::npos) && (op != ' |' )) {
593+ auto del_pos = pos;
594+ auto del_len = space_acls.length ();
595+
596+ // Either delete the command before or the comma after
597+ if (del_pos && (old_acls[del_pos - 1 ] == ' ,' )) {
598+ --del_pos;
599+ ++del_len;
600+ } else if ((del_pos + del_len < old_acls.length ()) &&
601+ (old_acls[del_pos + del_len] == ' ,' )) {
602+ ++del_len;
603+ }
604+
605+ old_acls = old_acls.erase (del_pos, del_len);
606+ }
607+
608+ if (op == ' >' ) { // Append rule
609+ out[outkey] = old_acls + std::string (" ," ) + space_acls;
610+ } else if (op == ' <' ) { // Prepend rule
611+ out[outkey] = space_acls + std::string (" ," ) + old_acls;
612+ }
613+
614+ if (op == ' |' ) {
615+ out[outkey] = old_acls;
616+ }
617+ }
549618 } else {
550- if (existing && !out.count (x.first )) {
551- // merge only existing attributes
552- continue ;
553- }
554- std::string inkey=x.first ;
555- std::string outkey=prefix?(std::string (" sys.space." ) + x.first ): x.first ;
556- if (x.first == " sys.acl" ) {
557- // ACL handling
558- if (x.second .substr (0 ,1 ) == " >" ) {
559- if (out[" sys.acl" ].length ()) {
560- // append rule
561- out[outkey] = out[" sys.acl" ] + std::string (" ," ) + x.second .substr (1 );
562- } else {
563- out[outkey] = x.second .substr (1 );
564- }
565- } else if (x.second .substr (0 ,1 ) == " <" ) {
566- if (out[" sys.acl" ].length ()) {
567- // prepend rule
568- out[outkey] = x.second .substr (1 ) + std::string (" ," ) + out[" sys.acl" ];
569- } else {
570- out[outkey] = x.second .substr (1 );
571- }
572- } else if (x.second .substr (0 ,1 ) == " |" ) {
573- if (!out[" sys.acl" ].length ()) {
574- // if not set rule
575- out[outkey] = x.second .substr (1 );
576- }
577- } else {
578- // overwrite rule
579- out[outkey] = x.second ;
580- }
581- } else {
582- // normal attribute handling
583- if (x.second .substr (0 ,1 ) == " |" ) {
584- // if not set rule
585- if (!out[x.first ].length ()) {
586- out[outkey] = x.second .substr (1 );
587- }
588- } else {
589- // overwrite rule
590- out[outkey] = x.second ;
591- }
592- }
619+ // Normal attribute handling
620+ if (x.second .substr (0 , 1 ) == " |" ) {
621+ // if not set rule
622+ if (!out[x.first ].length ()) {
623+ out[outkey] = x.second .substr (1 );
624+ }
625+ } else {
626+ // overwrite rule
627+ out[outkey] = x.second ;
628+ }
593629 }
594630 }
631+ }
595632}
596633
597634
598635void
599636XrdMgmOfs::listAttributes (eos::IView* view, eos::IContainerMD* target,
600- eos::IContainerMD::XAttrMap& out, bool prefixLinks){
637+ eos::IContainerMD::XAttrMap& out, bool prefixLinks)
638+ {
601639 eos::listAttributes (view, target, out, prefixLinks);
602640 mergeSpaceAttributes (out);
603641}
604642
605643void
606644XrdMgmOfs::listAttributes (eos::IView* view, eos::IFileMD* target,
607- eos::IContainerMD::XAttrMap& out, bool prefixLinks){
645+ eos::IContainerMD::XAttrMap& out, bool prefixLinks)
646+ {
608647 eos::listAttributes (view, target, out, prefixLinks);
609648 mergeSpaceAttributes (out);
610649}
611650
612651void
613652XrdMgmOfs::listAttributes (eos::IView* view, eos::FileOrContainerMD target,
614- eos::IContainerMD::XAttrMap& out, bool prefixLinks){
653+ eos::IContainerMD::XAttrMap& out, bool prefixLinks)
654+ {
615655 eos::listAttributes (view, target, out, prefixLinks);
616656 mergeSpaceAttributes (out);
617657}
618658
619659template <typename T>
620660bool XrdMgmOfs::getAttribute (eos::IView* view, T& md, std::string key,
621- std::string& rvalue)
661+ std::string& rvalue)
622662{
623663 auto result = eos::getAttribute (view, md, key, rvalue);
624664 eos::IContainerMD::XAttrMap attr;
665+
625666 if (!result) {
626- attr[key]= " " ;
667+ attr[key] = " " ;
627668 } else {
628669 attr[key] = rvalue;
629670 }
630- mergeSpaceAttributes (attr,false ,true );
671+
672+ mergeSpaceAttributes (attr, false , true );
631673 rvalue = attr[key];
674+
632675 if (!result) {
633676 return attr[key].length ();
634677 } else {
0 commit comments