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

FileIO.cpp

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifndef WIN32
#include <sys/stat.h>
#include <unistd.h>
#else
#include <windows.h>
#include <winreg.h>
#endif

#include "mudclient.h"

// Local helper function
int createPath(char * filename, char * pathname);

/**
 * Opens a file in the specified mode and returns a filehandle.
 * If path is specified, the file is loaded from that directory.  If
 * omitted the user's ~/.papaya directory is checked first, followed
 * by the system-wide install directory.
 *
 * Return: the filehandle, or NULL on error.
 */

FILE * openFile(char * filename, char * path, char * mode) {

  FILE * fp;
  char buf[1024];
  char * home;

  if (!filename || filename[0] == '\0')
    return NULL;

  if (!mode || mode[0] == '\0')
    return NULL;

  if (path) {
    snprintf(buf, 1024, "%s/%s", path, filename);
    fp = fopen(buf, mode);
    return fp;
  }

  home = getenv("HOME");
  if (home) {
    snprintf(buf, 1024, "%s/.papaya/%s", home, filename);
    fp = fopen(buf, mode);
    if (fp)
      return fp;
  }
  

#ifdef WIN32
  // Try the current working directory before anywhere else for Windows.
  fp = fopen(filename, mode);
  if (fp)
      return fp;

  // Look for a registry key telling us where the base Papaya directory is.
  HKEY hKey;
  int result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\GNU\\Papaya\\", 0, KEY_READ, &hKey);
  if (result == ERROR_SUCCESS) { // Success.
    DWORD type;
    BYTE data[1024];
      DWORD data_len = 1024;

      if (RegQueryValueEx(hKey, "root", 0, &type, data, &data_len) == ERROR_SUCCESS) {
        snprintf(buf, 1024, "%s/share/papaya/%s", data, filename);
      fp = fopen(buf, mode);
        if (fp)
          return fp;
      }

      RegCloseKey(hKey);
  }
#endif
  snprintf(buf, 1024, "%s/share/papaya/%s", getPrefix(), filename);
  fp = fopen(buf, mode);
  if (fp)
    return fp;

  // And if all else fails, try the current directory...
  fp = fopen(filename, mode);

  if ( !fp && (strchr(mode, 'w') || strchr(mode, 'a')) && createPath(filename, path))
    return openFile(filename, path, mode);

  return fp;
}

/**
 * Attempts to create a path to the specified file.
 * If path is specified, that path is attempted to be created.  If
 * omitted the user's ~/.papaya directory is tried first, followed
 * by the system-wide install directory.
 *
 * This function won't work under WIN32 because of the stupid path names
 * - that's probably fixable, but I'm not gonna submit untested code.
 *
 * Return: 1 for success, 0 for failure
 */

int createPath(char * filename, char * pathname) {
#ifndef WIN32
  char buf[1024];
  char path[1024];
  int made_new = 0;
  int rindex = 0;
  int windex = 0;
  struct stat fstatus;

  if (!filename || filename[0] == '\0')
    return 0;

  // Favouritism - path, $HOME, . - as in openFile
  if ( pathname )
    strcpy(path, pathname);
  else if ( getenv("HOME") ) {
    strcpy(path, getenv("HOME"));
    strcat(path, "/.papaya");
  } else {
    if ( !path )
      strcpy(path, ".");
  }

  for ( rindex = 0; path[rindex] != '\0'; ++rindex ) {
    // See if we've reached the end of a path component
    if (path[rindex] == '/' && rindex != 0) {
      // Terminate the buffer
      buf[windex] = '\0';
      // See if the component exists - if not, try to create it
      // If we still can't stat it then something is really wrong - fail.
      if (stat(buf, &fstatus)) {
        mkdir(buf, 0700);
        if (stat(buf, &fstatus))
          return 0;
        else
          made_new = 1;
      }
    }

    buf[windex++] = path[rindex];
  }

  // We reached the end of the string, which is probably a path
  // component - try it
  buf[windex] = '\0';
  if (stat(buf, &fstatus)) {
    mkdir(buf, 0700);
    if (stat(buf, &fstatus))
      return 0;
    else
      made_new = 1;
  }

  buf[windex++] = '/';

  // Now try again for the filename
  for ( rindex = 0; filename[rindex] != '\0'; ++rindex ) {
    // See if we've reached the end of a filename component
    if (filename[rindex] == '/' && rindex != 0) {
      // Terminate the buffer
      buf[windex] = '\0';
      // See if the component exists - if not, try to create it
      // If we still can't stat it then something is really wrong - fail.
      if (stat(buf, &fstatus)) {
        mkdir(buf, 0700);
        if (stat(buf, &fstatus))
          return 0;
        else
          made_new = 1;
      }
    } else {
      buf[windex++] = filename[rindex];
    }
  }

  // If we have changed something by making directories report it -
  // openFile can try again safely with no fear of recusion
  return made_new;
#else
  return 0;
#endif
}


#if 0
char * getFilePath(char * filename) {

  struct stat statbuf;
  static char buf[1024];

  // Attempt $HOME/.papaya/%s, then $PREFIX/share/papaya/%s, then pwd

  char * home = getenv("HOME");
  if (home) {
    snprintf(buf, 1024, "%s/.papaya/%s", home, filename);
    if (stat(buf, &statbuf) == 0) { // Success
      return buf;
    }
  }

  snprintf(buf, 1024, "%s/share/papaya/%s", getPrefix(), filename);
  if (stat(buf, &statbuf) == 0)
    return buf;

  if (stat(filename, &statbuf) == 0)
    return filename;

  return NULL;
}
#endif

Generated by  Doxygen 1.6.0   Back to index