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

gb_file_temp.h

/***************************************************************************

  file.c

  The file management routines

  (c) 2000-2004 Benoît Minisini <gambas@users.sourceforge.net>

  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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

#define __GB_FILE_C

#include "gb_common.h"
#include "gb_error.h"
#include "gb_limit.h"
#include "gb_component.h"

#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <dirent.h>

#include "gb_file.h"

#ifdef PROJECT_EXEC

PUBLIC FILE_STAT FILE_stat_info = { 0 };

PRIVATE DIR *file_dir = NULL;
PRIVATE char *file_pattern = NULL;
PRIVATE bool file_dir_arch = FALSE;

#endif

PRIVATE char file_buffer[MAX_PATH + 1];
PRIVATE int file_buffer_length;

#ifdef PROJECT_EXEC

PRIVATE void dir_exit(void)
{
  if (file_dir != NULL)
  {
    closedir(file_dir);
    file_dir = NULL;
  }

  STRING_free(&file_pattern);
}

PUBLIC char *FILE_make_temp(long *len)
{
  static long count = 0;

  if (len)
  {
    count++;
    *len = sprintf(file_buffer, FILE_TEMP_FILE, getuid(), getpid(), count);
  }
  else
    sprintf(file_buffer, FILE_TEMP_DIR, getuid());

  return file_buffer;
}

PUBLIC void FILE_init(void)
{
  mkdir(FILE_make_temp(NULL), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
}

PRIVATE void remove_temp_files(void)
{
  char pattern[24];
  char *file;
  long len;

  sprintf(pattern, "%d.*.tmp", getpid());
  FILE_dir_first(FILE_make_temp(NULL), pattern);

  while (!FILE_dir_next(&file, &len))
    unlink(FILE_cat(FILE_make_temp(NULL), file, NULL));
}


PUBLIC void FILE_exit(void)
{
  remove_temp_files();
  dir_exit();
}

#endif


PUBLIC const char *FILE_cat(const char *path, ...)
{
  char *p;
  va_list args;
  int len;
  boolean end_slash = FALSE;
  boolean add_slash = FALSE;

  va_start(args, path);

  p = file_buffer;

  if (path != file_buffer)
    *p = 0;

  for(;;)
  {
    if (*path == '/' && p != file_buffer)
      path++;

    len = strlen(path);
    if (add_slash)
      len++;

    if (len > 0)
    {
      if ((p + len) > &file_buffer[MAX_PATH])
        return NULL;

      if (p != path)
      {
        if (add_slash)
          p = stradd(p, "/");

          p = stradd(p, path);
      }
      else
        p += len;

      end_slash = (p[-1] == '/');
    }

    path = va_arg(args, char *);
    if (path == NULL)
      break;

    add_slash = ((!end_slash) && (*path != 0) && (*path != '/'));
  }

  file_buffer_length = p - file_buffer;
  return file_buffer;
}


PUBLIC int FILE_buffer_length(void)
{
  if (file_buffer_length < 0)
    file_buffer_length = strlen(file_buffer);

  return file_buffer_length;
}


PUBLIC const char *FILE_get_dir(const char *path)
{
  char *p;

  if (path == NULL || path[0] == 0)
    return NULL;

  if (path[0] == '/' && path[1] == 0)
    return "/";

  if (file_buffer != path)
    strcpy(file_buffer, path);

  p = rindex(file_buffer, '/');

  if (p == NULL)
    *file_buffer = 0;
  else
  {
    *p = 0;

    if (file_buffer[0] == 0 && path[0] == '/')
      strcpy(file_buffer, "/");
  }

  file_buffer_length = -1;
  return file_buffer;
}


PUBLIC const char *FILE_get_name(const char *path)
{
  const char *p;

  p = rindex(path, '/');
  if (p)
    return &p[1];
  else
    return path;
}


PUBLIC const char *FILE_get_ext(const char *path)
{
  const char *p;

  p = rindex(path, '/');
  if (p)
    path = &p[1];

  p = rindex(path, '.');
  if (p == NULL)
    return &path[strlen(path)];
  else
    return p + 1;
}


PUBLIC const char *FILE_set_ext(const char *path, const char *ext)
{
  char *p;

  if (path != file_buffer)
  {
    strcpy(file_buffer, path);
    path = file_buffer;
  }
  
  p = (char *)FILE_get_ext(path);
  
  if (!ext)
  {
    *p = 0;
    return path;
  }

  if (&p[strlen(ext)] >= &file_buffer[MAX_PATH])
    return path;
  
  if (p == path || p[-1] != '.')
    *p++ = '.';

  if (*ext == '.')
    ext++;
    
  strcpy(p, ext);

  file_buffer_length = -1;
  return path;
}


PUBLIC const char *FILE_get_basename(const char *path)
{
  char *p;

  path = FILE_get_name(path);

  if (file_buffer != path)
    strcpy(file_buffer, path);

  p = rindex(file_buffer, '.');
  if (p)
    *p = 0;

  file_buffer_length = -1;

  return file_buffer;
}


PUBLIC bool FILE_isdir(const char *path)
{
  struct stat buf;

  if (FILE_is_relative(path))
    return FALSE;

  if (stat(path, &buf))
    return FALSE;

  return (S_ISDIR(buf.st_mode));
}


#ifdef PROJECT_EXEC

PUBLIC bool FILE_exist_real(const char *path)
{
  struct stat buf;

  chdir(PROJECT_path);
  return (stat(path, &buf) == 0);
}

PUBLIC void FILE_stat(const char *path, FILE_STAT *info)
{
  struct stat buf;

  if (FILE_is_relative(path))
  {
    if (!EXEC_arch)
    {
      chdir(PROJECT_path);
      if (lstat(path, &buf) == 0)
        goto _OK;
    }

    ARCH_stat(path, info);
    return;
  }

  if (lstat(path, &buf) != 0)
    THROW_SYSTEM(errno, path);

_OK:

  if (S_ISREG(buf.st_mode))
    info->type = GB_STAT_FILE;
  else if (S_ISDIR(buf.st_mode))
    info->type = GB_STAT_DIRECTORY;
  else if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))
    info->type = GB_STAT_DEVICE;
  else if (S_ISFIFO(buf.st_mode))
    info->type = GB_STAT_PIPE;
  else if (S_ISSOCK(buf.st_mode))
    info->type = GB_STAT_SOCKET;
  else if (S_ISLNK(buf.st_mode))
    info->type = GB_STAT_LINK;

  info->mode = buf.st_mode & 07777;
  info->size = (long)buf.st_size;
  info->atime = (long)buf.st_atime;
  info->mtime = (long)buf.st_mtime;
  info->ctime = (long)buf.st_ctime;
  info->hidden = (*FILE_get_name(path) == '.');
  info->uid = buf.st_uid;
  info->gid = buf.st_gid;
}


PUBLIC void FILE_dir_first(const char *path, const char *pattern)
{
  struct stat buf;

  dir_exit();

  if (!path || *path == 0)
    path = ".";

  if (FILE_is_relative(path))
  {
    if (!EXEC_arch)
    {
      chdir(PROJECT_path);
      if (lstat(path, &buf) == 0)
        goto _OK;
    }

    file_dir_arch = TRUE;
    ARCH_dir_first(path, pattern);
    return;
  }

_OK:

  file_dir = opendir(path);
  if (file_dir == NULL)
    THROW_SYSTEM(errno, path);

  STRING_new(&file_pattern, pattern, -1);
}


PUBLIC bool FILE_dir_next(char **path, long *len)
{
  struct dirent *entry;
  long len_entry;
  bool ret;

  if (file_dir_arch)
  {
    ret = ARCH_dir_next(path, len);
    if (ret)
      file_dir_arch = FALSE;
    return ret;
  }

  if (file_dir == NULL)
    return TRUE;

  for(;;)
  {
    entry = readdir(file_dir);
    if (entry == NULL)
    {
      dir_exit();
      return TRUE;
    }

    if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0))
      continue;

    len_entry = strlen(entry->d_name);

    if (file_pattern == NULL)
      break;

    if (REGEXP_match(file_pattern, STRING_length(file_pattern), entry->d_name, len_entry))
      break;
  }

  *path = entry->d_name;
  *len = len_entry;

  return FALSE;
}

PUBLIC void FILE_unlink(const char *path)
{
  if (FILE_is_relative(path))
    THROW(E_ACCESS);

  if (unlink(path) != 0)
    THROW_SYSTEM(errno, path);
}


PUBLIC void FILE_rmdir(const char *path)
{
  if (FILE_is_relative(path))
    THROW(E_ACCESS);

  if (rmdir(path) != 0)
    THROW_SYSTEM(errno, path);
}


PUBLIC void FILE_mkdir(const char *path)
{
  if (FILE_is_relative(path))
    THROW(E_ACCESS);

  if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0)
    THROW_SYSTEM(errno, path);
}


PUBLIC void FILE_rename(const char *src, const char *dst)
{
  if (FILE_is_relative(src) || FILE_is_relative(dst))
    THROW(E_ACCESS);

  if (FILE_exist(dst))
    THROW(E_EXIST, dst);

  if (rename(src, dst) != 0)
    THROW_SYSTEM(errno, dst);
}

PUBLIC void FILE_copy(const char *src, const char *dst)
{
  STREAM stream_src;
  STREAM stream_dst;
  long len, n;
  char *buf = NULL;

  CLEAR(&stream_src);
  CLEAR(&stream_dst);

  if (FILE_exist(dst))
    THROW(E_EXIST, dst);

  ALLOC(&buf, MAX_IO, "FILE_copy");

  TRY
  {
    STREAM_open(&stream_src, src, ST_READ);
    STREAM_open(&stream_dst, dst, ST_CREATE);

    STREAM_lof(&stream_src, &len);

    while (len)
    {
      n = len > MAX_IO ? MAX_IO : len;
      STREAM_read(&stream_src, buf, n);
      STREAM_write(&stream_dst, buf, n);
      len -= n;
    }

    STREAM_close(&stream_src);
    STREAM_close(&stream_dst);

    FREE(&buf, "FILE_copy");
  }
  CATCH
  {
    if (stream_src.type)
      STREAM_close(&stream_src);
    if (stream_dst.type)
      STREAM_close(&stream_dst);
    FREE(&buf, "FILE_copy");

    PROPAGATE();
  }
  END_TRY
}


PUBLIC bool FILE_access(const char *path, int mode)
{
  if (FILE_is_relative(path))
  {
    if (!EXEC_arch)
    {
      chdir(PROJECT_path);
      if (access(path, mode) == 0)
        return TRUE;
    }

    if (mode & (W_OK | X_OK))
      return FALSE;
    else
      return ARCH_exist(path);
  }

  return (access(path, mode) == 0);
}


PUBLIC bool FILE_exist(const char *path)
{
  return FILE_access(path, F_OK);
}


PUBLIC void FILE_link(const char *src, const char *dst)
{
  /* src can be relative */
  if (FILE_is_relative(dst))
    THROW(E_ACCESS);

  if (FILE_exist(dst))
    THROW(E_EXIST, dst);

  if (symlink(src, dst) != 0)
    THROW_SYSTEM(errno, dst);
}

