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

gbx_c_file.c

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

  CFile.c

  The native File class

  (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 __GBX_C_FILE_C

#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>

#include "gb_common.h"
#include "gbx_api.h"
#include "gambas.h"
#include "gbx_class.h"
#include "gb_file.h"
#include "gbx_stream.h"
#include "gbx_exec.h"

#include "gbx_string.h"
#include "gbx_date.h"
#include "gbx_c_file.h"


PUBLIC CFILE CFILE_in, CFILE_out, CFILE_err;

DECLARE_EVENT(EVENT_Read);
DECLARE_EVENT(EVENT_Write);

static char _buffer[16];

PRIVATE void init(CFILE *_object, FILE *file)
{
  THIS->ob.ob.class = CLASS_File;
  THIS->ob.ob.ref = 1;

  THIS->ob.stream.type = &STREAM_buffer;
  THIS->ob.stream.buffer.file = file;
  THIS->ob.stream.buffer.size = 0;
}

PUBLIC void CFILE_init(void)
{
  init(&CFILE_in, stdin);
  init(&CFILE_out, stdout);
  init(&CFILE_err, stderr);
}


PRIVATE void callback_read(int fd, int type, CFILE *file)
{
  GB_Raise(file, EVENT_Read, 0);
}

PRIVATE void callback_write(int fd, int type, CFILE *file)
{
  GB_Raise(file, EVENT_Write, 0);
}


PUBLIC CFILE *CFILE_create(STREAM *stream, int mode)
{
  int fd;
  CFILE *file;

  OBJECT_new((void **)&file, CLASS_File, NULL, NULL);
  OBJECT_UNREF_KEEP((void **)&file, "CFILE_new");

  if (stream)
  {
    *CSTREAM_stream(file) = *stream;
    file->watch_fd = -1;

    if (mode & ST_WATCH)
    {
      fd = STREAM_handle(&file->ob.stream);
      file->watch_fd = fd;

      if (mode & ST_READ)
        GB_Watch(fd, GB_WATCH_READ, (void *)callback_read, (long)file);

      if (mode & ST_WRITE)
        GB_Watch(fd, GB_WATCH_WRITE, (void *)callback_write, (long)file);

      OBJECT_attach((OBJECT *)file, OP ? (OBJECT *)OP : (OBJECT *)CP, "File");
    }
  }

  return file;
}


BEGIN_METHOD_VOID(CFILE_free)

  STREAM_close(&THIS->ob.stream);
  if (THIS->watch_fd >= 0)
    GB_Watch(THIS->watch_fd, GB_WATCH_NONE, NULL, 0);

END_METHOD


BEGIN_PROPERTY(CFILE_get_in)

  GB_ReturnObject(&CFILE_in);

END_PROPERTY


BEGIN_PROPERTY(CFILE_get_out)

  GB_ReturnObject(&CFILE_out);

END_PROPERTY


BEGIN_PROPERTY(CFILE_get_err)

  GB_ReturnObject(&CFILE_err);

END_PROPERTY


BEGIN_PROPERTY(CFILE_type)

  GB_ReturnInt(THIS->info.type);

END_PROPERTY


BEGIN_PROPERTY(CFILE_mode)

  GB_ReturnInt(THIS->info.mode);

END_PROPERTY


BEGIN_PROPERTY(CFILE_hidden)

  GB_ReturnBoolean(THIS->info.hidden);

END_PROPERTY


BEGIN_PROPERTY(CFILE_size)

  GB_ReturnInt(THIS->info.size);

END_PROPERTY


BEGIN_PROPERTY(CFILE_atime)

  GB_DATE date;

  DATE_from_time(THIS->info.atime, 0, (VALUE *)&date);

  GB_ReturnDate(&date);

END_PROPERTY


BEGIN_PROPERTY(CFILE_ctime)

  GB_DATE date;

  DATE_from_time(THIS->info.ctime, 0, (VALUE *)&date);

  GB_ReturnDate(&date);

END_PROPERTY


BEGIN_PROPERTY(CFILE_mtime)

  GB_DATE date;

  DATE_from_time(THIS->info.mtime, 0, (VALUE *)&date);

  GB_ReturnDate(&date);

END_PROPERTY


static char *get_file_user(CFILE *_object)
{
  struct passwd *pwd;
  uid_t uid = THIS->info.uid;

  if (uid == 0)
    return "root";
  else
  {
    pwd = getpwuid(uid);
    if (!pwd)
    {
      sprintf(_buffer, "%d", uid);
      return _buffer;
    }
    else
      return pwd->pw_name;
  }
}

BEGIN_PROPERTY(CFILE_user)

  GB_ReturnNewZeroString(get_file_user(THIS));

END_PROPERTY


static char *get_file_group(CFILE *_object)
{
  struct group *grp;
  gid_t gid = THIS->info.gid;

  if (gid == 0)
    return "root";
  else
  {
    grp = getgrgid(gid);
    if (!grp)
    {
      sprintf(_buffer, "%d", gid);
      return _buffer;
    }
    else
      return grp->gr_name;
  }
}

BEGIN_PROPERTY(CFILE_group)

  GB_ReturnNewZeroString(get_file_group(THIS));

END_PROPERTY


BEGIN_PROPERTY(CFILE_setuid)

  GB_ReturnBoolean(THIS->info.mode & S_ISUID);

END_PROPERTY


BEGIN_PROPERTY(CFILE_setgid)

  GB_ReturnBoolean(THIS->info.mode & S_ISGID);

END_PROPERTY


BEGIN_PROPERTY(CFILE_sticky)

  GB_ReturnBoolean(THIS->info.mode & S_ISVTX);

END_PROPERTY

#if 0
BEGIN_METHOD(CFILE_access, GB_INTEGER who; GB_INTEGER access)

  bool ret;
  int access = VARGOPT(access, GB_STAT_READ);
  int who = VARG(who);
  int mode = THIS->info.mode;

  if ((access & GB_STAT_READ) == 0)
    mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
  if ((access & GB_STAT_WRITE) == 0)
    mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  if ((access & GB_STAT_EXEC) == 0)
    mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);

  switch(who)
  {
    case GB_STAT_USER: ret = mode & S_IRWXU; break;
    case GB_STAT_GROUP: ret = mode & S_IRWXG; break;
    case GB_STAT_OTHER: ret = mode & S_IRWXO; break;
    default: ret = FALSE; break;
  }

  GB_ReturnBoolean(ret);

