Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
updater.cpp File Reference
#include "bspatch.h"
#include "progressui.h"
#include "archivereader.h"
#include "errors.h"
#include "bzlib.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>

Go to the source code of this file.

Classes

class  AutoFD
class  Action
class  RemoveFile
class  AddFile
class  PatchFile
class  AddIfFile
class  PatchIfFile
class  ActionList

Defines

#define _O_BINARY   0
 

update.manifest


#define NULL   (0)
#define SSIZE_MAX   LONG_MAX
#define MAXPATHLEN   1024
#define LOG(args)   LogPrintf args
#define BACKUP_EXT   ".moz-backup"

Typedefs

typedef void(* ThreadFunc )(void *param)

Functions

static unsigned int crc32 (const unsigned char *buf, unsigned int len)
static void LogInit ()
static void LogFinish ()
static void LogPrintf (const char *fmt,...)
static PRUint32 mmin (PRUint32 a, PRUint32 b)
static char * mstrtok (const char *delims, char **str)
static void ensure_write_permissions (const char *path)
static int ensure_remove (const char *path)
static int ensure_open (const char *path, int flags, int options)
static int ensure_parent_dir (const char *path)
static int copy_file (const char *spath, const char *dpath)
static int backup_create (const char *path)
static int backup_restore (const char *path)
static int backup_discard (const char *path)
static void backup_finish (const char *path, int status)
static int DoUpdate ()
static void LaunchCallbackApp (const char *workingDir, int argc, char **argv)
static void WriteStatusFile (int status)
static void UpdateThreadFunc (void *param)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

unsigned int BZ2_crc32Table [256]
static char * gSourcePath
static ArchiveReader gArchiveReader
static const char kWhitespace [] = " \t"
static const char kNL [] = "\r\n"
static const char kQuote [] = "\""
static FILEgLogFP = NULL
static const int ACTION_DESCRIPTION_BUFSIZE = 256

Define Documentation

#define _O_BINARY   0

update.manifest

contents = 1*( line ) line = method LWS *( param LWS ) CRLF method = "add" | "remove" | "patch" CRLF = "\r\n" LWS = 1*( " " | "\t" )

Definition at line 91 of file updater.cpp.

#define BACKUP_EXT   ".moz-backup"

Definition at line 455 of file updater.cpp.

#define LOG (   args)    LogPrintf args

Definition at line 310 of file updater.cpp.

#define MAXPATHLEN   1024

Definition at line 110 of file updater.cpp.

#define NULL   (0)

Definition at line 95 of file updater.cpp.

#define SSIZE_MAX   LONG_MAX

Definition at line 99 of file updater.cpp.


Typedef Documentation

Definition at line 172 of file updater.cpp.


Function Documentation

static int backup_create ( const char *  path) [static]

Definition at line 458 of file updater.cpp.

{
  char backup[MAXPATHLEN];
  snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path);

  return copy_file(path, backup);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int backup_discard ( const char *  path) [static]

Definition at line 486 of file updater.cpp.

{
  char backup[MAXPATHLEN];
  snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path);

  int rv = ensure_remove(backup);
  if (rv)
    return WRITE_ERROR;

  return OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void backup_finish ( const char *  path,
int  status 
) [static]

Definition at line 499 of file updater.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

static int backup_restore ( const char *  path) [static]

Definition at line 469 of file updater.cpp.