#else

PUBLIC bool FILE_exist(const char *path)
{
  return (access(path, F_OK) == 0);
}

PUBLIC time_t FILE_get_time(const char *path)
{
  struct stat info;

  if (stat(path, &info) == 0)
    return info.st_mtime;
  else
    return (time_t)-1L;
}

#endif

PUBLIC const char *FILE_getcwd(const char *subdir)
{
  if (getcwd(file_buffer, PATH_MAX) == NULL)
    return NULL;

  file_buffer_length = strlen(file_buffer);

  if (subdir != NULL)
    return FILE_cat(file_buffer, subdir, NULL);
  else
    return file_buffer;
}


PUBLIC const char *FILE_readlink(const char *link)
{
  int len = readlink(link, file_buffer, MAX_PATH);

  if (len < 0)
    return NULL;

  file_buffer[len] = 0;
  file_buffer_length = len;
  return file_buffer;

}


PUBLIC const char *FILE_find_gambas(const char *exec)
{
  const char *path;

  if (FILE_exist(GAMBAS_LINK_PATH))
  {
    path = FILE_readlink(GAMBAS_LINK_PATH);
    if (!path)
      path = GAMBAS_LINK_PATH;
  }
  else
  {
    if (FILE_is_absolute(exec))
      path = exec;
    else
      path = FILE_getcwd(exec);
  }
  
  return path;
}

Generated by  Doxygen 1.6.0   Back to index