Logo Search packages:      
Sourcecode: bibledit version File versions  Download package

bibledit-olpc-libraries.cpp

/*
** Copyright (C) 2003-2006 Teus Benschop.
**  
** 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; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/


#include <exception>
#include <stdexcept>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
#include <sstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <config.h>
#include <vector>
#include <set>


using namespace std;


/*
This utilitiy helps in installing Bibledit on the OLPC.

It gathers all libraries that Bibledit, and its dependencies, use.
It reads a file that contains a list of all files already on the OlPC.
It then determines which libraries and files are still missing.
It will then create a gzipped tarball that contains all these libraries.
Also Bibledit itself will be put in it.

If this tarball is unpacked in the OLPC, then Bibledit will work there.
*/


void read_dependencies (const string& program, set<string>& all_dependencies, vector<string>& new_dependencies)
{
  // Execute the command "ldd program" and collect its output.
  FILE *stream;
  string command = "ldd " + program;
  stream = popen (command.c_str (), "r");
  char buf[1024];
  while (fgets (buf, sizeof (buf), stream)) {
    string dependency = buf;
    // Remove newline at the end.
    dependency.erase (dependency.length() - 1, 1); 
    // Find path to library.
    size_t position = dependency.find ("/");
    if (position != string::npos) {
      dependency.erase (0, position);
      position = dependency.find (" ");
      dependency.erase (position, 100);
      // If libraries not already found, insert it and add it to the list of the ones still to check.
      if (all_dependencies.find (dependency) == all_dependencies.end()) {
        all_dependencies.insert (dependency);
        new_dependencies.push_back (dependency);
      }
    }
  }
  pclose (stream);
}


string unix_which (const string program)
// Return full path of program, e.g. "bibledit" would normally return "/usr/bin/bibledit".
{
  string path;
  FILE *stream;
  string command = "which " + program;
  stream = popen (command.c_str (), "r");
  char buf[1024];
  if (fgets (buf, sizeof (buf), stream)) {
    path = buf;
    path.erase (path.length() - 1, 1); 
    size_t position = path.find (" ");
    if (position != string::npos) {
      path.erase (0, position);
    }
  }
  pclose (stream);
  return path;
}


string read_symlink (const string& path)
{
  // Todo
  string links_to;
  FILE *stream;
  string command = "ls -l " + path;
  stream = popen (command.c_str (), "r");
  char buf[1024];
  if (fgets (buf, sizeof (buf), stream)) {
    string s = buf;
    // Remove newline at the end.
    s.erase (s.length() - 1, 1); 
    if (s.substr (0, 1) == "l") {
      size_t position;
      position = s.find ("->");
      if (position != string::npos) {
        s.erase (0, position + 3);
        position = path.find_last_of ("/");
        string directory = path.substr (0, ++position);
        links_to = directory + s;        
      }
    }
  }
  pclose (stream);
  return links_to;
}


