Parse smb.conf based on an NFS mapping directory

So I’m not sure how others run their home networks but in my case I have a single large NFS NAS. This NAS hosts both Samba and NFS shares as well as a web portal.

After many years of trying different configurations to my primary data stores I’ve finally come up with a simple method which is shared across all clients. The way this is done is to export a directory called ‘mapping’, in which it maps back to the mounts and sub directories containing my various Music, Pictures, Software, categories. These are mapped via symbolic links. An example of this would be:

Music -> /nfs/hal/data1/Music

Well this works great, as all of the clients accessing the data (including the web portal) all mount my various arrays (data0 – data4) this way. This also works out well if I have problems and want to shift data around, I can quickly remove the Music link and say point it to /nfs/hal/data4/Music.

Now onto the Samba part, even though samba seemingly has zero problems following symbolic links, you can’t point a share directly to one. I have no idea why and really don’t want to try and get into the mess that is samba debugging. So the quick solution there for me is to generate a smb.conf template file. It’s basically my full blown smb.conf file except all path references are replaced with place holders. I.e.:

[Music]
comment = Music
writable = no
browseable = yes
guest ok = yes
create mask = 0777
path = %Music%

This why I can automate the replacement of paths based on my mapping directory. Below is the simple script I’m using to do this:

#!/usr/bin/perl

use strict;

our $mapping = '/exports/mapping';
our $template = '/etc/samba/smb.conf.template';

my %list;
if(opendir(my $dh, $mapping)){
        for(readdir $dh){
                if($_ eq '.' || $_ eq '..'){
                        next;
                } else {
                        my $path = readlink($mapping . '/' . $_);
                        if($path){
                                $list{ $_ } = $path;
                        }
                }
        }

        closedir($dh);
} else {
        die "Unable to read directory: $mapping $!\n";
}

if(open(my $fh, $template)){
        my $data;
        { local $/; $data = <$fh>; };

        for(keys %list){
                $data =~ s/\%$_\%/$list{$_}/g;
        }

        print $data;
}

exit;