[280] | 1 | /* raptoptions.cc - configuration handling |
---|
| 2 | * |
---|
| 3 | * Copyright (c) 2000, 2001 Conectiva S/A |
---|
| 4 | * |
---|
| 5 | * Author: Alfredo K. Kojima <kojima@conectiva.com.br> |
---|
| 6 | * |
---|
| 7 | * This program is free software; you can redistribute it and/or |
---|
| 8 | * modify it under the terms of the GNU General Public License as |
---|
| 9 | * published by the Free Software Foundation; either version 2 of the |
---|
| 10 | * License, or (at your option) any later version. |
---|
| 11 | * |
---|
| 12 | * This program is distributed in the hope that it will be useful, |
---|
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 15 | * GNU General Public License for more details. |
---|
| 16 | * |
---|
| 17 | * You should have received a copy of the GNU General Public License |
---|
| 18 | * along with this program; if not, write to the Free Software |
---|
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
---|
| 20 | * USA |
---|
| 21 | */ |
---|
| 22 | |
---|
| 23 | |
---|
| 24 | |
---|
| 25 | #include "config.h" |
---|
| 26 | #include <fstream> |
---|
| 27 | #include <sstream> |
---|
| 28 | #include <dirent.h> |
---|
| 29 | |
---|
| 30 | #include <apt-pkg/error.h> |
---|
| 31 | #include <apt-pkg/configuration.h> |
---|
| 32 | #include <apt-pkg/tagfile.h> |
---|
| 33 | #include <apt-pkg/policy.h> |
---|
| 34 | #include <apt-pkg/sptr.h> |
---|
| 35 | #include <apt-pkg/strutl.h> |
---|
| 36 | |
---|
| 37 | #include "rconfiguration.h" |
---|
| 38 | #include "raptoptions.h" |
---|
| 39 | |
---|
| 40 | #include "i18n.h" |
---|
| 41 | |
---|
| 42 | |
---|
| 43 | RAPTOptions *_roptions = new RAPTOptions; |
---|
| 44 | |
---|
| 45 | using namespace std; |
---|
| 46 | |
---|
| 47 | ostream &operator<<(ostream &os, const RAPTOptions::packageOptions &o) |
---|
| 48 | { |
---|
| 49 | os << o.isNew; |
---|
| 50 | return os; |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | istream &operator>>(istream &is, RAPTOptions::packageOptions &o) |
---|
| 54 | { |
---|
| 55 | is >> o.isNew; |
---|
| 56 | return is; |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | |
---|
| 60 | bool RAPTOptions::store() |
---|
| 61 | { |
---|
| 62 | ofstream out; |
---|
| 63 | if (!RPackageOptionsFile(out)) |
---|
| 64 | return false; |
---|
| 65 | |
---|
| 66 | for (packageOptionsIter it = _roptions->_packageOptions.begin(); |
---|
| 67 | it != _roptions->_packageOptions.end(); it++) { |
---|
| 68 | // we only write out if it's new and the pkgname is not empty |
---|
| 69 | if ((*it).second.isNew && !(*it).first.empty()) |
---|
| 70 | out << (*it).first << " " << (*it).second << endl; |
---|
| 71 | } |
---|
| 72 | return true; |
---|
| 73 | } |
---|
| 74 | |
---|
| 75 | |
---|
| 76 | bool RAPTOptions::restore() |
---|
| 77 | { |
---|
| 78 | string pkg, line; |
---|
| 79 | packageOptions o; |
---|
| 80 | |
---|
| 81 | //cout << "bool RAPTOptions::restore()" << endl; |
---|
| 82 | |
---|
| 83 | ifstream in; |
---|
| 84 | if (!RPackageOptionsFile(in)) |
---|
| 85 | return false; |
---|
| 86 | |
---|
| 87 | // new stuff |
---|
| 88 | while (!in.eof()) { |
---|
| 89 | getline(in, line); |
---|
| 90 | istringstream strstr(line.c_str()); |
---|
| 91 | strstr >> pkg >> o >> ws; |
---|
| 92 | _packageOptions[pkg] = o; |
---|
| 93 | } |
---|
| 94 | |
---|
| 95 | // upgrade code for older synaptic versions, can go away in the future |
---|
| 96 | if(FileExists(RConfDir()+"/preferences")) |
---|
| 97 | rename(string(RConfDir()+"/preferences").c_str(), |
---|
| 98 | string(RStateDir()+"/preferences").c_str()); |
---|
| 99 | |
---|
| 100 | |
---|
| 101 | // pining stuff |
---|
| 102 | string File = RStateDir() + "/preferences"; |
---|
| 103 | |
---|
| 104 | if (!FileExists(File)) |
---|
| 105 | return true; |
---|
| 106 | |
---|
| 107 | FileFd Fd(File, FileFd::ReadOnly); |
---|
| 108 | pkgTagFile TF(&Fd); |
---|
| 109 | if (_error->PendingError() == true) { |
---|
| 110 | return false; |
---|
| 111 | } |
---|
| 112 | pkgTagSection Tags; |
---|
| 113 | while (TF.Step(Tags) == true) { |
---|
| 114 | string Name = Tags.FindS("Package"); |
---|
| 115 | if (Name.empty() == true) |
---|
| 116 | return _error-> |
---|
| 117 | Error(_ |
---|
| 118 | ("Invalid record in the preferences file, no Package header")); |
---|
| 119 | if (Name == "*") |
---|
| 120 | Name = string(); |
---|
| 121 | |
---|
| 122 | const char *Start; |
---|
| 123 | const char *End; |
---|
| 124 | if (Tags.Find("Pin", Start, End) == false) |
---|
| 125 | continue; |
---|
| 126 | |
---|
| 127 | const char *Word = Start; |
---|
| 128 | for (; Word != End && isspace(*Word) == 0; Word++); |
---|
| 129 | |
---|
| 130 | // Parse the type, we are only interesseted in "version" for now |
---|
| 131 | pkgVersionMatch::MatchType Type; |
---|
| 132 | if (stringcasecmp(Start, Word, "version") == 0 && Name.empty() == false) |
---|
| 133 | Type = pkgVersionMatch::Version; |
---|
| 134 | else |
---|
| 135 | continue; |
---|
| 136 | for (; Word != End && isspace(*Word) != 0; Word++); |
---|
| 137 | |
---|
| 138 | setPackageLock(Name.c_str(), true); |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | // deborphan stuff |
---|
| 142 | rereadOrphaned(); |
---|
| 143 | |
---|
| 144 | // debconf stuff |
---|
| 145 | rereadDebconf(); |
---|
| 146 | |
---|
| 147 | return true; |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | bool RAPTOptions::getPackageDebconf(const char *package) |
---|
| 151 | { |
---|
| 152 | string tmp = string(package); |
---|
| 153 | |
---|
| 154 | if (_packageOptions.find(tmp) == _packageOptions.end()) |
---|
| 155 | return false; |
---|
| 156 | |
---|
| 157 | //cout << "getPackageOrphaned("<<package<<") called"<<endl; |
---|
| 158 | return _packageOptions[tmp].isDebconf; |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | |
---|
| 162 | void RAPTOptions::setPackageDebconf(const char *package, bool flag) |
---|
| 163 | { |
---|
| 164 | //cout << "debconf called pkg: " << package << endl; |
---|
| 165 | _packageOptions[string(package)].isDebconf = flag; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | void RAPTOptions::rereadDebconf() |
---|
| 169 | { |
---|
| 170 | //cout << "void RAPTOptions::rereadDebconf()" << endl; |
---|
| 171 | |
---|
| 172 | // forget about any previously debconf packages |
---|
| 173 | for (packageOptionsIter it = _roptions->_packageOptions.begin(); |
---|
| 174 | it != _roptions->_packageOptions.end(); it++) { |
---|
| 175 | (*it).second.isDebconf = false; |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | // read dir |
---|
| 179 | const char infodir[] = "/var/lib/dpkg/info"; |
---|
| 180 | const char configext[] = ".config"; |
---|
| 181 | |
---|
| 182 | DIR *dir; |
---|
| 183 | struct dirent *dent; |
---|
| 184 | char *point; |
---|
| 185 | |
---|
| 186 | if ((dir = opendir(infodir)) == NULL) { |
---|
| 187 | //cerr << "Error opening " << infodir << endl; |
---|
| 188 | return; |
---|
| 189 | } |
---|
| 190 | for (int i = 3; (dent = readdir(dir)); i++) { |
---|
| 191 | if ((point = strrchr(dent->d_name, '.')) == NULL) |
---|
| 192 | continue; |
---|
| 193 | if (strcmp(point, configext) == 0) { |
---|
| 194 | bzero(point, strlen(point)); |
---|
| 195 | //cout << (dent->d_name) << endl; |
---|
| 196 | setPackageDebconf(dent->d_name, true); |
---|
| 197 | } |
---|
| 198 | } |
---|
| 199 | closedir(dir); |
---|
| 200 | } |
---|
| 201 | |
---|
| 202 | void RAPTOptions::rereadOrphaned() |
---|
| 203 | { |
---|
| 204 | // forget about any previously orphaned packages |
---|
| 205 | for (packageOptionsIter it = _roptions->_packageOptions.begin(); |
---|
| 206 | it != _roptions->_packageOptions.end(); it++) { |
---|
| 207 | (*it).second.isOrphaned = false; |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | //mvo: call deborphan and read package list from it |
---|
| 211 | // TODO: make deborphan a library to make this cleaner |
---|
| 212 | FILE *fp; |
---|
| 213 | char buf[255]; |
---|
| 214 | char cmd[] = "/usr/bin/deborphan"; |
---|
| 215 | //FIXME: fail silently if deborphan is not installed - change this? |
---|
| 216 | if (!FileExists(cmd)) |
---|
| 217 | return; |
---|
| 218 | fp = popen(cmd, "r"); |
---|
| 219 | if (fp == NULL) { |
---|
| 220 | //cerr << "deborphan failed" << endl; |
---|
| 221 | return; |
---|
| 222 | } |
---|
| 223 | while (fgets(buf, 254, fp) != NULL) { |
---|
| 224 | //mvo: FIXME this sucks (remove newline at end) |
---|
| 225 | buf[strlen(buf) - 1] = 0; |
---|
| 226 | //cout << "buf: " << buf << endl; |
---|
| 227 | setPackageOrphaned(buf, true); |
---|
| 228 | } |
---|
| 229 | pclose(fp); |
---|
| 230 | } |
---|
| 231 | |
---|
| 232 | |
---|
| 233 | bool RAPTOptions::getPackageOrphaned(const char *package) |
---|
| 234 | { |
---|
| 235 | string tmp = string(package); |
---|
| 236 | |
---|
| 237 | if (_packageOptions.find(tmp) == _packageOptions.end()) |
---|
| 238 | return false; |
---|
| 239 | |
---|
| 240 | //cout << "getPackageOrphaned("<<package<<") called"<<endl; |
---|
| 241 | return _packageOptions[tmp].isOrphaned; |
---|
| 242 | } |
---|
| 243 | |
---|
| 244 | |
---|
| 245 | void RAPTOptions::setPackageOrphaned(const char *package, bool flag) |
---|
| 246 | { |
---|
| 247 | //cout << "orphaned called pkg: " << package << endl; |
---|
| 248 | _packageOptions[string(package)].isOrphaned = flag; |
---|
| 249 | } |
---|
| 250 | |
---|
| 251 | |
---|
| 252 | bool RAPTOptions::getPackageLock(const char *package) |
---|
| 253 | { |
---|
| 254 | string tmp = string(package); |
---|
| 255 | |
---|
| 256 | if (_packageOptions.find(tmp) == _packageOptions.end()) |
---|
| 257 | return false; |
---|
| 258 | |
---|
| 259 | return _packageOptions[tmp].isLocked; |
---|
| 260 | } |
---|
| 261 | |
---|
| 262 | |
---|
| 263 | void RAPTOptions::setPackageLock(const char *package, bool lock) |
---|
| 264 | { |
---|
| 265 | _packageOptions[string(package)].isLocked = lock; |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | bool RAPTOptions::getPackageNew(const char *package) |
---|
| 269 | { |
---|
| 270 | string tmp = string(package); |
---|
| 271 | |
---|
| 272 | if (_packageOptions.find(tmp) == _packageOptions.end()) |
---|
| 273 | return false; |
---|
| 274 | |
---|
| 275 | return _packageOptions[tmp].isNew; |
---|
| 276 | } |
---|
| 277 | |
---|
| 278 | void RAPTOptions::setPackageNew(const char *package, bool lock) |
---|
| 279 | { |
---|
| 280 | _packageOptions[string(package)].isNew = lock; |
---|
| 281 | } |
---|
| 282 | |
---|
| 283 | void RAPTOptions::forgetNewPackages() |
---|
| 284 | { |
---|
| 285 | for (packageOptionsIter it = _roptions->_packageOptions.begin(); |
---|
| 286 | it != _roptions->_packageOptions.end(); it++) { |
---|
| 287 | (*it).second.isNew = false; |
---|
| 288 | } |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | bool RAPTOptions::getFlag(const char *key) |
---|
| 292 | { |
---|
| 293 | if (_options.find(key) != _options.end()) |
---|
| 294 | return _options[string(key)] == "true"; |
---|
| 295 | else |
---|
| 296 | return false; |
---|
| 297 | } |
---|
| 298 | |
---|
| 299 | |
---|
| 300 | string RAPTOptions::getString(const char *key) |
---|
| 301 | { |
---|
| 302 | if (_options.find(key) != _options.end()) |
---|
| 303 | return _options[string(key)]; |
---|
| 304 | else |
---|
| 305 | return ""; |
---|
| 306 | } |
---|
| 307 | |
---|
| 308 | |
---|
| 309 | void RAPTOptions::setFlag(const char *key, bool value) |
---|
| 310 | { |
---|
| 311 | _options[string(key)] = string(value ? "true" : "false"); |
---|
| 312 | } |
---|
| 313 | |
---|
| 314 | |
---|
| 315 | void RAPTOptions::setString(const char *key, string value) |
---|
| 316 | { |
---|
| 317 | _options[string(key)] = value; |
---|
| 318 | } |
---|