Fixed 'lufsd' wrapping detection.
[lufs.git] / kernel / Linux / prepmod.in
index a458f2e..86a836b 100755 (executable)
@@ -27,13 +27,10 @@ use Getopt::Long;
 
 my $basedir='@datadir@/lufs';
 my $vardir='@localstatedir@/lib/lufs';
-my $includedir='@includedir@'; # '/lufs' is required by C '#include'
 $basedir=~s#\$\Q{prefix}\E#'@prefix@';#ge;
 $vardir=~s#\$\Q{prefix}\E#'@prefix@';#ge;
 $vardir="" if $vardir=~/^@/;
-$includedir=~s#\$\Q{prefix}\E#'@prefix@';#ge;
-$includedir="" if $includedir=~/^@/;
-sub srcdir { my($uname_r)=@_; $basedir."/".($uname_r lt "2.5" ? "2.4" : "2.5"); }
+sub srcdir { my($uname_r)=@_; $basedir."/".($uname_r lt "2.5" ? "2.4" : "2.6"); }
 my $modbindir=$basedir."/modbin";
 my @sources=qw(proc.c inode.c dir.c file.c symlink.c);
 
@@ -42,14 +39,21 @@ my $kernel;
 my $prebuild;
 use vars qw($kernel_gcc_args);
 $kernel_gcc_args="";
-$kernel_gcc_args="-I$includedir" if $includedir;
 