END_METHOD
#endif


static void return_perm(CFILE *_object, int rf, int wf, int xf)
{
  char perm[4];
  char *p;
  int mode = THIS->info.mode;
  
  p = perm;
  
  if (mode & rf) *p++ = 'r';
  if (mode & wf) *p++ = 'w';
  if (mode & xf) *p++ = 'x';
  
  *p = 0;

  GB_ReturnNewZeroString(perm);
}


BEGIN_PROPERTY(CFILE_perm_user)

  return_perm(THIS, S_IRUSR, S_IWUSR, S_IXUSR);

END_PROPERTY

BEGIN_PROPERTY(CFILE_perm_group)

  return_perm(THIS, S_IRGRP, S_IWGRP, S_IXGRP);

END_PROPERTY

BEGIN_PROPERTY(CFILE_perm_other)

  return_perm(THIS, S_IROTH, S_IWOTH, S_IXOTH);

END_PROPERTY

BEGIN_METHOD(CFILE_perm_get, GB_STRING user)

  char *who;
  char *user = GB_ToZeroString(ARG(user));
  
  who = get_file_user(THIS);
  if (strcmp(user, who) == 0)
  {
    return_perm(THIS, S_IRUSR, S_IWUSR, S_IWUSR);
    return;
  }

  who = get_file_group(THIS);
  if (strlen(user) > 2 && user[0] == '*' && user[1] == '.' && strcmp(&user[2], who) == 0)
  {
    return_perm(THIS, S_IRGRP, S_IWGRP, S_IWGRP);
    return;
  }

  return_perm(THIS, S_IROTH, S_IWOTH, S_IWOTH);

END_METHOD



BEGIN_PROPERTY(CFILE_separator)

  GB_ReturnConstZeroString("/");

END_PROPERTY


BEGIN_METHOD(CFILE_dir, GB_STRING path)

  const char *path = GB_ToZeroString(ARG(path));

  if (path)
    GB_ReturnNewZeroString(FILE_get_dir(path));
  else
    GB_ReturnNull();

/*
  char *path = PARAM(path).addr;
  int len = PARAM(path).len;

  if (len == 0)
  {
    GB_ReturnNull();
    return;
  }

  if (len == 1)
  {
    if (*path == '/')
      GB_ReturnCopyString(path, len);
    else
      GB_ReturnNull();
    return;
  }

  for(;;)
  {
    len--;
    if ((len == 0) || (path[len] == '/'))
    {
      GB_ReturnCopyString(path, len);
      return;
    }
  }
*/

END_METHOD


BEGIN_METHOD(CFILE_name, GB_STRING path)

  if (LENGTH(path) && STRING(path)[LENGTH(path) - 1] == '/')
    LENGTH(path)--;

  GB_ReturnNewString(FILE_get_name(GB_ToZeroString(ARG(path))), -1);

END_METHOD


BEGIN_METHOD(CFILE_ext, GB_STRING path)

  const char *path = GB_ToZeroString(ARG(path));

  if (path)
    GB_ReturnNewZeroString(FILE_get_ext(path));
  else
    GB_ReturnNull();

END_METHOD


