@@ -665,6 +665,11 @@ static constexpr const char kConfigUsageLines[] =
665665 " PATH [--mode ro|rw] [--persist]\n "
666666 " ll-cli config rm-fs [--global | <appid> | --base <baseid>] (--target PATH | "
667667 " --index N)\n "
668+ " ll-cli config add-fs-allow [--global | <appid> | --base <baseid>] --host PATH --target "
669+ " PATH [--mode ro|rw] [--persist]\n "
670+ " ll-cli config rm-fs-allow [--global | <appid> | --base <baseid>] (--target PATH | "
671+ " --index N)\n "
672+ " ll-cli config clear-fs-allow [--global | <appid> | --base <baseid>]\n "
668673 " ll-cli config set-command [--global | <appid> | --base <baseid>] <cmd> [--entrypoint P] "
669674 " [--cwd D] [--args-prefix \" ...\" ] [--args-suffix \" ...\" ] [KEY=VAL ...]\n "
670675 " ll-cli config unset-command [--global | <appid> | --base <baseid>] <cmd>\n " ;
@@ -895,9 +900,9 @@ struct FsArg {
895900 bool persist = false ;
896901};
897902
898- static void jsonAddFs (json &root, const FsArg &fs)
903+ static void jsonAddFsTo (json &root, const FsArg &fs, const char *field )
899904{
900- auto &arr = root[" filesystem " ];
905+ auto &arr = root[field ];
901906 if (!arr.is_array ()) {
902907 arr = json::array ();
903908 }
@@ -919,12 +924,22 @@ static void jsonAddFs(json &root, const FsArg &fs)
919924 arr.push_back (std::move (o));
920925}
921926
922- static bool jsonRmFsByTarget (json &root, const std::string &target)
927+ static void jsonAddFs (json &root, const FsArg &fs)
928+ {
929+ jsonAddFsTo (root, fs, " filesystem" );
930+ }
931+
932+ static void jsonAddFsAllow (json &root, const FsArg &fs)
933+ {
934+ jsonAddFsTo (root, fs, " filesystem_allow_only" );
935+ }
936+
937+ static bool jsonRmFsByTargetFrom (json &root, const std::string &target, const char *field)
923938{
924- if (!root.contains (" filesystem " ) || !root[" filesystem " ].is_array ()) {
939+ if (!root.contains (field ) || !root[field ].is_array ()) {
925940 return false ;
926941 }
927- auto &arr = root[" filesystem " ];
942+ auto &arr = root[field ];
928943 auto old = arr.size ();
929944 arr.erase (std::remove_if (arr.begin (), arr.end (), [&](const json &e) {
930945 return e.is_object () && e.value (" target" , " " ) == target;
@@ -933,19 +948,44 @@ static bool jsonRmFsByTarget(json &root, const std::string &target)
933948 return arr.size () != old;
934949}
935950
936- static bool jsonRmFsByIndex (json &root, size_t idx )
951+ static bool jsonRmFsByTarget (json &root, const std::string &target )
937952{
938- if (!root.contains (" filesystem" ) || !root[" filesystem" ].is_array ()) {
953+ return jsonRmFsByTargetFrom (root, target, " filesystem" );
954+ }
955+
956+ static bool jsonRmFsAllowByTarget (json &root, const std::string &target)
957+ {
958+ return jsonRmFsByTargetFrom (root, target, " filesystem_allow_only" );
959+ }
960+
961+ static bool jsonRmFsByIndexFrom (json &root, size_t idx, const char *field)
962+ {
963+ if (!root.contains (field) || !root[field].is_array ()) {
939964 return false ;
940965 }
941- auto &arr = root[" filesystem " ];
966+ auto &arr = root[field ];
942967 if (idx >= arr.size ()) {
943968 return false ;
944969 }
945970 arr.erase (arr.begin () + idx);
946971 return true ;
947972}
948973
974+ static bool jsonRmFsByIndex (json &root, size_t idx)
975+ {
976+ return jsonRmFsByIndexFrom (root, idx, " filesystem" );
977+ }
978+
979+ static bool jsonRmFsAllowByIndex (json &root, size_t idx)
980+ {
981+ return jsonRmFsByIndexFrom (root, idx, " filesystem_allow_only" );
982+ }
983+
984+ static void jsonClearFsAllow (json &root)
985+ {
986+ root[" filesystem_allow_only" ] = json::array ();
987+ }
988+
949989struct CmdSetArg {
950990 std::string cmd;
951991 std::optional<std::string> entrypoint;
@@ -1264,6 +1304,40 @@ int runCliApplication(int argc, char **mainArgv)
12641304 }
12651305 return 0 ;
12661306 }
1307+ if (sub == " add-fs-allow" ) {
1308+ auto [scope, appId, baseId, i] = parseScope (3 );
1309+ FsArg fs;
1310+ fs.mode = " ro" ;
1311+ fs.persist = false ;
1312+ for (; i < argc; ++i) {
1313+ std::string a = mainArgv[i];
1314+ if (a == " --persist" ) {
1315+ fs.persist = true ;
1316+ } else if (a == " --host" && i + 1 < argc) {
1317+ fs.host = mainArgv[++i];
1318+ } else if (a == " --target" && i + 1 < argc) {
1319+ fs.target = mainArgv[++i];
1320+ } else if (a == " --mode" && i + 1 < argc) {
1321+ fs.mode = mainArgv[++i];
1322+ } else {
1323+ fprintf (stderr, " unknown arg: %s\n " , a.c_str ());
1324+ return 1 ;
1325+ }
1326+ }
1327+ if (fs.host .empty () || fs.target .empty ()) {
1328+ printConfigUsage ();
1329+ return 1 ;
1330+ }
1331+ auto j = openConfig (scope, appId, baseId);
1332+ if (!j) {
1333+ return 1 ;
1334+ }
1335+ jsonAddFsAllow (*j, fs);
1336+ if (!saveConfig (scope, appId, baseId, *j)) {
1337+ return 1 ;
1338+ }
1339+ return 0 ;
1340+ }
12671341 if (sub == " rm-fs" ) {
12681342 auto [scope, appId, baseId, i] = parseScope (3 );
12691343 std::optional<std::string> target;
@@ -1303,6 +1377,57 @@ int runCliApplication(int argc, char **mainArgv)
13031377 }
13041378 return 0 ;
13051379 }
1380+ if (sub == " rm-fs-allow" ) {
1381+ auto [scope, appId, baseId, i] = parseScope (3 );
1382+ std::optional<std::string> target;
1383+ std::optional<size_t > index;
1384+ for (; i < argc; ++i) {
1385+ std::string a = mainArgv[i];
1386+ if (a == " --target" && i + 1 < argc) {
1387+ target = mainArgv[++i];
1388+ } else if (a == " --index" && i + 1 < argc) {
1389+ index = static_cast <size_t >(std::stoul (mainArgv[++i]));
1390+ } else {
1391+ fprintf (stderr, " unknown arg: %s\n " , a.c_str ());
1392+ return 1 ;
1393+ }
1394+ }
1395+ if (!target && !index) {
1396+ printConfigUsage ();
1397+ return 1 ;
1398+ }
1399+ auto j = openConfig (scope, appId, baseId);
1400+ if (!j) {
1401+ return 1 ;
1402+ }
1403+ bool ok = false ;
1404+ if (target) {
1405+ ok = jsonRmFsAllowByTarget (*j, *target);
1406+ }
1407+ if (!ok && index) {
1408+ ok = jsonRmFsAllowByIndex (*j, *index);
1409+ }
1410+ if (!ok) {
1411+ fprintf (stderr, " no filesystem_allow entry removed\n " );
1412+ return 1 ;
1413+ }
1414+ if (!saveConfig (scope, appId, baseId, *j)) {
1415+ return 1 ;
1416+ }
1417+ return 0 ;
1418+ }
1419+ if (sub == " clear-fs-allow" ) {
1420+ auto [scope, appId, baseId, i] = parseScope (3 );
1421+ auto j = openConfig (scope, appId, baseId);
1422+ if (!j) {
1423+ return 1 ;
1424+ }
1425+ jsonClearFsAllow (*j);
1426+ if (!saveConfig (scope, appId, baseId, *j)) {
1427+ return 1 ;
1428+ }
1429+ return 0 ;
1430+ }
13061431 if (sub == " set-command" ) {
13071432 auto [scope, appId, baseId, i] = parseScope (3 );
13081433 if (i >= argc) {
0 commit comments