diff options
Diffstat (limited to 'lilo-config/common')
-rw-r--r-- | lilo-config/common/Config.cc | 66 | ||||
-rw-r--r-- | lilo-config/common/Config.h | 40 | ||||
-rw-r--r-- | lilo-config/common/Disks.cc | 294 | ||||
-rw-r--r-- | lilo-config/common/Disks.h | 49 | ||||
-rw-r--r-- | lilo-config/common/Files.cc | 70 | ||||
-rw-r--r-- | lilo-config/common/Files.h | 47 | ||||
-rw-r--r-- | lilo-config/common/Makefile.am | 11 | ||||
-rw-r--r-- | lilo-config/common/String.cc | 437 | ||||
-rw-r--r-- | lilo-config/common/String.h | 96 | ||||
-rw-r--r-- | lilo-config/common/lilo.cc | 585 | ||||
-rw-r--r-- | lilo-config/common/lilo.h | 77 | ||||
-rw-r--r-- | lilo-config/common/tests/Makefile.am | 9 | ||||
-rw-r--r-- | lilo-config/common/tests/String.cc | 77 |
13 files changed, 1858 insertions, 0 deletions
diff --git a/lilo-config/common/Config.cc b/lilo-config/common/Config.cc new file mode 100644 index 0000000..37921ba --- /dev/null +++ b/lilo-config/common/Config.cc @@ -0,0 +1,66 @@ +/* Config.cc +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#include "Config.h" +void ConfigFile::set(String const &key, String const &value, bool const "e, bool const &removeIfEmpty, String const &prefix) +{ + String re="[ \t]*" + key + "[ \t]*="; + String s=grep(re); + if(value.empty() && removeIfEmpty) { + if(!s.empty()) + remove(s); + } else if(s.empty()) { + if(quote) + insert(end(), prefix + key + "=\"" + value + "\""); + else + insert(end(), prefix + key + "=" + value); + } else { + for(iterator it=begin(); it!=end(); it++) + if(!(*it).regex(re).empty()) { + if(quote) + (*it)=prefix + key + "=\"" + value +"\""; + else + (*it)=prefix + key + "=" + value; + break; + } + } +} +String const ConfigFile::get(String const &key, String const &dflt, bool const &unquote) +{ + String s=grep("[ \t]*" + key + "[ \t]*=").simplifyWhiteSpace(); + if(s.empty()) + return dflt; + s=s.mid(s.locate("=")+2).simplifyWhiteSpace(); + if(unquote) { + if(s.chr(0)=='"') + s=s.mid(2); + if(s.chr(s.size()-1)=='"') + s=s.left(s.size()-1); + } + return s.simplifyWhiteSpace(); +} diff --git a/lilo-config/common/Config.h b/lilo-config/common/Config.h new file mode 100644 index 0000000..6ac6334 --- /dev/null +++ b/lilo-config/common/Config.h @@ -0,0 +1,40 @@ +/* Config.h +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#ifndef _CONFIGFILE_H_ +#define _CONFIGFILE_H_ 1 + +#include "String.h" +class ConfigFile:public StringList +{ +public: + void set(String const &key, String const &value, bool const "e=true, bool const &removeIfEmpty=true, String const &prefix=""); + String const get(String const &key, String const &dflt="", bool const &unquote=true); +}; + +#endif diff --git a/lilo-config/common/Disks.cc b/lilo-config/common/Disks.cc new file mode 100644 index 0000000..b4a417d --- /dev/null +++ b/lilo-config/common/Disks.cc @@ -0,0 +1,294 @@ +/* Disks.cc +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#include "Disks.h" +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +StringList ptable::disklist() +{ + /* The basics behind scanning for a disk are simple: If it can be * + * opened, it exists. * + * Using access() is not sufficient - that's successful if the device * + * node exists but there's no actual device. * + * Checking /proc/devices would work, but it wouldn't autoload modules* + * so chances are we'd be missing something. */ + StringList dsk; + int fd; + bool finished=false; + #define CHECK_DEV(d) if((fd=open(d, O_RDONLY))<0) { \ + finished=true; \ + continue; \ + } \ + close(fd); \ + dsk+=d + String dev="/dev/hd"; // IDE devices: /dev/hd[a-t] + for(char a='a'; a<='t'; a++) { + // We can't use finished for IDE drives - it's perfectly OK + // to have a /dev/hdc but no /dev/hdb. + CHECK_DEV(dev+a); + } + finished=false; + dev="/dev/sd"; // SCSI disks 0-25 + for(char a='a'; a<='z' && !finished; a++) { + CHECK_DEV(dev+a); + } + for(char prefix='a'; prefix <='d' && !finished; prefix++) { + dev="/dev/sd" + prefix; // SCSI disks 26-127 + for(char a='a'; (a<='x' || (a<='z' && prefix<'d')) && !finished; a++) { + CHECK_DEV(dev+a); + } + } + finished=false; + dev="/dev/i2o/hd"; // I2O disks 0-25: /dev/i2o/hd[a-z] + for(char a='a'; a<='z' && !finished; a++) { + CHECK_DEV(dev+a); + } + for(char prefix='a'; prefix <='d' && !finished; prefix++) { + dev="/dev/i2o/hd" + prefix; // I2O disks 26-127 + for(char a='a'; (a<='x' || (a<='z' && prefix<'d')) && !finished; a++) { + CHECK_DEV(dev+a); + } + } + finished=false; + dev="/dev/pd"; // Parallel port disks: /dev/pd[a-d] + for(char a='a'; a<='d' && !finished; a++) { + CHECK_DEV(dev+a); + } + finished=false; + for(unsigned int i=0; i<=31 && !finished; i++) { // Software RAID + String device; + device.sprintf("/dev/md%u", i); + CHECK_DEV(device); + } + finished=false; + for(unsigned int i=0; i<=7; i++) { //Compaq Smart Array + for(unsigned int j=0; j<=15 && !finished; j++) { + String device; + device.sprintf("/dev/ida/c%ud%u", i, j); + CHECK_DEV(device); + } + } + finished=false; + for(unsigned int i=0; i<=7; i++) { // Mylex DAC960 + for(unsigned int j=0; j<=31 && !finished; j++) { + String device; + device.sprintf("/dev/rd/c%ud%u", i, j); + CHECK_DEV(device); + } + } + finished=false; + dev="/dev/ed"; // MCA ESDI harddisks: /dev/ed[ab] + for(char a='a'; a<='b' && !finished; a++) { + CHECK_DEV(dev+a); + } + finished=false; + dev="/dev/xd"; // XT (8-bit) harddisks: /dev/xd[ab] + for(char a='a'; a<='b' && !finished; a++) { + CHECK_DEV(dev+a); + } + return dsk; +} +StringList ptable::partlist() +{ + StringList s; + StringList d=disklist(); + for(StringList::const_iterator it=d.begin(); it!=d.end(); it++) { + for(int i=1; i<32; i++) { + String drive; + drive.sprintf("%s%u", (*it).cstr(), i); + int fd=open(drive, O_RDONLY); + if(fd>=0) { + char test; + if(read(fd, &test, 1)>0) + s += drive; + close(fd); + } else + break; + } + } + return s; +} +ptable::ptable(StringList const &disks) +{ + partition.clear(); + id.clear(); + mountpt.clear(); + for(StringList::const_iterator it=disks.begin(); it!=disks.end(); it++) + scandisk(*it); +} +ptable::ptable(String const &disk) +{ + partition.clear(); + id.clear(); + mountpt.clear(); + scandisk(disk); +} +void ptable::scandisk(String const &disk) +{ + String cmd; + cmd.sprintf("fdisk -l %s 2>&1", (char*)disk); + FILE *fdisk=popen(cmd, "r"); + char *buf=(char *) malloc(1024); + String dev; + while(fgets(buf, 1024, fdisk)) { + if(strncmp("/dev/", buf, 5)==0) { // Partition entry + // We don't care about active vs. non-active partitions. + // Remove the sign. + while(strchr(buf, '*')) *strchr(buf, '*')=' '; + // blanks are blanks... + while(strchr(buf, '\t')) *strchr(buf, '\t')=' '; + // Get the device + *strchr(buf, ' ')=0; + dev=buf; + partition += buf; + // And figure out where/if it's mounted + mountpt[dev]=mountpoint(dev); + // Lastly, get the partition type. + strcpy(buf, buf+strlen(buf)+1); + while(isspace(*buf)) strcpy(buf, buf+1); + strcpy(buf, strchr(buf, ' ')); // skip Start + while(isspace(*buf)) strcpy(buf, buf+1); + strcpy(buf, strchr(buf, ' ')); // skip End + while(isspace(*buf)) strcpy(buf, buf+1); + strcpy(buf, strchr(buf, ' ')); // skip Blocks + while(isspace(*buf)) strcpy(buf, buf+1); + id[dev]=strtol(buf, NULL, 16); + } + } + pclose(fdisk); + free(buf); +} +String ptable::mountpoint(String const &device, bool fstab_fallback) +{ + char *buf=new char[1024]; + FILE *f=fopen("/etc/mtab", "r"); + String mp=""; + while(fgets(buf, 1024, f)) { + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + if(device.cmp(buf)) { + strcpy(buf, buf+strlen(buf)+1); + while(isspace(*buf)) + strcpy(buf, buf+1); + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + mp=buf; + mp=mp.simplifyWhiteSpace(); + break; + } + } + fclose(f); + if(mp.empty() && fstab_fallback) { + f=fopen("/etc/fstab", "r"); + while(fgets(buf, 1024, f)) { + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + if(device.cmp(buf)) { + strcpy(buf, buf+strlen(buf)+1); + while(isspace(*buf)) + strcpy(buf, buf+1); + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + mp=buf; + mp=mp.simplifyWhiteSpace(); + break; + } + } + fclose(f); + } + delete buf; + return mp; +} +String ptable::device(String const &mountpt, bool fstab_fallback) +{ + char *buf=new char[1024]; + FILE *f=fopen("/etc/mtab", "r"); + String dev=""; + while(fgets(buf, 1024, f)) { + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + String device=buf; + strcpy(buf, buf+strlen(buf)+1); + while(isspace(*buf)) + strcpy(buf, buf+1); + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + String mp=buf; + mp=mp.simplifyWhiteSpace(); + if(mp==mountpt) { + dev=device; + break; + } + } + fclose(f); + + if(dev.empty() && fstab_fallback) { + // The FS is not mounted - maybe it could be, though. + f=fopen("/etc/fstab", "r"); + while(fgets(buf, 1024, f)) { + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + String device=buf; + strcpy(buf, buf+strlen(buf)+1); + while(isspace(*buf)) + strcpy(buf, buf+1); + if(strchr(buf,' ')) + *strchr(buf, ' ')=0; + if(strchr(buf,'\t')) + *strchr(buf, '\t')=0; + String mp=buf; + mp=mp.simplifyWhiteSpace(); + if(mp==mountpt) { + dev=device; + break; + } + } + fclose(f); + } + delete buf; + return dev; +} diff --git a/lilo-config/common/Disks.h b/lilo-config/common/Disks.h new file mode 100644 index 0000000..8965694 --- /dev/null +++ b/lilo-config/common/Disks.h @@ -0,0 +1,49 @@ +/* Disks.h +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#ifndef _DISKS_H_ +#define _DISKS_H_ 1 +#include "String.h" +#include <list> +#include <map> +class ptable { +public: + ptable(StringList const &disks=disklist()); + ptable(String const &disk); + static StringList disklist(); + static StringList partlist(); + static String mountpoint(String const &device, bool fstab_fallback=false); + static String device(String const &mountpt, bool fstab_fallback=false); +protected: + void scandisk(String const &disk); +public: + StringList partition; + std::map<String,int> id; + std::map<String,String> mountpt; +}; +#endif diff --git a/lilo-config/common/Files.cc b/lilo-config/common/Files.cc new file mode 100644 index 0000000..19af29d --- /dev/null +++ b/lilo-config/common/Files.cc @@ -0,0 +1,70 @@ +/* Files.cc +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#include "Files.h" +#include <glob.h> +#include <sys/stat.h> +#define ISSET(x,y) ((x&y)==y) +StringList &Files::glob(String name, enum Types types, bool dotfiles, bool braces) +{ + glob_t gl; + int flags=0; + StringList *result; + if(dotfiles) + flags |= GLOB_PERIOD; + if(braces) + flags |= GLOB_BRACE; + ::glob(name, flags, NULL, &gl); + if(types==Any) + result=new StringList(gl.gl_pathv, gl.gl_pathc); + else { + struct stat s; + result=new StringList; + for(unsigned int i=0; i<gl.gl_pathc; i++) { + if(!lstat(gl.gl_pathv[i], &s)) { + if(S_ISLNK(s.st_mode) && !ISSET(types,Link)) + continue; + if(S_ISREG(s.st_mode) && !ISSET(types,File)) + continue; + if(S_ISDIR(s.st_mode) && !ISSET(types,Dir)) + continue; + if(S_ISCHR(s.st_mode) && !ISSET(types,CharDevice)) + continue; + if(S_ISBLK(s.st_mode) && !ISSET(types,BlockDevice)) + continue; + if(S_ISFIFO(s.st_mode) && !ISSET(types,Fifo)) + continue; + if(S_ISSOCK(s.st_mode) && !ISSET(types,Socket)) + continue; + result->insert(result->end(), gl.gl_pathv[i]); + } + } + } + globfree(&gl); + return *result; +} diff --git a/lilo-config/common/Files.h b/lilo-config/common/Files.h new file mode 100644 index 0000000..ad1fa3b --- /dev/null +++ b/lilo-config/common/Files.h @@ -0,0 +1,47 @@ +/* Files.h +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#ifndef _FILES_H_ +#define _FILES_H_ 1 +#include "String.h" +class Files { +public: + enum Types { File = 0x1, + Dir = 0x2, + Link = 0x4, + CharDevice = 0x8, + BlockDevice= 0x10, + Device = CharDevice | BlockDevice, + Fifo = 0x20, + Socket = 0x40, + All = File | Dir | Link | Device | Fifo | Socket, + Any = All + }; + static StringList &glob(String name, enum Types types=All, bool dotfiles=true, bool braces=true); +}; +#endif diff --git a/lilo-config/common/Makefile.am b/lilo-config/common/Makefile.am new file mode 100644 index 0000000..37b44eb --- /dev/null +++ b/lilo-config/common/Makefile.am @@ -0,0 +1,11 @@ +# SUBDIRS = tests + +noinst_LTLIBRARIES = libcommon.la +INCLUDES = $(all_includes) + +noinst_HEADERS = \ + String.h Files.h Disks.h Config.h lilo.h + +libcommon_la_SOURCES = \ + String.cc Files.cc Disks.cc Config.cc lilo.cc + diff --git a/lilo-config/common/String.cc b/lilo-config/common/String.cc new file mode 100644 index 0000000..f8a0e35 --- /dev/null +++ b/lilo-config/common/String.cc @@ -0,0 +1,437 @@ +/* String.cc +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#define _GNU_SOURCE 1 +#include <features.h> +#include <string.h> +#include <string> +#include "String.h" +#include <stdio.h> +#include <regex.h> +#include <stdlib.h> + +using namespace std; + +void String::sprintf(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + char *buf=0; + int size=vsnprintf(buf, 0, format, arg); + if(size==-1) { /* ARGH!!! */ + cerr << "WARNING: Your C library (libc) does not conform to the ISO C99 standard!" << endl << "Consider upgrading to glibc 2.1 or higher!" << endl; + int bufsiz=1024; + while(size==-1) { + buf=(char *) malloc(bufsiz); + size=vsnprintf(buf, 0, format, arg); + bufsiz+=1024; + free(buf); + } + } + buf=(char *) malloc(size+1); + vsnprintf(buf, size+1, format, arg); + string str=buf; + *this=buf; + va_end(arg); + free(buf); + return; +} +bool String::readfile(String filename) +{ + FILE *f=fopen(filename, "r"); + if(!f) + return false; + + string str=""; + char *buf=(char *) malloc(1024); + while(!feof(f) && !ferror(f)) { + if(!fgets(buf, 1024, f)) + continue; + str += buf; + }; + *this=buf; + free(buf); + fclose(f); + return true; +} +char *String::cstr() const +{ + char *a=new char[size()+1]; + a[size()]=0; + strncpy(a, data(), size()); + return a; +} +bool String::cmp(char const * const s) const +{ + if(size() != strlen(s)) + return false; + return (strncmp(data(), s, size())==0); +} +bool String::casecmp(char const * const s) const +{ + if(size() != strlen(s)) + return false; + return (strncasecmp(data(), s, size())==0); +} +bool String::contains(String const &s, bool cs) const +{ + if(cs) + if(strstr(cstr(), s.cstr())) + return true; + else + return false; + else + if(strcasestr(cstr(), s.cstr())) + return true; + else + return false; +} +int String::locate(String const &s, bool cs, unsigned int startat) const +{ + if(startat>=size()) + return -1; + + char *s0=cstr(), *s1=s.cstr(), *s2; + int r; + if(cs) + s2=strstr(s0+startat, s1); + else + s2=strcasestr(s0+startat, s1); + if(s2==NULL) { + delete [] s0; + delete [] s1; + return -1; + } + r=(s2-s0); + if(startat>0) r++; + delete [] s0; + delete [] s1; + return r; +} +String const String::operator +(char const &s) { + char a[2]; + a[0]=s; + a[1]=0; + String st=cstr(); + st+=a; + return st; +} +String const String::operator +(char const * const s) { + String st=cstr(); + st += s; + return st; +} +bool String::operator ==(char s) { + if(size()==1 && cstr()[0]==s) + return true; + else + return false; +} +bool String::operator !=(char s) { + if(size()!=1 || cstr()[0]!=s) + return true; + else + return false; +} +String String::simplifyWhiteSpace() const { + char *s=cstr(); + for(unsigned int i=0; i<size(); i++) + if(isspace(s[i])) + s[i]=' '; + while(*s==' ') + strcpy(s, s+1); + int l = strlen(s); + while(l && (s[l-1]==' ')) + s[--l]=0; + + while(strstr(s, " ")) + strcpy(strstr(s, " "), strstr(s, " ")+1); + return s; +} +String String::left(unsigned int num) const +{ + if(num==0) return ""; + char *s=cstr(); + if(size()<=num) + return s; + s[num]=0; + return s; +} +String String::right(unsigned int num) const +{ + if(num==0) return ""; + char *s=cstr(); + if(size()<=num) + return s; + strcpy(s, s+strlen(s)-num); + return s; +} +String String::mid(unsigned int start, unsigned int num) const +{ + if(start>=size()) + return ""; + char *s=cstr(); + start--; + if(start>0) + strcpy(s, s+start); + if(num>0 && num<=strlen(s)) + s[num]=0; + return s; +} +String &String::regex(String const &expr, bool cs) const +{ + regex_t regexp; + int err; + regmatch_t reg[1]; + String *ret=new String(""); + if((err=regcomp(®exp, expr, cs?REG_EXTENDED:REG_EXTENDED|REG_ICASE))) { + regfree(®exp); + return *ret; + } + err=regexec(®exp, cstr(), 1, reg, 0); + regfree(®exp); + if(err) + return *ret; + if(reg[0].rm_so!=-1) { + char *s=strdup(cstr()+reg[0].rm_so); + s[reg[0].rm_eo-reg[0].rm_so]=0; + delete ret; + ret=new String(s); + free(s); + } + return *ret; +} +String &String::replace(String const &what, String const &with, bool all) const +{ + String *result; + if(!contains(what)) { + result=new String(*this); + return *result; + } + result=new String; + *result=left(locate(what)); + *result+=with; + if(!all) { + *result+=right(size()-locate(what)-what.size()); + } else { + unsigned int start=locate(what)+what.size()+1; + int loc; + while((loc=locate(what, true, start+1))!=-1) { + *result+=mid(start, loc-start); + *result+=with; + start=locate(what, true, start)+what.size(); + } + if(size()>start) + *result+=right(size()-start+1); + } + return *result; +} +String String::escapeForRegExp(String const &s) +{ + static const char meta[] = "$()*+.?[\\]^{|}"; + String quoted = s; + int i = 0; + + while ( i < (int) quoted.length() ) { + if ( strchr(meta, quoted.at(i)) != 0 ) + quoted.insert( i++, "\\" ); + i++; + } + return quoted; +} +StringList::StringList(String const &s) +{ + clear(); + char *st=strdup((char const * const)s); + char *tok; + char *line=strtok_r(st, "\n", &tok); + while(line) { + if(line[strlen(line)-1]=='\r') // Handle sucking OSes + line[strlen(line)-1]=0; + insert(end(), line); + line=strtok_r(NULL, "\n", &tok); + } + free(st); +} + +StringList::StringList(char **strs, int num) +{ + clear(); + if(num>=0) { + for(int i=0; i<num; i++) + insert(end(), strs[i]); + } else { + for(int i=0; strs[i]!=NULL; i++) + insert(end(), strs[i]); + } +} + +bool StringList::readfile(String const &filename) +{ + clear(); + FILE *f=fopen(filename, "r"); + if(!f) + return false; + char *buf=(char *) malloc(1024); + while(!feof(f) && !ferror(f)) { + if(!fgets(buf, 1024, f)) + continue; + while(strlen(buf) && (buf[strlen(buf)-1]=='\n' || buf[strlen(buf)-1]=='\r')) + buf[strlen(buf)-1]=0; + insert(end(), buf); + }; + free(buf); + fclose(f); + return true; +} +bool StringList::writefile(String const &filename) const +{ + FILE *f=fopen(filename, "w"); + if(!f) + return false; + for(const_iterator it=begin(); it!=end(); it++) { + fputs(*it, f); + fputs("\n", f); + } + fclose(f); + return true; +} +void StringList::operator +=(StringList const &s) +{ + for(const_iterator it=s.begin(); it!=s.end(); it++) + insert(end(), *it); +} +void StringList::operator +=(StringList const * const s) +{ + for(const_iterator it=s->begin(); it!=s->end(); it++) + insert(end(), *it); +} +bool StringList::contains(String const &s) const +{ + for(const_iterator it=begin(); it!=end(); it++) + if(*it == s) + return true; + return false; +} +void StringList::remove(String const &s) +{ + bool done=false; + for(iterator it=begin(); !done && it!=end(); it++) + if(*it==s) { + erase(it); + done=true; + } +} +String const &StringList::grep(String const &s) const +{ + for(const_iterator it=begin(); it!=end(); it++) + if(!(*it).regex(s).empty()) + return *it; + String *r=new String; + return *r; +} +int __stringlist_compare(const void *a, const void *b) +{ + if(a==0 && b==0) + return 0; + else if(a==0) + return 1; + else if(b==0) + return -1; + else + return strcmp((const char *)a,(const char *)b); +} +int __stringlist_compare_noncs(const void *a, const void *b) +{ + if(a==0 && b==0) + return 0; + else if(a==0) + return 1; + else if(b==0) + return -1; + else + return strcasecmp((const char *)a,(const char *)b); +} +void StringList::sort(bool cs) +{ + unsigned int i=0, s=size(); + char **strings=new char*[s]; + for(const_iterator it=begin(); it!=end(); it++) + strings[i++]=(*it).cstr(); + if(cs) + qsort(strings, s, sizeof(char*), __stringlist_compare); + else + qsort(strings, s, sizeof(char*), __stringlist_compare_noncs); + clear(); + for(i=0; i<s; i++) { + insert(end(), strings[i]); + delete [] strings[i]; + } + delete [] strings; +} +StringList::operator String() const +{ + String s=""; + for(const_iterator it=begin(); it!=end(); it++) { + s+=(*it); + if(s.right()!=String("\n") && s.right()!=String("\r")) + s+="\n"; + } + return s; +} + +ostream &operator <<(ostream &os, String const &s) +{ + if(!s.empty()) + os << (char const * const) s; + return os; +} +ostream &operator <<(ostream &os, String const *s) +{ + if(!s->empty()) + os << (char const * const) *s; + return os; +} +ostream &operator <<(ostream &os, StringList const &s) +{ + for(StringList::const_iterator it=s.begin(); it!=s.end(); it++) { + os << *it; + if((*it).right()!=String("\n") && (*it).right()!=String("\r")) + os << endl; + } + return os; +} +ostream &operator <<(ostream &os, StringList const *s) +{ + for(StringList::const_iterator it=s->begin(); it!=s->end(); it++) { + os << *it; + if((*it).right()!=String("\n") && (*it).right()!=String("\r")) + os << endl; + } + return os; +} diff --git a/lilo-config/common/String.h b/lilo-config/common/String.h new file mode 100644 index 0000000..7b12af5 --- /dev/null +++ b/lilo-config/common/String.h @@ -0,0 +1,96 @@ +/* String.h +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +/* Somewhat more sane string handling functions... * + * Should be portable, therefore we aren't simply using QString. */ + +#ifndef _STRING_H_ +#define _STRING_H_ 1 +#include <string> +#include <list> +#include <iostream> +#include <stdarg.h> + +class String; +class StringList; + +typedef std::list<String> strlist; + +class String:public std::string { +public: + String():std::string("") { } + String(char const * const &s):std::string(s) { } + String(std::string const &s):std::string(s) { } + String const operator +(char const &s); + String const operator +(char const * const s); + bool operator ==(char s); + bool operator !=(char s); + operator char * () const { return cstr(); } + char * cstr() const; + bool cmp(char const * const s) const; + bool casecmp(char const * const s) const; + bool contains(String const &s, bool cs=true) const; + int locate(String const &s, bool cs=true, unsigned int startat=0) const; + void sprintf(const char *format, ...); + bool readfile(String filename); + String simplifyWhiteSpace() const; + String left(unsigned int num=1) const; + String right(unsigned int num=1) const; + String mid(unsigned int start, unsigned int num=0) const; + String ®ex(String const &expr, bool cs=true) const; + String &replace(String const &what, String const &with, bool all=true) const; + static String escapeForRegExp(String const &s); + char chr(unsigned int index) const { if(index>=size()) return 0; else return data()[index]; } + int length() const { return size(); } // For compatibility with QString + char const *latin1() const { return cstr(); } // For compatibility with QString +}; + +class StringList:public strlist { +public: + StringList() { clear(); } + StringList(String const &s); + StringList(char **strs, int num=-1); + bool readfile(String const &filename); + bool writefile(String const &filename) const; + void operator +=(String const &s) { insert(end(), s); } + void operator +=(char const * const &s) { insert(end(), s); } + void operator +=(StringList const &s); + void operator +=(StringList const * const s); + operator String() const; + bool contains(String const &s) const; + void remove(String const &s); + void add(String const &s) { insert(end(), s); } + String const &grep(String const &s) const; + void sort(bool cs=true); +}; + +std::ostream &operator <<(std::ostream &os, String const &s); +std::ostream &operator <<(std::ostream &os, String const *s); +std::ostream &operator <<(std::ostream &os, StringList const &s); +std::ostream &operator <<(std::ostream &os, StringList const *s); +#endif diff --git a/lilo-config/common/lilo.cc b/lilo-config/common/lilo.cc new file mode 100644 index 0000000..6625f0d --- /dev/null +++ b/lilo-config/common/lilo.cc @@ -0,0 +1,585 @@ +/* lilo.cc +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#include "lilo.h" +#include "Disks.h" +#include "Files.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <fstream> +#include <string.h> + +using namespace std; + +bool liloimage::isLinux() const { + const_iterator it=begin(); + if((*it).contains("image")) + return true; + else + return false; +} + +liloimage *liloimages::find(String const &s) const +{ + String t = String::escapeForRegExp(s); + + String regex="^[ \t]*label[ \t]*=[ \t]*\"?" + t + "\"?[ \t]*"; + for(const_iterator it=begin(); it!=end(); it++) { + if(!(*it).grep(regex).empty()) + return (liloimage*)&(*it); + } + return 0; +} +void liloimages::remove(String const &s) +{ + liloimage *i=find(s); + for(iterator it=begin(); it!=end(); it++) + if(*it==*i) { + erase(it); + break; + } +} + +liloconf::liloconf(String const &filename) +{ + checked=false; + defaults.clear(); + images.clear(); + if(filename.empty()) { + probe(); + } else { + StringList s; + if(s.readfile(filename)) + set(s); + else + probe(); + } +} +void liloconf::set(StringList const &s) +{ + defaults.clear(); + images.clear(); + checked=false; + bool inHeader=true; + bool start; + liloimage *image=0; + for(StringList::const_iterator it=s.begin(); it!=s.end(); it++) { + String s=*it; + start=false; + s=s.simplifyWhiteSpace(); + if(s.empty()) + continue; + if(s.left(5)==(String)"other" && (s.mid(6, 1)==' ' || s.mid(6, 1)=='=')) { + inHeader=false; + start=true; + } + if(s.left(5)==(String)"image" && (s.mid(6, 1)==' ' || s.mid(6, 1)=='=')) { + inHeader=false; + start=true; + } + if(inHeader) { + defaults+=*it; + } else if(start) { + if(image) + images.insert(images.end(), *image); + image=new liloimage; + *image += *it; + } else { + *image += *it; + } + } + if(image) + images.insert(images.end(), *image); +} +void liloconf::set(String const &s) +{ + set((StringList)s); +} +void liloconf::writeFile(String const &filename) +{ + ofstream f; + f.open(filename, ios::out); + f << *this << endl; + f.close(); + chmod(filename, 0600); +} +bool liloconf::install(bool probeonly) +{ + char *lilotmp=strdup("/tmp/liloXXXXXX"); + String command; + int fd=mkstemp(lilotmp); + // Unfortunately, gcc 3.1 and higher don't have ofstream::attach + // anymore. Pity, used to be immensely useful. + // f.attach(fd); + close(fd); + ofstream f(lilotmp, ios::out); + f << defaults << endl; + for(liloimages::iterator it=images.begin(); it!=images.end(); it++) { + f << *it << endl; + } + f.close(); + + if(probeonly) + command.sprintf("/sbin/lilo -v -t -C %s 2>&1", (char const * const)lilotmp); + else + command.sprintf("/sbin/lilo -v -C %s 2>&1", (char const * const)lilotmp); + output=""; + FILE *lilo=popen(command, "r"); + char *buf=(char *) malloc(1024); + while(fgets(buf, 1024, lilo)) + output += buf; + free(buf); + ok=(pclose(lilo)==0); + unlink(lilotmp); + free(lilotmp); + checked=true; + return ok; +} +bool const liloconf::isOk() +{ + if(!checked) + check(); + return ok; +} +String const liloconf::liloOut() +{ + if(!checked) + check(); + return output; +} +bool liloconf::probe() +{ + ptable p; + StringList drives=p.disklist(); + String const root=p.device("/", true); + checked=false; + defaults.clear(); + images.clear(); + /* Set some reasonable defaults... */ + // Try to figure out the boot device first... + if(drives.contains("/dev/hda")) { + defaults += "boot=/dev/hda"; // 1st IDE/ATAPI harddisk + defaults += "lba32"; // otherwise it is assumed + } + else if(drives.contains("/dev/sda")) { + defaults += "boot=/dev/sda"; // 1st SCSI harddisk + defaults += "linear"; // some SCSI disks need this + } else if(drives.contains("/dev/i2o/hda")) + defaults += "boot=/dev/i2o/hda"; // 1st I2O harddisk + else if(drives.contains("/dev/eda")) + defaults += "boot=/dev/eda"; // 1st MCA ESDI harddisk + else if(drives.contains("/dev/pda")) + defaults += "boot=/dev/pda"; // 1st Parallel port IDE disk + else + defaults += "boot=Insert_your_boot_device_here"; // shouldn't happen + defaults += "prompt"; + defaults += "timeout=50"; + if(!access("/boot/message", F_OK)) + defaults += "message=/boot/message"; + defaults += "root=" + root; + + /* Scan for available operating systems... + * The list of what to do for each partition type is based on my + * best guess. I don't have anything but Linux (Red Hat Linux 7.0), + * FreeBSD (5.0-CURRENT), OpenBSD (2.6), FreeDOS (some CVS snapshot) + * and DR-DOS (7.03), so anything else might be wrong. + * If you have any additions or corrections, please send them to + * bero@redhat.com. + */ + // Scan for Linux kernels in the currently running system + // The following may or may not be specific to Red Hat Linux and + // similar distributions... If you're using a distribution that does + // things differently, tell me how it should be done there. + StringList files=Files::glob("/boot/*", Files::File); + for(StringList::iterator it=files.begin(); it!=files.end(); it++) { + struct stat s; + if(lstat(*it, &s)) // If we can't stat it, it can't be a kernel + continue; + if(s.st_size<131072) // if you managed to compile a kernel at less than 128k, you're cheating. ;) + continue; + if((*it).contains("System.map") || (*it).contains("initrd")) // definitely not a kernel + continue; + if((*it).contains("vmlinux")) { + // If the kernel exists both in compressed and in + // uncompressed form, ignore the uncompressed one. + String compr=(*it).replace("vmlinux", "vmlinuz"); + if(!access(compr, F_OK)) + continue; + } + String version=(*it).regex("(test-?|pre-?)?([0-9]\\.[0-9]\\.[0-9]+)(-?[0-9A-Za-z]+)*"); + String label=version; + if(version.empty()) // not a recognized kernel + version="linux"; + + if (label.empty()) + { + label = (*it); + if (label.find('/') != string::npos) + label = label.right(label.length()-1-label.rfind('/')); + } + // Check if we have an initial ramdisk (initrd) for this kernel... + String initrd1; // first guess + String initrd2; // second guess + if((*it).contains("vmlinuz")) { + initrd1=(*it).replace("vmlinux", "initrd")+".img"; + initrd2=(*it).replace("vmlinuz", "initrd.img"); + } + else if((*it).contains("vmlinux")) { + initrd1=(*it).replace("vmlinux", "initrd")+".img"; + initrd2=(*it).replace("vmlinuz", "initrd.img"); + } + else if((*it).contains("kernel")) { + initrd1=(*it).replace("kernel", "initrd")+".img"; + initrd2=(*it).replace("vmlinuz", "initrd.img"); + } + else if((*it).contains("linux")) { + initrd1=(*it).replace("linux", "initrd")+".img"; + initrd2=(*it).replace("vmlinuz", "initrd.img"); + } + else { + initrd1="/boot/initrd-"+version+".img"; + initrd2="/boot/initrd.img-"+version; + } + + String initrd = ""; + if(!access(initrd1, F_OK)) + initrd = initrd1; + else if(!access(initrd2, F_OK)) + initrd = initrd2; + + if(label.size()>15) // LILO can't handle this + if(label.contains("enterprise")) + label=label.replace("enterprise", "E"); + if(label.size()>15) + label=label.left(15); + + // label, kernel, root, initrd, optional, append, vga, readonly, + // literal, ramdisk + addLinux(label, *it, root, initrd); + } + addLinux("Linux_Compiled", "/usr/src/linux/arch/i386/boot/bzImage", root, "", true); // User-compiled kernel that wasn't moved... + + // Scan for other OSes... and Linux kernels on other partitions. + for(StringList::iterator it=p.partition.begin(); it!=p.partition.end(); it++) { + switch(p.id[*it]) { + case 0x01: // FAT12... Might be some really really old DOS. + case 0x04: // FAT16 < 32 M... Probably another old DOS. + case 0x06: // FAT16 + case 0x0b: // FAT32 + case 0x0c: // FAT32 (LBA) + case 0x0e: // FAT16 (LBA) + case 0x14: // Hidden FAT16 < 32 M... + case 0x16: // Hidden FAT16 + case 0x1b: // Hidden FAT32 + case 0x1c: // Hidden FAT32 (LBA) + case 0x1e: // Hidden FAT16 (LBA) + case 0x24: // NEC DOS + case 0x55: // EZ-Drive... I think this was some DOS tool + // to see "large" disks ages ago, so it may be + // a DOS partition... Not sure about this one. + case 0xc1: // DRDOS/sec + case 0xc4: // DRDOS/sec + case 0xc6: // DRDOS/sec + { + // Try to determine which type of DOS we're using + String mp=p.mountpt[*it]; + String lbl="DOS"; + if(mp.empty()) { + char *tmp=tmpnam(NULL); + tmp=tmpnam(NULL); + mkdir(tmp, 0700); + if(!mount(*it, tmp, "msdos", MS_MGC_VAL|MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL)) + mp=tmp; + else if(!mount(*it, mp, "vfat", MS_MGC_VAL|MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL)) + mp=tmp; + } + if(!mp.empty()) { + struct stat s; + if(stat(mp+"/ibmbio.com", &s) && stat(mp+"/io.sys", &s) && stat(mp+"/ntldr", &s)) // Doesn't look like a bootable DOS partition, ignore it + break; + if(!stat(mp+"/drdos.386", &s)) + lbl="DR-DOS"; + else if(!stat(mp+"/ntldr", &s)) + lbl="NT"; + else if(!stat(mp+"/msdos.sys", &s)) { + if(s.st_size < 4096) + /* msdos.sys is actual code in DOS, it's a config file in SuckOS */ + if(!stat(mp+"/windows/system/sfc.exe", &s)) /* This is (supposed to be?) a component of Suck98 but not Suck95 */ + lbl="Windows98"; + else + lbl="Windows95"; + } + if(p.mountpt[*it].empty()) { + umount(mp); + sync(); + rmdir(mp); + } + } + addOther(lbl, *it); + break; + } + case 0x02: // Xenix root... Does Xenix actually boot this way? + addOther("Xenix", *it); + break; + case 0x07: // HPFS or NTFS... Is there any way to check which? + // (without trying to mount them... many kernels + // support neither) + case 0x17: // Hidden HPFS or NTFS + addOther("NT", *it); + break; + case 0x09: // AIX + addOther("AIX", *it); + break; + case 0x83: // My favorite :) + case 0xfd: // Linux RAID + // TODO: scan other FSes for kernels... + break; + case 0x84: + { + // CLASH: SystemSoft MobilePRO BIOS and + // various Dell BIOSes use the same + // ID (0x84) for its hibernation partitions + // as OS/2 does for hidden C: drives. + // Fortunately, hibernation partitions are easy to + // recognize... + int fd=open(*it, O_RDONLY); + char *header=(char *) malloc(20); + read(fd, header, 20); + close(fd); + if(strncmp(header, "SystemSoft", 10)==0) // It's a hibernation partition + break; + else if(strncmp(header+3, "Dell Suspend", 12)==0) { // It's a Dell hibernation partition + // Dell BIOSes are ultimately buggy: They don't do resume-from-disk + // properly. + // Hibernation partitions are bootable and need to be loaded by the + // boot manager instead. + addOther("SuspendToDisk", *it); + break; + } + addOther("OS2", *it, false, "/boot/os2_d.b"); + } + case 0x0a: // OS/2 Boot Manager + addOther("OS2", *it, false, "/boot/os2_d.b"); + break; + case 0x10: // OPUS... (what is that?) + addOther("OPUS", *it); + break; + case 0x3c: // Partition Magic + addOther("PartitionMagic", *it); + break; + case 0x40: // Venix 80286 + addOther("Venix", *it); + break; + case 0x4d: // QNX + addOther("QNX", *it); + break; + case 0x52: // CP/M (does anyone dual-boot between CP/M and + // Linux? Would be interesting to see. ;) ) + case 0xdb: // CP/M/CTOS + addOther("CPM", *it); + break; + case 0x63: // GNU/Hurd + addOther("GNU_Hurd", *it); + break; + case 0x64: // Novell Netware + case 0x65: // Novell Netware + addOther("Netware", *it); + break; + case 0x75: // PC/IX (what is that?) + addOther("PCIX", *it); + break; + case 0x80: // Old Minix + case 0x81: // Minix and some VERY old Linux kernels + addOther("Minix", *it); + break; + case 0x9f: // BSD/OS + case 0xb7: // BSDI + addOther("BSD_OS", *it); + break; + case 0xa5: // Some BSDs... Is there any way to determine which + // one? + addOther("BSD", *it); + break; + case 0xa6: // OpenBSD + addOther("OpenBSD", *it); + break; + case 0xa7: // NeXTSTEP + addOther("NeXT", *it); + break; + case 0xc7: // Syrinx (what is that?) + addOther("Syrinx", *it); + break; + case 0xeb: // BeOS + addOther("BeOS", *it); + break; + case 0xfe: // LANstep (what is that?) + addOther("LANstep", *it); + break; + case 0xff: // BBT (what is that?) + addOther("BBT", *it); + break; + } + } + // addOther("floppy", "/dev/fd0", true); + //Would be nice, but LILO can't handle an optional + //other=nonexistantdevice entry ATM. + return true; +} +void liloconf::addLinux(String const &label, String const &kernel, String const &root, String const &initrd, bool optional, String const &append, String const &vga, bool readonly, String const &literal, String const &ramdisk) +{ + liloimage *lx_image=new liloimage; + *lx_image += "image="+kernel; + *lx_image += "\tlabel=\""+label+"\""; + if(!root.empty()) + *lx_image += "\troot="+root; + if(readonly) + *lx_image += "\tread-only"; + else + *lx_image += "\tread-write"; + if(!initrd.empty()) + *lx_image += "\tinitrd=\""+initrd+"\""; + if(!append.empty()) + *lx_image += "\tappend=\""+append+"\""; + if(!vga.empty()) + *lx_image += "\tvga=\""+vga+"\""; + if(!literal.empty()) + *lx_image += "\tliteral=\""+literal+"\""; + if(!ramdisk.empty()) + *lx_image += "\tramdisk=\""+ramdisk+"\""; + if(optional) + *lx_image += "\toptional"; + images.insert(images.end(), *lx_image); +} +void liloconf::addOther(String const &name, String const &partition, bool const &optional, String const &chain) +{ + liloimage *other=new liloimage; + *other += "other="+partition; + *other += "\tlabel=\""+name+"\""; + if(optional) + *other += "\toptional"; + if(!chain.empty()) + *other += "\tloader="+chain+"\""; + images.insert(images.end(), *other); +} +void liloconf::remove(String const &label) +{ + String t = String::escapeForRegExp(label); + + String regex="[ \t]*label[ \t]*=[ \t]*\"?"+t+"\"?[ \t]*"; + for(liloimages::iterator it=images.begin(); it!=images.end(); it++) { + if(!(*it).grep(regex).empty()) { + images.erase(it); + break; + } + } +} +void liloconf::removeKernel(String const &kernel) +{ + String t = String::escapeForRegExp(kernel); + + String regex="[ \t]*(image|other)[ \t]*=[ \t]*\"?"+t+"\"?[ \t]*"; + for(liloimages::iterator it=images.begin(); it!=images.end(); it++) { + if(!(*it).grep(regex).empty()) { + images.erase(it); + break; + } + } +} +StringList const &liloconf::entries() const +{ + StringList *s=new StringList; + for(liloimages::const_iterator it=images.begin(); it!=images.end(); it++) { + String lbl=(*it).grep("[ \t]*label[ \t]*=.*"); + lbl=lbl.mid(lbl.locate("label")+6); + while(isspace(lbl.chr(0)) || lbl.chr(0)=='=' || lbl.chr(0)=='\"') + lbl=lbl.mid(2); + while(isspace(lbl.right().chr(0)) || lbl.right()==(String)"\"") + lbl=lbl.left(lbl.size()-1); + s->add(lbl); + } + return *s; +} +String const liloconf::dflt() const +{ + String dflt=""; + for(StringList::const_iterator it=defaults.begin(); it!=defaults.end() && dflt.empty(); it++) + if(!((*it).regex("^[ \t]*default[ \t]*=")).empty()) + dflt=(*it).simplifyWhiteSpace(); + if(dflt.empty()) { + liloimages::const_iterator it=images.begin(); + if (it != images.end()) + dflt=(*it).grep("^[ \t]*label[ \t]*=").simplifyWhiteSpace(); + } + if(!dflt.empty()) { + dflt=dflt.mid(dflt.locate("=")+2).simplifyWhiteSpace(); + if(dflt.left()==(String)"\"") + dflt=dflt.mid(2).simplifyWhiteSpace(); + if(dflt.right()==(String)"\"") + dflt=dflt.left(dflt.size()-1).simplifyWhiteSpace(); + } + return dflt; +} +void liloconf::setDefault(String const &dflt) +{ + bool ready=false; + for(StringList::const_iterator it=defaults.begin(); !ready && it!=defaults.end(); it++) + if(!((*it).regex("^[ \t]*default[ \t]*=")).empty()) { + defaults.remove(*it); + ready=true; + } + defaults+="default=" + dflt; +} +liloconf::operator String() const +{ + String s=defaults; + s+="\n"; + for(liloimages::const_iterator it=images.begin(); it!=images.end(); it++) { + s+=*it; + s+="\n"; + } + return s; +} + +ostream &operator <<(ostream &os, liloconf const &l) +{ + os << l.defaults << endl; + for(liloimages::const_iterator it=l.images.begin(); it!=l.images.end(); it++) + os << *it << endl; + return os; +} +ostream &operator <<(ostream &os, liloconf const *l) +{ + os << l->defaults << endl; + for(liloimages::const_iterator it=l->images.begin(); it!=l->images.end(); it++) + os << *it << endl; + return os; +} diff --git a/lilo-config/common/lilo.h b/lilo-config/common/lilo.h new file mode 100644 index 0000000..c992df0 --- /dev/null +++ b/lilo-config/common/lilo.h @@ -0,0 +1,77 @@ +/* lilo.h +** +** Copyright (C) 2000,2001 by Bernhard Rosenkraenzer +** +** Contributions by A. Seigo and W. Bastian. +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ +#ifndef _LILO_H_ +#define _LILO_H_ 1 +#include "Config.h" +#include <iostream> + +class liloimage:public ConfigFile { +public: + bool isLinux() const; +}; + +class liloimages:public std::list<liloimage> { +public: + void remove(String const &s); + liloimage *find(String const &s) const; + liloimage *operator[](String const &s) const { return find(s); } +}; + +class liloconf { + friend std::ostream &operator <<(std::ostream &os, liloconf const &l); + friend std::ostream &operator <<(std::ostream &os, liloconf const *l); +public: + liloconf(String const &filename="/etc/lilo.conf"); + void set(StringList const &s); + void set(String const &s); + void writeFile(String const &filename); + bool const isOk(); + String const liloOut(); + bool install(bool probeonly=false); + bool probe(); + void addLinux(String const &label, String const &kernel, String const &root="", String const &initrd="", bool optional=false, String const &append="", String const &vga="", bool readonly=true, String const &literal="", String const &ramdisk=""); + void addOther(String const &name, String const &partition, bool const &optional=false, String const &chain=""); + void remove(String const &label); + void removeKernel(String const &kernel); + StringList const &entries() const; + String const dflt() const; + void setDefault(String const &dflt); + operator String() const; +protected: + void check() { install(true); } + bool ok; + String output; +public: + bool checked; + ConfigFile defaults; + liloimages images; +}; +std::ostream &operator <<(std::ostream &os, liloconf const &l); +std::ostream &operator <<(std::ostream &os, liloconf const *l); +#endif diff --git a/lilo-config/common/tests/Makefile.am b/lilo-config/common/tests/Makefile.am new file mode 100644 index 0000000..8059a44 --- /dev/null +++ b/lilo-config/common/tests/Makefile.am @@ -0,0 +1,9 @@ +String_LDADD = ../.libs/libcommon.a +noinst_PROGRAMS = String +INCLUDES = -I.. $(all_includes) + +String_SOURCES = \ + String.cc + +messages: + diff --git a/lilo-config/common/tests/String.cc b/lilo-config/common/tests/String.cc new file mode 100644 index 0000000..7b0b60e --- /dev/null +++ b/lilo-config/common/tests/String.cc @@ -0,0 +1,77 @@ +/* +** +** Copyright (C) 2000 by Bernhard Rosenkraenzer +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-devel@kde.org +*/ + +using namespace std; + +#include <String.h> +int main(int argc, char **argv) +{ + int bugs=0; + String s="Microsoft sucks! Red Hat doesn't suck!"; + String t="Microsoft sucks! Destroy Microsoft! Microsoft must die!"; + String u="Microsoft sucks!"; + if(s.left(16)!="Microsoft sucks!") { + cerr << "left() seems to be broken." << endl; + bugs++; + } + if(s.right(21) != "Red Hat doesn't suck!") { + cerr << "right() seems to be broken." << endl; + bugs++; + } + if(s.mid(18) != 'R') { + cerr << "mid() with one parameter seems to be broken." << endl; + bugs++; + } + if(s.mid(18, 7) != "Red Hat") { + cerr << "mid() with 2 parameters seems to be broken." << endl; + bugs++; + } + if(s.regex("Red ?[Hh]at|RED ?HAT")!="Red Hat") { + cerr << "regex() seems to be broken." << endl; + bugs++; + } + if(!s.contains("Red Hat")) { + cerr << "contains() seems to be broken." << endl; + bugs++; + } + if(t.replace("Microsoft", "Windows", false) != "Windows sucks! Destroy Microsoft! Microsoft must die!") { + cerr << "replace() [once] seems to be broken." << endl; + bugs++; + } + if(t.replace("Microsoft", "Windows") != "Windows sucks! Destroy Windows! Windows must die!") { + cerr << "replace() [all] seems to be broken." << endl; + bugs++; + } + if(u.replace("Microsoft", "Windows") != "Windows sucks!") { + cerr << "replace() [all, test case 2] seems to be broken." << endl; + bugs++; + } + + if(bugs==0) + cout << "No bugs in String class detected." << endl; + return bugs; +} |