<commit_before>{ config, lib, pkgs, ... }:

with lib;

let

  smbToString = x: if builtins.typeOf x == "bool"
                   then (if x then "true" else "false")
                   else toString x;

  cfg = config.services.samba;

  samba = cfg.package;

  setupScript =
    ''
      mkdir -p /var/lock/samba /var/log/samba /var/cache/samba /var/lib/samba/private
    '';

  shareConfig = name:
    let share = getAttr name cfg.shares; in
    "[${name}]\n " + (smbToString (
       map
         (key: "${key} = ${smbToString (getAttr key share)}\n")
         (attrNames share)
    ));

  configFile = pkgs.writeText "smb.conf"
    (if cfg.configText != null then cfg.configText else
    ''
      [ global ]
      security = ${cfg.securityType}
      passwd program = /var/setuid-wrappers/passwd %u
      pam password change = ${smbToString cfg.syncPasswordsByPam}
      invalid users = ${smbToString cfg.invalidUsers}

      ${cfg.extraConfig}

      ${smbToString (map shareConfig (attrNames cfg.shares))}
    '');

  # This may include nss_ldap, needed for samba if it has to use ldap.
  nssModulesPath = config.system.nssModules.path;

  daemonService = appName: args:
    { description = "Samba Service Daemon ${appName}";

      requiredBy = [ "samba.target" ];
      partOf = [ "samba.target" ];

      environment = {
        LD_LIBRARY_PATH = nssModulesPath;
        LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
      };

      serviceConfig = {
        ExecStart = "${samba}/sbin/${appName} ${args}";
        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
      };

      restartTriggers = [ configFile ];
    };

in