{
  char backup[MAXPATHLEN];
  snprintf(backup, sizeof(backup), "%s" BACKUP_EXT, path);

  int rv = copy_file(backup, path);
  if (rv)
    return rv;

  rv = ensure_remove(backup);
  if (rv)
    return WRITE_ERROR;

  return OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int copy_file ( const char *  spath,
const char *  dpath 
) [static]

Definition at line 410 of file updater.cpp.

{
  int rv = ensure_parent_dir(dpath);
  if (rv)
    return rv;

  struct stat ss;

  AutoFD sfd = open(spath, O_RDONLY | _O_BINARY);
  if (sfd < 0 || fstat(sfd, &ss)) {
    LOG(("copy_file: failed to open or stat: %d,%s,%d\n", (int) sfd, spath, errno));
    return READ_ERROR;
  }

  AutoFD dfd = ensure_open(dpath, O_WRONLY | O_TRUNC | O_CREAT | _O_BINARY, ss.st_mode);
  if (dfd < 0) {
    LOG(("copy_file: failed to open: %s,%d\n", dpath, errno));
    return WRITE_ERROR;
  }

  char buf[BUFSIZ];
  int sc;
  while ((sc = read(sfd, buf, sizeof(buf))) > 0) {
    int dc;
    char *bp = buf;
    while ((dc = write(dfd, bp, (unsigned int) sc)) > 0) {
      if ((sc -= dc) == 0)
        break;
      bp += dc;
    }
    if (dc < 0) {
      LOG(("copy_file: failed to write: %d\n", errno));
      return WRITE_ERROR;
    }
  }
  if (sc < 0) {
    LOG(("copy_file: failed to read: %d\n", errno));
    return READ_ERROR;
  }

  return OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned int crc32 ( const unsigned char *  buf,
unsigned int  len 
) [static]

Definition at line 127 of file updater.cpp.

{
  unsigned int crc = 0xffffffffL;

  const unsigned char *end = buf + len;
  for (; buf != end; ++buf)
    crc = (crc << 8) ^ BZ2_crc32Table[(crc >> 24) ^ *buf];

  crc = ~crc;
  return crc;
}
int DoUpdate ( ) [static]

Definition at line 1307 of file updater.cpp.

{
  char manifest[MAXPATHLEN];
  snprintf(manifest, MAXPATHLEN, "%s/update.manifest", gSourcePath);

  // extract the manifest
  int rv = gArchiveReader.ExtractFile("update.manifest", manifest);
  if (rv)
    return rv;

  AutoFD mfd = open(manifest, O_RDONLY | _O_BINARY);
  if (mfd < 0)
    return READ_ERROR;

  struct stat ms;
  rv = fstat(mfd, &ms);
  if (rv)
    return READ_ERROR;

  char *mbuf = (char*) malloc(ms.st_size + 1);
  if (!mbuf)
    return MEM_ERROR;

  int r = ms.st_size;
  char *rb = mbuf;
  while (r) {
    int c = read(mfd, rb, mmin(SSIZE_MAX,r));
    if (c < 0)
      return READ_ERROR;

    r -= c;
    rb += c;

    if (c == 0 && r)
      return UNEXPECTED_ERROR;
  }
  mbuf[ms.st_size] = '\0';

  ActionList list;

  rb = mbuf;
  char *line;
  while((line = mstrtok(kNL, &rb)) != 0) {
    // skip comments
    if (*line == '#')
      continue;

    char *token = mstrtok(kWhitespace, &line);
    if (!token)
      return PARSE_ERROR;

    Action *action = NULL;
    if (strcmp(token, "remove") == 0) {
      action = new RemoveFile();
    }
    else if (strcmp(token, "add") == 0) {
      action = new AddFile();
    }
    else if (strcmp(token, "patch") == 0) {
      action = new PatchFile();
    }
    else if (strcmp(token, "add-if") == 0) {
      action = new AddIfFile();
    }
    else if (strcmp(token, "patch-if") == 0) {
      action = new PatchIfFile();
    }
    else {
      return PARSE_ERROR;
    }

    if (!action)
      return MEM_ERROR;

    rv = action->Parse(line);
    if (rv)
      return rv;

    list.Append(action);
  }

  rv = list.Prepare();
  if (rv)
    return rv;

  rv = list.Execute();

  list.Finish(rv);
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ensure_open ( const char *  path,
int  flags,
int  options 
) [static]

Definition at line 380 of file updater.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

static int ensure_parent_dir ( const char *  path) [static]

Definition at line 387 of file updater.cpp.

{
  int rv = OK;

  char *slash = (char *) strrchr(path, '/');
  if (slash)
  {
    *slash = '\0';
    rv = ensure_parent_dir(path);
    if (rv == OK) {
      rv = mkdir(path, 0755);
      // If the directory already exists, then ignore the error.
      if (rv < 0 && errno != EEXIST) {
        rv = WRITE_ERROR;
      } else {
        rv = OK;
      }
    }
    *slash = '/';
  }
  return rv;
}

Here is the caller graph for this function:

static int ensure_remove ( const char *  path) [static]

Definition at line 371 of file updater.cpp.

{
  ensure_write_permissions(path);
  int rv = remove(path);
  if (rv)
    LOG(("remove failed: %d,%d (%s)\n", rv, errno, path));
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ensure_write_permissions ( const char *  path) [static]

Definition at line 359 of file updater.cpp.

{
#ifdef XP_WIN
  (void)_chmod(path, _S_IREAD | _S_IWRITE);
#else
  struct stat fs;
  if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) {
    (void)chmod(path, fs.st_mode | S_IWUSR);
  }
#endif
}

Here is the caller graph for this function:

static void LaunchCallbackApp ( const char *  workingDir,
int  argc,
char **  argv 
) [static]

Definition at line 1070 of file updater.cpp.

{
  putenv("NO_EM_RESTART=");
  putenv("MOZ_LAUNCHED_CHILD=1");

  // Run from the specified working directory (see bug 312360).
  chdir(workingDir);

#if defined(USE_EXECV)
  execv(argv[0], argv);
#elif defined(XP_MACOSX)
  LaunchChild(argc, argv);
#elif defined(XP_WIN)
  WinLaunchChild(argv[0], argc, argv, -1);
#else
# warning "Need implementaton of LaunchCallbackApp"
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void LogFinish ( ) [static]

Definition at line 290 of file updater.cpp.

{
  if (!gLogFP)
    return;

  fclose(gLogFP);
  gLogFP = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void LogInit ( ) [static]

Definition at line 279 of file updater.cpp.

{
  if (gLogFP)
    return;

  char logFile[MAXPATHLEN];
  snprintf(logFile, MAXPATHLEN, "%s/update.log", gSourcePath);

  gLogFP = fopen(logFile, "w");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void LogPrintf ( const char *  fmt,
  ... 
) [static]

Definition at line 299 of file updater.cpp.

{
  if (!gLogFP)
    return;

  va_list ap;
  va_start(ap, fmt);
  vfprintf(gLogFP, fmt, ap);
  va_end(ap);
}

Here is the call graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 1137 of file updater.cpp.

{
  InitProgressUI(&argc, &argv);

  // The updater command line consists of the directory path containing the
  // updater.mar file to process followed by the PID of the calling process.
  // The updater will wait on the parent process to exit if the PID is non-
  // zero.  This is leveraged on platforms such as Windows where it is
  // necessary for the parent process to exit before its executable image may
  // be altered.

  if (argc < 3) {
    fprintf(stderr, "Usage: updater <dir-path> <parent-pid> [working-dir callback args...]\n");
    return 1;
  }

  int pid = atoi(argv[2]);
  if (pid) {
#ifdef XP_WIN
    HANDLE parent = OpenProcess(SYNCHRONIZE, FALSE, (DWORD) pid);
    // May return NULL if the parent process has already gone away.
    // Otherwise, wait for the parent process to exit before starting the
    // update.
    if (parent) {
      DWORD result = WaitForSingleObject(parent, 5000);
      CloseHandle(parent);
      if (result != WAIT_OBJECT_0)
        return 1;
      // The process may be signaled before it releases the executable image.
      // This is a terrible hack, but it'll have to do for now :-(
      Sleep(50);
    }
#else
    int status;
    waitpid(pid, &status, 0);
#endif
  }

  gSourcePath = argv[1];

  LogInit();

  // Run update process on a background thread.  ShowProgressUI may return
  // before QuitProgressUI has been called, so wait for UpdateThreadFunc to
  // terminate.
  Thread t;
  if (t.Run(UpdateThreadFunc, NULL) == 0)
    ShowProgressUI();
  t.Join();

  LogFinish();

#ifdef XP_WIN
  if (gSucceeded && argc > 4)
    LaunchWinPostProcess(argv[4]);
#endif

  // The callback to execute is given as the last N arguments of our command
  // line.  The first of those arguments specifies the working directory for
  // the callback.
  if (argc > 4)
    LaunchCallbackApp(argv[3], argc - 4, argv + 4);

  return 0;
}

Here is the call graph for this function:

static PRUint32 mmin ( PRUint32  a,
PRUint32  b 
) [inline, static]

Definition at line 315 of file updater.cpp.

{
  return (a > b) ? b : a;
}

Here is the caller graph for this function:

static char* mstrtok ( const char *  delims,
char **  str 
) [static]

Definition at line 321 of file updater.cpp.

{
  if (!*str || !**str)
    return NULL;

  // skip leading "whitespace"
  char *ret = *str;
  const char *d;
  do {
    for (d = delims; *d != '\0'; ++d) {
      if (*ret == *d) {
        ++ret;
        break;
      }
    }
  } while (*d);

  if (!*ret) {
    *str = ret;
    return NULL;
  }

  char *i = ret;
  do {
    for (d = delims; *d != '\0'; ++d) {
      if (*i == *d) {
        *i = '\0';
        *str = ++i;
        return ret;
      }
    }
    ++i;
  } while (*i);

  *str = NULL;
  return ret;
}

Here is the caller graph for this function:

static void UpdateThreadFunc ( void param) [static]

Definition at line 1114 of file updater.cpp.

{
  // open ZIP archive and process...

  char dataFile[MAXPATHLEN];
  snprintf(dataFile, MAXPATHLEN, "%s/update.mar", gSourcePath);

  int rv = gArchiveReader.Open(dataFile);
  if (rv == OK) {
    rv = DoUpdate();
    gArchiveReader.Close();
  }

  if (rv)
    LOG(("failed: %d\n", rv));
  else
    LOG(("succeeded\n"));
  WriteStatusFile(rv);

  LOG(("calling QuitProgressUI\n"));
  QuitProgressUI();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void WriteStatusFile ( int  status) [static]

Definition at line 1090 of file updater.cpp.

{
  // This is how we communicate our completion status to the main application.

  char filename[MAXPATHLEN];
  snprintf(filename, MAXPATHLEN, "%s/update.status", gSourcePath);

  AutoFD fd = ensure_open(filename, O_WRONLY | O_TRUNC | O_CREAT | _O_BINARY, 0644);
  if (fd < 0)
    return;

  const char *text;

  char buf[32];
  if (status == OK) {
    text = "succeeded\n";
  } else {
    snprintf(buf, sizeof(buf), "failed: %d\n", status);
    text = buf;
  }
  write(fd, text, strlen(text));
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 511 of file updater.cpp.

unsigned int BZ2_crc32Table[256]

Definition at line 124 of file updater.cpp.

Definition at line 265 of file updater.cpp.

FILE* gLogFP = NULL [static]

Definition at line 277 of file updater.cpp.

char* gSourcePath [static]

Definition at line 264 of file updater.cpp.

const char kNL[] = "\r\n" [static]

Definition at line 271 of file updater.cpp.

const char kQuote[] = "\"" [static]

Definition at line 272 of file updater.cpp.

const char kWhitespace[] = " \t" [static]

Definition at line 270 of file updater.cpp.