X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/cec8c646c79e40d928464b08a6f2e3ea62bb1611..e39698a485e332742b935292dc4329abf19cbb53:/apt-pkg/cdrom.cc diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 2a914c665..2635ede76 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -1,26 +1,31 @@ /* */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include #include -#include #include #include #include #include #include -#include "indexcopy.h" +#include using namespace std; @@ -55,66 +60,91 @@ bool pkgCdrom::FindPackages(string CD, return _error->Errno("chdir","Unable to change to %s",CD.c_str()); // Look for a .disk subdirectory - struct stat Buf; - if (stat(".disk",&Buf) == 0) + if (DirectoryExists(".disk") == true) { if (InfoDir.empty() == true) InfoDir = CD + ".disk/"; } // Don't look into directories that have been marked to ingore. - if (stat(".aptignr",&Buf) == 0) + if (RealFileExists(".aptignr") == true) return true; - /* Check _first_ for a signature file as apt-cdrom assumes that all files under a Packages/Source file are in control of that file and stops the scanning */ - if (stat("Release.gpg",&Buf) == 0) + if (RealFileExists("Release.gpg") == true || RealFileExists("InRelease") == true) { SigList.push_back(CD); } + /* Aha! We found some package files. We assume that everything under this dir is controlled by those package files so we don't look down anymore */ - if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0) + std::vector const compressor = APT::Configuration::getCompressors(); + for (std::vector::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) { + if (RealFileExists(std::string("Packages").append(c->Extension).c_str()) == false) + continue; + + if (_config->FindB("Debug::aptcdrom",false) == true) + std::clog << "Found Packages in " << CD << std::endl; List.push_back(CD); - + // Continue down if thorough is given if (_config->FindB("APT::CDROM::Thorough",false) == false) return true; + break; } - if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0) + for (std::vector::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) { + if (RealFileExists(std::string("Sources").append(c->Extension).c_str()) == false) + continue; + + if (_config->FindB("Debug::aptcdrom",false) == true) + std::clog << "Found Sources in " << CD << std::endl; SList.push_back(CD); - + // Continue down if thorough is given if (_config->FindB("APT::CDROM::Thorough",false) == false) return true; + break; } - // see if we find translatin indexes - if (stat("i18n",&Buf) == 0) + // see if we find translation indices + if (DirectoryExists("i18n") == true) { D = opendir("i18n"); for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) { - if(strstr(Dir->d_name,"Translation") != NULL) + if(strncmp(Dir->d_name, "Translation-", strlen("Translation-")) != 0) + continue; + string file = Dir->d_name; + for (std::vector::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) { - if (_config->FindB("Debug::aptcdrom",false) == true) - std::clog << "found translations: " << Dir->d_name << "\n"; - string file = Dir->d_name; - if(file.substr(file.size()-3,file.size()) == ".gz") - file = file.substr(0,file.size()-3); - TransList.push_back(CD+"i18n/"+ file); + string fileext = flExtension(file); + if (file == fileext) + fileext.clear(); + else if (fileext.empty() == false) + fileext = "." + fileext; + + if (c->Extension == fileext) + { + if (_config->FindB("Debug::aptcdrom",false) == true) + std::clog << "Found translation " << Dir->d_name << " in " << CD << "i18n/" << std::endl; + file.erase(file.size() - fileext.size()); + TransList.push_back(CD + "i18n/" + file); + break; + } } } closedir(D); } - D = opendir("."); if (D == 0) return _error->Errno("opendir","Unable to read %s",CD.c_str()); @@ -241,6 +271,29 @@ bool pkgCdrom::DropBinaryArch(vector &List) --I; // the next entry is at the same index after the erase } + return true; +} + /*}}}*/ +// DropTranslation - Dump unwanted Translation- files /*{{{*/ +// --------------------------------------------------------------------- +/* Here we drop everything that is not configured in Acquire::Languages */ +bool pkgCdrom::DropTranslation(vector &List) +{ + for (unsigned int I = 0; I < List.size(); I++) + { + const char *Start; + if ((Start = strstr(List[I].c_str(), "/Translation-")) == NULL) + continue; + Start += strlen("/Translation-"); + + if (APT::Configuration::checkLanguage(Start, true) == true) + continue; + + // not accepted -> Erase it + List.erase(List.begin() + I); + --I; // the next entry is at the same index after the erase + } + return true; } /*}}}*/ @@ -249,30 +302,43 @@ bool pkgCdrom::DropBinaryArch(vector &List) /* Here we go and stat every file that we found and strip dup inodes. */ bool pkgCdrom::DropRepeats(vector &List,const char *Name) { + bool couldFindAllFiles = true; // Get a list of all the inodes ino_t *Inodes = new ino_t[List.size()]; - for (unsigned int I = 0; I != List.size(); I++) + for (unsigned int I = 0; I != List.size(); ++I) { struct stat Buf; - if (stat((List[I] + Name).c_str(),&Buf) != 0 && - stat((List[I] + Name + ".gz").c_str(),&Buf) != 0) - _error->Errno("stat","Failed to stat %s%s",List[I].c_str(), - Name); - Inodes[I] = Buf.st_ino; - } - - if (_error->PendingError() == true) { - delete[] Inodes; - return false; + bool found = false; + + std::vector const compressor = APT::Configuration::getCompressors(); + for (std::vector::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) + { + std::string filename = std::string(List[I]).append(Name).append(c->Extension); + if (stat(filename.c_str(), &Buf) != 0) + continue; + Inodes[I] = Buf.st_ino; + found = true; + break; + } + + if (found == false) + { + _error->Errno("stat","Failed to stat %s%s",List[I].c_str(), Name); + couldFindAllFiles = false; + Inodes[I] = 0; + } } - + // Look for dups for (unsigned int I = 0; I != List.size(); I++) { + if (Inodes[I] == 0) + continue; for (unsigned int J = I+1; J < List.size(); J++) { // No match - if (Inodes[J] != Inodes[I]) + if (Inodes[J] == 0 || Inodes[J] != Inodes[I]) continue; // We score the two paths.. and erase one @@ -298,19 +364,19 @@ bool pkgCdrom::DropRepeats(vector &List,const char *Name) List.erase(List.begin()+I); } - return true; + return couldFindAllFiles; } /*}}}*/ // ReduceSourceList - Takes the path list and reduces it /*{{{*/ // --------------------------------------------------------------------- /* This takes the list of source list expressed entires and collects similar ones to form a single entry for each dist */ -void pkgCdrom::ReduceSourcelist(string CD,vector &List) +void pkgCdrom::ReduceSourcelist(string /*CD*/,vector &List) { sort(List.begin(),List.end()); // Collect similar entries - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { // Find a space.. string::size_type Space = (*I).find(' '); @@ -322,7 +388,8 @@ void pkgCdrom::ReduceSourcelist(string CD,vector &List) string Word1 = string(*I,Space,SSpace-Space); string Prefix = string(*I,0,Space); - for (vector::iterator J = List.begin(); J != I; J++) + string Component = string(*I,SSpace); + for (vector::iterator J = List.begin(); J != I; ++J) { // Find a space.. string::size_type Space2 = (*J).find(' '); @@ -336,9 +403,11 @@ void pkgCdrom::ReduceSourcelist(string CD,vector &List) continue; if (string(*J,Space2,SSpace2-Space2) != Word1) continue; - - *J += string(*I,SSpace); - *I = string(); + + string Component2 = string(*J, SSpace2) + " "; + if (Component2.find(Component + " ") == std::string::npos) + *J += Component; + I->clear(); } } @@ -368,28 +437,12 @@ bool pkgCdrom::WriteDatabase(Configuration &Cnf) /* Write out all of the configuration directives by walking the configuration tree */ - const Configuration::Item *Top = Cnf.Tree(0); - for (; Top != 0;) - { - // Print the config entry - if (Top->Value.empty() == false) - Out << Top->FullTag() + " \"" << Top->Value << "\";" << endl; - - if (Top->Child != 0) - { - Top = Top->Child; - continue; - } - - while (Top != 0 && Top->Next == 0) - Top = Top->Parent; - if (Top != 0) - Top = Top->Next; - } + Cnf.Dump(Out, NULL, "%f \"%v\";\n", false); Out.close(); - - link(DFile.c_str(),string(DFile + '~').c_str()); + + if (FileExists(DFile) == true) + rename(DFile.c_str(), (DFile + '~').c_str()); if (rename(NewFile.c_str(),DFile.c_str()) != 0) return _error->Errno("rename","Failed to rename %s.new to %s", DFile.c_str(),DFile.c_str()); @@ -405,7 +458,7 @@ bool pkgCdrom::WriteDatabase(Configuration &Cnf) that were the same. */ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) { - if (List.size() == 0) + if (List.empty() == true) return true; string File = _config->FindFile("Dir::Etc::sourcelist"); @@ -455,7 +508,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) if (First == true) { - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { string::size_type Space = (*I).find(' '); if (Space == string::npos) @@ -489,7 +542,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) // Just in case the file was empty if (First == true) { - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { string::size_type Space = (*I).find(' '); if (Space == string::npos) @@ -502,7 +555,7 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) Out.close(); - rename(File.c_str(),string(File + '~').c_str()); + rename(File.c_str(), (File + '~').c_str()); if (rename(NewFile.c_str(),File.c_str()) != 0) return _error->Errno("rename","Failed to rename %s.new to %s", File.c_str(),File.c_str()); @@ -510,45 +563,68 @@ bool pkgCdrom::WriteSourceList(string Name,vector &List,bool Source) return true; } /*}}}*/ -bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log) /*{{{*/ +bool pkgCdrom::MountAndIdentCDROM(Configuration &Database, std::string &CDROM, std::string &ident, pkgCdromStatus * const log, bool const interactive)/*{{{*/ { - stringstream msg; - // Startup - string CDROM = _config->FindDir("Acquire::cdrom::mount"); + CDROM = _config->FindDir("Acquire::cdrom::mount"); if (CDROM[0] == '.') CDROM= SafeGetCWD() + '/' + CDROM; if (log != NULL) { - msg.str(""); - ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"), - CDROM.c_str()); - log->Update(msg.str()); + string msg; + log->SetTotal(STEP_LAST); + strprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str()); + log->Update(msg, STEP_PREPARE); + } + + // Unmount the CD and get the user to put in the one they want + if (_config->FindB("APT::CDROM::NoMount", false) == false) + { + if (interactive == true) + { + if(log != NULL) + log->Update(_("Unmounting CD-ROM...\n"), STEP_LAST); + UnmountCdrom(CDROM); + + if(log != NULL) + { + log->Update(_("Waiting for disc...\n"), STEP_WAIT); + if(!log->ChangeCdrom()) { + // user aborted + return false; + } + } + } + + // Mount the new CDROM + if(log != NULL) + log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT); + + if (MountCdrom(CDROM) == false) + return _error->Error("Failed to mount the cdrom."); } - if (MountCdrom(CDROM) == false) - return _error->Error("Failed to mount the cdrom."); // Hash the CD to get an ID if (log != NULL) - log->Update(_("Identifying.. ")); - + log->Update(_("Identifying... "), STEP_IDENT); if (IdentCdrom(CDROM,ident) == false) { ident = ""; + if (log != NULL) + log->Update("\n"); return false; } if (log != NULL) { - msg.str(""); - ioprintf(msg, "[%s]\n",ident.c_str()); - log->Update(msg.str()); + string msg; + strprintf(msg, "[%s]\n", ident.c_str()); + log->Update(msg); } // Read the database - Configuration Database; string DFile = _config->FindFile("Dir::State::cdroms"); if (FileExists(DFile) == true) { @@ -556,12 +632,22 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log) /*{{{*/ return _error->Error("Unable to read the cdrom database %s", DFile.c_str()); } + return true; +} + /*}}}*/ +bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log) /*{{{*/ +{ + Configuration Database; + std::string CDROM; + if (MountAndIdentCDROM(Database, CDROM, ident, log, false) == false) + return false; + if (log != NULL) { - msg.str(""); - ioprintf(msg, _("Stored label: %s\n"), - Database.Find("CD::"+ident).c_str()); - log->Update(msg.str()); + string msg; + strprintf(msg, _("Stored label: %s\n"), + Database.Find("CD::"+ident).c_str()); + log->Update(msg); } // Unmount and finish @@ -577,70 +663,13 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log) /*{{{*/ /*}}}*/ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ { - stringstream msg; - - // Startup - string CDROM = _config->FindDir("Acquire::cdrom::mount"); - if (CDROM[0] == '.') - CDROM= SafeGetCWD() + '/' + CDROM; - - if(log != NULL) - { - log->SetTotal(STEP_LAST); - msg.str(""); - ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str()); - log->Update(msg.str(), STEP_PREPARE); - } - - // Read the database Configuration Database; - string DFile = _config->FindFile("Dir::State::cdroms"); - if (FileExists(DFile) == true) - { - if (ReadConfigFile(Database,DFile) == false) - return _error->Error("Unable to read the cdrom database %s", - DFile.c_str()); - } - - // Unmount the CD and get the user to put in the one they want - if (_config->FindB("APT::CDROM::NoMount",false) == false) - { - if(log != NULL) - log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT); - UnmountCdrom(CDROM); - - if(log != NULL) - { - log->Update(_("Waiting for disc...\n"), STEP_WAIT); - if(!log->ChangeCdrom()) { - // user aborted - return false; - } - } - - // Mount the new CDROM - if(log != NULL) - log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT); - - if (MountCdrom(CDROM) == false) - return _error->Error("Failed to mount the cdrom."); - } - - // Hash the CD to get an ID - if(log != NULL) - log->Update(_("Identifying.. "), STEP_IDENT); - string ID; - if (IdentCdrom(CDROM,ID) == false) - { - if (log != NULL) - log->Update("\n"); + std::string ID, CDROM; + if (MountAndIdentCDROM(Database, CDROM, ID, log, true) == false) return false; - } + if(log != NULL) - { - log->Update("["+ID+"]\n"); - log->Update(_("Scanning disc for index files..\n"),STEP_SCAN); - } + log->Update(_("Scanning disc for index files...\n"),STEP_SCAN); // Get the CD structure vector List; @@ -656,18 +685,19 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ return false; } - chdir(StartDir.c_str()); + if (chdir(StartDir.c_str()) != 0) + return _error->Errno("chdir","Unable to change to %s", StartDir.c_str()); if (_config->FindB("Debug::aptcdrom",false) == true) { cout << "I found (binary):" << endl; - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) cout << *I << endl; cout << "I found (source):" << endl; - for (vector::iterator I = SourceList.begin(); I != SourceList.end(); I++) + for (vector::iterator I = SourceList.begin(); I != SourceList.end(); ++I) cout << *I << endl; cout << "I found (Signatures):" << endl; - for (vector::iterator I = SigList.begin(); I != SigList.end(); I++) + for (vector::iterator I = SigList.begin(); I != SigList.end(); ++I) cout << *I << endl; } @@ -677,18 +707,26 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ DropBinaryArch(List); DropRepeats(List,"Packages"); DropRepeats(SourceList,"Sources"); + // FIXME: We ignore stat() errors here as we usually have only one of those in use + // This has little potencial to drop 'valid' stat() errors as we know that one of these + // files need to exist, but it would be better if we would check it here + _error->PushToStack(); DropRepeats(SigList,"Release.gpg"); + DropRepeats(SigList,"InRelease"); + _error->RevertToStack(); DropRepeats(TransList,""); + if (_config->FindB("APT::CDROM::DropTranslation", true) == true) + DropTranslation(TransList); if(log != NULL) { - msg.str(""); - ioprintf(msg, _("Found %zu package indexes, %zu source indexes, " + string msg; + strprintf(msg, _("Found %zu package indexes, %zu source indexes, " "%zu translation indexes and %zu signatures\n"), List.size(), SourceList.size(), TransList.size(), SigList.size()); - log->Update(msg.str(), STEP_SCAN); + log->Update(msg, STEP_SCAN); } - if (List.size() == 0 && SourceList.size() == 0) + if (List.empty() == true && SourceList.empty() == true) { if (_config->FindB("APT::CDROM::NoMount",false) == false) UnmountCdrom(CDROM); @@ -704,7 +742,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ if (InfoDir.empty() == false && FileExists(InfoDir + "/info") == true) { - ifstream F(string(InfoDir + "/info").c_str()); + ifstream F((InfoDir + "/info").c_str()); if (!F == 0) getline(F,Name); @@ -712,15 +750,15 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ { // Escape special characters string::iterator J = Name.begin(); - for (; J != Name.end(); J++) + for (; J != Name.end(); ++J) if (*J == '"' || *J == ']' || *J == '[') *J = '_'; if(log != NULL) { - msg.str(""); - ioprintf(msg, _("Found label '%s'\n"), Name.c_str()); - log->Update(msg.str()); + string msg; + strprintf(msg, _("Found label '%s'\n"), Name.c_str()); + log->Update(msg); } Database.Set("CD::" + ID + "::Label",Name); } @@ -757,18 +795,26 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ // Escape special characters string::iterator J = Name.begin(); - for (; J != Name.end(); J++) + for (; J != Name.end(); ++J) if (*J == '"' || *J == ']' || *J == '[') *J = '_'; Database.Set("CD::" + ID,Name); if(log != NULL) { - msg.str(""); - ioprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str()); - log->Update(msg.str()); + string msg; + strprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str()); + log->Update(msg); log->Update(_("Copying package lists..."), STEP_COPY); } + + // check for existence and possibly create state directory for copying + string const listDir = _config->FindDir("Dir::State::lists"); + string const partialListDir = listDir + "partial/"; + if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false && + CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false) + return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str()); + // take care of the signatures and copy them if they are ok // (we do this before PackageCopy as it modifies "List" and "SourceList") SigVerify SignVerify; @@ -804,7 +850,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ if(log != NULL) log->Update(_("Source list entries for this disc are:\n")); - for (vector::iterator I = List.begin(); I != List.end(); I++) + for (vector::iterator I = List.begin(); I != List.end(); ++I) { string::size_type Space = (*I).find(' '); if (Space == string::npos) @@ -816,14 +862,14 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ if(log != NULL) { - msg.str(""); + stringstream msg; msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << " " << string(*I,Space+1) << endl; log->Update(msg.str()); } } - for (vector::iterator I = SourceList.begin(); I != SourceList.end(); I++) + for (vector::iterator I = SourceList.begin(); I != SourceList.end(); ++I) { string::size_type Space = (*I).find(' '); if (Space == string::npos) @@ -834,7 +880,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ } if(log != NULL) { - msg.str(""); + stringstream msg; msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << " " << string(*I,Space+1) << endl; log->Update(msg.str()); @@ -874,9 +920,7 @@ pkgUdevCdromDevices::Dlopen() /*{{{*/ libudev_handle = h; udev_new = (udev* (*)(void)) dlsym(h, "udev_new"); udev_enumerate_add_match_property = (int (*)(udev_enumerate*, const char*, const char*))dlsym(h, "udev_enumerate_add_match_property"); -#if 0 // FIXME: uncomment on next ABI break udev_enumerate_add_match_sysattr = (int (*)(udev_enumerate*, const char*, const char*))dlsym(h, "udev_enumerate_add_match_sysattr"); -#endif udev_enumerate_scan_devices = (int (*)(udev_enumerate*))dlsym(h, "udev_enumerate_scan_devices"); udev_enumerate_get_list_entry = (udev_list_entry* (*)(udev_enumerate*))dlsym(h, "udev_enumerate_get_list_entry"); udev_device_new_from_syspath = (udev_device* (*)(udev*, const char*))dlsym(h, "udev_device_new_from_syspath"); @@ -890,16 +934,14 @@ pkgUdevCdromDevices::Dlopen() /*{{{*/ return true; } /*}}}*/ - /*{{{*/ -// compatiblity only with the old API/ABI, can be removed on the next -// ABI break +// convenience interface, this will just call ScanForRemovable vector pkgUdevCdromDevices::Scan() -{ +{ bool CdromOnly = _config->FindB("APT::cdrom::CdromOnly", true); - return ScanForRemovable(CdromOnly); -}; + return ScanForRemovable(CdromOnly); +} /*}}}*/ /*{{{*/ vector @@ -918,10 +960,6 @@ pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly) if (CdromOnly) udev_enumerate_add_match_property(enumerate, "ID_CDROM", "1"); else { -#if 1 // FIXME: remove the next two lines on the next ABI break - int (*udev_enumerate_add_match_sysattr)(struct udev_enumerate *udev_enumerate, const char *property, const char *value); - udev_enumerate_add_match_sysattr = (int (*)(udev_enumerate*, const char*, const char*))dlsym(libudev_handle, "udev_enumerate_add_match_sysattr"); -#endif udev_enumerate_add_match_sysattr(enumerate, "removable", "1"); } @@ -948,7 +986,7 @@ pkgUdevCdromDevices::ScanForRemovable(bool CdromOnly) cdrom.DeviceName = string(devnode); if (mountpath != "") { cdrom.MountPath = mountpath; - string s = string(mountpath); + string s = mountpath; cdrom.Mounted = IsMounted(s); } else { cdrom.Mounted = false;