Blog hébergé par Yves et Iris :-)

Aller au contenu | Aller au menu | Aller à la recherche

Lightweight Windows Network Neighbourhood for TinyCore Linux

TinyCore is a Linux distribution, the aim of which is to be tiny. Although one can still install the whole KDE or Gnome desktop on TinyCore (it is still Linux after all), I prefer to keep it small. Thus, the “network neighbourhood” client proposed here is a rather lightweight Samba client, yet still with most needed features.

My tool is essentially a shell script, based on very few dependences: samba3 (for smbtree and smbclient), zenity, cifs-utils (for mount.cifs); that’s all. I could have written a proper TinyCore Extension (TCE) but I lacked the incentive. So I went the easy route. I only create two files and it’s ready :-)

Easy part first: find any PNG icon that means “network neighbourhood” to you, and save it as /etc/sysconfig/tcedir/ondemand/neighbourhood.img (mind the extension: it’s img even though it’s a PNG image).

Next, ensure your installation of TinyCore contains the three forementioned dependences.

Finally, create the /etc/sysconfig/tcedir/ondemand/neighbourhood script, with the following content:

# NEEDED: samba3 (smbtree, smbclient), zenity, cifs-utils (mount.cifs).


if [ ! -e /usr/local/tce.installed/samba3 ]; then
tce-load -il /etc/sysconfig/tcedir/optional/samba3.tcz
if [ ! -e /usr/local/tce.installed/zenity ]; then
tce-load -il /etc/sysconfig/tcedir/optional/zenity.tcz
if [ ! -e /usr/local/tce.installed/cifs-utils ]; then
tce-load -il /etc/sysconfig/tcedir/optional/cifs-utils.tcz

[ -d "$PFX" ] || mkdir -p "$PFX"
[ -d "$PFX" ] || { echo "Cannot create $PFX" >&2; exit 1; }

