@@ -440,7 +440,7 @@ static const char * const mkfs_usage[] = {
440440 "Creation:" ,
441441 OPTLINE ("-b|--byte-count SIZE" , "set size of each device to SIZE (filesystem size is sum of all device sizes)" ),
442442 OPTLINE ("-r|--rootdir DIR" , "copy files from DIR to the image root directory" ),
443- OPTLINE ("-u|--subvol SUBDIR" , "create SUBDIR as subvolume rather than normal directory, can be specified multiple times" ),
443+ OPTLINE ("-u|--subvol SUBDIR:FLAGS " , "create SUBDIR as subvolume rather than normal directory, can be specified multiple times" ),
444444 OPTLINE ("--shrink" , "(with --rootdir) shrink the filled filesystem to minimal size" ),
445445 OPTLINE ("-K|--nodiscard" , "do not perform whole device TRIM" ),
446446 OPTLINE ("-f|--force" , "force overwrite of existing filesystem" ),
@@ -1015,6 +1015,46 @@ static void *prepare_one_device(void *ctx)
10151015 return NULL ;
10161016}
10171017
1018+ static int parse_subvol_flags (struct rootdir_subvol * subvol , const char * flags )
1019+ {
1020+ char * buf , * orig_buf ;
1021+ int ret ;
1022+
1023+ buf = orig_buf = strdup (flags );
1024+
1025+ if (!buf ) {
1026+ error_msg (ERROR_MSG_MEMORY , NULL );
1027+ ret = - ENOMEM ;
1028+ goto out ;
1029+ }
1030+
1031+ while (true) {
1032+ char * comma = strstr (buf , "," );
1033+
1034+ if (comma )
1035+ * comma = 0 ;
1036+
1037+ if (!strcmp (buf , "default" )) {
1038+ subvol -> is_default = true;
1039+ } else if (buf [0 ] != 0 ) {
1040+ error ("unrecognized subvol flag \"%s\"" , buf );
1041+ ret = 1 ;
1042+ goto out ;
1043+ }
1044+
1045+ if (comma )
1046+ buf = comma + 1 ;
1047+ else
1048+ break ;
1049+ }
1050+
1051+ ret = 0 ;
1052+
1053+ out :
1054+ free (orig_buf );
1055+ return ret ;
1056+ }
1057+
10181058int BOX_MAIN (mkfs )(int argc , char * * argv )
10191059{
10201060 char * file ;
@@ -1058,6 +1098,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
10581098 char * source_dir = NULL ;
10591099 size_t source_dir_len = 0 ;
10601100 struct rootdir_subvol * rds ;
1101+ bool has_default_subvol = false;
10611102 LIST_HEAD (subvols );
10621103
10631104 cpu_detect_flags ();
@@ -1215,16 +1256,49 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
12151256 break ;
12161257 case 'u' : {
12171258 struct rootdir_subvol * subvol ;
1259+ char * colon ;
12181260
1219- subvol = malloc ( sizeof (struct rootdir_subvol ));
1261+ subvol = calloc ( 1 , sizeof (struct rootdir_subvol ));
12201262 if (!subvol ) {
12211263 error_msg (ERROR_MSG_MEMORY , NULL );
12221264 ret = 1 ;
12231265 goto error ;
12241266 }
12251267
1226- subvol -> dir = strdup (optarg );
1227- subvol -> full_path = NULL ;
1268+ colon = strstr (optarg , ":" );
1269+
1270+ if (colon ) {
1271+ /* Make sure we choose the last colon in
1272+ * optarg, in case the subvol name
1273+ * itself contains a colon. */
1274+ do {
1275+ char * colon2 ;
1276+
1277+ colon2 = strstr (colon + 1 , ":" );
1278+
1279+ if (colon2 )
1280+ colon = colon2 ;
1281+ else
1282+ break ;
1283+ } while (true);
1284+
1285+ subvol -> dir = strndup (optarg , colon - optarg );
1286+ if (parse_subvol_flags (subvol , colon + 1 )) {
1287+ ret = 1 ;
1288+ goto error ;
1289+ }
1290+ } else {
1291+ subvol -> dir = strdup (optarg );
1292+ }
1293+
1294+ if (subvol -> is_default ) {
1295+ if (has_default_subvol ) {
1296+ error ("subvol default flag can only be specified once" );
1297+ ret = 1 ;
1298+ goto error ;
1299+ }
1300+ has_default_subvol = true;
1301+ }
12281302
12291303 list_add_tail (& subvol -> list , & subvols );
12301304 break ;
0 commit comments