-my $lufsmnt_bin;
-if ($0 eq "lufsmnt" || $0=~m#/lufsmnt$#) {
+sub modext { my($uname_r)=@_; ($uname_r lt "2.5" ? "o" : "ko"); }
+
+# mount(8) will util-linux/lib/env.c/sanitize_env()
+# including the clearance our $PATH:
+$ENV{"PATH"}=join(":",qw(/usr/local/bin /usr/bin /bin),($ENV{"PATH"} || ()));
+
+my $lufsd_base='lufsd';
+do { eval '$lufsd_base=~'.$_.';' if !/^@/; } for ('@program_transform_name@');
+my $lufsd_bin;
+if ($0 eq $lufsd_base || $0=~m#/\Q$lufsd_base\E$#) {
        $quiet=1;
-       $lufsmnt_bin='@bindir@/lufsmnt-bin';
-       $lufsmnt_bin=~s#\$\Q{exec_prefix}\E#'@exec_prefix@';#ge;
-       $lufsmnt_bin=~s#\$\Q{prefix}\E#'@prefix@';#ge;
+       $lufsd_bin='@bindir@/'.$lufsd_base.'-bin';
+       $lufsd_bin=~s#\$\Q{exec_prefix}\E#'@exec_prefix@';#ge;
+       $lufsd_bin=~s#\$\Q{prefix}\E#'@prefix@';#ge;
        }
 else {
        die if !GetOptions(
@@ -102,9 +106,9 @@ my($load)=@_;
                do { ($modproberc=_system $_) and cluck "$_ failed - ignoring"; }
                                for ("/sbin/depmod -aq","/sbin/modprobe lufs");
                }
-       exit ($modproberc ? 1 : 0) if !$lufsmnt_bin;
-       do { exec $lufsmnt_bin,@ARGV; };
-       confess "Failed to exec '$lufsmnt_bin': $!";
+       exit ($modproberc ? 1 : 0) if !$lufsd_bin;
+       do { exec $lufsd_bin,@ARGV; };
+       confess "Failed to exec '$lufsd_bin': $!";
 }
 
 
@@ -114,6 +118,8 @@ my $modules=_readfile "/proc/modules";      # 'lufs' may be already loaded
 _pass if $modules=~/^lufs\b/m;
 _pass if !_system "/sbin/modprobe lufs 2>/dev/null";
 
+print STDERR "Preparing LUFS kernel module - this may take several minutes...\n";      # if !$quiet;
+
 my $proc_version=_readfile "/proc/version";
 my $uname_r=($proc_version=~/^Linux version (\S+)/)[0] || _readfile "uname -r|";
 chomp $uname_r;
@@ -122,6 +128,8 @@ my $uname_smp=($uname_r=~s/smp$// && "smp");
 my $uname_r_base=($uname_r=~/^([^-]+)/)[0];
 print STDERR "Running kernel version: $uname_r (base version $uname_r_base)\n" if !$quiet;
 
+my $lufs_o="lufs.".modext($uname_r);
+
 my $moduledir="/lib/modules/$uname_r$uname_smp/kernel/fs/lufs";
 print STDERR "Destination module directory: $moduledir\n" if !$quiet;
 
@@ -131,6 +139,7 @@ my @kernel_paths=(
                                "/usr/src/linux-$uname_r",
                                "/usr/src/linux-$uname_r_base",
                                "/usr/src/linux",
+                               "/usr/src/kernel-source-$uname_r",      # no .config?
                                );
 do { $kernel||=$_ if -d $_; } for (@kernel_paths);
 if (!$kernel) {
@@ -139,28 +148,31 @@ if (!$kernel) {
 else {
        # We need /usr/include/lufs/* for standard package compilation.
        # There is no sense to make separate 'devel' package.
-       for ("$vardir/lufs.o") {
+       for ("$vardir/$lufs_o") {
                next if !$vardir;
                # Create the 'lufs.o' in our /var/lib directory and only link it
                # to prevent using obsolete modules after upgrading 'lufs' package.
                # depmod(1) will take the larget symlink name - we must create directory for  it.
                if (build($kernel,$uname_r,$_)) {
                        do { cluck "Failed to symlink $_"; next; }
-                                       if _system "/bin/rm -rf $moduledir; /bin/mkdir -p $moduledir; /bin/ln -s $_ $moduledir/lufs.o";
+                                       if _system "/bin/rm -rf $moduledir; /bin/mkdir -p $moduledir; /bin/ln -s $_ $moduledir/$lufs_o";
                        _pass 1;
                        }
                }
        }
 
 local $_;
-for (<$modbindir/*-$uname_r*/*.o>,<$modbindir/*-${uname_r_base}*/*.o>,<$modbindir/*/*.o>) {
-       next if _system "/sbin/rmmod lufs 2>/dev/null; /sbin/insmod -o lufs -p $_ 2>/dev/null";
+for (<$modbindir/*-$uname_r*/$lufs_o>,<$modbindir/*-${uname_r_base}*/$lufs_o>,<$modbindir/*/$lufs_o>) {
+       # Do not: /sbin/insmod -o lufs -p $_ 2>/dev/null
+       # as 2.6 insmod has no options at all.
+       next if _system "/sbin/rmmod lufs 2>/dev/null; /sbin/insmod $_ 2>/dev/null";
        do { cluck "Failed to symlink $_"; next; }
-                       if _system "/bin/rm -rf $moduledir; /bin/mkdir -p $moduledir; /bin/ln -s $_ $moduledir/lufs.o";
-       _pass 1;
+                       if _system "/bin/rm -rf $moduledir; /bin/mkdir -p $moduledir; /bin/ln -s $_ $moduledir/$lufs_o";
+       # 0 as already insmod(8)ed.
+       _pass 0;
        }
 confess "lufs module not loaded: Try running $basedir/prepmod to see more." if $quiet;
-confess "Failed to prepare lufs.o module for your Linux kernel $uname_r.\n"
+confess "Failed to prepare $lufs_o module for your Linux kernel $uname_r.\n"
                .($kernel ? "Detected Linux kernel sources \"$kernel\" do not appear to be valid.\n"
                                : "No Linux kernel sources for your running kernel were found.\n")
                ."Please install kernel-source-x.y.z.i386.rpm or kernel-headers_x.y.z_i386.deb.\n"
@@ -186,15 +198,19 @@ my($kernel,$uname_r,$destmodule)=@_;
                        ." ".$kdebug
                        ." ".$kernel_gcc_args
                        ." -I$kernel/include"
-                       ." -I$kernel/include/asm-i386/mach-default";    # gcc should not care if this 2.5 dir does not exist
+                       ." -I$kernel/include/asm-i386/mach-default";    # gcc should not care if this 2.6 dir does not exist
 
        my $config=_readfile "$kernel/.config","optional";
        my $autoconf=_readfile "$kernel/include/linux/autoconf.h","optional";
-       $cmdline.=" -DMODVERSIONS -include $kernel/include/linux/modversions.h"
-                       if 0
-                                       || $config=~/^CONFIG_MODVERSIONS=y\b/m
-                                       || $autoconf=~/^#define CONFIG_MODVERSIONS\b/m
-                                       || (!$config && !$autoconf);    # assume modversions if not known
+       if (0
+                       || $config=~/^CONFIG_MODVERSIONS=y\b/m
+                       || $autoconf=~/^#define CONFIG_MODVERSIONS\b/m
+                       || (!$config && !$autoconf)) {  # assume modversions if not known
+               $cmdline.=" -DMODVERSIONS";
+               $cmdline.=" -include $kernel/include/linux/version.h"
+                               if -f "$kernel/include/linux/version.h";
+               $cmdline.=" -include $kernel/include/linux/modversions.h";
+               }
 
        my @objects=map({ my $o=$_; $o=~s/[.]c$/.o/; $o; } @sources);
        return !_system "set -e; /bin/mkdir -p `dirname $destmodule`; /bin/rm -f $destmodule;"
@@ -207,33 +223,49 @@ my($kernel,$uname_r,$destmodule)=@_;
 
 sub build_make
 {
-my($kernel,$uname_r,$destmodule)=@_;
+my($kernel,$uname_r,$destmodule,%args)=@_;
 
        print STDERR "Using kernel sources: $kernel\n" if !$quiet;
-       confess "Kernel sources $kernel do not contain 'Rules.make' file" if ! -f $kernel."/Rules.make";
+       # 'Rules.make' not present in 2.6+ kernels
+       do { confess "Kernel sources $kernel do not contain '$_' file" if ! -f $_; } for ($kernel."/arch/i386/Makefile");
 
        my $kdebug="";
        do { $kdebug=$_ if !/^@/; } for ('@KDEBUG_FLAGS@');
        my $predir=srcdir $uname_r;
        $predir=$ENV{"PWD"}."/$predir" if $predir!~m#^/#;
+       # Workaround a bug in at least Red Hat 2.4.18-18.8.0
+       if (-f "$kernel/include/linux/version.h") {
+               for ("$kernel/include/linux/modversions.h") {
+                       _system "cp -p $_ $_-orig" if ! -f "$_-orig";
+                       _writefile $_,"#include <linux/version.h>\t/* lufs */\n"._readfile $_;
+                       }
+               }
        my $cmdline="make -C $kernel"
                        ." SUBDIRS=\"$predir\" modules"
                        ." EXTRA_CFLAGS=\"$kernel_gcc_args\""
                        .($quiet ? ' &>/dev/null' : '');
-       my @objects=map({ my $o=$_; $o=~s/[.]c$/.o/; $o; } @sources);
-       return !_system "set -e; /bin/mkdir -p `dirname $destmodule`; /bin/rm -f $destmodule;"
+       my @objects=map({ my $o=$_; $o=~s/[.]c$/.o/; $o; } @sources,"lufs.mod.c","lufs.c");
+       $cmdline="set -e; /bin/mkdir -p `dirname $destmodule`; /bin/rm -f $destmodule;"
                        ." $cmdline;"
-                       ." /bin/rm -f ".join(" ",map(("$predir/$_","$predir/.$_.flags"),@objects)).";"
-                       ." /bin/mv -f $predir/lufs.o $destmodule;";
+                       ." /bin/mv -f $predir/lufs.".modext($uname_r)." $destmodule;"
+                       ." /bin/rm -f ".join(" ",map(("$predir/$_","$predir/.$_.flags","$predir/.$_.cmd"),@objects),"$predir/lufs.mod.c","$predir/.lufs.ko.cmd").";";
+       my $r=!_system $cmdline;
+       return $r if $r;
+       # Rebuild existing '$kernel/tmp_include_depends' or '$kernel/.depend'
+       # as it may contain non-existing pathnames:
+       _system "make -C $kernel dep"
+                               .($quiet ? ' &>/dev/null' : '');
+       return !_system $cmdline;
 }
 
 
 sub build
 {
-my($kernel,$uname_r,$destmodule)=@_;
+my($kernel,$uname_r,$destmodule,%args)=@_;
 
        # Debian uname(1) does not support '-p'.
-       my $arch=_readfile "uname -p|" || _readfile "uname -m|";
+       my $arch=_readfile "uname -p 2>/dev/null || true|"
+                       || _readfile "uname -m|";
        chomp $arch;
        my $single_config=-f "$kernel/.config";
        if (!$single_config) {
@@ -242,10 +274,11 @@ my($kernel,$uname_r,$destmodule)=@_;
                                if -f $spec_config;
                }
        my $r;
-       if (-f "$kernel/Rules.make" && -f "$kernel/.config")
-               { $r=build_make $kernel,$uname_r,$destmodule; }
+       # 'Rules.make' not present in 2.6+ kernels
+       if (-f $kernel."/arch/i386/Makefile" && -f "$kernel/.config")
+               { $r=build_make $kernel,$uname_r,$destmodule,%args; }
        else
-               { $r=build_gcc $kernel,$uname_r,$destmodule; }
+               { $r=build_gcc $kernel,$uname_r,$destmodule,%args; }
        _system "rm -f $kernel/.config"
                        if !$single_config;
        return $r;
@@ -254,11 +287,11 @@ my($kernel,$uname_r,$destmodule)=@_;
 
 sub prebuild_kernel
 {
-my($dir,$vendor,$uname_r)=@_;
+my($dir,$vendor,$uname_r,%args)=@_;
 
        confess "Unrecognized vendor for dir: $dir" if !$vendor;
        confess "Unrecognized uname_r for dir: $dir" if !$uname_r;
-       confess "Failed to build $dir" if !build $dir,$uname_r,$modbindir."/lufs-$vendor-$uname_r.o";
+       confess "Failed to build $dir" if !build $dir,$uname_r,$modbindir."/lufs-$vendor-$uname_r.".modext($uname_r),%args;
 }
 
 
@@ -283,9 +316,6 @@ my($rpm)=@_;
        $dir or confess "Kernel source tree not found in: $rpm";
        _system "cp -p $dir/include/linux/rhconfig.h $dir/include/linux/rhconfig.h-orig"
                                if -f "$dir/include/linux/rhconfig.h";
-       # Do not use existing '$dir/tmp_include_depends' or '$dir/.depend'
-       # as it may contain non-existing pathnames:
-       _system "make -C $dir dep";
        for my $smp ("","smp") {
                my @archs=qw(i386 i586 i686 athlon);
                for my $arch (@archs) {