Class List Method List File List

# Class: Yast::NfsOptionsClass

Inherits:
  Module
  - Object
  - Module
  - Yast::NfsOptionsClass
  show all
Defined in:
  ../../src/modules/NfsOptions.rb

## Instance Method Summary (collapse)

- - (Array) from_string(options)

  Parse to an internal representation: Simply split by commas, but “defaults” is represented by the empty list.

- - (Object) get_nfs41(options)

  FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! * @param options fstab option string * @return is version >= 4.1 enabled.

- - (Object) main
- - (Object) set_nfs41(options, nfs41)

  Add or remove minorversion=1 according to nfs41.

- - (Object) to_string(option_list)

  Convert list of individual options to a fstab option string.

- - (Object) validate(options)

  Checks the nfs options for /etc/fstab: nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)).

## Instance Method Details

### - (`Array`) from_string(options)

Parse to an internal representation: Simply split by commas, but "defaults" is represented by the empty list

Parameters:

- options (`String`) —

  a fstab option string

Returns:

- (`Array`) —

  of individual options

    15
    16
    17
    18
    # File '../../src/modules/NfsOptions.rb', line 15

    def from_string(options)
      options = "" if options == "defaults"
      Builtins.splitstring(options, ",")
    end

### - (`Object`) get_nfs41(options)

FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! * @param options fstab option string * @return is version >= 4.1 enabled

    176
    177
    178
    179
    180
    181
    # File '../../src/modules/NfsOptions.rb', line 176

    def get_nfs41(options)
      option_list = from_string(options)

      _ENABLED = "minorversion=1"
      Builtins.contains(option_list, _ENABLED)
    end

### - (`Object`) main

    7
    8
    9
    # File '../../src/modules/NfsOptions.rb', line 7

    def main
      textdomain "nfs"
    end

### - (`Object`) set_nfs41(options, nfs41)

Add or remove minorversion=1 according to nfs41. FIXME vfstype=nfs4 is deprecated in favor of nfsvers=4 (aka vers=4)

Parameters:

- options (`String`) —

  fstab option string

- nfs41 (`Boolean`) —

  is version >= 4.1 enabled

Returns:

- new fstab option string

    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    # File '../../src/modules/NfsOptions.rb', line 188

    def set_nfs41(options, nfs41)
      # don't mutate the string unnecessarily
      return options if get_nfs41(options) == nfs41

      _ENABLED = "minorversion=1"
      _DISABLED = "minorversion=0"

      option_list = from_string(options)
      option_list = Builtins.filter(option_list) { |opt| opt != _ENABLED }
      option_list = Builtins.filter(option_list) { |opt| opt != _DISABLED }

      option_list = Builtins.add(option_list, _ENABLED) if nfs41

      to_string(option_list)
    end

### - (`Object`) to_string(option_list)

Convert list of individual options to a fstab option string

Parameters:

- option_list (`Array<String>`) —

  list of individual options

Returns:

- a fstab option string

    23
    24
    25
    26
    27
    28
    # File '../../src/modules/NfsOptions.rb', line 23

    def to_string(option_list)
      option_list = deep_copy(option_list)
      options = Builtins.mergestring(option_list, ",")
      options = "defaults" if options == ""
      options
    end

### - (`Object`) validate(options)

Checks the nfs options for /etc/fstab: nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5))

Parameters:

- options (`String`) —

  options

Returns:

- a translated string with error message, emtpy string if ok

    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    # File '../../src/modules/NfsOptions.rb', line 34

    def validate(options)
      # To translators: error popup
      if Builtins.size(options) == 0
        return _("Empty option strings are not allowed.")
      end

      option_list = from_string(options)

      # The options should be kept synced with the code that handles them,
      # which is not an easy task, as there are many places:
      # - util-linux.rpm
      #   man 8 mount
      #   https://git.kernel.org/?p=utils/util-linux/util-linux.git;a=history;f=libmount/src/optmap.c
      # - nfs-client.rpm (nfs-utils.src.rpm)
      #   man 5 nfs
      #   http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=history;f=utils/mount/nfsmount.c
      # - kernel: fs/nfs/super.c
      #   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=history;f=fs/nfs/super.c
      # Note that minorversion in particular is mentioned only in the kernel
      # but not in nfs-utils. WTF.

      # these can be negated by "no"
      _NEGATABLE_OPTIONS = [
        "bg",
        "fg",
        "soft",
        "hard",
        "intr",
        "posix",
        "cto",
        "ac",
        "acl",
        "lock",
        "tcp",
        "udp",
        "rdirplus",
        # these are common for all fs types
        "atime",
        "auto",
        "dev",
        "exec",
        "group",
        "owner",
        "suid",
        "user",
        "users"
      ]
      _NEGATED_OPTIONS = Builtins.maplist(_NEGATABLE_OPTIONS) do |e|
        Builtins.sformat("no%1", e)
      end

      # these cannot be negated
      # they are not nfs specific BTW
      _SIMPLE_OPTIONS = [
        "defaults",
        "async",
        "sync",
        "dirsync",
        "ro",
        "rw",
        "remount",
        "bind",
        "rbind",
        "_netdev"
      ]
      _OPTIONS_WITH_VALUE = [
        "rsize",
        "wsize",
        "timeo",
        "retrans",
        "acregmin",
        "acregmax",
        "acdirmin",
        "acdirmin",
        "acdirmax",
        "actimeo",
        "retry",
        "namlen",
        "port",
        "proto",
        "clientaddr",
        "mountport",
        "mounthost",
        "mountprog",
        "mountvers",
        "nfsprog",
        "nfsvers",
        "vers",
        "minorversion",
        "sec"
      ]

      # first fiter out non value options and its nooptions forms (see nfs(5))
      option_list = Builtins.filter(option_list) do |e|
        !Builtins.contains(_NEGATABLE_OPTIONS, e)
      end
      option_list = Builtins.filter(option_list) do |e|
        !Builtins.contains(_NEGATED_OPTIONS, e)
      end
      option_list = Builtins.filter(option_list) do |e|
        !Builtins.contains(_SIMPLE_OPTIONS, e)
      end

      error_message = ""
      Builtins.foreach(option_list) do |opt|
        opt_tuple = Builtins.splitstring(opt, "=")
        key = Ops.get(opt_tuple, 0, "")
        value = Ops.get(opt_tuple, 1, "")
        # By now we have filtered out known options without values;
        # so what is left is either unknown options, ...
        # FIXME: this also triggers for "intr=bogus"
        # because we should have considered '=' before the simple options
        # FIXME "'" + foo + "'" used not to break translations; merge it.
        if !Builtins.contains(_OPTIONS_WITH_VALUE, key)
          # To translators: error popup
          error_message = Builtins.sformat(
            _("Unknown option: %1"),
            Ops.add(Ops.add("'", key), "'")
          )
        # ... or known ones with badly specified values
        elsif Builtins.size(opt_tuple) != 2
          # To translators: error popup
          error_message = Builtins.sformat(
            _("Invalid option: %1"),
            Ops.add(Ops.add("'", opt), "'")
          )
        elsif value == ""
          # To translators: error popup
          error_message = Builtins.sformat(
            _("Empty value for option: %1"),
            Ops.add(Ops.add("'", key), "'")
          )
        end
        raise Break if error_message != ""
      end

      error_message
    end