Packetizer

Resetting Directory and File Masks on Synology NAS

December 9, 2012

If you have a Synology NAS and you mount those file systems on Linux, you see something horrible. Synology always sets the directory and file creation masks to 0777, so all files and directories are readable and writable by everybody else on the Linux machine. It works fine on Windows since access to files is controlled by the Samba software.

If you're like me, though, you want a little more control. This Perl script, when run on a Synology NAS server running DSM 4.1, will add the desired config lines to the smb.conf file. Put is over in /usr/local/bin/modify_samba_config (make sure root can execute this program).

NOTE:DSM 5 and DSM 6 changes a few things. See the notes at the bottom.

#!/usr/bin/perl
#
# Modify the smb.conf file on the Synology disk station
#

# Location of the smb.conf and temp files
$smb_file = "/usr/syno/etc/smb.conf";
$tmp_file = "/tmp/mod_smb_cfg.$$";

# Below are the names of the shares and to the right
# are the config lines to introduce
%share_config =
(
    'archive'            => [
                                  "directory mask = 0755",
                                  "create mask = 0644"
                            ],
    'music'              => [
                                  "directory mask = 0755",
                                  "create mask = 0644"
                            ],
    'pictures'           => [
                                  "directory mask = 0755",
                                  "create mask = 0644"
                            ],
    'public'             => [
                                  "directory mask = 0775",
                                  "create mask = 0664"
                            ]
);

#
# SameOption
#
# This function will check to see if the option names are the same
#
sub SameOption
{
    my (@options) = @_;

    my ($i);

    if ($#options != 1)
    {
        return 0;
    }

    # Normalize values
    for ($i=0; $i<=1; $i++)
    {
        $options[$i] =~ s/=.*//;          # Remove everything after =
        $options[$i] =~ s/^\s+//;         # Remove all leading whitespace
        $options[$i] =~ s/\s$//;          # Remove all trailing whitespace
        1 while $options[$i] =~ s/  / /g; # Remove excess spaces
    }

    if (($options[0] eq $options[1]) && (length($options[0]) > 0))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

#
# MAIN
#
# The following is the main logic of the program
#

# Read the old config, make changes, writing to a temp file
open(SMBFILE, "< $smb_file") || exit;
open(TMPFILE, "> $tmp_file") || exit;

while(<SMBFILE>)
{
    # We will assume the current line will be printed
    $print_line = 1;

    # This logic will remove lines from the existing config that are
    # added via the $share_config array
    if ((!/^\[/) && (length($section_name) > 0))
    {
        $tline = $_;
        chomp($tline);

        foreach $line ( @{ $share_config{"$section_name"} } )
        {
            # Is the current config option in our
            if (SameOption($tline, $line))
            {
                $print_line = 0;
                last;
            }
        }
    }
    if ($print_line)
    {
        print TMPFILE;
    }
    next unless /^\[/;

    # Add configuration lines as specified in "share_config"
    chomp($section_name = $_);
    $section_name =~ s/^\[//;
    $section_name =~ s/\].*//;
    foreach $line ( @{ $share_config{"$section_name"} } )
    {
        print TMPFILE "\t$line\n";
    }
}

close(SMBFILE);
close(TMPFILE);

# Read the temp file in and replace the original config file
open(TMPFILE, "< $tmp_file") || exit;
open(SMBFILE, "> $smb_file") || exit;

while(<TMPFILE>)
{
    print SMBFILE;
}

close(TMPFILE);
close(SMBFILE);

# Get rid of the temp file
unlink($tmp_file);

You can modify the config lines, adding or removing whatever you wish. The "keys" in that hash (e.g., "archive" and "private") are the names of the Samba shares created on your Synology box. You'll need to assign those appropriately. You can have different additions per "share" to customize whatever you wish. (Note that if Synology already has a config line like what you introduce, your config line might be ignored. I've not tested what happens if there are two conflicting config lines.)

Now, you want this script to run before Samba starts. I tried adding it to rc.local, but the synology box loads services like Samba in the background, so there is a risk of a race condition and things not working right.

What I decided to do was create a "service" that the Synology box calls before it starts Samba, but after it has re-built the config (which it does every time the machine boots). I created a script in /usr/syno/etc/rc.d/S80alt_samba_config.sh. The Samba service is S80samba.sh, so this script will get called first (alphabetical sorting).

#!/bin/sh

if [ $# -eq 0 ]; then
        action=status
else
        action=$1
fi

# dispatch actions
case $action in
        start)
                /usr/local/bin/modify_samba_config
                ;;
        *)
                # Do nothing with any other command
                ;;
esac

That's it! Now, if you reboot the NAS server, you should get the permissions in Samba as you wanted.

DISCLAIMER: This is not a technique you should try if you're not familiar with Linux system administration. I cannot help you if you break your NAS server. Carefully review the code and test it before using it.

UPDATE: It appears that each time you install an update of the DSM software, the /usr/syno/etc/rc.d directory gets replaced. So, you'll have to put the "80alt_samba_config.sh" script back on place each time. The /usr/local/bin/ directory appears to remain untouched.

UPDATE: With DSM 5, I think it was, the name of the rc.d script had to change to S02smbfix.sh in order to run at the proper time.

UPDATE: With DSM 6, Synology moved things around. The smb.conf file is now in /etc/samba/. So, the line that says '$smb_file = "/usr/syno/etc/smb.conf";' needs to change to '$smb_file = "/etc/samba/smb.conf";'. Also, the rc.d directory changed. It appears that placing the script "S02smbfix.sh" into /usr/local/etc/rc.d will work.

Click here to view the main blog page.

Paul E. Jones

About Me
My Blog ATOM Feed
Email Me
IM Me

Certified ScrumMaster®