int main(int argc, char *argv[])
{
  // Usage info.
  if (argc == 1) {
    cout << "Bibledit for OLPC Librarian " << PACKAGE_VERSION << endl;
    cout << "Produces a tarball with all libraries Bibledit depends on," << endl;
    cout << "except the ones listed in a ls -R file." << endl;
    cout << "Usage:" << endl;
    cout << "bibledit-olpc-libraries path/to/olpc-libraries tarball" << endl;
    cout << "/path/to/olpc-libraries points to a file, created with ls -R, that lists all" << endl;
    cout << "files on the OLPC" << endl;
    cout << "tarball is the name of the gzipped tarball that will be created, with all" << endl;
    cout << " libraries that need to be transferred to the OLPC image" << endl;
    return 0;
  }
  // Load names of all files already on the OLPC.
  set<string> olpc_files;
  {
    cout << "Reading files already on the OLPC from " << argv[1] << endl;
    vector<string> lines;
    ifstream in (argv[1]);
    string s;
    while (getline (in, s)) {
      lines.push_back (s);
    }
    string prefix_path;
    prefix_path = lines[0];
    prefix_path.erase (prefix_path.find (":"), 1);
    string file_directory;
    for (unsigned int i = 0; i < lines.size(); i ++) {
      size_t position = lines[i].find (":");
      if (position != string::npos) {
        file_directory = lines[i];
        file_directory.erase (position, 1);
        file_directory.erase (0, prefix_path.length());
      } else {
        olpc_files.insert (file_directory + "/" + lines[i]);
      }
    }
  }
  cout << olpc_files.size() << " files on the OLPC" << endl;
  // Storage.
  vector<string> programs_libraries_to_process;
  set<string> all_dependencies;
  // Initially load all programs Bibledit uses in the list of dependencies to process.
  programs_libraries_to_process.push_back (unix_which ("bibledit"));
  programs_libraries_to_process.push_back (unix_which ("scripturechecks"));
  programs_libraries_to_process.push_back (unix_which ("which"));
  programs_libraries_to_process.push_back (unix_which ("grep"));
  programs_libraries_to_process.push_back (unix_which ("chmod"));
  programs_libraries_to_process.push_back (unix_which ("test"));
  programs_libraries_to_process.push_back (unix_which ("tee"));
  programs_libraries_to_process.push_back (unix_which ("date"));
  programs_libraries_to_process.push_back (unix_which ("tail"));
  programs_libraries_to_process.push_back (unix_which ("gzip"));
  programs_libraries_to_process.push_back (unix_which ("gunzip"));
  programs_libraries_to_process.push_back (unix_which ("iconv"));
  programs_libraries_to_process.push_back (unix_which ("strings"));
  programs_libraries_to_process.push_back (unix_which ("killall"));
  programs_libraries_to_process.push_back (unix_which ("mkfifo"));
  programs_libraries_to_process.push_back (unix_which ("cat"));
  programs_libraries_to_process.push_back (unix_which ("sort"));
  programs_libraries_to_process.push_back (unix_which ("head"));
  // Load the list in thhttp://people.redhat.com/berrange/olpc/sdke dependencies.
  for (unsigned int i = 0; i < programs_libraries_to_process.size(); i++) {
    all_dependencies.insert (programs_libraries_to_process[i]);  
  }
  // Go through all programs and libraries to check, and handle all their dependencies.
  unsigned int process_pointer = 0;
  do {
    read_dependencies (programs_libraries_to_process[process_pointer], all_dependencies, programs_libraries_to_process);
    process_pointer++;
  } while (process_pointer < programs_libraries_to_process.size());
  cout << "Bibledit depends on " << all_dependencies.size() << " programs and libraries" << endl;  
  // Find out which libraries are still missing.
  vector<string> missing_libraries;
  {
    vector<string> dependencies (all_dependencies.begin(), all_dependencies.end());
    for (unsigned int i = 0; i < dependencies.size(); i++) {
      if (olpc_files.find (dependencies[i]) == olpc_files.end())
        missing_libraries.push_back (dependencies[i]);
    }
  }
  // Check all missing libraries, deal with symlinks and what the point to.
  vector<string> missing_symlinks;
  set<string> missing_files_set;
  for (unsigned int i = 0; i < missing_libraries.size(); i++) {
    string symlink_path = read_symlink (missing_libraries[i]);
    if (!symlink_path.empty()) {
      missing_symlinks.push_back (missing_libraries[i]);
      if (olpc_files.find (symlink_path) == olpc_files.end())
        missing_files_set.insert (symlink_path);

    } else {
      missing_files_set.insert (missing_libraries[i]);
    }
  }
  vector<string> missing_files (missing_files_set.begin(), missing_files_set.end());
  vector <string> tarfiles;
  cout << "Files to be copied to the OLPC:" << endl; 
  for (unsigned int i = 0; i < missing_files.size(); i++) {
    cout << "  " << missing_files[i] << endl;
    tarfiles.push_back (missing_files[i]);
  }
  cout << "Symlinks to be copied to the OLPC:" << endl; 
  for (unsigned int i = 0; i < missing_symlinks.size(); i++) {
    cout << "  " << missing_symlinks[i] << endl;
    tarfiles.push_back (missing_symlinks[i]);
  }
  // Add runtime and shared data directories to it, and other parts belonging to Bibledit.
  cout << "Adding some programs and data directories" << endl;
  tarfiles.push_back ("/usr/var/bibledit");
  tarfiles.push_back ("/usr/share/bibledit/*");
  tarfiles.push_back ("/usr/share/scricheck/*");
  tarfiles.push_back ("/usr/bin/sc-*");
  tarfiles.push_back ("/usr/bin/bibledit.*");
  // Create tarball and gzip it.
  string tarball = argv[2];
  tarball.append (".tar");
  unlink (tarball.c_str());
  string command = "tar -cP";
  for (unsigned int i = 0; i < tarfiles.size(); i++) {
    command.append (" " + tarfiles[i]);
  }
  command.append (" > " + tarball);
  system (command.c_str());
  string gzipped_tarball = tarball + ".gz";
  unlink (gzipped_tarball.c_str());
  command = "gzip " + tarball;
  system (command.c_str());  
  cout << "Created gzipped tarball " << gzipped_tarball << endl;
  return 0;
}

Generated by  Doxygen 1.6.0   Back to index