/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
* bonobo-stream-fs.c: Sample file-system based Stream implementation
*
* This is just a sample file-system based Stream implementation.
* it is only used for debugging purposes
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*/
#include <config.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-util.h>
#include <libgnome/gnome-mime.h>
#include <storage-modules/bonobo-stream-fs.h>
#include <errno.h>
struct _BonoboStreamFSPrivate {
gchar *mime_type;
};
static BonoboStreamClass *bonobo_stream_fs_parent_class;
static gint
bonobo_mode_to_fs (Bonobo_Storage_OpenMode mode)
{
gint fs_mode = 0;
if (mode & Bonobo_Storage_READ)
fs_mode |= O_RDONLY;
if (mode & Bonobo_Storage_WRITE)
fs_mode |= O_RDWR;
if (mode & Bonobo_Storage_CREATE)
fs_mode |= O_CREAT | O_RDWR;
if (mode & Bonobo_Storage_FAILIFEXIST)
fs_mode |= O_EXCL;
return fs_mode;
}
static Bonobo_StorageInfo*
fs_get_info (BonoboStream *stream,
const Bonobo_StorageInfoFields mask,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
Bonobo_StorageInfo *si;
struct stat st;
if (mask & ~(Bonobo_FIELD_CONTENT_TYPE | Bonobo_FIELD_SIZE |
Bonobo_FIELD_TYPE)) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NotSupported, NULL);
return CORBA_OBJECT_NIL;
}
if (fstat (stream_fs->fd, &st) == -1)
goto get_info_except;
si = Bonobo_StorageInfo__alloc ();
si->size = st.st_size;
si->type = Bonobo_STORAGE_TYPE_REGULAR;
si->name = CORBA_string_dup ("");
si->content_type = CORBA_string_dup (stream_fs->priv->mime_type);
return si;
get_info_except:
if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NoPermission, NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
return CORBA_OBJECT_NIL;
}
static void
fs_set_info (BonoboStream *stream,
const Bonobo_StorageInfo *info,
const Bonobo_StorageInfoFields mask,
CORBA_Environment *ev)
{
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NotSupported, NULL);
}
static void
fs_write (BonoboStream *stream, const Bonobo_Stream_iobuf *buffer,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
errno = EINTR;
while ((write (stream_fs->fd, buffer->_buffer, buffer->_length) == -1)
&& (errno == EINTR));
if (errno == EINTR) return;
if ((errno == EBADF) || (errno == EINVAL))
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NoPermission, NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
}
static void
fs_read (BonoboStream *stream,
CORBA_long count,
Bonobo_Stream_iobuf **buffer,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
CORBA_octet *data;
int bytes_read;
if (count < 0) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
return;
}
*buffer = Bonobo_Stream_iobuf__alloc ();
CORBA_sequence_set_release (*buffer, TRUE);
data = CORBA_sequence_CORBA_octet_allocbuf (count);
(*buffer)->_buffer = data;
(*buffer)->_length = 0;
do {
bytes_read = read (stream_fs->fd, data, count);
} while ((bytes_read == -1) && (errno == EINTR));
if (bytes_read == -1) {
CORBA_free (*buffer);
*buffer = NULL;
if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NoPermission,
NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
} else
(*buffer)->_length = bytes_read;
}
static CORBA_long
fs_seek (BonoboStream *stream,
CORBA_long offset,
Bonobo_Stream_SeekType whence,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
int fs_whence;
CORBA_long pos;
if (whence == Bonobo_Stream_SEEK_CUR)
fs_whence = SEEK_CUR;
else if (whence == Bonobo_Stream_SEEK_END)
fs_whence = SEEK_END;
else
fs_whence = SEEK_SET;
if ((pos = lseek (stream_fs->fd, offset, fs_whence)) == -1) {
if (errno == ESPIPE)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NotSupported,
NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
return 0;
}
return pos;
}
static void
fs_truncate (BonoboStream *stream,
const CORBA_long new_size,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
if (ftruncate (stream_fs->fd, new_size) == 0)
return;
if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NoPermission, NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
}
static void
fs_copy_to (BonoboStream *stream,
const CORBA_char *dest,
const CORBA_long bytes,
CORBA_long *read_bytes,
CORBA_long *written_bytes,
CORBA_Environment *ev)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (stream);
gchar data[4096];
CORBA_unsigned_long more = bytes;
int v, w;
int fd_out;
*read_bytes = 0;
*written_bytes = 0;
if ((fd_out = creat(dest, 0644)) == -1)
goto copy_to_except;
do {
if (bytes == -1)
more = sizeof (data);
do {
v = read (stream_fs->fd, data,
MIN (sizeof (data), more));
} while ((v == -1) && (errno == EINTR));
if (v == -1)
goto copy_to_except;
if (v <= 0)
break;
*read_bytes += v;
more -= v;
do {
w = write (fd_out, data, v);
} while (w == -1 && errno == EINTR);
if (w == -1)
goto copy_to_except;
*written_bytes += w;
} while ((more > 0 || bytes == -1) && v > 0);
close (fd_out);
return;
copy_to_except:
if (fd_out != -1)
close (fd_out);
if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NoPermission, NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_IOError, NULL);
}
static void
fs_commit (BonoboStream *stream,
CORBA_Environment *ev)
{
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NotSupported, NULL);
}
static void
fs_revert (BonoboStream *stream,
CORBA_Environment *ev)
{
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Stream_NotSupported, NULL);
}
static void
fs_destroy (GtkObject *object)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (object);
if (close (stream_fs->fd))
g_warning ("Close failed");
stream_fs->fd = -1;
if (stream_fs->path)
g_free (stream_fs->path);
stream_fs->path = NULL;
if (stream_fs->priv->mime_type)
g_free (stream_fs->priv->mime_type);
stream_fs->priv->mime_type = NULL;
}
static void
fs_finalize (GtkObject *object)
{
BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (object);
if (stream_fs->priv)
g_free (stream_fs->priv);
stream_fs->priv = NULL;
}
static void
bonobo_stream_fs_class_init (BonoboStreamFSClass *klass)
{
GtkObjectClass *oclass = (GtkObjectClass *) klass;
BonoboStreamClass *sclass = BONOBO_STREAM_CLASS (klass);
bonobo_stream_fs_parent_class =
gtk_type_class (bonobo_stream_get_type ());
sclass->get_info = fs_get_info;
sclass->set_info = fs_set_info;
sclass->write = fs_write;
sclass->read = fs_read;
sclass->seek = fs_seek;
sclass->truncate = fs_truncate;
sclass->copy_to = fs_copy_to;
sclass->commit = fs_commit;
sclass->revert = fs_revert;
oclass->destroy = fs_destroy;
oclass->finalize = fs_finalize;
}
static void
bonobo_stream_fs_init (BonoboStreamFS *stream_fs)
{
stream_fs->priv = g_new0 (BonoboStreamFSPrivate,1);
stream_fs->priv->mime_type = NULL;
}
/**
* bonobo_stream_fs_get_type:
*
* Returns the GtkType for the BonoboStreamFS class.
*/
GtkType
bonobo_stream_fs_get_type (void)
{
static GtkType type = 0;
if (!type){
GtkTypeInfo info = {
"BonoboStreamFS",
sizeof (BonoboStreamFS),
sizeof (BonoboStreamFSClass),
(GtkClassInitFunc) bonobo_stream_fs_class_init,
(GtkObjectInitFunc) bonobo_stream_fs_init,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
};
type = gtk_type_unique (bonobo_stream_get_type (), &info);
}
return type;
}
/**
* bonobo_stream_fs_construct:
* @stream: The BonoboStreamFS object to initialize.
* @corba_stream: The CORBA server which implements the BonoboStreamFS service.
*
* This function initializes an object of type BonoboStreamFS using the
* provided CORBA server @corba_stream.
*
* Returns the constructed BonoboStreamFS @stream.
*/
BonoboStream *
bonobo_stream_fs_construct (BonoboStreamFS *stream,
Bonobo_Stream corba_stream)
{
g_return_val_if_fail (stream != NULL, NULL);
g_return_val_if_fail (BONOBO_IS_STREAM (stream), NULL);
g_return_val_if_fail (corba_stream != CORBA_OBJECT_NIL, NULL);
bonobo_object_construct (
BONOBO_OBJECT (stream), corba_stream);
return BONOBO_STREAM (stream);
}
static BonoboStream *
bonobo_stream_create (int fd, const char *path)
{
BonoboStreamFS *stream_fs;
Bonobo_Stream corba_stream;
stream_fs = gtk_type_new (bonobo_stream_fs_get_type ());
if (stream_fs == NULL)
return NULL;
stream_fs->fd = fd;
stream_fs->priv->mime_type = g_strdup (gnome_mime_type_of_file (path));
corba_stream = bonobo_stream_corba_object_create (
BONOBO_OBJECT (stream_fs));
if (corba_stream == CORBA_OBJECT_NIL) {
bonobo_object_unref (BONOBO_OBJECT (stream_fs));
return NULL;
}
return bonobo_stream_fs_construct (stream_fs, corba_stream);
}
/**
* bonobo_stream_fs_open:
* @path: The path to the file to be opened.
* @flags: The flags with which the file should be opened.
*
* Creates a new BonoboStream object for the filename specified by
* @path.
*/
BonoboStream *
bonobo_stream_fs_open (const char *path, gint flags, gint mode,
CORBA_Environment *ev)
{
BonoboStream *stream;
struct stat st;
int v, fd;
gint fs_flags;
if (!path || !ev) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_IOError, NULL);
return NULL;
}
if (((v = stat (path, &st)) == -1) &&
!(flags & Bonobo_Storage_CREATE)) {
if ((errno == ENOENT) || (errno == ENOTDIR))
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NotFound,
NULL);
else if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NoPermission,
NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_IOError, NULL);
return NULL;
}
if ((v != -1) && S_ISDIR(st.st_mode)) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NotStream,
NULL);
return NULL;
}
fs_flags = bonobo_mode_to_fs (flags);
if ((fd = open (path, fs_flags, mode)) == -1) {
if ((errno == ENOENT) || (errno == ENOTDIR))
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NotFound,
NULL);
else if (errno == EACCES)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NoPermission,
NULL);
else if (errno == EEXIST)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_NameExists,
NULL);
else
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_IOError, NULL);
return NULL;
}
if (!(stream = bonobo_stream_create (fd, path)))
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_Bonobo_Storage_IOError, NULL);
return stream;
}
syntax highlighted by Code2HTML, v. 0.9.1