BEGIN_METHOD(CFILE_basename, GB_STRING path)

  const char *path = GB_ToZeroString(ARG(path));

  if (path)
    GB_ReturnNewZeroString(FILE_get_basename(path));
  else
    GB_ReturnNull();

END_METHOD


BEGIN_METHOD(CFILE_load, GB_STRING path)

  STREAM stream;
  long len;
  char *str;
  boolean opened = FALSE;

  TRY
  {
    STREAM_open(&stream, STRING_conv_file_name(STRING(path), LENGTH(path)), ST_READ);
    opened = TRUE;

    STREAM_lof(&stream, &len);

    STRING_new_temp(&str, NULL, len);

    STREAM_read(&stream, str, len);
    STREAM_close(&stream);

    GB_ReturnString(str);
  }
  CATCH
  {
    if (opened)
      STREAM_close(&stream);
    PROPAGATE();
  }
  END_TRY

END_METHOD


BEGIN_METHOD(CFILE_save, GB_STRING path; GB_STRING data)

  STREAM stream;
  boolean opened = FALSE;

  TRY
  {
    STREAM_open(&stream, STRING_conv_file_name(STRING(path), LENGTH(path)), ST_CREATE);
    opened = TRUE;
    STREAM_write(&stream, STRING(data), LENGTH(data));
    STREAM_close(&stream);
  }
  CATCH
  {
    if (opened)
      STREAM_close(&stream);
    PROPAGATE();
  }
  END_TRY

END_METHOD


PUBLIC GB_DESC NATIVE_Stream[] =
{
  GB_DECLARE(".Stream", sizeof(CSTREAM)),
  GB_NOT_CREATABLE(),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_FilePerm[] =
{
  GB_DECLARE(".FilePerm", 0),
  GB_VIRTUAL_CLASS(),

  GB_METHOD("_get", "s", CFILE_perm_get, "(UserOrGroup)s"),
  GB_PROPERTY_READ("User", "s", CFILE_perm_user),
  GB_PROPERTY_READ("Group", "s", CFILE_perm_group),
  GB_PROPERTY_READ("Other", "s", CFILE_perm_other),

  GB_END_DECLARE
};


PUBLIC GB_DESC NATIVE_File[] =
{
  GB_DECLARE("File", sizeof(CFILE)),
  GB_INHERITS(".Stream"),
  GB_NOT_CREATABLE(),

  GB_METHOD("_free", NULL, CFILE_free, NULL),

  GB_STATIC_PROPERTY_READ("Separator", "s", CFILE_separator),

  GB_STATIC_PROPERTY_READ("In", "File", CFILE_get_in),
  GB_STATIC_PROPERTY_READ("Out", "File", CFILE_get_out),
  GB_STATIC_PROPERTY_READ("Err", "File", CFILE_get_err),

  GB_PROPERTY_READ("Type", "i", CFILE_type),
  GB_PROPERTY_READ("Mode", "i", CFILE_mode),
  GB_PROPERTY_READ("Hidden", "b", CFILE_hidden),
  GB_PROPERTY_READ("Size", "i", CFILE_size),
  GB_PROPERTY_READ("Time", "d", CFILE_mtime),
  GB_PROPERTY_READ("LastAccess", "d", CFILE_atime),
  GB_PROPERTY_READ("LastUpdate", "d", CFILE_mtime),
  GB_PROPERTY_READ("LastChange", "d", CFILE_ctime),
  GB_PROPERTY_READ("User", "s", CFILE_user),
  GB_PROPERTY_READ("Group", "s", CFILE_group),
  GB_PROPERTY_SELF("Perm", ".FilePerm"),
  GB_PROPERTY_READ("SetGID", "b", CFILE_setgid),
  GB_PROPERTY_READ("SetUID", "b", CFILE_setuid),
  GB_PROPERTY_READ("Sticky", "b", CFILE_sticky),
  //GB_METHOD("Access", "b", CFILE_access, "(Who)i[(Mode)i]"),

  GB_STATIC_METHOD("Dir", "s", CFILE_dir, "(FileName)s"),
  GB_STATIC_METHOD("Name", "s", CFILE_name, "(FileName)s"),
  GB_STATIC_METHOD("Ext", "s", CFILE_ext, "(FileName)s"),
  GB_STATIC_METHOD("BaseName", "s", CFILE_basename, "(FileName)s"),

  GB_STATIC_METHOD("Load", "s", CFILE_load, "(FileName)s"),
  GB_STATIC_METHOD("Save", NULL, CFILE_save, "(FileName)s(Data)s"),

  GB_EVENT("Read", NULL, NULL, &EVENT_Read),
  GB_EVENT("Write", NULL, NULL, &EVENT_Write),

  GB_END_DECLARE
};


Generated by  Doxygen 1.6.0   Back to index