toLower() {
tr '[A-Z]' '[a-z]'

# $1: server's "workgroup", "workgroup/server", or "workgroup/server/share"
# &1: client's "workgroup", or empty
getConfWorkgroup() {
local s="$(echo "/$1" | toLower)"
local g
while [ -n "$s" ] && [ -z "$g" ]; do
g="$(sed -n "s#^wkg:${s:1}=##p" "$CONF")"
[ -z "$g" ] && g="$(sed -n "s#^wkg:FORCED_WORKGROUP=##p" "$CONF")"
echo "$g"

# $1: server's "workgroup", "workgroup/server", or "workgroup/server/share"
# &1: client's "login%pass", or empty
getConfLogin() {
local s="$(echo "/$1" | toLower)"
local l
while [ -n "$s" ] && [ -z "$l" ]; do
l="$(sed -n "s#^pwd:${s:1}=##p" "$CONF")"
[ -z "$l" ] && l="$(sed -n "s#^pwd:DEFAULT_LOGIN=##p" "$CONF")"
echo "$l"

# $1: server's "workgroup", "workgroup/server", or "workgroup/server/share"
# &1: server's encoding for filenames (see `locale -a` for known encodings), or empty
getConfEncoding() {
local s="$(echo "/$1" | toLower)"
local e
while [ -n "$s" ] && [ -z "$e" ]; do
e="$(sed -n "s#^pwd:${s:1}=##p" "$CONF")"
[ -z "$e" ] && e="$(sed -n "s#^pwd:DEFAULT_LOCALE=##p" "$CONF")"
echo "$e"

# &1: list of workgroup/server appearing in the configuration
getConfServers() {
grep -o '^[^#]..:[^=]*' "$CONF" | tr ':' '/' | awk -F/ -vOFS=/ 'NF>2{print $2,$3}'

THIS="$(cd "$(dirname "$0")"; pwd)/$(basename "$0")"

if echo "$THIS" | grep -F "$PFX" &>/dev/null; then
# This is a symlink for a share
dir="$(dirname "$THIS")"
server="$(basename "$dir")"
group="$(basename "$(dirname "$dir")")"
mygrp="$(getConfWorkgroup "$group/$server")"
[ -z "$mygrp" ] && mygrp="$group"
login="$(getConfLogin "$group/$server")"

if [ -n "$login" ]; then
smbclient -g -W "$mygrp" -L "$server" -U "$login"
smbclient -g -W "$mygrp" -L "$server" -N
fi \
| sed -n 's/^Disk|\(.*\)|.*/\1/p' | sed p \
| zenity --list --title="${group}:\\\\${server}\\ ? \\" \
--radiolist --column='?' --column="${group}:\\\\${server}\\")

if [ -n "$share" ]; then
[ -d "$dir/$share" ] || mkdir "$dir/$share"
[ -d "$dir/$share" ] || { echo "Cannot create $share" >&2; exit 2; }
if ! grep -F " $dir/$share " /etc/mtab &>/dev/null; then
mygrp="$(getConfWorkgroup "$group/$server/$share")"
[ -z "$mygrp" ] && mygrp="$group"
login="$(getConfLogin "$group/$server/$share")"
if [ -n "$login" ]; then
enc="$(getConfEncoding "$group/$server/$share")"
[ -n "$enc" ] && export LANG="$enc"
sudo mount.cifs "//${server}/$share" "${dir}/$share" \
-o "$login"dom="$mygrp",noperm,nounix,rw,uid=$(id -u),iocharset=utf8
# This is the initial setup
cd "$PFX"
for d in */*/*; do
if [ -d "$d" ] \
&& [ $(/bin/ls -1 "$d" | wc -l) -eq 0 ] \
&& ! grep -F " $PFX/$d " /etc/mtab &>/dev/null; then
rm -rf "$d"
for d in */*; do
if [ $(/bin/ls -1 "$d" | wc -l) -eq 1 ] \
&& ! grep -F " $PFX/$d/" /etc/mtab &>/dev/null; then
rm -rf "$d"
for d in *; do
if [ $(/bin/ls -1 "$d" | wc -l) -eq 0 ]; then
rm -rf "$d"

smbtree -b -N | awk '{print $1}' | (
cd .
while read l; do case "$l" in
if [ ! -e "${l##*\\\\}" ]; then
mkdir "${l##*\\\\}"
ln -s "$THIS" "${l##*\\\\}/"
cd -
[ -d "$l" ] || mkdir "$l"
cd "$l"
if [ ! -e '_template_' ]; then
mkdir '_template_'
ln -s "$THIS" '_template_/'
esac; done
getConfServers | tr / '\n' | while read d; read b; do
for d2 in *; do
if [ "$d" == "$(echo "$d2" | toLower)" ]; then d="$d2"; break; fi
[ -d "$d" ] || mkdir "$d"
cd "$d" || continue
for d2 in *; do
if [ "$b" == "$(echo "$d2" | toLower)" ]; then b="$d2"; break; fi
[ -d "$b" ] || mkdir "$b"
[ -d "$b" ] || continue
ln -s "$THIS" "$b/"
cd ..

The first lines of the script define two parameters you might wish to change:

  • The CONF parameter defines the full path to the configuration file (more on that later).
  • The PFX parameter defines the full path of the directory where network shares will appear. I have the habit of creating my network “drives” (for when I work with Linux in a Windows kind of team) in a W folder inside my home directory (~/W/F/, ~/W/G/, and so on), hence my default choice of ~/W/Network for the neighbourhood.

Make sure the script file is executable. On next reboot, you should see your icon in TinyCore’s “on-demand” menu, as well as in the wbar (the application launcher at the bottom of the screen).

Before I explain the configuration file, I should tell what the script does:

  1. When it is launched for the first time, the script creates the network neighbourhood folder (see PFX above), and then searches the network for visible shares. A directory tree is then created inside PFX, with a directory for each workgroup, and inside each of these, a directory for each server found in the workgroup.
  2. Inside of each server-folder, a neighbourhood executable is created (actually a symbolic link to the script above). Running this script will open a window listing all of this server’s shares. Choosing a share will create a sub-folder of the server-folder, with the name of the share, and mount the Windows share on this sub-folder.
  3. If the script is launched anew, the whole directory tree inside PFX is deleted, except the still-mounted mount points of course. Then the network discovery is ran again as in step 1.

So, now the configuration file. It is a text file (see CONF above) with four kinds of lines :

  • Lines like “enc:…=…” let you choose the encoding for the file-names. Such a line can come in four forms: “enc:DEFAULT_LOCALE=<a locale>”, or “enc:workgroup=<a locale>”, or “enc:workgroup/server=<a locale>”, or “enc:workgroup/server/share=<a locale>”. The default locale is whatever TinyCore considers to be the default for Samba mount points.
  • Lines like “pwd:…=…” let you choose the login and password to use. Such a line can come in four forms: “pwd:DEFAULT_LOGIN=<login>%<password>”, or “pwd:workgroup=<login>%<password>”, or “pwd:workgroup/server=<login>%<password>”, or “pwd:workgroup/server/share=<login>%<password>”. The default is to attempt an anonymous connection.
  • Lines like “wkg:…=…” let you choose the workgroup to bind to. Such a line can come in four forms: “wkg:FORCED_WORKGROUP=<a workgroup>”, or “wkg:workgroup=<a workgroup>”, or “wkg:workgroup/server=<a workgroup>”, or “wkg:workgroup/server/share=<a workgroup>”. The default is to bind to the same workgroup, that the target server is part of.
  • Any other line is ignored, with the purpose of writing comments.

The order in which the lines are written has no consequence. However, the forms are given above in growing order of priority; for example, a login/password pair given for a share takes precedence over a login/password given for a whole workgroup, which in turn supersedes the DEFAULT_LOGIN. Writing nothing after the “=” sign is equivalent to not writing the line at all.

All workgroups’, servers’, and shares’ names must be written in lower-case in the configuration file. Also note that any server appearing in this file is treated as a kind of “favorite” and always appears in the directory tree created by the script; this comes handy for hidden servers, to which you can access, but do not appear in casual browsing.

Here is an example file:

# Defaults:

# At work:

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

La discussion continue ailleurs

URL de rétrolien :

Fil des commentaires de ce billet