Source

Frontier / Terrain / File.cpp

Full commit
/*-----------------------------------------------------------------------------

  File.cpp

-------------------------------------------------------------------------------

  Various useful file i/o functions.

-----------------------------------------------------------------------------*/

#include "StdAfx.h"
#include "File.h"
#ifdef WINDOWS
#include <windows.h>
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#include <sys/utime.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#endif
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

DWORD FileModified (char *filename)
{

#ifdef WINDOWS
  long                search;
  struct _finddata_t  info;
#else
  struct stat         st;
#endif
  DWORD               timestamp;

  timestamp = 0;
#ifdef WINDOWS
  if ((search = _findfirst (filename, &info)) != -1) {
    timestamp = info.time_write;
    _findclose (search);
  } 
#else
  if (!stat(filename, &st)) {
    timestamp = static_cast<DWORD>(st.st_size);
  }
#endif
  return timestamp;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool FileDelete (char* name)
{

#ifdef WINDOWS
  if (!_unlink (name))
    return true;
  return false;
#else
  return unlink(name) == 0;
#endif

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool FileSave (char *name, char *buf, int size)
{

  int fd;
  int flags = O_WRONLY | O_CREAT | O_TRUNC;

#ifdef WINDOWS
  flags |= O_BINARY;
#else
  // So close, windows "posix" mode.  So, so close.  Stupid underscores.
#define _open open
#define _write write
#define _close close
#define _unlink unlink
#endif

  if ((fd = _open (name, flags, S_IREAD | S_IWRITE)) == -1)
    return false;
  if (_write (fd, buf, size) != size) {
    _close (fd);
    _unlink (name);
    return false;
  }
  _close (fd);
  return true;

#ifndef WINDOWS
#undef _open
#undef _write
#undef _close
#undef _unlink
#endif
}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

char* FileLoad (const char* name, uint32_t* size)
{
#ifdef WINDOWS
  FILE*     f;
  char*     buffer;
  int       h;
  int       len;
#else
  char*       buffer;
  int         fd;
  struct stat st;
#endif

  buffer = NULL;
#ifdef WINDOWS
  len = 0;
  h = _open (name, _O_RDONLY | O_BINARY);
  if (h != -1) {
    //set file size
    len = _filelength (h) + 1;
    _close (h);
    buffer = (char*)malloc (len);
    f = fopen (name, "rb");
    fread (buffer, 1, len, f);
    fclose (f);
    //terminate string
    buffer[len - 1] = 0;
  }
  if (size)
    *size = len;
#else
  fd = open(name, O_RDONLY);
  if (fd != -1) {
    if (fstat(fd, &st) != 0) {
      return NULL;
    }
    buffer = (char*)malloc (st.st_size);
    // Note that reads of >2G might not finish in one syscall.
    // Oh well; these files aren't nearly that large.
    if (read(fd, buffer, st.st_size) != st.st_size) {
      free(buffer);
      close(fd);
      return NULL;
    }
    close(fd);
    buffer[st.st_size - 1] = 0;
  }
  if (size)
    *size = st.st_size;
#endif
  return buffer;

}


char* FileBinaryLoad (char* name, uint32_t* size)
{
#ifdef WINDOWS
  FILE*     f;
  char*     buffer;
  int       h;
  int       len;
#else
  int         fd;
  char*       buffer;
  struct stat st;
#endif

  buffer = NULL;

#ifdef WINDOWS
  len = 0;
  h = _open (name, _O_RDONLY | O_BINARY);
  if (h != -1) {
    //set file size
    len = _filelength (h);
    _close (h);
    buffer = (char*)malloc (len);
    f = fopen (name, "rb");
    fread (buffer, 1, len, f);
    fclose (f);
  }
  if (size)
    *size = len;
#else
  fd = open (name, O_RDONLY);
  if (fd != -1) {
    if (fstat(fd, &st) != 0) {
      return NULL;
    }
    buffer = (char*)malloc (st.st_size);
    if (read(fd, buffer, st.st_size) != st.st_size) {
      free(buffer);
      close(fd);
      return NULL;
    }
    close(fd);
  }
  if (size)
    *size = st.st_size;
#endif

  return buffer;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool FileExists (const char *name)
{


  FILE*     f;

  f = fopen (name, "rb");
  if (f == NULL)
    return false;
  fclose (f);
  return true;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void FileTouch (char *filename)
{

#ifdef WINDOWS
  _utime (filename, NULL);
#else
  // We could do without the FD, but only with second precision on times.
  int fd = open(filename, O_WRONLY);
  if (fd == -1) return;
  futimens(fd, NULL);
  close(fd);
#endif

}

/*-----------------------------------------------------------------------------
                       f i l e  c r e a t e  f o l d e r
-----------------------------------------------------------------------------*/

void FileMakeDirectory (char* folder)
{

  char*   dir;
  char*   p;
  char*   p1;
  int     errcode;

#ifdef WINDOWS
  char    pathsep = '\\';
#else
  char    pathsep = '/';
#endif

  dir = (char*)malloc (strlen (folder) + 1);
  strcpy (dir, folder);
  if (!(p = strchr (dir, '\\')))
    p = strchr (dir, '/');
  p1 = p;
  while (p && p1) {
    *p = '\0';
#ifdef WINDOWS
    _mkdir (dir);
#else
    mkdir (dir, 0777);
#endif
    *p = pathsep;
    p1++;
    if (p == NULL || p1 == NULL ||  *p == 0x0 || *p1 == 0x0)
      break;
    if (!(p = strchr (p1, '\\')))    
      if (!(p = strchr (p1, '/')))
        break;
    p1 = p;
  }

  errcode = 0;
#ifdef WINDOWS
  if (_mkdir (folder))
    errcode = errno;
#else
  if (mkdir (folder, 0777))
    errcode = errno;
#endif
  free (dir);

}