{

  ###### interface

  options = {

    # !!! clean up the descriptions.

    services.samba = {

      enable = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Whether to enable Samba, which provides file and print
          services to Windows clients through the SMB/CIFS protocol.
        '';
      };

      package = mkOption {
        type = types.package;
        default = pkgs.samba;
        defaultText = "pkgs.samba";
        example = literalExample "pkgs.samba4";
        description = ''
          Defines which package should be used for the samba server.
        '';
      };

      syncPasswordsByPam = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Enabling this will add a line directly after pam_unix.so.
          Whenever a password is changed the samba password will be updated as well.
          However, you still have to add the samba password once, using smbpasswd -a user.
          If you don't want to maintain an extra password database, you still can send plain text
          passwords which is not secure.
        '';
      };

      invalidUsers = mkOption {
        type = types.listOf types.str;
        default = [ "root" ];
        description = ''
          List of users who are denied to login via Samba.
        '';
      };

      extraConfig = mkOption {
        type = types.lines;
        default = "";
        description = ''
          Additional global section and extra section lines go in here.
        '';
      };

      configText = mkOption {
        type = types.nullOr types.lines;
        default = null;
        description = ''
          Verbatim contents of smb.conf. If null (default), use the
          autogenerated file from NixOS instead.
        '';
      };

      securityType = mkOption {
        type = types.str;
        default = "user";
        example = "share";
        description = "Samba security type";
      };

      nsswins = mkOption {
        default = false;
        type = types.bool;
        description = ''
          Whether to enable the WINS NSS (Name Service Switch) plug-in.
          Enabling it allows applications to resolve WINS/NetBIOS names (a.k.a.
          Windows machine names) by transparently querying the winbindd daemon.
        '';
      };

      shares = mkOption {
        default = {};
        description = ''
          A set describing shared resources.
          See <command>man smb.conf</command> for options.
        '';
        type = types.attrsOf (types.attrsOf types.unspecified);
        example =
          { srv =
             { path = "/srv";
               "read only" = true;
                comment = "Public samba share.";
             };<commit_msg>samba module: add more description<commit_after>{ config, lib, pkgs, ... }:

with lib;

let

  smbToString = x: if builtins.typeOf x == "bool"
                   then (if x then "true" else "false")
                   else toString x;

  cfg = config.services.samba;

  samba = cfg.package;

  setupScript =
    ''
      mkdir -p /var/lock/samba /var/log/samba /var/cache/samba /var/lib/samba/private
    '';

  shareConfig = name:
    let share = getAttr name cfg.shares; in
    "[${name}]\n " + (smbToString (
       map
         (key: "${key} = ${smbToString (getAttr key share)}\n")
         (attrNames share)
    ));

  configFile = pkgs.writeText "smb.conf"
    (if cfg.configText != null then cfg.configText else
    ''
      [ global ]
      security = ${cfg.securityType}
      passwd program = /var/setuid-wrappers/passwd %u
      pam password change = ${smbToString cfg.syncPasswordsByPam}
      invalid users = ${smbToString cfg.invalidUsers}

      ${cfg.extraConfig}

      ${smbToString (map shareConfig (attrNames cfg.shares))}
    '');

  # This may include nss_ldap, needed for samba if it has to use ldap.
  nssModulesPath = config.system.nssModules.path;

  daemonService = appName: args:
    { description = "Samba Service Daemon ${appName}";

      requiredBy = [ "samba.target" ];
      partOf = [ "samba.target" ];

      environment = {
        LD_LIBRARY_PATH = nssModulesPath;
        LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
      };

      serviceConfig = {
        ExecStart = "${samba}/sbin/${appName} ${args}";
        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
      };

      restartTriggers = [ configFile ];
    };

in

{

  ###### interface

  options = {

    # !!! clean up the descriptions.

    services.samba = {

      enable = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Whether to enable Samba, which provides file and print
          services to Windows clients through the SMB/CIFS protocol.

          <note>
            <para>If you use the firewall consider adding the following:</para>
            <programlisting>
              networking.firewall.allowedTCPPorts = [ 139 445 ];
              networking.firewall.allowedUDPPorts = [ 137 138 ];
            </programlisting>
          </note>
        '';
      };

      package = mkOption {
        type = types.package;
        default = pkgs.samba;
        defaultText = "pkgs.samba";
        example = literalExample "pkgs.samba3";
        description = ''
          Defines which package should be used for the samba server.
        '';
      };

      syncPasswordsByPam = mkOption {
        type = types.bool;
        default = false;
        description = ''
          Enabling this will add a line directly after pam_unix.so.
          Whenever a password is changed the samba password will be updated as well.
          However, you still have to add the samba password once, using smbpasswd -a user.
          If you don't want to maintain an extra password database, you still can send plain text
          passwords which is not secure.
        '';
      };

      invalidUsers = mkOption {
        type = types.listOf types.str;
        default = [ "root" ];
        description = ''
          List of users who are denied to login via Samba.
        '';
      };

      extraConfig = mkOption {
        type = types.lines;
        default = "";
        description = ''
          Additional global section and extra section lines go in here.
        '';
        example = ''
          guest account = nobody
          map to guest = bad user
        '';
      };

      configText = mkOption {
        type = types.nullOr types.lines;
        default = null;
        description = ''
          Verbatim contents of smb.conf. If null (default), use the
          autogenerated file from NixOS instead.
        '';
      };

      securityType = mkOption {
        type = types.str;
        default = "user";
        example = "share";
        description = "Samba security type";
      };

      nsswins = mkOption {
        default = false;
        type = types.bool;
        description = ''
          Whether to enable the WINS NSS (Name Service Switch) plug-in.
          Enabling it allows applications to resolve WINS/NetBIOS names (a.k.a.
          Windows machine names) by transparently querying the winbindd daemon.
        '';
      };

      shares = mkOption {
        default = {};
        description = ''
          A set describing shared resources.
          See <command>man smb.conf</command> for options.
        '';
        type = types.attrsOf (types.attrsOf types.unspecified);
        example =
          { public =
             { path = "/srv/public";
               "read only" = true;
               browseable = "yes";
               "guest ok" = "yes";
                comment = "Public samba share.";
             };
{'fraction_non_alphanumeric': 0.10480442176870748, 'fraction_numerical': 0.001488095238095238, 'mean_word_length': 1.8306257521058966, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2975614', 'n_tokens_mistral': 2712, 'n_tokens_neox': 2646, 'n_words': 789}