From 5948769d62fc83dd6640fdc97429286dbae617b7 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 16 Jul 2006 15:00:39 +0200 Subject: [MEDIUM] - pkg-0.7.1 : * newpkg: don't look for newname in .. anymore, and select only the packages containing a build.cfg * newpkg: do not propose a list of multiple identical new names * release: also identify non-shell text scripts. * release: put only package's basename in changelogs. --- .flxpkg/ChangeLog | 62 ++ .flxpkg/build.cfg | 64 ++ ChangeLog | 54 ++ findcdrom/findcdrom.c | 127 +-- include/rules.make | 10 +- init/init-cleanup.c | 1808 +++++++++++++++++++++++++++++++++++++++ scripts/flxextract | 11 +- scripts/flxfix | 84 +- scripts/pkg | 1010 +++++++++++----------- scripts/pkg-0.5.3 | 1994 +++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.5.4 | 2035 ++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.5.5 | 2135 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.5.6 | 2183 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.5.7 | 2193 ++++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.5.8 | 2195 ++++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.6.0 | 2239 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.6.1 | 2239 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/pkg-0.7.0 | 1928 ++++++++++++++++++++++++++++++++++++++++++ 18 files changed, 21760 insertions(+), 611 deletions(-) create mode 100644 .flxpkg/ChangeLog create mode 100644 .flxpkg/build.cfg create mode 100644 init/init-cleanup.c create mode 100755 scripts/pkg-0.5.3 create mode 100755 scripts/pkg-0.5.4 create mode 100755 scripts/pkg-0.5.5 create mode 100755 scripts/pkg-0.5.6 create mode 100755 scripts/pkg-0.5.7 create mode 100755 scripts/pkg-0.5.8 create mode 100755 scripts/pkg-0.6.0 create mode 100755 scripts/pkg-0.6.1 create mode 100755 scripts/pkg-0.7.0 diff --git a/.flxpkg/ChangeLog b/.flxpkg/ChangeLog new file mode 100644 index 0000000..eeee872 --- /dev/null +++ b/.flxpkg/ChangeLog @@ -0,0 +1,62 @@ +2005/04/10 22:56 willy@pcw + + * released flxutils-0.1.29-flx0.1 + +2005/04/09 15:06 willy@pcw + + * pkg 0.5.2 fixes a small bug and provides support for RANLIB + * finally located the old signfs sources, so the binary could + be replaced. Nobody should ever need it anyway, but it's + more for cleanness. + * flx: added the '--ignore-dir' option to ignore differences + in directories dates. + * flx: during a check, do not compute the md5 sums if the user + asks to ignore it. This makes simple diffs a lot faster. + * flx: bumped version to 0.7.1 + +2005/03/01 00:19 willy@wtap + + * released flxutils-0.1.28-flx0.1 + * pkg 0.5.0 provides some cross-compilation variables + * some makefiles have been modified to support cross-compilation + +2004/12/22 12:06 willy@wtap + + * released flxutils-0.1.27-flx0.1 + * merged benoit's patch to escape unprintable characters in flx. + * bumped flx version to 0.7.0 + +2004/12/14 14:52 willy@wtap + + * released flxutils-0.1.26-flx0.1 + * fixed a bug in fct1.c where two different but valid links would + not be reported as different. + +2004/12/07 19:39 willy@wtap + + * released flxutils-0.1.25-flx0.1 + * removed stupid debugging defines from init which prevented it from + working anymore in 0.1.24 ! + +2004/11/21 14:27 root@pcw + + * released flxutils-0.1.24-flx0.1 + * added the "wk" command (waitkey) to init + * wdd now automatically opens /dev/misc/watchdog as presented by devfs + * flx 0.6.8 builds with gcc-3.3 + +2004/08/06 16:51 willy@wtap + + * released flxutils-0.1.23-flx0.1 + * brought back lcdwrite and lcdtee sources which were lost + * the watchdog daemon (wdd) now has a man page and can check + reachability of arbitrary files. + +2004/02/24 21:31 willy@wtap + + * released flxutils-0.1.22-flx0.1 + * several major 'pkg' changes (update to 0.4.3) + * changed some makefiles to make use of new GCC options + provided by pkg-0.4 + * included and packaged 'wdd' (the watchdog daemon) + diff --git a/.flxpkg/build.cfg b/.flxpkg/build.cfg new file mode 100644 index 0000000..bba9d5a --- /dev/null +++ b/.flxpkg/build.cfg @@ -0,0 +1,64 @@ +SUBDIRS="findcdrom init mktmp remount uname wd mii ifenslave lcd signfs" + +function do_compile { + for dir in $SUBDIRS; do + $FLXPMAKE -C $dir COPTS="$GCC_ARCH_SMALL $GCC_CPU_SMALL $GCC_OPT_SMALL" + done + # we still need a *fast* flx + $FLXPMAKE -C flx COPTS="$GCC_ARCH_COMMON $GCC_CPU_COMMON $GCC_OPT_FAST" +} + +function do_distclean { + for dir in $SUBDIRS; do + $FLXPMAKE -C $dir clean + $FLXPMAKE -C $dir distclean + $FLXPMAKE -C $dir mrproper + done + $FLXPMAKE -C flx clean + ( do_delpack ) +} + +function do_clean { + for dir in $SUBDIRS; do + $FLXPMAKE -C $dir clean + done + + $FLXPMAKE -C flx clean + #$FLXPMAKE -C ifenslave clean + #$FLXPMAKE -C mii clean + ( do_delpack ) +} + +function do_prepack { + #mkdir -p $ROOTDIR/usr/include $ROOTDIR/sbin $ROOTDIR/bin $ROOTDIR/usr/bin $ROOTDIR/usr/man/man8 $ROOTDIR/usr/man/man5 $ROOTDIR/usr/man/man1 + mkdir -p $ROOTDIR/sbin $ROOTDIR/bin $ROOTDIR/usr/bin $ROOTDIR/usr/share/examples/flxutils/init $ROOTDIR/usr/sbin $ROOTDIR/usr/man/man8 + cp findcdrom/findcdrom $ROOTDIR/sbin/ + cp flx/flx signfs/signfs mktmp/mktmp remount/remountr lcd/lcd{tee,write} $ROOTDIR/bin/ + ln -s flx $ROOTDIR/bin/flxcheck + ln -s flx $ROOTDIR/bin/flxsign + ln -s remountr $ROOTDIR/bin/remountw + cp -R ifenslave/ifenslave ifenslave/ifenslave-1.0.1[12] init/init init/mkdev wd/wdd mii/mii-diag scripts/{pci-listall,pcidev,noctrlaltdel,mkinstall.old,mkinstall} $ROOTDIR/sbin/ + cp scripts/{pkg,reset,flxsearch,flxextract,flxrescan} $ROOTDIR/usr/bin/ + cp wd/wdd.8 $ROOTDIR/usr/man/man8/ + cp scripts/{flxadd,flxfix} $ROOTDIR/usr/sbin + cp init/examples/* $ROOTDIR/usr/share/examples/flxutils/init/ + + #chown -R root:root $ROOTDIR + #chmod -R og-w $ROOTDIR + #chown root:adm $ROOTDIR/bin/* $ROOTDIR/sbin/* $ROOTDIR/usr/sbin/* $ROOTDIR/usr/bin/* + #chmod 740 $ROOTDIR/sbin/* $ROOTDIR/usr/sbin/* + #chmod 755 $ROOTDIR/usr/bin/* + #chmod 751 $ROOTDIR/bin/* + set_default_perm $ROOTDIR + chmod 640 $ROOTDIR/usr/share/examples/flxutils/init/* + # flxfix is useful for normal users too. + chmod 755 $ROOTDIR/usr/sbin/flxfix +} + +function do_strip { + # avoids a double strip on flx, which destroys it after sstrip + if ! objdump -h $ROOTDIR/bin/flx | grep -q '\.text'; then return; fi + strip --strip-unneeded -x -R .comment -R .note $ROOTDIR/bin/flx $ROOTDIR/bin/signfs $ROOTDIR/sbin/ifenslave + sstrip $ROOTDIR/bin/flx $ROOTDIR/bin/signfs #$ROOTDIR/sbin/ifenslave || : +} + diff --git a/ChangeLog b/ChangeLog index a45a808..2cdcea5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -103,3 +103,57 @@ - flx: during a check, do not compute the md5 sums if the user asks to ignore it. This makes simple diffs a lot faster. - flx: bumped version to 0.7.1 + +2005/04/17 + - flxfix: now also supports signature files in input ; added options to not + update timestamps or uid. + +2005/05/21 + - pkg 0.5.3: added the NM variable, and changed options for OPT_SMALL + +2005/08/12 + - pkg 0.5.4 : objdump is used to find lib dependencies instead of ldd, because + this last one is not cross-platform compatible, and abusively recurses + through the dependency tree instead of staying at the first level. + - pkg 0.5.4 : added some FLX* variables (notably FLXHOST* and FLXTARG*), and + the '--env' option to make pkg print the useful environment variables + +2005/08/13 + - pkg 0.5.5 : executable dependencies are computed precisely with information + about every version needed for each library + +2005/08/17 + - pkg 0.5.6 : reorganized the architecture detection a bit + +2005/08/21 + - pkg 0.5.7 : added support for CXX and HOSTCXX variables + - pkg 0.5.8 : fixed .flxpkg symlink resolution ; tar now uses numeric owner + +2005/08/27 + - pkg 0.6.0 : now supports local package repositories under .flxpkg as a + directory, and can ignore the local directory name if .flxpkg/Version + exists. + +2005/09/17 + - pkg 0.6.1 : use --one-file-system instead of -l for tar (removes a warning) + +2005/10/04 + - pkg 0.7.0 : * provide install-{ln,file,dir,dirs} so that build scripts can + work at the file level + * added a PKG_VERSION variable and a check_pkg_version function + * fixed a few package naming bugs which showed up when packaged + referenced absolute paths + * make sure that we chown root:root $ROOTDIR in prepack. + +2005/10/16 + - findcdrom : * fixed parsing of /proc/sys/dev/cdrom/info + * code cleanup + - include/rules.make : add some configuration parameters + +2005/12/17 + - pkg-0.7.1 : * newpkg: don't look for newname in .. anymore, and select only + the packages containing a build.cfg + * newpkg: do not propose a list of multiple identical new names + * release: also identify non-shell text scripts. + * release: put only package's basename in changelogs. + diff --git a/findcdrom/findcdrom.c b/findcdrom/findcdrom.c index 3c99b34..d0c985e 100644 --- a/findcdrom/findcdrom.c +++ b/findcdrom/findcdrom.c @@ -13,61 +13,86 @@ // 3 : cdrom found but cannot creat /dev/cdrom // 4 : no cdrom data found +#define BUFF_SIZE 4096 +#define TMP_SIZE 4096 + +#define STR_SECT ".rodata" +#define STRING static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) + +STRING dev_str[] = "/dev"; +STRING cdrom_str[] = "cdrom"; +STRING info_str[] = "/proc/sys/dev/cdrom/info"; +STRING driver_name[] = "\ndrive name:"; +STRING found_str[] = "Found CDROM: "; +STRING nocdrom_str[] = "No CDROM found\n"; +STRING eol_str[] = "\n"; int main() { - int fd,fd2,s,t=0; - char tmp[4096],buff[4096],*p,*f; - static const char nocdrom[]="No CDROM found\n"; + int fd, fd2, s, t=0; + char *p, *f; + char tmp[TMP_SIZE], buff[BUFF_SIZE]; + + // find CDROM detection in /proc/sys/dev/cdrom/info + if ((fd = open(info_str, O_RDONLY)) < 0) { + write(2, nocdrom_str, sizeof(nocdrom_str) - 1); + exit(1); + } + if (chdir(dev_str)) { + PRINTF("Cannot chdir to /dev\n"); + exit(2); + } + // looking for "driver name:" + while ((s = read(fd, tmp + t, TMP_SIZE - t)) > 0) { + t += s; + if (t < TMP_SIZE) + tmp[t] = 0; + else + tmp[TMP_SIZE] = 0; - // find CDROM detection in /proc/sys/dev/cdrom/info - if ((fd=open("/proc/sys/dev/cdrom/info",O_RDONLY)) < 0) { - write(2,nocdrom,sizeof(nocdrom)); - exit(1); - } - if (chdir("/dev")) { - PRINTF("Cannot chdir to /dev\n"); - exit(2); - } - // looking for "driver name:" - while ((s=read(fd,tmp+t,4096-t)) > 0) { - t+=s; - if ((p=(char*)strstr(tmp,"\ndrive name:")) && strchr(p+=13,'\n')) { - // have found it, looking for drive name(s) - while (*p != '\n') { - while (*p == ' ' || *p == '\t') p++; - for (f=p;*f > ' ' ; f++) ; - if (*f == '\n') *f=0; else *f++=0; - // found and now try - PRINTF("Trying [%s]\n",p); - if ((fd2=open(p,O_RDONLY)) >= 0) { - // read a small packet to detect valid iso9660 - if (read(fd2,buff,4096) > 0) { - close(fd2); - close(fd); - // creat the symbolic link to /dev/cdrom - if (symlink(p,"cdrom") == 0) { + if ((p = (char*)strstr(tmp, driver_name)) && strchr(p += 13, '\n')) { + // have found it, looking for drive name(s) + while (*p && *p != '\n') { + while (*p == ' ' || *p == '\t') + p++; + + for (f = p; *f > ' ' ; f++); + + if (*f == '\n') + *f = 0; + else + *f++ = 0; + + // found and now try + PRINTF("Trying [%s]\n", p); + if ((fd2 = open(p, O_RDONLY)) >= 0) { + // read a small packet to detect valid iso9660 + if (read(fd2, buff, BUFF_SIZE) > 0) { + close(fd2); + close(fd); + // creat the symbolic link to /dev/cdrom + if (symlink(p, cdrom_str) == 0) { #ifdef DEBUG - write(2," ",2); + write(2, " ", 2); #endif - write(2,"Found CDROM: ",13); - write(2,p,strlen(p)); - write(2,"\n",1); - exit(0); - } - exit(3); - } - PRINTF(" read failed\n"); - close(fd2); - } else { - PRINTF(" open failed\n"); - } - p=f; - } - break; + write(2, found_str, sizeof(found_str) - 1); + write(2, p, strlen(p)); + write(2, eol_str, 1); + exit(0); + } + exit(3); + } + PRINTF(" read failed\n"); + close(fd2); + } else { + PRINTF(" open failed\n"); + } + p = f; + } + break; + } } - } - if (s >= 0) close(fd); - write(2,nocdrom,sizeof(nocdrom)); - return (4); + if (s >= 0) + close(fd); + write(2, nocdrom_str, sizeof(nocdrom_str) - 1); + return (4); } - diff --git a/include/rules.make b/include/rules.make index b1b5f17..8e4c36d 100644 --- a/include/rules.make +++ b/include/rules.make @@ -1,5 +1,11 @@ +CC ?= gcc +STRIP ?= strip +OBJDUMP ?= objdump +SSTRIP ?= sstrip +DIET ?= diet + CC_ORIG := $(CC) -CC := diet $(CC) +override CC := $(DIET) -Os $(CC) CFLAGS=$(GCC_ARCH_SMALL) $(GCC_CPU_SMALL) $(GCC_OPT_SMALL) #-mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0 -Os -march=i386 -mcpu=i386 @@ -12,7 +18,7 @@ all: $(OBJS) $(STRIP) -x --strip-unneeded -R .comment -R .note $@ $(OBJDUMP) -h $@ | grep -q '\.data[ ]*00000000' && $(STRIP) -R .data $@ || true $(OBJDUMP) -h $@ | grep -q '\.sbss[ ]*00000000' && $(STRIP) -R .sbss $@ || true - -sstrip $@ + -if [ -n "$(SSTRIP)" ]; then $(SSTRIP) $@ ; fi %-debug: %.c $(CC) $(LDFLAGS) $(CFLAGS) -DDEBUG -o $@ $< diff --git a/init/init-cleanup.c b/init/init-cleanup.c new file mode 100644 index 0000000..5cb6400 --- /dev/null +++ b/init/init-cleanup.c @@ -0,0 +1,1808 @@ +/* + WARNING ! THIS CODE IS OPTIMIZED FOR SIZE WITH COMPILED-IN ARGUMENTS. IT IS + SUBJECT TO BUFFER OVERFLOWS SO DON'T USE IT WITH RUNTIME ARGUMENTS !!! +*/ + +/* TODO : + - make the config buffer bigger + - a few security checks (buffer overflows...) + - cleanup the code a bit +*/ + +/* + preinit - new try on 2002/04/20 - Willy Tarreau + + usage : /sbin/preinit [ \< config_file ] [ { init args | "rebuild" } ] + + Note : the "\< config_file" is to be used within configuration files : + #!/sbin/preinit < + .... + Thus, when you pass "init=/.preinit", the kernel executes : + /sbin/preinit < /.preinit + + The '<' character has been chosen for its rareness. + + the "rebuild" argument make the tool only rebuild a complete /dev + tree from the informations contained in the .preinit file, and then + exit. It does this even if the pid is not 1, but doesn't execute nor + mount anything. Only mkdir, links, blocks, chars and fifo devices are + created. Very useful before a lilo : + + # chroot /mnt/disk /.preinit rebuild + # lilo -r /mnt/disk + # umount /mnt/disk/dev + + If /dev/console is found under /dev, it will not be rebuilt. + + **** needs to rework the doc a bit since it's not up-to-date. **** + + This code tries to build a few filesystem squeleton so that init has enough + to work correctly : + - mount -t proc /proc /proc + - mount -t tmpfs /dev /dev + - get information from a file : /.preinit which describes what to mount, + what ramdisks, links and dirs to make : + +ln L source dest + make a symlink from to +md D path [ mode ] + create a directory named with the mode . If mode is left + undefined, 0755 is assumed. +mt M blkdev[(major:minor)] path fstype [ { ro | rw } [ flags ] ] + if is specified, create a block device + with and and mode 0600. + mount under with type , read-only, except if + rw is specified, and args . +in I path + set the next init program to +ex E cmd [ args ]* + execute with args and wait for its completion. +rx R dir cmd [ args ]* + chroot to , execute with args and wait for its completion. +bl B mode uid gid major minor naming_rule + create a set of block devices +ch C mode uid gid major minor naming_rule + create a set of char devices +fi F mode uid gid name + create a fifo +ma U mode + change umask +pr P + pivot root : old root is displaced into new_root/put_old_relative, and + new_root is displaced under /. +mv K + keep directory after a pivot, then unmount it from old_dir. + usefull for /dev, /proc, /var ... +um O + umount after a pivot for example. +lo l + losetup /dev/loopX file. + # anything + comment. + + The devices naming rules consist in strings mixed with numbering rules delimited with + brackets. Each numbering rule has 4 comma-separated fields : + - type of this string portion : 'c' for a single char, 'i' for an int, 'I' for an int + for which 0 is not printed, 'h' for an hex digit + - the range : + - chars: any concatenation of character ranges separated with a dash '-': 'a-fk-npq' + - ints : either an int or a range composed of 2 ints separated with a dash : '1-16' + - hex : same as int, but with hex digits (case insensitive) + - the scale : how much to add to the minor device for each step in the range. + + The commands may be prefixed with a '|' or '&', in which case, they will be + executed only if the previous command failed (|) or succeeded (&). + + Example : + ln hda3 /dev/disk => symlinks /dev/disk to hda3 + md /var/tmp 1777 => creates a directory /var/tmp with mode 1777 + mt /dev/hda1 /boot ext2 => attempts to mount /dev/hda1 read-only under /boot. + |mt /dev/hda1(3:1) /boot ext2 => only if the previous command failed, creates /dev/hda1 with major 3, minor 1 and mounts it under /boot + in /sbin/init-std => the following init will be this /sbin/init-std (31 chars max) + ex /sbin/initramdisk /dev/ram6 1200 => executes /sbin/initramdisk with these args and waits for its completion + bl 0600 0 0 3 1 hd[c,ab,64][i,1-16,1] => makes all hdaX and hdbX with X ranging from 1 to 16 + ch 0600 0 5 2 0 pty[c,p-za-f,16][h,0-f,1] => makes all 256 pty* + #comment => ignore this line + + For executable reduction reasons, the .preinit file is limited to 4 kB. + + The choice of the init program is quite complex, because we want to avoid + stupid loops and buggy behaviours while conservating quite a parametrable + init. Basically, we'll use environment variables that we will destroy once + read, to avoid getting them again if we loop on ourselves (imagine an + 'exec /sbin/init" from a shell cmd line, which will blindly re-exec a shell). + So there are two distinct cases (init and linuxrc) : + + 1) linuxrc + We want to be able to either return or transfer execution to the real init. + + - if we find "init2=xxxx" in the env, we memorize it and move it away from the env. + - if "in xxxx" has been specified on a keyboard input from an "rd" + statement, we unconditionnaly do an execve("xxx", "xxx", ##no args##, ##envp##). + - if the env contained "init2=xxxx", we do an execve("xxxx", "xxxx", ##no args##, ##envp##). + we don't pass the args because it is a rescue init, such as a shell, and + we don't want it to fail on "bash: auto: command not found" or similar. + - if the conf contained "in xxxx", we do an execve("xxxx", "xxxx", argv[], ##envp##) + because we want it to know about the original args. Eg: init=/linuxrc single + - if the conf didn't contain "in xxxx", we unmount all what we can and + return. The kernel will be able to switch over to the next init stage. + + 2) init, or anything else (telinit, ...) + We want to transfer execution to the real init. + + - if we find "INIT=xxxx" in the env, we memorize it and move it away from the env. + - if "in xxxx" has been specified on a keyboard input from an "rd" + statement, we unconditionnaly do an execve("xxx", "xxx", ##no args##, ##envp##). + - if the env contained "INIT=xxxx", we do an execve("xxxx", "xxxx", ##no args##, ##envp##). + we don't pass the args because it is a rescue init, such as a shell, and + we don't want it to fail on "bash: auto: command not found" or similar. + - if the conf contained "in xxxx", we do an execve("xxxx", "xxxx", argv[], ##envp##) + because we want it to know about the original args. Eg: init=/.preinit single + - if the conf didn't contain "in xxxx", we transfer execution to "/sbin/init-sysv". + + Note: basically, each time an environment variable is read, it must be killed afterwards. + Eg: init2=, INIT=, ... + + + The root directory should contain the following dirs : + - /var (directory) -> can be a ramfs or a real dir on another device + - /var/tmp (directory) -> idem + - /tmp (directory) -> idem + - /etc (directory or symlink) -> several possibilities : + - directory on the root fs (preferably) + - directory on another fs + - ramfs (or ramdisk) and directory extracted from other source + - symlink to /boot/etc (in this case, /boot/etc must be a populated directory) + /etc will already have several symlinks + + /boot (mandatory directory) contains the following : + - [kernel version] (directory) with vmlinuz, System.map, config and + the tree behind /lib/modules/[version] + - current (symlink to kernel version) + - vmlinuz (symlink to current/vmlinuz) + - System.map (symlink to current/System.map) + - config (symlink to current/config) + - eventually initrd (symlink to current/initrd) + - modules.dep (symlink to current/modules.dep) + - modules.pcimap (symlink to current/modules.pcimap) + + /boot *may* contain the following : + - etc (populated directory) + - bootfstab (if /etc and /boot/etc empty or non-existant) + + This helps in making /lib/modules : it will simply be a symlink to + /boot/current which will contain all modules. + + +wrong for now: + /tmp will always be linked to fs/var/tmp. + /var will always be linked to fs/var. + /fs must contain a description file for it (what to mount where, what to + initialize) so that init has a working filesystem hierarchy and fstab works. + /fs should be FAT-compatible, at least for its root structure. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MNT_DETACH +#define MNT_DETACH 2 +#endif + +#ifndef MS_MOVE +#define MS_MOVE 8192 +#endif + +#define STR_SECT ".rodata" + +#ifdef DEBUG +static void print(char *c) { + char *p = c; + while (*p) + p++; + write(0, c, p-c); +} +#else +#define print(a,...) do{}while(0) +#endif + +//#define ATOL(x) atol(x) +#define ATOL(x) my_atoul(x) + +typedef unsigned char uchar; + + +/* This ordering is awful but it's the most efficient regarding space wasted in + * long strings alignment with gcc-2.95.3 (gcc 3.2.3 doesn't try to align long + * strings). + */ +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) msg_ent_console[] = "Entering command line mode : enter one command per line, end with '.'\n"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) root_dir[] = "/"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cur_dir[] = "."; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_name[] = "/dev"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_dir[] = "/var"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cfg_fname[] = "/.preinit"; /* configuration file */ +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) msg_err_console[] = "Command ignored, input alread bound to console !\n"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_console[] = "dev/console"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) str_rebuild[] = "rebuild"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_tmp[] = "/var/tmp"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) var_run[] = "/var/run"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_self_fd[] = "/proc/self/fd"; +//static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_cmdline[] = "/proc/cmdline"; +//static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) sbin_init[] = "sbin/init"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) sbin_init_sysv[] = "sbin/init-sysv"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) cfg_linuxrc[] = "/.linuxrc"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_options[] = "size=0,nr_inodes=4096,mode=755"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) str__linuxrc[] = "/linuxrc"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) proc_dir[] = "/proc"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) tmpfs_fs[] = "tmpfs"; +static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) dev_root[] = "dev/root"; + + +#define tmp_name (var_tmp + 4) // static const char tmp_name[] = "/tmp"; +#define proc_fs (proc_dir+1) // static const char proc_fs[] = "proc"; +#define fd_dir (proc_self_fd + 11) // static const char fd_dir[] = "fd"; +#define str_linuxrc (str__linuxrc+1) // "linuxrc" + + +#define CONST_STR(x) ({ static const char __attribute__ ((__section__(STR_SECT),__aligned__(1))) ___str___[]=x; (char *)___str___; }) + +/* used by naming rules */ +#define MAX_FIELDS 8 +#define MAX_DEVNAME_LEN 64 +#define MAX_CFG_SIZE 16384 +#define MAX_CFG_ARGS 64 +//#define MAX_CMDLINE_LEN 512 +#define MAX_BRACE_LEVEL 10 + +struct dev_varstr { + char type; + union { + struct { + char *set; + char *ptr; + char value; /* value to be printed */ + uchar index; /* index in the set */ + } chr; + struct { + uchar low; + uchar high; + uchar value; + } num; + } u; + uchar scale; +}; + +enum { + TOK_LN = 0, /* ln : make a symlink */ + TOK_MD, /* md : mkdir */ + TOK_MT, /* mt : mount */ + TOK_RE, /* re : remount */ + TOK_IN, /* in : set init program */ + TOK_EX, /* ex : execute */ + TOK_RX, /* rx : execute under chroot */ + TOK_BL, /* bl : make block devices */ + TOK_CH, /* ch : make char devices */ + TOK_FI, /* fi : make a fifo */ + TOK_MA, /* ma : set umask */ + TOK_PR, /* pr : pivot root */ + TOK_MV, /* mv : move a filesystem */ + TOK_BI, /* bi : bind a directory */ + TOK_UM, /* um : umount a filesystem */ + TOK_LO, /* lo : losetup */ + TOK_EC, /* ec : echo */ + TOK_TE, /* te : test an environment variable */ + TOK_RD, /* rd : read a command from the console */ + TOK_RM, /* rm : remove files */ + TOK_ST, /* st : stat file existence */ + TOK_WK, /* wk : wait key */ + TOK_OB, /* { : begin a command block */ + TOK_CB, /* } : end a command block */ + TOK_DOT, /* . : end of config */ + TOK_UNK, /* unknown command */ + TOK_EOF, /* end of file */ + TOK_COND_NEG = 0x20, /* negate the result before evaluation */ + TOK_COND_OR = 0x40, /* conditionnal OR */ + TOK_COND_AND = 0x80, /* conditionnal AND */ + TOK_COND = 0xE0, /* any condition */ +}; + +/* counts from TOK_LN to TOK_DOT */ +#define NB_TOKENS 25 + +/* this contains all two-chars command, 1-char commands, followed by a token + * number. + */ +static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { + char lcmd[2]; /* long form */ + char scmd; /* short form */ + char minargs; /* min #args */ +} tokens[NB_TOKENS] = { + "ln", 'L', 2, /* TOK_LN */ + "md", 'D', 1, /* TOK_MD */ + "mt", 'M', 3, /* TOK_MT */ + "re", 0, 3, /* TOK_RE */ + "in", 'I', 1, /* TOK_IN */ + "ex", 'E', 1, /* TOK_EX */ + "rx", 'R', 2, /* TOK_RX */ + "bl", 'B', 6, /* TOK_BL */ + "ch", 'C', 6, /* TOK_CH */ + "fi", 'F', 4, /* TOK_FI */ + "ma", 'U', 1, /* TOK_MA */ + "pr", 'P', 2, /* TOK_PR */ + "mv", 'K', 2, /* TOK_MV */ + "bi", 'K', 2, /* TOK_BI */ + "um", 'O', 1, /* TOK_UM */ + "lo", 'l', 2, /* TOK_LO */ + "ec", 0, 0, /* TOK_EC */ + "te", 0, 1, /* TOK_TE */ + "rd", 0, 0, /* TOK_RD */ + "rm", 0, 1, /* TOK_RM */ + "st", 0, 1, /* TOK_ST */ + "wk", 0, 2, /* TOK_WK */ + "{", '{', 0, /* TOK_OB */ + "}", '}', 0, /* TOK_CB */ + ".", '.', 0, /* TOK_DOT : put every command before this one */ +}; + +#define UID_ROOT 0 +#define GID_ROOT 0 +#define GID_TTY 5 +#define GID_KMEM 9 + +static const __attribute__ ((__section__(STR_SECT),__aligned__(1))) struct { + char name[8]; + short gid; + char major, minor; + mode_t mode; /* mode + S_IFCHR, S_IFBLK, S_IFIFO */ +} dev_nodes[] = { + /* console must always be at the first location */ + { "console", GID_TTY, 5, 1, 0600 | S_IFCHR }, + { "mem", GID_KMEM, 1, 1, 0640 | S_IFCHR }, + { "kmem", GID_KMEM, 1, 2, 0640 | S_IFCHR }, + { "null", GID_ROOT, 1, 3, 0666 | S_IFCHR }, + { "port", GID_KMEM, 1, 4, 0640 | S_IFCHR }, + { "zero", GID_ROOT, 1, 5, 0666 | S_IFCHR }, + { "full", GID_ROOT, 1, 7, 0666 | S_IFCHR }, + { "random", GID_ROOT, 1, 8, 0644 | S_IFCHR }, + { "urandom", GID_ROOT, 1, 9, 0644 | S_IFCHR }, + { "tty0", GID_TTY, 4, 0, 0600 | S_IFCHR }, + { "tty", GID_TTY, 5, 0, 0666 | S_IFCHR }, + { "ptmx", GID_TTY, 5, 2, 0666 | S_IFCHR }, + { "initctl", GID_ROOT, 0, 0, 0600 | S_IFIFO }, +} ; + +static char cfg_data[MAX_CFG_SIZE]; +static char *cfg_args[MAX_CFG_ARGS]; +static char *cfg_line; +//static char cmdline[MAX_CMDLINE_LEN]; +static char *cst_str[MAX_FIELDS]; +static char *var_str[MAX_FIELDS]; +static struct dev_varstr var[MAX_FIELDS]; +static int error; /* an error has emerged from last operation */ +static int linuxrc; /* non-zero if we were called as 'linuxrc' */ + +/* the two input modes */ +#define INPUT_FILE 0 +#define INPUT_KBD 1 + +static unsigned long my_atoul(const char *s) { + unsigned long res = 0; + unsigned long digit; + + while (*s) { + digit = *s - '0'; + if (digit > 9) + return 0; + res = res * 10 + digit; + s++; + } + return res; +} + +static int streq(const char *str1, const char *str2) { + char c1; + while ((c1 = *str1) && c1 == *str2) { /* the second test ensures that *str2 != 0 */ + str1++; + str2++; + } + return ((c1 | *str2) == 0); +} + +/* + * copies at most chars from to . Last char is always + * set to 0, unless is 0. The number of chars copied is returned + * (excluding the terminating zero). + * This code has been optimized for size and speed : on x86, it's 45 bytes + * long, uses only registers, and consumes only 4 cycles per char. + */ +static inline int my_strlcpy(char *dst, const char *src, int size) { + char *orig = dst; + if (size) { + while (--size && (*dst = *src)) { + src++; dst++; + } + *dst = 0; + } + return dst - orig; +} + +static void reopen_console() { + int i, fd, oldfd; + + oldfd = dup2(0, 3); // keep a valid console on fd 3 + + for (i = 0; i < 3; i++) + close(i); + + fd = open(dev_console, O_RDWR); // fd = 0 (stdin) or -1 (error) + if (fd < 0) + dup(oldfd); // restore 0 from old console + + close(oldfd); + dup(0); // stdout + dup(0); // stderr + + print("init/info : reopened /dev/console\n"); +} + +#if 0 +/* reads the kernel command line into memory and searches + * for the first assignment of the required variable. Return its value + * (which may be empty) or NULL if not found. + */ +char *find_arg(char *arg) { + char *a, *c; + + /* read cmdline the first time */ + if (!*cmdline) { + int fd, len; + + if ((fd = open(proc_cmdline, O_RDONLY)) == -1) + return NULL; + if ((len = read(fd, cmdline, sizeof(cmdline)-1)) == -1) { + close(fd); + return NULL; + } + cmdline[len] = 0; + close(fd); + } + + /* search for the required arg in cmdline */ + c = cmdline; + a = arg; + + while (*c) { + if (*a == 0) { + /* complete match. is it a full word ? */ + if (*c == '=') { + a = ++c; + while ((*a != ' ') && (*a != '\0') && (*a != '\n')) + a++; + *a = 0; + return c; /* return value */ + } + else if (*c == ' ' || *c == '\n' || *c == '\0') { + *c = 0; + return c; /* return pointer to empty string */ + } + else { /* not full word. bad match. */ + c -= (a - arg) - 1; + a = arg; + } + } + if (*c == *a) { + a++; + c++; + } + else { + c -= (a - arg) - 1; + a = arg; + } + } + if (*a == 0) /* complete match at end of string */ + return c; /* pointer to empty string */ + else + return NULL; /* not found */ +} +#endif + +/* + * looks for the last assignment of variable 'var=' in 'envp'. + * the value found is returned (or NULL if not found). + * if 'remove' is not zero, the assignment is removed afterwards. + * eg: init=my_getenv(envp, "init=", 1); + */ +char *my_getenv(char **envp, char *var, const int remove) { + int namelen; + char **last; + + last = NULL; + namelen = strlen(var); + while (*envp != NULL) { + if (!strncmp(*envp, var, namelen)) + last = envp; + envp++; + } + + if (last == NULL) { + return NULL; + } else { + char *ret = (*last) + namelen; + if (remove) + while (*last != NULL) { + *last = *(last+1); + last++; + } + return ret; + } +} + +/* reads the configuration file into memory. + * returns 0 if OK, -1 if error. + */ +static inline int read_cfg(char *cfg_file) { + int cfg_fd; + int cfg_size; + + if (cfg_line == NULL) { + if (((cfg_fd = open(cfg_file, O_RDONLY)) == -1) || + ((cfg_size = read(cfg_fd, cfg_data, sizeof(cfg_data) - 1)) == -1)) { + return -1; + } + close(cfg_fd); + cfg_line = cfg_data; + cfg_data[cfg_size] = 0; + } + return 0; +} + +/* reads one line from . comments are ignored. The command token is + * returned as the result of this function, or TOK_UNK if none matches, or + * TOK_EOF if nothing left. All args are copied into as an array + * of pointers. Maximum line length is 256 chars and maximum args number is 15. + */ +static int parse_cfg(char **cfg_data) { + int nbargs; + int token; + int cond; + char *cfg_line = *cfg_data; + + memset(cfg_args, 0, sizeof(cfg_args)); + while (*cfg_line) { + char c, *p = cfg_line; + + cond = 0; + /* search beginning of line */ + do { + if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') { + if (*p == '|') { + cond |= TOK_COND_OR; + } else if (*p == '&') { + cond |= TOK_COND_AND; + } else if (*p == '!') { + cond ^= TOK_COND_NEG; + } else { + /* catches any printable char and the final zero */ + break; + } + } + p++; + } while (1); + + /* now search end of line */ + cfg_line = p; + while (*cfg_line && *cfg_line != '#' && *cfg_line != '\n' && *cfg_line != '\r') { + cfg_line++; + } + + /* terminate the line cleanly to avoid further tests */ + while (c = *cfg_line) { + *cfg_line++ = '\0'; + if (c == '\n') + break; + } + + /* update the caller's pointer once for all. */ + *cfg_data = cfg_line; + + /* skip empty lines */ + if (!*p) + continue; + + /* fills the cfg_args[] array with the command itself, followed by all + * args. cfg_args[last+1]=NULL. + * + * We have a particular case here : + * if the line begins with '/', then we return TOK_EX so that it executes + * the command just as it would have done with 'ex' prefixed to the line. + * For this, we insert a fake cfg_args[0], also pointing to the '/', which + * will be matched later. + */ + nbargs = 0; + if (*p == '/') + cfg_args[nbargs++] = p; + + for (; *p && (nbargs < MAX_CFG_ARGS - 1); nbargs++) { + int backslash = 0, quote = 0; + + cfg_args[nbargs] = p; + + do { + if (backslash) { + backslash = 0; + if (*p == 'n') + *p = '\n'; + else if (*p == 'r') + *p = '\r'; + else if (*p == 't') + *p = '\t'; + memmove(p - 1, p, cfg_line - p); + } else { + backslash = (*p == '\\'); + if (*p == '"') { + memmove(p, p + 1, cfg_line - p - 1); + quote = !quote; + } + else + p++; + } + } while (*p && (backslash || quote || (*p != ' ' && *p != '\t'))); + if (*p) { + *p = 0; + do p++; while (*p == ' ' || *p == '\t'); + } + } + + /* search a matching token for the command : it can either be a single + * char (old language) or a double char (new language). + * + * We have a particular case : + * if the line begins with '/', then we return TOK_EX so that it executes + * the command just as it would have done with 'ex' prefixed to the line. + */ + if (**cfg_args == '/') + return TOK_EX | cond; + + for (token = 0; token < NB_TOKENS; token++) + if ((!cfg_args[0][1] && tokens[token].scmd == cfg_args[0][0]) || + (cfg_args[0][1] && + (tokens[token].lcmd[1] == cfg_args[0][1]) && + (tokens[token].lcmd[0] == cfg_args[0][0]))) + return token | cond; + + return TOK_UNK; + } + return TOK_EOF; +} + +/* makes a dev entry. continues on error, but reports them. */ +static inline int mknod_chown(mode_t mode, uid_t uid, gid_t gid, uchar major, uchar minor, char *name) { + int error; + + if (mknod(name, mode, makedev(major, minor)) == -1) { + error = 1; + print("init/error : mknod("); print(name); print(") failed\n"); + } + + if (chown(name, uid, gid) == -1) { + error = 1; + print("init/error : chown("); print(name); print(") failed\n"); + } + + return error; +} + +/* breaks a 3-fields, comma-separated string into 3 fields */ +static inline int varstr_break(char *str, char *type, char **set, uchar *scale) { + int state; + char *res[3]; + + for (state = 0; state < 3; state++) { + res[state] = str; + while (*str && *str != ',') + str++; + if (*str) + *str++ = 0; + else if (state < 2) + return 1; + } + + *type = *res[0]; + *set = res[1]; + *scale = ATOL(res[2]); + return 0; +} + +/* reads a range from a string of the form "low-high" or "value". + * Returns 0 if OK, or 1 if error. + */ +static int int_range(char *from, uchar *low, uchar *high) { + char c; + *low = 0; + while ((c = *from) != '\0') { + if (isdigit(c)) + *low = *low * 10 + c - '0'; + else if (c == '-') { + low = high; + *low = 0; + } + else + return 1; + from++; + } + if (low != high) /* high has not been written to */ + *high = *low; + + return 0; +} + +/* reads a range from a hex string of the form "low-high" or "value". + * Returns 0 if OK, or 1 if error. + */ +static int hex_range(char *from, uchar *low, uchar *high) { + uchar c; + *low = 0; + while ((c = *from) != '\0') { + if (c == '-') { + low = high; /* all writes will now be done on */ + *low = 0; + } + else { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else + return 1; + + *low = (*low << 4) + c; + } + from++; + } + if (low != high) /* high has not been written to */ + *high = *low; + + return 0; +} + +static inline char *addcst(char *dest, char *cst) { + while ((*dest++ = *cst++) != '\0'); + return dest - 1; +} + +static inline char *addchr(char *dest, char chr) { + *dest++ = chr; + *dest = '\0'; + return dest; +} + +static char *addint(char *dest, uchar num) { + int div; + char *out = dest; + for (div = (1<<16) + (10<<8) + (100); div > 0;) { + int q, r, d; + d = (unsigned char)div; + q = num / d; r = num % d; + div >>= 8; + if (!div || (out != dest) || q) { + *out++ = q + '0'; + } + num = r; + } + *out = '\0'; + return out; +} + +static char *addhex(char *dest, uchar num) { + uchar c; + if (num > 0x0F) { + c = num >> 4; + *dest++ = (c > 9) ? (c - 10 + 'a') : (c + '0'); + } + c = num & 0x0F; + *dest++ = (c > 9) ? (c - 10 + 'a') : (c + '0'); + *dest = '\0'; + return dest; +} + +/* builds a device name from the current and arrays, + * and compute the corresponding minor number by adding all the relevant + * fields' values + */ +static void name_and_minor(char *name, uchar *minor, int fields) { + uchar min; + int f; + + min = 0; + for (f = 0; f < fields; f++) { + if (*cst_str[f]) + name = addcst(name, cst_str[f]); + switch (var[f].type) { + case 'c' : + name = addchr(name, var[f].u.chr.value); + min += var[f].u.chr.index * var[f].scale; + break; + case 'h' : + name = addhex(name, var[f].u.num.value); + goto recalc_int; + case 'i' : + name = addint(name, var[f].u.num.value); + goto recalc_int; + case 'I' : + if (var[f].u.num.value) + name = addint(name, var[f].u.num.value); + recalc_int: + min += (var[f].u.num.value - var[f].u.num.low) * var[f].scale; + break; + case 0 : + break; + default: + print("init/conf : field type must be c, h, i or I\n"); + } + } + if (minor) + *minor = min; +} + +/* increments the index for variable #f. When it overflows, it goes back to the + * beginning and a carry is returned for the next variable to be incremented. + * 0 is returned if no carry is returned, otherwise, 1 is returned. + */ +static int inc_var_index(int f) { + switch (var[f].type) { + case 'c' : + if ((var[f].u.chr.ptr[1] == '-') && (var[f].u.chr.value < var[f].u.chr.ptr[2])) { + var[f].u.chr.value++; + var[f].u.chr.index++; + return 0; + } else { /* we cannot increment within the current range */ + if (*++var[f].u.chr.ptr == '-') { + if (*++var[f].u.chr.ptr) + var[f].u.chr.ptr++; + } + if (!*var[f].u.chr.ptr) { /* no other range found */ + var[f].u.chr.value = *(var[f].u.chr.ptr = var[f].u.chr.set); + var[f].u.chr.index = 0; + return 1; + } + else { /* found a new range */ + var[f].u.chr.value = *var[f].u.chr.ptr; + var[f].u.chr.index++; + return 0; + } + } + case 'h': + case 'i': + case 'I': + if (var[f].u.num.value == var[f].u.num.high) { + var[f].u.num.value = var[f].u.num.low; + return 1; + } else { + var[f].u.num.value++; + return 0; + } + default: + return 1; /* an empty variable propagates carry */ + } +} + + +/* makes one or several device inodes depending on the rule */ +static void multidev(mode_t mode, uid_t uid, gid_t gid, uchar major, uchar minor, char *rule) { + char *p1, *p2; + int state; + int i; + + enum { + ST_STRING = 0, + ST_CONST + }; + + int field; /* each field is a couple of a cst string and a var string */ + + p1 = p2 = rule; + state = ST_STRING; + field = 0; + + cst_str[field] = var_str[field] = p2; /* be sure to point to something valid */ + + while (*p2) { + if (state == ST_STRING) { + if (*p2 == '[') { + state = ST_CONST; + cst_str[field] = p1; + *p2++ = 0; + p1 = p2; + } + else + p2++; + } + else if (state == ST_CONST) { + if (*p2 == ']') { + state = ST_STRING; + var_str[field++] = p1; + *p2++ = 0; + p1 = p2; + cst_str[field] = p1; + } + else + p2++; + } + } + + if (state == ST_STRING) { + if (p2 > p1) { + state = ST_CONST; + cst_str[field] = p1; + var_str[field++] = p2; + *p2++ = 0; + } + } + else { + print("var string incomplete\n"); + } + + /* now we must "compile" the variable fields */ + for (i = 0; i < field; i++) { + memset(&var[i], 0, sizeof(var[i])); + if (varstr_break(var_str[i], &var[i].type, &var[i].u.chr.set, &var[i].scale)) { + //print("empty variable field in string <"); print(var_str[i]); print(">\n"); + continue; + } + + switch (var[i].type) { + case 'c': + var[i].u.chr.value = *(var[i].u.chr.ptr = var[i].u.chr.set); + var[i].u.chr.index = 0; + break; + case 'h': + if (hex_range(var[i].u.chr.set, &var[i].u.num.low, &var[i].u.num.high)) { + print("init/conf : error in hex range\n"); + continue; + } + var[i].u.num.value = var[i].u.num.low; + break; + case 'i': + case 'I': + if (int_range(var[i].u.chr.set, &var[i].u.num.low, &var[i].u.num.high)) { + print("init/conf : error in int range\n"); + continue; + } + var[i].u.num.value = var[i].u.num.low; + break; + default: + // unknown type + break; + } + } + + while (1) { + char name[MAX_DEVNAME_LEN]; + uchar minor_offset; + int f; + + name_and_minor(name, &minor_offset, field); + + mknod_chown(mode, uid, gid, major, minor + minor_offset, name); + f = 0; + while (inc_var_index(f) && (f= field) + break; + } +} + +/* converts an octal permission mode into the mode_t equivalent */ +static mode_t a2mode(char *ascii) { + mode_t m = 0; + while ((unsigned)(*ascii - '0') < 8) { + m = (m << 3) | (*ascii - '0'); + ascii++; + } + return m; +} + +void flush_stdin() { + int ret; + fd_set in; + struct timeval tv; + + while (1) { + FD_ZERO(&in); + FD_SET(0, &in); + tv.tv_sec = tv.tv_usec = 0; + ret = select(1, &in, NULL, NULL, &tv); + if (ret <= 0) + break; + read(0, &ret, sizeof(ret)); + } +} + +/* waits seconds for a character to be entered from stdin. It returns + * zero if the timeout expires, otherwise it flushes stdin and returns 1 + */ +int keypressed(int delay) { + int ret; + fd_set in; + struct timeval tv; + FD_ZERO(&in); + FD_SET(0, &in); + tv.tv_sec = delay; tv.tv_usec=0; + ret = select(1, &in, NULL, NULL, &tv); + if (ret <= 0) + return 0; + flush_stdin(); + return 1; +} + +int main(int argc, char **argv, char **envp) { + int old_umask; + int pid1, err; + int cfg_ok; + int rebuild; + int token; + int cmd_input = INPUT_FILE; + static char cmd_line[256]; /* one line of config from the prompt */ + struct stat statf; + // char *cmdline_arg; + char *cfg_file; + int brace_level, kbd_level, run_level; + struct { + int error; + int cond; + } context[MAX_BRACE_LEVEL]; + + char *conf_init, *force_init; + + /* first, we'll check if we have been called as 'linuxrc', used only in + initrd. In this particular case, we ignore all arguments and use + /.linuxrc as a configuration file. + */ + +#ifdef DEBUG + print("argv[0]: "); print(argv[0]); print("\n"); + sleep(1); +#endif + + /* if we are called as "linuxrc" or "/linuxrc", then we work a bit + * differently : /dev is unmounted at the end, and we proceed even if the + * pid is not 1. + * + * Warning: for an unknown reason (isolinux, kernel?) specifying + * 'init=/linuxrc' or 'init=linuxrc' on the command line doesn't work + * because 'init' is set in argv[0] ! But setting it by hand works, + * so does 'init=/.linuxrc'. Rather strange. So the best solution is + * to link /sbin/init to /.linuxrc so that the interpreter's name is + * used even if nothing is specified. + */ + if (!strcmp(argv[0], str_linuxrc) || !strcmp(argv[0], str__linuxrc)) { + linuxrc = 1; + rebuild = 0; + pid1 = 0; + } + /* check if a config file name has been given to preinit : init [ \< ] [ init args ] */ + if (argc > 2 && *argv[1] == '<') { + cfg_file = argv[2]; + argv[2] = argv[0]; + argv += 2; + argc -= 2; + } + else + cfg_file = linuxrc ? (char *)cfg_linuxrc : (char *)cfg_fname; + + if (!linuxrc) { + /*FIXME*/ + /* restore the correct name. Warning: in the case where init is launched + * from userspace, the config file is not read again so only the hardcoded + * name will be used for the executable name. + */ + //*argv = (char *)&sbin_init_sysv; /*"sbin/init-sysv"*/; + conf_init = (char *)&sbin_init_sysv; /*"sbin/init-sysv"*/; + force_init = my_getenv(envp, CONST_STR("INIT="), 1); + //printf("force_init=<%s>, INIT_new=%p\n", my_getenv(envp, "INIT=", 0)); + /* if "rebuild" is passed as the only argument, then we'll try to rebuild a + * full /dev even if not pid==1, but only if it was not already populated + */ + rebuild = (argc == 2 && streq(argv[1], str_rebuild/*"rebuild"*/)); + pid1 = (getpid() == 1); + } + else { + conf_init = NULL; + force_init = my_getenv(envp, CONST_STR("init2="), 1); + //*argv = (char *)&sbin_init; /* "sbin/init" */ + //printf("force_init=<%s>, init2_new=%s\n", my_getenv(envp, "init2=", 0)); + } + + if (pid1 || linuxrc) { + setsid(); + } + + old_umask = umask(0); + cfg_ok = (read_cfg(cfg_file) == 0); + + chdir(root_dir); /* be sure not to stay under /dev ! */ + /* do nothing if we're not called as the first process */ + if (pid1 || linuxrc || rebuild) { + /* check if /dev is already populated : /dev/console should exist. We + * can safely ignore and overwrite /dev in case of linuxrc, reason why + * we don't test the presence of /dev/console. + */ +#ifndef I_AM_REALLY_DEBUGGING + if (linuxrc || stat(dev_console, &statf) == -1) { + print("init/info: /dev/console not found, rebuilding /dev.\n"); + if (mount(dev_name, dev_name, tmpfs_fs, MS_MGC_VAL, dev_options) == -1) + print("init/err: cannot mount /dev.\n"); + else { + int i; + if (chdir(dev_name) == -1) + print("init/error : cannot chdir(/dev)\n"); + + print("init/info: /dev has been mounted.\n"); + for (i = 0; i < sizeof(dev_nodes) / sizeof(dev_nodes[0]); i++) { + mknod_chown(dev_nodes[i].mode, (uid_t)UID_ROOT, (gid_t)dev_nodes[i].gid, + dev_nodes[i].major, dev_nodes[i].minor, (char *)dev_nodes[i].name); + } + symlink(proc_self_fd, fd_dir); + print("init/info: /dev has been rebuilt.\n"); + + chdir(root_dir); + /* if /dev was empty, we may not have had /dev/console, so the + * kernel couldn't bind us to it. So let's attach to it now. + */ + reopen_console(); + } + } else if (!pid1) { + /* we don't want to rebuild anything else if pid is not 1 */ +#ifdef DEBUG + print("init/info: /dev is OK.\n"); + sleep(10); +#endif + return 0; + } +#endif + /* if /dev/root is non-existent, we'll try to make it now */ + + if (stat(dev_root, &statf) == -1) { + print("init/info : /dev/root does not exist. Rebuilding...\n"); + if (stat(root_dir, &statf) == 0) { + if (mknod(dev_root, 0600 | S_IFBLK, statf.st_dev) == -1) { + //error = 1; + print("init/error : mknod(/dev/root) failed\n"); + } + } + else { + print("init/error : cannot stat(/)\n"); + } + } + } + + /* here, the cwd is still "/" */ + if (cfg_ok) { + print("ready to parse file : "); print(cfg_file); print("\n"); + + run_level = brace_level = 0; + context[brace_level].error = 0; + context[brace_level].cond = 0; + + /* main parsing loop */ + while (1) { + int cond = 0; + + if (cmd_input == INPUT_KBD) { + int len; + char *cmd_ptr = cmd_line; + static char prompt[MAX_BRACE_LEVEL + 4]; + char *p = prompt; + int lev1, lev2; + + p += my_strlcpy(p, error ? CONST_STR("ER\n>") : CONST_STR("OK\n>"), 5); + + lev1 = run_level; + lev2 = brace_level; + while (lev1) { + *p++ = '>'; + lev1--; + lev2--; + } + if (lev2) { + *p++ = '{'; + while (lev2--) + *p++ = '>'; + *p++ = '}'; + } + *p++ = ' '; + write(1, prompt, p-prompt); + + len = read(0, cmd_line, sizeof(cmd_line)-1); + if (len > 0) { + cmd_line[len] = 0; + token = parse_cfg(&cmd_ptr); + if (token == TOK_EOF) /* empty line */ + continue; + } else { + token = TOK_DOT; + } + + if (token == TOK_DOT) { + cmd_input = INPUT_FILE; + brace_level = kbd_level; + /* if it was not right, 'rd' would not have been called : */ + run_level = brace_level; + /* don't report prompt errors to the rest of the config ! */ + error = 0; + } + } /* end of kbd */ + + if (cmd_input == INPUT_FILE) { + token = parse_cfg(&cfg_line); + if (token == TOK_EOF || token == TOK_DOT) + break; + } + + if (token == TOK_UNK) { + print("unknown command.\n"); + continue; + } + + cond = token & TOK_COND; + token &= ~TOK_COND; + + if (cfg_args[(int)tokens[token].minargs] == NULL) { + print("Missing args\n"); + continue; + } + + /* now we can reset the error */ + context[brace_level].error = error; + error = 0; + + if (token == TOK_CB) { /* closing brace */ + if (cond & TOK_COND) { + print("Conditions not permitted with a closing brace.\n"); + /* we close the brace anyway, ignoring the condition. */ + } else if (brace_level == 0) { + print("Too many closing braces.\n"); + error = context[brace_level].error; + continue; + } + /* transmit the current error to the upper level, and restore the upper + * condition to know if we had to negate the result or not. + */ + error = context[brace_level--].error; + cond = context[brace_level].cond; + if (run_level > brace_level) + run_level = brace_level; + goto finish_cmd; + } + else if (token == TOK_OB) { /* opening brace */ + if (brace_level == MAX_BRACE_LEVEL - 1) { + print("Too many brace levels.\n"); + error = context[brace_level].error; + break; + } + + /* if this block should not be executed because of a particular + * condition, we'll mark the new level to be skipped, so that + * other braces are correctly counted but not evaluated. + */ + if ((run_level == brace_level) && + (!(cond & TOK_COND_OR) || context[brace_level].error) && + (!(cond & TOK_COND_AND) || !context[brace_level].error)) { + /* save the current condition to properly handle a negation. + * The error code has already been set to 0. + */ + context[brace_level++].cond = cond; + run_level = brace_level; + } + else { + /* the braces will not be evaluated because a & or | prevents + * it to do so. Since we want to be able to chain these + * expressions to do if/then/else with &{}|{}, we'll propagate + * the current error code and void the condition. + */ + error = context[brace_level].error; + context[brace_level++].cond = 0; + } + continue; + } + + //printf("parsing intruction <%s %s...> at level %d (%d)\n", cfg_args[0], cfg_args[1], brace_level, run_level); + /* skip conditionnal executions if they cannot change the error status, + * as well as blocks of code excluded from the evaluation + */ + if ((cond & TOK_COND_OR) && !context[brace_level].error || + (cond & TOK_COND_AND) && context[brace_level].error || + (run_level < brace_level)) { + error = context[brace_level].error; + continue; + } + + + /* + * Now we begin to parse the 'real' commands. The first set is always available + */ + + if (token == TOK_IN) { + /* I | in : specify the path to init. + * Problem: what to do with init args ? + * We could pass ours, but if init is replaced with a + * shell, this one might be called with 'auto'... + * So we flush them all. + */ + print("nit : used config name for init\n"); + + /* in keyboard mode, specifying init stops any further parsing, + * so that the rest of the config file can be skipped. + */ + if (cmd_input == INPUT_KBD) { + force_init = cfg_args[1]; + break; + } else { + /* non sense to switch error status when assigning init */ + error = context[brace_level].error; + conf_init = cfg_args[1]; + continue; + } + } else if (token == TOK_TE) { + /* te : compare an environment variable to a value. + * In fact, look for the exact assignment in the environment. + * The result is OK if found, NOK if not. + */ + char **env = envp; + while (*env) { + //printf("testing <%s> against <%s>\n", cfg_args[1], *env); + if (!strcmp(*env, cfg_args[1])) + break; + env++; + } + error = (*env == NULL); + goto finish_cmd; + } + + /* other options are reserved for pid 1/linuxrc/rebuild and prompt mode */ + if (!pid1 && !linuxrc && !rebuild && cmd_input != INPUT_KBD) { + print("Command ignored since pid not 1\n"); + error = context[brace_level].error; + continue; + + } else if (token == TOK_RD || token == TOK_EC || token == TOK_WK) { + /* ec : echo a string + rd : display message then read commands from the console instead of the file + wk : display message and wait for a key for at most seconds. + returns TRUE if a key is pressed, FALSE otherwise. + */ + char *msg; + int len; + + if (cfg_args[1] != NULL) { + len = strlen(cfg_args[1]); + cfg_args[1][len] = '\n'; + write(1, cfg_args[1], len + 1); + } + + if (token == TOK_WK) { + error = !keypressed(ATOL(cfg_args[2])); + goto finish_cmd; + } + + if (token != TOK_RD) + goto finish_cmd; + + if (cmd_input == INPUT_KBD) { + msg = (char *)msg_err_console; + len = sizeof(msg_err_console) - 1; + } else { + msg = (char *)msg_ent_console; + len = sizeof(msg_ent_console) - 1; + kbd_level = brace_level; + } + error = context[brace_level].error; + write(1, msg, len); + cmd_input = INPUT_KBD; + continue; + } + + /* the second command set is available if pid==1 or if "rebuild" is set */ + switch (token) { + case TOK_MD: + /* md path [ mode ] : make a directory */ + if (mkdir(cfg_args[1], (cfg_args[2] == NULL) ? 0755 : a2mode(cfg_args[2])) == -1) { + error = 1; + print("irectory : mkdir() failed\n"); + } + goto finish_cmd; + case TOK_LN: + /* ln from to : make a symlink */ + if (symlink(cfg_args[1], cfg_args[2]) == -1) { + error = 1; + print("ymlink : symlink() failed\n"); + } + goto finish_cmd; + case TOK_ST: { + /* st file : return error if file does not exist */ + struct stat stat_buf; + if (stat(cfg_args[1], &stat_buf) == -1) { + error = 1; + } + goto finish_cmd; + } + case TOK_RM: { + /* rm file... : unlink file or links */ + int arg = 1; + while (cfg_args[arg]) { + if (unlink(cfg_args[arg]) == -1) { + error = 1; + print("Unlink : unlink() failed\n"); + } + arg++; + } + goto finish_cmd; + } + case TOK_BL: + /* bl : build a block device */ + case TOK_CH: + /* ch : build a character device */ + if (chdir(dev_name) == -1) { + print("lock_dev/har_dev : cannot chdir(/dev)\n"); + error = 1; + goto finish_cmd; + } + + multidev(a2mode(cfg_args[1]) | ((token == TOK_BL) ? S_IFBLK : S_IFCHR), + (uid_t)ATOL(cfg_args[2]), (gid_t)ATOL(cfg_args[3]), + ATOL(cfg_args[4]), ATOL(cfg_args[5]), cfg_args[6]); + chdir(root_dir); + goto finish_cmd; + case TOK_FI: + /* F : build a fifo */ + if (chdir(dev_name) == -1) { + print("ifo : cannot chdir(/dev)\n"); + error = 1; + goto finish_cmd; + } + + error = mknod_chown(a2mode(cfg_args[1]) | S_IFIFO, + (uid_t)ATOL(cfg_args[2]), (gid_t)ATOL(cfg_args[3]), + 0, 0, cfg_args[4]); + chdir(root_dir); + goto finish_cmd; + } /* end of switch() */ + + /* other options are reserved for pid 1/linuxrc/prompt mode only */ + if (!pid1 && !linuxrc && cmd_input != INPUT_KBD) { + print("Command ignored since pid not 1\n"); + error = context[brace_level].error; + continue; + } + + switch (token) { + case TOK_MT: + case TOK_RE: { + /* M dev[(major:minor)] mnt type [ {rw|ro} [ flags ] ]: (re)mount dev on mnt (read-only) */ + char *maj, *min, *end; + char *mntdev; + int mntarg; + + /* if the device name doesn't begin with a slash, look for it + * in /proc/cmdline + */ + mntdev = cfg_args[1]; + // the following code handles "var=/dev/sda2" or "home=/dev/hda1(3:1)" on + // the kernel command line. + //if ((*mntdev != '/') && ((cmdline_arg = find_arg(mntdev)) != NULL)) { + // mntdev = cmdline_arg; + // print("ount : using command line device\n"); + //} + + maj = mntdev; /* handles /dev/xxx(maj:min) */ + while (*maj && *maj != '(') + maj++; + if (*maj) { + int imaj = 0, imin = 0; + dev_t dev; + + *(maj++) = 0; + min = end = maj; + while (*min && *min != ':') + min++; + + if (*min) { + *(min++) = 0; + end = min; + } + + while (*end && *end != ')') + end++; + + if (*end) + *end = 0; + if (*maj) + imaj = ATOL(maj); + if (*min) + imin = ATOL(min); + dev = makedev(imaj, imin); + if (mknod(mntdev, S_IFBLK|0600, dev) == -1) { /* makes the node as required */ + error = 1; + print("ount : mknod() failed\n"); + } + } + + mntarg = MS_RDONLY; + if (cfg_args[4] != NULL && streq(cfg_args[4], CONST_STR("rw"))) { + print("ount : 'rw' flag found, mounting read/write\n"); + mntarg &= ~MS_RDONLY; + } + else { + print("ount : 'rw' flag not found, mounting read only\n"); + } + + if (token == TOK_RE) + mntarg |= MS_REMOUNT; + + if (mount(mntdev, cfg_args[2], cfg_args[3], MS_MGC_VAL | mntarg, cfg_args[5]) == -1) { + error = 1; + print("ount : error during mount()\n"); + } + + break; + } + case TOK_EX: + /* E cmd [cfg_args] : execute cmd with cfg_args, chrooted to dir */ + /* fall through TOK_RX */ + case TOK_RX: { + /* R dir cmd [cfg_args] : execute cmd with cfg_args, chrooted to dir */ + char **exec_args, *exec_dir; + int res; + + exec_args = cfg_args + 1; + if (token == TOK_EX) { + exec_dir = (char *)root_dir; + } + else { + exec_dir = cfg_args[1]; + exec_args++; + } + + res = fork(); + if (res == 0) { + chroot(exec_dir); + execve(exec_args[0], exec_args, envp); + print("xec(child) : execve() failed\n"); + return 1; + } + else if (res > 0) { + int ret; + print("xec(parent) : waiting for termination\n"); + while (((ret = wait(&error)) != -1) && (ret != res)) + print("xec(parent) : signal received\n"); + + error = (ret == -1) || ((WIFEXITED(error) > 0) ? WEXITSTATUS(error) : 1); + print("xec(parent) : child exited\n"); + } + else { + print("xec : fork() failed\n"); + error = 1; + } + break; + } + case TOK_MA: + /* U : change umask */ + umask(a2mode(cfg_args[1])); + break; + case TOK_PR: + /* P : pivot root */ + if (chdir(cfg_args[1]) == -1) { + error = 1; + print("

ivot : error during chdir(new root)\n"); + } + + if (pivot_root(/*CONST_STR(".")*/cur_dir, cfg_args[2]) == -1) { + error = 1; + print("

ivot : error during pivot_root()\n"); + } + + chroot(cur_dir/*CONST_STR(".")*/); + if (chdir(root_dir) == -1) { + error = 1; + print("

ivot : error during chdir(/)\n"); + } + + /* replace stdin/stdout/stderr with newer ones */ + reopen_console(); + break; + case TOK_MV: + /* K | mv : + * initially used to keep directory after a pivot, now used to + * move a filesystem to another directory. + */ + if (mount(cfg_args[1], cfg_args[2], cfg_args[1], MS_MGC_VAL | MS_MOVE, NULL) == 0) + break; + /* if it doesn't work, we'll try to cheat with BIND/UMOUNT */ + case TOK_BI: + /* bi : bind old_dir to new_dir, which means that directory + * will show the same contents as . + */ + if (mount(cfg_args[1], cfg_args[2], cfg_args[1], MS_MGC_VAL | MS_BIND, NULL) == -1) { + error = 1; + print(" : error during mount|bind\n"); + } + if (token == TOK_BI) + break; + /* fall through umount if we were trying a move */ + case TOK_UM: + /* um : umount after a pivot. */ + if (umount2(cfg_args[1], MNT_DETACH) == -1) { + error = 1; + print(" : error during umount\n"); + } + break; + case TOK_LO: { + /* lo : losetup /dev/loopX file */ + struct loop_info loopinfo; + int lfd, ffd; + + if ((lfd = open (cfg_args[1], O_RDONLY)) < 0) { + error = 1; + print("(l)osetup : error opening loop device\n"); + break; + } + if ((ffd = open (cfg_args[2], O_RDONLY)) < 0) { + error = 1; + print("(l)osetup : error opening image\n"); + goto losetup_close_all; + } + memset(&loopinfo, 0, sizeof (loopinfo)); + my_strlcpy(loopinfo.lo_name, cfg_args[2], LO_NAME_SIZE); + if (ioctl(lfd, LOOP_SET_FD, ffd) < 0) { + error = 1; + print("(l)osetup : error during LOOP_SET_FD\n"); + goto losetup_close_all; + } + if (ioctl(lfd, LOOP_SET_STATUS, &loopinfo) < 0) { + error = 1; + ioctl(lfd, LOOP_CLR_FD, 0); + print("(l)osetup : error during LOOP_SET_STATUS\n"); + goto losetup_close_all; + } + losetup_close_all: + close (lfd); close (ffd); + break; + } + default: + print("unknown cmd in /.preinit\n"); + break; + } + finish_cmd: + if (cond & TOK_COND_NEG) + error = !error; + } /* while (1) */ + } else if (pid1 && !linuxrc) { + print("init/info : error while opening configuration file : "); + print(cfg_file); print("\n"); + + /* /.preinit was not found. In this case, we take default actions : + * - mount /proc + * - mount /var as tmpfs if it's empty and /tmp is a symlink + */ + if (mount(proc_dir, proc_dir, proc_fs, MS_MGC_VAL, NULL) == -1) + print("init/err: cannot mount /proc.\n"); + else + print("init/info: /proc mounted RW.\n"); + + /* we'll see if we want to build /var */ + if ((stat(var_tmp, &statf) == -1) && /* no /var/tmp */ + (stat(tmp_name, &statf) == 0) && S_ISLNK(statf.st_mode)) { /* and /tmp is a symlink */ + print("init/info: building /var.\n"); + if (mount(var_dir, var_dir, tmpfs_fs, MS_MGC_VAL, NULL) == -1) + print("init/err: cannot mount /var.\n"); + else { + print("init/info: /var has been mounted.\n"); + mkdir(var_dir, 0755); + mkdir(var_tmp, 01777); + mkdir(var_run, 0755); + print("init/info: /var has been built.\n"); + } + } + } + else { + print("init/info : error while opening configuration file : "); + print(cfg_file); print("\n"); + } + + if (rebuild) { + print("end of rebuild\n"); +#ifdef SLOW_DEBUG + sleep(10); +#endif + /* nothing more to do */ + return 0; + } + + + /* We undo all that we can to restore a clean context. + * In case the init has been specified by the user at the console prompt, + * we don't close 0/1/2 nor dismount /dev, else we wouldn't be able to do + * anything. + */ + + if (force_init != NULL) { + /* we keep the cmdline args if we take it from the kernel cmdline, + * but we flush any args if it comes from the keyboard + */ + argv[0] = force_init; + if (cmd_input == INPUT_KBD) + argv[1] = NULL; + } else { + /* standard conf or new linuxrc : !NULL = chained init */ + /* old linuxrc : NULL = no chained init */ + argv[0] = conf_init; + } + + if (linuxrc && force_init == NULL) { + /* normal linuxrc : we close and unmount all what we have done, but not + * in case of forced init, because if we force, it should mean that we + * want a prompt or something special. + */ + close(2); close(1); close(0); + umount2(dev_name, MNT_DETACH); + } + +#if 0 + + if (cmd_input != INPUT_KBD) { + if (linuxrc) { + close(2); close(1); close(0); + umount2(dev_name, MNT_DETACH); + print("exit from linuxrc\n"); +#ifdef SLOW_DEBUG + sleep(10); +#endif + /* handle the lilo command line "init2=prog" */ + //cmdline_arg = find_arg(CONST_STR("init2")); + //cmdline_arg = my_getenv(envp, CONST_STR("init2="), 1); + } else { + /* handle the lilo command line "INIT=prog" */ + //cmdline_arg = find_arg(CONST_STR("INIT")); + cmdline_arg = my_getenv(envp, CONST_STR("INIT="), 1); + } + + if (cmdline_arg != NULL) { + argv[0] = cmdline_arg; + argv[1] = NULL; + } + } + + print("init/debug: *argv = "); print (*argv); print("\n"); +#endif + + umask(old_umask); +#ifdef SLOW_DEBUG + sleep(10); +#endif + /* the old linuxrc behaviour doesn't exec on exit. */ + if (*argv != NULL) { + err = execve(*argv, argv, envp); + print("init/error : last execve() failed\n"); + + /* we'll get a panic there, so let some time for the user to read messages */ + if (pid1) + sleep(60); + return err; + } + return 0; +} diff --git a/scripts/flxextract b/scripts/flxextract index e4aa4ee..7077fa2 100755 --- a/scripts/flxextract +++ b/scripts/flxextract @@ -1,6 +1,6 @@ #!/bin/bash # -# flxextract - package extracter - version 0.0.2 - 2003-06-16 +# flxextract - package extracter - version 0.0.3 - 2005-10-31 # This file is part of the Formilux project : http://formilux.ant-computing.com/ # # Copyright (C) 2001-2003 Benoit Dolez & Willy Tarreau @@ -19,7 +19,7 @@ function main { for pack in ${packages//,/ }; do pkgsrc=$(find $SEARCHPATH -name ${pack}'*'.lst | head -1) - [ "$pkgsrc" ] && break + [ -n "$pkgsrc" ] && break done if [ -z "$pkgsrc" ]; then @@ -27,7 +27,7 @@ function main { continue fi - set -- $( grep "$file" $pkgsrc | awk '{ if ($8=="'$file'") print $0; }' ) + set -- $(awk "/$file/ { if (\$8==\"$file\") print \$0; }" $pkgsrc) if [ -z "$*" ]; then echo "##not found## $file $pkgsrc" >> $LOGFILE continue @@ -36,7 +36,7 @@ function main { # it's a directory rm -f $ROOTDIR/$8 >/dev/null 2>&1 # just in case it was something else mkdir -p $ROOTDIR/$8 - touch -t `date -d "Jan 1 00:00:$7 UTC 1970" +"%Y%m%d%H%M.%S" ` $ROOTDIR/$8 + touch -t $(date -d "Jan 1 00:00:00 UTC 1970 + $7 sec" +"%Y%m%d%H%M.%S" ) $ROOTDIR/$8 chown $3:$4 $ROOTDIR/$8 chmod $2 $ROOTDIR/$8 echo "$8/" >> $LOGFILE @@ -48,8 +48,7 @@ function main { echo >&2 ; echo -n "Extracting files ..." >&2 for lst in $( awk '{print $2}' $SFILES | sort -u ) ; do - tgz="$(dirname $lst)/$(basename $lst .lst).tgz" - grep -- " $lst$" $SFILES | awk '{print $1}' | tar zUxpvf $tgz -C $ROOTDIR -T - >> $LOGFILE + awk "/ $lst\$/ {print \$1}" $SFILES | tar zUxpvf ${lst%.lst}.tgz -C $ROOTDIR -T - >> $LOGFILE echo -n "." >&2 done echo "." >&2 diff --git a/scripts/flxfix b/scripts/flxfix index ef09a90..8952c39 100755 --- a/scripts/flxfix +++ b/scripts/flxfix @@ -1,27 +1,83 @@ #!/bin/bash -# flxfix - 2003/01/31 - Willy Tarreau +# flxfix 0.2 - 2005/04/17 - Willy Tarreau # Generates a shell script from a difference between two trees so that the last -# one becomes as close to the first one as possible. +# one becomes as close to the first one as possible. Second usage is to rebuild +# all the meta-data from a signature. +# # usage: # flx check | flxfix [ -R ] > fix.sh -# Use -R to swap the two trees +# Use -R to swap the two trees +# flx sign | flxfix -n > create.sh +# Generates a shell script which rebuilds the meta-data from the tree's +# signature. +# +# WARNING: this script does not understand flx-0.7's extended encoding of +# unprintable characters. + + +entryisdiff=1 +restoredate=1 +unset mustswap ignoreuid # usage : fixperms $perm $uid $gid $date $name function fixperms { - echo touch -t \"`date -d "Jan 1 00:00:$4 UTC 1970" +"%Y%m%d%H%M.%S" `\" $5 - echo chown $2:$3 $5 + echo touch ${restoredate:+-t \"$(date -d "Jan 1 00:00:$4 UTC 1970" +"%Y%m%d%H%M.%S" )\"} $5 + [ -z "$ignoreuid" ] && echo chown $2:$3 $5 echo chmod $1 $5 } -mustswap=0 -if [ "x$1" = "x-R" ]; then - mustswap=1 -fi +# swap diff direction : -/+, +function swap { + local x + x=${1//<}; x=${x/./>} + x=${x/-/.}; x=${x/+/-}; x=${x/./+} + echo -n $x +} + +# usage: usage progname exitcode +function usage { + echo "$1: Generates a script to rebuild the meta-data from an flx signature" + echo "Usage:" + echo " flx check | $1 > fix.sh" + echo " flx check | $1 -R > fix.sh" + echo " flx sign | $1 -n > new.sh" + echo " cat old-signature.lst | $1 -n > new.sh" + echo "" + echo "Options:" + echo " -R swap the two trees" + echo " -n recreate a new tree from a single signature" + echo " -t do not restore timestamp" + echo " -u do not restore uid/gid" + + exit $2 +} + + +while [ $# -gt 0 ]; do + if [ "x$1" = "x-R" ]; then + mustswap=1 + elif [ "x$1" = "x-n" ]; then + unset entryisdiff + elif [ "x$1" = "x-u" ]; then + ignoreuid=1 + elif [ "x$1" = "x-t" ]; then + unset restoredate + elif [ "x$1" = "x-h" ]; then + usage "${0##*/}" 0 + else + echo "Warning: ignoring unknown option: $1" + usage "${0##*/}" 1 + fi + shift +done -while read chg type perm uid gid size sign date name link rest; do - if [ $mustswap = 1 ]; then - chg=`echo $chg | tr '<>+\-' '><\-+'` +# trick: we only reference the 'chg' variable if 'entryisdiff' is set. +while read ${entryisdiff:+chg} type perm uid gid size sign date name link rest; do + if [ -z "$entryisdiff" ]; then + chg='-' + elif [ -n "$mustswap" ]; then + chg=$(swap $chg) fi if [ "x$rest" != "x" -o "x$type" != "xl" -a "x$link" != "x" ]; then @@ -45,7 +101,7 @@ while read chg type perm uid gid size sign date name link rest; do if [ x$type = xl ]; then # we'll rebuild a symbolic link echo ln -s $link $name - echo chown -h $uid:$gid $name + [ -z "$ignoreuid" ] && echo chown -h $uid:$gid $name elif [ x$type = xd ]; then # we'll rebuild a directory echo mkdir -p $name @@ -70,7 +126,7 @@ while read chg type perm uid gid size sign date name link rest; do # we'll destroy and rebuild a symbolic link echo rm -f $name echo ln -s $link $name - echo chown -h $uid:$gid $name + [ -z "$ignoreuid" ] && echo chown -h $uid:$gid $name elif [ x$type = xc -o x$type = xb -o x$type = xf ]; then # we'll destroy and rebuild nodes echo rm -f $name diff --git a/scripts/pkg b/scripts/pkg index e9465ef..9c38b6b 100755 --- a/scripts/pkg +++ b/scripts/pkg @@ -1,16 +1,19 @@ #!/bin/bash -# pkg - Formilux package builder - version 0.5.2 - 2005-03-25 +# pkg - Formilux package builder - version 0.7.1 - 2005-12-17 # # Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau # mailto: benoit@ant-computing.com,willy@ant-computing.com # # This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) +######## Please update this version ######## +PKG_VERSION=0.7.1 +############################################ + ## WARNING ## # This version is not compatible with pkg scripts written for pre-0.2.0 versions - # Usage: # pkg [ pkg [ pkg2 ] ] # @@ -50,7 +53,17 @@ umask og-w # set some constants KERNDIR=${KERNDIR:-/usr/src/linux} -FLXARCH=${FLXARCH:-$(uname -m)} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + DEVROOT=${DEVROOT:-/var/flx-dev} PKGROOT=${PKGROOT:-/var/flx-pkg} # use -p1 by default to apply a patch @@ -66,6 +79,7 @@ INSTNAME=".flxdisk" LINKNAME=".flxpkg" FIND_CMD=pkgfilefind +CURDIR="$(pwd)" FILE_LIST= @@ -76,6 +90,46 @@ EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cd ###### here are some undertermined type functions ###### +# check that this utility's version is at least as high as the version +# specified in $1. Returns 0 if OK, 1 if inferior. + +function check_pkg_version { + local version="$1" + local major minor patch + local mymajor myminor mypatch + + major=${version%%.*} + minor=${version#$major.}; minor=${minor%%.*} + patch=${version##*.} + + mymajor=${PKG_VERSION%%.*} + myminor=${PKG_VERSION#$mymajor.}; myminor=${myminor%%.*} + mypatch=${PKG_VERSION##*.} + + if [ -n "$major" ]; then + [ "$mymajor" -gt "$major" ] && return 0 + [ "$mymajor" -lt "$major" ] && return 1 + else + return 0 + fi + + if [ -n "$minor" ]; then + [ "$myminor" -gt "$minor" ] && return 0 + [ "$myminor" -lt "$minor" ] && return 1 + else + return 0 + fi + + if [ -n "$patch" ]; then + [ "$mypatch" -gt "$patch" ] && return 0 + [ "$mypatch" -lt "$patch" ] && return 1 + else + return 0 + fi + return 0 +} + + # find packageable files (that can't be automaticaly created) and return only # their relative path to the argument. @@ -92,6 +146,106 @@ function pkgfilefind { } +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + ###### ###### here are some functions for manipulating package names ###### @@ -127,6 +281,7 @@ function get_next_build { # This function accepts a list of versionned names, and returns them sorted by # version number. The names must NOT contain any '|' or '~' character, or they # will be discarded. Names that don't have any version are also discarded. +# Note: package names can be full path names. function sortnames { local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION local base version rest filename i t file flist @@ -143,10 +298,11 @@ function sortnames { VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" # make the list appear in the form 'package|version|rest|full_name' - list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ - -e "s/^$FIELD|$VERSION/\1|\2|/" \ - -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ - -e "s/^[^|]*|[^|]*$//")) + list=($(echo "$*" | grep -v "|~" | sed -e "s,$VERSION,\1|," \ + -e "s,^$FIELD|$VERSION,\1|\2|," \ + -e "s,^$FIELD|$FIELD|$FIELD$,\1|\2|\3~\1\2\3," \ + -e "s,^[^|]*|[^|]*$,," \ + -e 's,^[^|]*/,,')) # there's a risk that it doesn't complete for all the list, and that some # elements keep a "rest". But what can we do about it ? @@ -362,22 +518,31 @@ function do_build { # %D => use the default package # If several packages match a given pattern, the user is asked to select the # desired one. -# The result is returned in REPLY. +# The resulting package name is returned in REPLY, and the package directoryy +# is returned in PKGDIR whenever possible. function get_name { local pattern pkg_name local radix ver build local -a rel_list dev_list sort_list - local i + local i search_dir REPLY= for pattern in $*; do + search_dir= if [ "$pattern" = "%P" ]; then - pattern=$(basename $(pwd)) + search_dir="${CURDIR%/*}" ; search_dir="/${search_dir#/}" + pattern="$(basename $CURDIR)" elif [ "$pattern" = "%L" ]; then - if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + return + elif [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then # the link is always an EXACT name, so we return it as-is. - pattern=$(readlink ${LINKNAME}) - REPLY=$(basename $pattern) + pattern="$(readlink ${LINKNAME})" + PKGDIR="$pattern/." + REPLY="${pattern##*/}" return else continue @@ -394,13 +559,18 @@ function get_name { # we loop until pkg_name is empty, which allows recursive choices. while [ "$pkg_name" ]; do # now we'll try to build a list of potentially matching packages for - # each pattern. We'll reduce the original name until either we have - # a non-empty list or the package name is void. + # each pattern. A valid package needs to host 'build.cfg'. We could + # also look for the 'RELEASED' entry for released packages, but there + # are still a lot of old ones without this entry. We'll reduce the + # original name until either we have a non-empty list or the package + # name is void. rel_list=( ); dev_list=( ) while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do - rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + #rel_list=( $(find ${search_dir:+$search_dir/} $PKGROOT/ -maxdepth 2 -type f -path ${pkg_name}/build.cfg -printf "%h\n" 2>/dev/null) ) + #rel_list=( ${search_dir:+$CURDIR} $(find $PKGROOT/ -maxdepth 2 -type f -path ${pkg_name}/build.cfg -printf "%h\n" 2>/dev/null) ) + rel_list=( $(find ${search_dir:+$CURDIR/} $PKGROOT/ -maxdepth 2 -type f -path "*/${pkg_name}/build.cfg" -printf "%h\n" 2>/dev/null | uniq) ) if [ "$release_only" != "1" ]; then - dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 2 -type f -path "*/${pkg_name}/build.cfg" -printf "%h\n" 2>/dev/null) ) fi if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then @@ -434,7 +604,9 @@ function get_name { if [ ${#sort_list[*]} -eq 0 ]; then continue elif [ ${#sort_list[*]} -eq 1 ]; then - REPLY=${sort_list[0]} + REPLY="${sort_list[0]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" return fi @@ -443,21 +615,24 @@ function get_name { printf " %5d : - None of the following packages -\n" 0 while [ $i -lt ${#sort_list[*]} ]; do # we'll display an 'R' in front of released names, or a 'D' for dev. + # FIXME : we risk a wrong match here (eg: flx0.1 <-> flx0.10) if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then - printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} else - printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} fi i=$[$i+1] done echo while : ; do - echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i if [ -z "$i" ]; then # empty string, we use the last choice which is the preferred one. i=${#sort_list[*]} - REPLY=${sort_list[$[$i-1]]} + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" return elif [ "${i//[0-9]/}" ]; then # not a plain integer, we'll allow to recursively re-select @@ -472,7 +647,9 @@ function get_name { # if the user explicitly replied "0", then he wants other choices. break; elif [ $i -le ${#sort_list[*]} ]; then - REPLY=${sort_list[$[$i-1]]} + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" return fi done @@ -480,6 +657,8 @@ function get_name { # if he refuses these ones. done done + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" } # choose a package and make ${LINKNAME} point to it @@ -525,7 +704,7 @@ function do_newpkg { if [ -z "$new_name" ]; then # the user has not specified any version string, we'll use the directory # name. - new_name=$(basename $(pwd)) + new_name=$(basename $CURDIR) fi rel_list=( ); dev_list=( ) @@ -541,13 +720,13 @@ function do_newpkg { build=$(get_build_num $new_name) new_name=${radix:-*}-${ver:-*} - rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) - dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) sort_list=(${rel_list[*]} ${dev_list[*]}) if [ "${sort_list[*]}" ]; then sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) - sort_list=( $(sortnames ${sort_list[*]}) ) + sort_list=( $(sortnames ${sort_list[*]##*/} | uniq) ) if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then # if the package was properly named, and not already listed, let's @@ -561,21 +740,13 @@ function do_newpkg { local i=0 echo; echo ">>> Please select the name of the package to create :";echo while [ $i -lt ${#sort_list[*]} ]; do - # we'll display an 'R' in front of released names, 'P' - # in front of packaged ones, or a 'D' for dev. - if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then - printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} - elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then - printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} - else - printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} - fi + printf " %5d : %s\n" $[$i+1] ${sort_list[$i]##*/} i=$[$i+1] done echo while : ; do - echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i if [ -z "$i" ]; then new_name=${sort_list[${#sort_list[*]}-1]} break @@ -594,8 +765,8 @@ function do_newpkg { # we'll search for all packages starting with the same name and version # in both release and dev dirs. Then we'll be able to deduce the latest # build number used. -# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) - sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + #sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%p\n" 2>/dev/null|sort -u) ) if [ ${#sort_list[*]} -eq 0 ]; then # this can happen with new BUILDSFX/BUILDVER new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 @@ -648,7 +819,7 @@ function do_newpkg { rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ - -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + --exclude='./Version' --one-file-system -cpf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) chmod u+rw $new_name/build.cfg echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." @@ -680,13 +851,14 @@ function do_cat { function do_lst { local FPNAME - FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH cat $FPNAME.lst } function pre_info { - echo "Information for package '$EXACTPKG' :" + echo "Information for package '${EXACTPKG##*/}' (\${EXACTPKG##*/}) :" + echo " Package name : $PKGRADIX (\$PKGRADIX)" echo " Package version : $PKGVER (\$PKGVER)" echo " Distrib version : $DISTVER (\$DISTVER)" echo -n " Config. file : " @@ -695,10 +867,10 @@ function pre_info { else echo "none found." fi - echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo " Package file : $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF" echo -n " Package size : " - if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then - echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + if [ -e $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF |cut -f1) bytes." else echo "does not exist yet." fi @@ -752,10 +924,10 @@ function pre_prepack { fi # WARNING! here, we don't use $ROOTDIR because we don't want to risk # erasing a wrong directory as root ! - [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" # permissions are important here because we don't want to get an # inherited setgid or something alike on the root dir - [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chown 0:0 $ROOTDIR; chmod 0755 $ROOTDIR; } #mkdir -p "$EXAMPLEDIR" return 0 } @@ -783,7 +955,7 @@ function build_opt { function do_delpack { # WARNING! here, we don't use $ROOTDIR because we don't want to risk # erasing a wrong directory as root ! - [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" return 0 } @@ -844,7 +1016,7 @@ function do_unpatch { # extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). function do_unpack { - local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + local FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF mkdir -p $ROOTDIR cd $ROOTDIR @@ -881,7 +1053,7 @@ function pre_pack { function get_perl_depend { local filename=$1 local dep DEP - local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + local DEP_FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.dep DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ @@ -913,7 +1085,7 @@ function _do_pack_files { echo "done." # full path name of different files - FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH DEP_FILE=$FPNAME.dep rm -rf $DEP_FILE @@ -935,7 +1107,7 @@ function _do_pack_files { bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) flr="$(file $REPLY)" case "$flr" in - *\ shell\ *) + *\ script\ *) echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE ;; *perl\ commands*) @@ -943,13 +1115,13 @@ function _do_pack_files { get_perl_depend $REPLY ;; *:\ symbolic\ link*) - echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE ;; *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) - echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + elf_get_dep $REPLY >> $DEP_FILE ;; *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) - echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + elf_get_dep $REPLY >> $DEP_FILE ;; esac ;; @@ -972,12 +1144,12 @@ function _do_pack_files { echo -n "Creating $FPNAME.$PKGSUFF ... " # we want everything, including directories. - cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null # create shortcuts ".*" for tgz, dep and lst files for ext in dep lst tgz; do rm -f $PKGDIR/.$ext - ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext done echo "done." return 0 @@ -996,7 +1168,7 @@ function do_pack { if [ -z "${file##/*}" ]; then FILE_LISTS="$FILE_LISTS $file" else - FILE_LISTS="$FILE_LISTS $(pwd)/$file" + FILE_LISTS="$FILE_LISTS $CURDIR/$file" fi done # FIXME: is this normal ??? @@ -1025,7 +1197,7 @@ function do_pack { echo "done." # full path name of different files - FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH DEP_FILE=$FPNAME.dep # rebuild dependencies file, first is a diff file @@ -1083,7 +1255,7 @@ function do_pack { bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) flr="$(file $REPLY)" case "$flr" in - *\ shell\ *) + *\ script\ *) echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE ;; *perl\ commands*) @@ -1091,13 +1263,13 @@ function do_pack { get_perl_depend $REPLY ;; *:\ symbolic\ link*) - echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE ;; *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) - echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + elf_get_dep $REPLY >> $DEP_FILE ;; *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) - echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + elf_get_dep $REPLY >> $DEP_FILE ;; esac ;; @@ -1113,32 +1285,20 @@ function do_pack { # we want everything, and directories only if they're empty. # All this without './' we shouldn't get an empty line since . # should contain at least what we want to tar ! - $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null # create shortcuts ".*" for tgz, dep and lst files for ext in dep lst tgz; do rm -f $PKGDIR/.$ext - ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext done echo "done." return 0 } -# this function sets all needed compiler options -function set_compiler_options { - # now we'll set default ARCH and CPU for the current FLXARCH if none is set. - case "$FLXARCH" in - i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; - i586) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; - i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; - i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; - ev[456]*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; - parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; - sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; - sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; - *) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; - esac - + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { # Handling of cross-compilers : # - setting CC will force both HOSTCC and FLXCROSSCC # - setting HOSTCC will keep it @@ -1147,25 +1307,31 @@ function set_compiler_options { if [ -z "$FLX_CROSS_OPT_SET" ]; then CC=${CC:-gcc} + CXX=${CXX:-g++} AS=${AS:-as} LD=${LD:-ld} AR=${AR:-ar} + NM=${NM:-nm} RANLIB=${RANLIB:-ranlib} STRIP=${STRIP:-strip} OBJDUMP=${OBJDUMP:-objdump} HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} HOSTAS=${HOSTAS:-$AS} HOSTLD=${HOSTLD:-$LD} HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} HOSTSTRIP=${HOSTSTRIP:-$STRIP} HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} if [ -n "$FLXCROSS" ]; then CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} @@ -1173,10 +1339,28 @@ function set_compiler_options { # specify that we don't want to do this again FLX_CROSS_OPT_SET=1 fi - +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file case "$FLXARCH" in *86) CC=${CC:-gcc} + CXX=${CXX:-g++} FLX_ARCH_CURRENT="$FLXARCH" FLX_ARCH_COMMON="i586" FLX_ARCH_SMALL="$basearch" @@ -1189,15 +1373,16 @@ function set_compiler_options { GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" - if [ $TESTGCC -gt 0 ] && $CC -falign-loops=0 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" - GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -falign-jumps=0" - GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -falign-jumps=0 -falign-loops=0 -falign-functions=0" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" fi - ;; - + ;; + parisc*) CC=${CC:-gcc} + CXX=${CXX:-g++} FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" FLX_ARCH_COMMON="1.0" FLX_ARCH_SMALL="1.0" @@ -1208,12 +1393,13 @@ function set_compiler_options { GCC_CPU_COMMON="-mschedule=7100" GCC_CPU_SMALL="-mschedule=7100" GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" - GCC_OPT_FAST="-O2 -falign-jumps=0" - GCC_OPT_SMALL="-Os -falign-jumps=0 -falign-loops=0 -falign-functions=0" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" ;; sparc*) CC=${CC:-gcc} + CXX=${CXX:-g++} FLX_ARCH_CURRENT="$FLXARCH" FLX_ARCH_COMMON="$FLXARCH" FLX_ARCH_SMALL="$FLXARCH" @@ -1224,12 +1410,13 @@ function set_compiler_options { GCC_CPU_COMMON="-mtune=$cpu" GCC_CPU_SMALL="-mtune=$cpu" GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" - GCC_OPT_FAST="-O2 -falign-jumps=0" - GCC_OPT_SMALL="-Os -falign-jumps=0 -falign-loops=0 -falign-functions=0" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" ;; ev[456]*) CC=${CC:-gcc} + CXX=${CXX:-g++} FLX_ARCH_CURRENT="$FLXARCH" FLX_ARCH_COMMON="$FLXARCH" FLX_ARCH_SMALL="$FLXARCH" @@ -1240,38 +1427,107 @@ function set_compiler_options { GCC_CPU_COMMON="-mtune=$cpu" GCC_CPU_SMALL="-mtune=$cpu" GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" - GCC_OPT_FAST="-O2 -falign-jumps=0" - GCC_OPT_SMALL="-Os -falign-jumps=0 -falign-loops=0 -falign-functions=0" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" ;; *) CC=${CC:-gcc} + CXX=${CXX:-g++} FLX_ARCH_CURRENT="$FLXARCH" FLX_ARCH_COMMON="$FLXARCH" FLX_ARCH_SMALL="$FLXARCH" GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" GCC_OPT_FAST="-O2 -malign-jumps=0" GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" - if [ $TESTGCC -gt 0 ] && $CC -falign-loops=0 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" - GCC_OPT_FAST="-O2 -falign-jumps=0" - GCC_OPT_SMALL="-Os -falign-jumps=0 -falign-loops=0 -falign-functions=0" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" fi ;; esac + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL - export CC AS LD AR STRIP OBJDUMP GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL return 0 } +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + function usage { # this is needed to present current options to the user + set_cross_environment set_compiler_options + echo "PKG version $PKG_VERSION - Formilux package build utility." echo "Usage:" echo " pkg [-options]* [ pkg [ pkg2 ] ]" echo @@ -1313,6 +1569,8 @@ function usage { echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" echo "GCC_OPT_FAST=$GCC_OPT_FAST" echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." # Those two are not user-settable anymore # echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" @@ -1359,11 +1617,11 @@ function do_release { fi # first, the destination directory must not exist - if [ -d "$PKGROOT/$EXACTPKG" ]; then - if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + if [ -d "$PKGROOT/${EXACTPKG##*/}" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/RELEASED" ]; then echo "Error: This package already exists." else - echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + echo "Error: The package directory $PKGROOT/${EXACTPKG##*/} already exists." fi exit 1 fi @@ -1375,11 +1633,11 @@ function do_release { last_pkg=${last_pkg##*released } fi - if [ "$last_pkg" != "$EXACTPKG" ]; then + if [ "$last_pkg" != "${EXACTPKG##*/}" ]; then # Let's create a new changelog entry touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; - echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo $'\t'"* released ${EXACTPKG##*/}"; echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null fi @@ -1394,15 +1652,71 @@ function do_release { echo "Error: cannot move the package to the released directory. Cancelling." # the mv here fails atomically, so nothing's lost in PKGDIR, but we have # to clean a possible partial copy - rm -rf $PKGROOT/$EXACTPKG + rm -rf $PKGROOT/${EXACTPKG##*/} exit 2 fi - touch $PKGROOT/$EXACTPKG/RELEASED + touch $PKGROOT/${EXACTPKG##*/}/RELEASED return 0 } +# usage: install-files file... +# +function install-files { + local owner="$1" ; shift + local perm="$1" ; shift + local dst="$1" ; shift + local file + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + cp -dpfP "$@" "$ROOTDIR/$dst/" && \ + ( cd "$ROOTDIR/$dst" && chown -h $owner "${@##*/}" && chmod $perm "${@##*/}" ) + + [ -n "$FILE_LIST" ] && for file in "$@"; do echo "$dst/$file $owner $perm"; done >> $FILE_LIST +} + +# usage: install-file +# +function install-file { + local owner="$1" ; shift + local perm="$1" ; shift + local src="$1" ; shift + local dst="$1" ; shift + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + if cp -dpfP "$src" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" \ + && [ ! -L "$ROOTDIR/$dst" ]; then chmod $perm "$ROOTDIR/$dst"; fi + + [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST +} + +# usage: install-dir

... +# +function install-dir { + local owner="$1" ; shift + local perm="$1" ; shift + local dst + + for dst in "$@"; do + mkdir -pm $perm "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" + [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST + done +} + +# usage: install-ln +# +function install-ln { + local owner="$1" ; shift + local target="$1" ; shift + local dst="$1" ; shift + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + ln -s "$target" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" + [ -n "$FILE_LIST" ] && echo $dst $owner 000 >> $FILE_LIST +} + + ###### ###### here are some functions used only from main ###### @@ -1425,6 +1739,7 @@ release_only=0 force=0 TESTGCC=0 PRINTUSAGE=0 +PRINTENV=0 ARGLIST=( ) ACTION= CHAINCMD=1 @@ -1439,6 +1754,10 @@ while [ $# -gt 0 ] ; do --help|-h) PRINTUSAGE=1 ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; --rel|-r*) release_only=1 ;; @@ -1460,6 +1779,7 @@ done #echo "arglist=${ARGLIST[*]}" +[ $PRINTENV -gt 0 ] && print_env [ $PRINTUSAGE -gt 0 ] && usage [ ${#ARGLIST[*]} -lt 1 ] && usage @@ -1488,32 +1808,57 @@ while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do CHAINCMD=0 KNOWNCMD=1 get_name ${ARGLIST[0]} %L %P %D + [ -d "$PKGDIR" ] || PKGDIR= ;; patch|unpatch) CHAINCMD=0 KNOWNCMD=1 - REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) - PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi # get_name %L ;; compile_only|config|config_only|compile|build) KNOWNCMD=1 - REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) - PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi TESTGCC=1 # get_name %L ;; prepack|strip|pack|delpack|release|clean) KNOWNCMD=1 - REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) - PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi # get_name %L ;; *) CHAINCMD=0 KNOWNCMD=0 - REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) - PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi # get_name %L ;; esac @@ -1526,27 +1871,28 @@ while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do echo "Error: package name not found." exit 1 fi - EXACTPKG=$REPLY + EXACTPKG="$PKGDIR/$REPLY" if [ -z "$PKGDIR" ]; then - if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then - PKGDIR=$PKGROOT/$EXACTPKG + if [ -e "$PKGROOT/${EXACTPKG##*/}/build.cfg" ]; then + PKGDIR="$PKGROOT/${EXACTPKG##*/}" else - PKGDIR=$DEVROOT/$EXACTPKG + PKGDIR="$DEVROOT/${EXACTPKG##*/}" fi fi - CFGFILE=$PKGDIR/build.cfg - PKGRADIX=$(get_pkg_radix $EXACTPKG) - PKGVER=$(get_pkg_ver $EXACTPKG) - DISTVER=$(get_build_num $EXACTPKG) - ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} - EXAMPLEDIR=${ROOTDIR}/usr/share/examples + CFGFILE="$PKGDIR/build.cfg" + PKGRADIX="$(get_pkg_radix ${EXACTPKG##*/})" + PKGVER="$(get_pkg_ver ${EXACTPKG##*/})" + DISTVER="$(get_build_num ${EXACTPKG##*/})" + ROOTDIR="${ROOTDIR:-$CURDIR/${INSTNAME}}" + EXAMPLEDIR="${ROOTDIR}/usr/share/examples" # for compatibility with old functions. Not used anywhere outside this script. - packver=$EXACTPKG - pack=$PKGRADIX + packver="${EXACTPKG##*/}" + pack="$PKGRADIX" fi + set_cross_environment set_compiler_options if [ "$ACTION" != "newpkg" ]; then @@ -1554,10 +1900,10 @@ while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do fi # FLXMAKE is used for sequential make and FLXPMAKE for parallel make - FLXMAKE=${FLXMAKE:-make} - FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + FLXMAKE="${FLXMAKE:-make}" + FLXPMAKE="${FLXPMAKE:-$FLXMAKE}" - export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST # echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" # echo "ARGLIST=${ARGLIST[*]}" @@ -1577,415 +1923,3 @@ done [ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 exit 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -exit 99 - -############################################################################################################### -############################################################################################################### -############################################################################################################### -############################################################################################################### - - -DEAD CODE BELOW !!! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -function usage { - echo "Usage: pkg [new_pkg [old_pkg]]" - echo " action is one of :" - echo " help : display this help." - echo " info : get information on current package." - echo " newpkg : build a more recent .pkg script from an old one." - echo " cat : display last .pkg file." - echo " edit : edit last .pkg file." - echo " patch : apply a list of patches to the directory prior to compile." - echo " unpatch : revert a list of patches to the directory." - echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" - echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" - echo " strip : strip binaries in temporary directory" - echo " pack : strip binaries, then package into $PKGROOT" - echo " delpack : remove temporary directory" - echo " clean : execute 'make clean' and remove temporary directory." - echo " build : execute clean compile prepack pack." - echo " unpack : extract package into temporary directory" - echo "Variables are :" - echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" - echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" - echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" - echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" - echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" - echo "FLXARCH : architecture for package name, <$FLXARCH>" - echo "KERNDIR : base directory for package (not source), <$KERNDIR>" - echo "DISTVER : build version (flx.1)" - exit 1 -} - - - - - - - - - -for ACTION in ${ARGLIST[*]}; do - -# now we will try to identify two packages names : -# - the EXACT one, deduced from command line, then version symlink, then the -# directory name ; this one doesn't have to exist to be correct. -# - the NEAREST one, deduced from the same criterions, with and without -# versions, and based on EXISTING files only. -# The NEAREST one will be used as a source, while the EXACT one will be used as -# a target. When the EXACT one exists, the NEAREST one must obviously be the -# same. - -# EXACTPKG can be specified as an environment variable if needed -[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) -[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) -[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) - -if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then - TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) - TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} - TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} - TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} -# if [ -z "$TEMP" ]; then -# echo "Cannot find a suitable package for the current directory. Please specify" -# echo "a correct name on the command line." -# usage -# exit 1 -# fi - [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) - [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 -fi - -if [ -z "$(get_build_num $EXACTPKG)" ]; then - RADIX=$(get_pkg_radix $EXACTPKG) - TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) - - VER=$(get_pkg_ver $TEMP) - BUILD=$(get_build_num $TEMP) - EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} -fi - -NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) -NEWPKGVER=$(get_pkg_ver $EXACTPKG) -NEWDISTVER=$(get_build_num $EXACTPKG) -NEWDISTVER=${NEWDISTVER:-flx.1} -EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER - -trylist=( ) -[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) -[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) -[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) -trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) -trylist=( ${trylist[*]} $NEWPKGRADIX ) -trylist=( ${trylist[*]} $(basename $(pwd))) -trylist=( ${trylist[*]} "default") - -echo trylist=${trylist[*]} - -for NEARESTPKG in ${trylist[*]}; do - if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then - TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) - TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} - TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} - #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} - [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue - fi - - RADIX=$(get_pkg_radix $NEARESTPKG) - VER=$(get_pkg_ver $NEARESTPKG) - BUILD=$(get_build_num $NEARESTPKG) - NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} - - #### [ "$(get_build_num $NEARESTPKG)" ] && - - [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break -echo NEARESTPKG=$NEARESTPKG - - ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) - ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break -done - -RADIX=$(get_pkg_radix $NEARESTPKG) -VER=$(get_pkg_ver $NEARESTPKG) -BUILD=$(get_build_num $NEARESTPKG) -NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} - -echo "EXACTPKG=$EXACTPKG" -echo "NEARESTPKG=$NEARESTPKG" - -# to be removed ## look if there was an argument, in which case we would treat it as a package -# to be removed ## name (either source or destination, depending on the action). These variables -# to be removed ## are set : -# to be removed ## - ARGPKGFULL : full package name with version -# to be removed ## - ARGPKGRADIX : package radix name (without version) -# to be removed ## - ARGPKGVER : package version without -flx* -# to be removed ## - ARGDISTVER : package build version (flx*) -# to be removed # -# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then -# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) -# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) -# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) -# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then -# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) -# to be removed # fi -# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} -# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} -# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} -# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} -# to be removed #fi -# to be removed # -# to be removed ## look for package name from the '.flxver' link in current dir, then dir name -# to be removed # -# to be removed #if [ -L .flxver ]; then -# to be removed # PKGFULL=$(readlink .flxver) -# to be removed #else -# to be removed # PKGFULL=$(basename $(pwd)) -# to be removed #fi -# to be removed # -# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) -# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) -# to be removed # -# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then -# to be removed # DISTVER=$(get_build_num $PKGFULL) -# to be removed #fi -# to be removed # -# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} -# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} -# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} -# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} -# to be removed # -# to be removed # -# to be removed # -# to be removed ## now process the destination parameters -# to be removed # -# to be removed #if [ -L .flxver ]; then -# to be removed # NEWPKGFULL=$(readlink .flxver) -# to be removed #else -# to be removed # NEWPKGFULL=$(basename $(pwd)) -# to be removed #fi -# to be removed # -# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) -# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) -# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} -# to be removed # -# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then -# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) -# to be removed #fi -# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} -# to be removed # -# to be removed ## recompute the new package version -# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} -# to be removed # - - -# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the -# directory name for the new package. If it cannot be found, all actions except -# info and newpkg will fail. So we have to do a newpkg before using a new dir. - -if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then - echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." - exit 1 -fi - -# source configuration -ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} - - -CURPKG=$NEARESTPKG -PKGRADIX=$(get_pkg_radix $NEARESTPKG) -PKGVER=$(get_pkg_ver $NEARESTPKG) -if echo $NEARESTPKG | grep -q -- "-flx\." ; then - DISTVER=$(get_build_num $NEARESTPKG) - NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER -else - DISTVER= - NEARESTPKG=$PKGRADIX-$PKGVER -fi - -CFGDIR=$CFGROOT/$CURPKG -CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF - -echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" - -exit 0 - - - -if [ -n "$CFGFILE" ]; then - CFGDIR=$NEWCFGROOT/$NEWBASECFG - . $CFGFILE -else - #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` - #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} - #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} - #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} - CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` - CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} - CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} - CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} - - # to be completed - - if [ -z "$CFGFILE" ]; then - echo "CFGFILE not found. Cannot continue." >&2 - exit 1 - fi - - if [ -d $CFGFILE ]; then - CFGROOT=`dirname $CFGFILE` - CFGDIR=`basename $CFGFILE`-pkg - CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF - else - CFGROOT=`dirname $CFGFILE` - CFGDIR=`basename $CFGFILE`-pkg - CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF - if [ ! -e $CFGROOT/$CFGDIR ]; then - echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." - mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF - if [ $? != 0 ]; then - echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" - exit 1 - else - echo "Done !" - fi - fi - fi - - if [ -e "$CFGFILE" ]; then - . $CFGFILE - else - echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 - exit 1 - fi - fi - - if [ -z "$DISTVER" ]; then - if echo $CFGFILE | grep -q -- "-flx\." ; then - DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` - else - DISTVER='flx.1' - fi - fi - - echo $packver | grep -q -- "-flx\." - if [ $? != 0 ] ; then - packver=$packver-$DISTVER - fi - - echo $packver | grep -q -- "-$FLXARCH\$" - if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi - - prefix=${packver%%[._-][0-9]*} - suffix=${packver#$prefix[._-]} - PKGVER=${suffix%-flx*} - PKGRADIX=$prefix - #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" - if [ -z "$DISTVER" ]; then - DISTVER=${suffix#$PKGVER-} - if [ "$DISTVER" = "$PKGVER" ]; then - DISTVER="flx.1" - else - DISTVER=${DISTVER%-*} - fi - fi - - case "$FLXARCH" in - i686) arch=i686 cpu=i686 basearch=i386 ;; - i486) arch=i486 cpu=i486 basearch=i386 ;; - i386) arch=i386 cpu=i386 basearch=i386 ;; - *) arch=i586 cpu=i686 basearch=i386 ;; - esac - - if [ -z "$FLXMAKE" ]; then - FLXMAKE=make - fi - - - if [ -z "${PATCH_LIST}" ]; then - PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff - if [ ! -e ${PATCH_LIST} ]; then - unset PATCH_LIST - fi - fi - - export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST - - declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) - [ $? != 0 ] && exit $? - declare -f do_$ACTION > /dev/null && ( do_$ACTION ) - [ $? != 0 ] && exit $? - declare -f post_$ACTION > /dev/null && ( post_$ACTION ) - [ $? != 0 ] && exit $? - fi -fi - diff --git a/scripts/pkg-0.5.3 b/scripts/pkg-0.5.3 new file mode 100755 index 0000000..7eb096a --- /dev/null +++ b/scripts/pkg-0.5.3 @@ -0,0 +1,1994 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.3 - 2005-05-21 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXARCH=${FLXARCH:-$(uname -m)} +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + echo "$REPLY $(ldd $REPLY 2>/dev/null | grep -v 'statically linked' | awk '{print $1}' | tr '\012' ' ')" >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i586) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + ev[456]*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + *) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + esac + + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi + + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export CC AS LD AR STRIP OBJDUMP GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + + return 0 +} + +function usage { + # this is needed to present current options to the user + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.5.4 b/scripts/pkg-0.5.4 new file mode 100755 index 0000000..ec13c3d --- /dev/null +++ b/scripts/pkg-0.5.4 @@ -0,0 +1,2035 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.4 - 2005-08-12 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + echo "$REPLY $(objdump -p $REPLY 2>/dev/null | grep ' NEEDED ' | awk '{print $2}' | tr '\012' ' ')" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + echo "$REPLY $(objdump -p $REPLY 2>/dev/null | grep ' NEEDED ' | awk '{print $2}' | tr '\012' ' ')" >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY $(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + echo "$REPLY $(objdump -p $REPLY 2>/dev/null | grep ' NEEDED ' | awk '{print $2}' | tr '\012' ' ')" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + echo "$REPLY $(objdump -p $REPLY 2>/dev/null | grep ' NEEDED ' | awk '{print $2}' | tr '\012' ' ')" >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i586) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + ev[456]*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + *) arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + esac + + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.5.5 b/scripts/pkg-0.5.5 new file mode 100755 index 0000000..6fab71c --- /dev/null +++ b/scripts/pkg-0.5.5 @@ -0,0 +1,2135 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.5 - 2005-08-12 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.5.6 b/scripts/pkg-0.5.6 new file mode 100755 index 0000000..297ee6d --- /dev/null +++ b/scripts/pkg-0.5.6 @@ -0,0 +1,2183 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.6 - 2005-08-17 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.5.7 b/scripts/pkg-0.5.7 new file mode 100755 index 0000000..7e12878 --- /dev/null +++ b/scripts/pkg-0.5.7 @@ -0,0 +1,2193 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.7 - 2005-08-21 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + CXX=${CXX:-g++} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.5.8 b/scripts/pkg-0.5.8 new file mode 100755 index 0000000..5056766 --- /dev/null +++ b/scripts/pkg-0.5.8 @@ -0,0 +1,2195 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.5.8 - 2005-08-21 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s/$VERSION/\1|/" \ + -e "s/^$FIELD|$VERSION/\1|\2|/" \ + -e "s/^$FIELD|$FIELD|$FIELD$/\1|\2|\3~\1\2\3/" \ + -e "s/^[^|]*|[^|]*$//")) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The result is returned in REPLY. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i + + REPLY= + for pattern in $*; do + if [ "$pattern" = "%P" ]; then + pattern=$(basename $(pwd)) + elif [ "$pattern" = "%L" ]; then + if [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern=$(readlink ${LINKNAME}) + REPLY=$(basename $pattern) + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%f\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY=${sort_list[0]} + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY=${sort_list[$[$i-1]]} + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY=${sort_list[$[$i-1]]} + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $(pwd)) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%f\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "$PKGROOT/${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. +# sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%f\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d $(pwd)/${INSTNAME} ] && rm -rf $(pwd)/${INSTNAME} + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $(pwd)/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/$EXACTPKG-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/$EXACTPKG-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + CXX=${CXX:-g++} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/$EXACTPKG" ]; then + if [ -e "$PKGROOT/$EXACTPKG/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/$EXACTPKG already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/$EXACTPKG + exit 2 + fi + + touch $PKGROOT/$EXACTPKG/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + [ -d "$PKGDIR" ] || PKGDIR= + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + REPLY=$(basename $(readlink ${LINKNAME}) 2>/dev/null) + PKGDIR=$(readlink ${LINKNAME} 2>/dev/null) + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG=$REPLY + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/$EXACTPKG/build.cfg" ]; then + PKGDIR=$PKGROOT/$EXACTPKG + else + PKGDIR=$DEVROOT/$EXACTPKG + fi + fi + CFGFILE=$PKGDIR/build.cfg + PKGRADIX=$(get_pkg_radix $EXACTPKG) + PKGVER=$(get_pkg_ver $EXACTPKG) + DISTVER=$(get_build_num $EXACTPKG) + ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + EXAMPLEDIR=${ROOTDIR}/usr/share/examples + + # for compatibility with old functions. Not used anywhere outside this script. + packver=$EXACTPKG + pack=$PKGRADIX + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE=${FLXMAKE:-make} + FLXPMAKE=${FLXPMAKE:-$FLXMAKE} + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$EXACTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$EXACTPKG* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/$EXACTPKG-* $CFGROOT/$EXACTPKG $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/$EXACTPKG" -o -f "$CFGROOT/$EXACTPKG.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.6.0 b/scripts/pkg-0.6.0 new file mode 100755 index 0000000..3c0e3cb --- /dev/null +++ b/scripts/pkg-0.6.0 @@ -0,0 +1,2239 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.6.0 - 2005-08-27 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind +CURDIR="$(pwd)" + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +# Note: package names can be full path names. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s,$VERSION,\1|," \ + -e "s,^$FIELD|$VERSION,\1|\2|," \ + -e "s,^$FIELD|$FIELD|$FIELD$,\1|\2|\3~\1\2\3," \ + -e "s,^[^|]*|[^|]*$,," \ + -e 's,^[^|]*/,,')) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The resulting package name is returned in REPLY, and the package directoryy +# is returned in PKGDIR whenever possible. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i search_dir + + REPLY= + for pattern in $*; do + search_dir= + if [ "$pattern" = "%P" ]; then + search_dir="${CURDIR%/*}" ; search_dir="/${search_dir#/}" + pattern="$(basename $CURDIR)" + elif [ "$pattern" = "%L" ]; then + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + return + elif [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern="$(readlink ${LINKNAME})" + PKGDIR="$pattern/." + REPLY="${pattern##*/}" + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find ${search_dir:+$search_dir/} $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY="${sort_list[0]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + # FIXME : we risk a wrong match here (eg: flx0.1 <-> flx0.10) + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $CURDIR) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. + #sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%p\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + --exclude='./Version' -cplf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $CURDIR/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + CXX=${CXX:-g++} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/${EXACTPKG##*/}" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/${EXACTPKG##*/} already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/${EXACTPKG##*/} + exit 2 + fi + + touch $PKGROOT/${EXACTPKG##*/}/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + [ -d "$PKGDIR" ] || PKGDIR= + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG="$PKGDIR/$REPLY" + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/build.cfg" ]; then + PKGDIR="$PKGROOT/${EXACTPKG##*/}" + else + PKGDIR="$DEVROOT/${EXACTPKG##*/}" + fi + fi + CFGFILE="$PKGDIR/build.cfg" + PKGRADIX="$(get_pkg_radix $EXACTPKG)" + PKGVER="$(get_pkg_ver $EXACTPKG)" + DISTVER="$(get_build_num $EXACTPKG)" + ROOTDIR="${ROOTDIR:-$CURDIR/${INSTNAME}}" + EXAMPLEDIR="${ROOTDIR}/usr/share/examples" + + # for compatibility with old functions. Not used anywhere outside this script. + packver="$EXACTPKG" + pack="$PKGRADIX" + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE="${FLXMAKE:-make}" + FLXPMAKE="${FLXPMAKE:-$FLXMAKE}" + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/${EXACTPKG##*/}-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/${EXACTPKG##*/}-* $CFGROOT/${EXACTPKG##*/} $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/${EXACTPKG##*/}" -o -f "$CFGROOT/${EXACTPKG##*/}.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.6.1 b/scripts/pkg-0.6.1 new file mode 100755 index 0000000..5ee7c0a --- /dev/null +++ b/scripts/pkg-0.6.1 @@ -0,0 +1,2239 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.6.1 - 2005-09-17 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind +CURDIR="$(pwd)" + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +# Note: package names can be full path names. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s,$VERSION,\1|," \ + -e "s,^$FIELD|$VERSION,\1|\2|," \ + -e "s,^$FIELD|$FIELD|$FIELD$,\1|\2|\3~\1\2\3," \ + -e "s,^[^|]*|[^|]*$,," \ + -e 's,^[^|]*/,,')) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The resulting package name is returned in REPLY, and the package directoryy +# is returned in PKGDIR whenever possible. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i search_dir + + REPLY= + for pattern in $*; do + search_dir= + if [ "$pattern" = "%P" ]; then + search_dir="${CURDIR%/*}" ; search_dir="/${search_dir#/}" + pattern="$(basename $CURDIR)" + elif [ "$pattern" = "%L" ]; then + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + return + elif [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern="$(readlink ${LINKNAME})" + PKGDIR="$pattern/." + REPLY="${pattern##*/}" + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find ${search_dir:+$search_dir/} $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY="${sort_list[0]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + # FIXME : we risk a wrong match here (eg: flx0.1 <-> flx0.10) + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $CURDIR) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. + #sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%p\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + --exclude='./Version' --one-file-system -cpf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '$EXACTPKG' :" + + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $CURDIR/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + CXX=${CXX:-g++} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/${EXACTPKG##*/}" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/${EXACTPKG##*/} already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/${EXACTPKG##*/} + exit 2 + fi + + touch $PKGROOT/${EXACTPKG##*/}/RELEASED + + return 0 +} + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + [ -d "$PKGDIR" ] || PKGDIR= + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG="$PKGDIR/$REPLY" + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/build.cfg" ]; then + PKGDIR="$PKGROOT/${EXACTPKG##*/}" + else + PKGDIR="$DEVROOT/${EXACTPKG##*/}" + fi + fi + CFGFILE="$PKGDIR/build.cfg" + PKGRADIX="$(get_pkg_radix $EXACTPKG)" + PKGVER="$(get_pkg_ver $EXACTPKG)" + DISTVER="$(get_build_num $EXACTPKG)" + ROOTDIR="${ROOTDIR:-$CURDIR/${INSTNAME}}" + EXAMPLEDIR="${ROOTDIR}/usr/share/examples" + + # for compatibility with old functions. Not used anywhere outside this script. + packver="$EXACTPKG" + pack="$PKGRADIX" + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE="${FLXMAKE:-make}" + FLXPMAKE="${FLXPMAKE:-$FLXMAKE}" + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +exit 99 + +############################################################################################################### +############################################################################################################### +############################################################################################################### +############################################################################################################### + + +DEAD CODE BELOW !!! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function usage { + echo "Usage: pkg [new_pkg [old_pkg]]" + echo " action is one of :" + echo " help : display this help." + echo " info : get information on current package." + echo " newpkg : build a more recent .pkg script from an old one." + echo " cat : display last .pkg file." + echo " edit : edit last .pkg file." + echo " patch : apply a list of patches to the directory prior to compile." + echo " unpatch : revert a list of patches to the directory." + echo " compile : do_compile=do_config_only+do_compile_only in .pkg script ($CFGROOT/$CFGDIR)" + echo " prepack : execute do_prepack in .pkg script ($CFGROOT/$CFGDIR)" + echo " strip : strip binaries in temporary directory" + echo " pack : strip binaries, then package into $PKGROOT" + echo " delpack : remove temporary directory" + echo " clean : execute 'make clean' and remove temporary directory." + echo " build : execute clean compile prepack pack." + echo " unpack : extract package into temporary directory" + echo "Variables are :" + echo "CFGROOT : directory for .pkg and patches, <$CFGROOT>" + echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" + echo "PKGROOT : directory for .lst, .tgz and .dep, <$PKGROOT>" + echo "ROOTDIR : base directory for package (not source), <$ROOTDIR>" + echo "EXAMPLEDIR : base directory for sample config , <$EXAMPLEDIR>" + echo "FLXARCH : architecture for package name, <$FLXARCH>" + echo "KERNDIR : base directory for package (not source), <$KERNDIR>" + echo "DISTVER : build version (flx.1)" + exit 1 +} + + + + + + + + + +for ACTION in ${ARGLIST[*]}; do + +# now we will try to identify two packages names : +# - the EXACT one, deduced from command line, then version symlink, then the +# directory name ; this one doesn't have to exist to be correct. +# - the NEAREST one, deduced from the same criterions, with and without +# versions, and based on EXISTING files only. +# The NEAREST one will be used as a source, while the EXACT one will be used as +# a target. When the EXACT one exists, the NEAREST one must obviously be the +# same. + +# EXACTPKG can be specified as an environment variable if needed +[ $NEAREST_IS_SRC -eq 0 ] && [ -z "$EXACTPKG" -a ${#ARGLIST[*]} -gt 0 ] && EXACTPKG=$(basename ${ARGLIST[0]}) +[ -z "$EXACTPKG" -a -L .flxver ] && EXACTPKG=$(readlink .flxver) +[ -z "$EXACTPKG" ] && EXACTPKG=$(basename $(pwd)) + +if [ -z "$(get_pkg_ver $EXACTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/${EXACTPKG##*/}-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}-* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/${EXACTPKG##*/}* | tail -1)} +# if [ -z "$TEMP" ]; then +# echo "Cannot find a suitable package for the current directory. Please specify" +# echo "a correct name on the command line." +# usage +# exit 1 +# fi + [ "$TEMP" ] && EXACTPKG=$(basename $TEMP) + [ -z "$(get_pkg_ver $EXACTPKG)" ] && EXACTPKG=$EXACTPKG-0 +fi + +if [ -z "$(get_build_num $EXACTPKG)" ]; then + RADIX=$(get_pkg_radix $EXACTPKG) + TEMP=$(sortnames $CFGROOT/${EXACTPKG##*/}-* $CFGROOT/${EXACTPKG##*/} $CFGROOT/$RADIX | tail -1) + + VER=$(get_pkg_ver $TEMP) + BUILD=$(get_build_num $TEMP) + EXACTPKG=${RADIX}-${VER:-0}-${BUILD:-flx.1} +fi + +NEWPKGRADIX=$(get_pkg_radix $EXACTPKG) +NEWPKGVER=$(get_pkg_ver $EXACTPKG) +NEWDISTVER=$(get_build_num $EXACTPKG) +NEWDISTVER=${NEWDISTVER:-flx.1} +EXACTPKG=$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER + +trylist=( ) +[ -d "$CFGROOT/${EXACTPKG##*/}" -o -f "$CFGROOT/${EXACTPKG##*/}.$PKGSUFF" ] && trylist=( ${trylist[*]} $EXACTPKG) +[ ${#ARGLIST[*]} -gt 0 ] && trylist=( ${trylist[*]} $(basename ${ARGLIST[0]})) +[ -L .flxver ] && trylist=( ${trylist[*]} $(readlink .flxver)) +trylist=( ${trylist[*]} $NEWPKGRADIX-$NEWPKGVER ) +trylist=( ${trylist[*]} $NEWPKGRADIX ) +trylist=( ${trylist[*]} $(basename $(pwd))) +trylist=( ${trylist[*]} "default") + +echo trylist=${trylist[*]} + +for NEARESTPKG in ${trylist[*]}; do + if [ -z "$(get_pkg_ver $NEARESTPKG)" ]; then + TEMP=$(sortnames $CFGROOT/$NEARESTPKG-[0-9]* | tail -1) + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG.* | tail -1)} + TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1)} + #TEMP=${TEMP:-$(sortnames $CFGROOT/$NEARESTPKG | tail -1)} + [ "$TEMP" ] && NEARESTPKG=$(basename $TEMP) || continue + fi + + RADIX=$(get_pkg_radix $NEARESTPKG) + VER=$(get_pkg_ver $NEARESTPKG) + BUILD=$(get_build_num $NEARESTPKG) + NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + + #### [ "$(get_build_num $NEARESTPKG)" ] && + + [ -d "$CFGROOT/$NEARESTPKG" -o -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ] && break +echo NEARESTPKG=$NEARESTPKG + + ###TEMP=$(sortnames $CFGROOT/$NEARESTPKG-* | tail -1) + ###[ "$(get_build_num $TEMP)" ] && NEARESTPKG=$(basename $TEMP) && break +done + +RADIX=$(get_pkg_radix $NEARESTPKG) +VER=$(get_pkg_ver $NEARESTPKG) +BUILD=$(get_build_num $NEARESTPKG) +NEARESTPKG=${RADIX}${VER:+-$VER}${BUILD:+-$BUILD} + +echo "EXACTPKG=$EXACTPKG" +echo "NEARESTPKG=$NEARESTPKG" + +# to be removed ## look if there was an argument, in which case we would treat it as a package +# to be removed ## name (either source or destination, depending on the action). These variables +# to be removed ## are set : +# to be removed ## - ARGPKGFULL : full package name with version +# to be removed ## - ARGPKGRADIX : package radix name (without version) +# to be removed ## - ARGPKGVER : package version without -flx* +# to be removed ## - ARGDISTVER : package build version (flx*) +# to be removed # +# to be removed #if [ ${#ARGLIST[*]} -gt 0 ]; then +# to be removed # ARGPKGFULL=$(basename ${ARGLIST[0]}) +# to be removed # ARGPKGRADIX=$(get_pkg_radix $ARGPKGFULL) +# to be removed # ARGPKGVER=$(get_pkg_ver $ARGPKGFULL) +# to be removed # if echo $ARGPKGFULL | grep -q -- "-flx\." ; then +# to be removed # ARGDISTVER=$(get_build_num $ARGPKGFULL) +# to be removed # fi +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGFULL* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER-* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-$ARGPKGVER* |tail -1)} +# to be removed # ARGBASECFG=${ARGBASECFG:-$(sortnames $CFGROOT/$ARGPKGRADIX-* |tail -1)} +# to be removed #fi +# to be removed # +# to be removed ## look for package name from the '.flxver' link in current dir, then dir name +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # PKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # PKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #PKGRADIX=$(get_pkg_radix $PKGFULL) +# to be removed #PKGVER=$(get_pkg_ver $PKGFULL) +# to be removed # +# to be removed #if [ -z "$DISTVER" ] && echo $PKGFULL | grep -q -- "-flx\." ; then +# to be removed # DISTVER=$(get_build_num $PKGFULL) +# to be removed #fi +# to be removed # +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGFULL* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER-* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-$PKGVER* |tail -1)} +# to be removed #BASECFG=${BASECFG:-$(sortnames $CFGROOT/$PKGRADIX-* |tail -1)} +# to be removed # +# to be removed # +# to be removed # +# to be removed ## now process the destination parameters +# to be removed # +# to be removed #if [ -L .flxver ]; then +# to be removed # NEWPKGFULL=$(readlink .flxver) +# to be removed #else +# to be removed # NEWPKGFULL=$(basename $(pwd)) +# to be removed #fi +# to be removed # +# to be removed #NEWPKGRADIX=$(get_pkg_radix $NEWPKGFULL) +# to be removed #NEWPKGVER=$(get_pkg_ver $NEWPKGFULL) +# to be removed #NEWPKGVER=${NEWPKGVER:-$PKGVER} +# to be removed # +# to be removed #if [ -z "$NEWDISTVER" ] && echo $NEWPKGFULL | grep -q -- "-flx\." ; then +# to be removed # NEWDISTVER=$(get_build_num $NEWPKGFULL) +# to be removed #fi +# to be removed #NEWDISTVER=${NEWDISTVER:-$DISTVER} +# to be removed # +# to be removed ## recompute the new package version +# to be removed #NEWBASECFG=${NEWBASECFG:-$NEWPKGRADIX-$NEWPKGVER-$NEWDISTVER} +# to be removed # + + +# now this is rather simple : for nearly all actions, NEWPKGFULL is used as the +# directory name for the new package. If it cannot be found, all actions except +# info and newpkg will fail. So we have to do a newpkg before using a new dir. + +if [ ! -d "$CFGROOT/$NEARESTPKG" -a ! -f "$CFGROOT/$NEARESTPKG.$PKGSUFF" ]; then + echo "Config directory <$NEARESTPKG> (NEARESTPKG) does not exist, use 'newpkg' first." + exit 1 +fi + +# source configuration +ROOTDIR=${ROOTDIR:-$(pwd)/${INSTNAME}} + + +CURPKG=$NEARESTPKG +PKGRADIX=$(get_pkg_radix $NEARESTPKG) +PKGVER=$(get_pkg_ver $NEARESTPKG) +if echo $NEARESTPKG | grep -q -- "-flx\." ; then + DISTVER=$(get_build_num $NEARESTPKG) + NEARESTPKG=$PKGRADIX-$PKGVER-$DISTVER +else + DISTVER= + NEARESTPKG=$PKGRADIX-$PKGVER +fi + +CFGDIR=$CFGROOT/$CURPKG +CFGFILE=$CFGDIR/$PKGRADIX.$CFGSUFF + +echo "CFGFILE=$CFGFILE, PKGVER=$PKGVER, CFGDIR=$CFGDIR" + +exit 0 + + + +if [ -n "$CFGFILE" ]; then + CFGDIR=$NEWCFGROOT/$NEWBASECFG + . $CFGFILE +else + #CFGFILE=`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-$FLXARCH.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1` + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*-${DISTVER:-*}-*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack[-_]*.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + #CFGFILE=${CFGFILE:-`find $CFGROOT/ -name "$pack.$CFGSUFF"|sed -e "s/\.$CFGSUFF\$//"|sort|tail -1`} + CFGFILE=`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-${DISTVER:-*}-pkg"|sed -e "s/-pkg\$//"|sort|tail -1` + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type d -name "$pack[-_]*-pkg"|sed -e "s/-pkg\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-${DISTVER:-*}-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + CFGFILE=${CFGFILE:-`find $CFGROOT/ -maxdepth 1 -type f -name "$pack[-_]*-pkg.$PKGSUFF"|sed -e "s/-pkg\.$PKGSUFF\$//"|sort|tail -1`} + + # to be completed + + if [ -z "$CFGFILE" ]; then + echo "CFGFILE not found. Cannot continue." >&2 + exit 1 + fi + + if [ -d $CFGFILE ]; then + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + else + CFGROOT=`dirname $CFGFILE` + CFGDIR=`basename $CFGFILE`-pkg + CFGFILE=$CFGROOT/$CFGDIR/$pack.$CFGSUFF + if [ ! -e $CFGROOT/$CFGDIR ]; then + echo "Opening package $CFGROOT/$CFGDIR.$PKGSUFF into $CFGROOT/$CFGDIR..." + mkdir -p $CFGROOT/$CFGDIR && tar -C $CFGROOT/$CFGDIR -Uxpf $CFGROOT/$CFGDIR.$PKGSUFF + if [ $? != 0 ]; then + echo "There was an error during this operation. You may have to manually clean $CFGROOT/$CFGDIR. Cannot continue !" + exit 1 + else + echo "Done !" + fi + fi + fi + + if [ -e "$CFGFILE" ]; then + . $CFGFILE + else + echo "CFGFILE ($CFGFILE) not found. Cannot continue." >&2 + exit 1 + fi + fi + + if [ -z "$DISTVER" ]; then + if echo $CFGFILE | grep -q -- "-flx\." ; then + DISTVER=`echo $CFGFILE|sed 's/\(.*-\)\(flx.[0-9]\+\)\(.*\)/\2/'` + else + DISTVER='flx.1' + fi + fi + + echo $packver | grep -q -- "-flx\." + if [ $? != 0 ] ; then + packver=$packver-$DISTVER + fi + + echo $packver | grep -q -- "-$FLXARCH\$" + if [ $? != 0 ] ; then packver=$packver-$FLXARCH ; fi + + prefix=${packver%%[._-][0-9]*} + suffix=${packver#$prefix[._-]} + PKGVER=${suffix%-flx*} + PKGRADIX=$prefix + #echo "packver=$packver suffix=$suffix PKGVER=$PKGVER" + if [ -z "$DISTVER" ]; then + DISTVER=${suffix#$PKGVER-} + if [ "$DISTVER" = "$PKGVER" ]; then + DISTVER="flx.1" + else + DISTVER=${DISTVER%-*} + fi + fi + + case "$FLXARCH" in + i686) arch=i686 cpu=i686 basearch=i386 ;; + i486) arch=i486 cpu=i486 basearch=i386 ;; + i386) arch=i386 cpu=i386 basearch=i386 ;; + *) arch=i586 cpu=i686 basearch=i386 ;; + esac + + if [ -z "$FLXMAKE" ]; then + FLXMAKE=make + fi + + + if [ -z "${PATCH_LIST}" ]; then + PATCH_LIST=${CFGFILE%%.$CFGSUFF}.diff + if [ ! -e ${PATCH_LIST} ]; then + unset PATCH_LIST + fi + fi + + export DISTVER PKGRADIX PKGVER FLXMAKE PATCH_LIST FILE_LIST + + declare -f pre_$ACTION > /dev/null && ( pre_$ACTION ) + [ $? != 0 ] && exit $? + declare -f do_$ACTION > /dev/null && ( do_$ACTION ) + [ $? != 0 ] && exit $? + declare -f post_$ACTION > /dev/null && ( post_$ACTION ) + [ $? != 0 ] && exit $? + fi +fi + diff --git a/scripts/pkg-0.7.0 b/scripts/pkg-0.7.0 new file mode 100755 index 0000000..889a034 --- /dev/null +++ b/scripts/pkg-0.7.0 @@ -0,0 +1,1928 @@ +#!/bin/bash + +# pkg - Formilux package builder - version 0.7.0 - 2005-10-04 +# +# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau +# mailto: benoit@ant-computing.com,willy@ant-computing.com +# +# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) + +######## Please update this version ######## +PKG_VERSION=0.7.0 +############################################ + +## WARNING ## +# This version is not compatible with pkg scripts written for pre-0.2.0 versions + +# Usage: +# pkg [ pkg [ pkg2 ] ] +# +# pkg newpkg [ new_pkg [ old_pkg ] ] +# [new_pkg]=[old_pkg] +# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1 +# pkg newpkg apache apache-1.3 +# pkg newpkg bash +# pkg newpkg gcc gcc-3*flx*.1 +# +# pkg setpkg [ new_pkg ] +# ex: pkg setpkg openssl-0.9.6g-flx0.1 +# +# pkg { info | cat | edit | unpack } [ pkg ] +# ex: pkg info +# pkg info bash +# pkg edit modutils-2.4 +# pkg cat gzip-1.3 +# +# pkg { compile,build,prepack,strip,pack,delpack,release,clean }* +# +# pkg { patch | unpatch } [ patch_name ] +# +# pkg { any_command } [ any_args ] +# + +# don't return stupid names, and we also want dotfiles and use extended globbing +shopt -s nullglob +shopt -s dotglob +shopt -s extglob + +# disable pathnames expansion +set -o noglob + +# change the default mask to avoid common security problems +umask og-w + +# set some constants +KERNDIR=${KERNDIR:-/usr/src/linux} +FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')} +FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)} +FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS} + +# FLXTARGARCH can be influenced by FLXARCH if defined +FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS} +FLXTARGARCH=${FLXTARGARCH:-$FLXARCH} +FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH} +FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS} +FLXARCH=${FLXARCH:-$FLXTARGARCH} + +DEVROOT=${DEVROOT:-/var/flx-dev} +PKGROOT=${PKGROOT:-/var/flx-pkg} +# use -p1 by default to apply a patch +PATCH_LEVEL=${PATCH_LEVEL:-1} +# the suffix that we use to name different builds. It also matches build +# versions with this name followed by a number (BUILDVER) +BUILDSFX=${BUILDSFX:-flx} +BUILDVER=${BUILDVER:-0} + +PKGSUFF="tgz" +CFGSUFF="cfg" +INSTNAME=".flxdisk" +LINKNAME=".flxpkg" + +FIND_CMD=pkgfilefind +CURDIR="$(pwd)" + +FILE_LIST= + +# all the directories that should be ignored by do_pack +EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm ) + +###### +###### here are some undertermined type functions +###### + +# check that this utility's version is at least as high as the version +# specified in $1. Returns 0 if OK, 1 if inferior. + +function check_pkg_version { + local version="$1" + local major minor patch + local mymajor myminor mypatch + + major=${version%%.*} + minor=${version#$major.}; minor=${minor%%.*} + patch=${version##*.} + + mymajor=${PKG_VERSION%%.*} + myminor=${PKG_VERSION#$mymajor.}; myminor=${myminor%%.*} + mypatch=${PKG_VERSION##*.} + + if [ -n "$major" ]; then + [ "$mymajor" -gt "$major" ] && return 0 + [ "$mymajor" -lt "$major" ] && return 1 + else + return 0 + fi + + if [ -n "$minor" ]; then + [ "$myminor" -gt "$minor" ] && return 0 + [ "$myminor" -lt "$minor" ] && return 1 + else + return 0 + fi + + if [ -n "$patch" ]; then + [ "$mypatch" -gt "$patch" ] && return 0 + [ "$mypatch" -lt "$patch" ] && return 1 + else + return 0 + fi + return 0 +} + + +# find packageable files (that can't be automaticaly created) and return only +# their relative path to the argument. + +function pkgfilefind { + local start=${1%%/} + local dir + local -a exclude_args=( ) + + for dir in "${EXCLUDE_LIST[@]}"; do + exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" ) + done + + find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n" +} + + +# resolves a symlink to an absolute location. +# usage: resolve_link +function resolve_link { + # prints $1 if $2 is empty, and prints $2 if it starts with a '/'. + if [ -z "$2" ]; then + dir="$1" + elif [ -z "${2##/*}" ]; then + dir="$2" + else + dir="$1/$2" + fi + + # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right, + # then enclose with '/' + while [ -n "$dir" ]; do + if [ -z "${dir##./*}" ]; then dir="${dir#./}" + elif [ -z "${dir##/*}" ]; then dir="${dir#/}" + elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}" + elif [ -z "${dir%%*/}" ]; then dir="${dir%/}" + elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}" + elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}" + else + dir="/$dir/" + break; + fi + done + + # now resolve '/../' from left to right only. + while [ -z "${dir##*/../*}" ]; do + # if dir goes past root, we must truncate it + if [ -z "${dir##/../*}" ]; then + dir="/${dir##/../}" + else + # turn all '/x/../' into '/' + odir="$dir" + dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')" + [ "$dir" = "$odir" ] && break + fi + done + + [ "$dir" = "/" ] || dir="${dir#/}" + [ "$dir" = "/" ] || dir="${dir%/}" + echo "$dir" +} + +# this function analyses an ELF executable and prints its name along with some +# informations such as : +# %N:soname : for libraries, their soname +# %D:libname : library it depends on (their soname) +# %P:provide : feature provided by a library, in the form soname/version +# %R:require : required feature, in the for soname/version +function elf_get_dep { + local elf + for elf in "$@"; do + $OBJDUMP -p "$elf" | ( + soname_str="" + soname="" + needed="" + provide="" + require="" + curreq="" + section="" + while read; do + case "$REPLY" in + Dynamic\ Section*) + section="dynamic" ;; + Version\ defin*) + section="definitions" ;; + Version\ Refer*) + section="references" ;; + *) + set -- $REPLY + if [ "$section" = "dynamic" ]; then + if [ "$1" = "NEEDED" ]; then + needed="${needed:+$needed }%D:$2" + elif [ "$1" = "SONAME" ]; then + soname="$2" + soname_str="${soname_str:+$soname_str }%N:$2" + fi + elif [ "$section" = "definitions" ]; then + if [ "$#" = "4" -a "$2" = "0x00" ]; then + provide="${provide:+$provide }%P:$soname/$4" + fi + elif [ "$section" = "references" ]; then + if [ "$#" = "3" -a "$1" = "required" ]; then + curreq="${3%:}" + elif [ "$#" = "4" ]; then + require="${require:+$require }%R:$curreq/$4" + fi + fi + ;; + esac + done + echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}" + ) + done + return 0 +} + + +###### +###### here are some functions for manipulating package names +###### + +# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg' +function get_pkg_radix { + echo ${1%%[-_][0-9]*} +} + +# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a' +function get_pkg_ver { + local ver=${1#${1%%[_-][0-9]*}[._-]} + ver=${ver%-${BUILDSFX}*} + [ "$ver" = "$1" ] || echo $ver +} + +# returns the build number from a package name when appropriate, or empty when +# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12' +function get_build_num { + local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg + build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12 + build=${build#-} # flx0.12 + [ "$build" != "$1" ] && echo $build +} + +# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13' +function get_next_build { + local prefix=${1%%.*} + local suffix=${1##*.} + echo $prefix.$[$suffix + 1] +} + +# This function accepts a list of versionned names, and returns them sorted by +# version number. The names must NOT contain any '|' or '~' character, or they +# will be discarded. Names that don't have any version are also discarded. +# Note: package names can be full path names. +function sortnames { + local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION + local base version rest filename i t file flist + local -a list + + # a numeric versions consists in a series of numbers delimited by dots, and + # optionnally ending with one or several dots, so that strange namings are + # correctly processed. An alphanumeric version consists in everything that + # cannot match a numeric version, optionnaly ending with one or more dots. + IFS=$'\n' + FIELD='\([^|]*\)' + NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)' + ALPHA_VERSION='\([^0-9~|.]\+[.]*\)' + VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)" + + # make the list appear in the form 'package|version|rest|full_name' + list=($(echo "$*" | grep -v "|~" | sed -e "s,$VERSION,\1|," \ + -e "s,^$FIELD|$VERSION,\1|\2|," \ + -e "s,^$FIELD|$FIELD|$FIELD$,\1|\2|\3~\1\2\3," \ + -e "s,^[^|]*|[^|]*$,," \ + -e 's,^[^|]*/,,')) + + # there's a risk that it doesn't complete for all the list, and that some + # elements keep a "rest". But what can we do about it ? + + # we loop on the list if there's at least one element + # this will build alternating series of numeric-only and non-numeric + # substrings, packed by six. + while [ "${list[0]}" ] ; do + # now we add sub-version delimiters ',' + list=( $(for file in ${list[*]} ; do + IFS="|~" ; set -- $file + base=$1 ; version=$2 ; rest=$3 ; filename=$4 + if [ -z "$rest" ] ; then + IFS="." ; set -- $version + # we append a dot to the version for sed below. + echo "$base,$1,$2,$3,$4,$5,$6|.~$filename" + continue + fi + IFS="." ; set -- $version + echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename" + done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/")) + IFS=$'\n' + # and we stop once everyone has "|\.|~" (no rest) + if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi + done + + # now construct a field separator list for 'sort'. Since it's full of bugs, + # the only way for it to work is -k1,1 -k2,2n -k3,3n ... + # To match most cases, we'll assume that most of our packages will be + # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating). + IFS=',' ; i=1 ; flist= + for t in ${list[0]%%|*} ; do + if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then + flist="$flist${flist:+ }-k$i,$i" + else + flist="$flist${flist:+ }-k$i,$i"n + fi + i=$[$i+1]; + done + + IFS=$'\n'$'\t'' ' + # Do not use '-u' since sort is stupid enough to remove nearly identical + # lines ! + #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~ + echo "${list[*]}" | sort -t , $flist | cut -f2 -d~ +} + + +###### +###### here are some "exported" functions used to ease file manipulation +###### + +# +# usage: set_perm uid:gid mode file... +function set_perm { + local own mode + [ $# -gt 2 ] || return 1 + own=$1 ; shift + mode=$1 ; shift + chown $own "$@" + chmod $mode "$@" + return 0 +} + +# +# usage: set_default_perm $ROOTDIR/start_dir +function set_default_perm { + local start_dir=$1 + local strip_dir=${ROOTDIR%%/} + local type executable script + + if [ -z "$1" ]; then + echo; echo "### ERROR! set_default_perm called without arguments !!!" + echo "### You must specify the root directory to fix." + return 1 + fi + + echo + echo "PKG : Fixing permissions in $1 ... " + echo " Please wait..." + echo " Fixing directories..." + + # first pass : check directories + find $start_dir -type d | while read; do + case "${REPLY##$strip_dir}" in + /|/.) + set_perm root:root 755 "$REPLY" + ;; + /sbin|/sbin/init.d|/usr/sbin) + set_perm root:adm 751 "$REPLY" + ;; + /root) + set_perm root:root 700 "$REPLY" + ;; + /etc/formilux|/var/core) + set_perm root:adm 750 "$REPLY" + ;; + *) + if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then + set_perm root:root 755 "$REPLY" + fi + ;; + esac + done + + echo " Fixing special files..." + # second pass : check special files (block, char, fifo) + find $start_dir -not -xtype d -a -not -xtype f | while read; do + if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then + set_perm root:root 600 "$REPLY" + fi + done + + echo " Fixing regular files..." + # third pass : check regular files + find $start_dir -type f | while read; do + if [ -u "$REPLY" -o -g "$REPLY" ]; then + # remove other r/w on setuid/setgid + chmod o-rw "$REPLY" + else + type=$(file -z "$REPLY") + executable=0 + script=0 + + if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \ + -z "${type//*ERROR: Corrupt*/}" ]; then + executable=1 + elif [ -z "${type//*script*/}" ]; then + script=1 + fi + + #echo "processing ${REPLY##$strip_dir}" + case "${REPLY##$strip_dir}" in + /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*) + if [ $executable -gt 0 ]; then + set_perm root:adm ug-w,o-rw "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm ugo-w "$REPLY" + else + set_perm root:adm ugo-w "$REPLY" + fi + ;; + /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*) + if [ $executable -gt 0 ]; then + set_perm root:adm u-sw,g-wx,o-rwx "$REPLY" + elif [ $script -gt 0 ]; then + set_perm root:adm u-sw,g-swx,o-rwx "$REPLY" + else + # neither an exec nor a script, no need to execute it ! + set_perm root:adm ug-swx,o-wx "$REPLY" + fi + ;; + /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\ + /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*) + set_perm root:adm ug-sw,o-w,+x "$REPLY" + ;; + /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao]) + set_perm root:adm ugo-swx "$REPLY" + ;; + /etc/profile.d/*.var) + set_perm root:adm 0644 "$REPLY" + ;; + /etc/profile.d/*) + set_perm root:adm 0755 "$REPLY" + ;; + /boot/*/*|/boot/*|/etc/*/*) + set_perm root:adm ug-swx,o-rwx "$REPLY" + ;; + /etc/*) + set_perm root:adm ugo-swx "$REPLY" + ;; + /*/man/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*) + set_perm root:man ugo-swx "$REPLY" + ;; + /usr/share/examples/*|/usr/share/examples/*/*) + set_perm root:man ugo-swx "$REPLY" + ;; + *) + # chgrp adm if not setgid and group==root + # chmod ugo-w if user==root + ;; + esac + fi + done + echo "PKG : done fixing permissions." +} + +###### +###### here are "exported" functions, which can be used and redefined by build.cfg +###### + +# builds everything from a clean start +function do_build { + local ACTION + # ACTION will be inherited by other functions + for ACTION in clean compile prepack strip pack ; do + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + done + return 0 +} + +# this function returns one exact package name from a list of potentially +# interesting ones, classed from higher preference to lower. They are all +# passed as strings, constituting packages names, or some of the following +# special names : +# %P => use current directory as the source for the name +# %L => use the package pointed to by the ${LINKNAME} link +# %D => use the default package +# If several packages match a given pattern, the user is asked to select the +# desired one. +# The resulting package name is returned in REPLY, and the package directoryy +# is returned in PKGDIR whenever possible. +function get_name { + local pattern pkg_name + local radix ver build + local -a rel_list dev_list sort_list + local i search_dir + + REPLY= + for pattern in $*; do + search_dir= + if [ "$pattern" = "%P" ]; then + search_dir="${CURDIR%/*}" ; search_dir="/${search_dir#/}" + pattern="$(basename $CURDIR)" + elif [ "$pattern" = "%L" ]; then + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + return + elif [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then + # the link is always an EXACT name, so we return it as-is. + pattern="$(readlink ${LINKNAME})" + PKGDIR="$pattern/." + REPLY="${pattern##*/}" + return + else + continue + fi + elif [ "$pattern" = "%D" ]; then + pattern=default + fi + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + + REPLY= + # we loop until pkg_name is empty, which allows recursive choices. + while [ "$pkg_name" ]; do + # now we'll try to build a list of potentially matching packages for + # each pattern. We'll reduce the original name until either we have + # a non-empty list or the package name is void. + rel_list=( ); dev_list=( ) + while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do + rel_list=( $(find ${search_dir:+$search_dir/} $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + if [ "$release_only" != "1" ]; then + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) ) + fi + + if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then + radix=$(get_pkg_radix $pkg_name) + ver=$(get_pkg_ver $pkg_name) + build=$(get_build_num $pkg_name) + + if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then + if [ "$build" -a "$build" != "*" ]; then + pkg_name=${radix}-${ver}-* + elif [ "${ver%.*}" != "$ver" ]; then + # let's reduce the version precision + pkg_name=${radix}-${ver%.*}-* + else + pkg_name=${radix}-* + fi + else + break + fi + else + break + fi + done + + # we're prepared to break the big loop, unless someone sets pkg_name again. + pkg_name= + sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) ) + + # if we matched nothing, we jump to the next pattern, and if we matched + # exactly one result, we return it immediately. + if [ ${#sort_list[*]} -eq 0 ]; then + continue + elif [ ${#sort_list[*]} -eq 1 ]; then + REPLY="${sort_list[0]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + + # now, we'll present the possible names to the user. + i=0 + printf " %5d : - None of the following packages -\n" 0 + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, or a 'D' for dev. + # FIXME : we risk a wrong match here (eg: flx0.1 <-> flx0.10) + if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + echo + + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + # empty string, we use the last choice which is the preferred one. + i=${#sort_list[*]} + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll allow to recursively re-select + #pattern=${pattern}*${i} + pattern=${i} + radix=$(get_pkg_radix $pattern) + ver=$(get_pkg_ver $pattern) + build=$(get_build_num $pattern) + pkg_name=${radix:-*}-${ver:-*}-${build:-*} + break; + elif [ $i -le 0 ]; then + # if the user explicitly replied "0", then he wants other choices. + break; + elif [ $i -le ${#sort_list[*]} ]; then + REPLY="${sort_list[$[$i-1]]}" + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" + return + fi + done + # we get here only either if someone tries to refine the package name or + # if he refuses these ones. + done + done + PKGDIR="${REPLY/*}" + REPLY="${REPLY##*/}" +} + +# choose a package and make ${LINKNAME} point to it +function do_setpkg { + rm -f ${LINKNAME} + ln -s $PKGDIR ${LINKNAME} +} + + +# look for existing packages, and propose a new version for the current one +function do_newpkg { + local -a rel_list dev_list sort_list + local pkg_name new_name + local radix ver build + + set -o noglob + if [ -e ${LINKNAME} ]; then + if [ -L ${LINKNAME} ]; then + if [ -d ${LINKNAME}/. ]; then + echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually." + exit 1 + else + rm -f ${LINKNAME} + fi + else + echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually." + exit 1 + fi + fi + + if [ $# -gt 0 ]; then + # the user has specified an explicit version string + # either it's the complete name, or it's the complete name followed + # by an '=' sign preceding the old name. + new_name=${1%%=*} + if [ $# -gt 1 ]; then + pkg_name=$2 + elif [ "$new_name" != "$1" ]; then + pkg_name=${1##*=} + fi + fi + + if [ -z "$new_name" ]; then + # the user has not specified any version string, we'll use the directory + # name. + new_name=$(basename $CURDIR) + fi + + rel_list=( ); dev_list=( ) + + # now we'll have to guess the new package name. + # The build rev part (flx*.*) will be ignored. + # We'll look for existing packages with the exact + # name+version, and if found, use this + the first unused build number. + # If not found, a new package is created with the exact name and flx0.1 + + radix=$(get_pkg_radix $new_name) + ver=$(get_pkg_ver $new_name) + build=$(get_build_num $new_name) + new_name=${radix:-*}-${ver:-*} + + rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) ) + sort_list=(${rel_list[*]} ${dev_list[*]}) + + if [ "${sort_list[*]}" ]; then + sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) ) + sort_list=( $(sortnames ${sort_list[*]}) ) + if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \ + ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then + # if the package was properly named, and not already listed, let's + # propose it on last position. + sort_list=( ${sort_list[*]} $new_name ) + fi + # echo "package_list : ${sort_list[*]}" + + # now, we'll present the possible names to the user + if [ ${#sort_list[*]} -gt 1 ]; then + local i=0 + echo; echo ">>> Please select the name of the package to create :";echo + while [ $i -lt ${#sort_list[*]} ]; do + # we'll display an 'R' in front of released names, 'P' + # in front of packaged ones, or a 'D' for dev. + if [ -e "${sort_list[$i]}/RELEASED" ]; then + printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/} + elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then + printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]##*/} + else + printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/} + fi + i=$[$i+1] + done + + echo + while : ; do + echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i + if [ -z "$i" ]; then + new_name=${sort_list[${#sort_list[*]}-1]} + break + elif [ "${i//[0-9]/}" ]; then + # not a plain integer, we'll take it for the new name + new_name=$i + break; + elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then + new_name=${sort_list[$[$i-1]]} + break; + fi + done + else + new_name=${sort_list[0]} + fi + # we'll search for all packages starting with the same name and version + # in both release and dev dirs. Then we'll be able to deduce the latest + # build number used. + #sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) ) + sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%p\n" 2>/dev/null|sort -u) ) + if [ ${#sort_list[*]} -eq 0 ]; then + # this can happen with new BUILDSFX/BUILDVER + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + else + sort_list=( $(sortnames ${sort_list[*]} )) + new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]})) + fi + else + if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then + echo "Error: no existing package matches $new_name, and wildcards" + echo "or incomplete names cannot be part of a real name." + exit 1 + fi + # we keep new_name since it's syntactically correct + new_name=${new_name}-${BUILDSFX}${BUILDVER}.1 + fi + + #echo "new_name: $new_name" + + # if pkg_name is unspecified, we'll use the current directory name to guess + # the source package, else we'll use the explicit name + echo; echo ">>> Please select the package to use as a reference :"; echo + + get_name $pkg_name $new_name %P %D + + if [ -z "$REPLY" ]; then + echo "No reference package found (even default). Please specify one." + exit 1 + fi + + echo "Using '$REPLY'." + + if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then + pkg_name=$PKGROOT/$REPLY + else + pkg_name=$DEVROOT/$REPLY + fi + + # new_name is always relative to DEVROOT + #echo "new_name: $new_name ; old_name: $(basename $pkg_name)" + + # we should verify that new_name/released doesn't exist before extracting + # anything into it, or even that new_name doesn't exist at all. + new_name=$DEVROOT/$new_name + if [ -e $new_name ]; then + echo "Error! new directory $new_name already exists. Refusing to overwrite." + exit 1 + fi + + rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \ + tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \ + --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \ + --exclude='./Version' --one-file-system -cpf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME}) + chmod u+rw $new_name/build.cfg + + echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'." + echo "The link '${LINKNAME}' now points to it." + echo + if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then + echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***" + echo + fi + set +o noglob + return 0 +} + + +function do_edit { + if [ -e "$PKGDIR/RELEASED" ]; then + echo "Editing $CFGFILE in read-only mode..." + vi -R $CFGFILE + else + echo "Editing $CFGFILE..." + vi $CFGFILE + fi +} + +function do_cat { + cat $CFGFILE +} + +function do_lst { + local FPNAME + + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + cat $FPNAME.lst +} + +function pre_info { + echo "Information for package '${EXACTPKG##*/}' (\${EXACTPKG##*/}) :" + + echo " Package name : $PKGRADIX (\$PKGRADIX)" + echo " Package version : $PKGVER (\$PKGVER)" + echo " Distrib version : $DISTVER (\$DISTVER)" + echo -n " Config. file : " + if [ -e $CFGFILE ]; then + echo "$CFGFILE" + else + echo "none found." + fi + echo " Package file : $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF" + echo -n " Package size : " + if [ -e $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF ]; then + echo "$(du -b $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF |cut -f1) bytes." + else + echo "does not exist yet." + fi + if [ -n "${PATCH_LIST}" ]; then + echo " Patches list : ${PATCH_LIST}" + else + echo " Empty patch list." + fi + + if [ -e "$PKGDIR/ChangeLog" ]; then + echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)" + else + echo " No ChangeLog." + fi + + if [ -e "$PKGDIR/RELEASED" ]; then + echo " Tagged as RELEASED" + else + echo " UNRELEASED." + fi + + return 0 +} + +# does only compile, not changing the current config +function do_compile_only { + $FLXMAKE + return $? +} + +# new simplified name for 'config_only', which is deprecated, not changing current scripts. +function do_config { + if declare -f do_config_only >/dev/null 2>&1; then + do_config_only + return $? + else + return 0 + fi +} + +# configures and compiles +function do_compile { + ( do_config ) && ( do_compile_only ) +} + +# preparatory work for prepack() +function pre_prepack { + if [ "$UID" != "0" -a "$force" != "1" ]; then + echo "You must specify '--force' to install as non-root" + exit 1 + fi + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + # permissions are important here because we don't want to get an + # inherited setgid or something alike on the root dir + [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chown 0:0 $ROOTDIR; chmod 0755 $ROOTDIR; } + #mkdir -p "$EXAMPLEDIR" + return 0 +} + +# build link in /opt directory +# INPUT: selected path to creation in /opt +function build_opt { + local dir + + if [ -d $ROOTDIR/opt ] ; then ( + [ $# = 0 ] && set -- bin sbin lib + set +o noglob + shopt -s nullglob + cd $ROOTDIR/opt + for dir in $* ; do + mkdir $dir + dirs=( */$dir ) + [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n" + done + ) fi + return 0 +} + +# deletes the current prepack directory. +function do_delpack { + # WARNING! here, we don't use $ROOTDIR because we don't want to risk + # erasing a wrong directory as root ! + [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}" + return 0 +} + +# does a full clean +function do_clean { + make distclean || make mrproper || make clean + ( do_delpack ) + return 0 +} + +# applies all the patches to the current sources +# files which match *.rej and *~ will be deleted +function do_patch { + local i + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL + else + patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# reverts all the patches from the current sources +# files which match *.rej and *~ will be deleted +function do_unpatch { + local i + local UNPATCH_LIST="" + + find . -name '*.rej' -o -name '*~' | xargs rm -f + + for i in ${PATCH_LIST}; do + UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} ) + done + + for i in ${UNPATCH_LIST[@]}; do + [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz" + if [ -z "${i##*.gz}" ]; then + gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL + else + patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i + fi + done + + if [ -z "$(find . -name '*.rej')" ]; then + find . -name '*~' | xargs rm -f + fi + return 0 +} + +# extracts a binary package into $ROOTDIR, to reflect the state prior to pack(). +function do_unpack { + local FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF + mkdir -p $ROOTDIR + cd $ROOTDIR + + echo -n "Extracting $FILE into $ROOTDIR ... " + tar zUxpf $FILE >/dev/null 2>&1 + echo "done." + return 0 +} + +# strips symbols from executables before building the package. +# Abort if ROOTDIR doesn't exist (thus needing prepack() first). +function do_strip { + if [ ! -d $ROOTDIR ] ; then + echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'." + exit 1 + fi + #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped + find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1 + return 0 +} + +# forces pack() to strip before starting, even if do_pack() is redefined by the user. +function pre_pack { + # in the mean time, we avoid removing this directory since it could have + # been brought legally by an authorized package. + #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null + ( do_strip ) + return 0 +} + +# this function finds perl dependencies for a given file. +# It's only called from _do_pack_files() and do_pack() +function get_perl_depend { + local filename=$1 + local dep DEP + local DEP_FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.dep + + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ + sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ + -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ + sed 's@::@/@g') + if [ "x$DEP" != "x" ] ; then + echo -n "$filename" >> $DEP_FILE + for dep in $DEP ; do + if [ "x${dep/*.*}" != "x" ] ; then + echo -n " $dep.pm" >> $DEP_FILE + else + echo -n " $dep" >> $DEP_FILE + fi + done + echo >> $DEP_FILE + fi +} + +# same as pack, except that it uses files in the current directory as the root +# entries, and that no strip, link nor compression is performed. +# Only entries listed in the files pointed to by $* find their way to the archive. +# This function relies on get_perl_depend(). +function _do_pack_files { + local DEP_FILE FPNAME ext + local FILE_LIST=$* + + echo -n "Updating timestamps ... " + find . -not -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + echo -n "Creating $DEP_FILE ... " + touch $DEP_FILE + ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + # we try the special case of the '.' entry which is needed to set the root permissions. + # this entry must be set as "." in FILE_LIST. + if grep -q '^.[ ]' $FILE_LIST; then + set -- $(grep '^.[ ]' $FILE_LIST) + owner=${2%%:*} + group=${2##*:} + echo "d $3 $owner $group 0 -------------------------------- 0 ." + fi > $FPNAME.lst + (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + + # we want everything, including directories. + cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# packs the prepacked files into a new file located in $DEVROOT. +# any eventual old package is removed. +# this function relies on _do_pack_files(), get_perl_depend(), +function do_pack { + local DEP_FILE FPNAME + local FILE_LISTS ext + + # normalize the list with an absolute path for each entry + for file in $FILE_LIST ; do + if [ -z "${file##/*}" ]; then + FILE_LISTS="$FILE_LISTS $file" + else + FILE_LISTS="$FILE_LISTS $CURDIR/$file" + fi + done + # FIXME: is this normal ??? + if [ ! -d "$ROOTDIR" ] ; then + echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR" + exit 1 + fi + cd $ROOTDIR + + # use the file list when available + if [ "$FILE_LISTS" ]; then + _do_pack_files $FILE_LISTS + return $? + fi + +## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \ +## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \ +## ldconfig -nr . ) > /dev/null 2>&1 + + echo -n "Updating libraries ... " + ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1 + echo "done." + + echo -n "Updating timestamps ... " + find . ! -type l | xargs touch -m + echo "done." + + # full path name of different files + FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH + DEP_FILE=$FPNAME.dep + + # rebuild dependencies file, first is a diff file + echo -n "Creating $DEP_FILE ... " + rm -rf $DEP_FILE + if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi + + # build a one shot function 'add' to add dependences + oldadd="$(declare -f add)" + # usage: add file [...] need file [...] + function add { + local file files + # remove file + while [ $# -gt 0 -a "x$1" != xneed ] ; do + files=( "$1" "${files[@]}" ) + shift + done + [ $# -le 1 ] && return + shift + for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done + } + # load dependences function + declare -f load_deps > /dev/null && ( load_deps ) + # reset 'add' function + unset add + # reload old one + [ -n "$oldadd" ] && eval "$oldadd" + + touch $DEP_FILE + find . \( -type f -o -type l \) -printf "%P\n" | while read ; do + case $REPLY in + *.pm|*.pl|*.ph) + get_perl_depend $REPLY + ;; + */man/man*/*.[0-9n]) + if [ "${REPLY/*gz}" ] ; then + if [ -L $REPLY ] ; then + LINK=$(readlink $REPLY) + rm $REPLY + ln -s $LINK.gz $REPLY.gz + else + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + fi + echo "$REPLY \$MAN" >> $DEP_FILE + ;; + */info/*.info|*/info/*.info-[0-9]*) + if [ "${REPLY/*gz}" ] ; then + gzip -f -9 $REPLY + chmod 644 $REPLY.gz + fi + echo "$REPLY \$INFO" >> $DEP_FILE + ;; + bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*) + flr="$(file $REPLY)" + case "$flr" in + *\ shell\ *) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE + ;; + *perl\ commands*) + echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE + get_perl_depend $REPLY + ;; + *:\ symbolic\ link*) + echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + *\ ELF\ [0-9][0-9]-bit\ *shared\ object*) + elf_get_dep $REPLY >> $DEP_FILE + ;; + esac + ;; + esac + done + echo "done." + + echo -n "Creating $FPNAME.lst ... " + ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1 + echo "done." + + echo -n "Creating $FPNAME.$PKGSUFF ... " + # we want everything, and directories only if they're empty. + # All this without './' we shouldn't get an empty line since . + # should contain at least what we want to tar ! + $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null + + # create shortcuts ".*" for tgz, dep and lst files + for ext in dep lst tgz; do + rm -f $PKGDIR/.$ext + ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext + done + echo "done." + return 0 +} + + +# this function prepares all needed variables to work in a cross-compiler environment +function set_cross_environment { + # Handling of cross-compilers : + # - setting CC will force both HOSTCC and FLXCROSSCC + # - setting HOSTCC will keep it + # - setting FLXCROSS will set CC + # - setting FLXCROSSCC will set CC whatever FLXCROSS is. + + if [ -z "$FLX_CROSS_OPT_SET" ]; then + CC=${CC:-gcc} + CXX=${CXX:-g++} + AS=${AS:-as} + LD=${LD:-ld} + AR=${AR:-ar} + NM=${NM:-nm} + RANLIB=${RANLIB:-ranlib} + STRIP=${STRIP:-strip} + OBJDUMP=${OBJDUMP:-objdump} + + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTAS=${HOSTAS:-$AS} + HOSTLD=${HOSTLD:-$LD} + HOSTAR=${HOSTAR:-$AR} + HOSTNM=${HOSTNM:-$NM} + HOSTSTRIP=${HOSTSTRIP:-$STRIP} + HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP} + + if [ -n "$FLXCROSS" ]; then + CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC} + CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX} + AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} + LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} + AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} + STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} + OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} + fi + # specify that we don't want to do this again + FLX_CROSS_OPT_SET=1 + fi +} + +# this function sets all needed compiler options +function set_compiler_options { + # now we'll set default ARCH and CPU for the current FLXARCH if none is set. + case "$FLXARCH" in + i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;; + i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;; + i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;; + parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;; + sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;; + sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;; + ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;; + esac + + # FIXME: this should go into a per-architecture file + case "$FLXARCH" in + *86) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="i586" + FLX_ARCH_SMALL="$basearch" + GCC_ARCH_CURRENT="-march=$arch" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mcpu=$cpu" + GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON" + GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + + parisc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}" + FLX_ARCH_COMMON="1.0" + FLX_ARCH_SMALL="1.0" + GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT" + GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON" + GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL" + GCC_CPU_CURRENT="-mschedule=7100LC" + GCC_CPU_COMMON="-mschedule=7100" + GCC_CPU_SMALL="-mschedule=7100" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + sparc*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + ev[456]*) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_ARCH_CURRENT="-mcpu=$arch" + GCC_ARCH_COMMON="-mcpu=$arch" + GCC_ARCH_SMALL="-mcpu=$arch" + GCC_CPU_CURRENT="-mtune=$cpu" + GCC_CPU_COMMON="-mtune=$cpu" + GCC_CPU_SMALL="-mtune=$cpu" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + ;; + + *) + CC=${CC:-gcc} + CXX=${CXX:-g++} + FLX_ARCH_CURRENT="$FLXARCH" + FLX_ARCH_COMMON="$FLXARCH" + FLX_ARCH_SMALL="$FLXARCH" + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -malign-jumps=0" + GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + GCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + GCC_OPT_FAST="-O2 -fno-align-jumps" + GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + case "$FLXHOSTARCH" in + *86) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + parisc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + sparc*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + ev[456]*) + HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST" + HOSTCC_OPT_FAST="$GCC_OPT_FAST" + HOSTCC_OPT_SMALL="$GCC_OPT_SMALL" + ;; + + *) + HOSTCC=${HOSTCC:-$CC} + HOSTCXX=${HOSTCXX:-$CXX} + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -malign-jumps=0" + HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0" + if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then + HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer" + HOSTCC_OPT_FAST="-O2 -fno-align-jumps" + HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels" + fi + ;; + esac + + export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL + export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG + export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL + export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL + export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL + export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL + + return 0 +} + +# displays used environment variables +function print_env { + set_cross_environment + set_compiler_options + for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \ + FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \ + FLXCROSS FLXTOOLDIR FLXROOTDIR \ + AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \ + GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \ + GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \ + GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \ + HOSTCC HOSTCXX \ + HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \ + FLXMAKE FLXPMAKE; do + echo "$i=$(eval echo \$$i)" + done + exit 0 +} + +function usage { + # this is needed to present current options to the user + set_cross_environment + set_compiler_options + + echo "PKG version $PKG_VERSION - Formilux package build utility." + echo "Usage:" + echo " pkg [-options]* [ pkg [ pkg2 ] ]" + echo + echo " pkg newpkg [ new_pkg [ old_pkg ] ]" + echo " pkg newpkg [ newpkg ]=[ old_pkg ]" + echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1" + echo " pkg newpkg =apache-1.3" + echo " pkg newpkg bash" + echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1" + echo + echo " pkg setpkg [ new_pkg ]" + echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1" + echo + echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]" + echo " ex: pkg info" + echo " pkg info bash" + echo " pkg edit modutils-2.4" + echo " pkg cat gzip-1.3" + echo + echo " pkg { clean | compile | config | compile_only | build }*" + echo " pkg { prepack | strip | pack | delpack | release }*" + echo + echo " pkg { patch | unpatch } [ patch_name ]" + echo + echo " pkg { any_command } [ any_args ]" + echo + echo "User variables are :" + echo "PKGROOT : directory containing released packages <$PKGROOT>" + echo "DEVROOT : directory containing unreleased packages <$DEVROOT>" + echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>" + echo "FLXARCH : architecture to use for the package, <$FLXARCH>" + echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>" + echo + echo "Architecture-specific variables :" + echo -e " CURRENT\t|COMMON\t|SMALL" + echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL" + echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL" + echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL" + echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST" + echo "GCC_OPT_FAST=$GCC_OPT_FAST" + echo "GCC_OPT_SMALL=$GCC_OPT_SMALL" + echo + echo "Use pkg --env to get all variables." + +# Those two are not user-settable anymore +# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>" +# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)" + exit 1 +} + +# displays usage +function do_help { + usage + return 0 +} + +# creates a new changelog entry and prompts the user to add information. +function do_changelog { + # Let's create a new changelog entry + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t* '; echo ''; echo '.' ; + echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + + # we'll ask the user to fill the changelog + vi -c ":3" $PKGDIR/ChangeLog + return 0 +} + +# marks the current package as released +function do_release { + local last_pkg + + echo "#####################################################" + echo "# Release command not implemented yet ! Aborting... #" + echo "#####################################################" + #exit 1 + # some important checks before things get wrong + if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then + echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !" + exit 1 + fi + + if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then + echo "Nothing to be released in this package." + echo "Please ensure that .lst, .dep and .tgz exist." + exit 1 + fi + + # first, the destination directory must not exist + if [ -d "$PKGROOT/${EXACTPKG##*/}" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/RELEASED" ]; then + echo "Error: This package already exists." + else + echo "Error: The package directory $PKGROOT/${EXACTPKG##*/} already exists." + fi + exit 1 + fi + + # identify last changelog entry + last_pkg="" + if [ -e "$PKGDIR/ChangeLog" ]; then + last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog") + last_pkg=${last_pkg##*released } + fi + + if [ "$last_pkg" != "$EXACTPKG" ]; then + # Let's create a new changelog entry + touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist + (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME"; + echo ''; echo $'\t'"* released $EXACTPKG"; + echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null + fi + + # we'll ask the user to fill the changelog + vi -c ":4" $PKGDIR/ChangeLog + +# +#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi +# + + if ! mv $PKGDIR $PKGROOT/ ; then + echo "Error: cannot move the package to the released directory. Cancelling." + # the mv here fails atomically, so nothing's lost in PKGDIR, but we have + # to clean a possible partial copy + rm -rf $PKGROOT/${EXACTPKG##*/} + exit 2 + fi + + touch $PKGROOT/${EXACTPKG##*/}/RELEASED + + return 0 +} + +# usage: install-files file... +# +function install-files { + local owner="$1" ; shift + local perm="$1" ; shift + local dst="$1" ; shift + local file + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + cp -dpfP "$@" "$ROOTDIR/$dst/" && \ + ( cd "$ROOTDIR/$dst" && chown -h $owner "${@##*/}" && chmod $perm "${@##*/}" ) + + [ -n "$FILE_LIST" ] && for file in "$@"; do echo "$dst/$file $owner $perm"; done >> $FILE_LIST +} + +# usage: install-file +# +function install-file { + local owner="$1" ; shift + local perm="$1" ; shift + local src="$1" ; shift + local dst="$1" ; shift + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + if cp -dpfP "$src" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" \ + && [ ! -L "$ROOTDIR/$dst" ]; then chmod $perm "$ROOTDIR/$dst"; fi + + [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST +} + +# usage: install-dir ... +# +function install-dir { + local owner="$1" ; shift + local perm="$1" ; shift + local dst + + for dst in "$@"; do + mkdir -pm $perm "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" + [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST + done +} + +# usage: install-ln +# +function install-ln { + local owner="$1" ; shift + local target="$1" ; shift + local dst="$1" ; shift + + [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}" + ln -s "$target" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" + [ -n "$FILE_LIST" ] && echo $dst $owner 000 >> $FILE_LIST +} + + +###### +###### here are some functions used only from main +###### + +function known_cmd { + declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; } + declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; } + declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; } + return 0 +} + + +###### +###### here is the main entry point +###### + +# scan the command line + +release_only=0 +force=0 +TESTGCC=0 +PRINTUSAGE=0 +PRINTENV=0 +ARGLIST=( ) +ACTION= +CHAINCMD=1 + +[ $# -eq 0 ] && PRINTUSAGE=1 + +while [ $# -gt 0 ] ; do + case "$1" in + --force ) + force=1 + ;; + --help|-h) + PRINTUSAGE=1 + ;; + --env|-e) + PRINTENV=1 + TESTGCC=1 + ;; + --rel|-r*) + release_only=1 + ;; + --) + shift + ARGLIST=(${ARGLIST[*]} $*) + break + ;; + -* ) + PRINTUSAGE=1 + ;; + *) + ARGLIST=(${ARGLIST[*]} "$1") + ;; + esac + shift +done + + +#echo "arglist=${ARGLIST[*]}" + +[ $PRINTENV -gt 0 ] && print_env +[ $PRINTUSAGE -gt 0 ] && usage +[ ${#ARGLIST[*]} -lt 1 ] && usage + +# Some actions can be chained, others not. we'll get the longest +# possible chain, and stop once we encounter a non-chainable action + +while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do + set -o noglob + ACTION=${ARGLIST[0]} + TESTGCC=0 + # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!! + ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash ! + + case "$ACTION" in + newpkg) + CHAINCMD=0 + KNOWNCMD=1 + # newpkg is the only command which doesn't start by a package lookup. + ;; + setpkg) + CHAINCMD=0 + KNOWNCMD=1 + get_name $1 %P default + ;; + info|edit|cat|unpack|changelog) + CHAINCMD=0 + KNOWNCMD=1 + get_name ${ARGLIST[0]} %L %P %D + [ -d "$PKGDIR" ] || PKGDIR= + ;; + patch|unpatch) + CHAINCMD=0 + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + compile_only|config|config_only|compile|build) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + TESTGCC=1 + # get_name %L + ;; + prepack|strip|pack|delpack|release|clean) + KNOWNCMD=1 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + *) + CHAINCMD=0 + KNOWNCMD=0 + if [ -r ".flxpkg/Version" ]; then + REPLY="$(cat .flxpkg/Version)" + REPLY="${REPLY##*/}" + PKGDIR="$CURDIR/.flxpkg/." + else + REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)" + PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)" + fi + # get_name %L + ;; + esac + + [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2 + + set +o noglob + if [ "$ACTION" != "newpkg" ]; then + if [ -z "$REPLY" ]; then + echo "Error: package name not found." + exit 1 + fi + EXACTPKG="$PKGDIR/$REPLY" + + if [ -z "$PKGDIR" ]; then + if [ -e "$PKGROOT/${EXACTPKG##*/}/build.cfg" ]; then + PKGDIR="$PKGROOT/${EXACTPKG##*/}" + else + PKGDIR="$DEVROOT/${EXACTPKG##*/}" + fi + fi + CFGFILE="$PKGDIR/build.cfg" + PKGRADIX="$(get_pkg_radix ${EXACTPKG##*/})" + PKGVER="$(get_pkg_ver ${EXACTPKG##*/})" + DISTVER="$(get_build_num ${EXACTPKG##*/})" + ROOTDIR="${ROOTDIR:-$CURDIR/${INSTNAME}}" + EXAMPLEDIR="${ROOTDIR}/usr/share/examples" + + # for compatibility with old functions. Not used anywhere outside this script. + packver="${EXACTPKG##*/}" + pack="$PKGRADIX" + fi + + set_cross_environment + set_compiler_options + + if [ "$ACTION" != "newpkg" ]; then + . $CFGFILE + fi + + # FLXMAKE is used for sequential make and FLXPMAKE for parallel make + FLXMAKE="${FLXMAKE:-make}" + FLXPMAKE="${FLXPMAKE:-$FLXMAKE}" + + export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST + +# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD" +# echo "ARGLIST=${ARGLIST[*]}" + + if [ $KNOWNCMD -gt 0 ]; then + known_cmd ${ARGLIST[*]} || exit 1 + else + if declare -f do_$ACTION >/dev/null; then + ( do_$ACTION ${ARGLIST[*]} ) || exit 1 + fi + fi + [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2 + + # now, we'll loop only if we were in a chainable action +done + +[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2 +exit 0 + -- cgit v1.2.3