commit: 604787e02b2ad230af2861917848970a6484afda
parent 59a90280fe0ac46c055e2f317babcc8982a0f197
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sat, 12 Apr 2025 20:18:04 +0200
lib/mode: fix handling of …-s / …=s and …-t / …=t
Diffstat:
2 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/lib/mode.c b/lib/mode.c
@@ -247,26 +247,50 @@ new_mode(const char *mode, mode_t old, const char **errstr)
if(S_ISDIR(old)) apply(&meta, 01);
break;
case 's':
+ {
if(meta.op == OP_RST)
{
*errstr = "perm 's' given without operator";
return 0;
}
- if(FIELD_MATCH(meta.dest, WHO_USER))
- meta.new_modes.set = S_ISUID >> 9;
- else if(FIELD_MATCH(meta.dest, WHO_GROUP))
- meta.new_modes.set = S_ISGID >> 9;
- else
- meta.new_modes.set = S_ISUID >> 9;
+ mode_t set_id = S_ISUID >> 9;
+ if(FIELD_MATCH(meta.dest, WHO_GROUP)) set_id = S_ISGID >> 9;
+
+ switch(meta.op)
+ {
+ case OP_ADD:
+ FIELD_SET(meta.new_modes.set, set_id);
+ break;
+ case OP_DEL:
+ FIELD_CLR(meta.new_modes.set, set_id);
+ break;
+ case OP_SET:
+ meta.new_modes.set = set_id;
+ break;
+ default:
+ abort();
+ }
break;
+ }
case 't':
// Implementation defined behavior outside of directories and !(WHO_ALL|WHO_RST)
- if(meta.op == OP_RST)
+ switch(meta.op)
{
+ case OP_RST:
*errstr = "perm 't' given without operator";
return 0;
+ case OP_ADD:
+ FIELD_SET(meta.new_modes.set, S_ISVTX >> 9);
+ break;
+ case OP_DEL:
+ FIELD_CLR(meta.new_modes.set, S_ISVTX >> 9);
+ break;
+ case OP_SET:
+ meta.new_modes.set = S_ISVTX >> 9;
+ break;
+ default:
+ abort();
}
- meta.new_modes.set = S_ISVTX >> 9;
break;
default:
diff --git a/test-lib/t_mode.c b/test-lib/t_mode.c
@@ -288,7 +288,7 @@ non_symbolic(void)
int
main(void)
{
- int plan = 155;
+ int plan = 161;
printf("1..%d\n", plan);
t_mode(NULL, 0, 0);
@@ -300,6 +300,14 @@ main(void)
t_mode("-w,+x", 00666, 00577);
+ t_mode("a-wx,u+x,u+s", 00666, 04544);
+ t_mode("a-wx,ug+x,g+s", 00666, 02554);
+ t_mode("a-wx,ug+x,+t", 00666, 01554);
+
+ t_mode("-s", 04544, 00544);
+ t_mode("g-s", 02544, 00544);
+ t_mode("-t", 01544, 00544);
+
add_read();
set_read();
del_read();