lunariX Package System Package File Format The basis for the package is the zlib library, as files will be of "gzip" format. There will be just one file per package. The file will be divided into three sections, the Beginning, Middle and End. The Beginning will be a header, the details of which are below. The Middle is a list of files, sizes, permissions, and so forth. The End is actual file data. Advantages of this format The most important bits to do with package management are at the beginning, where they can be quickly accessed. It is often difficult to get this rapid access with .tar.gz files because the whole tar file is usually searched, causing the whole file to be passed through unzipping. This is slow, especially if all you want to do is query what sort of package it is, test to see whether it could be installed, delete the files installed by the package, et cetera. Disadvantages of this format Not directly compatible with anything else that exists currently, but will be very simple to write something that you pipe this through to get a tar file, so we're not too worried =) Constants and types I hope that the following makes sense. * + ? [ ] | have all been used as is standard for regular expressions. Normal (brackets) are used for casting. Everything after the first colon and space is the definition until the start of the whitespace which ends with an {open squirly bracket}. I assume the existance of two types, the char and the int, and the existance of the separator characters . - : / @. Concatenation of types and separator characters is implicit. Used in Beginning ints: (string) [int|**] {eg "*", "3"} string: [char]* {eg "hello world"} headtype: string[-int.int]+ {eg "count-1.2-3.4"} header: headtype = "lunch-0.1" {constant - this version of lunch} pname: string {eg "glibc"} pvernum: (string) int.int.int.int {eg "2.0.36.3"} dpvernum: (string) ints.ints.ints.ints {eg "2.0.3.*"} parch: string {eg "i386"} dparch: [string|**] {eg "*", "i386"} pbuild: (string) int {eg "1"} dpbuild: (string) ints {eg "*", "42"} pver: (string) pvernum.parch.pbuild {eg "0.16.3.0.i386.1"} dpver: (string) dpvernum.dparch.dpbuild {eg "0.16.3.*.*.1"} packagename: pname.pver {eg "enlightenment.0.16.3.0.i386.1"} dpackname: dpname.dpver {eg "e.0.1.6.*.*.*"} dpackagename: dpackname[||dpackname]+ {eg "e.0.1.6.*.*.*|e.0.1.7.*.*.*"} host: [string.]*string {eg "www.lunarix.org"} port: (strig) int {eg "80"} bistro: (string) host:port {eg "www.lunarix.org:80"} rpath: [string/]* {eg "usr/bin/"} apath: /rpath {eg "/usr/bin/"} fpath: [/rpath]?[string] {eg "/usr/bin/uustat"} url: (string) [ftp|http]://host[apath]? {eg "http://maz.nu/index.html"} email: string@host {eg "root@localhost"} dname: string {eg "lunarix"} distributor: dname bistro url email {eg "a b:1 http://c/d/e.f g@h"} pmajor: string {eg "system"} pminor: string {eg "library"} packagetype: pmajor/pminor {eg "network/server"} comment: string {eg "This package rules. Install it!" } Used in Middle specialfile: [string/]*[string] {eg "META/somewhere"} normalfile: [/string]+ {eg "/usr/bin/fixdlsrps"} pathfile: [specialfile|normalfile] {eg "/usr/bin/python"} filesize: (string) int {eg "42"} fileblock: (string) int-int {eg "1-42"} crc: (string) int {eg "13525"} size: filesize.fileblock[.fileblock]*.crc {eg "42.0-41.123"} user: string {eg "root"} group: string {eg "bin"} owner: user.group {eg "root.lunarix"} ftype: [f|d|l|p|c|b|s] {file,dir,link,pipe,char,block} perm: (string) int {r,w,x,suid,sticky,none} atr: [a|i|s] {append, immute, syncwrite} permission: [ftype].[perm].[atr] {eg "d.rwx.rx.rx.-"} Layout of file Once decompressed (with the zlib library) the file will have the following structure: LX header [start of Beginning] PN packagename DI distributor HD dpackagename dpackagename ... dpackagename SD dpackagename dpackagename ... dpackagename PT packagetype ## comment ## comment [end of Beginning] pathfile:size:permission:owner [start of Middle] pathfile:size:permission:owner pathfile:size:permission:owner [end of Middle] datadatadatadatad... [start of End] ...atadatadatadat... ...adatadata[EOF] [end of End] Description of fields LX header The first line of the file is so that the file type may be detected - the so-called "magic numbers". It also defines the version of the file type, so that forward/backward compatibility may be handled. Although the header is a fixed value currently, future versions of the package specification will use different headers. It is necessary therefore to read in the whole header line and check to see whether a version number that your program understands is contained within the header. Note that "globbing" is legal, but * is the only permitted glob character (? is not valid). Examples LX lunch-0.0-0.1-0.3 This file conforms to version 0.0, 0.1, 0.3 but someho w will break if an unpacker that only understands 0.2 tries to unpack it. LX lunch-0.*-1.1 Any 0.x unpacker and the 1.1 unpacker can unpack this. PN packagename The packagename consists of two parts, pname.pver. The pname is simply what the package is. This should be as specific as needs be, but still cover the entire contents of the package, while being concise. In other words, a package called "ls-cd-ln-mkdir-..." isn't as sensible a name as "binutils". Then again, "utils" is too vague a name, as anything could be a utility. In addition, initial capitalised pnames are reserved for packages which have no content except a long list of hard/soft depends, thus making up a "super-package". Totally capitalised pnames are also reserved. The valid list of characters for pnames is below: Valid characters for pnames abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ The pvernum is the version of this package, which should be as closely mapped onto the version what's inside the package as possible. The version allows for 4 digits of version information. If less digits are required then the least-significant digits should be set to zero. Development versions of packages (eg a source tree) should have the least significant digit negated to show that they are not actually a proper release. The modulus of the number increases with increasing version number, but the number is negated until the package reaches a stable ".0" release. Example pvernums version pvernum 2.0.36 2.0.36.0 2.0.37-ac5 2.0.37.-5 1 1.0.0.0 2-devel-6 2.0.0.-6 The arch field defines the architecture(s) of the package (if compiled) or that it is source (and will compile on any architecture). These strings are predefined as for the linux kernel. Architecture strings alpha arm i386 m68k mips ppc sparc sparc64 SRC [source, works on any platform] The pbuild field allows one final item of information to be included within the version. This is for where the actual version has not changed, although something has been "upgraded" (for example, default configuration files cleaned up and made more secure). These numbers should start at 1. Examples PN linux-kernel-binary.2.0.36.0.i386.2 PN less-332.0.0.0.i386.1 PN enlightenment.0.16.3.-4.SRC.1 DI distributor The distributor field is intended as a means of getting upgrades to the package quickly and easily, in a hope that downloading and installing package upgrades can be 99% automated. This field consists of a 4 item space separated list which serve as identifiers for the distributor of the package. dname field This is simply the name of the distributor. In the case of lunariX, the string would simply be "lunariX". bistro field This is the host:port of a server where this package is expected to be resolvable by use of the bistro protocol (outlined elsewhere). In the case of lunariX, this field would be "bistro.lunariX.org:80". url field The URL field is to be used for the website of the distributor. In the case of lunariX, this string would be "http://www.lunariX.org/". email field The email address of who built the package. Useful as a last resort for finding out more about the package or contacting the distributor to report bugs/etc. In the case of lunariX, this field would be "buildmeister@lunariX.org". Examples DI lunariX bistro.lunariX.org:80 http://www.lunariX.org/ buildmeister@lunariX.o rg HD dpackagename dpackagename ... dpackagename The harddepend suggests that this package cannot function without another package having been installed first. For example, there is no point installing a C compiler unless the system include files have been installed first. As a full packagename is specified, a version number must be included. This has been known to cause problems in some library "upgrades" for example, where an allegedly backward-compatible library has been broken in some form and will not work with a particular program. This accounts for the slightly complex syntax of a dpackagename. It is basically a list of pipe (|) separated dpacknames. Any dpackname in the dpackagenamelist that matches fulfils the dependency. A dpackname is similar to a packagename except it allows any of the pver part to be globbed. Globbing in dpacknames Numeric matching * match anything in this field 1,2 match if field matches 1 or 2 [1234] match if character is one of 1234 [01][01] will match 0, 1, 10, 11 (leading zeros are stripped) [124+] match 12456789 [!3] match 012456789 [!345] match 0126789 [01][01],2 will match 0, 1, 2, 10, 11 Architecture matching * match any architecture except SRC + match any architecture including SRC !i386 match any architecture except i386 !i386!alpha match any architecture except i386 or alpha i386,alpha match only i386 and alpha Package name matching !package fail if package is installed Examples [Taken from an email to lunariX development (and edited slightly)] For something which needs a C compiler (either egcs or gcc will work): HD egcs.*.*.*.*.*.*|gcc.*.*.*.*.*.* Now let's look at gcc and egcs. You don't usually want BOTH installed, do you? So let's put some soft depends in (they're only recommendations, after all, and can be overridden at some UI level [if the UI supports overriding depends])... egcs's SD: SD !gcc.*.*.*.*.*.* gcc's SD: SD !egcs.*.*.*.*.*.* Now let's go look at our friend, libstupid again. Assume for a moment that libstupid-0.1.1 worked fine. libstupid-0.1.2 broke something that badlywritten-0.4 uses. libstupid-0.1.3 fixed it again. libstupid-0.1.4 hasn't been written yet, but because we can't predict the future we have two options: 1) optimism - future versions WILL be backwards compatible 2) pessimism - future versions will be BROKEN (like libstupid-0.1.2) badlywritten-0.4 can have either of these hard depends (NB, they've been split over several lines with # comments and spaces etc. They should be one line with no spaces, naturally)... 1) optimistic: HD libstupid.0.1.[!2].*.*.* # 0.1.2 doesn't work | libstupid.0.[2+].*.*.* # 0.2.0 and above will work | libstupid.[1+].*.*.*.*.*.* # 1.0.0 and above will work 2) pessimistic: HD libstupid.0.1.[13].*.*.* # only 0.1.1 and 0.1.3 work SD dpackagename dpackagename ... dpackagename Identical to harddepends except that instead of being required to provide core functionality, they merely add functionality. For example, Netscape would have soft-depends on various plugins. However, the plugins themselves would have a hard-dependency on Netscape (they are useless without it!). Examples SD tcl.*.*.*.*.*.* perl.5.0.*.*.*.* SD tk.4.0.1.0.i386.* PT packagetype Similar to a MIME-type, the packagetype is a broad description of what this package is for. A tree of currently registered types is shown below. Valid packagetypes system system [a full system distribution] kernel [vmlinuz, modules, etc] library [libc, gtk, xlib] startup [init and the like] admin [adduser and similar] tools [gzip, sed, awk, less, more, binutils, xterm] xserver [x] devel [gcc, egcs, tcl, perl, python] network client [telnet, netscape] server [inetd, apache...] admin [configuration utilities] hardware printer [lpr and various filters] admin [pcmcia managers] multimedia sound [esd, cdparanoia] graphic [gimp, xv, ee, imagemagick] NB. This list will probably be modified as more subgroups are required. http://mcji2.clare.cam.ac.uk/lunariX/system/lunch created Wed Jan 19 04:15:13 GMT 2000 All content copyright (C) 1999-2000 lunarix