mount: add support for -O list. +44 bytes
No binary (build failed)
—
(log yok)
| @@ -1760,43 +1760,61 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |
| return rc; | |
| } | |
| - | /* -O support |
| - | * Unlike -t, -O should interpret "no" prefix differently: |
| - | * -t noa,b,c = -t no(a,b,c) = mount all except fs'es with types a,b, and c |
| - | * -O noa,b,c = -O noa,b,c = mount all with without option a, |
| - | * or with option b or c. |
| - | * But for now we do not support -O a,b,c at all (only -O a). |
| - | * |
| - | * Another difference from -t support (match_fstype) is that |
| - | * we need to examine the _list_ of options in fsopt, not just a string. |
| - | */ |
| - | static int match_opt(const char *fs_opt, const char *O_opt) |
| + | // -O support |
| + | // -O interprets a list of filter options which select whether a mount |
| + | // point will be mounted: only mounts with options matching *all* filtering |
| + | // options will be selected. |
| + | // By default each -O filter option must be present in the list of mount |
| + | // options, but if it is prefixed by "no" then it must be absent. |
| + | // For example, |
| + | // -O a,nob,c matches -o a,c but fails to match -o a,b,c |
| + | // (and also fails to match -o a because -o c is absent). |
| + | // |
| + | // It is different from -t in that each option is matched exactly; a leading |
| + | // "no" at the beginning of one option does not negate the rest. |
| + | static int match_opt(const char *fs_opt_in, const char *O_opt) |
| { | |
| - | int match = 1; |
| - | int len; |
| - | |
| if (!O_opt) | |
| - | return match; |
| - | |
| - | if (O_opt[0] == 'n' && O_opt[1] == 'o') { |
| - | match--; |
| - | O_opt += 2; |
| - | } |
| - | |
| - | len = strlen(O_opt); |
| - | while (1) { |
| - | if (strncmp(fs_opt, O_opt, len) == 0 |
| - | && (fs_opt[len] == '\0' || fs_opt[len] == ',') |
| - | ) { |
| - | return match; |
| + | return 1; |
| + | |
| + | while (*O_opt) { |
| + | const char *fs_opt = fs_opt_in; |
| + | int O_len; |
| + | int match; |
| + | |
| + | // If option begins with "no" then treat as an inverted match: |
| + | // matching is a failure |
| + | match = 0; |
| + | if (O_opt[0] == 'n' && O_opt[1] == 'o') { |
| + | match = 1; |
| + | O_opt += 2; |
| + | } |
| + | // Isolate the current O option |
| + | O_len = strchrnul(O_opt, ',') - O_opt; |
| + | // Check for a match against existing options |
| + | while (1) { |
| + | if (strncmp(fs_opt, O_opt, O_len) == 0 |
| + | && (fs_opt[O_len] == '\0' || fs_opt[O_len] == ',') |
| + | ) { |
| + | if (match) |
| + | return 0; // "no" prefix, but option found |
| + | match = 1; // current O option found, go check next one |
| + | break; |
| + | } |
| + | fs_opt = strchr(fs_opt, ','); |
| + | if (!fs_opt) |
| + | break; |
| + | fs_opt++; |
| } | |
| - | fs_opt = strchr(fs_opt, ','); |
| - | if (!fs_opt) |
| + | if (match == 0) |
| + | return 0; // match wanted but not found |
| + | if (O_opt[O_len] == '\0') // end? |
| break; | |
| - | fs_opt++; |
| + | // Step to the next O option |
| + | O_opt += O_len + 1; |
| } | |
| - | |
| - | return !match; |
| + | // If we get here then everything matched |
| + | return 1; |
| } | |
| // Parse options, if necessary parse fstab/mtab, and call singlemount for | |