gio/ docs/reference/gio Merged gio-standalone into glib.

2007-11-26  Alexander Larsson  <alexl@redhat.com>

        * Makefile.am:
        * configure.in:
        * gio-2.0-uninstalled.pc.in:
        * gio-2.0.pc.in: 
        * gio-unix-2.0-uninstalled.pc.in:
        * gio-unix-2.0.pc.in:
	* gio/
	* docs/reference/gio
	Merged gio-standalone into glib.
	
        * glib/glibintl.h:
        * glib/gutils.c:
	Export glib_gettext so that gio can use it
	Add P_ (using same domain for now)
	Add I_ as g_intern_static_string


svn path=/trunk/; revision=5941
This commit is contained in:
Alexander Larsson 2007-11-26 16:13:05 +00:00 committed by Alexander Larsson
parent 8bdbcb9213
commit 3781343738
183 changed files with 52751 additions and 5 deletions

View File

@ -1,3 +1,21 @@
2007-11-26 Alexander Larsson <alexl@redhat.com>
* Makefile.am:
* configure.in:
* gio-2.0-uninstalled.pc.in:
* gio-2.0.pc.in:
* gio-unix-2.0-uninstalled.pc.in:
* gio-unix-2.0.pc.in:
* gio/
* docs/reference/gio
Merged gio-standalone into glib.
* glib/glibintl.h:
* glib/gutils.c:
Export glib_gettext so that gio can use it
Add P_ (using same domain for now)
Add I_ as g_intern_static_string
2007-11-26 Tor Lillqvist <tml@novell.com>
* glib/win_iconv.c: ISO8859-1 is CP28591, not CP1252.

View File

@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.decl
AUTOMAKE_OPTIONS = 1.7
SUBDIRS = . m4macros glib gobject gmodule gthread tests build po docs
SUBDIRS = . m4macros glib gobject gmodule gthread gio tests build po docs
bin_SCRIPTS = glib-gettextize
@ -45,11 +45,15 @@ EXTRA_DIST += \
gmodule-export-2.0.pc.in \
gmodule-no-export-2.0.pc.in \
gthread-2.0.pc.in \
gio-2.0.pc.in \
gio-unix-2.0.pc.in \
glib-2.0-uninstalled.pc.in \
gobject-2.0-uninstalled.pc.in \
gmodule-2.0-uninstalled.pc.in \
gthread-2.0-uninstalled.pc.in \
gmodule-no-export-2.0-uninstalled.pc.in
gmodule-no-export-2.0-uninstalled.pc.in \
gio-2.0-uninstalled.pc.in \
gio-unix-2.0-uninstalled.pc.in
# These may be in the builddir too
@ -77,7 +81,7 @@ stamp-gc-h: config.status
echo timestamp > stamp-gc-h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = glib-2.0.pc gobject-2.0.pc gmodule-2.0.pc gmodule-export-2.0.pc gmodule-no-export-2.0.pc gthread-2.0.pc
pkgconfig_DATA = glib-2.0.pc gobject-2.0.pc gmodule-2.0.pc gmodule-export-2.0.pc gmodule-no-export-2.0.pc gthread-2.0.pc gio-2.0.pc gio-unix-2.0.pc
$(pkgconfig_DATA): config.status

View File

@ -822,9 +822,15 @@ AM_CONDITIONAL(HAVE_SUNSTUDIO_VISIBILITY, [test x$g_have_sunstudio_visibility =
AC_C_BIGENDIAN
# check for header files
AC_CHECK_HEADERS([dirent.h float.h limits.h pwd.h sys/param.h sys/poll.h sys/resource.h])
AC_CHECK_HEADERS([dirent.h float.h limits.h pwd.h grp.h sys/param.h sys/poll.h sys/resource.h])
AC_CHECK_HEADERS([sys/time.h sys/times.h sys/wait.h unistd.h values.h])
AC_CHECK_HEADERS([sys/select.h sys/types.h stdint.h sched.h malloc.h])
AC_CHECK_HEADERS([sys/vfs.h sys/mount.h sys/vmount.h sys/statfs.h sys/statvfs.h])
AC_CHECK_HEADERS([mntent.h sys/mnttab.h sys/vfstab.h sys/mntctl.h sys/sysctl.h fstab.h])
# check for structure fields
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec, struct stat.st_atimensec, struct stat.st_atim.tv_nsec, struct stat.st_ctimensec, struct stat.st_ctim.tv_nsec])
AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_blocks])
# Checks for libcharset
jm_LANGINFO_CODESET
@ -888,6 +894,8 @@ AC_MSG_RESULT(unsigned $glib_size_type)
# Check for some functions
AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf stpcpy strcasecmp strncasecmp poll getcwd vasprintf setenv unsetenv getc_unlocked readlink symlink fdwalk)
AC_CHECK_FUNCS(chown lchown fchmod fchown link statvfs statfs utimes getgrgid getpwuid)
AC_CHECK_FUNCS(setmntent endmntent hasmntopt getmntinfo)
# Check for high-resolution sleep functions
AC_CHECK_FUNCS(nanosleep nsleep)
@ -897,6 +905,47 @@ AC_CHECK_FUNCS(_NSGetEnviron)
AC_FUNC_VSNPRINTF_C99
AC_FUNC_PRINTF_UNIX98
dnl
dnl if statfs() takes 2 arguments (Posix) or 4 (Solaris)
dnl
if test "$ac_cv_func_statfs" = yes ; then
AC_MSG_CHECKING([number of arguments to statfs()])
AC_TRY_COMPILE([#include <unistd.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif], [struct statfs st;
statfs(NULL, &st);],[
AC_MSG_RESULT([2])
AC_DEFINE(STATFS_ARGS, 2, [Number of arguments to statfs()])],[
AC_TRY_COMPILE([#include <unistd.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif], [struct statfs st;
statfs(NULL, &st, sizeof (st), 0);],[
AC_MSG_RESULT([4])
AC_DEFINE(STATFS_ARGS, 4, [Number of arguments to statfs()])],[
AC_MSG_RESULT(unknown)
AC_MSG_ERROR([unable to determine number of arguments to statfs()])])])
fi
#
# Check whether to use an included printf
#
@ -1399,6 +1448,105 @@ esac
AC_MSG_RESULT($GIO)
AC_SUBST(GIO)
dnl **********************************
dnl *** Check for libselinux (GIO) ***
dnl **********************************
AC_ARG_ENABLE(selinux, [ --disable-selinux build without selinux support])
msg_selinux=no
SELINUX_LIBS=
if test "x$enable_selinux" != "xno"; then
AC_CHECK_LIB(selinux, is_selinux_enabled,
[AC_CHECK_HEADERS(selinux/selinux.h,
[AC_SEARCH_LIBS(lgetfilecon_raw, selinux,
[AC_DEFINE(HAVE_SELINUX, 1, [Define to 1 if libselinux is available])
SELINUX_LIBS="-lselinux"
msg_selinux=yes])
])
])
fi
AC_SUBST(SELINUX_LIBS)
dnl *****************************
dnl ** Check for inotify (GIO) **
dnl *****************************
inotify_support=no
AC_CHECK_HEADERS([linux/inotify.h],
[
inotify_support=yes
])
AC_CHECK_HEADERS([sys/inotify.h],
[
inotify_support=yes
])
AM_CONDITIONAL(HAVE_INOTIFY, [test "$inotify_support" = "yes"])
dnl ****************************
dnl *** Checks for FAM (GIO) ***
dnl ****************************
should_disable_fam=no
AC_ARG_ENABLE(fam, [ --disable-fam build without enabling fam for file system monitoring],
[
if test "x$enable_fam" = "xno"; then
should_disable_fam=yes
echo "Not building FAM support"
fi
]
)
fam_support=no
FAM_LIBS=
if test "x$should_disable_fam" = "xno"; then
AC_CHECK_LIB(fam, FAMOpen,
[AC_CHECK_HEADERS(fam.h,
[AC_DEFINE(HAVE_FAM, [], [Define if we have FAM])
AC_CHECK_LIB(fam, FAMNoExists,
AC_DEFINE(HAVE_FAM_NO_EXISTS, [], [Define if we have FAMNoExists in fam]))
FAM_LIBS="-lfam"]
fam_support=yes,
AC_MSG_WARN(*** FAM support will not be built (header files not found) ***))],
AC_MSG_WARN(*** FAM support will not be built (FAM library not found) ***))
AC_SUBST(FAM_LIBS)
fi
AM_CONDITIONAL(HAVE_FAM, [test "$fam_support" = "yes"])
dnl *****************************
dnl *** Check for xattr (GIO) ***
dnl *****************************
AC_ARG_ENABLE(xattr, [ --disable-xattr build without xattr support])
msg_xattr=no
XATTR_LIBS=
if test "x$enable_xattr" != "xno"; then
dnl either glibc or libattr can provide xattr support
dnl for both of them, we check for getxattr being in
dnl the library and a valid xattr header.
dnl try glibc
AC_CHECK_LIB(c, getxattr,
[AC_CHECK_HEADERS(sys/xattr.h,
[AC_DEFINE(HAVE_XATTR, 1, [Define to 1 if xattr is available])
msg_xattr=yes])
])
if test "x$msg_xattr" != "xyes"; then
dnl failure. try libattr
AC_CHECK_LIB(attr, getxattr,
[AC_CHECK_HEADERS(attr/xattr.h,
[AC_DEFINE(HAVE_XATTR, 1, [Define to 1 if xattr is available])
XATTR_LIBS="-lattr"
msg_xattr=yes])
])
fi
fi
AC_SUBST(XATTR_LIBS)
dnl ****************************************
dnl *** platform dependent source checks ***
dnl ****************************************
@ -1872,6 +2020,45 @@ int main () {
fi
fi
fi
if test "$ac_cv_header_grp_h" = "yes"; then
AC_CACHE_CHECK([for posix getgrgid_r],
ac_cv_func_posix_getgrgid_r,
[AC_TRY_RUN([
#include <errno.h>
#include <grp.h>
int main () {
char buffer[10000];
struct group grp, *grpptr = &grp;
int error;
errno = 0;
error = getgrgid_r (0, &grp, buffer,
sizeof (buffer), &grpptr);
return (error < 0 && errno == ENOSYS)
|| error == ENOSYS;
} ],
[ac_cv_func_posix_getgrgid_r=yes],
[ac_cv_func_posix_getgrgid_r=no])])
GLIB_ASSERT_SET(ac_cv_func_posix_getgrgid_r)
if test "$ac_cv_func_posix_getgrgid_r" = yes; then
AC_DEFINE(HAVE_POSIX_GETGRGID_R,1,
[Have POSIX function getgrgid_r])
else
AC_CACHE_CHECK([for nonposix getgrgid_r],
ac_cv_func_nonposix_getgrgid_r,
[AC_TRY_LINK([#include <grp.h>],
[char buffer[10000];
struct group grp;
getgrgid_r (0, &grp, buffer,
sizeof (buffer));],
[ac_cv_func_nonposix_getgrgid_r=yes],
[ac_cv_func_nonposix_getgrgid_r=no])])
GLIB_ASSERT_SET(ac_cv_func_nonposix_getgrgid_r)
if test "$ac_cv_func_nonposix_getgrgid_r" = yes; then
AC_DEFINE(HAVE_NONPOSIX_GETGRGID_R,1,
[Have non-POSIX function getgrgid_r])
fi
fi
fi
LIBS="$G_THREAD_LIBS $LIBS"
if test x"$have_threads" = xposix; then
glib_save_CPPFLAGS="$CPPFLAGS"
@ -2974,6 +3161,10 @@ gthread-2.0.pc
gthread-2.0-uninstalled.pc
gobject-2.0.pc
gobject-2.0-uninstalled.pc
gio-2.0.pc
gio-unix-2.0.pc
gio-2.0-uninstalled.pc
gio-unix-2.0-uninstalled.pc
glib-zip
glib-gettextize
Makefile
@ -2992,6 +3183,10 @@ gmodule/gmoduleconf.h
gobject/Makefile
gobject/glib-mkenums
gthread/Makefile
gio/Makefile
gio/xdgmime/Makefile
gio/inotify/Makefile
gio/fam/Makefile
po/Makefile.in
docs/Makefile
docs/reference/Makefile
@ -2999,6 +3194,8 @@ docs/reference/glib/Makefile
docs/reference/glib/version.xml
docs/reference/gobject/Makefile
docs/reference/gobject/version.xml
docs/reference/gio/Makefile
docs/reference/gio/version.xml
tests/Makefile
tests/gobject/Makefile
tests/refcount/Makefile

View File

@ -1,3 +1,13 @@
2007-11-26 Alexander Larsson <alexl@redhat.com>
* Makefile.am:
* gio/Makefile.am:
* gio/gio-docs.xml:
* gio/gio-sections.txt:
* gio/gio.types:
* gio/version.xml.in:
Add gio docs
2007-11-23 Matthias Clasen <mclasen@redhat.com>
* glib/tmpl/i18n.sgml:

View File

@ -1,3 +1,3 @@
include $(top_srcdir)/Makefile.decl
SUBDIRS = glib gobject
SUBDIRS = glib gobject gio

View File

@ -0,0 +1,90 @@
include $(top_srcdir)/Makefile.decl
NULL =
# The name of the module.
DOC_MODULE=gio
# The top-level SGML file.
DOC_MAIN_SGML_FILE=gio-docs.xml
# Extra options to supply to gtkdoc-scan
SCAN_OPTIONS=--deprecated-guards="G_DISABLE_DEPRECATED"
# The directory containing the source code. Relative to $(srcdir)
DOC_SOURCE_DIR=$(top_srcdir)/gio
HFILE_GLOB=$(top_srcdir)/gio/*.h
CFILE_GLOB=$(top_srcdir)/gio/*.c
# Headers to ignore
IGNORE_HFILES= \
fam-helper.h \
gasynchelper.h \
gdesktopappinfo.h \
gdummyfile.h \
gfamdirectorymonitor.h \
gfamfilemonitor.h \
ginotifydirectorymonitor.h \
ginotifyfilemonitor.h \
glocaldirectorymonitor.h \
glocalfile.h \
glocalfileenumerator.h \
glocalfileinfo.h \
glocalfileinputstream.h \
glocalfilemonitor.h \
glocalfileoutputstream.h \
glocalvfs.h \
gnativevolumemonitor.h \
gpollfilemonitor.h \
gunionvolumemonitor.h \
gunixdrive.h \
gunixvolume.h \
gunixvolumemonitor.h \
gvolumeprivate.h \
gwin32appinfo.h \
inotify-kernel.h \
local_inotify.h \
local_inotify_syscalls.h \
xdgmime.h \
xdgmimealias.h \
xdgmimecache.h \
xdgmimeglob.h \
xdgmimeint.h \
xdgmimemagic.h \
xdgmimeparent.h \
$(NULL)
# CFLAGS and LDFLAGS for compiling scan program. Only needed
# if $(DOC_MODULE).types is non-empty.
INCLUDES = \
-I$(srcdir) \
-I$(top_srcdir) \
-I$(top_srcdir)/glib \
-I$(top_srcdir)/gobject \
-I$(top_builddir) \
-I$(top_builddir)/glib \
-I$(top_builddir)/gobject \
$(GLIB_DEBUG_FLAGS)
GTKDOC_LIBS = \
$(top_builddir)/glib/libglib-2.0.la \
$(top_builddir)/gobject/libgobject-2.0.la \
$(top_builddir)/gmodule/libgmodule-2.0.la \
$(top_builddir)/gio/libgio-2.0.la \
$(NULL)
# Extra options to supply to gtkdoc-mkdb
MKDB_OPTIONS = --output-format=xml --sgml-mode
# Images to copy into HTML directory
HTML_IMAGES =
content_files = \
version.xml
extra_files = version.xml.in
include $(top_srcdir)/gtk-doc.make
EXTRA_DIST += \
version.xml.in

View File

@ -0,0 +1,106 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY version SYSTEM "version.xml">
]>
<book lang="en" id="gio" xmlns:xi="http://www.w3.org/2003/XInclude">
<title>GIO Reference Manual</title>
<bookinfo>
<title>GIO Reference Manual</title>
<releaseinfo>for GIO &version;</releaseinfo>
</bookinfo>
<part>
<title>GIO Overview</title>
</part>
<part>
<title>API Reference</title>
<chapter id="file_ops">
<title>File Operations</title>
<xi:include href="xml/gfile.xml"/>
<xi:include href="xml/gfileattribute.xml"/>
<xi:include href="xml/gfileinfo.xml"/>
<xi:include href="xml/gfileenumerator.xml"/>
<xi:include href="xml/gmountoperation.xml"/>
<xi:include href="xml/gioerror.xml"/>
</chapter>
<chapter id="file_mon">
<title>File System Monitoring</title>
<xi:include href="xml/gfilemonitor.xml"/>
<xi:include href="xml/gdirectorymonitor.xml"/>
</chapter>
<chapter id="async">
<title>Asynchronous I/O</title>
<xi:include href="xml/gcancellable.xml"/>
<xi:include href="xml/gasyncresult.xml"/>
<xi:include href="xml/gioscheduler.xml"/>
<xi:include href="xml/gsimpleasyncresult.xml"/>
</chapter>
<chapter id="streaming">
<title>Streaming I/O</title>
<xi:include href="xml/gseekable.xml"/>
<xi:include href="xml/ginputstream.xml"/>
<xi:include href="xml/goutputstream.xml"/>
<xi:include href="xml/gfileinputstream.xml"/>
<xi:include href="xml/gfileoutputstream.xml"/>
<xi:include href="xml/gfilterinputstream.xml"/>
<xi:include href="xml/gfilteroutputstream.xml"/>
<xi:include href="xml/gmemoryinputstream.xml"/>
<xi:include href="xml/gmemoryoutputstream.xml"/>
<xi:include href="xml/gbufferedinputstream.xml"/>
<xi:include href="xml/gbufferedoutputstream.xml"/>
<xi:include href="xml/gdatainputstream.xml"/>
<xi:include href="xml/gdataoutputstream.xml"/>
<xi:include href="xml/gsocketinputstream.xml"/>
<xi:include href="xml/gsocketoutputstream.xml"/>
</chapter>
<chapter id="types">
<title>File types and applications</title>
<xi:include href="xml/gcontenttype.xml"/>
<xi:include href="xml/gappinfo.xml"/>
</chapter>
<chapter id="volume_mon">
<title>Volumes and Drives</title>
<xi:include href="xml/gvolumemonitor.xml"/>
<xi:include href="xml/gvolume.xml"/>
<xi:include href="xml/gdrive.xml"/>
<xi:include href="xml/gunixmounts.xml"/>
</chapter>
<chapter id="icons">
<title>Icons</title>
<xi:include href="xml/gicon.xml"/>
<xi:include href="xml/gfileicon.xml"/>
<xi:include href="xml/gloadableicon.xml"/>
<xi:include href="xml/gthemedicon.xml"/>
</chapter>
<chapter id="utils">
<title>Utilities</title>
<xi:include href="xml/gfilenamecompleter.xml"/>
<xi:include href="xml/gurifuncs.xml"/>
</chapter>
<chapter id="extending">
<title>Extending GIO</title>
<xi:include href="xml/gvfs.xml"/>
<xi:include href="xml/giomodule.xml"/>
</chapter>
</part>
<chapter id="gio-hierarchy">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index>
<title id="index-all">Index</title>
</index>
</book>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
g_icon_get_type
g_seekable_get_type
g_unix_mount_monitor_get_type
g_data_output_stream_get_type
g_socket_output_stream_get_type
g_local_file_enumerator_get_type
g_socket_input_stream_get_type
g_dummy_file_get_type
g_memory_input_stream_get_type
g_volume_get_type
g_file_monitor_get_type
g_data_input_stream_get_type
g_vfs_get_type
g_mount_operation_get_type
g_local_directory_monitor_get_type
g_themed_icon_get_type
g_local_file_input_stream_get_type
g_file_enumerator_get_type
g_async_result_get_type
g_filename_completer_get_type
g_local_file_get_type
g_local_vfs_get_type
g_filter_output_stream_get_type
g_file_icon_get_type
g_buffered_input_stream_get_type
g_local_file_monitor_get_type
g_union_volume_monitor_get_type
g_output_stream_get_type
g_unix_drive_get_type
g_drive_get_type
g_file_input_stream_get_type
g_poll_file_monitor_get_type
g_file_get_type
g_filter_input_stream_get_type
g_volume_monitor_get_type
g_directory_monitor_get_type
g_desktop_app_info_get_type
g_io_module_get_type
g_native_volume_monitor_get_type
g_buffered_output_stream_get_type
g_unix_volume_get_type
g_input_stream_get_type
g_app_info_get_type
g_file_output_stream_get_type
g_cancellable_get_type
g_memory_output_stream_get_type
g_simple_async_result_get_type
g_loadable_icon_get_type
g_local_file_output_stream_get_type
g_file_info_get_type
g_unix_volume_monitor_get_type

View File

@ -0,0 +1 @@
@VERSION@

View File

@ -0,0 +1,6 @@
Name: GIO Uninstalled
Description: glib I/O library, Not Installed
Version: @VERSION@
Requires: gobject-2.0-uninstalled,gmodule-no-export-2.0-uninstalled
Libs: ${pc_top_builddir}/${pcfiledir}/gio/libgio-2.0.la
Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@

11
gio-2.0.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: GIO
Description: glib I/O library
Version: @VERSION@
Requires: gobject-2.0,gmodule-no-export-2.0
Libs: -L${libdir} -lgio-2.0
Cflags:

View File

@ -0,0 +1,6 @@
Name: GIO unix specific APIs
Description: unix specific headers for glib I/O library, Not Installed
Version: @VERSION@
Requires: gobject-2.0-uninstalled,gmodule-no-export-2.0-uninstalled,gio-2.0-uninstalled
Libs: ${pc_top_builddir}/${pcfiledir}/gio/libgio-2.0.la
Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@

11
gio-unix-2.0.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: GIO unix specific APIs
Description: unix specific headers for glib I/O library
Version: @VERSION@
Requires: gobject-2.0,gmodule-no-export-2.0,gio-2.0
Libs: -L${libdir} -lgio-2.0
Cflags: -I${includedir}/gio-unix-2.0/

225
gio/Makefile.am Normal file
View File

@ -0,0 +1,225 @@
NULL =
SUBDIRS=
if OS_UNIX
SUBDIRS += xdgmime
endif
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\"GLib-GIO\" \
-I$(top_builddir) \
-I$(top_srcdir) \
-I$(top_srcdir)/glib \
-I$(top_srcdir)/gmodule \
$(GLIB_DEBUG_FLAGS) \
-DG_DISABLE_DEPRECATED \
-DGIO_MODULE_DIR=\"$(libdir)/gio/modules\"
lib_LTLIBRARIES = libgio-2.0.la
marshal_sources = \
gio-marshal.h \
gio-marshal.c \
$(NULL)
if CROSS_COMPILING
glib_genmarshal=$(GLIB_GENMARSHAL)
else
glib_genmarshal=../gobject/glib-genmarshal
endif
gio-marshal.h: gio-marshal.list
$(glib_genmarshal) --prefix=_gio_marshal $(srcdir)/gio-marshal.list --header > $@
gio-marshal.c: gio-marshal.h gio-marshal.list
(echo "#include \"gio-marshal.h\""; \
$(glib_genmarshal) --prefix=_gio_marshal $(srcdir)/gio-marshal.list --body) > $@
local_sources = \
glocaldirectorymonitor.c \
glocaldirectorymonitor.h \
glocalfile.c \
glocalfile.h \
glocalfileenumerator.c \
glocalfileenumerator.h \
glocalfileinfo.c \
glocalfileinfo.h \
glocalfileinputstream.c \
glocalfileinputstream.h \
glocalfilemonitor.c \
glocalfilemonitor.h \
glocalfileoutputstream.c \
glocalfileoutputstream.h \
glocalvfs.c \
glocalvfs.h \
$(NULL)
platform_libadd =
appinfo_sources =
if HAVE_INOTIFY
SUBDIRS += inotify
platform_libadd += inotify/libinotify.la
endif
SUBDIRS += .
if HAVE_FAM
SUBDIRS += fam
endif
if OS_UNIX
appinfo_sources += gdesktopappinfo.c gdesktopappinfo.h
platform_libadd += xdgmime/libxdgmime.la
unix_sources = \
gunixdrive.c \
gunixdrive.h \
gunixmounts.c \
gunixmounts.h \
gunixvolume.c \
gunixvolume.h \
gunixvolumemonitor.c \
gunixvolumemonitor.h \
$(NULL)
giounixincludedir=$(includedir)/gio-unix-2.0/gio
giounixinclude_HEADERS = \
gunixmounts.h \
$(NULL)
endif
if OS_WIN32
appinfo_sources += gwin32appinfo.c gwin32appinfo.h
platform_libadd += -lshlwapi
endif
libgio_2_0_la_SOURCES = \
gappinfo.c \
gasynchelper.c \
gasynchelper.h \
gasyncresult.c \
gbufferedinputstream.c \
gbufferedoutputstream.c \
gcancellable.c \
gcontenttype.c \
gcontenttypeprivate.h \
gdatainputstream.c \
gdataoutputstream.c \
gdirectorymonitor.c \
gdrive.c \
gdriveprivate.h \
gdummyfile.c \
gfile.c \
gfileattribute.c \
gfileenumerator.c \
gfileicon.c \
gfileinfo.c \
gfileinputstream.c \
gfilemonitor.c \
gfilenamecompleter.c \
gfileoutputstream.c \
gfilterinputstream.c \
gfilteroutputstream.c \
gicon.c \
ginputstream.c \
gioerror.c \
giomodule.c \
gioscheduler.c \
gloadableicon.c \
gmemoryinputstream.c \
gmemoryoutputstream.c \
gmountoperation.c \
gnativevolumemonitor.c \
gnativevolumemonitor.h \
goutputstream.c \
gpollfilemonitor.c \
gpollfilemonitor.h \
gseekable.c \
gsimpleasyncresult.c \
gsocketinputstream.c \
gsocketoutputstream.c \
gthemedicon.c \
gunionvolumemonitor.c \
gunionvolumemonitor.h \
gurifuncs.c \
gvfs.c \
gvolume.c \
gvolumemonitor.c \
gvolumeprivate.h \
$(appinfo_sources) \
$(unix_sources) \
$(local_sources) \
$(marshal_sources) \
$(NULL)
$(libgio_2_0_la_OBJECTS): $(marshal_sources)
libgio_2_0_la_LIBADD = \
$(top_builddir)/glib/libglib-2.0.la \
$(top_builddir)/gobject/libgobject-2.0.la \
$(top_builddir)/gmodule/libgmodule-2.0.la \
$(platform_libadd) \
$(SELINUX_LIBS) \
$(GLIB_LIBS) \
$(XATTR_LIBS) \
$(NULL)
if OS_WIN32
no_undefined = -no-undefined
endif
libgio_2_0_la_LDFLAGS= -export-dynamic $(no_undefined) -export-symbols-regex '^g_.*'
gioincludedir=$(includedir)/glib-2.0/gio/
gioinclude_HEADERS = \
gappinfo.h \
gasyncresult.h \
gbufferedinputstream.h \
gbufferedoutputstream.h \
gcancellable.h \
gcontenttype.h \
gdatainputstream.h \
gdataoutputstream.h \
gdirectorymonitor.h \
gdrive.h \
gdummyfile.h \
gfile.h \
gfileattribute.h \
gfileenumerator.h \
gfileicon.h \
gfileinfo.h \
gfileinputstream.h \
gfilemonitor.h \
gfilenamecompleter.h \
gfileoutputstream.h \
gfilterinputstream.h \
gfilteroutputstream.h \
gicon.h \
ginputstream.h \
gioerror.h \
giomodule.h \
gioscheduler.h \
gloadableicon.h \
gmemoryinputstream.h \
gmemoryoutputstream.h \
gmountoperation.h \
goutputstream.h \
gseekable.h \
gsimpleasyncresult.h \
gsocketinputstream.h \
gsocketoutputstream.h \
gthemedicon.h \
gurifuncs.h \
gvfs.h \
gvolume.h \
gvolumemonitor.h \
$(NULL)
EXTRA_DIST = \
gio-marshal.list \
$(NULL)
CLEANFILES = \
$(marshal_sources) \
$(NULL)

33
gio/fam/Makefile.am Normal file
View File

@ -0,0 +1,33 @@
NULL =
module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
giomodule_LTLIBRARIES = libgiofam.la
giomoduledir = $(libdir)/gio/modules
libgiofam_la_SOURCES = \
fam-helper.c \
fam-helper.h \
fam-module.c \
gfamdirectorymonitor.c \
gfamdirectorymonitor.h \
gfamfilemonitor.c \
gfamfilemonitor.h \
$(NULL)
libgiofam_la_CFLAGS = \
-DG_LOG_DOMAIN=\"GLib-GIO\" \
-I$(top_srcdir) \
-I$(top_srcdir)/glib \
-I$(top_srcdir)/gmodule \
-I$(top_srcdir)/gio \
-DGIO_MODULE_DIR=\"$(libdir)/gio/modules\" \
-DG_DISABLE_DEPRECATED
libgiofam_la_LDFLAGS = $(module_flags)
libgiofam_la_LIBADD = \
$(top_builddir)/gio/libgio-2.0.la \
$(GLIB_LIBS) \
$(FAM_LIBS) \
$(NULL)

245
gio/fam/fam-helper.c Normal file
View File

@ -0,0 +1,245 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include "config.h"
#include <fam.h>
#include <gio/gfilemonitor.h>
#include <gio/gdirectorymonitor.h>
#include "fam-helper.h"
static FAMConnection* fam_connection = NULL;
static gint fam_watch_id = 0;
G_LOCK_DEFINE_STATIC(fam_connection);
struct _fam_sub
{
gchar *pathname;
gboolean directory;
gpointer user_data;
gboolean cancelled;
FAMRequest request;
};
static GFileMonitorEvent
fam_event_to_file_monitor_event (enum FAMCodes code)
{
switch (code)
{
case FAMChanged:
return G_FILE_MONITOR_EVENT_CHANGED;
break;
case FAMDeleted:
return G_FILE_MONITOR_EVENT_DELETED;
break;
case FAMCreated:
return G_FILE_MONITOR_EVENT_CREATED;
break;
default:
return -1;
break;
}
}
static gboolean
fam_do_iter_unlocked (void)
{
while (fam_connection != NULL && FAMPending (fam_connection)) {
FAMEvent ev;
fam_sub* sub = NULL;
gboolean cancelled;
if (FAMNextEvent (fam_connection, &ev) != 1) {
FAMClose (fam_connection);
g_free (fam_connection);
g_source_remove (fam_watch_id);
fam_watch_id = 0;
fam_connection = NULL;
return FALSE;
}
sub = (fam_sub*)ev.userdata;
cancelled = sub->cancelled;
if (ev.code == FAMAcknowledge && cancelled)
{
g_free (sub);
continue;
}
if (cancelled)
continue;
if (sub->directory)
{
GDirectoryMonitor* monitor = G_DIRECTORY_MONITOR (sub->user_data);
GFileMonitorEvent eflags = fam_event_to_file_monitor_event (ev.code);
gchar* path = NULL;
GFile *child, *parent;
/* unsupported event */
if (eflags == -1)
continue;
if (ev.filename[0] == '/')
path = g_strdup (ev.filename);
else
path = g_strdup_printf ("%s/%s", sub->pathname, ev.filename);
child = g_file_new_for_path (path);
parent = g_file_get_parent (child);
g_directory_monitor_emit_event (monitor, child, NULL, eflags);
g_free (path);
g_object_unref (child);
g_object_unref (parent);
} else {
GFile *child;
GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data);
GFileMonitorEvent eflags = fam_event_to_file_monitor_event (ev.code);
gchar* path = NULL;
if (eflags == -1)
continue;
path = g_strdup (ev.filename);
child = g_file_new_for_path (path);
g_file_monitor_emit_event (monitor, child, NULL, eflags);
g_free (path);
g_object_unref (child);
}
}
return TRUE;
}
static gboolean
fam_callback (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
gboolean res;
G_LOCK (fam_connection);
res = fam_do_iter_unlocked ();
G_UNLOCK (fam_connection);
return res;
}
gboolean
_fam_sub_startup (void)
{
GIOChannel *ioc;
G_LOCK (fam_connection);
if (fam_connection == NULL) {
fam_connection = g_new0 (FAMConnection, 1);
if (FAMOpen2 (fam_connection, "gvfs user") != 0) {
g_warning ("FAMOpen failed, FAMErrno=%d\n", FAMErrno);
g_free (fam_connection);
fam_connection = NULL;
G_UNLOCK (fam_connection);
return FALSE;
}
#ifdef HAVE_FAM_NO_EXISTS
/* This is a gamin extension that avoids sending all the Exists event for dir monitors */
FAMNoExists (fam_connection);
#endif
ioc = g_io_channel_unix_new (FAMCONNECTION_GETFD(fam_connection));
fam_watch_id = g_io_add_watch (ioc,
G_IO_IN | G_IO_HUP | G_IO_ERR,
fam_callback, fam_connection);
g_io_channel_unref (ioc);
}
G_UNLOCK (fam_connection);
return TRUE;
}
fam_sub*
_fam_sub_add (const gchar* pathname,
gboolean directory,
gpointer user_data)
{
fam_sub *sub;
if (!_fam_sub_startup ())
return NULL;
sub = g_new0 (fam_sub, 1);
sub->pathname = g_strdup (pathname);
sub->directory = directory;
sub->user_data = user_data;
G_LOCK (fam_connection);
/* We need to queue up incoming messages to avoid blocking on write
* if there are many monitors being canceled */
fam_do_iter_unlocked ();
if (fam_connection == NULL) {
G_UNLOCK (fam_connection);
return NULL;
}
if (directory)
FAMMonitorDirectory (fam_connection, pathname, &sub->request, sub);
else
FAMMonitorFile (fam_connection, pathname, &sub->request, sub);
G_UNLOCK (fam_connection);
return sub;
}
gboolean
_fam_sub_cancel (fam_sub* sub)
{
if (sub->cancelled)
return TRUE;
sub->cancelled = TRUE;
G_LOCK (fam_connection);
/* We need to queue up incoming messages to avoid blocking on write
* if there are many monitors being canceled */
fam_do_iter_unlocked ();
if (fam_connection == NULL) {
G_UNLOCK (fam_connection);
return FALSE;
}
FAMCancelMonitor (fam_connection, &sub->request);
G_UNLOCK (fam_connection);
return TRUE;
}
void
_fam_sub_free (fam_sub* sub)
{
g_free (sub->pathname);
g_free (sub);
}

37
gio/fam/fam-helper.h Normal file
View File

@ -0,0 +1,37 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#ifndef __FAM_HELPER_H__
#define __FAM_HELPER_H__
typedef struct _fam_sub fam_sub;
gboolean _fam_sub_startup (void);
fam_sub* _fam_sub_add (const gchar* pathname,
gboolean directory,
gpointer user_data);
gboolean _fam_sub_cancel (fam_sub* sub);
void _fam_sub_free (fam_sub* sub);
#endif /* __FAM_HELPER_H__ */

41
gio/fam/fam-module.c Normal file
View File

@ -0,0 +1,41 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2007 Sebastian Dröge.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include "giomodule.h"
#include "gfamdirectorymonitor.h"
#include "gfamfilemonitor.h"
void
g_io_module_load (GIOModule *module)
{
g_fam_file_monitor_register (module);
g_fam_directory_monitor_register (module);
}
void
g_io_module_unload (GIOModule *module)
{
}

View File

@ -0,0 +1,152 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2007 Sebastian Dröge.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include <config.h>
#include "gfamdirectorymonitor.h"
#include "giomodule.h"
#include "fam-helper.h"
struct _GFamDirectoryMonitor
{
GLocalDirectoryMonitor parent_instance;
fam_sub *sub;
};
static gboolean g_fam_directory_monitor_cancel (GDirectoryMonitor* monitor);
G_DEFINE_DYNAMIC_TYPE (GFamDirectoryMonitor, g_fam_directory_monitor, G_TYPE_LOCAL_DIRECTORY_MONITOR)
static void
g_fam_directory_monitor_finalize (GObject *object)
{
GFamDirectoryMonitor *fam_monitor = G_FAM_DIRECTORY_MONITOR (object);
fam_sub *sub = fam_monitor->sub;
if (sub) {
if (!_fam_sub_cancel (sub))
g_warning ("Unexpected error cancelling fam monitor");
_fam_sub_free (sub);
fam_monitor->sub = NULL;
}
if (G_OBJECT_CLASS (g_fam_directory_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_fam_directory_monitor_parent_class)->finalize) (object);
}
static GObject *
g_fam_directory_monitor_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
GFamDirectoryMonitorClass *klass;
GObjectClass *parent_class;
GFamDirectoryMonitor *fam_monitor;
const gchar *dirname = NULL;
fam_sub *sub = NULL;
klass = G_FAM_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_FAM_DIRECTORY_MONITOR));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
fam_monitor = G_FAM_DIRECTORY_MONITOR (obj);
dirname = G_LOCAL_DIRECTORY_MONITOR (obj)->dirname;
g_assert (dirname != NULL);
sub = _fam_sub_add (dirname, TRUE, fam_monitor);
/* FIXME: what to do about errors here? we can't return NULL or another
* kind of error and an assertion is probably too hard */
g_assert (sub != NULL);
fam_monitor->sub = sub;
return obj;
}
static void
g_fam_directory_monitor_class_finalize (GFamDirectoryMonitorClass *klass)
{
}
static gboolean
g_fam_directory_monitor_is_supported (void)
{
return _fam_sub_startup ();
}
static void
g_fam_directory_monitor_class_init (GFamDirectoryMonitorClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
GDirectoryMonitorClass *directory_monitor_class = G_DIRECTORY_MONITOR_CLASS (klass);
GLocalDirectoryMonitorClass *local_directory_monitor_class = G_LOCAL_DIRECTORY_MONITOR_CLASS (klass);
gobject_class->finalize = g_fam_directory_monitor_finalize;
gobject_class->constructor = g_fam_directory_monitor_constructor;
directory_monitor_class->cancel = g_fam_directory_monitor_cancel;
local_directory_monitor_class->prio = 10;
local_directory_monitor_class->mount_notify = FALSE;
local_directory_monitor_class->is_supported = g_fam_directory_monitor_is_supported;
}
static void
g_fam_directory_monitor_init (GFamDirectoryMonitor* monitor)
{
}
static gboolean
g_fam_directory_monitor_cancel (GDirectoryMonitor* monitor)
{
GFamDirectoryMonitor *fam_monitor = G_FAM_DIRECTORY_MONITOR (monitor);
fam_sub *sub = fam_monitor->sub;
if (sub) {
if (!_fam_sub_cancel (sub))
g_warning ("Unexpected error cancelling fam monitor");
_fam_sub_free (sub);
fam_monitor->sub = NULL;
}
if (G_DIRECTORY_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel)
(*G_DIRECTORY_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel) (monitor);
return TRUE;
}
void
g_fam_directory_monitor_register (GIOModule *module)
{
g_fam_directory_monitor_register_type (G_TYPE_MODULE (module));
}

View File

@ -0,0 +1,55 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2007 Sebastian Dröge.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#ifndef __G_FAM_DIRECTORY_MONITOR_H__
#define __G_FAM_DIRECTORY_MONITOR_H__
#include <glib-object.h>
#include <string.h>
#include <gio/gdirectorymonitor.h>
#include "glocaldirectorymonitor.h"
#include "giomodule.h"
G_BEGIN_DECLS
#define G_TYPE_FAM_DIRECTORY_MONITOR (g_fam_directory_monitor_get_type ())
#define G_FAM_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FAM_DIRECTORY_MONITOR, GFamDirectoryMonitor))
#define G_FAM_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_FAM_DIRECTORY_MONITOR, GFamDirectoryMonitorClass))
#define G_IS_FAM_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FAM_DIRECTORY_MONITOR))
#define G_IS_FAM_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FAM_DIRECTORY_MONITOR))
typedef struct _GFamDirectoryMonitor GFamDirectoryMonitor;
typedef struct _GFamDirectoryMonitorClass GFamDirectoryMonitorClass;
struct _GFamDirectoryMonitorClass {
GLocalDirectoryMonitorClass parent_class;
};
GType g_fam_directory_monitor_get_type (void);
void g_fam_directory_monitor_register (GIOModule *module);
G_END_DECLS
#endif /* __G_FAM_DIRECTORY_MONITOR_H__ */

150
gio/fam/gfamfilemonitor.c Normal file
View File

@ -0,0 +1,150 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2007 Sebastian Dröge.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include <config.h>
#include "gfamfilemonitor.h"
#include "giomodule.h"
#include "fam-helper.h"
struct _GFamFileMonitor
{
GLocalFileMonitor parent_instance;
fam_sub *sub;
};
static gboolean g_fam_file_monitor_cancel (GFileMonitor* monitor);
G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR)
static void
g_fam_file_monitor_finalize (GObject *object)
{
GFamFileMonitor *fam_monitor = G_FAM_FILE_MONITOR (object);
fam_sub *sub = fam_monitor->sub;
if (sub) {
if (!_fam_sub_cancel (sub))
g_warning ("Unexpected error cancelling fam monitor");
_fam_sub_free (sub);
fam_monitor->sub = NULL;
}
if (G_OBJECT_CLASS (g_fam_file_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_fam_file_monitor_parent_class)->finalize) (object);
}
static GObject *
g_fam_file_monitor_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
GFamFileMonitorClass *klass;
GObjectClass *parent_class;
GFamFileMonitor *fam_monitor;
const gchar *filename = NULL;
fam_sub *sub = NULL;
klass = G_FAM_FILE_MONITOR_CLASS (g_type_class_peek (G_TYPE_FAM_FILE_MONITOR));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
fam_monitor = G_FAM_FILE_MONITOR (obj);
filename = G_LOCAL_FILE_MONITOR (obj)->filename;
g_assert (filename != NULL);
sub = _fam_sub_add (filename, FALSE, fam_monitor);
/* FIXME: what to do about errors here? we can't return NULL or another
* kind of error and an assertion is probably too hard */
g_assert (sub != NULL);
fam_monitor->sub = sub;
return obj;
}
static void
g_fam_file_monitor_class_finalize (GFamFileMonitorClass *klass)
{
}
static gboolean
g_fam_file_monitor_is_supported (void)
{
return _fam_sub_startup ();
}
static void
g_fam_file_monitor_class_init (GFamFileMonitorClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass);
GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass);
gobject_class->finalize = g_fam_file_monitor_finalize;
gobject_class->constructor = g_fam_file_monitor_constructor;
file_monitor_class->cancel = g_fam_file_monitor_cancel;
local_file_monitor_class->prio = 10;
local_file_monitor_class->is_supported = g_fam_file_monitor_is_supported;
}
static void
g_fam_file_monitor_init (GFamFileMonitor* monitor)
{
}
static gboolean
g_fam_file_monitor_cancel (GFileMonitor* monitor)
{
GFamFileMonitor *fam_monitor = G_FAM_FILE_MONITOR (monitor);
fam_sub *sub = fam_monitor->sub;
if (sub) {
if (!_fam_sub_cancel (sub))
g_warning ("Unexpected error cancelling fam monitor");
_fam_sub_free (sub);
fam_monitor->sub = NULL;
}
if (G_FILE_MONITOR_CLASS (g_fam_file_monitor_parent_class)->cancel)
(*G_FILE_MONITOR_CLASS (g_fam_file_monitor_parent_class)->cancel) (monitor);
return TRUE;
}
void
g_fam_file_monitor_register (GIOModule *module)
{
g_fam_file_monitor_register_type (G_TYPE_MODULE (module));
}

55
gio/fam/gfamfilemonitor.h Normal file
View File

@ -0,0 +1,55 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
* Copyright (C) 2007 Sebastian Dröge.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#ifndef __G_FAM_FILE_MONITOR_H__
#define __G_FAM_FILE_MONITOR_H__
#include <glib-object.h>
#include <string.h>
#include <gio/gfilemonitor.h>
#include "glocalfilemonitor.h"
#include "giomodule.h"
G_BEGIN_DECLS
#define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ())
#define G_FAM_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor))
#define G_FAM_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_FAM_FILE_MONITOR, GFamFileMonitorClass))
#define G_IS_FAM_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FAM_FILE_MONITOR))
#define G_IS_FAM_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FAM_FILE_MONITOR))
typedef struct _GFamFileMonitor GFamFileMonitor;
typedef struct _GFamFileMonitorClass GFamFileMonitorClass;
struct _GFamFileMonitorClass {
GLocalFileMonitorClass parent_class;
};
GType g_fam_file_monitor_get_type (void);
void g_fam_file_monitor_register (GIOModule *module);
G_END_DECLS
#endif /* __G_FAM_FILE_MONITOR_H__ */

535
gio/gappinfo.c Normal file
View File

@ -0,0 +1,535 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gappinfo.h"
#include "glibintl.h"
#include <gioerror.h>
static void g_app_info_base_init (gpointer g_class);
static void g_app_info_class_init (gpointer g_class,
gpointer class_data);
GType
g_app_info_get_type (void)
{
static GType app_info_type = 0;
if (! app_info_type)
{
static const GTypeInfo app_info_info =
{
sizeof (GAppInfoIface), /* class_size */
g_app_info_base_init, /* base_init */
NULL, /* base_finalize */
g_app_info_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
app_info_type =
g_type_register_static (G_TYPE_INTERFACE, I_("GAppInfo"),
&app_info_info, 0);
g_type_interface_add_prerequisite (app_info_type, G_TYPE_OBJECT);
}
return app_info_type;
}
static void
g_app_info_class_init (gpointer g_class,
gpointer class_data)
{
}
static void
g_app_info_base_init (gpointer g_class)
{
}
/**
* g_app_info_dup:
* @appinfo: a #GAppInfo.
*
* Returns: a duplicate of @appinfo.
**/
GAppInfo *
g_app_info_dup (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->dup) (appinfo);
}
/**
* g_app_info_equal:
* @appinfo1: the first #GAppInfo.
* @appinfo2: the second #GAppInfo.
*
* Returns: %TRUE if @appinfo1 is equal to @appinfo2. %FALSE otherwise.
*
**/
gboolean
g_app_info_equal (GAppInfo *appinfo1,
GAppInfo *appinfo2)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo1), FALSE);
g_return_val_if_fail (G_IS_APP_INFO (appinfo2), FALSE);
if (G_TYPE_FROM_INSTANCE (appinfo1) != G_TYPE_FROM_INSTANCE (appinfo2))
return FALSE;
iface = G_APP_INFO_GET_IFACE (appinfo1);
return (* iface->equal) (appinfo1, appinfo2);
}
/**
* g_app_info_get_id:
* @appinfo: a #GAppInfo.
*
* Returns:
**/
const char *
g_app_info_get_id (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->get_id) (appinfo);
}
/**
* g_app_info_get_name:
* @appinfo: a #GAppInfo.
*
* Returns: the name of the application for @appinfo.
**/
const char *
g_app_info_get_name (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->get_name) (appinfo);
}
/**
* g_app_info_get_description:
* @appinfo: a #GAppInfo.
*
* Returns: a string containing a description of the
* application @appinfo.
* The returned string should be not freed when no longer needed.
**/
const char *
g_app_info_get_description (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->get_description) (appinfo);
}
/**
* g_app_info_get_executable:
* @appinfo: a #GAppInfo.
*
* Returns: a string containing the @appinfo's application
* binary's name.
**/
const char *
g_app_info_get_executable (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->get_executable) (appinfo);
}
/**
* g_app_info_set_as_default_for_type:
* @appinfo: a #GAppInfo.
* @content_type: the content type.
* @error: a #GError.
*
* Returns: %TRUE if the given @appinfo is the default
* for the given @content_type. %FALSE if not,
* or in case of an error.
**/
gboolean
g_app_info_set_as_default_for_type (GAppInfo *appinfo,
const char *content_type,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
g_return_val_if_fail (content_type != NULL, FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->set_as_default_for_type) (appinfo, content_type, error);
}
/**
* g_app_info_set_as_default_for_extension:
* @appinfo: a #GAppInfo.
* @extension: a string containing the file extension.
* @error: a #GError.
*
* Returns: %TRUE if the given @appinfo is the default
* for the given @extension. %FALSE if not,
* or in case of an error.
**/
gboolean
g_app_info_set_as_default_for_extension (GAppInfo *appinfo,
const char *extension,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
g_return_val_if_fail (extension != NULL, FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
if (iface->set_as_default_for_extension)
return (* iface->set_as_default_for_extension) (appinfo, extension, error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "g_app_info_set_as_default_for_extension not supported yet");
return FALSE;
}
/**
* g_app_info_add_supports_type:
* @appinfo: a #GAppInfo.
* @content_type: a string.
* @error: a #GError.
*
* Returns: %TRUE if @appinfo supports @content_type.
* %FALSE if not, or in case of an error.
**/
gboolean
g_app_info_add_supports_type (GAppInfo *appinfo,
const char *content_type,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
g_return_val_if_fail (content_type != NULL, FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
if (iface->add_supports_type)
return (* iface->add_supports_type) (appinfo, content_type, error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "g_app_info_add_supports_type not supported yet");
return FALSE;
}
/**
* g_app_info_can_remove_support_type:
* @appinfo: a #GAppInfo.
*
* Returns: %TRUE if it is possible to remove supported
* content types from a given @appinfo, %FALSE if not.
**/
gboolean
g_app_info_can_remove_supports_type (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
if (iface->can_remove_supports_type)
return (* iface->can_remove_supports_type) (appinfo);
return FALSE;
}
/**
* g_app_info_remove_supports_type:
* @appinfo: a #GAppInfo.
* @content_type: a string.
* @error: a #GError.
*
* Returns: %TRUE if @content_type support was removed
* from @appinfo. %FALSE if not.
**/
gboolean
g_app_info_remove_supports_type (GAppInfo *appinfo,
const char *content_type,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
g_return_val_if_fail (content_type != NULL, FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
if (iface->remove_supports_type)
return (* iface->remove_supports_type) (appinfo, content_type, error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "g_app_info_remove_supports_type not supported yet");
return FALSE;
}
/**
* g_app_info_get_icon:
* @appinfo: a #GAppInfo.
*
* Returns: the default #GIcon for @appinfo.
**/
GIcon *
g_app_info_get_icon (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->get_icon) (appinfo);
}
/**
* g_app_info_launch:
* @appinfo: a #GAppInfo.
* @files: a #GList of #GFile objects.
* @launch_context: a #GAppLaunchContext.
* @error: a #GError.
*
* Returns: %TRUE on successful launch.
**/
gboolean
g_app_info_launch (GAppInfo *appinfo,
GList *files,
GAppLaunchContext *launch_context,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->launch) (appinfo, files, launch_context, error);
}
/**
* g_app_info_supports_uris:
* @appinfo: a #GAppInfo.
*
* Returns: %TRUE if the @appinfo supports URIs.
**/
gboolean
g_app_info_supports_uris (GAppInfo *appinfo)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->supports_uris) (appinfo);
}
/**
* g_app_info_launch_uris:
* @appinfo: a #GAppInfo.
* @uris: a #GList containing URIs to launch.
* @launch_context: a #GAppLaunchContext.
* @error: a #GError.
*
* Returns: %TRUE if the @appinfo was launched
* with the given @uris.
**/
gboolean
g_app_info_launch_uris (GAppInfo *appinfo,
GList *uris,
GAppLaunchContext *launch_context,
GError **error)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->launch) (appinfo, uris, launch_context, error);
}
/**
* g_app_info_should_show:
* @appinfo: a #GAppInfo.
* @desktop_env: a string.
*
* Returns: %TRUE if the @GAppInfo should be shown,
* %FALSE otherwise.
**/
gboolean
g_app_info_should_show (GAppInfo *appinfo,
const char *desktop_env)
{
GAppInfoIface *iface;
g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
iface = G_APP_INFO_GET_IFACE (appinfo);
return (* iface->should_show) (appinfo, desktop_env);
}
G_DEFINE_TYPE (GAppLaunchContext, g_app_launch_context, G_TYPE_OBJECT);
/**
* g_app_launch_context_new:
*
* Returns: A new #GAppLaunchContext.
**/
GAppLaunchContext *
g_app_launch_context_new (void)
{
return g_object_new (G_TYPE_APP_LAUNCH_CONTEXT, NULL);
}
static void
g_app_launch_context_class_init (GAppLaunchContextClass *klass)
{
}
static void
g_app_launch_context_init (GAppLaunchContext *launch_context)
{
}
/**
* g_app_launch_context_get_display:
* @context: a #GAppLaunchContext.
* @info: a #GAppInfo.
* @files: a #GList of files.
*
**/
char *
g_app_launch_context_get_display (GAppLaunchContext *context,
GAppInfo *info,
GList *files)
{
GAppLaunchContextClass *class;
g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL);
g_return_val_if_fail (G_IS_APP_INFO (info), NULL);
class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context);
if (class->get_display == NULL)
return NULL;
return class->get_display (context, info, files);
}
/**
* g_app_launch_context_get_startup_notify_id:
* @context: a #GAppLaunchContext.
* @info: a #GAppInfo.
* @files: a #GList of files.
*
**/
char *
g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
GAppInfo *info,
GList *files)
{
GAppLaunchContextClass *class;
g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL);
g_return_val_if_fail (G_IS_APP_INFO (info), NULL);
class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context);
if (class->get_startup_notify_id == NULL)
return NULL;
return class->get_startup_notify_id (context, info, files);
}
/**
* g_app_launch_context_get_startup_notify_id:
* @context: a #GAppLaunchContext.
* @startup_notify_id: a string containing the startup ID of the application.
*
**/
void
g_app_launch_context_launch_failed (GAppLaunchContext *context,
const char *startup_notify_id)
{
GAppLaunchContextClass *class;
g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context));
g_return_if_fail (startup_notify_id != NULL);
class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context);
if (class->launch_failed != NULL)
class->launch_failed (context, startup_notify_id);
}

206
gio/gappinfo.h Normal file
View File

@ -0,0 +1,206 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_APP_INFO_H__
#define __G_APP_INFO_H__
#include <glib-object.h>
#include <gio/gicon.h>
G_BEGIN_DECLS
#define G_TYPE_APP_INFO (g_app_info_get_type ())
#define G_APP_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_APP_INFO, GAppInfo))
#define G_IS_APP_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_APP_INFO))
#define G_APP_INFO_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_APP_INFO, GAppInfoIface))
#define G_TYPE_APP_LAUNCH_CONTEXT (g_app_launch_context_get_type ())
#define G_APP_LAUNCH_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContext))
#define G_APP_LAUNCH_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContextClass))
#define G_IS_APP_LAUNCH_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_APP_LAUNCH_CONTEXT))
#define G_IS_APP_LAUNCH_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_APP_LAUNCH_CONTEXT))
#define G_APP_LAUNCH_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_APP_LAUNCH_CONTEXT, GAppLaunchContextClass))
typedef enum {
G_APP_INFO_CREATE_FLAGS_NONE = 0,
G_APP_INFO_CREATE_NEEDS_TERMINAL = (1<<0)
} GAppInfoCreateFlags;
typedef struct _GAppLaunchContext GAppLaunchContext;
typedef struct _GAppLaunchContextClass GAppLaunchContextClass;
typedef struct _GAppLaunchContextPrivate GAppLaunchContextPrivate;
typedef struct _GAppInfo GAppInfo; /* Dummy typedef */
typedef struct _GAppInfoIface GAppInfoIface;
struct _GAppInfoIface
{
GTypeInterface g_iface;
/* Virtual Table */
GAppInfo * (*dup) (GAppInfo *appinfo);
gboolean (*equal) (GAppInfo *appinfo1,
GAppInfo *appinfo2);
const char * (*get_id) (GAppInfo *appinfo);
const char * (*get_name) (GAppInfo *appinfo);
const char * (*get_description) (GAppInfo *appinfo);
const char * (*get_executable) (GAppInfo *appinfo);
GIcon * (*get_icon) (GAppInfo *appinfo);
gboolean (*launch) (GAppInfo *appinfo,
GList *filenames,
GAppLaunchContext *launch_context,
GError **error);
gboolean (*supports_uris) (GAppInfo *appinfo);
gboolean (*launch_uris) (GAppInfo *appinfo,
GList *uris,
GAppLaunchContext *launch_context,
GError **error);
gboolean (*should_show) (GAppInfo *appinfo,
const char *desktop_env);
gboolean (*supports_xdg_startup_notify) (GAppInfo *appinfo);
/* For changing associations */
gboolean (*set_as_default_for_type) (GAppInfo *appinfo,
const char *content_type,
GError **error);
gboolean (*set_as_default_for_extension) (GAppInfo *appinfo,
const char *extension,
GError **error);
gboolean (*add_supports_type) (GAppInfo *appinfo,
const char *content_type,
GError **error);
gboolean (*can_remove_supports_type) (GAppInfo *appinfo);
gboolean (*remove_supports_type) (GAppInfo *appinfo,
const char *content_type,
GError **error);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
void (*_g_reserved6) (void);
void (*_g_reserved7) (void);
void (*_g_reserved8) (void);
void (*_g_reserved9) (void);
void (*_g_reserved10) (void);
};
GType g_app_info_get_type (void) G_GNUC_CONST;
GType g_app_launch_context_get_type (void) G_GNUC_CONST;
GAppInfo * g_app_info_create_from_commandline (const char *commandline,
const char *application_name,
GAppInfoCreateFlags flags,
GError **error);
GAppInfo * g_app_info_dup (GAppInfo *appinfo);
gboolean g_app_info_equal (GAppInfo *appinfo1,
GAppInfo *appinfo2);
const char *g_app_info_get_id (GAppInfo *appinfo);
const char *g_app_info_get_name (GAppInfo *appinfo);
const char *g_app_info_get_description (GAppInfo *appinfo);
const char *g_app_info_get_executable (GAppInfo *appinfo);
GIcon * g_app_info_get_icon (GAppInfo *appinfo);
gboolean g_app_info_launch (GAppInfo *appinfo,
GList *files,
GAppLaunchContext *launch_context,
GError **error);
gboolean g_app_info_supports_uris (GAppInfo *appinfo);
gboolean g_app_info_launch_uris (GAppInfo *appinfo,
GList *uris,
GAppLaunchContext *launch_context,
GError **error);
gboolean g_app_info_should_show (GAppInfo *appinfo,
const char *desktop_env);
gboolean g_app_info_set_as_default_for_type (GAppInfo *appinfo,
const char *content_type,
GError **error);
gboolean g_app_info_set_as_default_for_extension (GAppInfo *appinfo,
const char *extension,
GError **error);
gboolean g_app_info_add_supports_type (GAppInfo *appinfo,
const char *content_type,
GError **error);
gboolean g_app_info_can_remove_supports_type (GAppInfo *appinfo);
gboolean g_app_info_remove_supports_type (GAppInfo *appinfo,
const char *content_type,
GError **error);
GList * g_app_info_get_all (void);
GList * g_app_info_get_all_for_type (const char *content_type);
GAppInfo *g_app_info_get_default_for_type (const char *content_type,
gboolean must_support_uris);
GAppInfo *g_app_info_get_default_for_uri_scheme (const char *uri_scheme);
/* TODO: missing operations:
add app as supporting a content type, but don't make it default
implement set_as_default_for_extension
can_remove, remove (as in, don't support a specific mimetype)
*/
struct _GAppLaunchContext
{
GObject parent_instance;
GAppLaunchContextPrivate *priv;
};
struct _GAppLaunchContextClass
{
GObjectClass parent_class;
char * (*get_display) (GAppLaunchContext *context,
GAppInfo *info,
GList *files);
char * (*get_startup_notify_id) (GAppLaunchContext *context,
GAppInfo *info,
GList *files);
void (*launch_failed) (GAppLaunchContext *context,
const char *startup_notify_id);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GAppLaunchContext *g_app_launch_context_new (void);
char * g_app_launch_context_get_display (GAppLaunchContext *context,
GAppInfo *info,
GList *files);
char * g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
GAppInfo *info,
GList *files);
void g_app_launch_context_launch_failed (GAppLaunchContext *context,
const char * startup_notify_id);
G_END_DECLS
#endif /* __G_APP_INFO_H__ */

163
gio/gasynchelper.c Normal file
View File

@ -0,0 +1,163 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gasynchelper.h"
static void
async_result_free (gpointer data)
{
GAsyncResultData *res = data;
if (res->error)
g_error_free (res->error);
g_object_unref (res->async_object);
g_free (res);
}
void
_g_queue_async_result (GAsyncResultData *result,
gpointer async_object,
GError *error,
gpointer user_data,
GSourceFunc source_func)
{
GSource *source;
g_return_if_fail (G_IS_OBJECT (async_object));
result->async_object = g_object_ref (async_object);
result->user_data = user_data;
result->error = error;
source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_callback (source, source_func, result, async_result_free);
g_source_attach (source, NULL);
g_source_unref (source);
}
/*************************************************************************
* fd source *
************************************************************************/
typedef struct
{
GSource source;
GPollFD pollfd;
GCancellable *cancellable;
gulong cancelled_tag;
} FDSource;
static gboolean
fd_source_prepare (GSource *source,
gint *timeout)
{
FDSource *fd_source = (FDSource *)source;
*timeout = -1;
return g_cancellable_is_cancelled (fd_source->cancellable);
}
static gboolean
fd_source_check (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
return
g_cancellable_is_cancelled (fd_source->cancellable) ||
fd_source->pollfd.revents != 0;
}
static gboolean
fd_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GFDSourceFunc func = (GFDSourceFunc)callback;
FDSource *fd_source = (FDSource *)source;
g_assert (func != NULL);
return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
}
static void
fd_source_finalize (GSource *source)
{
FDSource *fd_source = (FDSource *)source;
if (fd_source->cancelled_tag)
g_signal_handler_disconnect (fd_source->cancellable,
fd_source->cancelled_tag);
if (fd_source->cancellable)
g_object_unref (fd_source->cancellable);
}
static GSourceFuncs fd_source_funcs = {
fd_source_prepare,
fd_source_check,
fd_source_dispatch,
fd_source_finalize
};
/* Might be called on another thread */
static void
fd_source_cancelled_cb (GCancellable *cancellable,
gpointer data)
{
/* Wake up the mainloop in case we're waiting on async calls with FDSource */
g_main_context_wakeup (NULL);
}
GSource *
_g_fd_source_new (int fd,
gushort events,
GCancellable *cancellable)
{
GSource *source;
FDSource *fd_source;
source = g_source_new (&fd_source_funcs, sizeof (FDSource));
fd_source = (FDSource *)source;
if (cancellable)
fd_source->cancellable = g_object_ref (cancellable);
fd_source->pollfd.fd = fd;
fd_source->pollfd.events = events;
g_source_add_poll (source, &fd_source->pollfd);
if (cancellable)
fd_source->cancelled_tag =
g_signal_connect_data (cancellable, "cancelled",
(GCallback)fd_source_cancelled_cb,
NULL, NULL,
0);
return source;
}

53
gio/gasynchelper.h Normal file
View File

@ -0,0 +1,53 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_ASYNC_HELPER_H__
#define __G_ASYNC_HELPER_H__
#include <glib-object.h>
#include "gcancellable.h"
G_BEGIN_DECLS
typedef struct {
gpointer async_object;
GError * error;
gpointer user_data;
} GAsyncResultData;
typedef gboolean (*GFDSourceFunc) (gpointer user_data,
GIOCondition condition,
int fd);
void _g_queue_async_result (GAsyncResultData *result,
gpointer async_object,
GError *error,
gpointer user_data,
GSourceFunc source_func);
GSource *_g_fd_source_new (int fd,
gushort events,
GCancellable *cancellable);
G_END_DECLS
#endif /* __G_ASYNC_HELPER_H__ */

107
gio/gasyncresult.c Normal file
View File

@ -0,0 +1,107 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gasyncresult.h"
#include "glibintl.h"
static void g_async_result_base_init (gpointer g_class);
static void g_async_result_class_init (gpointer g_class,
gpointer class_data);
GType
g_async_result_get_type (void)
{
static GType async_result_type = 0;
if (! async_result_type)
{
static const GTypeInfo async_result_info =
{
sizeof (GAsyncResultIface), /* class_size */
g_async_result_base_init, /* base_init */
NULL, /* base_finalize */
g_async_result_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
async_result_type =
g_type_register_static (G_TYPE_INTERFACE, I_("GAsyncResult"),
&async_result_info, 0);
g_type_interface_add_prerequisite (async_result_type, G_TYPE_OBJECT);
}
return async_result_type;
}
static void
g_async_result_class_init (gpointer g_class,
gpointer class_data)
{
}
static void
g_async_result_base_init (gpointer g_class)
{
}
/**
* g_async_result_get_user_data:
* @res: a #GAsyncResult.
*
* Returns: the user data for the given @res, or
* %NULL on failure.
**/
gpointer
g_async_result_get_user_data (GAsyncResult *res)
{
GAsyncResultIface *iface;
g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
iface = G_ASYNC_RESULT_GET_IFACE (res);
return (* iface->get_user_data) (res);
}
/**
* g_async_result_get_source_object:
* @res: a #GAsyncResult.
*
* Returns: the source object for the @res.
**/
GObject *
g_async_result_get_source_object (GAsyncResult *res)
{
GAsyncResultIface *iface;
g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
iface = G_ASYNC_RESULT_GET_IFACE (res);
return (* iface->get_source_object) (res);
}

59
gio/gasyncresult.h Normal file
View File

@ -0,0 +1,59 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_ASYNC_RESULT_H__
#define __G_ASYNC_RESULT_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define G_TYPE_ASYNC_RESULT (g_async_result_get_type ())
#define G_ASYNC_RESULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ASYNC_RESULT, GAsyncResult))
#define G_IS_ASYNC_RESULT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ASYNC_RESULT))
#define G_ASYNC_RESULT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ASYNC_RESULT, GAsyncResultIface))
typedef struct _GAsyncResult GAsyncResult; /* Dummy typedef */
typedef struct _GAsyncResultIface GAsyncResultIface;
typedef void (*GAsyncReadyCallback) (GObject *source_object,
GAsyncResult *res,
gpointer user_data);
struct _GAsyncResultIface
{
GTypeInterface g_iface;
/* Virtual Table */
gpointer (*get_user_data) (GAsyncResult *async_result);
GObject * (*get_source_object) (GAsyncResult *async_result);
};
GType g_async_result_get_type (void) G_GNUC_CONST;
gpointer g_async_result_get_user_data (GAsyncResult *res);
GObject *g_async_result_get_source_object (GAsyncResult *res);
G_END_DECLS
#endif /* __G_ASYNC_RESULT_H__ */

1230
gio/gbufferedinputstream.c Normal file

File diff suppressed because it is too large Load Diff

110
gio/gbufferedinputstream.h Normal file
View File

@ -0,0 +1,110 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#ifndef __G_BUFFERED_INPUT_STREAM_H__
#define __G_BUFFERED_INPUT_STREAM_H__
#include <glib-object.h>
#include <gio/gfilterinputstream.h>
G_BEGIN_DECLS
#define G_TYPE_BUFFERED_INPUT_STREAM (g_buffered_input_stream_get_type ())
#define G_BUFFERED_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStream))
#define G_BUFFERED_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStreamClass))
#define G_IS_BUFFERED_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_BUFFERED_INPUT_STREAM))
#define G_IS_BUFFERED_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_BUFFERED_INPUT_STREAM))
#define G_BUFFERED_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_BUFFERED_INPUT_STREAM, GBufferedInputStreamClass))
typedef struct _GBufferedInputStream GBufferedInputStream;
typedef struct _GBufferedInputStreamClass GBufferedInputStreamClass;
typedef struct _GBufferedInputStreamPrivate GBufferedInputStreamPrivate;
struct _GBufferedInputStream
{
GFilterInputStream parent;
/*< private >*/
GBufferedInputStreamPrivate *priv;
};
struct _GBufferedInputStreamClass
{
GFilterInputStreamClass parent_class;
gssize (* fill) (GBufferedInputStream *stream,
gssize count,
GCancellable *cancellable,
GError **error);
/* Async ops: (optional in derived classes) */
void (* fill_async) (GBufferedInputStream *stream,
gssize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize (* fill_finish) (GBufferedInputStream *stream,
GAsyncResult *result,
GError **error);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_buffered_input_stream_get_type (void) G_GNUC_CONST;
GInputStream* g_buffered_input_stream_new (GInputStream *base_stream);
GInputStream* g_buffered_input_stream_new_sized (GInputStream *base_stream,
gsize size);
gsize g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream);
void g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream,
gsize size);
gsize g_buffered_input_stream_get_available (GBufferedInputStream *stream);
gsize g_buffered_input_stream_peek (GBufferedInputStream *stream,
void *buffer,
gsize offset,
gsize count);
gssize g_buffered_input_stream_fill (GBufferedInputStream *stream,
gssize count,
GCancellable *cancellable,
GError **error);
void g_buffered_input_stream_fill_async (GBufferedInputStream *stream,
gssize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize g_buffered_input_stream_fill_finish (GBufferedInputStream *stream,
GAsyncResult *result,
GError **error);
G_END_DECLS
#endif /* __G_BUFFERED_INPUT_STREAM_H__ */

734
gio/gbufferedoutputstream.c Normal file
View File

@ -0,0 +1,734 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#include <config.h>
#include "gbufferedoutputstream.h"
#include "goutputstream.h"
#include "gsimpleasyncresult.h"
#include "string.h"
#include "glibintl.h"
#define DEFAULT_BUFFER_SIZE 4096
struct _GBufferedOutputStreamPrivate {
guint8 *buffer;
gsize len;
goffset pos;
gboolean auto_grow;
};
enum {
PROP_0,
PROP_BUFSIZE
};
static void g_buffered_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_buffered_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void g_buffered_output_stream_finalize (GObject *object);
static gssize g_buffered_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_buffered_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static gboolean g_buffered_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static void g_buffered_output_stream_write_async (GOutputStream *stream,
const void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gssize g_buffered_output_stream_write_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static void g_buffered_output_stream_flush_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gboolean g_buffered_output_stream_flush_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static void g_buffered_output_stream_close_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gboolean g_buffered_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
G_DEFINE_TYPE (GBufferedOutputStream,
g_buffered_output_stream,
G_TYPE_FILTER_OUTPUT_STREAM)
static void
g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass)
{
GObjectClass *object_class;
GOutputStreamClass *ostream_class;
g_type_class_add_private (klass, sizeof (GBufferedOutputStreamPrivate));
object_class = G_OBJECT_CLASS (klass);
object_class->get_property = g_buffered_output_stream_get_property;
object_class->set_property = g_buffered_output_stream_set_property;
object_class->finalize = g_buffered_output_stream_finalize;
ostream_class = G_OUTPUT_STREAM_CLASS (klass);
ostream_class->write = g_buffered_output_stream_write;
ostream_class->flush = g_buffered_output_stream_flush;
ostream_class->close = g_buffered_output_stream_close;
ostream_class->write_async = g_buffered_output_stream_write_async;
ostream_class->write_finish = g_buffered_output_stream_write_finish;
ostream_class->flush_async = g_buffered_output_stream_flush_async;
ostream_class->flush_finish = g_buffered_output_stream_flush_finish;
ostream_class->close_async = g_buffered_output_stream_close_async;
ostream_class->close_finish = g_buffered_output_stream_close_finish;
g_object_class_install_property (object_class,
PROP_BUFSIZE,
g_param_spec_uint ("buffer-size",
P_("Buffer Size"),
P_("The size of the backend buffer"),
1,
G_MAXUINT,
DEFAULT_BUFFER_SIZE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
}
/**
* g_buffered_output_stream_get_buffer_size:
* @stream: a #GBufferedOutputStream.
*
* Returns: the current size of the buffer.
**/
gsize
g_buffered_output_stream_get_buffer_size (GBufferedOutputStream *stream)
{
g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), -1);
return stream->priv->len;
}
/**
* g_buffered_output_stream_set_buffer_size:
* @stream: a #GBufferedOutputStream.
* @size: a #gsize.
*
* Sets the size of the internal buffer to @size.
*
**/
void
g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream,
gsize size)
{
GBufferedOutputStreamPrivate *priv;
guint8 *buffer;
g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream));
priv = stream->priv;
if (priv->buffer)
{
size = MAX (size, priv->pos);
buffer = g_malloc (size);
memcpy (buffer, priv->buffer, priv->pos);
g_free (priv->buffer);
priv->buffer = buffer;
priv->len = size;
/* Keep old pos */
}
else
{
priv->buffer = g_malloc (size);
priv->len = size;
priv->pos = 0;
}
}
/**
* g_buffered_output_stream_get_auto_grow:
* @stream: a #GBufferedOutputStream.
*
* Returns: %TRUE if the @stream's buffer automatically grows,
* %FALSE otherwise.
**/
gboolean
g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream)
{
g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), FALSE);
return stream->priv->auto_grow;
}
/**
* g_buffered_output_stream_set_auto_grow:
* @stream: a #GBufferedOutputStream.
* @auto_grow: a boolean.
*
* Sets whether or not the @stream's buffer should automatically grow.
*
**/
void
g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream,
gboolean auto_grow)
{
g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream));
stream->priv->auto_grow = auto_grow;
}
static void
g_buffered_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GBufferedOutputStream *buffered_stream;
GBufferedOutputStreamPrivate *priv;
buffered_stream = G_BUFFERED_OUTPUT_STREAM (object);
priv = buffered_stream->priv;
switch (prop_id)
{
case PROP_BUFSIZE:
g_buffered_output_stream_set_buffer_size (buffered_stream, g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_buffered_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GBufferedOutputStream *buffered_stream;
GBufferedOutputStreamPrivate *priv;
buffered_stream = G_BUFFERED_OUTPUT_STREAM (object);
priv = buffered_stream->priv;
switch (prop_id)
{
case PROP_BUFSIZE:
g_value_set_uint (value, priv->len);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_buffered_output_stream_finalize (GObject *object)
{
GBufferedOutputStream *stream;
GBufferedOutputStreamPrivate *priv;
stream = G_BUFFERED_OUTPUT_STREAM (object);
priv = stream->priv;
g_free (priv->buffer);
if (G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize)
(*G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize) (object);
}
static void
g_buffered_output_stream_init (GBufferedOutputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_BUFFERED_OUTPUT_STREAM,
GBufferedOutputStreamPrivate);
}
/**
* g_buffered_output_stream_new:
* @base_stream: a #GOutputStream.
*
* Returns: a #GOutputStream for the given @base_stream.
**/
GOutputStream *
g_buffered_output_stream_new (GOutputStream *base_stream)
{
GOutputStream *stream;
g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL);
stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM,
"base-stream", base_stream,
NULL);
return stream;
}
/**
* g_buffered_output_stream_new_sized:
* @base_stream: a #GOutputStream.
* @size: a #gsize.
*
* Returns: a #GOutputStream with an internal buffer set to @size.
**/
GOutputStream *
g_buffered_output_stream_new_sized (GOutputStream *base_stream,
guint size)
{
GOutputStream *stream;
g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL);
stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM,
"base-stream", base_stream,
"buffer-size", size,
NULL);
return stream;
}
static gboolean
flush_buffer (GBufferedOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GBufferedOutputStreamPrivate *priv;
GOutputStream *base_stream;
gboolean res;
gsize bytes_written;
gsize count;
priv = stream->priv;
bytes_written = 0;
base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream;
g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), FALSE);
res = g_output_stream_write_all (base_stream,
priv->buffer,
priv->pos,
&bytes_written,
cancellable,
error);
count = priv->pos - bytes_written;
if (count > 0)
g_memmove (priv->buffer, priv->buffer + bytes_written, count);
priv->pos -= bytes_written;
return res;
}
static gssize
g_buffered_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GBufferedOutputStream *bstream;
GBufferedOutputStreamPrivate *priv;
gboolean res;
gsize n;
gsize new_size;
bstream = G_BUFFERED_OUTPUT_STREAM (stream);
priv = bstream->priv;
n = priv->len - priv->pos;
if (priv->auto_grow && n < count)
{
new_size = MAX (priv->len * 2, priv->len + count);
g_buffered_output_stream_set_buffer_size (bstream, new_size);
}
else if (n == 0)
{
res = flush_buffer (bstream, cancellable, error);
if (res == FALSE)
return -1;
}
n = priv->len - priv->pos;
count = MIN (count, n);
memcpy (priv->buffer + priv->pos, buffer, count);
priv->pos += count;
return count;
}
static gboolean
g_buffered_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GBufferedOutputStream *bstream;
GBufferedOutputStreamPrivate *priv;
GOutputStream *base_stream;
gboolean res;
bstream = G_BUFFERED_OUTPUT_STREAM (stream);
priv = bstream->priv;
base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream;
res = flush_buffer (bstream, cancellable, error);
if (res == FALSE) {
return FALSE;
}
res = g_output_stream_flush (base_stream,
cancellable,
error);
return res;
}
static gboolean
g_buffered_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GBufferedOutputStream *bstream;
GBufferedOutputStreamPrivate *priv;
GOutputStream *base_stream;
gboolean res;
bstream = G_BUFFERED_OUTPUT_STREAM (stream);
priv = bstream->priv;
base_stream = G_FILTER_OUTPUT_STREAM (bstream)->base_stream;
res = flush_buffer (bstream, cancellable, error);
/* report the first error but still close the stream */
if (res)
{
res = g_output_stream_close (base_stream,
cancellable,
error);
}
else
{
g_output_stream_close (base_stream,
cancellable,
NULL);
}
return res;
}
/* ************************** */
/* Async stuff implementation */
/* ************************** */
/* TODO: This should be using the base class async ops, not threads */
typedef struct {
guint flush_stream : 1;
guint close_stream : 1;
} FlushData;
static void
free_flush_data (gpointer data)
{
g_slice_free (FlushData, data);
}
/* This function is used by all three (i.e.
* _write, _flush, _close) functions since
* all of them will need to flush the buffer
* and so closing and writing is just a special
* case of flushing + some addition stuff */
static void
flush_buffer_thread (GSimpleAsyncResult *result,
GObject *object,
GCancellable *cancellable)
{
GBufferedOutputStream *stream;
GOutputStream *base_stream;
FlushData *fdata;
gboolean res;
GError *error = NULL;
stream = G_BUFFERED_OUTPUT_STREAM (object);
fdata = g_simple_async_result_get_op_res_gpointer (result);
base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream;
res = flush_buffer (stream, cancellable, &error);
/* if flushing the buffer didn't work don't even bother
* to flush the stream but just report that error */
if (res && fdata->flush_stream)
{
res = g_output_stream_flush (base_stream,
cancellable,
&error);
}
if (fdata->close_stream)
{
/* if flushing the buffer or the stream returned
* an error report that first error but still try
* close the stream */
if (res == FALSE)
{
g_output_stream_close (base_stream,
cancellable,
NULL);
}
else
{
res = g_output_stream_close (base_stream,
cancellable,
&error);
}
}
if (res == FALSE)
{
g_simple_async_result_set_from_error (result, error);
g_error_free (error);
}
}
typedef struct {
FlushData fdata;
gsize count;
const void *buffer;
} WriteData;
static void
free_write_data (gpointer data)
{
g_slice_free (WriteData, data);
}
static void
g_buffered_output_stream_write_async (GOutputStream *stream,
const void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GBufferedOutputStream *buffered_stream;
GBufferedOutputStreamPrivate *priv;
GSimpleAsyncResult *res;
WriteData *wdata;
buffered_stream = G_BUFFERED_OUTPUT_STREAM (stream);
priv = buffered_stream->priv;
wdata = g_slice_new (WriteData);
wdata->count = count;
wdata->buffer = buffer;
res = g_simple_async_result_new (G_OBJECT (stream),
callback,
data,
g_buffered_output_stream_write_async);
g_simple_async_result_set_op_res_gpointer (res, wdata, free_write_data);
/* if we have space left directly call the
* callback (from idle) otherwise schedule a buffer
* flush in the thread. In both cases the actual
* copying of the data to the buffer will be done in
* the write_finish () func since that should
* be fast enough */
if (priv->len - priv->pos > 0)
{
g_simple_async_result_complete_in_idle (res);
}
else
{
wdata->fdata.flush_stream = FALSE;
wdata->fdata.close_stream = FALSE;
g_simple_async_result_run_in_thread (res,
flush_buffer_thread,
io_priority,
cancellable);
g_object_unref (res);
}
}
static gssize
g_buffered_output_stream_write_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GBufferedOutputStreamPrivate *priv;
GBufferedOutputStream *buffered_stream;
GSimpleAsyncResult *simple;
WriteData *wdata;
gssize count;
simple = G_SIMPLE_ASYNC_RESULT (result);
buffered_stream = G_BUFFERED_OUTPUT_STREAM (stream);
priv = buffered_stream->priv;
g_assert (g_simple_async_result_get_source_tag (simple) ==
g_buffered_output_stream_write_async);
wdata = g_simple_async_result_get_op_res_gpointer (simple);
/* Now do the real copying of data to the buffer */
count = priv->len - priv->pos;
count = MIN (wdata->count, count);
memcpy (priv->buffer + priv->pos, wdata->buffer, count);
priv->pos += count;
return count;
}
static void
g_buffered_output_stream_flush_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GSimpleAsyncResult *res;
FlushData *fdata;
fdata = g_slice_new (FlushData);
fdata->flush_stream = TRUE;
fdata->close_stream = FALSE;
res = g_simple_async_result_new (G_OBJECT (stream),
callback,
data,
g_buffered_output_stream_flush_async);
g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data);
g_simple_async_result_run_in_thread (res,
flush_buffer_thread,
io_priority,
cancellable);
g_object_unref (res);
}
static gboolean
g_buffered_output_stream_flush_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
simple = G_SIMPLE_ASYNC_RESULT (result);
g_assert (g_simple_async_result_get_source_tag (simple) ==
g_buffered_output_stream_flush_async);
return TRUE;
}
static void
g_buffered_output_stream_close_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GSimpleAsyncResult *res;
FlushData *fdata;
fdata = g_slice_new (FlushData);
fdata->close_stream = TRUE;
res = g_simple_async_result_new (G_OBJECT (stream),
callback,
data,
g_buffered_output_stream_close_async);
g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data);
g_simple_async_result_run_in_thread (res,
flush_buffer_thread,
io_priority,
cancellable);
g_object_unref (res);
}
static gboolean
g_buffered_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
simple = G_SIMPLE_ASYNC_RESULT (result);
g_assert (g_simple_async_result_get_source_tag (simple) ==
g_buffered_output_stream_flush_async);
return TRUE;
}
/* vim: ts=2 sw=2 et */

View File

@ -0,0 +1,76 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#ifndef __G_BUFFERED_OUTPUT_STREAM_H__
#define __G_BUFFERED_OUTPUT_STREAM_H__
#include <glib-object.h>
#include <gio/gfilteroutputstream.h>
G_BEGIN_DECLS
#define G_TYPE_BUFFERED_OUTPUT_STREAM (g_buffered_output_stream_get_type ())
#define G_BUFFERED_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStream))
#define G_BUFFERED_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStreamClass))
#define G_IS_BUFFERED_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_BUFFERED_OUTPUT_STREAM))
#define G_IS_BUFFERED_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_BUFFERED_OUTPUT_STREAM))
#define G_BUFFERED_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_BUFFERED_OUTPUT_STREAM, GBufferedOutputStreamClass))
typedef struct _GBufferedOutputStream GBufferedOutputStream;
typedef struct _GBufferedOutputStreamClass GBufferedOutputStreamClass;
typedef struct _GBufferedOutputStreamPrivate GBufferedOutputStreamPrivate;
struct _GBufferedOutputStream
{
GFilterOutputStream parent;
/*< protected >*/
GBufferedOutputStreamPrivate *priv;
};
struct _GBufferedOutputStreamClass
{
GOutputStreamClass parent_class;
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_buffered_output_stream_get_type (void) G_GNUC_CONST;
GOutputStream* g_buffered_output_stream_new (GOutputStream *base_stream);
GOutputStream* g_buffered_output_stream_new_sized (GOutputStream *base_stream,
guint size);
gsize g_buffered_output_stream_get_buffer_size (GBufferedOutputStream *stream);
void g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream,
gsize size);
gboolean g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream);
void g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream,
gboolean auto_grow);
G_END_DECLS
#endif /* __G_BUFFERED_OUTPUT_STREAM_H__ */

322
gio/gcancellable.c Normal file
View File

@ -0,0 +1,322 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <unistd.h>
#include <fcntl.h>
#include <gioerror.h>
#include "gcancellable.h"
#include "glibintl.h"
/*
* GCancellable is a thread-safe operation cancellation stack used
* throughout GIO to allow for cancellation of asynchronous operations.
*/
enum {
CANCELLED,
LAST_SIGNAL
};
struct _GCancellable
{
GObject parent_instance;
guint cancelled : 1;
guint allocated_pipe : 1;
int cancel_pipe[2];
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GCancellable, g_cancellable, G_TYPE_OBJECT);
static GStaticPrivate current_cancellable = G_STATIC_PRIVATE_INIT;
G_LOCK_DEFINE_STATIC(cancellable);
static void
g_cancellable_finalize (GObject *object)
{
GCancellable *cancellable = G_CANCELLABLE (object);
if (cancellable->cancel_pipe[0] != -1)
close (cancellable->cancel_pipe[0]);
if (cancellable->cancel_pipe[1] != -1)
close (cancellable->cancel_pipe[1]);
if (G_OBJECT_CLASS (g_cancellable_parent_class)->finalize)
(*G_OBJECT_CLASS (g_cancellable_parent_class)->finalize) (object);
}
static void
g_cancellable_class_init (GCancellableClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_cancellable_finalize;
signals[CANCELLED] =
g_signal_new (I_("cancelled"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GCancellableClass, cancelled),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
set_fd_nonblocking (int fd)
{
#ifdef F_GETFL
glong fcntl_flags;
fcntl_flags = fcntl (fd, F_GETFL);
#ifdef O_NONBLOCK
fcntl_flags |= O_NONBLOCK;
#else
fcntl_flags |= O_NDELAY;
#endif
fcntl (fd, F_SETFL, fcntl_flags);
#endif
}
static void
g_cancellable_open_pipe (GCancellable *cancellable)
{
if (pipe (cancellable->cancel_pipe) == 0)
{
/* Make them nonblocking, just to be sure we don't block
* on errors and stuff
*/
set_fd_nonblocking (cancellable->cancel_pipe[0]);
set_fd_nonblocking (cancellable->cancel_pipe[1]);
}
else
g_warning ("Failed to create pipe for GCancellable. Out of file descriptors?");
}
static void
g_cancellable_init (GCancellable *cancellable)
{
cancellable->cancel_pipe[0] = -1;
cancellable->cancel_pipe[1] = -1;
}
/**
* g_cancellable_new:
*
* Returns: a new #GCancellable object.
**/
GCancellable *
g_cancellable_new (void)
{
return g_object_new (G_TYPE_CANCELLABLE, NULL);
}
/**
* g_push_current_cancellable:
* @cancellable: optional #GCancellable object, %NULL to ignore.
*
* Pushes @cancellable onto the cancellable stack.
**/
void
g_push_current_cancellable (GCancellable *cancellable)
{
GSList *l;
g_assert (cancellable != NULL);
l = g_static_private_get (&current_cancellable);
l = g_slist_prepend (l, cancellable);
g_static_private_set (&current_cancellable, l, NULL);
}
/**
* g_pop_current_cancellable:
* @cancellable: optional #GCancellable object, %NULL to ignore.
*
* Pops @cancellable off the cancellable stack if @cancellable
* is on the top of the stack.
**/
void
g_pop_current_cancellable (GCancellable *cancellable)
{
GSList *l;
l = g_static_private_get (&current_cancellable);
g_assert (l != NULL);
g_assert (l->data == cancellable);
l = g_slist_delete_link (l, l);
g_static_private_set (&current_cancellable, l, NULL);
}
/**
* g_cancellable_get_current:
*
* Returns: a #GCancellable from the top of the stack, or %NULL
* if the stack is empty.
**/
GCancellable *
g_cancellable_get_current (void)
{
GSList *l;
l = g_static_private_get (&current_cancellable);
if (l == NULL)
return NULL;
return G_CANCELLABLE (l->data);
}
/**
* g_cancellable_reset:
* @cancellable: a #GCancellable object.
*
* Resets @cancellable to its uncancelled state.
*
**/
void
g_cancellable_reset (GCancellable *cancellable)
{
g_return_if_fail (G_IS_CANCELLABLE (cancellable));
G_LOCK(cancellable);
/* Make sure we're not leaving old cancel state around */
if (cancellable->cancelled)
{
char ch;
if (cancellable->cancel_pipe[0] != -1)
read (cancellable->cancel_pipe[0], &ch, 1);
cancellable->cancelled = FALSE;
}
G_UNLOCK(cancellable);
}
/**
* g_cancellable_is_cancelled:
* @cancellable: a #GCancellable or NULL.
*
* Returns: %TRUE if @cancellable is is cancelled,
* FALSE if called with %NULL or if item is not cancelled.
**/
gboolean
g_cancellable_is_cancelled (GCancellable *cancellable)
{
return cancellable != NULL && cancellable->cancelled;
}
/**
* g_cancellable_set_error_if_cancelled:
* @cancellable: a #GCancellable object.
* @error: #GError to append error state to.
*
* Sets the current error to notify that the operation was cancelled.
*
* Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not.
**/
gboolean
g_cancellable_set_error_if_cancelled (GCancellable *cancellable,
GError **error)
{
if (g_cancellable_is_cancelled (cancellable))
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED,
_("Operation was cancelled"));
return TRUE;
}
return FALSE;
}
/**
* g_cancellable_get_fd:
* @cancellable: a #GCancellable.
*
* Returns: A valid file descriptor. -1 if the file descriptor
* is not supported, or on errors.
**/
int
g_cancellable_get_fd (GCancellable *cancellable)
{
int fd;
if (cancellable == NULL)
return -1;
G_LOCK(cancellable);
if (!cancellable->allocated_pipe)
{
cancellable->allocated_pipe = TRUE;
g_cancellable_open_pipe (cancellable);
}
fd = cancellable->cancel_pipe[0];
G_UNLOCK(cancellable);
return fd;
}
/**
* g_cancellable_cancel:
* @cancellable: a #GCancellable object.
*
* Will set @cancellable to cancelled, and will emit the CANCELLED
* signal. This function is thread-safe.
*
**/
void
g_cancellable_cancel (GCancellable *cancellable)
{
gboolean cancel;
cancel = FALSE;
G_LOCK(cancellable);
if (cancellable != NULL &&
!cancellable->cancelled)
{
char ch = 'x';
cancel = TRUE;
cancellable->cancelled = TRUE;
if (cancellable->cancel_pipe[1] != -1)
write (cancellable->cancel_pipe[1], &ch, 1);
}
G_UNLOCK(cancellable);
if (cancel)
{
g_object_ref (cancellable);
g_signal_emit (cancellable, signals[CANCELLED], 0);
g_object_unref (cancellable);
}
}

74
gio/gcancellable.h Normal file
View File

@ -0,0 +1,74 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_CANCELLABLE_H__
#define __G_CANCELLABLE_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define G_TYPE_CANCELLABLE (g_cancellable_get_type ())
#define G_CANCELLABLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CANCELLABLE, GCancellable))
#define G_CANCELLABLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CANCELLABLE, GCancellableClass))
#define G_IS_CANCELLABLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CANCELLABLE))
#define G_IS_CANCELLABLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CANCELLABLE))
#define G_CANCELLABLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CANCELLABLE, GCancellableClass))
typedef struct _GCancellable GCancellable;
typedef struct _GCancellableClass GCancellableClass;
struct _GCancellableClass
{
GObjectClass parent_class;
void (* cancelled) (GCancellable *cancellable);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_cancellable_get_type (void) G_GNUC_CONST;
GCancellable *g_cancellable_new (void);
/* These are only safe to call inside a cancellable op */
gboolean g_cancellable_is_cancelled (GCancellable *cancellable);
gboolean g_cancellable_set_error_if_cancelled (GCancellable *cancellable,
GError **error);
int g_cancellable_get_fd (GCancellable *cancellable);
GCancellable *g_cancellable_get_current (void);
void g_push_current_cancellable (GCancellable *cancellable);
void g_pop_current_cancellable (GCancellable *cancellable);
void g_cancellable_reset (GCancellable *cancellable);
/* This is safe to call from another thread */
void g_cancellable_cancel (GCancellable *cancellable);
G_END_DECLS
#endif /* __G_CANCELLABLE_H__ */

861
gio/gcontenttype.c Normal file
View File

@ -0,0 +1,861 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include "gcontenttypeprivate.h"
#include "glibintl.h"
/* A content type is a platform specific string that defines the type
of a file. On unix it is a mime type, on win32 it is an extension string
like ".doc", ".txt" or a percieved string like "audio". Such strings
can be looked up in the registry at HKEY_CLASSES_ROOT.
*/
#ifdef G_OS_WIN32
#include <windows.h>
static char *
get_registry_classes_key (const char *subdir,
const wchar_t *key_name)
{
wchar_t *wc_key;
HKEY reg_key = NULL;
DWORD key_type;
DWORD nbytes;
char *value_utf8;
value_utf8 = NULL;
nbytes = 0;
wc_key = g_utf8_to_utf16 (subdir, -1, NULL, NULL, NULL);
if (RegOpenKeyExW (HKEY_CLASSES_ROOT, wc_key, 0,
KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS &&
RegQueryValueExW (reg_key, key_name, 0,
&key_type, NULL, &nbytes) == ERROR_SUCCESS &&
key_type == REG_SZ)
{
wchar_t *wc_temp = g_new (wchar_t, (nbytes+1)/2 + 1);
RegQueryValueExW (reg_key, key_name, 0,
&key_type, (LPBYTE) wc_temp, &nbytes);
wc_temp[nbytes/2] = '\0';
value_utf8 = g_utf16_to_utf8 (wc_temp, -1, NULL, NULL, NULL);
g_free (wc_temp);
}
g_free (wc_key);
if (reg_key != NULL)
RegCloseKey (reg_key);
return value_utf8;
}
/**
* g_content_type_equals:
* @type1: a content type string.
* @type2: a content type string.
*
* Compares two content types for equality.
*
* Returns: %TRUE if the two strings are identical or equivalent,
* %FALSE otherwise.
**/
gboolean
g_content_type_equals (const char *type1,
const char *type2)
{
char *progid1, *progid2;
gboolean res;
g_return_val_if_fail (type1 != NULL, FALSE);
g_return_val_if_fail (type2 != NULL, FALSE);
if (g_ascii_strcasecmp (type1, type2) == 0)
return TRUE;
res = FALSE;
progid1 = get_registry_classes_key (type1, NULL);
progid2 = get_registry_classes_key (type2, NULL);
if (progid1 != NULL && progid2 != NULL &&
strcmp (progid1, progid2) == 0)
res = TRUE;
g_free (progid1);
g_free (progid2);
return res;
}
/**
* g_content_type_is_a:
* @type: a content type string. a content type string.
* @supertype: a string.
*
* Determines if @type is a subset of @supertype.
*
* Returns: %TRUE if @type is a kind of @supertype,
* %FALSE otherwise.
**/
gboolean
g_content_type_is_a (const char *type,
const char *supertype)
{
gboolean res;
char *value_utf8;
g_return_val_if_fail (type != NULL, FALSE);
g_return_val_if_fail (supertype != NULL, FALSE);
if (g_content_type_equals (type, supertype))
return TRUE;
res = FALSE;
value_utf8 = get_registry_classes_key (type, L"PerceivedType");
if (value_utf8 && strcmp (value_utf8, supertype) == 0)
res = TRUE;
g_free (value_utf8);
return res;
}
/**
* g_content_type_is_unknown:
* @type: a content type string. a content type string.
*
* Returns:
**/
gboolean
g_content_type_is_unknown (const char *type)
{
g_return_val_if_fail (type != NULL, FALSE);
return strcmp ("*", type) == 0;
}
/**
* g_content_type_get_description:
* @type: a content type string. a content type string.
*
* Returns: a short description of the content type @type.
**/
char *
g_content_type_get_description (const char *type)
{
char *progid;
char *description;
g_return_val_if_fail (type != NULL, NULL);
progid = get_registry_classes_key (type, NULL);
if (progid)
{
description = get_registry_classes_key (progid, NULL);
g_free (progid);
if (description)
return description;
}
if (g_content_type_is_unknown (type))
return g_strdup (_("Unknown type"));
return g_strdup_printf (_("%s filetype"), type);
}
/**
* g_content_type_get_mime_type:
* @type: a content type string. a content type string.
*
* Returns: the registered mime-type for the given @type.
**/
char *
g_content_type_get_mime_type (const char *type)
{
char *mime;
g_return_val_if_fail (type != NULL, NULL);
mime = get_registry_classes_key (type, L"Content Type");
if (mime)
return mime;
else if (g_content_type_is_unknown (type))
return g_strdup ("application/octet-stream");
else if (*type == '.')
return g_strdup_printf ("application/x-ext-%s", type+1);
/* TODO: Map "image" to "image/ *", etc? */
return g_strdup ("application/octet-stream");
}
/**
* g_content_type_get_icon:
* @type: a content type string. a content type string.
*
* Returns: #GIcon corresponding to the content type.
**/
GIcon *
g_content_type_get_icon (const char *type)
{
g_return_val_if_fail (type != NULL, NULL);
/* TODO: How do we represent icons???
In the registry they are the default value of
HKEY_CLASSES_ROOT\<progid>\DefaultIcon with typical values like:
<type>: <value>
REG_EXPAND_SZ: %SystemRoot%\System32\Wscript.exe,3
REG_SZ: shimgvw.dll,3
*/
return NULL;
}
/**
* g_content_type_can_be_executable:
* @type: a content type string.
*
* Returns: %TRUE if the file type corresponds to something that
* can be executable, %FALSE otherwise. Note that for instance
* things like textfiles can be executables (i.e. scripts)
**/
gboolean
g_content_type_can_be_executable (const char *type)
{
g_return_val_if_fail (type != NULL, FALSE);
if (strcmp (type, ".exe") == 0 ||
strcmp (type, ".com") == 0 ||
strcmp (type, ".bat") == 0)
return TRUE;
return FALSE;
}
static gboolean
looks_like_text (const guchar *data, gsize data_size)
{
gsize i;
guchar c;
for (i = 0; i < data_size; i++)
{
c = data[i];
if (g_ascii_iscntrl (c) && !g_ascii_isspace (c))
return FALSE;
}
return TRUE;
}
/**
* g_content_type_guess:
* @filename: a string.
* @data: a stream of data.
* @data_size: the size of @data.
* @result_uncertain: a flag indicating the certainty of the
* result.
*
* Returns: a string indicating a guessed content type for the
* given data. If the function is uncertain, @result_uncertain
* will be set to %TRUE.
**/
char *
g_content_type_guess (const char *filename,
const guchar *data,
gsize data_size,
gboolean *result_uncertain)
{
char *basename;
char *type;
char *dot;
type = NULL;
if (filename)
{
basename = g_path_get_basename (filename);
dot = strrchr (basename, '.');
if (dot)
type = g_strdup (dot);
g_free (basename);
}
if (type)
return type;
if (data && looks_like_text (data, data_size))
return g_strdup (".txt");
return g_strdup ("*");
}
/**
* g_content_types_get_registered:
*
* Returns: #GList of the registered content types.
**/
GList *
g_content_types_get_registered (void)
{
DWORD index;
wchar_t keyname[256];
DWORD key_len;
char *key_utf8;
GList *types;
types = NULL;
index = 0;
key_len = 256;
while (RegEnumKeyExW(HKEY_CLASSES_ROOT,
index,
keyname,
&key_len,
NULL,
NULL,
NULL,
NULL) == ERROR_SUCCESS)
{
key_utf8 = g_utf16_to_utf8 (keyname, -1, NULL, NULL, NULL);
if (key_utf8)
{
if (*key_utf8 == '.')
types = g_list_prepend (types, key_utf8);
else
g_free (key_utf8);
}
index++;
key_len = 256;
}
return g_list_reverse (types);
}
#else /* !G_OS_WIN32 - Unix specific version */
#define XDG_PREFIX _gio_xdg
#include "xdgmime/xdgmime.h"
/* We lock this mutex whenever we modify global state in this module. */
G_LOCK_DEFINE_STATIC (gio_xdgmime);
gsize
_g_unix_content_type_get_sniff_len (void)
{
gsize size;
G_LOCK (gio_xdgmime);
size = xdg_mime_get_max_buffer_extents ();
G_UNLOCK (gio_xdgmime);
return size;
}
char *
_g_unix_content_type_unalias (const char *type)
{
char *res;
G_LOCK (gio_xdgmime);
res = g_strdup (xdg_mime_unalias_mime_type (type));
G_UNLOCK (gio_xdgmime);
return res;
}
char **
_g_unix_content_type_get_parents (const char *type)
{
const char *umime;
const char **parents;
GPtrArray *array;
int i;
array = g_ptr_array_new ();
G_LOCK (gio_xdgmime);
umime = xdg_mime_unalias_mime_type (type);
g_ptr_array_add (array, g_strdup (umime));
parents = xdg_mime_get_mime_parents (umime);
for (i = 0; parents && parents[i] != NULL; i++)
g_ptr_array_add (array, g_strdup (parents[i]));
G_UNLOCK (gio_xdgmime);
g_ptr_array_add (array, NULL);
return (char **)g_ptr_array_free (array, FALSE);
}
gboolean
g_content_type_equals (const char *type1,
const char *type2)
{
gboolean res;
g_return_val_if_fail (type1 != NULL, FALSE);
g_return_val_if_fail (type2 != NULL, FALSE);
G_LOCK (gio_xdgmime);
res = xdg_mime_mime_type_equal (type1, type2);
G_UNLOCK (gio_xdgmime);
return res;
}
gboolean
g_content_type_is_a (const char *type,
const char *supertype)
{
gboolean res;
g_return_val_if_fail (type != NULL, FALSE);
g_return_val_if_fail (supertype != NULL, FALSE);
G_LOCK (gio_xdgmime);
res = xdg_mime_mime_type_subclass (type, supertype);
G_UNLOCK (gio_xdgmime);
return res;
}
gboolean
g_content_type_is_unknown (const char *type)
{
g_return_val_if_fail (type != NULL, FALSE);
return strcmp (XDG_MIME_TYPE_UNKNOWN, type) == 0;
}
typedef enum {
MIME_TAG_TYPE_OTHER,
MIME_TAG_TYPE_COMMENT
} MimeTagType;
typedef struct {
int current_type;
int current_lang_level;
int comment_lang_level;
char *comment;
} MimeParser;
static int
language_level (const char *lang)
{
const char * const *lang_list;
int i;
/* The returned list is sorted from most desirable to least
desirable and always contains the default locale "C". */
lang_list = g_get_language_names ();
for (i = 0; lang_list[i]; i++)
if (strcmp (lang_list[i], lang) == 0)
return 1000-i;
return 0;
}
static void
mime_info_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error)
{
int i;
const char *lang;
MimeParser *parser = user_data;
if (strcmp (element_name, "comment") == 0)
{
lang = "C";
for (i = 0; attribute_names[i]; i++)
if (strcmp (attribute_names[i], "xml:lang") == 0)
{
lang = attribute_values[i];
break;
}
parser->current_lang_level = language_level (lang);
parser->current_type = MIME_TAG_TYPE_COMMENT;
}
else
parser->current_type = MIME_TAG_TYPE_OTHER;
}
static void
mime_info_end_element (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error)
{
MimeParser *parser = user_data;
parser->current_type = MIME_TAG_TYPE_OTHER;
}
static void
mime_info_text (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error)
{
MimeParser *parser = user_data;
if (parser->current_type == MIME_TAG_TYPE_COMMENT &&
parser->current_lang_level > parser->comment_lang_level)
{
g_free (parser->comment);
parser->comment = g_strndup (text, text_len);
parser->comment_lang_level = parser->current_lang_level;
}
}
static char *
load_comment_for_mime_helper (const char *dir, const char *basename)
{
GMarkupParseContext *context;
char *filename, *data;
gsize len;
gboolean res;
MimeParser parse_data = {0};
GMarkupParser parser = {
mime_info_start_element,
mime_info_end_element,
mime_info_text
};
filename = g_build_filename (dir, "mime", basename, NULL);
res = g_file_get_contents (filename, &data, &len, NULL);
g_free (filename);
if (!res)
return NULL;
context = g_markup_parse_context_new (&parser, 0, &parse_data, NULL);
res = g_markup_parse_context_parse (context, data, len, NULL);
g_free (data);
g_markup_parse_context_free (context);
if (!res)
return NULL;
return parse_data.comment;
}
static char *
load_comment_for_mime (const char *mimetype)
{
const char * const* dirs;
char *basename;
char *comment;
int i;
basename = g_strdup_printf ("%s.xml", mimetype);
comment = load_comment_for_mime_helper (g_get_user_data_dir (), basename);
if (comment)
{
g_free (basename);
return comment;
}
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i] != NULL; i++)
{
comment = load_comment_for_mime_helper (dirs[i], basename);
if (comment)
{
g_free (basename);
return comment;
}
}
g_free (basename);
return g_strdup_printf (_("%s type"), mimetype);
}
char *
g_content_type_get_description (const char *type)
{
static GHashTable *type_comment_cache = NULL;
char *comment;
g_return_val_if_fail (type != NULL, NULL);
G_LOCK (gio_xdgmime);
if (type_comment_cache == NULL)
type_comment_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
comment = g_hash_table_lookup (type_comment_cache, type);
comment = g_strdup (comment);
G_UNLOCK (gio_xdgmime);
if (comment != NULL)
return comment;
comment = load_comment_for_mime (type);
G_LOCK (gio_xdgmime);
g_hash_table_insert (type_comment_cache,
g_strdup (type),
g_strdup (comment));
G_UNLOCK (gio_xdgmime);
return comment;
}
char *
g_content_type_get_mime_type (const char *type)
{
g_return_val_if_fail (type != NULL, NULL);
return g_strdup (type);
}
GIcon *
g_content_type_get_icon (const char *type)
{
g_return_val_if_fail (type != NULL, NULL);
/* TODO: Implement */
return NULL;
}
/**
* g_content_type_can_be_executable:
* @type: a content type string.
*
* Returns: %TRUE if the file type corresponds to something that
* can be executable, %FALSE otherwise. Note that for instance
* things like textfiles can be executables (i.e. scripts)
**/
gboolean
g_content_type_can_be_executable (const char *type)
{
g_return_val_if_fail (type != NULL, FALSE);
if (g_content_type_is_a (type, "application/x-executable") ||
g_content_type_is_a (type, "text/plain"))
return TRUE;
return FALSE;
}
static gboolean
looks_like_text (const guchar *data, gsize data_size)
{
gsize i;
for (i = 0; i < data_size; i++)
{
if g_ascii_iscntrl (data[i])
return FALSE;
}
return TRUE;
}
char *
g_content_type_guess (const char *filename,
const guchar *data,
gsize data_size,
gboolean *result_uncertain)
{
char *basename;
const char *name_mimetypes[10], *sniffed_mimetype;
char *mimetype;
int i;
int n_name_mimetypes;
int sniffed_prio;
sniffed_prio = 0;
n_name_mimetypes = 0;
sniffed_mimetype = XDG_MIME_TYPE_UNKNOWN;
if (result_uncertain)
*result_uncertain = FALSE;
G_LOCK (gio_xdgmime);
if (filename)
{
basename = g_path_get_basename (filename);
n_name_mimetypes = xdg_mime_get_mime_types_from_file_name (basename, name_mimetypes, 10);
g_free (basename);
}
/* Got an extension match, and no conflicts. This is it. */
if (n_name_mimetypes == 1)
{
G_UNLOCK (gio_xdgmime);
return g_strdup (name_mimetypes[0]);
}
if (data)
{
sniffed_mimetype = xdg_mime_get_mime_type_for_data (data, data_size, &sniffed_prio);
if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN &&
data &&
looks_like_text (data, data_size))
sniffed_mimetype = "text/plain";
}
if (n_name_mimetypes == 0)
{
if (sniffed_mimetype == XDG_MIME_TYPE_UNKNOWN &&
result_uncertain)
*result_uncertain = TRUE;
mimetype = g_strdup (sniffed_mimetype);
}
else
{
mimetype = NULL;
if (sniffed_mimetype != XDG_MIME_TYPE_UNKNOWN)
{
if (sniffed_prio >= 80) /* High priority sniffing match, use that */
mimetype = g_strdup (sniffed_mimetype);
else
{
/* There are conflicts between the name matches and we have a sniffed
type, use that as a tie breaker. */
for (i = 0; i < n_name_mimetypes; i++)
{
if ( xdg_mime_mime_type_subclass (name_mimetypes[i], sniffed_mimetype))
{
/* This nametype match is derived from (or the same as) the sniffed type).
This is probably it. */
mimetype = g_strdup (name_mimetypes[i]);
break;
}
}
}
}
if (mimetype == NULL)
{
/* Conflicts, and sniffed type was no help or not there. guess on the first one */
mimetype = g_strdup (name_mimetypes[0]);
if (result_uncertain)
*result_uncertain = TRUE;
}
}
G_UNLOCK (gio_xdgmime);
return mimetype;
}
static gboolean
foreach_mimetype (gpointer key,
gpointer value,
gpointer user_data)
{
GList **l = user_data;
*l = g_list_prepend (*l, (char *)key);
return TRUE;
}
static void
enumerate_mimetypes_subdir (const char *dir, const char *prefix, GHashTable *mimetypes)
{
DIR *d;
struct dirent *ent;
char *mimetype;
d = opendir (dir);
if (d)
{
while ((ent = readdir (d)) != NULL)
{
if (g_str_has_suffix (ent->d_name, ".xml"))
{
mimetype = g_strdup_printf ("%s/%.*s", prefix, (int) strlen (ent->d_name) - 4, ent->d_name);
g_hash_table_insert (mimetypes, mimetype, NULL);
}
}
closedir (d);
}
}
static void
enumerate_mimetypes_dir (const char *dir, GHashTable *mimetypes)
{
DIR *d;
struct dirent *ent;
char *mimedir;
char *name;
mimedir = g_build_filename (dir, "mime", NULL);
d = opendir (mimedir);
if (d)
{
while ((ent = readdir (d)) != NULL)
{
if (strcmp (ent->d_name, "packages") != 0)
{
name = g_build_filename (mimedir, ent->d_name, NULL);
if (g_file_test (name, G_FILE_TEST_IS_DIR))
enumerate_mimetypes_subdir (name, ent->d_name, mimetypes);
g_free (name);
}
}
closedir (d);
}
g_free (mimedir);
}
GList *
g_content_types_get_registered (void)
{
const char * const* dirs;
GHashTable *mimetypes;
int i;
GList *l;
mimetypes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
enumerate_mimetypes_dir (g_get_user_data_dir (), mimetypes);
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i] != NULL; i++)
enumerate_mimetypes_dir (dirs[i], mimetypes);
l = NULL;
g_hash_table_foreach_steal (mimetypes, foreach_mimetype, &l);
g_hash_table_destroy (mimetypes);
return l;
}
#endif /* Unix version */

50
gio/gcontenttype.h Normal file
View File

@ -0,0 +1,50 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_CONTENT_TYPE_H__
#define __G_CONTENT_TYPE_H__
#include <glib.h>
#include <gio/gicon.h>
G_BEGIN_DECLS
gboolean g_content_type_equals (const char *type1,
const char *type2);
gboolean g_content_type_is_a (const char *type,
const char *supertype);
gboolean g_content_type_is_unknown (const char *type);
char * g_content_type_get_description (const char *type);
char * g_content_type_get_mime_type (const char *type);
GIcon * g_content_type_get_icon (const char *type);
gboolean g_content_type_can_be_executable (const char *type);
char * g_content_type_guess (const char *filename,
const guchar *data,
gsize data_size,
gboolean *result_uncertain );
GList * g_content_types_get_registered (void);
G_END_DECLS
#endif /* __G_CONTENT_TYPE_H__ */

36
gio/gcontenttypeprivate.h Normal file
View File

@ -0,0 +1,36 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_CONTENT_TYPE_PRIVATE_H__
#define __G_CONTENT_TYPE_PRIVATE_H__
#include "gcontenttype.h"
G_BEGIN_DECLS
gsize _g_unix_content_type_get_sniff_len (void);
char * _g_unix_content_type_unalias (const char *type);
char **_g_unix_content_type_get_parents (const char *type);
G_END_DECLS
#endif /* __G_CONTENT_TYPE_PRIVATE_H__ */

718
gio/gdatainputstream.c Normal file
View File

@ -0,0 +1,718 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gdatainputstream.h"
#include "glibintl.h"
struct _GDataInputStreamPrivate {
GDataStreamByteOrder byte_order;
GDataStreamNewlineType newline_type;
};
enum {
PROP_0
};
static void g_data_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_data_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GDataInputStream,
g_data_input_stream,
G_TYPE_BUFFERED_INPUT_STREAM)
static void
g_data_input_stream_class_init (GDataInputStreamClass *klass)
{
GObjectClass *object_class;
g_type_class_add_private (klass, sizeof (GDataInputStreamPrivate));
object_class = G_OBJECT_CLASS (klass);
object_class->get_property = g_data_input_stream_get_property;
object_class->set_property = g_data_input_stream_set_property;
}
static void
g_data_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GDataInputStreamPrivate *priv;
GDataInputStream *dstream;
dstream = G_DATA_INPUT_STREAM (object);
priv = dstream->priv;
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_data_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GDataInputStreamPrivate *priv;
GDataInputStream *dstream;
dstream = G_DATA_INPUT_STREAM (object);
priv = dstream->priv;
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_data_input_stream_init (GDataInputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_DATA_INPUT_STREAM,
GDataInputStreamPrivate);
stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF;
}
/**
* g_data_input_stream_new:
* @base_stream: a given #GInputStream.
*
* Returns: a new #GDataInputStream.
**/
GDataInputStream *
g_data_input_stream_new (GInputStream *base_stream)
{
GDataInputStream *stream;
g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
stream = g_object_new (G_TYPE_DATA_INPUT_STREAM,
"base-stream", base_stream,
NULL);
return stream;
}
/**
* g_data_input_stream_set_byte_order:
* @stream: a given #GDataInputStream.
* @order: a #GDataStreamByteOrder to set.
*
* This function sets the byte order for the given @stream. All subsequent
* reads from the @stream will be read in the given @order.
*
**/
void
g_data_input_stream_set_byte_order (GDataInputStream *stream,
GDataStreamByteOrder order)
{
g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
stream->priv->byte_order = order;
}
/**
* g_data_input_stream_get_byte_order:
* @stream: a given #GDataInputStream.
*
* Returns the @stream's current #GDataStreamByteOrder.
**/
GDataStreamByteOrder
g_data_input_stream_get_byte_order (GDataInputStream *stream)
{
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
return stream->priv->byte_order;
}
/**
* g_data_input_stream_set_newline_type:
* @stream: a given #GDataInputStream.
* @type: the type of new line return as #GDataStreamNewlineType.
*
* Sets the newline type for the @stream.
*
* TODO: is it valid to set this to G_DATA_STREAM_NEWLINE_TYPE_ANY, or
* should it always be set to {_LF, _CR, _CR_LF}
*
**/
void
g_data_input_stream_set_newline_type (GDataInputStream *stream,
GDataStreamNewlineType type)
{
g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
stream->priv->newline_type = type;
}
/**
* g_data_input_stream_get_newline_type:
* @stream: a given #GDataInputStream.
*
* Gets the current newline type for the @stream.
*
* Returns: #GDataStreamNewlineType for the given @stream.
**/
GDataStreamNewlineType
g_data_input_stream_get_newline_type (GDataInputStream *stream)
{
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY);
return stream->priv->newline_type;
}
static gboolean
read_data (GDataInputStream *stream,
void *buffer,
gsize size,
GCancellable *cancellable,
GError **error)
{
gsize available;
gssize res;
while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size)
{
res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream),
size - available,
cancellable, error);
if (res < 0)
return FALSE;
if (res == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Unexpected early end-of-stream"));
return FALSE;
}
}
/* This should always succeed, since its in the buffer */
res = g_input_stream_read (G_INPUT_STREAM (stream),
buffer, size,
NULL, NULL);
g_assert (res == size);
return TRUE;
}
/**
* g_data_input_stream_read_byte:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns: an unsigned 8-bit/1-byte value read from the @stream or %0
* if an error occured.
**/
guchar
g_data_input_stream_read_byte (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
guchar c;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0');
if (read_data (stream, &c, 1, cancellable, error))
return c;
return 0;
}
/**
* g_data_input_stream_read_int16:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns a signed 16-bit/2-byte value read from @stream or %0 if
* an error occured.
**/
gint16
g_data_input_stream_read_int16 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
gint16 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 2, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GINT16_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GINT16_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
/**
* g_data_input_stream_read_uint16:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns an unsigned 16-bit/2-byte value read from the @stream or %0 if
* an error occured.
**/
guint16
g_data_input_stream_read_uint16 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
guint16 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 2, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GUINT16_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GUINT16_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
/**
* g_data_input_stream_read_int32:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns a signed 32-bit/4-byte value read from the @stream or %0 if
* an error occured.
**/
gint32
g_data_input_stream_read_int32 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
gint32 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 4, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GINT32_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GINT32_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
/**
* g_data_input_stream_read_uint32:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns an unsigned 32-bit/4-byte value read from the @stream or %0 if
* an error occured.
**/
guint32
g_data_input_stream_read_uint32 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
guint32 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 4, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GUINT32_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GUINT32_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
/**
* g_data_input_stream_read_int64:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
*
* Returns a signed 64-bit/8-byte value read from @stream or %0 if
* an error occured.
**/
gint64
g_data_input_stream_read_int64 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
gint64 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 8, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GINT64_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GINT64_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
/**
* g_data_input_stream_read_uint64:
* @stream: a given #GDataInputStream.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* In order to get the correct byte order for this read operation,
* see g_data_stream_get_byte_order().
*
* Returns an unsigned 64-bit/8-byte read from @stream or %0 if
* an error occured.
**/
guint64
g_data_input_stream_read_uint64 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error)
{
guint64 v;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
if (read_data (stream, &v, 8, cancellable, error))
{
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
v = GUINT64_FROM_BE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
v = GUINT64_FROM_LE (v);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return v;
}
return 0;
}
static gssize
scan_for_newline (GDataInputStream *stream,
gsize *checked_out,
gboolean *last_saw_cr_out,
int *newline_len_out)
{
GBufferedInputStream *bstream;
GDataInputStreamPrivate *priv;
char buffer[100];
gsize start, end, peeked;
int i;
gssize found_pos;
int newline_len;
gsize available, checked;
gboolean last_saw_cr;
priv = stream->priv;
bstream = G_BUFFERED_INPUT_STREAM (stream);
available = g_buffered_input_stream_get_available (bstream);
checked = *checked_out;
last_saw_cr = *last_saw_cr_out;
found_pos = -1;
newline_len = 0;
while (checked < available)
{
start = checked;
end = MIN (start + sizeof(buffer), available);
peeked = g_buffered_input_stream_peek (bstream, buffer, start, end - start);
end = start + peeked;
for (i = 0; i < peeked; i++)
{
switch (priv->newline_type)
{
case G_DATA_STREAM_NEWLINE_TYPE_LF:
if (buffer[i] == 10)
{
found_pos = start + i;
newline_len = 1;
}
break;
case G_DATA_STREAM_NEWLINE_TYPE_CR:
if (buffer[i] == 13)
{
found_pos = start + i;
newline_len = 1;
}
break;
case G_DATA_STREAM_NEWLINE_TYPE_CR_LF:
if (last_saw_cr && buffer[i] == 10)
{
found_pos = start + i - 1;
newline_len = 2;
}
break;
default:
case G_DATA_STREAM_NEWLINE_TYPE_ANY:
if (buffer[i] == 10) /* LF */
{
if (last_saw_cr)
{
/* CR LF */
found_pos = start + i - 1;
newline_len = 2;
}
else
{
/* LF */
found_pos = start + i;
newline_len = 1;
}
}
else if (last_saw_cr)
{
/* Last was cr, this is not LF, end is CR */
found_pos = start + i - 1;
newline_len = 1;
}
/* Don't check for CR here, instead look at last_saw_cr on next byte */
break;
}
last_saw_cr = (buffer[i] == 13);
if (found_pos != -1)
{
*newline_len_out = newline_len;
return found_pos;
}
}
checked = end;
}
*checked_out = checked;
*last_saw_cr_out = last_saw_cr;
return -1;
}
/**
* g_data_input_stream_read_line:
* @stream: a given #GDataInputStream.
* @length: a #gsize to get the length of the data read in.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* Returns a string with the line that was read in. Set @length to
* a #gsize to get the length of the read line. This function will
* return %NULL on an error.
**/
char *
g_data_input_stream_read_line (GDataInputStream *stream,
gsize *length,
GCancellable *cancellable,
GError **error)
{
GBufferedInputStream *bstream;
gsize checked;
gboolean last_saw_cr;
gssize found_pos;
gssize res;
int newline_len;
char *line;
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
bstream = G_BUFFERED_INPUT_STREAM (stream);
newline_len = 0;
checked = 0;
last_saw_cr = FALSE;
while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1)
{
if (g_buffered_input_stream_get_available (bstream) ==
g_buffered_input_stream_get_buffer_size (bstream))
g_buffered_input_stream_set_buffer_size (bstream,
2 * g_buffered_input_stream_get_buffer_size (bstream));
res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
if (res < 0)
return NULL;
if (res == 0)
{
/* End of stream */
if (g_buffered_input_stream_get_available (bstream) == 0)
{
if (length)
*length = 0;
return NULL;
}
else
{
found_pos = checked;
newline_len = 0;
break;
}
}
}
line = g_malloc (found_pos + newline_len + 1);
res = g_input_stream_read (G_INPUT_STREAM (stream),
line,
found_pos + newline_len,
NULL, NULL);
if (length)
*length = (gsize)found_pos;
g_assert (res == found_pos + newline_len);
line[found_pos] = 0;
return line;
}
/**
* g_data_input_stream_read_until:
* @stream: a given #GDataInputStream.
* @stop_char: character to terminate the read.
* @length: a #gsize to get the length of the data read in.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: #GError for error reporting.
*
* NOTE: not supported for #GDataInputStream.
* Returns %NULL.
**/
char *
g_data_input_stream_read_until (GDataInputStream *stream,
gchar stop_char,
gsize *length,
GCancellable *cancellable,
GError **error)
{
/* TODO: should be implemented */
g_assert_not_reached ();
return NULL;
}

117
gio/gdatainputstream.h Normal file
View File

@ -0,0 +1,117 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DATA_INPUT_STREAM_H__
#define __G_DATA_INPUT_STREAM_H__
#include <glib-object.h>
#include <gio/gbufferedinputstream.h>
G_BEGIN_DECLS
#define G_TYPE_DATA_INPUT_STREAM (g_data_input_stream_get_type ())
#define G_DATA_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DATA_INPUT_STREAM, GDataInputStream))
#define G_DATA_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DATA_INPUT_STREAM, GDataInputStreamClass))
#define G_IS_DATA_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DATA_INPUT_STREAM))
#define G_IS_DATA_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DATA_INPUT_STREAM))
#define G_DATA_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DATA_INPUT_STREAM, GDataInputStreamClass))
typedef struct _GDataInputStream GDataInputStream;
typedef struct _GDataInputStreamClass GDataInputStreamClass;
typedef struct _GDataInputStreamPrivate GDataInputStreamPrivate;
struct _GDataInputStream
{
GBufferedInputStream parent;
/*< private >*/
GDataInputStreamPrivate *priv;
};
struct _GDataInputStreamClass
{
GBufferedInputStreamClass parent_class;
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
typedef enum {
G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN,
G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN,
G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN
} GDataStreamByteOrder;
typedef enum {
G_DATA_STREAM_NEWLINE_TYPE_LF,
G_DATA_STREAM_NEWLINE_TYPE_CR,
G_DATA_STREAM_NEWLINE_TYPE_CR_LF,
G_DATA_STREAM_NEWLINE_TYPE_ANY
} GDataStreamNewlineType;
GType g_data_input_stream_get_type (void) G_GNUC_CONST;
GDataInputStream* g_data_input_stream_new (GInputStream *base_stream);
void g_data_input_stream_set_byte_order (GDataInputStream *stream,
GDataStreamByteOrder order);
GDataStreamByteOrder g_data_input_stream_get_byte_order (GDataInputStream *stream);
void g_data_input_stream_set_newline_type (GDataInputStream *data_stream,
GDataStreamNewlineType type);
GDataStreamNewlineType g_data_input_stream_get_newline_type (GDataInputStream *stream);
guchar g_data_input_stream_read_byte (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
gint16 g_data_input_stream_read_int16 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
guint16 g_data_input_stream_read_uint16 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
gint32 g_data_input_stream_read_int32 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
guint32 g_data_input_stream_read_uint32 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
gint64 g_data_input_stream_read_int64 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
guint64 g_data_input_stream_read_uint64 (GDataInputStream *stream,
GCancellable *cancellable,
GError **error);
char * g_data_input_stream_read_line (GDataInputStream *stream,
gsize *length,
GCancellable *cancellable,
GError **error);
char * g_data_input_stream_read_until (GDataInputStream *stream,
gchar stop_char,
gsize *length,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_DATA_INPUT_STREAM_H__ */

441
gio/gdataoutputstream.c Normal file
View File

@ -0,0 +1,441 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <string.h>
#include "gdataoutputstream.h"
#include "glibintl.h"
struct _GDataOutputStreamPrivate {
GDataStreamByteOrder byte_order;
};
enum {
PROP_0
};
static void g_data_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_data_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GDataOutputStream,
g_data_output_stream,
G_TYPE_FILTER_OUTPUT_STREAM)
static void
g_data_output_stream_class_init (GDataOutputStreamClass *klass)
{
GObjectClass *object_class;
g_type_class_add_private (klass, sizeof (GDataOutputStreamPrivate));
object_class = G_OBJECT_CLASS (klass);
object_class->get_property = g_data_output_stream_get_property;
object_class->set_property = g_data_output_stream_set_property;
}
static void
g_data_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GDataOutputStreamPrivate *priv;
GDataOutputStream *dstream;
dstream = G_DATA_OUTPUT_STREAM (object);
priv = dstream->priv;
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_data_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GDataOutputStreamPrivate *priv;
GDataOutputStream *dstream;
dstream = G_DATA_OUTPUT_STREAM (object);
priv = dstream->priv;
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_data_output_stream_init (GDataOutputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_DATA_OUTPUT_STREAM,
GDataOutputStreamPrivate);
stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
}
/**
* g_data_output_stream_new:
* @base_stream: a #GOutputStream.
*
* Returns: #GDataOutputStream.
**/
GDataOutputStream *
g_data_output_stream_new (GOutputStream *base_stream)
{
GDataOutputStream *stream;
g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL);
stream = g_object_new (G_TYPE_DATA_OUTPUT_STREAM,
"base-stream", base_stream,
NULL);
return stream;
}
/**
* g_data_output_stream_set_byte_order:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @order: a %GDataStreamByteOrder.
*
**/
void
g_data_output_stream_set_byte_order (GDataOutputStream *stream,
GDataStreamByteOrder order)
{
g_return_if_fail (G_IS_DATA_OUTPUT_STREAM (stream));
stream->priv->byte_order = order;
}
/**
* g_data_output_stream_get_byte_order:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
*
* Returns: the %GDataStreamByteOrder for the @stream.
**/
GDataStreamByteOrder
g_data_output_stream_get_byte_order (GDataOutputStream *stream)
{
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
return stream->priv->byte_order;
}
/**
* g_data_output_stream_put_byte:
* @data_stream: a #GDataOutputStream.
* @data: a #guchar.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_byte (GDataOutputStream *data_stream,
guchar data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (data_stream), FALSE);
return g_output_stream_write_all (G_OUTPUT_STREAM (data_stream),
&data, 1,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_int16:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #gint16.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_int16 (GDataOutputStream *stream,
gint16 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GINT16_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GINT16_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 2,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_uint16:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #guint16.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_uint16 (GDataOutputStream *stream,
guint16 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GUINT16_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GUINT16_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 2,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_int32:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #gint32.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_int32 (GDataOutputStream *stream,
gint32 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GINT32_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GINT32_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 4,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_uint32:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #guint32.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_uint32 (GDataOutputStream *stream,
guint32 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GUINT32_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GUINT32_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 4,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_int64:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #gint64.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_int64 (GDataOutputStream *stream,
gint64 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GINT64_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GINT64_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 8,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_uint64:
* @stream: a #GDataOutputStream. a #GDataOutputStream.
* @data: a #guint64.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_uint64 (GDataOutputStream *stream,
guint64 data,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
switch (stream->priv->byte_order)
{
case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
data = GUINT64_TO_BE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
data = GUINT64_TO_LE (data);
break;
case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
default:
break;
}
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
&data, 8,
&bytes_written,
cancellable, error);
}
/**
* g_data_output_stream_put_string:
* @stream: a #GDataOutputStream.
* @str: a string.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError.
*
* Returns: %TRUE if @data was successfully added to the @stream.
**/
gboolean
g_data_output_stream_put_string (GDataOutputStream *stream,
const char *str,
GCancellable *cancellable,
GError **error)
{
gsize bytes_written;
g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
g_return_val_if_fail (str != NULL, FALSE);
return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
str, strlen (str),
&bytes_written,
cancellable, error);
}

108
gio/gdataoutputstream.h Normal file
View File

@ -0,0 +1,108 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DATA_OUTPUT_STREAM_H__
#define __G_DATA_OUTPUT_STREAM_H__
#include <glib-object.h>
#include <gio/gfilteroutputstream.h>
#include <gio/gdatainputstream.h>
G_BEGIN_DECLS
#define G_TYPE_DATA_OUTPUT_STREAM (g_data_output_stream_get_type ())
#define G_DATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStream))
#define G_DATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStreamClass))
#define G_IS_DATA_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DATA_OUTPUT_STREAM))
#define G_IS_DATA_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DATA_OUTPUT_STREAM))
#define G_DATA_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DATA_OUTPUT_STREAM, GDataOutputStreamClass))
typedef struct _GDataOutputStream GDataOutputStream;
typedef struct _GDataOutputStreamClass GDataOutputStreamClass;
typedef struct _GDataOutputStreamPrivate GDataOutputStreamPrivate;
struct _GDataOutputStream
{
GFilterOutputStream parent;
/*< private >*/
GDataOutputStreamPrivate *priv;
};
struct _GDataOutputStreamClass
{
GFilterOutputStreamClass parent_class;
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_data_output_stream_get_type (void) G_GNUC_CONST;
GDataOutputStream* g_data_output_stream_new (GOutputStream *base_stream);
void g_data_output_stream_set_byte_order (GDataOutputStream *data_stream,
GDataStreamByteOrder order);
GDataStreamByteOrder g_data_output_stream_get_byte_order (GDataOutputStream *stream);
void g_data_output_stream_set_expand_buffer (GDataOutputStream *data_stream,
gboolean expand_buffer);
gboolean g_data_output_stream_put_byte (GDataOutputStream *data_stream,
guchar data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_int16 (GDataOutputStream *stream,
gint16 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_uint16 (GDataOutputStream *stream,
guint16 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_int32 (GDataOutputStream *stream,
gint32 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_uint32 (GDataOutputStream *stream,
guint32 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_int64 (GDataOutputStream *stream,
gint64 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_uint64 (GDataOutputStream *stream,
guint64 data,
GCancellable *cancellable,
GError **error);
gboolean g_data_output_stream_put_string (GDataOutputStream *stream,
const char *str,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_DATA_OUTPUT_STREAM_H__ */

2185
gio/gdesktopappinfo.c Normal file

File diff suppressed because it is too large Load Diff

54
gio/gdesktopappinfo.h Normal file
View File

@ -0,0 +1,54 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DESKTOP_APP_INFO_H__
#define __G_DESKTOP_APP_INFO_H__
#include <gio/gappinfo.h>
G_BEGIN_DECLS
#define G_TYPE_DESKTOP_APP_INFO (g_desktop_app_info_get_type ())
#define G_DESKTOP_APP_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DESKTOP_APP_INFO, GDesktopAppInfo))
#define G_DESKTOP_APP_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DESKTOP_APP_INFO, GDesktopAppInfoClass))
#define G_IS_DESKTOP_APP_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DESKTOP_APP_INFO))
#define G_IS_DESKTOP_APP_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DESKTOP_APP_INFO))
#define G_DESKTOP_APP_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DESKTOP_APP_INFO, GDesktopAppInfoClass))
typedef struct _GDesktopAppInfo GDesktopAppInfo;
typedef struct _GDesktopAppInfoClass GDesktopAppInfoClass;
struct _GDesktopAppInfoClass
{
GObjectClass parent_class;
};
GType g_desktop_app_info_get_type (void) G_GNUC_CONST;
GDesktopAppInfo *g_desktop_app_info_new_from_filename (const char *filename);
GDesktopAppInfo *g_desktop_app_info_new (const char *desktop_id);
gboolean g_desktop_app_info_get_is_hidden (GDesktopAppInfo *info);
G_END_DECLS
#endif /* __G_DESKTOP_APP_INFO_H__ */

472
gio/gdirectorymonitor.c Normal file
View File

@ -0,0 +1,472 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <string.h>
#include "gdirectorymonitor.h"
#include "gio-marshal.h"
#include "gfile.h"
#include "gvfs.h"
#include "glibintl.h"
enum {
CHANGED,
LAST_SIGNAL
};
G_DEFINE_ABSTRACT_TYPE (GDirectoryMonitor, g_directory_monitor, G_TYPE_OBJECT);
typedef struct {
GFile *file;
guint32 last_sent_change_time; /* 0 == not sent */
guint32 send_delayed_change_at; /* 0 == never */
guint32 send_virtual_changes_done_at; /* 0 == never */
} RateLimiter;
struct _GDirectoryMonitorPrivate {
gboolean cancelled;
int rate_limit_msec;
GHashTable *rate_limiter;
GSource *timeout;
guint32 timeout_fires_at;
};
#define DEFAULT_RATE_LIMIT_MSECS 800
#define DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS 2
static guint signals[LAST_SIGNAL] = { 0 };
static void
rate_limiter_free (RateLimiter *limiter)
{
g_object_unref (limiter->file);
g_free (limiter);
}
static void
g_directory_monitor_finalize (GObject *object)
{
GDirectoryMonitor *monitor;
monitor = G_DIRECTORY_MONITOR (object);
if (monitor->priv->timeout)
{
g_source_destroy (monitor->priv->timeout);
g_source_unref (monitor->priv->timeout);
}
g_hash_table_destroy (monitor->priv->rate_limiter);
if (G_OBJECT_CLASS (g_directory_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_directory_monitor_parent_class)->finalize) (object);
}
static void
g_directory_monitor_dispose (GObject *object)
{
GDirectoryMonitor *monitor;
monitor = G_DIRECTORY_MONITOR (object);
/* Make sure we cancel on last unref */
if (!monitor->priv->cancelled)
g_directory_monitor_cancel (monitor);
if (G_OBJECT_CLASS (g_directory_monitor_parent_class)->dispose)
(*G_OBJECT_CLASS (g_directory_monitor_parent_class)->dispose) (object);
}
static void
g_directory_monitor_class_init (GDirectoryMonitorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (GDirectoryMonitorPrivate));
gobject_class->finalize = g_directory_monitor_finalize;
gobject_class->dispose = g_directory_monitor_dispose;
/**
* GDirectoryMonitor::changed:
* @monitor: the #GDirectoryMonitor
* @child: the #GFile which changed
* @other_file: the other #GFile which changed
* @event_type: a #GFileMonitorEvent indicating what the event was
*
* Emitted when a child file changes.
*/
signals[CHANGED] =
g_signal_new (I_("changed"),
G_TYPE_DIRECTORY_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GDirectoryMonitorClass, changed),
NULL, NULL,
_gio_marshal_VOID__OBJECT_OBJECT_INT,
G_TYPE_NONE,3,
G_TYPE_FILE,
G_TYPE_FILE,
G_TYPE_INT);
}
static void
g_directory_monitor_init (GDirectoryMonitor *monitor)
{
monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
G_TYPE_DIRECTORY_MONITOR,
GDirectoryMonitorPrivate);
monitor->priv->rate_limit_msec = DEFAULT_RATE_LIMIT_MSECS;
monitor->priv->rate_limiter = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal,
NULL, (GDestroyNotify) rate_limiter_free);
}
/**
* g_directory_monitor_cancel:
* @monitor:
*
* Returns:
**/
gboolean
g_directory_monitor_cancel (GDirectoryMonitor* monitor)
{
GDirectoryMonitorClass *class;
g_return_val_if_fail (G_IS_DIRECTORY_MONITOR (monitor), FALSE);
if (monitor->priv->cancelled)
return TRUE;
monitor->priv->cancelled = TRUE;
class = G_DIRECTORY_MONITOR_GET_CLASS (monitor);
return (* class->cancel) (monitor);
}
/**
* g_directory_monitor_set_rate_limit:
* @monitor:
* @limit_msecs:
*
**/
void
g_directory_monitor_set_rate_limit (GDirectoryMonitor *monitor,
int limit_msecs)
{
g_return_if_fail (G_IS_DIRECTORY_MONITOR (monitor));
monitor->priv->rate_limit_msec = limit_msecs;
}
/**
* g_directory_monitor_is_cancelled:
* @monitor:
*
* Returns:
**/
gboolean
g_directory_monitor_is_cancelled (GDirectoryMonitor *monitor)
{
g_return_val_if_fail (G_IS_DIRECTORY_MONITOR (monitor), FALSE);
return monitor->priv->cancelled;
}
static guint32
get_time_msecs (void)
{
return g_thread_gettime() / (1000 * 1000);
}
static guint32
time_difference (guint32 from, guint32 to)
{
if (from > to)
return 0;
return to - from;
}
static RateLimiter *
new_limiter (GDirectoryMonitor *monitor,
GFile *file)
{
RateLimiter *limiter;
limiter = g_new0 (RateLimiter, 1);
limiter->file = g_object_ref (file);
g_hash_table_insert (monitor->priv->rate_limiter, file, limiter);
return limiter;
}
static void
rate_limiter_send_virtual_changes_done_now (GDirectoryMonitor *monitor, RateLimiter *limiter)
{
if (limiter->send_virtual_changes_done_at != 0)
{
g_signal_emit (monitor, signals[CHANGED], 0, limiter->file, NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
limiter->send_virtual_changes_done_at = 0;
}
}
static void
rate_limiter_send_delayed_change_now (GDirectoryMonitor *monitor, RateLimiter *limiter, guint32 time_now)
{
if (limiter->send_delayed_change_at != 0)
{
g_signal_emit (monitor, signals[CHANGED], 0, limiter->file, NULL, G_FILE_MONITOR_EVENT_CHANGED);
limiter->send_delayed_change_at = 0;
limiter->last_sent_change_time = time_now;
}
}
typedef struct {
guint32 min_time;
guint32 time_now;
GDirectoryMonitor *monitor;
} ForEachData;
static gboolean
calc_min_time (GDirectoryMonitor *monitor, RateLimiter *limiter, guint32 time_now, guint32 *min_time)
{
gboolean delete_me;
guint32 expire_at;
delete_me = TRUE;
if (limiter->last_sent_change_time != 0)
{
/* Set a timeout at 2*rate limit so that we can clear out the change from the hash eventualy */
expire_at = limiter->last_sent_change_time + 2 * monitor->priv->rate_limit_msec;
if (time_difference (time_now, expire_at) > 0)
{
delete_me = FALSE;
*min_time = MIN (*min_time,
time_difference (time_now, expire_at));
}
}
if (limiter->send_delayed_change_at != 0)
{
delete_me = FALSE;
*min_time = MIN (*min_time,
time_difference (time_now, limiter->send_delayed_change_at));
}
if (limiter->send_virtual_changes_done_at != 0)
{
delete_me = FALSE;
*min_time = MIN (*min_time,
time_difference (time_now, limiter->send_virtual_changes_done_at));
}
return delete_me;
}
static gboolean
foreach_rate_limiter_fire (gpointer key,
gpointer value,
gpointer user_data)
{
RateLimiter *limiter = value;
ForEachData *data = user_data;
if (limiter->send_delayed_change_at != 0 &&
time_difference (data->time_now, limiter->send_delayed_change_at) == 0)
rate_limiter_send_delayed_change_now (data->monitor, limiter, data->time_now);
if (limiter->send_virtual_changes_done_at != 0 &&
time_difference (data->time_now, limiter->send_virtual_changes_done_at) == 0)
rate_limiter_send_virtual_changes_done_now (data->monitor, limiter);
return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time);
}
static gboolean
rate_limiter_timeout (gpointer timeout_data)
{
GDirectoryMonitor *monitor = timeout_data;
ForEachData data;
GSource *source;
data.min_time = G_MAXUINT32;
data.monitor = monitor;
data.time_now = get_time_msecs ();
g_hash_table_foreach_remove (monitor->priv->rate_limiter,
foreach_rate_limiter_fire,
&data);
/* Remove old timeout */
if (monitor->priv->timeout)
{
g_source_destroy (monitor->priv->timeout);
g_source_unref (monitor->priv->timeout);
monitor->priv->timeout = NULL;
monitor->priv->timeout_fires_at = 0;
}
/* Set up new timeout */
if (data.min_time != G_MAXUINT32)
{
source = g_timeout_source_new (data.min_time + 1); /* + 1 to make sure we've really passed the time */
g_source_set_callback (source, rate_limiter_timeout, monitor, NULL);
g_source_attach (source, NULL);
monitor->priv->timeout = source;
monitor->priv->timeout_fires_at = data.time_now + data.min_time;
}
return FALSE;
}
static gboolean
foreach_rate_limiter_update (gpointer key,
gpointer value,
gpointer user_data)
{
RateLimiter *limiter = value;
ForEachData *data = user_data;
return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time);
}
static void
update_rate_limiter_timeout (GDirectoryMonitor *monitor, guint new_time)
{
ForEachData data;
GSource *source;
if (monitor->priv->timeout_fires_at != 0 && new_time != 0 &&
time_difference (new_time, monitor->priv->timeout_fires_at) == 0)
return; /* Nothing to do, we already fire earlier than that */
data.min_time = G_MAXUINT32;
data.monitor = monitor;
data.time_now = get_time_msecs ();
g_hash_table_foreach_remove (monitor->priv->rate_limiter,
foreach_rate_limiter_update,
&data);
/* Remove old timeout */
if (monitor->priv->timeout)
{
g_source_destroy (monitor->priv->timeout);
g_source_unref (monitor->priv->timeout);
monitor->priv->timeout_fires_at = 0;
monitor->priv->timeout = NULL;
}
/* Set up new timeout */
if (data.min_time != G_MAXUINT32)
{
source = g_timeout_source_new (data.min_time + 1); /* + 1 to make sure we've really passed the time */
g_source_set_callback (source, rate_limiter_timeout, monitor, NULL);
g_source_attach (source, NULL);
monitor->priv->timeout = source;
monitor->priv->timeout_fires_at = data.time_now + data.min_time;
}
}
/**
* g_directory_monitor_emit_event:
* @monitor:
* @child:
* @other_file:
* @event_type:
*
**/
void
g_directory_monitor_emit_event (GDirectoryMonitor *monitor,
GFile *child,
GFile *other_file,
GFileMonitorEvent event_type)
{
guint32 time_now, since_last;
gboolean emit_now;
RateLimiter *limiter;
g_return_if_fail (G_IS_DIRECTORY_MONITOR (monitor));
g_return_if_fail (G_IS_FILE (child));
limiter = g_hash_table_lookup (monitor->priv->rate_limiter, child);
if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
{
if (limiter)
{
rate_limiter_send_delayed_change_now (monitor, limiter, get_time_msecs ());
if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
limiter->send_virtual_changes_done_at = 0;
else
rate_limiter_send_virtual_changes_done_now (monitor, limiter);
update_rate_limiter_timeout (monitor, 0);
}
g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type);
}
else
{
/* Changed event, rate limit */
time_now = get_time_msecs ();
emit_now = TRUE;
if (limiter)
{
since_last = time_difference (limiter->last_sent_change_time, time_now);
if (since_last < monitor->priv->rate_limit_msec)
{
/* We ignore this change, but arm a timer so that we can fire it later if we
don't get any other events (that kill this timeout) */
emit_now = FALSE;
if (limiter->send_delayed_change_at == 0)
{
limiter->send_delayed_change_at = time_now + monitor->priv->rate_limit_msec;
update_rate_limiter_timeout (monitor, limiter->send_delayed_change_at);
}
}
}
if (limiter == NULL)
limiter = new_limiter (monitor, child);
if (emit_now)
{
g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type);
limiter->last_sent_change_time = time_now;
limiter->send_delayed_change_at = 0;
/* Set a timeout of 2*rate limit so that we can clear out the change from the hash eventualy */
update_rate_limiter_timeout (monitor, time_now + 2 * monitor->priv->rate_limit_msec);
}
/* Schedule a virtual change done. This is removed if we get a real one, and
postponed if we get more change events. */
limiter->send_virtual_changes_done_at = time_now + DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS * 1000;
update_rate_limiter_timeout (monitor, limiter->send_virtual_changes_done_at);
}
}

86
gio/gdirectorymonitor.h Normal file
View File

@ -0,0 +1,86 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DIRECTORY_MONITOR_H__
#define __G_DIRECTORY_MONITOR_H__
#include <glib-object.h>
#include <gio/gfile.h>
#include <gio/gfilemonitor.h>
G_BEGIN_DECLS
#define G_TYPE_DIRECTORY_MONITOR (g_directory_monitor_get_type ())
#define G_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitor))
#define G_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitorClass))
#define G_IS_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DIRECTORY_MONITOR))
#define G_IS_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DIRECTORY_MONITOR))
#define G_DIRECTORY_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitorClass))
typedef struct _GDirectoryMonitorClass GDirectoryMonitorClass;
typedef struct _GDirectoryMonitorPrivate GDirectoryMonitorPrivate;
struct _GDirectoryMonitor
{
GObject parent;
/*< private >*/
GDirectoryMonitorPrivate *priv;
};
struct _GDirectoryMonitorClass
{
GObjectClass parent_class;
/* Signals */
void (* changed) (GDirectoryMonitor* monitor,
GFile *child,
GFile *other_file,
GFileMonitorEvent event_type);
/* Virtual Table */
gboolean (*cancel)(GDirectoryMonitor* monitor);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_directory_monitor_get_type (void) G_GNUC_CONST;
gboolean g_directory_monitor_cancel (GDirectoryMonitor *monitor);
gboolean g_directory_monitor_is_cancelled (GDirectoryMonitor *monitor);
void g_directory_monitor_set_rate_limit (GDirectoryMonitor *monitor,
int limit_msecs);
/* For implementations */
void g_directory_monitor_emit_event (GDirectoryMonitor *monitor,
GFile *child,
GFile *other_file,
GFileMonitorEvent event_type);
G_END_DECLS
#endif /* __G_DIRECTORY_MONITOR_H__ */

348
gio/gdrive.c Normal file
View File

@ -0,0 +1,348 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gdrive.h"
#include "gsimpleasyncresult.h"
#include "glibintl.h"
static void g_drive_base_init (gpointer g_class);
static void g_drive_class_init (gpointer g_class,
gpointer class_data);
GType
g_drive_get_type (void)
{
static GType drive_type = 0;
if (! drive_type)
{
static const GTypeInfo drive_info =
{
sizeof (GDriveIface), /* class_size */
g_drive_base_init, /* base_init */
NULL, /* base_finalize */
g_drive_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
drive_type =
g_type_register_static (G_TYPE_INTERFACE, I_("GDrive"),
&drive_info, 0);
g_type_interface_add_prerequisite (drive_type, G_TYPE_OBJECT);
}
return drive_type;
}
static void
g_drive_class_init (gpointer g_class,
gpointer class_data)
{
}
static void
g_drive_base_init (gpointer g_class)
{
static gboolean initialized = FALSE;
if (! initialized)
{
g_signal_new (I_("changed"),
G_TYPE_DRIVE,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GDriveIface, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
initialized = TRUE;
}
}
/**
* g_drive_get_name:
* @drive: a #GDrive.
*
* Returns: string containing @drive's name.
*
* The returned string should be freed when no longer needed
**/
char *
g_drive_get_name (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->get_name) (drive);
}
/**
* g_drive_get_icon:
* @drive: a #GDrive.
*
* Gets the icon for @drive.
*
* Returns: #GIcon for the @drive.
**/
GIcon *
g_drive_get_icon (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->get_icon) (drive);
}
/**
* g_drive_has_volumes:
* @drive: a #GDrive.
*
* Returns: %TRUE if @drive contains volumes, %FALSE otherwise.
**/
gboolean
g_drive_has_volumes (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->has_volumes) (drive);
}
/**
* g_drive_get_volumes:
* @drive: a #GDrive.
*
* Returns: #GList containing any #GVolume s on the given @drive.
* NOTE: Fact-check this.
**/
GList *
g_drive_get_volumes (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->get_volumes) (drive);
}
/**
* g_drive_is_automounted:
* @drive: a #GDrive.
*
* Returns: %TRUE if the drive was automounted. %FALSE otherwise.
**/
gboolean
g_drive_is_automounted (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->is_automounted) (drive);
}
/**
* g_drive_can_mount:
* @drive: a #GDrive.
*
* Returns: %TRUE if the @drive can be mounted. %FALSE otherwise.
**/
gboolean
g_drive_can_mount (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
iface = G_DRIVE_GET_IFACE (drive);
if (iface->can_mount == NULL)
return FALSE;
return (* iface->can_mount) (drive);
}
/**
* g_drive_can_eject:
* @drive: pointer to a #GDrive.
*
* Returns: %TRUE if the @drive can be ejected. %FALSE otherwise.
**/
gboolean
g_drive_can_eject (GDrive *drive)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
iface = G_DRIVE_GET_IFACE (drive);
if (iface->can_eject == NULL)
return FALSE;
return (* iface->can_eject) (drive);
}
/**
* g_drive_mount:
* @drive: a #GDrive.
* @mount_operation: a #GMountOperation.
* @callback: a #GAsyncReadyCallback.
* @user_data: a #gpointer.
*
*
**/
void
g_drive_mount (GDrive *drive,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDriveIface *iface;
g_return_if_fail (G_IS_DRIVE (drive));
g_return_if_fail (G_IS_MOUNT_OPERATION (mount_operation));
iface = G_DRIVE_GET_IFACE (drive);
if (iface->mount == NULL)
{
g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("drive doesn't implement mount"));
return;
}
(* iface->mount) (drive, mount_operation, cancellable, callback, user_data);
}
/**
* g_drive_mount_finish:
* @drive: pointer to a #GDrive.
* @result: a #GAsyncResult.
* @error: a #GError.
*
* Returns: %TRUE, %FALSE if operation failed.
**/
gboolean
g_drive_mount_finish (GDrive *drive,
GAsyncResult *result,
GError **error)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
}
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->mount_finish) (drive, result, error);
}
/**
* g_drive_eject:
* @drive: a #GDrive.
* @callback: a #GAsyncReadyCallback.
* @user_data: a #gpointer.
*
**/
void
g_drive_eject (GDrive *drive,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDriveIface *iface;
g_return_if_fail (G_IS_DRIVE (drive));
iface = G_DRIVE_GET_IFACE (drive);
if (iface->eject == NULL)
{
g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("drive doesn't implement eject"));
return;
}
(* iface->eject) (drive, cancellable, callback, user_data);
}
/**
* g_drive_eject_finish
* @drive: a #GDrive.
* @result: a #GAsyncResult.
* @error: a #GError.
*
* Returns: %TRUE if the drive has been ejected successfully,
* %FALSE otherwise.
**/
gboolean
g_drive_eject_finish (GDrive *drive,
GAsyncResult *result,
GError **error)
{
GDriveIface *iface;
g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
}
iface = G_DRIVE_GET_IFACE (drive);
return (* iface->mount_finish) (drive, result, error);
}

99
gio/gdrive.h Normal file
View File

@ -0,0 +1,99 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DRIVE_H__
#define __G_DRIVE_H__
#include <glib-object.h>
#include <gio/gvolume.h>
#include <gio/gmountoperation.h>
G_BEGIN_DECLS
#define G_TYPE_DRIVE (g_drive_get_type ())
#define G_DRIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DRIVE, GDrive))
#define G_IS_DRIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DRIVE))
#define G_DRIVE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_DRIVE, GDriveIface))
typedef struct _GDriveIface GDriveIface;
struct _GDriveIface
{
GTypeInterface g_iface;
/* signals */
void (*changed) (GVolume *volume);
/* Virtual Table */
char * (*get_name) (GDrive *drive);
GIcon * (*get_icon) (GDrive *drive);
gboolean (*has_volumes) (GDrive *drive);
GList * (*get_volumes) (GDrive *drive);
gboolean (*is_automounted)(GDrive *drive);
gboolean (*can_mount) (GDrive *drive);
gboolean (*can_eject) (GDrive *drive);
void (*mount) (GDrive *drive,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*mount_finish)(GDrive *drive,
GAsyncResult *result,
GError **error);
void (*eject) (GDrive *drive,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*eject_finish)(GDrive *drive,
GAsyncResult *result,
GError **error);
};
GType g_drive_get_type (void) G_GNUC_CONST;
char * g_drive_get_name (GDrive *drive);
GIcon * g_drive_get_icon (GDrive *drive);
gboolean g_drive_has_volumes (GDrive *drive);
GList * g_drive_get_volumes (GDrive *drive);
gboolean g_drive_is_automounted (GDrive *drive);
gboolean g_drive_can_mount (GDrive *drive);
gboolean g_drive_can_eject (GDrive *drive);
void g_drive_mount (GDrive *drive,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_drive_mount_finish (GDrive *drive,
GAsyncResult *result,
GError **error);
void g_drive_eject (GDrive *drive,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_drive_eject_finish (GDrive *drive,
GAsyncResult *result,
GError **error);
G_END_DECLS
#endif /* __G_DRIVE_H__ */

32
gio/gdriveprivate.h Normal file
View File

@ -0,0 +1,32 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DRIVEPRIV_H__
#define __G_DRIVEPRIV_H__
#include <gio/gdrive.h>
G_BEGIN_DECLS
G_END_DECLS
#endif /* __G_DRIVEPRIV_H__ */

752
gio/gdummyfile.c Normal file
View File

@ -0,0 +1,752 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "gdummyfile.h"
static void g_dummy_file_file_iface_init (GFileIface *iface);
typedef struct {
char *scheme;
char *userinfo;
char *host;
int port; /* -1 => not in uri */
char *path;
char *query;
char *fragment;
} GDecodedUri;
struct _GDummyFile
{
GObject parent_instance;
GDecodedUri *decoded_uri;
char *text_uri;
};
G_DEFINE_TYPE_WITH_CODE (GDummyFile, g_dummy_file, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
g_dummy_file_file_iface_init))
#define SUB_DELIM_CHARS "!$&'()*+,;="
static char * _g_encode_uri (GDecodedUri *decoded);
static void _g_decoded_uri_free (GDecodedUri *decoded);
static GDecodedUri *_g_decode_uri (const char *uri);
static GDecodedUri *_g_decoded_uri_new (void);
static char * unescape_string (const gchar *escaped_string,
const gchar *escaped_string_end,
const gchar *illegal_characters);
static void g_string_append_encoded (GString *string, const char *encoded,
const char *reserved_chars_allowed);
static void
g_dummy_file_finalize (GObject *object)
{
GDummyFile *dummy;
dummy = G_DUMMY_FILE (object);
if (dummy->decoded_uri)
_g_decoded_uri_free (dummy->decoded_uri);
g_free (dummy->text_uri);
if (G_OBJECT_CLASS (g_dummy_file_parent_class)->finalize)
(*G_OBJECT_CLASS (g_dummy_file_parent_class)->finalize) (object);
}
static void
g_dummy_file_class_init (GDummyFileClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_dummy_file_finalize;
}
static void
g_dummy_file_init (GDummyFile *dummy)
{
}
/**
* g_dummy_file_new:
* @uri: Universal Resource Identifier for the dummy file object.
*
* Returns: a new #GFile.
**/
GFile *
g_dummy_file_new (const char *uri)
{
GDummyFile *dummy;
g_return_val_if_fail (uri != NULL, NULL);
dummy = g_object_new (G_TYPE_DUMMY_FILE, NULL);
dummy->text_uri = g_strdup (uri);
dummy->decoded_uri = _g_decode_uri (uri);
return G_FILE (dummy);
}
static gboolean
g_dummy_file_is_native (GFile *file)
{
return FALSE;
}
static char *
g_dummy_file_get_basename (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
if (dummy->decoded_uri)
return g_path_get_basename (dummy->decoded_uri->path);
return g_strdup (dummy->text_uri);
}
static char *
g_dummy_file_get_path (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
if (dummy->decoded_uri)
return g_strdup (dummy->decoded_uri->path);
return NULL;
}
static char *
g_dummy_file_get_uri (GFile *file)
{
return g_strdup (G_DUMMY_FILE (file)->text_uri);
}
static char *
g_dummy_file_get_parse_name (GFile *file)
{
return g_strdup (G_DUMMY_FILE (file)->text_uri);
}
static GFile *
g_dummy_file_get_parent (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
GFile *parent;
char *dirname;
char *uri;
GDecodedUri new_decoded_uri;
if (dummy->decoded_uri == NULL)
return NULL;
dirname = g_path_get_dirname (dummy->decoded_uri->path);
if (strcmp (dirname, ".") == 0)
{
g_free (dirname);
return NULL;
}
new_decoded_uri = *dummy->decoded_uri;
new_decoded_uri.path = dirname;
uri = _g_encode_uri (&new_decoded_uri);
g_free (dirname);
parent = g_dummy_file_new (uri);
g_free (uri);
return parent;
}
static GFile *
g_dummy_file_dup (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
return g_dummy_file_new (dummy->text_uri);
}
static guint
g_dummy_file_hash (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
return g_str_hash (dummy->text_uri);
}
static gboolean
g_dummy_file_equal (GFile *file1,
GFile *file2)
{
GDummyFile *dummy1 = G_DUMMY_FILE (file1);
GDummyFile *dummy2 = G_DUMMY_FILE (file2);
return g_str_equal (dummy1->text_uri, dummy2->text_uri);
}
static int
safe_strcmp (const char *a, const char *b)
{
if (a == NULL)
a = "";
if (b == NULL)
b = "";
return strcmp (a, b);
}
static gboolean
uri_same_except_path (GDecodedUri *a,
GDecodedUri *b)
{
if (safe_strcmp (a->scheme, b->scheme) != 0)
return FALSE;
if (safe_strcmp (a->userinfo, b->userinfo) != 0)
return FALSE;
if (safe_strcmp (a->host, b->host) != 0)
return FALSE;
if (a->port != b->port)
return FALSE;
return TRUE;
}
static const char *
match_prefix (const char *path, const char *prefix)
{
int prefix_len;
prefix_len = strlen (prefix);
if (strncmp (path, prefix, prefix_len) != 0)
return NULL;
return path + prefix_len;
}
static gboolean
g_dummy_file_contains_file (GFile *parent,
GFile *descendant)
{
GDummyFile *parent_dummy = G_DUMMY_FILE (parent);
GDummyFile *descendant_dummy = G_DUMMY_FILE (descendant);
const char *remainder;
if (parent_dummy->decoded_uri != NULL &&
descendant_dummy->decoded_uri != NULL)
{
if (uri_same_except_path (parent_dummy->decoded_uri,
descendant_dummy->decoded_uri)) {
remainder = match_prefix (descendant_dummy->decoded_uri->path,
parent_dummy->decoded_uri->path);
if (remainder != NULL && *remainder == '/')
{
while (*remainder == '/')
remainder++;
if (*remainder != 0)
return TRUE;
}
}
}
else
{
remainder = match_prefix (descendant_dummy->text_uri,
parent_dummy->text_uri);
if (remainder != NULL && *remainder == '/')
{
while (*remainder == '/')
remainder++;
if (*remainder != 0)
return TRUE;
}
}
return FALSE;
}
static char *
g_dummy_file_get_relative_path (GFile *parent,
GFile *descendant)
{
GDummyFile *parent_dummy = G_DUMMY_FILE (parent);
GDummyFile *descendant_dummy = G_DUMMY_FILE (descendant);
const char *remainder;
if (parent_dummy->decoded_uri != NULL &&
descendant_dummy->decoded_uri != NULL)
{
if (uri_same_except_path (parent_dummy->decoded_uri,
descendant_dummy->decoded_uri)) {
remainder = match_prefix (descendant_dummy->decoded_uri->path,
parent_dummy->decoded_uri->path);
if (remainder != NULL && *remainder == '/')
{
while (*remainder == '/')
remainder++;
if (*remainder != 0)
return g_strdup (remainder);
}
}
}
else
{
remainder = match_prefix (descendant_dummy->text_uri,
parent_dummy->text_uri);
if (remainder != NULL && *remainder == '/')
{
while (*remainder == '/')
remainder++;
if (*remainder != 0)
return unescape_string (remainder, NULL, "/");
}
}
return NULL;
}
static GFile *
g_dummy_file_resolve_relative_path (GFile *file,
const char *relative_path)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
GFile *child;
char *uri;
GDecodedUri new_decoded_uri;
GString *str;
if (dummy->decoded_uri == NULL)
{
str = g_string_new (dummy->text_uri);
g_string_append (str, "/");
g_string_append_encoded (str, relative_path, SUB_DELIM_CHARS ":@/");
child = g_dummy_file_new (str->str);
g_string_free (str, TRUE);
}
else
{
new_decoded_uri = *dummy->decoded_uri;
if (g_path_is_absolute (relative_path))
new_decoded_uri.path = g_strdup (relative_path);
else
new_decoded_uri.path = g_build_filename (new_decoded_uri.path, relative_path, NULL);
uri = _g_encode_uri (&new_decoded_uri);
g_free (new_decoded_uri.path);
child = g_dummy_file_new (uri);
g_free (uri);
}
return child;
}
static GFile *
g_dummy_file_get_child_for_display_name (GFile *file,
const char *display_name,
GError **error)
{
return g_file_get_child (file, display_name);
}
static gboolean
g_dummy_file_has_uri_scheme (GFile *file,
const char *uri_scheme)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
if (dummy->decoded_uri)
return g_ascii_strcasecmp (uri_scheme, dummy->decoded_uri->scheme) == 0;
return FALSE;
}
static char *
g_dummy_file_get_uri_scheme (GFile *file)
{
GDummyFile *dummy = G_DUMMY_FILE (file);
if (dummy->decoded_uri)
return g_strdup (dummy->decoded_uri->scheme);
return NULL;
}
static void
g_dummy_file_file_iface_init (GFileIface *iface)
{
iface->dup = g_dummy_file_dup;
iface->hash = g_dummy_file_hash;
iface->equal = g_dummy_file_equal;
iface->is_native = g_dummy_file_is_native;
iface->has_uri_scheme = g_dummy_file_has_uri_scheme;
iface->get_uri_scheme = g_dummy_file_get_uri_scheme;
iface->get_basename = g_dummy_file_get_basename;
iface->get_path = g_dummy_file_get_path;
iface->get_uri = g_dummy_file_get_uri;
iface->get_parse_name = g_dummy_file_get_parse_name;
iface->get_parent = g_dummy_file_get_parent;
iface->contains_file = g_dummy_file_contains_file;
iface->get_relative_path = g_dummy_file_get_relative_path;
iface->resolve_relative_path = g_dummy_file_resolve_relative_path;
iface->get_child_for_display_name = g_dummy_file_get_child_for_display_name;
}
/* Uri handling helper functions: */
static int
unescape_character (const char *scanner)
{
int first_digit;
int second_digit;
first_digit = g_ascii_xdigit_value (*scanner++);
if (first_digit < 0)
return -1;
second_digit = g_ascii_xdigit_value (*scanner++);
if (second_digit < 0)
return -1;
return (first_digit << 4) | second_digit;
}
static char *
unescape_string (const gchar *escaped_string,
const gchar *escaped_string_end,
const gchar *illegal_characters)
{
const gchar *in;
gchar *out, *result;
gint character;
if (escaped_string == NULL)
return NULL;
if (escaped_string_end == NULL)
escaped_string_end = escaped_string + strlen (escaped_string);
result = g_malloc (escaped_string_end - escaped_string + 1);
out = result;
for (in = escaped_string; in < escaped_string_end; in++) {
character = *in;
if (*in == '%') {
in++;
if (escaped_string_end - in < 2)
{
g_free (result);
return NULL;
}
character = unescape_character (in);
/* Check for an illegal character. We consider '\0' illegal here. */
if (character <= 0 ||
(illegal_characters != NULL &&
strchr (illegal_characters, (char)character) != NULL))
{
g_free (result);
return NULL;
}
in++; /* The other char will be eaten in the loop header */
}
*out++ = (char)character;
}
*out = '\0';
g_assert (out - result <= strlen (escaped_string));
return result;
}
void
_g_decoded_uri_free (GDecodedUri *decoded)
{
if (decoded == NULL)
return;
g_free (decoded->scheme);
g_free (decoded->query);
g_free (decoded->fragment);
g_free (decoded->userinfo);
g_free (decoded->host);
g_free (decoded->path);
g_free (decoded);
}
GDecodedUri *
_g_decoded_uri_new (void)
{
GDecodedUri *uri;
uri = g_new0 (GDecodedUri, 1);
uri->port = -1;
return uri;
}
GDecodedUri *
_g_decode_uri (const char *uri)
{
GDecodedUri *decoded;
const char *p, *in, *hier_part_start, *hier_part_end, *query_start, *fragment_start;
char *out;
char c;
/* From RFC 3986 Decodes:
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
*/
p = uri;
/* Decode scheme:
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
*/
if (!g_ascii_isalpha (*p))
return NULL;
while (1)
{
c = *p++;
if (c == ':')
break;
if (!(g_ascii_isalnum(c) ||
c == '+' ||
c == '-' ||
c == '.'))
return NULL;
}
decoded = _g_decoded_uri_new ();
decoded->scheme = g_malloc (p - uri);
out = decoded->scheme;
for (in = uri; in < p - 1; in++)
*out++ = g_ascii_tolower (*in);
*out = 0;
hier_part_start = p;
query_start = strchr (p, '?');
if (query_start)
{
hier_part_end = query_start++;
fragment_start = strchr (query_start, '#');
if (fragment_start)
{
decoded->query = g_strndup (query_start, fragment_start - query_start);
decoded->fragment = g_strdup (fragment_start+1);
}
else
{
decoded->query = g_strdup (query_start);
decoded->fragment = NULL;
}
}
else
{
/* No query */
decoded->query = NULL;
fragment_start = strchr (p, '#');
if (fragment_start)
{
hier_part_end = fragment_start++;
decoded->fragment = g_strdup (fragment_start);
}
else
{
hier_part_end = p + strlen (p);
decoded->fragment = NULL;
}
}
/* 3:
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
*/
if (hier_part_start[0] == '/' &&
hier_part_start[1] == '/')
{
const char *authority_start, *authority_end;
const char *userinfo_start, *userinfo_end;
const char *host_start, *host_end;
const char *port_start;
authority_start = hier_part_start + 2;
/* authority is always followed by / or nothing */
authority_end = memchr (authority_start, '/', hier_part_end - authority_start);
if (authority_end == NULL)
authority_end = hier_part_end;
/* 3.2:
authority = [ userinfo "@" ] host [ ":" port ]
*/
userinfo_end = memchr (authority_start, '@', authority_end - authority_start);
if (userinfo_end)
{
userinfo_start = authority_start;
decoded->userinfo = unescape_string (userinfo_start, userinfo_end, NULL);
if (decoded->userinfo == NULL)
{
_g_decoded_uri_free (decoded);
return NULL;
}
host_start = userinfo_end + 1;
}
else
host_start = authority_start;
port_start = memchr (host_start, ':', authority_end - host_start);
if (port_start)
{
host_end = port_start++;
decoded->port = atoi(port_start);
}
else
{
host_end = authority_end;
decoded->port = -1;
}
decoded->host = g_strndup (host_start, host_end - host_start);
hier_part_start = authority_end;
}
decoded->path = unescape_string (hier_part_start, hier_part_end, "/");
if (decoded->path == NULL)
{
_g_decoded_uri_free (decoded);
return NULL;
}
return decoded;
}
static gboolean
is_valid (char c, const char *reserved_chars_allowed)
{
if (g_ascii_isalnum (c) ||
c == '-' ||
c == '.' ||
c == '_' ||
c == '~')
return TRUE;
if (reserved_chars_allowed &&
strchr (reserved_chars_allowed, c) != NULL)
return TRUE;
return FALSE;
}
static void
g_string_append_encoded (GString *string, const char *encoded,
const char *reserved_chars_allowed)
{
unsigned char c;
const char *end;
static const gchar hex[16] = "0123456789ABCDEF";
end = encoded + strlen (encoded);
while ((c = *encoded) != 0)
{
if (is_valid (c, reserved_chars_allowed))
{
g_string_append_c (string, c);
encoded++;
}
else
{
g_string_append_c (string, '%');
g_string_append_c (string, hex[((guchar)c) >> 4]);
g_string_append_c (string, hex[((guchar)c) & 0xf]);
encoded++;
}
}
}
static char *
_g_encode_uri (GDecodedUri *decoded)
{
GString *uri;
uri = g_string_new (NULL);
g_string_append (uri, decoded->scheme);
g_string_append (uri, "://");
if (decoded->host != NULL)
{
if (decoded->userinfo)
{
/* userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) */
g_string_append_encoded (uri, decoded->userinfo, SUB_DELIM_CHARS ":");
g_string_append_c (uri, '@');
}
g_string_append (uri, decoded->host);
if (decoded->port != -1)
{
g_string_append_c (uri, ':');
g_string_append_printf (uri, "%d", decoded->port);
}
}
g_string_append_encoded (uri, decoded->path, SUB_DELIM_CHARS ":@/");
if (decoded->query)
{
g_string_append_c (uri, '?');
g_string_append (uri, decoded->query);
}
if (decoded->fragment)
{
g_string_append_c (uri, '#');
g_string_append (uri, decoded->fragment);
}
return g_string_free (uri, FALSE);
}

51
gio/gdummyfile.h Normal file
View File

@ -0,0 +1,51 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_DUMMY_FILE_H__
#define __G_DUMMY_FILE_H__
#include <gio/gfile.h>
G_BEGIN_DECLS
#define G_TYPE_DUMMY_FILE (g_dummy_file_get_type ())
#define G_DUMMY_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DUMMY_FILE, GDummyFile))
#define G_DUMMY_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DUMMY_FILE, GDummyFileClass))
#define G_IS_DUMMY_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DUMMY_FILE))
#define G_IS_DUMMY_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DUMMY_FILE))
#define G_DUMMY_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DUMMY_FILE, GDummyFileClass))
typedef struct _GDummyFile GDummyFile;
typedef struct _GDummyFileClass GDummyFileClass;
struct _GDummyFileClass
{
GObjectClass parent_class;
};
GType g_dummy_file_get_type (void) G_GNUC_CONST;
GFile * g_dummy_file_new (const char *uri);
G_END_DECLS
#endif /* __G_DUMMY_FILE_H__ */

4345
gio/gfile.c Normal file

File diff suppressed because it is too large Load Diff

676
gio/gfile.h Normal file
View File

@ -0,0 +1,676 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_H__
#define __G_FILE_H__
#include <glib-object.h>
#include <gio/gfileinfo.h>
#include <gio/gfileenumerator.h>
#include <gio/gfileinputstream.h>
#include <gio/gfileoutputstream.h>
#include <gio/gmountoperation.h>
G_BEGIN_DECLS
#define G_TYPE_FILE (g_file_get_type ())
#define G_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_FILE, GFile))
#define G_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_FILE))
#define G_FILE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_FILE, GFileIface))
typedef enum {
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS = (1<<0)
} GFileQueryInfoFlags;
typedef enum {
G_FILE_CREATE_FLAGS_NONE = 0,
G_FILE_CREATE_FLAGS_PRIVATE = (1<<0)
} GFileCreateFlags;
typedef enum {
G_FILE_COPY_OVERWRITE = (1<<0),
G_FILE_COPY_BACKUP = (1<<1),
G_FILE_COPY_NOFOLLOW_SYMLINKS = (1<<2),
G_FILE_COPY_ALL_METADATA = (1<<3)
} GFileCopyFlags;
typedef enum {
G_FILE_MONITOR_FLAGS_NONE = 0,
G_FILE_MONITOR_FLAGS_MONITOR_MOUNTS = (1<<0)
} GFileMonitorFlags;
typedef struct _GFile GFile; /* Dummy typedef */
typedef struct _GFileIface GFileIface;
typedef struct _GDirectoryMonitor GDirectoryMonitor;
typedef struct _GFileMonitor GFileMonitor;
typedef struct _GVolume GVolume; /* Dummy typedef */
typedef void (*GFileProgressCallback) (goffset current_num_bytes,
goffset total_num_bytes,
gpointer user_data);
typedef gboolean (* GFileReadMoreCallback) (const char *file_contents,
goffset file_size,
gpointer callback_data);
struct _GFileIface
{
GTypeInterface g_iface;
/* Virtual Table */
GFile * (*dup) (GFile *file);
guint (*hash) (GFile *file);
gboolean (*equal) (GFile *file1,
GFile *file2);
gboolean (*is_native) (GFile *file);
gboolean (*has_uri_scheme) (GFile *file,
const char *uri_scheme);
char * (*get_uri_scheme) (GFile *file);
char * (*get_basename) (GFile *file);
char * (*get_path) (GFile *file);
char * (*get_uri) (GFile *file);
char * (*get_parse_name) (GFile *file);
GFile * (*get_parent) (GFile *file);
gboolean (*contains_file) (GFile *parent,
GFile *descendant);
char * (*get_relative_path) (GFile *parent,
GFile *descendant);
GFile * (*resolve_relative_path) (GFile *file,
const char *relative_path);
GFile * (*get_child_for_display_name) (GFile *file,
const char *display_name,
GError **error);
GFileEnumerator * (*enumerate_children) (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void (*enumerate_children_async) (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileEnumerator * (*enumerate_children_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileInfo * (*query_info) (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void (*query_info_async) (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo * (*query_info_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileInfo * (*query_filesystem_info)(GFile *file,
const char *attributes,
GCancellable *cancellable,
GError **error);
void (*_query_filesystem_info_async) (void);
void (*_query_filesystem_info_finish) (void);
GVolume * (*find_enclosing_volume)(GFile *file,
GCancellable *cancellable,
GError **error);
void (*find_enclosing_volume_async)(GFile *file,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GVolume * (*find_enclosing_volume_finish)(GFile *file,
GAsyncResult *res,
GError **error);
GFile * (*set_display_name) (GFile *file,
const char *display_name,
GCancellable *cancellable,
GError **error);
void (*set_display_name_async) (GFile *file,
const char *display_name,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFile * (*set_display_name_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileAttributeInfoList * (*query_settable_attributes) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*_query_settable_attributes_async) (void);
void (*_query_settable_attributes_finish) (void);
GFileAttributeInfoList * (*query_writable_namespaces) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*_query_writable_namespaces_async) (void);
void (*_query_writable_namespaces_finish) (void);
gboolean (*set_attribute) (GFile *file,
const char *attribute,
const GFileAttributeValue *value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean (*set_attributes_from_info) (GFile *file,
GFileInfo *info,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void (*set_attributes_async) (GFile *file,
GFileInfo *info,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*set_attributes_finish) (GFile *file,
GAsyncResult *result,
GFileInfo **info,
GError **error);
GFileInputStream * (*read) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*read_async) (GFile *file,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInputStream * (*read_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileOutputStream * (*append_to) (GFile *file,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
void (*append_to_async) (GFile *file,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * (*append_to_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileOutputStream * (*create) (GFile *file,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
void (*create_async) (GFile *file,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * (*create_finish) (GFile *file,
GAsyncResult *res,
GError **error);
GFileOutputStream * (*replace) (GFile *file,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
void (*replace_async) (GFile *file,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * (*replace_finish) (GFile *file,
GAsyncResult *res,
GError **error);
gboolean (*delete_file) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*_delete_file_async) (void);
void (*_delete_file_finish) (void);
gboolean (*trash) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*_trash_async) (void);
void (*_trash_finish) (void);
gboolean (*make_directory) (GFile *file,
GCancellable *cancellable,
GError **error);
void (*_make_directory_async) (void);
void (*_make_directory_finish) (void);
gboolean (*make_symbolic_link) (GFile *file,
const char *symlink_value,
GCancellable *cancellable,
GError **error);
void (*_make_symbolic_link_async) (void);
void (*_make_symbolic_link_finish) (void);
gboolean (*copy) (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error);
void (*_copy_async) (void);
void (*_copy_finish) (void);
gboolean (*move) (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error);
void (*_move_async) (void);
void (*_move_finish) (void);
void (*mount_mountable) (GFile *file,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFile * (*mount_mountable_finish) (GFile *file,
GAsyncResult *result,
GError **error);
void (*unmount_mountable) (GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*unmount_mountable_finish) (GFile *file,
GAsyncResult *result,
GError **error);
void (*eject_mountable) (GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*eject_mountable_finish) (GFile *file,
GAsyncResult *result,
GError **error);
void (*mount_for_location) (GFile *location,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*mount_for_location_finish) (GFile *location,
GAsyncResult *result,
GError **error);
GDirectoryMonitor* (*monitor_dir) (GFile *file,
GFileMonitorFlags flags,
GCancellable *cancellable);
GFileMonitor* (*monitor_file) (GFile *file,
GFileMonitorFlags flags,
GCancellable *cancellable);
};
GType g_file_get_type (void) G_GNUC_CONST;
GFile * g_file_new_for_path (const char *path);
GFile * g_file_new_for_uri (const char *uri);
GFile * g_file_new_for_commandline_arg (const char *arg);
GFile * g_file_parse_name (const char *parse_name);
GFile * g_file_dup (GFile *file);
guint g_file_hash (gconstpointer file);
gboolean g_file_equal (GFile *file1,
GFile *file2);
char * g_file_get_basename (GFile *file);
char * g_file_get_path (GFile *file);
char * g_file_get_uri (GFile *file);
char * g_file_get_parse_name (GFile *file);
GFile * g_file_get_parent (GFile *file);
GFile * g_file_get_child (GFile *file,
const char *name);
GFile * g_file_get_child_for_display_name (GFile *file,
const char *display_name,
GError **error);
gboolean g_file_contains_file (GFile *parent,
GFile *descendant);
char * g_file_get_relative_path (GFile *parent,
GFile *descendant);
GFile * g_file_resolve_relative_path (GFile *file,
const char *relative_path);
gboolean g_file_is_native (GFile *file);
gboolean g_file_has_uri_scheme (GFile *file,
const char *uri_scheme);
char * g_file_get_uri_scheme (GFile *file);
GFileInputStream * g_file_read (GFile *file,
GCancellable *cancellable,
GError **error);
void g_file_read_async (GFile *file,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInputStream * g_file_read_finish (GFile *file,
GAsyncResult *res,
GError **error);
GFileOutputStream * g_file_append_to (GFile *file,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
GFileOutputStream * g_file_create (GFile *file,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
GFileOutputStream * g_file_replace (GFile *file,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
void g_file_append_to_async (GFile *file,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * g_file_append_to_finish (GFile *file,
GAsyncResult *res,
GError **error);
void g_file_create_async (GFile *file,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * g_file_create_finish (GFile *file,
GAsyncResult *res,
GError **error);
void g_file_replace_async (GFile *file,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileOutputStream * g_file_replace_finish (GFile *file,
GAsyncResult *res,
GError **error);
GFileInfo * g_file_query_info (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void g_file_query_info_async (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo * g_file_query_info_finish (GFile *file,
GAsyncResult *res,
GError **error);
GFileInfo * g_file_query_filesystem_info (GFile *file,
const char *attributes,
GCancellable *cancellable,
GError **error);
GVolume * g_file_find_enclosing_volume (GFile *file,
GCancellable *cancellable,
GError **error);
GFileEnumerator * g_file_enumerate_children (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void g_file_enumerate_children_async (GFile *file,
const char *attributes,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileEnumerator * g_file_enumerate_children_finish (GFile *file,
GAsyncResult *res,
GError **error);
GFile * g_file_set_display_name (GFile *file,
const char *display_name,
GCancellable *cancellable,
GError **error);
void g_file_set_display_name_async (GFile *file,
const char *display_name,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFile * g_file_set_display_name_finish (GFile *file,
GAsyncResult *res,
GError **error);
gboolean g_file_delete (GFile *file,
GCancellable *cancellable,
GError **error);
gboolean g_file_trash (GFile *file,
GCancellable *cancellable,
GError **error);
gboolean g_file_copy (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error);
gboolean g_file_move (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GFileProgressCallback progress_callback,
gpointer progress_callback_data,
GError **error);
gboolean g_file_make_directory (GFile *file,
GCancellable *cancellable,
GError **error);
gboolean g_file_make_symbolic_link (GFile *file,
const char *symlink_value,
GCancellable *cancellable,
GError **error);
GFileAttributeInfoList *g_file_query_settable_attributes (GFile *file,
GCancellable *cancellable,
GError **error);
GFileAttributeInfoList *g_file_query_writable_namespaces (GFile *file,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute (GFile *file,
const char *attribute,
const GFileAttributeValue *value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attributes_from_info (GFile *file,
GFileInfo *info,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void g_file_set_attributes_async (GFile *file,
GFileInfo *info,
GFileQueryInfoFlags flags,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_set_attributes_finish (GFile *file,
GAsyncResult *result,
GFileInfo **info,
GError **error);
gboolean g_file_set_attribute_string (GFile *file,
const char *attribute,
const char *value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute_byte_string (GFile *file,
const char *attribute,
const char *value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute_uint32 (GFile *file,
const char *attribute,
guint32 value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute_int32 (GFile *file,
const char *attribute,
gint32 value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute_uint64 (GFile *file,
const char *attribute,
guint64 value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean g_file_set_attribute_int64 (GFile *file,
const char *attribute,
gint64 value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
void g_mount_for_location (GFile *location,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_mount_for_location_finish (GFile *location,
GAsyncResult *result,
GError **error);
void g_file_mount_mountable (GFile *file,
GMountOperation *mount_operation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFile * g_file_mount_mountable_finish (GFile *file,
GAsyncResult *result,
GError **error);
void g_file_unmount_mountable (GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_unmount_mountable_finish (GFile *file,
GAsyncResult *result,
GError **error);
void g_file_eject_mountable (GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_eject_mountable_finish (GFile *file,
GAsyncResult *result,
GError **error);
gboolean g_file_copy_attributes (GFile *source,
GFile *destination,
GFileCopyFlags flags,
GCancellable *cancellable,
GError **error);
GDirectoryMonitor* g_file_monitor_directory (GFile *file,
GFileMonitorFlags flags,
GCancellable *cancellable);
GFileMonitor* g_file_monitor_file (GFile *file,
GFileMonitorFlags flags,
GCancellable *cancellable);
/* Utilities */
gboolean g_file_load_contents (GFile *file,
GCancellable *cancellable,
char **contents,
gsize *length,
char **etag_out,
GError **error);
void g_file_load_contents_async (GFile *file,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_load_contents_finish (GFile *file,
GAsyncResult *res,
char **contents,
gsize *length,
char **etag_out,
GError **error);
void g_file_load_partial_contents_async (GFile *file,
GCancellable *cancellable,
GFileReadMoreCallback read_more_callback,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_load_partial_contents_finish (GFile *file,
GAsyncResult *res,
char **contents,
gsize *length,
char **etag_out,
GError **error);
gboolean g_file_replace_contents (GFile *file,
const char *contents,
gsize length,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
char **new_etag,
GCancellable *cancellable,
GError **error);
void g_file_replace_contents_async (GFile *file,
const char *contents,
gsize length,
const char *etag,
gboolean make_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_replace_contents_finish (GFile *file,
GAsyncResult *res,
char **new_etag,
GError **error);
G_END_DECLS
#endif /* __G_FILE_H__ */

704
gio/gfileattribute.c Normal file
View File

@ -0,0 +1,704 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <string.h>
#include "gfileattribute.h"
#include <glib-object.h>
#include "glibintl.h"
/**
* g_file_attribute_value_free:
* @attr: a #GFileAttributeValue.
*
* Frees the memory used by @attr.
*
**/
void
g_file_attribute_value_free (GFileAttributeValue *attr)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
g_free (attr);
}
/**
* g_file_attribute_value_clear:
* @attr: a #GFileAttributeValue.
*
* Clears the value of @attr and sets its type to
* %G_FILE_ATTRIBUTE_TYPE_INVALID.
*
**/
void
g_file_attribute_value_clear (GFileAttributeValue *attr)
{
g_return_if_fail (attr != NULL);
if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
g_free (attr->u.string);
if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
attr->u.obj != NULL)
g_object_unref (attr->u.obj);
attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
}
/**
* g_file_attribute_value_set:
* @attr: a #GFileAttributeValue.
* @new_value:
*
**/
void
g_file_attribute_value_set (GFileAttributeValue *attr,
const GFileAttributeValue *new_value)
{
g_return_if_fail (attr != NULL);
g_return_if_fail (new_value != NULL);
g_file_attribute_value_clear (attr);
*attr = *new_value;
if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
attr->u.string = g_strdup (attr->u.string);
if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
attr->u.obj != NULL)
g_object_ref (attr->u.obj);
}
/**
* g_file_attribute_value_new:
*
* Returns: a new #GFileAttributeValue.
**/
GFileAttributeValue *
g_file_attribute_value_new (void)
{
GFileAttributeValue *attr;
attr = g_new (GFileAttributeValue, 1);
attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
return attr;
}
/**
* g_file_attribute_value_dup:
* @other: a #GFileAttributeValue to duplicate.
*
* Returns: a duplicate of the @other.
**/
GFileAttributeValue *
g_file_attribute_value_dup (const GFileAttributeValue *other)
{
GFileAttributeValue *attr;
g_return_val_if_fail (other != NULL, NULL);
attr = g_new (GFileAttributeValue, 1);
attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
g_file_attribute_value_set (attr, other);
return attr;
}
static gboolean
valid_char (char c)
{
return c >= 32 && c <= 126 && c != '\\';
}
static char *
escape_byte_string (const char *str)
{
size_t len;
int num_invalid, i;
char *escaped_val, *p;
unsigned char c;
char *hex_digits = "0123456789abcdef";
len = strlen (str);
num_invalid = 0;
for (i = 0; i < len; i++)
{
if (!valid_char (str[i]))
num_invalid++;
}
if (num_invalid == 0)
return g_strdup (str);
else
{
escaped_val = g_malloc (len + num_invalid*3 + 1);
p = escaped_val;
for (i = 0; i < len; i++)
{
c = str[i];
if (valid_char (c))
*p++ = c;
else
{
*p++ = '\\';
*p++ = 'x';
*p++ = hex_digits[(c >> 8) & 0xf];
*p++ = hex_digits[c & 0xf];
}
}
*p++ = 0;
return escaped_val;
}
}
/**
* g_file_attribute_value_as_string:
* @attr: a #GFileAttributeValue.
*
* Converts a #GFileAttributeValue to a string for display.
* The returned string should be freed when no longer needed
*
* Returns: a string from the @attr, %NULL on error, or "<invalid>" if
* @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
**/
char *
g_file_attribute_value_as_string (const GFileAttributeValue *attr)
{
char *str;
g_return_val_if_fail (attr != NULL, NULL);
switch (attr->type)
{
case G_FILE_ATTRIBUTE_TYPE_STRING:
str = g_strdup (attr->u.string);
break;
case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
str = escape_byte_string (attr->u.string);
break;
case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
break;
case G_FILE_ATTRIBUTE_TYPE_UINT32:
str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
break;
case G_FILE_ATTRIBUTE_TYPE_INT32:
str = g_strdup_printf ("%i", (int)attr->u.int32);
break;
case G_FILE_ATTRIBUTE_TYPE_UINT64:
str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
break;
case G_FILE_ATTRIBUTE_TYPE_INT64:
str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
break;
case G_FILE_ATTRIBUTE_TYPE_OBJECT:
str = g_strdup_printf ("%s:%p", g_type_name_from_instance
((GTypeInstance *) attr->u.obj),
attr->u.obj);
break;
default:
g_warning ("Invalid type in GFileInfo attribute");
str = g_strdup ("<invalid>");
break;
}
return str;
}
/**
* g_file_attribute_value_get_string:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
const char *
g_file_attribute_value_get_string (const GFileAttributeValue *attr)
{
if (attr == NULL)
return NULL;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
return attr->u.string;
}
/**
* g_file_attribute_value_get_byte_string:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
const char *
g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
{
if (attr == NULL)
return NULL;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
return attr->u.string;
}
/**
* g_file_attribute_value_get_boolean:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
gboolean
g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
{
if (attr == NULL)
return FALSE;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
return attr->u.boolean;
}
/**
* g_file_attribute_value_get_uint32:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
guint32
g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
{
if (attr == NULL)
return 0;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
return attr->u.uint32;
}
/**
* g_file_attribute_value_get_int32:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
gint32
g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
{
if (attr == NULL)
return 0;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
return attr->u.int32;
}
/**
* g_file_attribute_value_get_uint64:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
guint64
g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
{
if (attr == NULL)
return 0;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
return attr->u.uint64;
}
/**
* g_file_attribute_value_get_int64:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
gint64
g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
{
if (attr == NULL)
return 0;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
return attr->u.int64;
}
/**
* g_file_attribute_value_get_object:
* @attr: a #GFileAttributeValue.
*
* Returns:
**/
GObject *
g_file_attribute_value_get_object (const GFileAttributeValue *attr)
{
if (attr == NULL)
return NULL;
g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
return attr->u.obj;
}
/**
* g_file_attribute_value_set_string:
* @attr: a #GFileAttributeValue.
* @string:
*
**/
void
g_file_attribute_value_set_string (GFileAttributeValue *attr,
const char *string)
{
g_return_if_fail (attr != NULL);
g_return_if_fail (string != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
attr->u.string = g_strdup (string);
}
/**
* g_file_attribute_value_set_byte_string:
* @attr: a #GFileAttributeValue.
* @string:
*
**/
void
g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
const char *string)
{
g_return_if_fail (attr != NULL);
g_return_if_fail (string != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
attr->u.string = g_strdup (string);
}
/**
* g_file_attribute_value_set_boolean:
* @attr: a #GFileAttributeValue.
* @value:
*
**/
void
g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
gboolean value)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
attr->u.boolean = !!value;
}
/**
* g_file_attribute_value_set_uint32:
* @attr: a #GFileAttributeValue.
* @value:
*
**/
void
g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
guint32 value)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
attr->u.uint32 = value;
}
/**
* g_file_attribute_value_set_int32:
* @attr: a #GFileAttributeValue.
* @value:
*
**/
void
g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
gint32 value)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
attr->u.int32 = value;
}
/**
* g_file_attribute_value_set_uint64:
* @attr: a #GFileAttributeValue.
* @value:
*
**/
void
g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
guint64 value)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
attr->u.uint64 = value;
}
/**
* g_file_attribute_value_set_int64:
* @attr: a #GFileAttributeValue.
* @value: a #gint64 to set the value to.
*
**/
void
g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
gint64 value)
{
g_return_if_fail (attr != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
attr->u.int64 = value;
}
/**
* g_file_attribute_value_set_object:
* @attr: a #GFileAttributeValue.
* @obj: a #GObject.
*
* Sets the file attribute @attr to contain the value @obj.
* The @attr references the object internally.
*
**/
void
g_file_attribute_value_set_object (GFileAttributeValue *attr,
GObject *obj)
{
g_return_if_fail (attr != NULL);
g_return_if_fail (obj != NULL);
g_file_attribute_value_clear (attr);
attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
attr->u.obj = g_object_ref (obj);
}
typedef struct {
GFileAttributeInfoList public;
GArray *array;
int ref_count;
} GFileAttributeInfoListPriv;
static void
list_update_public (GFileAttributeInfoListPriv *priv)
{
priv->public.infos = (GFileAttributeInfo *)priv->array->data;
priv->public.n_infos = priv->array->len;
}
/**
* g_file_attribute_info_list_new:
*
* Returns a new #GFileAttributeInfoList.
**/
GFileAttributeInfoList *
g_file_attribute_info_list_new (void)
{
GFileAttributeInfoListPriv *priv;
priv = g_new0 (GFileAttributeInfoListPriv, 1);
priv->ref_count = 1;
priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
list_update_public (priv);
return (GFileAttributeInfoList *)priv;
}
/**
* g_file_attribute_info_list_dup:
* @list: a #GFileAttributeInfoList to duplicate.
*
* Returns a duplicate of the given @list.
**/
GFileAttributeInfoList *
g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
{
GFileAttributeInfoListPriv *new;
int i;
g_return_val_if_fail (list != NULL, NULL);
new = g_new0 (GFileAttributeInfoListPriv, 1);
new->ref_count = 1;
new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
g_array_set_size (new->array, list->n_infos);
list_update_public (new);
for (i = 0; i < list->n_infos; i++)
{
new->public.infos[i].name = g_strdup (list->infos[i].name);
new->public.infos[i].type = list->infos[i].type;
new->public.infos[i].flags = list->infos[i].flags;
}
return (GFileAttributeInfoList *)new;
}
/**
* g_file_attribute_info_list_ref:
* @list: a #GFileAttributeInfoList to reference.
*
* Returns: #GFileAttributeInfoList or %NULL on error.
**/
GFileAttributeInfoList *
g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
{
GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
g_return_val_if_fail (list != NULL, NULL);
g_return_val_if_fail (priv->ref_count > 0, NULL);
g_atomic_int_inc (&priv->ref_count);
return list;
}
/**
* g_file_attribute_info_list_unref:
* @list: The #GFileAttributeInfoList to unreference.
*
* Removes a reference from the given @list. If the reference count
* falls to zero, the @list is deleted.
**/
void
g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
{
GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
int i;
g_return_if_fail (list != NULL);
g_return_if_fail (priv->ref_count > 0);
if (g_atomic_int_dec_and_test (&priv->ref_count))
{
for (i = 0; i < list->n_infos; i++)
g_free (list->infos[i].name);
g_array_free (priv->array, TRUE);
}
}
static int
g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
const char *name)
{
int start, end, mid;
start = 0;
end = list->n_infos;
while (start != end)
{
mid = start + (end - start) / 2;
if (strcmp (name, list->infos[mid].name) < 0)
end = mid;
else if (strcmp (name, list->infos[mid].name) > 0)
start = mid + 1;
else
return mid;
}
return start;
}
/**
* g_file_attribute_info_list_lookup:
* @list: a #GFileAttributeInfoList.
* @name: the name of the attribute to lookup.
*
* Returns: a #GFileAttributeInfo for the @name, or %NULL if an
* attribute isn't found.
**/
const GFileAttributeInfo *
g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
const char *name)
{
int i;
g_return_val_if_fail (list != NULL, NULL);
g_return_val_if_fail (name != NULL, NULL);
i = g_file_attribute_info_list_bsearch (list, name);
if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
return &list->infos[i];
return NULL;
}
/**
* g_file_attribute_info_list_add:
* @list: a #GFileAttributeInfoList.
* @name: the name of the attribute to add.
* @type: the #GFileAttributeType for the attribute.
* @flags: #GFileAttributeFlags for the attribute.
*
* Adds a new attribute with @name to the @list, setting
* its @type and @flags.
*
**/
void
g_file_attribute_info_list_add (GFileAttributeInfoList *list,
const char *name,
GFileAttributeType type,
GFileAttributeFlags flags)
{
GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
GFileAttributeInfo info;
int i;
g_return_if_fail (list != NULL);
g_return_if_fail (name != NULL);
i = g_file_attribute_info_list_bsearch (list, name);
if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
{
list->infos[i].type = type;
return;
}
info.name = g_strdup (name);
info.type = type;
info.flags = flags;
g_array_insert_vals (priv->array, i, &info, 1);
list_update_public (priv);
}

132
gio/gfileattribute.h Normal file
View File

@ -0,0 +1,132 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_ATTRIBUTE_H__
#define __G_FILE_ATTRIBUTE_H__
#include <glib-object.h>
G_BEGIN_DECLS
typedef enum {
G_FILE_ATTRIBUTE_TYPE_INVALID = 0,
G_FILE_ATTRIBUTE_TYPE_STRING,
G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, /* zero terminated string of non-zero bytes */
G_FILE_ATTRIBUTE_TYPE_BOOLEAN,
G_FILE_ATTRIBUTE_TYPE_UINT32,
G_FILE_ATTRIBUTE_TYPE_INT32,
G_FILE_ATTRIBUTE_TYPE_UINT64,
G_FILE_ATTRIBUTE_TYPE_INT64,
G_FILE_ATTRIBUTE_TYPE_OBJECT
} GFileAttributeType;
typedef enum {
G_FILE_ATTRIBUTE_FLAGS_NONE = 0,
G_FILE_ATTRIBUTE_FLAGS_COPY_WITH_FILE = 1 << 0,
G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED = 1 << 1
} GFileAttributeFlags;
/* Used by g_file_set_attributes_from_info */
typedef enum {
G_FILE_ATTRIBUTE_STATUS_UNSET = 0,
G_FILE_ATTRIBUTE_STATUS_SET,
G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING
} GFileAttributeStatus;
#define G_FILE_ATTRIBUTE_VALUE_INIT {0}
typedef struct {
GFileAttributeType type : 8;
GFileAttributeStatus status : 8;
union {
gboolean boolean;
gint32 int32;
guint32 uint32;
gint64 int64;
guint64 uint64;
char *string;
GQuark quark;
GObject *obj;
} u;
} GFileAttributeValue;
typedef struct {
char *name;
GFileAttributeType type;
GFileAttributeFlags flags;
} GFileAttributeInfo;
typedef struct {
GFileAttributeInfo *infos;
int n_infos;
} GFileAttributeInfoList;
GFileAttributeValue *g_file_attribute_value_new (void);
void g_file_attribute_value_free (GFileAttributeValue *attr);
void g_file_attribute_value_clear (GFileAttributeValue *attr);
void g_file_attribute_value_set (GFileAttributeValue *attr,
const GFileAttributeValue *new_value);
GFileAttributeValue *g_file_attribute_value_dup (const GFileAttributeValue *other);
char * g_file_attribute_value_as_string (const GFileAttributeValue *attr);
const char * g_file_attribute_value_get_string (const GFileAttributeValue *attr);
const char * g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr);
gboolean g_file_attribute_value_get_boolean (const GFileAttributeValue *attr);
guint32 g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr);
gint32 g_file_attribute_value_get_int32 (const GFileAttributeValue *attr);
guint64 g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr);
gint64 g_file_attribute_value_get_int64 (const GFileAttributeValue *attr);
GObject * g_file_attribute_value_get_object (const GFileAttributeValue *attr);
void g_file_attribute_value_set_string (GFileAttributeValue *attr,
const char *string);
void g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
const char *string);
void g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
gboolean value);
void g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
guint32 value);
void g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
gint32 value);
void g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
guint64 value);
void g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
gint64 value);
void g_file_attribute_value_set_object (GFileAttributeValue *attr,
GObject *obj);
GFileAttributeInfoList * g_file_attribute_info_list_new (void);
GFileAttributeInfoList * g_file_attribute_info_list_ref (GFileAttributeInfoList *list);
void g_file_attribute_info_list_unref (GFileAttributeInfoList *list);
GFileAttributeInfoList * g_file_attribute_info_list_dup (GFileAttributeInfoList *list);
const GFileAttributeInfo *g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
const char *name);
void g_file_attribute_info_list_add (GFileAttributeInfoList *list,
const char *name,
GFileAttributeType type,
GFileAttributeFlags flags);
G_END_DECLS
#endif /* __G_FILE_INFO_H__ */

617
gio/gfileenumerator.c Normal file
View File

@ -0,0 +1,617 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gfileenumerator.h"
#include "gioscheduler.h"
#include "gasynchelper.h"
#include "gsimpleasyncresult.h"
#include "glibintl.h"
G_DEFINE_TYPE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT);
struct _GFileEnumeratorPrivate {
/* TODO: Should be public for subclasses? */
guint closed : 1;
guint pending : 1;
GAsyncReadyCallback outstanding_callback;
GError *outstanding_error;
};
static void g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
int num_files,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static GList * g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
GAsyncResult *res,
GError **error);
static void g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static gboolean g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
GAsyncResult *res,
GError **error);
static void
g_file_enumerator_finalize (GObject *object)
{
GFileEnumerator *enumerator;
enumerator = G_FILE_ENUMERATOR (object);
if (!enumerator->priv->closed)
g_file_enumerator_close (enumerator, NULL, NULL);
if (G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize)
(*G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize) (object);
}
static void
g_file_enumerator_class_init (GFileEnumeratorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (GFileEnumeratorPrivate));
gobject_class->finalize = g_file_enumerator_finalize;
klass->next_files_async = g_file_enumerator_real_next_files_async;
klass->next_files_finish = g_file_enumerator_real_next_files_finish;
klass->close_async = g_file_enumerator_real_close_async;
klass->close_finish = g_file_enumerator_real_close_finish;
}
static void
g_file_enumerator_init (GFileEnumerator *enumerator)
{
enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator,
G_TYPE_FILE_ENUMERATOR,
GFileEnumeratorPrivate);
}
/**
* g_file_enumerator_next_file:
* @enumerator: a #GFileEnumerator.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: location to store the error occuring, or %NULL to ignore
*
* Returns information for the next file in the enumerated object.
* Will block until the information is available.
*
* On error, returns %NULL and sets @error to the error. If the
* enumerator is at the end, %NULL will be returned and @error will
* be unset.
*
* Return value: A #GFileInfo or %NULL on error or end of enumerator
**/
GFileInfo *
g_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
GFileEnumeratorClass *class;
GFileInfo *info;
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
g_return_val_if_fail (enumerator != NULL, NULL);
if (enumerator->priv->closed)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Enumerator is closed"));
return NULL;
}
if (enumerator->priv->pending)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("File enumerator has outstanding operation"));
return NULL;
}
if (enumerator->priv->outstanding_error)
{
g_propagate_error (error, enumerator->priv->outstanding_error);
enumerator->priv->outstanding_error = NULL;
return NULL;
}
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
if (cancellable)
g_push_current_cancellable (cancellable);
enumerator->priv->pending = TRUE;
info = (* class->next_file) (enumerator, cancellable, error);
enumerator->priv->pending = FALSE;
if (cancellable)
g_pop_current_cancellable (cancellable);
return info;
}
/**
* g_file_enumerator_close:
* @enumerator: a #GFileEnumerator.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: location to store the error occuring, or %NULL to ignore
*
* Releases all resources used by this enumerator, making the
* enumerator return %G_IO_ERROR_CLOSED on all calls.
*
* This will be automatically called when the last reference
* is dropped, but you might want to call make sure resources
* are released as early as possible.
*
* Return value: #TRUE on success or #FALSE on error.
**/
gboolean
g_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
GFileEnumeratorClass *class;
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
g_return_val_if_fail (enumerator != NULL, FALSE);
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
if (enumerator->priv->closed)
return TRUE;
if (enumerator->priv->pending)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("File enumerator has outstanding operation"));
return FALSE;
}
if (cancellable)
g_push_current_cancellable (cancellable);
enumerator->priv->pending = TRUE;
(* class->close) (enumerator, cancellable, error);
enumerator->priv->pending = FALSE;
enumerator->priv->closed = TRUE;
if (cancellable)
g_pop_current_cancellable (cancellable);
return TRUE;
}
static void
next_async_callback_wrapper (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
enumerator->priv->pending = FALSE;
if (enumerator->priv->outstanding_callback)
(*enumerator->priv->outstanding_callback) (source_object, res, user_data);
g_object_unref (enumerator);
}
/**
* g_file_enumerator_next_files_async:
* @enumerator: a #GFileEnumerator.
* @num_files: the number of file info objects to request
* @io_priority: the io priority of the request. the io priority of the request
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: callback to call when the request is satisfied
* @user_data: the user_data to pass to callback function
*
* Request information for a number of files from the enumerator asynchronously.
* When all i/o for the operation is finished the @callback will be called with
* the requested information.
*
* The callback can be called with less than @num_files files in case of error
* or at the end of the enumerator. In case of a partial error the callback will
* be called with any succeeding items and no error, and on the next request the
* error will be reported. If a request is cancelled the callback will be called
* with %G_IO_ERROR_CANCELLED.
*
* During an async request no other sync and async calls are allowed, and will
* result in %G_IO_ERROR_PENDING errors.
*
* Any outstanding i/o request with higher priority (lower numerical value) will
* be executed before an outstanding request with lower priority. Default
* priority is %G_PRIORITY_DEFAULT.
**/
void
g_file_enumerator_next_files_async (GFileEnumerator *enumerator,
int num_files,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFileEnumeratorClass *class;
GSimpleAsyncResult *simple;
g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
g_return_if_fail (enumerator != NULL);
g_return_if_fail (num_files >= 0);
if (num_files == 0)
{
simple = g_simple_async_result_new (G_OBJECT (enumerator),
callback,
user_data,
g_file_enumerator_next_files_async);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
return;
}
if (enumerator->priv->closed)
{
g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("File enumerator is already closed"));
return;
}
if (enumerator->priv->pending)
{
g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_PENDING,
_("File enumerator has outstanding operation"));
return;
}
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
enumerator->priv->pending = TRUE;
enumerator->priv->outstanding_callback = callback;
g_object_ref (enumerator);
(* class->next_files_async) (enumerator, num_files, io_priority, cancellable,
next_async_callback_wrapper, user_data);
}
/**
* g_file_enumerator_next_files_finish:
* @enumerator: a #GFileEnumerator.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
GList *
g_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error)
{
GFileEnumeratorClass *class;
GSimpleAsyncResult *simple;
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
/* Special case read of 0 files */
if (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_next_files_async)
return NULL;
}
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
return class->next_files_finish (enumerator, result, error);
}
static void
close_async_callback_wrapper (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
enumerator->priv->pending = FALSE;
enumerator->priv->closed = TRUE;
if (enumerator->priv->outstanding_callback)
(*enumerator->priv->outstanding_callback) (source_object, res, user_data);
g_object_unref (enumerator);
}
/**
* g_file_enumerator_close_async:
* @enumerator: a #GFileEnumerator.
* @io_priority: the io priority of the request. the io priority of the request
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: callback to call when the request is satisfied
* @user_data: the user_data to pass to callback function
*
**/
void
g_file_enumerator_close_async (GFileEnumerator *enumerator,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFileEnumeratorClass *class;
g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
if (enumerator->priv->closed)
{
g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("File enumerator is already closed"));
return;
}
if (enumerator->priv->pending)
{
g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_PENDING,
_("File enumerator has outstanding operation"));
return;
}
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
enumerator->priv->pending = TRUE;
enumerator->priv->outstanding_callback = callback;
g_object_ref (enumerator);
(* class->close_async) (enumerator, io_priority, cancellable,
close_async_callback_wrapper, user_data);
}
/**
* g_file_enumerator_close_finish:
* @enumerator: a #GFileEnumerator.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns: %TRUE if the close operation has finished successfully.
**/
gboolean
g_file_enumerator_close_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
GFileEnumeratorClass *class;
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
}
class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
return class->close_finish (enumerator, result, error);
}
/**
* g_file_enumerator_is_closed:
* @enumerator: a #GFileEnumerator.
*
* Returns: %TRUE if the @enumerator is closed.
**/
gboolean
g_file_enumerator_is_closed (GFileEnumerator *enumerator)
{
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
return enumerator->priv->closed;
}
/**
* g_file_enumerator_has_pending:
* @enumerator: a #GFileEnumerator.
*
* Returns: %TRUE if the @enumerator has pending operations.
**/
gboolean
g_file_enumerator_has_pending (GFileEnumerator *enumerator)
{
g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
return enumerator->priv->pending;
}
/**
* g_file_enumerator_set_pending:
* @enumerator: a #GFileEnumerator.
* @pending: a boolean value.
*
**/
void
g_file_enumerator_set_pending (GFileEnumerator *enumerator,
gboolean pending)
{
g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
enumerator->priv->pending = pending;
}
typedef struct {
int num_files;
GList *files;
} NextAsyncOp;
static void
next_files_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
NextAsyncOp *op;
GFileEnumeratorClass *class;
GError *error = NULL;
GFileInfo *info;
GFileEnumerator *enumerator;
int i;
enumerator = G_FILE_ENUMERATOR (object);
op = g_simple_async_result_get_op_res_gpointer (res);
class = G_FILE_ENUMERATOR_GET_CLASS (object);
for (i = 0; i < op->num_files; i++)
{
if (g_cancellable_set_error_if_cancelled (cancellable, &error))
info = NULL;
else
info = class->next_file (enumerator, cancellable, &error);
if (info == NULL)
{
/* If we get an error after first file, return that on next operation */
if (error != NULL && i > 0)
{
if (error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_CANCELLED)
g_error_free (error); /* Never propagate cancel errors to other call */
else
enumerator->priv->outstanding_error = error;
error = NULL;
}
break;
}
else
op->files = g_list_prepend (op->files, info);
}
}
static void
g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
int num_files,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
NextAsyncOp *op;
op = g_new0 (NextAsyncOp, 1);
op->num_files = num_files;
op->files = NULL;
res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_file_enumerator_real_next_files_async);
g_simple_async_result_set_op_res_gpointer (res, op, g_free);
g_simple_async_result_run_in_thread (res, next_files_thread, io_priority, cancellable);
g_object_unref (res);
}
static GList *
g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
NextAsyncOp *op;
g_assert (g_simple_async_result_get_source_tag (simple) ==
g_file_enumerator_real_next_files_async);
op = g_simple_async_result_get_op_res_gpointer (simple);
return op->files;
}
static void
close_async_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GFileEnumeratorClass *class;
GError *error = NULL;
gboolean result;
/* Auto handling of cancelation disabled, and ignore
cancellation, since we want to close things anyway, although
possibly in a quick-n-dirty way. At least we never want to leak
open handles */
class = G_FILE_ENUMERATOR_GET_CLASS (object);
result = class->close (G_FILE_ENUMERATOR (object), cancellable, &error);
if (!result)
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
}
static void
g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
res = g_simple_async_result_new (G_OBJECT (enumerator),
callback,
user_data,
g_file_enumerator_real_close_async);
g_simple_async_result_set_handle_cancellation (res, FALSE);
g_simple_async_result_run_in_thread (res,
close_async_thread,
io_priority,
cancellable);
g_object_unref (res);
}
static gboolean
g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
g_assert (g_simple_async_result_get_source_tag (simple) ==
g_file_enumerator_real_close_async);
return TRUE;
}

130
gio/gfileenumerator.h Normal file
View File

@ -0,0 +1,130 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_ENUMERATOR_H__
#define __G_FILE_ENUMERATOR_H__
#include <glib-object.h>
#include <gio/gioerror.h>
#include <gio/gcancellable.h>
#include <gio/gfileinfo.h>
#include <gio/gasyncresult.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_ENUMERATOR (g_file_enumerator_get_type ())
#define G_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_ENUMERATOR, GFileEnumerator))
#define G_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_ENUMERATOR, GFileEnumeratorClass))
#define G_IS_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_ENUMERATOR))
#define G_IS_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_ENUMERATOR))
#define G_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_ENUMERATOR, GFileEnumeratorClass))
typedef struct _GFileEnumerator GFileEnumerator;
typedef struct _GFileEnumeratorClass GFileEnumeratorClass;
typedef struct _GFileEnumeratorPrivate GFileEnumeratorPrivate;
struct _GFileEnumerator
{
GObject parent;
/*< private >*/
GFileEnumeratorPrivate *priv;
};
struct _GFileEnumeratorClass
{
GObjectClass parent_class;
/* Virtual Table */
GFileInfo *(*next_file) (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
gboolean (*close) (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
void (*next_files_async) (GFileEnumerator *enumerator,
int num_files,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GList * (*next_files_finish) (GFileEnumerator *enumerator,
GAsyncResult *res,
GError **error);
void (*close_async) (GFileEnumerator *enumerator,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*close_finish) (GFileEnumerator *enumerator,
GAsyncResult *res,
GError **error);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
void (*_g_reserved6) (void);
void (*_g_reserved7) (void);
};
GType g_file_enumerator_get_type (void) G_GNUC_CONST;
GFileInfo *g_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
gboolean g_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
void g_file_enumerator_next_files_async (GFileEnumerator *enumerator,
int num_files,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GList * g_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error);
void g_file_enumerator_close_async (GFileEnumerator *enumerator,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_file_enumerator_close_finish (GFileEnumerator *enumerator,
GAsyncResult *result,
GError **error);
gboolean g_file_enumerator_is_closed (GFileEnumerator *enumerator);
gboolean g_file_enumerator_has_pending (GFileEnumerator *enumerator);
void g_file_enumerator_set_pending (GFileEnumerator *enumerator,
gboolean pending);
G_END_DECLS
#endif /* __G_FILE_ENUMERATOR_H__ */

257
gio/gfileicon.c Normal file
View File

@ -0,0 +1,257 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gfileicon.h"
#include "gsimpleasyncresult.h"
static void g_file_icon_icon_iface_init (GIconIface *iface);
static void g_file_icon_loadable_icon_iface_init (GLoadableIconIface *iface);
static void g_file_icon_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
struct _GFileIcon
{
GObject parent_instance;
GFile *file;
};
struct _GFileIconClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE_WITH_CODE (GFileIcon, g_file_icon, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
g_file_icon_icon_iface_init);
G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON,
g_file_icon_loadable_icon_iface_init);
)
static void
g_file_icon_finalize (GObject *object)
{
GFileIcon *icon;
icon = G_FILE_ICON (object);
g_object_unref (icon->file);
if (G_OBJECT_CLASS (g_file_icon_parent_class)->finalize)
(*G_OBJECT_CLASS (g_file_icon_parent_class)->finalize) (object);
}
static void
g_file_icon_class_init (GFileIconClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_file_icon_finalize;
}
static void
g_file_icon_init (GFileIcon *file)
{
}
/**
* g_file_icon_new:
* @file:
*
* Returns:
**/
GIcon *
g_file_icon_new (GFile *file)
{
GFileIcon *icon;
g_return_val_if_fail (G_IS_FILE (file), NULL);
icon = g_object_new (G_TYPE_FILE_ICON, NULL);
icon->file = g_object_ref (file);
return G_ICON (icon);
}
/**
* g_file_icon_get_file:
* @icon:
*
* Returns:
**/
GFile *
g_file_icon_get_file (GFileIcon *icon)
{
g_return_val_if_fail (G_IS_FILE_ICON (icon), NULL);
return icon->file;
}
static guint
g_file_icon_hash (GIcon *icon)
{
GFileIcon *file_icon = G_FILE_ICON (icon);
return g_file_hash (file_icon->file);
}
static gboolean
g_file_icon_equal (GIcon *icon1,
GIcon *icon2)
{
GFileIcon *file1 = G_FILE_ICON (icon1);
GFileIcon *file2 = G_FILE_ICON (icon2);
return g_file_equal (file1->file, file2->file);
}
static void
g_file_icon_icon_iface_init (GIconIface *iface)
{
iface->hash = g_file_icon_hash;
iface->equal = g_file_icon_equal;
}
static GInputStream *
g_file_icon_load (GLoadableIcon *icon,
int size,
char **type,
GCancellable *cancellable,
GError **error)
{
GFileInputStream *stream;
GFileIcon *file_icon = G_FILE_ICON (icon);
stream = g_file_read (file_icon->file,
cancellable,
error);
return G_INPUT_STREAM (stream);
}
typedef struct {
GLoadableIcon *icon;
GAsyncReadyCallback callback;
gpointer user_data;
} LoadData;
static void
load_data_free (LoadData *data)
{
g_object_unref (data->icon);
g_free (data);
}
static void
load_async_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GFileInputStream *stream;
GError *error = NULL;
GSimpleAsyncResult *simple;
LoadData *data = user_data;
stream = g_file_read_finish (G_FILE (source_object), res, &error);
if (stream == NULL)
{
simple = g_simple_async_result_new_from_error (G_OBJECT (data->icon),
data->callback,
data->user_data,
error);
g_error_free (error);
}
else
{
simple = g_simple_async_result_new (G_OBJECT (data->icon),
data->callback,
data->user_data,
g_file_icon_load_async);
g_simple_async_result_set_op_res_gpointer (simple,
stream,
g_object_unref);
}
g_simple_async_result_complete (simple);
load_data_free (data);
}
static void
g_file_icon_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFileIcon *file_icon = G_FILE_ICON (icon);
LoadData *data;
data = g_new0 (LoadData, 1);
data->icon = g_object_ref (icon);
data->callback = callback;
data->user_data = user_data;
g_file_read_async (file_icon->file, 0,
cancellable,
load_async_callback, data);
}
static GInputStream *
g_file_icon_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
gpointer op;
g_assert (g_simple_async_result_get_source_tag (simple) == g_file_icon_load_async);
if (type)
*type = NULL;
op = g_simple_async_result_get_op_res_gpointer (simple);
if (op)
return g_object_ref (op);
return NULL;
}
static void
g_file_icon_loadable_icon_iface_init (GLoadableIconIface *iface)
{
iface->load = g_file_icon_load;
iface->load_async = g_file_icon_load_async;
iface->load_finish = g_file_icon_load_finish;
}

49
gio/gfileicon.h Normal file
View File

@ -0,0 +1,49 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_ICON_H__
#define __G_FILE_ICON_H__
#include <gio/gloadableicon.h>
#include <gio/gfile.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_ICON (g_file_icon_get_type ())
#define G_FILE_ICON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_ICON, GFileIcon))
#define G_FILE_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_ICON, GFileIconClass))
#define G_IS_FILE_ICON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_ICON))
#define G_IS_FILE_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_ICON))
#define G_FILE_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_ICON, GFileIconClass))
typedef struct _GFileIcon GFileIcon;
typedef struct _GFileIconClass GFileIconClass;
GType g_file_icon_get_type (void) G_GNUC_CONST;
GIcon *g_file_icon_new (GFile *file);
GFile *g_file_icon_get_file (GFileIcon *icon);
G_END_DECLS
#endif /* __G_FILE_ICON_H__ */

1924
gio/gfileinfo.c Normal file

File diff suppressed because it is too large Load Diff

280
gio/gfileinfo.h Normal file
View File

@ -0,0 +1,280 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_INFO_H__
#define __G_FILE_INFO_H__
#include <glib-object.h>
#include <gio/gfileattribute.h>
#include <gio/gicon.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_INFO (g_file_info_get_type ())
#define G_FILE_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_INFO, GFileInfo))
#define G_FILE_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_INFO, GFileInfoClass))
#define G_IS_FILE_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_INFO))
#define G_IS_FILE_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_INFO))
#define G_FILE_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_INFO, GFileInfoClass))
typedef struct _GFileInfo GFileInfo;
typedef struct _GFileInfoClass GFileInfoClass;
typedef struct _GFileAttributeMatcher GFileAttributeMatcher;
typedef enum {
G_FILE_TYPE_UNKNOWN = 0,
G_FILE_TYPE_REGULAR,
G_FILE_TYPE_DIRECTORY,
G_FILE_TYPE_SYMBOLIC_LINK,
G_FILE_TYPE_SPECIAL, /* socket, fifo, blockdev, chardev */
G_FILE_TYPE_SHORTCUT,
G_FILE_TYPE_MOUNTABLE
} GFileType;
/* Common Attributes: */
#define G_FILE_ATTRIBUTE_STD_TYPE "std:type" /* uint32 (GFileType) */
#define G_FILE_ATTRIBUTE_STD_IS_HIDDEN "std:is_hidden" /* boolean */
#define G_FILE_ATTRIBUTE_STD_IS_BACKUP "std:is_backup" /* boolean */
#define G_FILE_ATTRIBUTE_STD_IS_SYMLINK "std:is_symlink" /* boolean */
#define G_FILE_ATTRIBUTE_STD_IS_VIRTUAL "std:is_virtual" /* boolean */
#define G_FILE_ATTRIBUTE_STD_NAME "std:name" /* byte string */
#define G_FILE_ATTRIBUTE_STD_DISPLAY_NAME "std:display_name" /* string */
#define G_FILE_ATTRIBUTE_STD_EDIT_NAME "std:edit_name" /* string */
#define G_FILE_ATTRIBUTE_STD_COPY_NAME "std:copy_name" /* string */
#define G_FILE_ATTRIBUTE_STD_ICON "std:icon" /* object (GIcon) */
#define G_FILE_ATTRIBUTE_STD_CONTENT_TYPE "std:content_type" /* string */
#define G_FILE_ATTRIBUTE_STD_FAST_CONTENT_TYPE "std:fast_content_type" /* string */
#define G_FILE_ATTRIBUTE_STD_SIZE "std:size" /* uint64 */
#define G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET "std:symlink_target" /* byte string */
#define G_FILE_ATTRIBUTE_STD_TARGET_URI "std:target_uri" /* string */
#define G_FILE_ATTRIBUTE_STD_SORT_ORDER "std:sort_order" /* int32 */
/* Entity tags, used to avoid missing updates on save */
#define G_FILE_ATTRIBUTE_ETAG_VALUE "etag:value" /* string */
/* File identifier, for e.g. avoiding loops when doing recursive directory scanning */
#define G_FILE_ATTRIBUTE_ID_FILE "id:file" /* string */
#define G_FILE_ATTRIBUTE_ID_FS "id:fs" /* string */
/* Calculated Access Rights for current user */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_READ "access:can_read" /* boolean */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "access:can_write" /* boolean */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE "access:can_execute" /* boolean */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE "access:can_delete" /* boolean */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH "access:can_trash" /* boolean */
#define G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME "access:can_rename" /* boolean */
/* TODO: Should we have special version for directories? can_enumerate, etc */
/* Mountable attributes */
#define G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT "mountable:can_mount" /* boolean */
#define G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT "mountable:can_unmount" /* boolean */
#define G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT "mountable:can_eject" /* boolean */
#define G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE "mountable:unix_device" /* uint32 */
#define G_FILE_ATTRIBUTE_MOUNTABLE_HAL_UDI "mountable:hal_udi" /* string */
/* Time attributes */
/* The last time the file content or an attribute was modified */
#define G_FILE_ATTRIBUTE_TIME_MODIFIED "time:modified" /* uint64 */
#define G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC "time:modified_usec" /* uint32 */
/* The last time the file was read */
#define G_FILE_ATTRIBUTE_TIME_ACCESS "time:access" /* uint64 */
#define G_FILE_ATTRIBUTE_TIME_ACCESS_USEC "time:access_usec" /* uint32 */
/* The last time a file attribute was changed (e.g. unix ctime) */
#define G_FILE_ATTRIBUTE_TIME_CHANGED "time:changed" /* uint64 */
#define G_FILE_ATTRIBUTE_TIME_CHANGED_USEC "time:changed_usec" /* uint32 */
/* When the file was originally created (e.g. ntfs ctime) */
#define G_FILE_ATTRIBUTE_TIME_CREATED "time:created" /* uint64 */
#define G_FILE_ATTRIBUTE_TIME_CREATED_USEC "time:created_usec" /* uint32 */
/* Unix specific attributes */
#define G_FILE_ATTRIBUTE_UNIX_DEVICE "unix:device" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_INODE "unix:inode" /* uint64 */
#define G_FILE_ATTRIBUTE_UNIX_MODE "unix:mode" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_NLINK "unix:nlink" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_UID "unix:uid" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_GID "unix:gid" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_RDEV "unix:rdev" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE "unix:block_size" /* uint32 */
#define G_FILE_ATTRIBUTE_UNIX_BLOCKS "unix:blocks" /* uint64 */
#define G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT "unix:is_mountpoint" /* boolean */
/* DOS specific attributes */
#define G_FILE_ATTRIBUTE_DOS_IS_ARCHIVE "dos:is_archive" /* boolean */
#define G_FILE_ATTRIBUTE_DOS_IS_SYSTEM "dos:is_system" /* boolean */
/* Owner attributes */
#define G_FILE_ATTRIBUTE_OWNER_USER "owner:user" /* string */
#define G_FILE_ATTRIBUTE_OWNER_USER_REAL "owner:user_real" /* string */
#define G_FILE_ATTRIBUTE_OWNER_GROUP "owner:group" /* string */
/* Thumbnails */
#define G_FILE_ATTRIBUTE_THUMBNAIL_PATH "thumbnail:path" /* bytestring */
#define G_FILE_ATTRIBUTE_THUMBNAILING_FAILED "thumbnail:failed" /* bytestring */
/* File system info (for g_file_get_filesystem_info) */
#define G_FILE_ATTRIBUTE_FS_SIZE "fs:size" /* uint64 */
#define G_FILE_ATTRIBUTE_FS_FREE "fs:free" /* uint64 */
#define G_FILE_ATTRIBUTE_FS_TYPE "fs:type" /* string */
#define G_FILE_ATTRIBUTE_FS_READONLY "fs:readonly" /* boolean */
#define G_FILE_ATTRIBUTE_GVFS_BACKEND "gvfs:backend" /* string */
GType g_file_info_get_type (void) G_GNUC_CONST;
GFileInfo * g_file_info_new (void);
GFileInfo * g_file_info_dup (GFileInfo *other);
void g_file_info_copy_into (GFileInfo *src_info,
GFileInfo *dest_info);
gboolean g_file_info_has_attribute (GFileInfo *info,
const char *attribute);
char ** g_file_info_list_attributes (GFileInfo *info,
const char *name_space);
GFileAttributeType g_file_info_get_attribute_type (GFileInfo *info,
const char *attribute);
void g_file_info_remove_attribute (GFileInfo *info,
const char *attribute);
GFileAttributeValue * g_file_info_get_attribute (GFileInfo *info,
const char *attribute);
const char * g_file_info_get_attribute_string (GFileInfo *info,
const char *attribute);
const char * g_file_info_get_attribute_byte_string (GFileInfo *info,
const char *attribute);
gboolean g_file_info_get_attribute_boolean (GFileInfo *info,
const char *attribute);
guint32 g_file_info_get_attribute_uint32 (GFileInfo *info,
const char *attribute);
gint32 g_file_info_get_attribute_int32 (GFileInfo *info,
const char *attribute);
guint64 g_file_info_get_attribute_uint64 (GFileInfo *info,
const char *attribute);
gint64 g_file_info_get_attribute_int64 (GFileInfo *info,
const char *attribute);
GObject * g_file_info_get_attribute_object (GFileInfo *info,
const char *attribute);
void g_file_info_set_attribute (GFileInfo *info,
const char *attribute,
const GFileAttributeValue *attr_value);
void g_file_info_set_attribute_string (GFileInfo *info,
const char *attribute,
const char *attr_value);
void g_file_info_set_attribute_byte_string (GFileInfo *info,
const char *attribute,
const char *attr_value);
void g_file_info_set_attribute_boolean (GFileInfo *info,
const char *attribute,
gboolean attr_value);
void g_file_info_set_attribute_uint32 (GFileInfo *info,
const char *attribute,
guint32 attr_value);
void g_file_info_set_attribute_int32 (GFileInfo *info,
const char *attribute,
gint32 attr_value);
void g_file_info_set_attribute_uint64 (GFileInfo *info,
const char *attribute,
guint64 attr_value);
void g_file_info_set_attribute_int64 (GFileInfo *info,
const char *attribute,
gint64 attr_value);
void g_file_info_set_attribute_object (GFileInfo *info,
const char *attribute,
GObject *attr_value);
void g_file_info_clear_status (GFileInfo *info);
/* Helper getters: */
GFileType g_file_info_get_file_type (GFileInfo *info);
gboolean g_file_info_get_is_hidden (GFileInfo *info);
gboolean g_file_info_get_is_backup (GFileInfo *info);
gboolean g_file_info_get_is_symlink (GFileInfo *info);
const char * g_file_info_get_name (GFileInfo *info);
const char * g_file_info_get_display_name (GFileInfo *info);
const char * g_file_info_get_edit_name (GFileInfo *info);
GIcon * g_file_info_get_icon (GFileInfo *info);
const char * g_file_info_get_content_type (GFileInfo *info);
goffset g_file_info_get_size (GFileInfo *info);
void g_file_info_get_modification_time (GFileInfo *info,
GTimeVal *result);
const char * g_file_info_get_symlink_target (GFileInfo *info);
const char * g_file_info_get_etag (GFileInfo *info);
gint32 g_file_info_get_sort_order (GFileInfo *info);
void g_file_info_set_attribute_mask (GFileInfo *info,
GFileAttributeMatcher *mask);
void g_file_info_unset_attribute_mask (GFileInfo *info);
/* Helper setters: */
void g_file_info_set_file_type (GFileInfo *info,
GFileType type);
void g_file_info_set_is_hidden (GFileInfo *info,
gboolean is_hidden);
void g_file_info_set_is_symlink (GFileInfo *info,
gboolean is_symlink);
void g_file_info_set_name (GFileInfo *info,
const char *name);
void g_file_info_set_display_name (GFileInfo *info,
const char *display_name);
void g_file_info_set_edit_name (GFileInfo *info,
const char *edit_name);
void g_file_info_set_icon (GFileInfo *info,
GIcon *icon);
void g_file_info_set_content_type (GFileInfo *info,
const char *content_type);
void g_file_info_set_size (GFileInfo *info,
goffset size);
void g_file_info_set_modification_time (GFileInfo *info,
GTimeVal *mtime);
void g_file_info_set_symlink_target (GFileInfo *info,
const char *symlink_target);
void g_file_info_set_sort_order (GFileInfo *info,
gint32 sort_order);
/* Helper functions for attributes: */
/* TODO: Move this to glib when merging */
char *g_format_file_size_for_display (goffset size);
GFileAttributeMatcher *g_file_attribute_matcher_new (const char *attributes);
GFileAttributeMatcher *g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher);
void g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher);
gboolean g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
const char *attribute);
gboolean g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
const char *attribute);
gboolean g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
const char *ns);
const char * g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher);
G_END_DECLS
#endif /* __G_FILE_INFO_H__ */

481
gio/gfileinputstream.c Normal file
View File

@ -0,0 +1,481 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <glib.h>
#include <gfileinputstream.h>
#include <gseekable.h>
#include "gsimpleasyncresult.h"
#include "glibintl.h"
static void g_file_input_stream_seekable_iface_init (GSeekableIface *iface);
static goffset g_file_input_stream_seekable_tell (GSeekable *seekable);
static gboolean g_file_input_stream_seekable_can_seek (GSeekable *seekable);
static gboolean g_file_input_stream_seekable_seek (GSeekable *seekable,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
static gboolean g_file_input_stream_seekable_can_truncate (GSeekable *seekable);
static gboolean g_file_input_stream_seekable_truncate (GSeekable *seekable,
goffset offset,
GCancellable *cancellable,
GError **error);
static void g_file_input_stream_real_query_info_async (GFileInputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static GFileInfo *g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
GAsyncResult *result,
GError **error);
G_DEFINE_TYPE_WITH_CODE (GFileInputStream, g_file_input_stream, G_TYPE_INPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
g_file_input_stream_seekable_iface_init))
struct _GFileInputStreamPrivate {
GAsyncReadyCallback outstanding_callback;
};
static void
g_file_input_stream_class_init (GFileInputStreamClass *klass)
{
g_type_class_add_private (klass, sizeof (GFileInputStreamPrivate));
klass->query_info_async = g_file_input_stream_real_query_info_async;
klass->query_info_finish = g_file_input_stream_real_query_info_finish;
}
static void
g_file_input_stream_seekable_iface_init (GSeekableIface *iface)
{
iface->tell = g_file_input_stream_seekable_tell;
iface->can_seek = g_file_input_stream_seekable_can_seek;
iface->seek = g_file_input_stream_seekable_seek;
iface->can_truncate = g_file_input_stream_seekable_can_truncate;
iface->truncate = g_file_input_stream_seekable_truncate;
}
static void
g_file_input_stream_init (GFileInputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_FILE_INPUT_STREAM,
GFileInputStreamPrivate);
}
/**
* g_file_input_stream_query_info:
* @stream:
* @attributes:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
GFileInfo *
g_file_input_stream_query_info (GFileInputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error)
{
GFileInputStreamClass *class;
GInputStream *input_stream;
GFileInfo *info;
g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
input_stream = G_INPUT_STREAM (stream);
if (g_input_stream_is_closed (input_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return NULL;
}
if (g_input_stream_has_pending (input_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return NULL;
}
info = NULL;
g_input_stream_set_pending (input_stream, TRUE);
if (cancellable)
g_push_current_cancellable (cancellable);
class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
if (class->query_info)
info = class->query_info (stream, attributes, cancellable, error);
else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Stream doesn't support query_info"));
if (cancellable)
g_pop_current_cancellable (cancellable);
g_input_stream_set_pending (input_stream, FALSE);
return info;
}
static void
async_ready_callback_wrapper (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GFileInputStream *stream = G_FILE_INPUT_STREAM (source_object);
g_input_stream_set_pending (G_INPUT_STREAM (stream), FALSE);
if (stream->priv->outstanding_callback)
(*stream->priv->outstanding_callback) (source_object, res, user_data);
g_object_unref (stream);
}
/**
* g_file_input_stream_query_info_async:
* @stream:
* @attributes:
* @io_priority: the io priority of the request.
* @cancellable: optional #GCancellable object, %NULL to ignore. @callback:
* @user_data:
*
**/
void
g_file_input_stream_query_info_async (GFileInputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFileInputStreamClass *klass;
GInputStream *input_stream;
g_return_if_fail (G_IS_FILE_INPUT_STREAM (stream));
input_stream = G_INPUT_STREAM (stream);
if (g_input_stream_is_closed (input_stream))
{
g_simple_async_report_error_in_idle (G_OBJECT (stream),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return;
}
if (g_input_stream_has_pending (input_stream))
{
g_simple_async_report_error_in_idle (G_OBJECT (stream),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return;
}
klass = G_FILE_INPUT_STREAM_GET_CLASS (stream);
g_input_stream_set_pending (input_stream, TRUE);
stream->priv->outstanding_callback = callback;
g_object_ref (stream);
klass->query_info_async (stream, attributes, io_priority, cancellable,
async_ready_callback_wrapper, user_data);
}
/**
* g_file_input_stream_query_info_finish:
* @stream:
* @result:
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns: #GFileInfo.
**/
GFileInfo *
g_file_input_stream_query_info_finish (GFileInputStream *stream,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
GFileInputStreamClass *class;
g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
}
class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
return class->query_info_finish (stream, result, error);
}
/**
* g_file_input_stream_tell:
* @stream:
*
* Returns:
**/
goffset
g_file_input_stream_tell (GFileInputStream *stream)
{
GFileInputStreamClass *class;
goffset offset;
g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), 0);
class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
offset = 0;
if (class->tell)
offset = class->tell (stream);
return offset;
}
static goffset
g_file_input_stream_seekable_tell (GSeekable *seekable)
{
return g_file_input_stream_tell (G_FILE_INPUT_STREAM (seekable));
}
/**
* g_file_input_stream_can_seek:
* @stream:
*
* Returns: %TRUE if stream can be seeked. %FALSE otherwise.
**/
gboolean
g_file_input_stream_can_seek (GFileInputStream *stream)
{
GFileInputStreamClass *class;
gboolean can_seek;
g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
can_seek = FALSE;
if (class->seek)
{
can_seek = TRUE;
if (class->can_seek)
can_seek = class->can_seek (stream);
}
return can_seek;
}
static gboolean
g_file_input_stream_seekable_can_seek (GSeekable *seekable)
{
return g_file_input_stream_can_seek (G_FILE_INPUT_STREAM (seekable));
}
/**
* g_file_input_stream_seek:
* @stream:
* @offset:
* @type:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
gboolean
g_file_input_stream_seek (GFileInputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
GFileInputStreamClass *class;
GInputStream *input_stream;
gboolean res;
g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
input_stream = G_INPUT_STREAM (stream);
class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
if (g_input_stream_is_closed (input_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return FALSE;
}
if (g_input_stream_has_pending (input_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return FALSE;
}
if (!class->seek)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Seek not supported on stream"));
return FALSE;
}
g_input_stream_set_pending (input_stream, TRUE);
if (cancellable)
g_push_current_cancellable (cancellable);
res = class->seek (stream, offset, type, cancellable, error);
if (cancellable)
g_pop_current_cancellable (cancellable);
g_input_stream_set_pending (input_stream, FALSE);
return res;
}
static gboolean
g_file_input_stream_seekable_seek (GSeekable *seekable,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable),
offset, type, cancellable, error);
}
static gboolean
g_file_input_stream_seekable_can_truncate (GSeekable *seekable)
{
return FALSE;
}
static gboolean
g_file_input_stream_seekable_truncate (GSeekable *seekable,
goffset offset,
GCancellable *cancellable,
GError **error)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Truncate not allowed on input stream"));
return FALSE;
}
/********************************************
* Default implementation of async ops *
********************************************/
typedef struct {
char *attributes;
GFileInfo *info;
} QueryInfoAsyncData;
static void
query_info_data_free (QueryInfoAsyncData *data)
{
if (data->info)
g_object_unref (data->info);
g_free (data->attributes);
g_free (data);
}
static void
query_info_async_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GFileInputStreamClass *class;
GError *error = NULL;
QueryInfoAsyncData *data;
GFileInfo *info;
data = g_simple_async_result_get_op_res_gpointer (res);
info = NULL;
class = G_FILE_INPUT_STREAM_GET_CLASS (object);
if (class->query_info)
info = class->query_info (G_FILE_INPUT_STREAM (object), data->attributes, cancellable, &error);
else
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Stream doesn't support query_info"));
if (info == NULL)
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
else
data->info = info;
}
static void
g_file_input_stream_real_query_info_async (GFileInputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
QueryInfoAsyncData *data;
data = g_new0 (QueryInfoAsyncData, 1);
data->attributes = g_strdup (attributes);
res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_file_input_stream_real_query_info_async);
g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_info_data_free);
g_simple_async_result_run_in_thread (res, query_info_async_thread, io_priority, cancellable);
g_object_unref (res);
}
static GFileInfo *
g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
QueryInfoAsyncData *data;
g_assert (g_simple_async_result_get_source_tag (simple) == g_file_input_stream_real_query_info_async);
data = g_simple_async_result_get_op_res_gpointer (simple);
if (data->info)
return g_object_ref (data->info);
return NULL;
}

110
gio/gfileinputstream.h Normal file
View File

@ -0,0 +1,110 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_INPUT_STREAM_H__
#define __G_FILE_INPUT_STREAM_H__
#include <gio/ginputstream.h>
#include <gio/gfileinfo.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_INPUT_STREAM (g_file_input_stream_get_type ())
#define G_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_INPUT_STREAM, GFileInputStream))
#define G_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_INPUT_STREAM, GFileInputStreamClass))
#define G_IS_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_INPUT_STREAM))
#define G_IS_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_INPUT_STREAM))
#define G_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_INPUT_STREAM, GFileInputStreamClass))
typedef struct _GFileInputStream GFileInputStream;
typedef struct _GFileInputStreamClass GFileInputStreamClass;
typedef struct _GFileInputStreamPrivate GFileInputStreamPrivate;
struct _GFileInputStream
{
GInputStream parent;
/*< private >*/
GFileInputStreamPrivate *priv;
};
struct _GFileInputStreamClass
{
GInputStreamClass parent_class;
goffset (*tell) (GFileInputStream *stream);
gboolean (*can_seek) (GFileInputStream *stream);
gboolean (*seek) (GFileInputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
GFileInfo *(*query_info) (GFileInputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
void (*query_info_async) (GFileInputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo *(*query_info_finish) (GFileInputStream *stream,
GAsyncResult *res,
GError **error);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_file_input_stream_get_type (void) G_GNUC_CONST;
GFileInfo *g_file_input_stream_query_info (GFileInputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
void g_file_input_stream_query_info_async (GFileInputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo *g_file_input_stream_query_info_finish (GFileInputStream *stream,
GAsyncResult *result,
GError **error);
goffset g_file_input_stream_tell (GFileInputStream *stream);
gboolean g_file_input_stream_can_seek (GFileInputStream *stream);
gboolean g_file_input_stream_seek (GFileInputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_FILE_FILE_INPUT_STREAM_H__ */

380
gio/gfilemonitor.c Normal file
View File

@ -0,0 +1,380 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <string.h>
#include "gfilemonitor.h"
#include "gio-marshal.h"
#include "gvfs.h"
#include "glibintl.h"
enum {
CHANGED,
LAST_SIGNAL
};
G_DEFINE_ABSTRACT_TYPE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT);
struct _GFileMonitorPrivate {
gboolean cancelled;
int rate_limit_msec;
/* Rate limiting change events */
guint32 last_sent_change_time; /* Some monitonic clock in msecs */
GFile *last_sent_change_file;
guint send_delayed_change_timeout;
/* Virtual CHANGES_DONE_HINT emission */
GSource *virtual_changes_done_timeout;
GFile *virtual_changes_done_file;
};
#define DEFAULT_RATE_LIMIT_MSECS 800
#define DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS 2
static guint signals[LAST_SIGNAL] = { 0 };
static void
g_file_monitor_finalize (GObject *object)
{
GFileMonitor *monitor;
monitor = G_FILE_MONITOR (object);
if (monitor->priv->last_sent_change_file)
g_object_unref (monitor->priv->last_sent_change_file);
if (monitor->priv->send_delayed_change_timeout != 0)
g_source_remove (monitor->priv->send_delayed_change_timeout);
if (monitor->priv->virtual_changes_done_file)
g_object_unref (monitor->priv->virtual_changes_done_file);
if (monitor->priv->virtual_changes_done_timeout)
g_source_destroy (monitor->priv->virtual_changes_done_timeout);
if (G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize) (object);
}
static void
g_file_monitor_dispose (GObject *object)
{
GFileMonitor *monitor;
monitor = G_FILE_MONITOR (object);
/* Make sure we cancel on last unref */
if (!monitor->priv->cancelled)
g_file_monitor_cancel (monitor);
if (G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose)
(*G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose) (object);
}
static void
g_file_monitor_class_init (GFileMonitorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (GFileMonitorPrivate));
gobject_class->finalize = g_file_monitor_finalize;
gobject_class->dispose = g_file_monitor_dispose;
signals[CHANGED] =
g_signal_new (I_("changed"),
G_TYPE_FILE_MONITOR,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GFileMonitorClass, changed),
NULL, NULL,
_gio_marshal_VOID__OBJECT_OBJECT_INT,
G_TYPE_NONE,3,
G_TYPE_FILE,
G_TYPE_FILE,
G_TYPE_INT);
}
static void
g_file_monitor_init (GFileMonitor *monitor)
{
monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
G_TYPE_FILE_MONITOR,
GFileMonitorPrivate);
monitor->priv->rate_limit_msec = DEFAULT_RATE_LIMIT_MSECS;
}
/**
* g_file_monitor_is_cancelled:
* @monitor:
*
* Returns: %TRUE if monitor is canceled. %FALSE otherwise.
**/
gboolean
g_file_monitor_is_cancelled (GFileMonitor *monitor)
{
g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
return monitor->priv->cancelled;
}
/**
* g_file_monitor_cancel:
* @monitor:
*
* Returns: %TRUE if monitor was cancelled.
**/
gboolean
g_file_monitor_cancel (GFileMonitor* monitor)
{
GFileMonitorClass *klass;
g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
if (monitor->priv->cancelled)
return TRUE;
monitor->priv->cancelled = TRUE;
klass = G_FILE_MONITOR_GET_CLASS (monitor);
return (* klass->cancel) (monitor);
}
/**
* g_file_monitor_set_rate_limit:
* @monitor: a #GFileMonitor.
* @limit_msecs: a integer with the limit in milliseconds to
* poll for changes.
*
* Sets the rate limit to which the @monitor will poll for changes
* on the device.
*
**/
void
g_file_monitor_set_rate_limit (GFileMonitor *monitor,
int limit_msecs)
{
g_return_if_fail (G_IS_FILE_MONITOR (monitor));
monitor->priv->rate_limit_msec = limit_msecs;
}
static guint32
get_time_msecs (void)
{
return g_thread_gettime() / (1000 * 1000);
}
static guint32
time_difference (guint32 from, guint32 to)
{
if (from > to)
return 0;
return to - from;
}
/* Change event rate limiting support: */
static void
update_last_sent_change (GFileMonitor *monitor, GFile *file, guint32 time_now)
{
if (monitor->priv->last_sent_change_file != file)
{
if (monitor->priv->last_sent_change_file)
{
g_object_unref (monitor->priv->last_sent_change_file);
monitor->priv->last_sent_change_file = NULL;
}
if (file)
monitor->priv->last_sent_change_file = g_object_ref (file);
}
monitor->priv->last_sent_change_time = time_now;
}
static void
send_delayed_change_now (GFileMonitor *monitor)
{
if (monitor->priv->send_delayed_change_timeout)
{
g_signal_emit (monitor, signals[CHANGED], 0,
monitor->priv->last_sent_change_file, NULL,
G_FILE_MONITOR_EVENT_CHANGED);
g_source_remove (monitor->priv->send_delayed_change_timeout);
monitor->priv->send_delayed_change_timeout = 0;
/* Same file, new last_sent time */
monitor->priv->last_sent_change_time = get_time_msecs ();
}
}
static gboolean
delayed_changed_event_timeout (gpointer data)
{
GFileMonitor *monitor = data;
send_delayed_change_now (monitor);
return FALSE;
}
static void
schedule_delayed_change (GFileMonitor *monitor, GFile *file, guint32 delay_msec)
{
if (monitor->priv->send_delayed_change_timeout == 0) /* Only set the timeout once */
{
monitor->priv->send_delayed_change_timeout =
g_timeout_add (delay_msec, delayed_changed_event_timeout, monitor);
}
}
static void
cancel_delayed_change (GFileMonitor *monitor)
{
if (monitor->priv->send_delayed_change_timeout != 0)
{
g_source_remove (monitor->priv->send_delayed_change_timeout);
monitor->priv->send_delayed_change_timeout = 0;
}
}
/* Virtual changes_done_hint support: */
static void
send_virtual_changes_done_now (GFileMonitor *monitor)
{
if (monitor->priv->virtual_changes_done_timeout)
{
g_signal_emit (monitor, signals[CHANGED], 0,
monitor->priv->virtual_changes_done_file, NULL,
G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
g_source_destroy (monitor->priv->virtual_changes_done_timeout);
monitor->priv->virtual_changes_done_timeout = NULL;
g_object_unref (monitor->priv->virtual_changes_done_file);
monitor->priv->virtual_changes_done_file = NULL;
}
}
static gboolean
virtual_changes_done_timeout (gpointer data)
{
GFileMonitor *monitor = data;
send_virtual_changes_done_now (monitor);
return FALSE;
}
static void
schedule_virtual_change_done (GFileMonitor *monitor, GFile *file)
{
GSource *source;
source = g_timeout_source_new_seconds (DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS);
g_source_set_callback (source, virtual_changes_done_timeout, monitor, NULL);
g_source_attach (source, NULL);
monitor->priv->virtual_changes_done_timeout = source;
monitor->priv->virtual_changes_done_file = g_object_ref (file);
g_source_unref (source);
}
static void
cancel_virtual_changes_done (GFileMonitor *monitor)
{
if (monitor->priv->virtual_changes_done_timeout)
{
g_source_destroy (monitor->priv->virtual_changes_done_timeout);
monitor->priv->virtual_changes_done_timeout = NULL;
g_object_unref (monitor->priv->virtual_changes_done_file);
monitor->priv->virtual_changes_done_file = NULL;
}
}
/**
* g_file_monitor_emit_event:
* @monitor:
* @file:
* @other_file:
* @event_type:
*
**/
void
g_file_monitor_emit_event (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type)
{
guint32 time_now, since_last;
gboolean emit_now;
g_return_if_fail (G_IS_FILE_MONITOR (monitor));
g_return_if_fail (G_IS_FILE (file));
if (event_type != G_FILE_MONITOR_EVENT_CHANGED)
{
send_delayed_change_now (monitor);
update_last_sent_change (monitor, NULL, 0);
if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
cancel_virtual_changes_done (monitor);
else
send_virtual_changes_done_now (monitor);
g_signal_emit (monitor, signals[CHANGED], 0, file, other_file, event_type);
}
else
{
time_now = get_time_msecs ();
emit_now = TRUE;
if (monitor->priv->last_sent_change_file)
{
since_last = time_difference (monitor->priv->last_sent_change_time, time_now);
if (since_last < monitor->priv->rate_limit_msec)
{
/* We ignore this change, but arm a timer so that we can fire it later if we
don't get any other events (that kill this timeout) */
emit_now = FALSE;
schedule_delayed_change (monitor, file,
monitor->priv->rate_limit_msec - since_last);
}
}
if (emit_now)
{
g_signal_emit (monitor, signals[CHANGED], 0, file, other_file, event_type);
cancel_delayed_change (monitor);
update_last_sent_change (monitor, file, time_now);
}
/* Schedule a virtual change done. This is removed if we get a real one, and
postponed if we get more change events. */
cancel_virtual_changes_done (monitor);
schedule_virtual_change_done (monitor, file);
}
}

97
gio/gfilemonitor.h Normal file
View File

@ -0,0 +1,97 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_MONITOR_H__
#define __G_FILE_MONITOR_H__
#include <glib-object.h>
#include <gio/gfile.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_MONITOR (g_file_monitor_get_type ())
#define G_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_MONITOR, GFileMonitor))
#define G_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_MONITOR, GFileMonitorClass))
#define G_IS_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_MONITOR))
#define G_IS_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_MONITOR))
#define G_FILE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_MONITOR, GFileMonitorClass))
typedef enum {
G_FILE_MONITOR_EVENT_CHANGED,
G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT,
G_FILE_MONITOR_EVENT_DELETED,
G_FILE_MONITOR_EVENT_CREATED,
G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED,
G_FILE_MONITOR_EVENT_PRE_UNMOUNT,
G_FILE_MONITOR_EVENT_UNMOUNTED
} GFileMonitorEvent;
typedef struct _GFileMonitorClass GFileMonitorClass;
typedef struct _GFileMonitorPrivate GFileMonitorPrivate;
struct _GFileMonitor
{
GObject parent;
/*< private >*/
GFileMonitorPrivate *priv;
};
struct _GFileMonitorClass
{
GObjectClass parent_class;
/* Signals */
void (* changed) (GFileMonitor* monitor,
GFile* file,
GFile* other_file,
GFileMonitorEvent event_type);
/* Virtual Table */
gboolean (*cancel)(GFileMonitor* monitor);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_file_monitor_get_type (void) G_GNUC_CONST;
gboolean g_file_monitor_cancel (GFileMonitor *monitor);
gboolean g_file_monitor_is_cancelled (GFileMonitor *monitor);
void g_file_monitor_set_rate_limit (GFileMonitor *monitor,
int limit_msecs);
/* For implementations */
void g_file_monitor_emit_event (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type);
G_END_DECLS
#endif /* __G_FILE_MONITOR_H__ */

489
gio/gfilenamecompleter.c Normal file
View File

@ -0,0 +1,489 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gfilenamecompleter.h"
#include "gurifuncs.h"
#include "gfile.h"
#include <string.h>
#include "glibintl.h"
enum {
GOT_COMPLETION_DATA,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
GFilenameCompleter *completer;
GFileEnumerator *enumerator;
GCancellable *cancellable;
gboolean should_escape;
GFile *dir;
GList *basenames;
gboolean dirs_only;
} LoadBasenamesData;
struct _GFilenameCompleter {
GObject parent;
GFile *basenames_dir;
gboolean basenames_are_escaped;
GList *basenames;
gboolean dirs_only;
LoadBasenamesData *basename_loader;
};
G_DEFINE_TYPE (GFilenameCompleter, g_filename_completer, G_TYPE_OBJECT);
static void cancel_load_basenames (GFilenameCompleter *completer);
static void
g_filename_completer_finalize (GObject *object)
{
GFilenameCompleter *completer;
completer = G_FILENAME_COMPLETER (object);
cancel_load_basenames (completer);
if (completer->basenames_dir)
g_object_unref (completer->basenames_dir);
g_list_foreach (completer->basenames, (GFunc)g_free, NULL);
g_list_free (completer->basenames);
if (G_OBJECT_CLASS (g_filename_completer_parent_class)->finalize)
(*G_OBJECT_CLASS (g_filename_completer_parent_class)->finalize) (object);
}
static void
g_filename_completer_class_init (GFilenameCompleterClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_filename_completer_finalize;
signals[GOT_COMPLETION_DATA] = g_signal_new (I_("got_completion_data"),
G_TYPE_FILENAME_COMPLETER,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GFilenameCompleterClass, got_completion_data),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
g_filename_completer_init (GFilenameCompleter *completer)
{
}
/**
* g_filename_completer_new:
*
* Returns: a new #GFilenameCompleter.
**/
GFilenameCompleter *
g_filename_completer_new (void)
{
return g_object_new (G_TYPE_FILENAME_COMPLETER, NULL);
}
static char *
longest_common_prefix (char *a, char *b)
{
char *start;
start = a;
while (g_utf8_get_char (a) == g_utf8_get_char (b))
{
a = g_utf8_next_char (a);
b = g_utf8_next_char (b);
}
return g_strndup (start, a - start);
}
static void
load_basenames_data_free (LoadBasenamesData *data)
{
if (data->enumerator)
g_object_unref (data->enumerator);
g_object_unref (data->cancellable);
g_object_unref (data->dir);
g_list_foreach (data->basenames, (GFunc)g_free, NULL);
g_list_free (data->basenames);
g_free (data);
}
static void
got_more_files (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
LoadBasenamesData *data = user_data;
GList *infos, *l;
GFileInfo *info;
const char *name;
gboolean append_slash;
char *t;
char *basename;
if (data->completer == NULL)
{
/* Was cancelled */
load_basenames_data_free (data);
return;
}
infos = g_file_enumerator_next_files_finish (data->enumerator, res, NULL);
for (l = infos; l != NULL; l = l->next)
{
info = l->data;
if (data->dirs_only &&
g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)
{
g_object_unref (info);
continue;
}
append_slash = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
name = g_file_info_get_name (info);
if (name == NULL)
{
g_object_unref (info);
continue;
}
if (data->should_escape)
basename = g_uri_escape_string (name,
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,
TRUE);
else
/* If not should_escape, must be a local filename, convert to utf8 */
basename = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
if (basename)
{
if (append_slash)
{
t = basename;
basename = g_strconcat (basename, "/", NULL);
g_free (t);
}
data->basenames = g_list_prepend (data->basenames, basename);
}
g_object_unref (info);
}
g_list_free (infos);
if (infos)
{
/* Not last, get more files */
g_file_enumerator_next_files_async (data->enumerator,
100,
0,
data->cancellable,
got_more_files, data);
}
else
{
data->completer->basename_loader = NULL;
if (data->completer->basenames_dir)
g_object_unref (data->completer->basenames_dir);
g_list_foreach (data->completer->basenames, (GFunc)g_free, NULL);
g_list_free (data->completer->basenames);
data->completer->basenames_dir = g_object_ref (data->dir);
data->completer->basenames = data->basenames;
data->completer->basenames_are_escaped = data->should_escape;
data->basenames = NULL;
g_file_enumerator_close_async (data->enumerator, 0, NULL, NULL, NULL);
g_signal_emit (data->completer, signals[GOT_COMPLETION_DATA], 0);
load_basenames_data_free (data);
}
}
static void
got_enum (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
LoadBasenamesData *data = user_data;
if (data->completer == NULL)
{
/* Was cancelled */
load_basenames_data_free (data);
return;
}
data->enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, NULL);
if (data->enumerator == NULL)
{
data->completer->basename_loader = NULL;
if (data->completer->basenames_dir)
g_object_unref (data->completer->basenames_dir);
g_list_foreach (data->completer->basenames, (GFunc)g_free, NULL);
g_list_free (data->completer->basenames);
/* Mark uptodate with no basenames */
data->completer->basenames_dir = g_object_ref (data->dir);
data->completer->basenames = NULL;
data->completer->basenames_are_escaped = data->should_escape;
load_basenames_data_free (data);
return;
}
g_file_enumerator_next_files_async (data->enumerator,
100,
0,
data->cancellable,
got_more_files, data);
}
static void
schedule_load_basenames (GFilenameCompleter *completer,
GFile *dir,
gboolean should_escape)
{
LoadBasenamesData *data;
cancel_load_basenames (completer);
data = g_new0 (LoadBasenamesData, 1);
data->completer = completer;
data->cancellable = g_cancellable_new ();
data->dir = g_object_ref (dir);
data->should_escape = should_escape;
data->dirs_only = completer->dirs_only;
completer->basename_loader = data;
g_file_enumerate_children_async (dir,
G_FILE_ATTRIBUTE_STD_NAME "," G_FILE_ATTRIBUTE_STD_TYPE,
0, 0,
data->cancellable,
got_enum, data);
}
static void
cancel_load_basenames (GFilenameCompleter *completer)
{
LoadBasenamesData *loader;
if (completer->basename_loader)
{
loader = completer->basename_loader;
loader->completer = NULL;
g_cancellable_cancel (loader->cancellable);
completer->basename_loader = NULL;
}
}
/* Returns a list of possible matches and the basename to use for it */
static GList *
init_completion (GFilenameCompleter *completer,
const char *initial_text,
char **basename_out)
{
gboolean should_escape;
GFile *file, *parent;
char *basename;
char *t;
int len;
*basename_out = NULL;
should_escape = ! (g_path_is_absolute (initial_text) || *initial_text == '~');
len = strlen (initial_text);
if (len > 0 &&
initial_text[len - 1] == '/')
return NULL;
file = g_file_parse_name (initial_text);
parent = g_file_get_parent (file);
if (parent == NULL)
{
g_object_unref (file);
return NULL;
}
if (completer->basenames_dir == NULL ||
completer->basenames_are_escaped != should_escape ||
!g_file_equal (parent, completer->basenames_dir))
{
schedule_load_basenames (completer, parent, should_escape);
g_object_unref (file);
return NULL;
}
basename = g_file_get_basename (file);
if (should_escape)
{
t = basename;
basename = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
g_free (t);
}
else
{
t = basename;
basename = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
g_free (t);
if (basename == NULL)
return NULL;
}
*basename_out = basename;
return completer->basenames;
}
/**
* g_filename_completer_get_completion_suffix:
* @completer: the filename completer.
* @initial_text: text to be completed.
*
* Returns: a completed string. This string is not owned by GIO, so
* remember to g_free() it when finished.
**/
char *
g_filename_completer_get_completion_suffix (GFilenameCompleter *completer,
const char *initial_text)
{
GList *possible_matches, *l;
char *prefix;
char *suffix;
char *possible_match;
char *lcp;
g_return_val_if_fail (G_IS_FILENAME_COMPLETER (completer), NULL);
g_return_val_if_fail (initial_text != NULL, NULL);
possible_matches = init_completion (completer, initial_text, &prefix);
suffix = NULL;
for (l = possible_matches; l != NULL; l = l->next)
{
possible_match = l->data;
if (g_str_has_prefix (possible_match, prefix))
{
if (suffix == NULL)
suffix = g_strdup (possible_match + strlen (prefix));
else
{
lcp = longest_common_prefix (suffix,
possible_match + strlen (prefix));
g_free (suffix);
suffix = lcp;
if (*suffix == 0)
break;
}
}
}
g_free (prefix);
return suffix;
}
/**
* g_filename_completer_get_completions:
* @completer: the filename completer.
* @initial_text: text to be completed.
*
* Returns: array of strings with possible completions for @initial_text.
* This array must be freed by g_strfreev() when finished.
**/
char **
g_filename_completer_get_completions (GFilenameCompleter *completer,
const char *initial_text)
{
GList *possible_matches, *l;
char *prefix;
char *possible_match;
GPtrArray *res;
g_return_val_if_fail (G_IS_FILENAME_COMPLETER (completer), NULL);
g_return_val_if_fail (initial_text != NULL, NULL);
possible_matches = init_completion (completer, initial_text, &prefix);
res = g_ptr_array_new ();
for (l = possible_matches; l != NULL; l = l->next)
{
possible_match = l->data;
if (g_str_has_prefix (possible_match, prefix))
g_ptr_array_add (res,
g_strconcat (initial_text, possible_match + strlen (prefix), NULL));
}
g_free (prefix);
return (char**)g_ptr_array_free (res, FALSE);
}
/**
* g_filename_completer_set_dirs_only:
* @completer: the filename completer.
* @dirs_only:
*
* If @dirs_only is %TRUE, @completer will only
* complete directory names, and not file names.
**/
void
g_filename_completer_set_dirs_only (GFilenameCompleter *completer,
gboolean dirs_only)
{
g_return_if_fail (G_IS_FILENAME_COMPLETER (completer));
completer->dirs_only = dirs_only;
}

66
gio/gfilenamecompleter.h Normal file
View File

@ -0,0 +1,66 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILENAME_COMPLETER_H__
#define __G_FILENAME_COMPLETER_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define G_TYPE_FILENAME_COMPLETER (g_filename_completer_get_type ())
#define G_FILENAME_COMPLETER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILENAME_COMPLETER, GFilenameCompleter))
#define G_FILENAME_COMPLETER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILENAME_COMPLETER, GFilenameCompleterClass))
#define G_FILENAME_COMPLETER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILENAME_COMPLETER, GFilenameCompleterClass))
#define G_IS_FILENAME_COMPLETER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILENAME_COMPLETER))
#define G_IS_FILENAME_COMPLETER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILENAME_COMPLETER))
typedef struct _GFilenameCompleter GFilenameCompleter;
typedef struct _GFilenameCompleterClass GFilenameCompleterClass;
struct _GFilenameCompleterClass {
GObjectClass parent_class;
/*< public >*/
/* signals */
void (* got_completion_data) (GFilenameCompleter *filename_completer);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
};
GType g_filename_completer_get_type (void) G_GNUC_CONST;
GFilenameCompleter *g_filename_completer_new (void);
char * g_filename_completer_get_completion_suffix (GFilenameCompleter *completer,
const char *initial_text);
char ** g_filename_completer_get_completions (GFilenameCompleter *completer,
const char *initial_text);
void g_filename_completer_set_dirs_only (GFilenameCompleter *completer,
gboolean dirs_only);
G_END_DECLS
#endif /* __G_FILENAME_COMPLETER_H__ */

613
gio/gfileoutputstream.c Normal file
View File

@ -0,0 +1,613 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <glib.h>
#include <gfileoutputstream.h>
#include <gseekable.h>
#include "gsimpleasyncresult.h"
#include "glibintl.h"
static void g_file_output_stream_seekable_iface_init (GSeekableIface *iface);
static goffset g_file_output_stream_seekable_tell (GSeekable *seekable);
static gboolean g_file_output_stream_seekable_can_seek (GSeekable *seekable);
static gboolean g_file_output_stream_seekable_seek (GSeekable *seekable,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
static gboolean g_file_output_stream_seekable_can_truncate (GSeekable *seekable);
static gboolean g_file_output_stream_seekable_truncate (GSeekable *seekable,
goffset offset,
GCancellable *cancellable,
GError **error);
static void g_file_output_stream_real_query_info_async (GFileOutputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static GFileInfo *g_file_output_stream_real_query_info_finish (GFileOutputStream *stream,
GAsyncResult *result,
GError **error);
G_DEFINE_TYPE_WITH_CODE (GFileOutputStream, g_file_output_stream, G_TYPE_OUTPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
g_file_output_stream_seekable_iface_init));
struct _GFileOutputStreamPrivate {
GAsyncReadyCallback outstanding_callback;
};
static void
g_file_output_stream_class_init (GFileOutputStreamClass *klass)
{
g_type_class_add_private (klass, sizeof (GFileOutputStreamPrivate));
klass->query_info_async = g_file_output_stream_real_query_info_async;
klass->query_info_finish = g_file_output_stream_real_query_info_finish;
}
static void
g_file_output_stream_seekable_iface_init (GSeekableIface *iface)
{
iface->tell = g_file_output_stream_seekable_tell;
iface->can_seek = g_file_output_stream_seekable_can_seek;
iface->seek = g_file_output_stream_seekable_seek;
iface->can_truncate = g_file_output_stream_seekable_can_truncate;
iface->truncate = g_file_output_stream_seekable_truncate;
}
static void
g_file_output_stream_init (GFileOutputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_FILE_OUTPUT_STREAM,
GFileOutputStreamPrivate);
}
/**
* g_file_output_stream_query_info:
* @stream: a #GFileOutputStream.
* @attributes:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
*
* * Returns: %NULL or a #GFileInfo for the @stream.
*
* For the asynchronous version of this function, see
* g_file_output_stream_query_info_async().
**/
GFileInfo *
g_file_output_stream_query_info (GFileOutputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error)
{
GFileOutputStreamClass *class;
GOutputStream *output_stream;
GFileInfo *info;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), NULL);
output_stream = G_OUTPUT_STREAM (stream);
if (g_output_stream_is_closed (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return NULL;
}
if (g_output_stream_has_pending (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return NULL;
}
info = NULL;
g_output_stream_set_pending (output_stream, TRUE);
if (cancellable)
g_push_current_cancellable (cancellable);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
if (class->query_info)
info = class->query_info (stream, attributes, cancellable, error);
else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Stream doesn't support query_info"));
if (cancellable)
g_pop_current_cancellable (cancellable);
g_output_stream_set_pending (output_stream, FALSE);
return info;
}
static void
async_ready_callback_wrapper (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GFileOutputStream *stream = G_FILE_OUTPUT_STREAM (source_object);
g_output_stream_set_pending (G_OUTPUT_STREAM (stream), FALSE);
if (stream->priv->outstanding_callback)
(*stream->priv->outstanding_callback) (source_object, res, user_data);
g_object_unref (stream);
}
/**
* g_file_output_stream_query_info_async:
* @stream: a #GFileOutputStream.
* @attributes:
* @io_priority: the io priority of the request.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: a #GAsyncReadyCallback.
* @user_data: user data for @callback.
*
* Asynchronously queries the @stream for a #GFileInfo. When completed,
* @callback will be called with a #GAsyncResult which can be used to
* finish the operation with g_file_output_stream_query_info_finish().
*
* For the synchronous version of this function, see
* g_file_output_stream_query_info().
*
**/
void
g_file_output_stream_query_info_async (GFileOutputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFileOutputStreamClass *klass;
GOutputStream *output_stream;
g_return_if_fail (G_IS_FILE_OUTPUT_STREAM (stream));
output_stream = G_OUTPUT_STREAM (stream);
if (g_output_stream_is_closed (output_stream))
{
g_simple_async_report_error_in_idle (G_OBJECT (stream),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return;
}
if (g_output_stream_has_pending (output_stream))
{
g_simple_async_report_error_in_idle (G_OBJECT (stream),
callback,
user_data,
G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return;
}
klass = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
g_output_stream_set_pending (output_stream, TRUE);
stream->priv->outstanding_callback = callback;
g_object_ref (stream);
klass->query_info_async (stream, attributes, io_priority, cancellable,
async_ready_callback_wrapper, user_data);
}
/**
* g_file_output_stream_query_info_finish:
* @stream: a #GFileOutputStream.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
*
* Finalizes the asynchronous query started
* by g_file_output_stream_query_info_async().
*
* Returns: A #GFileInfo for the finished query.
**/
GFileInfo *
g_file_output_stream_query_info_finish (GFileOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
GFileOutputStreamClass *class;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
if (G_IS_SIMPLE_ASYNC_RESULT (result))
{
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
}
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
return class->query_info_finish (stream, result, error);
}
/**
* g_file_output_stream_get_etag:
* @stream: a #GFileOutputString.
*
* Returns:
**/
char *
g_file_output_stream_get_etag (GFileOutputStream *stream)
{
GFileOutputStreamClass *class;
GOutputStream *output_stream;
char *etag;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), NULL);
output_stream = G_OUTPUT_STREAM (stream);
if (!g_output_stream_is_closed (output_stream))
{
g_warning ("stream is not closed yet, can't get etag");
return NULL;
}
etag = NULL;
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
if (class->get_etag)
etag = class->get_etag (stream);
return etag;
}
/**
* g_file_output_stream_tell:
* @stream:
*
* Returns:
**/
goffset
g_file_output_stream_tell (GFileOutputStream *stream)
{
GFileOutputStreamClass *class;
goffset offset;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), 0);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
offset = 0;
if (class->tell)
offset = class->tell (stream);
return offset;
}
static goffset
g_file_output_stream_seekable_tell (GSeekable *seekable)
{
return g_file_output_stream_tell (G_FILE_OUTPUT_STREAM (seekable));
}
/**
* g_file_output_stream_can_seek:
* @stream:
*
* Returns:
**/
gboolean
g_file_output_stream_can_seek (GFileOutputStream *stream)
{
GFileOutputStreamClass *class;
gboolean can_seek;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), FALSE);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
can_seek = FALSE;
if (class->seek)
{
can_seek = TRUE;
if (class->can_seek)
can_seek = class->can_seek (stream);
}
return can_seek;
}
static gboolean
g_file_output_stream_seekable_can_seek (GSeekable *seekable)
{
return g_file_output_stream_can_seek (G_FILE_OUTPUT_STREAM (seekable));
}
/**
* g_file_output_stream_seek:
* @stream:
* @offset:
* @type:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
gboolean
g_file_output_stream_seek (GFileOutputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
GFileOutputStreamClass *class;
GOutputStream *output_stream;
gboolean res;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), FALSE);
output_stream = G_OUTPUT_STREAM (stream);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
if (g_output_stream_is_closed (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return FALSE;
}
if (g_output_stream_has_pending (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return FALSE;
}
if (!class->seek)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Seek not supported on stream"));
return FALSE;
}
g_output_stream_set_pending (output_stream, TRUE);
if (cancellable)
g_push_current_cancellable (cancellable);
res = class->seek (stream, offset, type, cancellable, error);
if (cancellable)
g_pop_current_cancellable (cancellable);
g_output_stream_set_pending (output_stream, FALSE);
return res;
}
static gboolean
g_file_output_stream_seekable_seek (GSeekable *seekable,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
return g_file_output_stream_seek (G_FILE_OUTPUT_STREAM (seekable),
offset, type, cancellable, error);
}
/**
* g_file_output_stream_can_truncate:
* @stream:
*
* Returns: %TRUE if stream can be truncated.
**/
gboolean
g_file_output_stream_can_truncate (GFileOutputStream *stream)
{
GFileOutputStreamClass *class;
gboolean can_truncate;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), FALSE);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
can_truncate = FALSE;
if (class->truncate)
{
can_truncate = TRUE;
if (class->can_truncate)
can_truncate = class->can_truncate (stream);
}
return can_truncate;
}
static gboolean
g_file_output_stream_seekable_can_truncate (GSeekable *seekable)
{
return g_file_output_stream_can_truncate (G_FILE_OUTPUT_STREAM (seekable));
}
/**
* g_file_output_stream_truncate:
* @stream:
* @size:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns: %TRUE if @stream is truncated.
**/
gboolean
g_file_output_stream_truncate (GFileOutputStream *stream,
goffset size,
GCancellable *cancellable,
GError **error)
{
GFileOutputStreamClass *class;
GOutputStream *output_stream;
gboolean res;
g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), FALSE);
output_stream = G_OUTPUT_STREAM (stream);
class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream);
if (g_output_stream_is_closed (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
_("Stream is already closed"));
return FALSE;
}
if (g_output_stream_has_pending (output_stream))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
_("Stream has outstanding operation"));
return FALSE;
}
if (!class->truncate)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Truncate not supported on stream"));
return FALSE;
}
g_output_stream_set_pending (output_stream, TRUE);
if (cancellable)
g_push_current_cancellable (cancellable);
res = class->truncate (stream, size, cancellable, error);
if (cancellable)
g_pop_current_cancellable (cancellable);
g_output_stream_set_pending (output_stream, FALSE);
return res;
}
static gboolean
g_file_output_stream_seekable_truncate (GSeekable *seekable,
goffset size,
GCancellable *cancellable,
GError **error)
{
return g_file_output_stream_truncate (G_FILE_OUTPUT_STREAM (seekable),
size, cancellable, error);
}
/********************************************
* Default implementation of async ops *
********************************************/
typedef struct {
char *attributes;
GFileInfo *info;
} QueryInfoAsyncData;
static void
query_info_data_free (QueryInfoAsyncData *data)
{
if (data->info)
g_object_unref (data->info);
g_free (data->attributes);
g_free (data);
}
static void
query_info_async_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GFileOutputStreamClass *class;
GError *error = NULL;
QueryInfoAsyncData *data;
GFileInfo *info;
data = g_simple_async_result_get_op_res_gpointer (res);
info = NULL;
class = G_FILE_OUTPUT_STREAM_GET_CLASS (object);
if (class->query_info)
info = class->query_info (G_FILE_OUTPUT_STREAM (object), data->attributes, cancellable, &error);
else
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("Stream doesn't support query_info"));
if (info == NULL)
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
else
data->info = info;
}
static void
g_file_output_stream_real_query_info_async (GFileOutputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
QueryInfoAsyncData *data;
data = g_new0 (QueryInfoAsyncData, 1);
data->attributes = g_strdup (attributes);
res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_file_output_stream_real_query_info_async);
g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_info_data_free);
g_simple_async_result_run_in_thread (res, query_info_async_thread, io_priority, cancellable);
g_object_unref (res);
}
static GFileInfo *
g_file_output_stream_real_query_info_finish (GFileOutputStream *stream,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
QueryInfoAsyncData *data;
g_assert (g_simple_async_result_get_source_tag (simple) == g_file_output_stream_real_query_info_async);
data = g_simple_async_result_get_op_res_gpointer (simple);
if (data->info)
return g_object_ref (data->info);
return NULL;
}

121
gio/gfileoutputstream.h Normal file
View File

@ -0,0 +1,121 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_FILE_OUTPUT_STREAM_H__
#define __G_FILE_OUTPUT_STREAM_H__
#include <gio/goutputstream.h>
#include <gio/gfileinfo.h>
G_BEGIN_DECLS
#define G_TYPE_FILE_OUTPUT_STREAM (g_file_output_stream_get_type ())
#define G_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_OUTPUT_STREAM, GFileOutputStream))
#define G_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_OUTPUT_STREAM, GFileOutputStreamClass))
#define G_IS_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_OUTPUT_STREAM))
#define G_IS_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_OUTPUT_STREAM))
#define G_FILE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_OUTPUT_STREAM, GFileOutputStreamClass))
typedef struct _GFileOutputStream GFileOutputStream;
typedef struct _GFileOutputStreamClass GFileOutputStreamClass;
typedef struct _GFileOutputStreamPrivate GFileOutputStreamPrivate;
struct _GFileOutputStream
{
GOutputStream parent;
/*< private >*/
GFileOutputStreamPrivate *priv;
};
struct _GFileOutputStreamClass
{
GOutputStreamClass parent_class;
goffset (*tell) (GFileOutputStream *stream);
gboolean (*can_seek) (GFileOutputStream *stream);
gboolean (*seek) (GFileOutputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
gboolean (*can_truncate) (GFileOutputStream *stream);
gboolean (*truncate) (GFileOutputStream *stream,
goffset size,
GCancellable *cancellable,
GError **error);
GFileInfo *(*query_info) (GFileOutputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
void (*query_info_async) (GFileOutputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo *(*query_info_finish) (GFileOutputStream *stream,
GAsyncResult *res,
GError **error);
char *(*get_etag) (GFileOutputStream *stream);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_file_output_stream_get_type (void) G_GNUC_CONST;
GFileInfo *g_file_output_stream_query_info (GFileOutputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
void g_file_output_stream_query_info_async (GFileOutputStream *stream,
char *attributes,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GFileInfo *g_file_output_stream_query_info_finish (GFileOutputStream *stream,
GAsyncResult *result,
GError **error);
char * g_file_output_stream_get_etag (GFileOutputStream *stream);
goffset g_file_output_stream_tell (GFileOutputStream *stream);
gboolean g_file_output_stream_can_seek (GFileOutputStream *stream);
gboolean g_file_output_stream_seek (GFileOutputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
gboolean g_file_output_stream_can_truncate (GFileOutputStream *stream);
gboolean g_file_output_stream_truncate (GFileOutputStream *stream,
goffset size,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_FILE_FILE_OUTPUT_STREAM_H__ */

391
gio/gfilterinputstream.c Normal file
View File

@ -0,0 +1,391 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#include <config.h>
#include "gfilterinputstream.h"
#include "ginputstream.h"
#include "glibintl.h"
enum {
PROP_0,
PROP_BASE_STREAM
};
static void g_filter_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_filter_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void g_filter_input_stream_finalize (GObject *object);
static gssize g_filter_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gssize g_filter_input_stream_skip (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_filter_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
static void g_filter_input_stream_read_async (GInputStream *stream,
void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static gssize g_filter_input_stream_read_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
static void g_filter_input_stream_skip_async (GInputStream *stream,
gsize count,
int io_priority,
GCancellable *cancellabl,
GAsyncReadyCallback callback,
gpointer datae);
static gssize g_filter_input_stream_skip_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
static void g_filter_input_stream_close_async (GInputStream *stream,
int io_priority,
GCancellable *cancellabl,
GAsyncReadyCallback callback,
gpointer data);
static gboolean g_filter_input_stream_close_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
G_DEFINE_TYPE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
static void
g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
{
GObjectClass *object_class;
GInputStreamClass *istream_class;
object_class = G_OBJECT_CLASS (klass);
object_class->get_property = g_filter_input_stream_get_property;
object_class->set_property = g_filter_input_stream_set_property;
object_class->finalize = g_filter_input_stream_finalize;
istream_class = G_INPUT_STREAM_CLASS (klass);
istream_class->read = g_filter_input_stream_read;
istream_class->skip = g_filter_input_stream_skip;
istream_class->close = g_filter_input_stream_close;
istream_class->read_async = g_filter_input_stream_read_async;
istream_class->read_finish = g_filter_input_stream_read_finish;
istream_class->skip_async = g_filter_input_stream_skip_async;
istream_class->skip_finish = g_filter_input_stream_skip_finish;
istream_class->close_async = g_filter_input_stream_close_async;
istream_class->close_finish = g_filter_input_stream_close_finish;
g_object_class_install_property (object_class,
PROP_BASE_STREAM,
g_param_spec_object ("base-stream",
P_("The Filter Base Stream"),
P_("The underlying base stream the io ops will be done on"),
G_TYPE_INPUT_STREAM,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
}
static void
g_filter_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GFilterInputStream *filter_stream;
GObject *obj;
filter_stream = G_FILTER_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BASE_STREAM:
obj = g_value_dup_object (value);
filter_stream->base_stream = G_INPUT_STREAM (obj);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_filter_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GFilterInputStream *filter_stream;
filter_stream = G_FILTER_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BASE_STREAM:
g_value_set_object (value, filter_stream->base_stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_filter_input_stream_finalize (GObject *object)
{
GFilterInputStream *stream;
stream = G_FILTER_INPUT_STREAM (object);
g_object_unref (stream->base_stream);
if (G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize)
(*G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize) (object);
}
static void
g_filter_input_stream_init (GFilterInputStream *stream)
{
}
/**
* g_filter_input_stream_get_base_stream:
* @stream: a #GFilterInputStream.
*
* Returns: a #GInputStream.
**/
GInputStream *
g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
{
g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL);
return stream->base_stream;
}
static gssize
g_filter_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gssize nread;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
nread = g_input_stream_read (base_stream,
buffer,
count,
cancellable,
error);
return nread;
}
static gssize
g_filter_input_stream_skip (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gssize nskipped;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
nskipped = g_input_stream_skip (base_stream,
count,
cancellable,
error);
return nskipped;
}
static gboolean
g_filter_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gboolean res;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
res = g_input_stream_close (base_stream,
cancellable,
error);
return res;
}
static void
g_filter_input_stream_read_async (GInputStream *stream,
void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
g_input_stream_read_async (base_stream,
buffer,
count,
io_priority,
cancellable,
callback,
user_data);
}
static gssize
g_filter_input_stream_read_finish (GInputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gssize nread;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
nread = g_input_stream_read_finish (base_stream,
result,
error);
return nread;
}
static void
g_filter_input_stream_skip_async (GInputStream *stream,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
g_input_stream_skip_async (base_stream,
count,
io_priority,
cancellable,
callback,
user_data);
}
static gssize
g_filter_input_stream_skip_finish (GInputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gssize nskipped;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
nskipped = g_input_stream_skip_finish (base_stream,
result,
error);
return nskipped;
}
static void
g_filter_input_stream_close_async (GInputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
g_input_stream_close_async (base_stream,
io_priority,
cancellable,
callback,
user_data);
}
static gboolean
g_filter_input_stream_close_finish (GInputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterInputStream *filter_stream;
GInputStream *base_stream;
gboolean res;
filter_stream = G_FILTER_INPUT_STREAM (stream);
base_stream = filter_stream->base_stream;
res = g_input_stream_close_finish (stream,
result,
error);
return res;
}
/* vim: ts=2 sw=2 et */

65
gio/gfilterinputstream.h Normal file
View File

@ -0,0 +1,65 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#ifndef __G_FILTER_INPUT_STREAM_H__
#define __G_FILTER_INPUT_STREAM_H__
#include <glib-object.h>
#include <gio/ginputstream.h>
G_BEGIN_DECLS
#define G_TYPE_FILTER_INPUT_STREAM (g_filter_input_stream_get_type ())
#define G_FILTER_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILTER_INPUT_STREAM, GFilterInputStream))
#define G_FILTER_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamClass))
#define G_IS_FILTER_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILTER_INPUT_STREAM))
#define G_IS_FILTER_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILTER_INPUT_STREAM))
#define G_FILTER_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamClass))
typedef struct _GFilterInputStream GFilterInputStream;
typedef struct _GFilterInputStreamClass GFilterInputStreamClass;
typedef struct _GFilterInputStreamPrivate GFilterInputStreamPrivate;
struct _GFilterInputStream
{
GInputStream parent;
/*<protected >*/
GInputStream *base_stream;
};
struct _GFilterInputStreamClass
{
GInputStreamClass parent_class;
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
};
GType g_filter_input_stream_get_type (void) G_GNUC_CONST;
GInputStream *g_filter_input_stream_get_base_stream (GFilterInputStream *stream);
G_END_DECLS
#endif /* __G_FILTER_INPUT_STREAM_H__ */

366
gio/gfilteroutputstream.c Normal file
View File

@ -0,0 +1,366 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#include <config.h>
#include "gfilteroutputstream.h"
#include "goutputstream.h"
#include "glibintl.h"
enum {
PROP_0,
PROP_BASE_STREAM
};
static void g_filter_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void g_filter_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void g_filter_output_stream_dispose (GObject *object);
static gssize g_filter_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_filter_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static gboolean g_filter_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static void g_filter_output_stream_write_async (GOutputStream *stream,
const void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gssize g_filter_output_stream_write_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static void g_filter_output_stream_flush_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gboolean g_filter_output_stream_flush_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static void g_filter_output_stream_close_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);
static gboolean g_filter_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
G_DEFINE_TYPE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM)
static void
g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
{
GObjectClass *object_class;
GOutputStreamClass *ostream_class;
object_class = G_OBJECT_CLASS (klass);
object_class->get_property = g_filter_output_stream_get_property;
object_class->set_property = g_filter_output_stream_set_property;
object_class->dispose = g_filter_output_stream_dispose;
ostream_class = G_OUTPUT_STREAM_CLASS (klass);
ostream_class->write = g_filter_output_stream_write;
ostream_class->flush = g_filter_output_stream_flush;
ostream_class->close = g_filter_output_stream_close;
ostream_class->write_async = g_filter_output_stream_write_async;
ostream_class->write_finish = g_filter_output_stream_write_finish;
ostream_class->flush_async = g_filter_output_stream_flush_async;
ostream_class->flush_finish = g_filter_output_stream_flush_finish;
ostream_class->close_async = g_filter_output_stream_close_async;
ostream_class->close_finish = g_filter_output_stream_close_finish;
g_object_class_install_property (object_class,
PROP_BASE_STREAM,
g_param_spec_object ("base-stream",
P_("The Filter Base Stream"),
P_("The underlying base stream the io ops will be done on"),
G_TYPE_OUTPUT_STREAM,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
}
static void
g_filter_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GFilterOutputStream *filter_stream;
GObject *obj;
filter_stream = G_FILTER_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_BASE_STREAM:
obj = g_value_dup_object (value);
filter_stream->base_stream = G_OUTPUT_STREAM (obj);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_filter_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GFilterOutputStream *filter_stream;
filter_stream = G_FILTER_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_BASE_STREAM:
g_value_set_object (value, filter_stream->base_stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
g_filter_output_stream_dispose (GObject *object)
{
GFilterOutputStream *stream;
stream = G_FILTER_OUTPUT_STREAM (object);
G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object);
if (stream->base_stream)
{
g_object_unref (stream->base_stream);
stream->base_stream = NULL;
}
}
static void
g_filter_output_stream_init (GFilterOutputStream *stream)
{
}
GOutputStream *
g_filter_output_stream_get_base_stream (GFilterOutputStream *stream)
{
g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), NULL);
return stream->base_stream;
}
static gssize
g_filter_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GFilterOutputStream *filter_stream;
gssize nwritten;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
nwritten = g_output_stream_write (filter_stream->base_stream,
buffer,
count,
cancellable,
error);
return nwritten;
}
static gboolean
g_filter_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GFilterOutputStream *filter_stream;
gboolean res;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
res = g_output_stream_flush (filter_stream->base_stream,
cancellable,
error);
return res;
}
static gboolean
g_filter_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GFilterOutputStream *filter_stream;
gboolean res;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
res = g_output_stream_close (filter_stream->base_stream,
cancellable,
error);
return res;
}
static void
g_filter_output_stream_write_async (GOutputStream *stream,
const void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GFilterOutputStream *filter_stream;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
g_output_stream_write_async (filter_stream->base_stream,
buffer,
count,
io_priority,
cancellable,
callback,
data);
}
static gssize
g_filter_output_stream_write_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterOutputStream *filter_stream;
gssize nwritten;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
nwritten = g_output_stream_write_finish (filter_stream->base_stream,
result,
error);
return nwritten;
}
static void
g_filter_output_stream_flush_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GFilterOutputStream *filter_stream;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
g_output_stream_flush_async (filter_stream->base_stream,
io_priority,
cancellable,
callback,
data);
}
static gboolean
g_filter_output_stream_flush_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterOutputStream *filter_stream;
gboolean res;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
res = g_output_stream_flush_finish (filter_stream->base_stream,
result,
error);
return res;
}
static void
g_filter_output_stream_close_async (GOutputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
GFilterOutputStream *filter_stream;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
g_output_stream_close_async (filter_stream->base_stream,
io_priority,
cancellable,
callback,
data);
}
static gboolean
g_filter_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error)
{
GFilterOutputStream *filter_stream;
gboolean res;
filter_stream = G_FILTER_OUTPUT_STREAM (stream);
res = g_output_stream_close_finish (filter_stream->base_stream,
result,
error);
return res;
}
/* vim: ts=2 sw=2 et */

65
gio/gfilteroutputstream.h Normal file
View File

@ -0,0 +1,65 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Christian Kellner <gicmo@gnome.org>
*/
#ifndef __G_FILTER_OUTPUT_STREAM_H__
#define __G_FILTER_OUTPUT_STREAM_H__
#include <glib-object.h>
#include <gio/goutputstream.h>
G_BEGIN_DECLS
#define G_TYPE_FILTER_OUTPUT_STREAM (g_filter_output_stream_get_type ())
#define G_FILTER_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStream))
#define G_FILTER_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStreamClass))
#define G_IS_FILTER_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILTER_OUTPUT_STREAM))
#define G_IS_FILTER_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILTER_OUTPUT_STREAM))
#define G_FILTER_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStreamClass))
typedef struct _GFilterOutputStream GFilterOutputStream;
typedef struct _GFilterOutputStreamClass GFilterOutputStreamClass;
typedef struct _GFilterOutputStreamPrivate GFilterOutputStreamPrivate;
struct _GFilterOutputStream
{
GOutputStream parent;
/*< protected >*/
GOutputStream *base_stream;
};
struct _GFilterOutputStreamClass
{
GOutputStreamClass parent_class;
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
};
GType g_filter_output_stream_get_type (void) G_GNUC_CONST;
GOutputStream *g_filter_output_stream_get_base_stream (GFilterOutputStream *stream);
G_END_DECLS
#endif /* __G_FILTER_OUTPUT_STREAM_H__ */

118
gio/gicon.c Normal file
View File

@ -0,0 +1,118 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gicon.h"
#include "glibintl.h"
static void g_icon_base_init (gpointer g_class);
static void g_icon_class_init (gpointer g_class,
gpointer class_data);
GType
g_icon_get_type (void)
{
static GType icon_type = 0;
if (! icon_type)
{
static const GTypeInfo icon_info =
{
sizeof (GIconIface), /* class_size */
g_icon_base_init, /* base_init */
NULL, /* base_finalize */
g_icon_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
icon_type =
g_type_register_static (G_TYPE_INTERFACE, I_("GIcon"),
&icon_info, 0);
g_type_interface_add_prerequisite (icon_type, G_TYPE_OBJECT);
}
return icon_type;
}
static void
g_icon_class_init (gpointer g_class,
gpointer class_data)
{
}
static void
g_icon_base_init (gpointer g_class)
{
}
/**
* g_icon_hash:
* @icon: #gconstpointer to an icon object.
*
* Returns: a #guint containing a hash for the @icon, suitable for
* use in a #GHashTable or similar data structure.
**/
guint
g_icon_hash (gconstpointer icon)
{
GIconIface *iface;
g_return_val_if_fail (G_IS_ICON (icon), 0);
iface = G_ICON_GET_IFACE (icon);
return (* iface->hash) ((GIcon *)icon);
}
/**
* g_icon_equal:
* @icon1: pointer to the first #GIcon.
* @icon2: pointer to the second #GIcon.
*
* Returns: %TRUE if @icon1 is equal to @icon2. %FALSE otherwise.
**/
gboolean
g_icon_equal (GIcon *icon1,
GIcon *icon2)
{
GIconIface *iface;
if (icon1 == NULL && icon2 == NULL)
return TRUE;
if (icon1 == NULL || icon2 == NULL)
return FALSE;
if (G_TYPE_FROM_INSTANCE (icon1) != G_TYPE_FROM_INSTANCE (icon2))
return FALSE;
iface = G_ICON_GET_IFACE (icon1);
return (* iface->equal) (icon1, icon2);
}

58
gio/gicon.h Normal file
View File

@ -0,0 +1,58 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_ICON_H__
#define __G_ICON_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define G_TYPE_ICON (g_icon_get_type ())
#define G_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ICON, GIcon))
#define G_IS_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ICON))
#define G_ICON_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ICON, GIconIface))
typedef struct _GIcon GIcon; /* Dummy typedef */
typedef struct _GIconIface GIconIface;
struct _GIconIface
{
GTypeInterface g_iface;
/* Virtual Table */
guint (*hash) (GIcon *icon);
gboolean (*equal) (GIcon *icon1,
GIcon *icon2);
};
GType g_icon_get_type (void) G_GNUC_CONST;
guint g_icon_hash (gconstpointer icon);
gboolean g_icon_equal (GIcon *icon1,
GIcon *icon2);
G_END_DECLS
#endif /* __G_ICON_H__ */

1184
gio/ginputstream.c Normal file

File diff suppressed because it is too large Load Diff

165
gio/ginputstream.h Normal file
View File

@ -0,0 +1,165 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_INPUT_STREAM_H__
#define __G_INPUT_STREAM_H__
#include <glib-object.h>
#include <gio/gioerror.h>
#include <gio/gcancellable.h>
#include <gio/gasyncresult.h>
G_BEGIN_DECLS
#define G_TYPE_INPUT_STREAM (g_input_stream_get_type ())
#define G_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_INPUT_STREAM, GInputStream))
#define G_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_INPUT_STREAM, GInputStreamClass))
#define G_IS_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_INPUT_STREAM))
#define G_IS_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_INPUT_STREAM))
#define G_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_INPUT_STREAM, GInputStreamClass))
typedef struct _GInputStream GInputStream;
typedef struct _GInputStreamClass GInputStreamClass;
typedef struct _GInputStreamPrivate GInputStreamPrivate;
struct _GInputStream
{
GObject parent;
/*< private >*/
GInputStreamPrivate *priv;
};
struct _GInputStreamClass
{
GObjectClass parent_class;
/* Sync ops: */
gssize (* read) (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
gssize (* skip) (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error);
gboolean (* close) (GInputStream *stream,
GCancellable *cancellable,
GError **error);
/* Async ops: (optional in derived classes) */
void (* read_async) (GInputStream *stream,
void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize (* read_finish) (GInputStream *stream,
GAsyncResult *result,
GError **error);
void (* skip_async) (GInputStream *stream,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize (* skip_finish) (GInputStream *stream,
GAsyncResult *result,
GError **error);
void (* close_async) (GInputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (* close_finish)(GInputStream *stream,
GAsyncResult *result,
GError **error);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType g_input_stream_get_type (void) G_GNUC_CONST;
gssize g_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
gboolean g_input_stream_read_all (GInputStream *stream,
void *buffer,
gsize count,
gsize *bytes_read,
GCancellable *cancellable,
GError **error);
gssize g_input_stream_skip (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error);
gboolean g_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
void g_input_stream_read_async (GInputStream *stream,
void *buffer,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize g_input_stream_read_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
void g_input_stream_skip_async (GInputStream *stream,
gsize count,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gssize g_input_stream_skip_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
void g_input_stream_close_async (GInputStream *stream,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_input_stream_close_finish (GInputStream *stream,
GAsyncResult *result,
GError **error);
/* For implementations: */
gboolean g_input_stream_is_closed (GInputStream *stream);
gboolean g_input_stream_has_pending (GInputStream *stream);
void g_input_stream_set_pending (GInputStream *stream,
gboolean pending);
G_END_DECLS
#endif /* __G_INPUT_STREAM_H__ */

4
gio/gio-marshal.list Normal file
View File

@ -0,0 +1,4 @@
BOOLEAN:STRING,STRING,STRING,INT
BOOLEAN:STRING,POINTER
VOID:BOOLEAN,POINTER
VOID:OBJECT,OBJECT,INT

155
gio/gioerror.c Normal file
View File

@ -0,0 +1,155 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <errno.h>
#include "gioerror.h"
/**
* g_io_error_quark:
*
* Return value: The quark used as %G_IO_ERROR
**/
GQuark
g_io_error_quark (void)
{
return g_quark_from_static_string ("g-io-error-quark");
}
GIOErrorEnum
g_io_error_from_errno (gint err_no)
{
switch (err_no)
{
#ifdef EEXIST
case EEXIST:
return G_IO_ERROR_EXISTS;
break;
#endif
#ifdef EISDIR
case EISDIR:
return G_IO_ERROR_IS_DIRECTORY;
break;
#endif
#ifdef EACCES
case EACCES:
return G_IO_ERROR_PERMISSION_DENIED;
break;
#endif
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
return G_IO_ERROR_FILENAME_TOO_LONG;
break;
#endif
#ifdef ENOENT
case ENOENT:
return G_IO_ERROR_NOT_FOUND;
break;
#endif
#ifdef ENOTDIR
case ENOTDIR:
return G_IO_ERROR_NOT_DIRECTORY;
break;
#endif
#ifdef EROFS
case EROFS:
return G_IO_ERROR_READ_ONLY;
break;
#endif
#ifdef ELOOP
case ELOOP:
return G_IO_ERROR_TOO_MANY_LINKS;
break;
#endif
#ifdef ENOSPC
case ENOSPC:
return G_IO_ERROR_NO_SPACE;
break;
#endif
#ifdef ENOMEM
case ENOMEM:
return G_IO_ERROR_NO_SPACE;
break;
#endif
#ifdef EINVAL
case EINVAL:
return G_IO_ERROR_INVALID_ARGUMENT;
break;
#endif
#ifdef EPERM
case EPERM:
return G_IO_ERROR_PERMISSION_DENIED;
break;
#endif
#ifdef ECANCELED
case ECANCELED:
return G_IO_ERROR_CANCELLED;
break;
#endif
#ifdef ENOTEMPTY
case ENOTEMPTY:
return G_IO_ERROR_NOT_EMPTY;
break;
#endif
#ifdef ENOTSUP
case ENOTSUP:
return G_IO_ERROR_NOT_SUPPORTED;
break;
#endif
#ifdef ETIMEDOUT
case ETIMEDOUT:
return G_IO_ERROR_TIMED_OUT;
break;
#endif
#ifdef EBUSY
case EBUSY:
return G_IO_ERROR_BUSY;
break;
#endif
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
return G_IO_ERROR_WOULD_BLOCK;
break;
#endif
default:
return G_IO_ERROR_FAILED;
break;
}
}

78
gio/gioerror.h Normal file
View File

@ -0,0 +1,78 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_IO_ERROR_H__
#define __G_IO_ERROR_H__
#include <glib/gerror.h>
G_BEGIN_DECLS
GQuark g_io_error_quark (void);
#define G_IO_ERROR g_io_error_quark()
/* This enumeration conflicts with GIOError in giochannel.h. However,
* that is only used as a return value in some deprecated functions.
* So, we reuse the same prefix for the enumeration values, but call
* the actual enumeration (which is rarely used) GIOErrorEnum.
*/
typedef enum
{
G_IO_ERROR_FAILED,
G_IO_ERROR_NOT_FOUND,
G_IO_ERROR_EXISTS,
G_IO_ERROR_IS_DIRECTORY,
G_IO_ERROR_NOT_DIRECTORY,
G_IO_ERROR_NOT_EMPTY,
G_IO_ERROR_NOT_REGULAR_FILE,
G_IO_ERROR_NOT_SYMBOLIC_LINK,
G_IO_ERROR_NOT_MOUNTABLE_FILE,
G_IO_ERROR_FILENAME_TOO_LONG,
G_IO_ERROR_INVALID_FILENAME,
G_IO_ERROR_TOO_MANY_LINKS,
G_IO_ERROR_NO_SPACE,
G_IO_ERROR_INVALID_ARGUMENT,
G_IO_ERROR_PERMISSION_DENIED,
G_IO_ERROR_NOT_SUPPORTED,
G_IO_ERROR_NOT_MOUNTED,
G_IO_ERROR_ALREADY_MOUNTED,
G_IO_ERROR_CLOSED,
G_IO_ERROR_CANCELLED,
G_IO_ERROR_PENDING,
G_IO_ERROR_READ_ONLY,
G_IO_ERROR_CANT_CREATE_BACKUP,
G_IO_ERROR_WRONG_ETAG,
G_IO_ERROR_TIMED_OUT,
G_IO_ERROR_WOULD_RECURSE,
G_IO_ERROR_BUSY,
G_IO_ERROR_WOULD_BLOCK,
G_IO_ERROR_HOST_NOT_FOUND,
G_IO_ERROR_WOULD_MERGE
} GIOErrorEnum;
GIOErrorEnum g_io_error_from_errno (gint err_no);
G_END_DECLS
#endif /* __G_IO_ERROR_H__ */

237
gio/giomodule.c Normal file
View File

@ -0,0 +1,237 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "giomodule.h"
struct _GIOModule {
GTypeModule parent_instance;
gchar *filename;
GModule *library;
void (* load) (GIOModule *module);
void (* unload) (GIOModule *module);
};
struct _GIOModuleClass
{
GTypeModuleClass parent_class;
};
static void g_io_module_finalize (GObject *object);
static gboolean g_io_module_load_module (GTypeModule *gmodule);
static void g_io_module_unload_module (GTypeModule *gmodule);
G_DEFINE_TYPE (GIOModule, g_io_module, G_TYPE_TYPE_MODULE);
static void
g_io_module_class_init (GIOModuleClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GTypeModuleClass *type_module_class = G_TYPE_MODULE_CLASS (class);
object_class->finalize = g_io_module_finalize;
type_module_class->load = g_io_module_load_module;
type_module_class->unload = g_io_module_unload_module;
}
static void
g_io_module_init (GIOModule *module)
{
}
static void
g_io_module_finalize (GObject *object)
{
GIOModule *module = G_IO_MODULE (object);
g_free (module->filename);
G_OBJECT_CLASS (g_io_module_parent_class)->finalize (object);
}
static gboolean
g_io_module_load_module (GTypeModule *gmodule)
{
GIOModule *module = G_IO_MODULE (gmodule);
if (!module->filename)
{
g_warning ("GIOModule path not set");
return FALSE;
}
module->library = g_module_open (module->filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!module->library)
{
g_printerr ("%s\n", g_module_error ());
return FALSE;
}
/* Make sure that the loaded library contains the required methods */
if (! g_module_symbol (module->library,
"g_io_module_load",
(gpointer *) &module->load) ||
! g_module_symbol (module->library,
"g_io_module_unload",
(gpointer *) &module->unload))
{
g_printerr ("%s\n", g_module_error ());
g_module_close (module->library);
return FALSE;
}
/* Initialize the loaded module */
module->load (module);
return TRUE;
}
static void
g_io_module_unload_module (GTypeModule *gmodule)
{
GIOModule *module = G_IO_MODULE (gmodule);
module->unload (module);
g_module_close (module->library);
module->library = NULL;
module->load = NULL;
module->unload = NULL;
}
/**
* g_io_module_new:
* @filename: filename of the module to load.
*
* Returns: a new #GIOModule from given @filename,
* or %NULL on error.
**/
GIOModule *
g_io_module_new (const gchar *filename)
{
GIOModule *module;
g_return_val_if_fail (filename != NULL, NULL);
module = g_object_new (G_IO_TYPE_MODULE, NULL);
module->filename = g_strdup (filename);
return module;
}
static gboolean
is_valid_module_name (const gchar *basename)
{
#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
return
g_str_has_prefix (basename, "lib") &&
g_str_has_suffix (basename, ".so");
#else
return g_str_has_suffix (basename, ".dll");
#endif
}
static GList *
load_modules (const char *dirname)
{
const gchar *name;
GDir *dir;
GList *modules;
if (!g_module_supported ())
return NULL;
dir = g_dir_open (dirname, 0, NULL);
if (!dir)
return NULL;
modules = NULL;
while ((name = g_dir_read_name (dir)))
{
if (is_valid_module_name (name))
{
GIOModule *module;
gchar *path;
path = g_build_filename (dirname, name, NULL);
module = g_io_module_new (path);
if (!g_type_module_use (G_TYPE_MODULE (module)))
{
g_printerr ("Failed to load module: %s\n", path);
g_object_unref (module);
g_free (path);
continue;
}
g_free (path);
g_type_module_unuse (G_TYPE_MODULE (module));
modules = g_list_prepend (modules, module);
}
}
g_dir_close (dir);
return modules;
}
G_LOCK_DEFINE_STATIC (loaded_dirs);
static GHashTable *loaded_dirs = NULL;
/**
* g_io_module_ensure_loaded:
* @directory: directory to ensure is loaded.
*
**/
void
g_io_modules_ensure_loaded (const char *directory)
{
GList *modules;
g_return_if_fail (directory != NULL);
G_LOCK (loaded_dirs);
if (loaded_dirs == NULL)
loaded_dirs = g_hash_table_new (g_str_hash, g_str_equal);
if (!g_hash_table_lookup_extended (loaded_dirs, directory,
NULL, NULL))
{
modules = load_modules (directory);
g_hash_table_insert (loaded_dirs,
g_strdup (directory),
modules);
}
G_UNLOCK (loaded_dirs);
}

52
gio/giomodule.h Normal file
View File

@ -0,0 +1,52 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_IO_MODULE_H__
#define __G_IO_MODULE_H__
#include <glib-object.h>
#include <gmodule.h>
G_BEGIN_DECLS
#define G_IO_TYPE_MODULE (g_io_module_get_type ())
#define G_IO_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_IO_TYPE_MODULE, GIOModule))
#define G_IO_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_IO_TYPE_MODULE, GIOModuleClass))
#define G_IO_IS_MODULE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_IO_TYPE_MODULE))
#define G_IO_IS_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_IO_TYPE_MODULE))
#define G_IO_MODULE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_IO_TYPE_MODULE, GIOModuleClass))
typedef struct _GIOModule GIOModule;
typedef struct _GIOModuleClass GIOModuleClass;
GType g_io_module_get_type (void) G_GNUC_CONST;
GIOModule *g_io_module_new (const gchar *filename);
void g_io_modules_ensure_loaded (const char *directory);
/* API for the modules to implement */
void g_io_module_load (GIOModule *module);
void g_io_module_unload (GIOModule *module);
G_END_DECLS
#endif /* __G_IO_MODULE_H__ */

372
gio/gioscheduler.c Normal file
View File

@ -0,0 +1,372 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gioscheduler.h"
struct _GIOJob {
GSList *active_link;
GIOJobFunc job_func;
GIODataFunc cancel_func; /* Runs under job map lock */
gpointer data;
GDestroyNotify destroy_notify;
gint io_priority;
GCancellable *cancellable;
guint idle_tag;
};
G_LOCK_DEFINE_STATIC(active_jobs);
static GSList *active_jobs = NULL;
static GThreadPool *job_thread_pool = NULL;
static void io_job_thread (gpointer data,
gpointer user_data);
static void
g_io_job_free (GIOJob *job)
{
if (job->cancellable)
g_object_unref (job->cancellable);
g_free (job);
}
static gint
g_io_job_compare (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
const GIOJob *aa = a;
const GIOJob *bb = b;
/* Cancelled jobs are set prio == -1, so that
they are executed as quickly as possible */
/* Lower value => higher priority */
if (aa->io_priority < bb->io_priority)
return -1;
if (aa->io_priority == bb->io_priority)
return 0;
return 1;
}
static gpointer
init_scheduler (gpointer arg)
{
if (job_thread_pool == NULL)
{
/* TODO: thread_pool_new can fail */
job_thread_pool = g_thread_pool_new (io_job_thread,
NULL,
10,
FALSE,
NULL);
if (job_thread_pool != NULL)
{
g_thread_pool_set_sort_function (job_thread_pool,
g_io_job_compare,
NULL);
/* Its kinda weird that this is a global setting
* instead of per threadpool. However, we really
* want to cache some threads, but not keep around
* those threads forever. */
g_thread_pool_set_max_idle_time (15 * 1000);
g_thread_pool_set_max_unused_threads (2);
}
}
return NULL;
}
static void
remove_active_job (GIOJob *job)
{
GIOJob *other_job;
GSList *l;
gboolean resort_jobs;
G_LOCK (active_jobs);
active_jobs = g_slist_delete_link (active_jobs, job->active_link);
resort_jobs = FALSE;
for (l = active_jobs; l != NULL; l = l->next)
{
other_job = l->data;
if (other_job->io_priority >= 0 &&
g_cancellable_is_cancelled (other_job->cancellable))
{
other_job->io_priority = -1;
resort_jobs = TRUE;
}
}
G_UNLOCK (active_jobs);
if (resort_jobs &&
job_thread_pool != NULL)
g_thread_pool_set_sort_function (job_thread_pool,
g_io_job_compare,
NULL);
}
static void
io_job_thread (gpointer data,
gpointer user_data)
{
GIOJob *job = data;
if (job->cancellable)
g_push_current_cancellable (job->cancellable);
job->job_func (job, job->cancellable, job->data);
if (job->cancellable)
g_pop_current_cancellable (job->cancellable);
if (job->destroy_notify)
job->destroy_notify (job->data);
remove_active_job (job);
g_io_job_free (job);
}
static gboolean
run_job_at_idle (gpointer data)
{
GIOJob *job = data;
if (job->cancellable)
g_push_current_cancellable (job->cancellable);
job->job_func (job, job->cancellable, job->data);
if (job->cancellable)
g_pop_current_cancellable (job->cancellable);
if (job->destroy_notify)
job->destroy_notify (job->data);
remove_active_job (job);
g_io_job_free (job);
return FALSE;
}
/**
* g_schedule_io_job:
* @job_func: a #GIOJobFunc.
* @user_data: a #gpointer.
* @notify: a #GDestroyNotify.
* @io_priority: the io priority of the request. a #gint.
* @cancellable: optional #GCancellable object, %NULL to ignore.
*
* Schedules the @job_func.
*
**/
void
g_schedule_io_job (GIOJobFunc job_func,
gpointer user_data,
GDestroyNotify notify,
gint io_priority,
GCancellable *cancellable)
{
static GOnce once_init = G_ONCE_INIT;
GIOJob *job;
g_return_if_fail (job_func != NULL);
job = g_new0 (GIOJob, 1);
job->job_func = job_func;
job->data = user_data;
job->destroy_notify = notify;
job->io_priority = io_priority;
if (cancellable)
job->cancellable = g_object_ref (cancellable);
G_LOCK (active_jobs);
active_jobs = g_slist_prepend (active_jobs, job);
job->active_link = active_jobs;
G_UNLOCK (active_jobs);
if (g_thread_supported())
{
g_once (&once_init, init_scheduler, NULL);
g_thread_pool_push (job_thread_pool, job, NULL);
}
else
{
/* Threads not available, instead do the i/o sync inside a
* low prio idle handler
*/
job->idle_tag = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1 + io_priority / 10,
run_job_at_idle,
job, NULL);
}
}
/**
* g_cancel_all_io_jobs:
*
* Cancels all cancellable I/O Jobs.
**/
void
g_cancel_all_io_jobs (void)
{
GSList *cancellable_list, *l;
G_LOCK (active_jobs);
cancellable_list = NULL;
for (l = active_jobs; l != NULL; l = l->next)
{
GIOJob *job = l->data;
if (job->cancellable)
cancellable_list = g_slist_prepend (cancellable_list,
g_object_ref (job->cancellable));
}
G_UNLOCK (active_jobs);
for (l = cancellable_list; l != NULL; l = l->next)
{
GCancellable *c = l->data;
g_cancellable_cancel (c);
g_object_unref (c);
}
g_slist_free (cancellable_list);
}
typedef struct {
GIODataFunc func;
gpointer data;
GDestroyNotify notify;
GMutex *ack_lock;
GCond *ack_condition;
} MainLoopProxy;
static gboolean
mainloop_proxy_func (gpointer data)
{
MainLoopProxy *proxy = data;
proxy->func (proxy->data);
if (proxy->ack_lock)
{
g_mutex_lock (proxy->ack_lock);
g_cond_signal (proxy->ack_condition);
g_mutex_unlock (proxy->ack_lock);
}
return FALSE;
}
static void
mainloop_proxy_free (MainLoopProxy *proxy)
{
if (proxy->ack_lock)
{
g_mutex_free (proxy->ack_lock);
g_cond_free (proxy->ack_condition);
}
g_free (proxy);
}
static void
mainloop_proxy_notify (gpointer data)
{
MainLoopProxy *proxy = data;
if (proxy->notify)
proxy->notify (proxy->data);
/* If nonblocking we free here, otherwise we free in io thread */
if (proxy->ack_lock == NULL)
mainloop_proxy_free (proxy);
}
/**
* g_io_job_send_to_mainloop:
* @job: a #GIOJob.
* @func: a #GIODataFunc.
* @user_data: a #gpointer.
* @notify: a #GDestroyNotify.
* @block: boolean flag indicating whether or not this job should block.
*
*
**/
void
g_io_job_send_to_mainloop (GIOJob *job,
GIODataFunc func,
gpointer user_data,
GDestroyNotify notify,
gboolean block)
{
GSource *source;
MainLoopProxy *proxy;
guint id;
g_return_if_fail (job != NULL);
g_return_if_fail (func != NULL);
if (job->idle_tag)
{
/* We just immediately re-enter in the case of idles (non-threads)
* Anything else would just deadlock. If you can't handle this, enable threads.
*/
func (user_data);
return;
}
proxy = g_new0 (MainLoopProxy, 1);
proxy->func = func;
proxy->data = user_data;
proxy->notify = notify;
if (block)
{
proxy->ack_lock = g_mutex_new ();
proxy->ack_condition = g_cond_new ();
}
source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_callback (source, mainloop_proxy_func, proxy, mainloop_proxy_notify);
if (block)
g_mutex_lock (proxy->ack_lock);
id = g_source_attach (source, NULL);
g_source_unref (source);
if (block)
{
g_cond_wait (proxy->ack_condition, proxy->ack_lock);
g_mutex_unlock (proxy->ack_lock);
/* destroy notify didn't free proxy */
mainloop_proxy_free (proxy);
}
}

55
gio/gioscheduler.h Normal file
View File

@ -0,0 +1,55 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_IO_SCHEDULER_H__
#define __G_IO_SCHEDULER_H__
#include <glib.h>
#include <gio/gcancellable.h>
G_BEGIN_DECLS
typedef struct _GIOJob GIOJob;
typedef void (*GIOJobFunc) (GIOJob *job,
GCancellable *cancellable,
gpointer user_data);
typedef void (*GIODataFunc) (gpointer user_data);
void g_schedule_io_job (GIOJobFunc job_func,
gpointer user_data,
GDestroyNotify notify,
gint io_priority,
GCancellable *cancellable);
void g_cancel_all_io_jobs (void);
void g_io_job_send_to_mainloop (GIOJob *job,
GIODataFunc func,
gpointer user_data,
GDestroyNotify notify,
gboolean block);
G_END_DECLS
#endif /* __G_IO_SCHEDULER_H__ */

260
gio/gloadableicon.c Normal file
View File

@ -0,0 +1,260 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "gsimpleasyncresult.h"
#include "gloadableicon.h"
#include "glibintl.h"
static void g_loadable_icon_real_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static GInputStream *g_loadable_icon_real_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error);
static void g_loadable_icon_base_init (gpointer g_class);
static void g_loadable_icon_class_init (gpointer g_class,
gpointer class_data);
GType
g_loadable_icon_get_type (void)
{
static GType loadable_icon_type = 0;
if (! loadable_icon_type)
{
static const GTypeInfo loadable_icon_info =
{
sizeof (GLoadableIconIface), /* class_size */
g_loadable_icon_base_init, /* base_init */
NULL, /* base_finalize */
g_loadable_icon_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
loadable_icon_type =
g_type_register_static (G_TYPE_INTERFACE, I_("GLoadableIcon"),
&loadable_icon_info, 0);
g_type_interface_add_prerequisite (loadable_icon_type, G_TYPE_ICON);
}
return loadable_icon_type;
}
static void
g_loadable_icon_class_init (gpointer g_class,
gpointer class_data)
{
GLoadableIconIface *iface = g_class;
iface->load_async = g_loadable_icon_real_load_async;
iface->load_finish = g_loadable_icon_real_load_finish;
}
static void
g_loadable_icon_base_init (gpointer g_class)
{
}
/**
* g_loadable_icon_load:
* @icon:
* @size:
* @type:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
GInputStream *
g_loadable_icon_load (GLoadableIcon *icon,
int size,
char **type,
GCancellable *cancellable,
GError **error)
{
GLoadableIconIface *iface;
g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL);
iface = G_LOADABLE_ICON_GET_IFACE (icon);
return (* iface->load) (icon, size, type, cancellable, error);
}
/**
* g_loadable_icon_load_async:
* @icon:
* @size:
* @cancellable: optional #GCancellable object, %NULL to ignore. @callback:
* @user_data:
*
* Loads an icon asynchronously.
*
**/
void
g_loadable_icon_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GLoadableIconIface *iface;
g_return_if_fail (G_IS_LOADABLE_ICON (icon));
iface = G_LOADABLE_ICON_GET_IFACE (icon);
(* iface->load_async) (icon, size, cancellable, callback, user_data);
}
/**
* g_loadable_icon_load_finish:
* @icon:
* @res:
* @type:
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
GInputStream *
g_loadable_icon_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error)
{
GLoadableIconIface *iface;
g_return_val_if_fail (G_IS_LOADABLE_ICON (icon), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
if (G_IS_SIMPLE_ASYNC_RESULT (res))
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
}
iface = G_LOADABLE_ICON_GET_IFACE (icon);
return (* iface->load_finish) (icon, res, type, error);
}
/********************************************
* Default implementation of async load *
********************************************/
typedef struct {
int size;
char *type;
GInputStream *stream;
} LoadData;
static void
load_data_free (LoadData *data)
{
if (data->stream)
g_object_unref (data->stream);
g_free (data->type);
g_free (data);
}
static void
load_async_thread (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GLoadableIconIface *iface;
GInputStream *stream;
LoadData *data;
GError *error = NULL;
char *type = NULL;
data = g_simple_async_result_get_op_res_gpointer (res);
iface = G_LOADABLE_ICON_GET_IFACE (object);
stream = iface->load (G_LOADABLE_ICON (object), data->size, &type, cancellable, &error);
if (stream == NULL)
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
else
{
data->stream = stream;
data->type = type;
}
}
static void
g_loadable_icon_real_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *res;
LoadData *data;
res = g_simple_async_result_new (G_OBJECT (icon), callback, user_data, g_loadable_icon_real_load_async);
data = g_new0 (LoadData, 1);
g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify) load_data_free);
g_simple_async_result_run_in_thread (res, load_async_thread, 0, cancellable);
g_object_unref (res);
}
static GInputStream *
g_loadable_icon_real_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
LoadData *data;
g_assert (g_simple_async_result_get_source_tag (simple) == g_loadable_icon_real_load_async);
data = g_simple_async_result_get_op_res_gpointer (simple);
if (type)
{
*type = data->type;
data->type = NULL;
}
return g_object_ref (data->stream);
}

83
gio/gloadableicon.h Normal file
View File

@ -0,0 +1,83 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOADABLE_ICON_H__
#define __G_LOADABLE_ICON_H__
#include <glib-object.h>
#include <gio/gicon.h>
#include <gio/ginputstream.h>
G_BEGIN_DECLS
#define G_TYPE_LOADABLE_ICON (g_loadable_icon_get_type ())
#define G_LOADABLE_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_LOADABLE_ICON, GLoadableIcon))
#define G_IS_LOADABLE_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_LOADABLE_ICON))
#define G_LOADABLE_ICON_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_LOADABLE_ICON, GLoadableIconIface))
typedef struct _GLoadableIcon GLoadableIcon; /* Dummy typedef */
typedef struct _GLoadableIconIface GLoadableIconIface;
struct _GLoadableIconIface
{
GTypeInterface g_iface;
/* Virtual Table */
GInputStream * (*load) (GLoadableIcon *icon,
int size,
char **type,
GCancellable *cancellable,
GError **error);
void (*load_async) (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream * (*load_finish) (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error);
};
GType g_loadable_icon_get_type (void) G_GNUC_CONST;
GInputStream *g_loadable_icon_load (GLoadableIcon *icon,
int size,
char **type,
GCancellable *cancellable,
GError **error);
void g_loadable_icon_load_async (GLoadableIcon *icon,
int size,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream *g_loadable_icon_load_finish (GLoadableIcon *icon,
GAsyncResult *res,
char **type,
GError **error);
G_END_DECLS
#endif /* __G_LOADABLE_ICON_H__ */

View File

@ -0,0 +1,290 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "glocaldirectorymonitor.h"
#include "gunixmounts.h"
#include "gdirectorymonitor.h"
#include "giomodule.h"
#include <string.h>
enum
{
PROP_0,
PROP_DIRNAME
};
static gboolean g_local_directory_monitor_cancel (GDirectoryMonitor* monitor);
static void mounts_changed (GUnixMountMonitor *mount_monitor, gpointer user_data);
G_DEFINE_ABSTRACT_TYPE (GLocalDirectoryMonitor, g_local_directory_monitor, G_TYPE_DIRECTORY_MONITOR)
static void
g_local_directory_monitor_finalize (GObject* object)
{
GLocalDirectoryMonitor* local_monitor;
local_monitor = G_LOCAL_DIRECTORY_MONITOR (object);
g_free (local_monitor->dirname);
if (local_monitor->mount_monitor)
{
g_signal_handlers_disconnect_by_func (local_monitor->mount_monitor, mounts_changed, local_monitor);
g_object_unref (local_monitor->mount_monitor);
local_monitor->mount_monitor = NULL;
}
if (G_OBJECT_CLASS (g_local_directory_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_local_directory_monitor_parent_class)->finalize) (object);
}
static void
g_local_directory_monitor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
case PROP_DIRNAME:
/* Do nothing */
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static GObject *
g_local_directory_monitor_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
GLocalDirectoryMonitorClass *klass;
GObjectClass *parent_class;
GLocalDirectoryMonitor *local_monitor;
const gchar *dirname = NULL;
gint i;
klass = G_LOCAL_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_LOCAL_DIRECTORY_MONITOR));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
local_monitor = G_LOCAL_DIRECTORY_MONITOR (obj);
for (i = 0; i < n_construct_properties; i++)
{
if (strcmp ("dirname", g_param_spec_get_name (construct_properties[i].pspec)) == 0)
{
g_assert (G_VALUE_HOLDS_STRING (construct_properties[i].value));
dirname = g_value_get_string (construct_properties[i].value);
break;
}
}
local_monitor->dirname = g_strdup (dirname);
if (!klass->mount_notify)
{
GUnixMount *mount;
/* Emulate unmount detection */
mount = g_get_unix_mount_at (local_monitor->dirname, NULL);
local_monitor->was_mounted = mount != NULL;
if (mount)
g_unix_mount_free (mount);
local_monitor->mount_monitor = g_unix_mount_monitor_new ();
g_signal_connect (local_monitor->mount_monitor, "mounts_changed",
G_CALLBACK (mounts_changed), local_monitor);
}
return obj;
}
static void
g_local_directory_monitor_class_init (GLocalDirectoryMonitorClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (klass);
GDirectoryMonitorClass *dir_monitor_class = G_DIRECTORY_MONITOR_CLASS (klass);
gobject_class->finalize = g_local_directory_monitor_finalize;
gobject_class->set_property = g_local_directory_monitor_set_property;
gobject_class->constructor = g_local_directory_monitor_constructor;
dir_monitor_class->cancel = g_local_directory_monitor_cancel;
g_object_class_install_property (gobject_class, PROP_DIRNAME,
g_param_spec_string ("dirname", "Directory name", "Directory to monitor",
NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
klass->mount_notify = FALSE;
}
static void
g_local_directory_monitor_init (GLocalDirectoryMonitor* local_monitor)
{
}
static void
mounts_changed (GUnixMountMonitor *mount_monitor,
gpointer user_data)
{
GLocalDirectoryMonitor *local_monitor = user_data;
GUnixMount *mount;
gboolean is_mounted;
GFile *file;
/* Emulate unmount detection */
mount = g_get_unix_mount_at (local_monitor->dirname, NULL);
is_mounted = mount != NULL;
if (mount)
g_unix_mount_free (mount);
if (local_monitor->was_mounted != is_mounted)
{
if (local_monitor->was_mounted && !is_mounted)
{
file = g_file_new_for_path (local_monitor->dirname);
g_directory_monitor_emit_event (G_DIRECTORY_MONITOR (local_monitor),
file, NULL,
G_FILE_MONITOR_EVENT_UNMOUNTED);
g_object_unref (file);
}
local_monitor->was_mounted = is_mounted;
}
}
static gint
_compare_monitor_class_by_prio (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
GType *type1 = (GType *) a, *type2 = (GType *) b;
GLocalDirectoryMonitorClass *klass1, *klass2;
gint ret;
klass1 = G_LOCAL_DIRECTORY_MONITOR_CLASS (g_type_class_ref (*type1));
klass2 = G_LOCAL_DIRECTORY_MONITOR_CLASS (g_type_class_ref (*type2));
ret = klass1->prio - klass2->prio;
g_type_class_unref (klass1);
g_type_class_unref (klass2);
return ret;
}
extern GType g_inotify_directory_monitor_get_type (void);
static gpointer
get_default_local_directory_monitor (gpointer data)
{
GType *monitor_impls, chosen_type;
guint n_monitor_impls;
GType *ret = (GType *) data;
gint i;
#if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
/* Register Inotify monitor */
g_inotify_directory_monitor_get_type ();
#endif
g_io_modules_ensure_loaded (GIO_MODULE_DIR);
monitor_impls = g_type_children (G_TYPE_LOCAL_DIRECTORY_MONITOR,
&n_monitor_impls);
chosen_type = G_TYPE_INVALID;
g_qsort_with_data (monitor_impls,
n_monitor_impls,
sizeof (GType),
_compare_monitor_class_by_prio,
NULL);
for (i = n_monitor_impls - 1; i >= 0 && chosen_type == G_TYPE_INVALID; i--)
{
GLocalDirectoryMonitorClass *klass;
klass = G_LOCAL_DIRECTORY_MONITOR_CLASS (g_type_class_ref (monitor_impls[i]));
if (klass->is_supported())
chosen_type = monitor_impls[i];
g_type_class_unref (klass);
}
g_free (monitor_impls);
*ret = chosen_type;
return NULL;
}
/**
* g_local_directory_monitor_new:
* @dirname: filename of the directory to monitor.
* @flags: #GFileMonitorFlags.
*
* Returns: new #GDirectoryMonitor for the given @dirname.
**/
GDirectoryMonitor*
g_local_directory_monitor_new (const char* dirname,
GFileMonitorFlags flags)
{
static GOnce once_init = G_ONCE_INIT;
static GType monitor_type = G_TYPE_INVALID;
g_once (&once_init, get_default_local_directory_monitor, &monitor_type);
if (monitor_type != G_TYPE_INVALID)
return G_DIRECTORY_MONITOR (g_object_new (monitor_type, "dirname", dirname, NULL));
return NULL;
}
static gboolean
g_local_directory_monitor_cancel (GDirectoryMonitor* monitor)
{
GLocalDirectoryMonitor *local_monitor = G_LOCAL_DIRECTORY_MONITOR (monitor);
if (local_monitor->mount_monitor)
{
g_signal_handlers_disconnect_by_func (local_monitor->mount_monitor, mounts_changed, local_monitor);
g_object_unref (local_monitor->mount_monitor);
local_monitor->mount_monitor = NULL;
}
return TRUE;
}

View File

@ -0,0 +1,65 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_DIRECTORY_MONITOR_H__
#define __G_LOCAL_DIRECTORY_MONITOR_H__
#include <glib-object.h>
#include <gio/gdirectorymonitor.h>
#include "gunixmounts.h"
G_BEGIN_DECLS
#define G_TYPE_LOCAL_DIRECTORY_MONITOR (g_local_directory_monitor_get_type ())
#define G_LOCAL_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_DIRECTORY_MONITOR, GLocalDirectoryMonitor))
#define G_LOCAL_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_LOCAL_DIRECTORY_MONITOR, GLocalDirectoryMonitorClass))
#define G_IS_LOCAL_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_DIRECTORY_MONITOR))
#define G_IS_LOCAL_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_DIRECTORY_MONITOR))
typedef struct _GLocalDirectoryMonitor GLocalDirectoryMonitor;
typedef struct _GLocalDirectoryMonitorClass GLocalDirectoryMonitorClass;
struct _GLocalDirectoryMonitor
{
GDirectoryMonitor parent_instance;
gchar *dirname;
/* For mount emulation */
GUnixMountMonitor *mount_monitor;
gboolean was_mounted;
};
struct _GLocalDirectoryMonitorClass {
GDirectoryMonitorClass parent_class;
gint prio;
gboolean mount_notify;
gboolean (*is_supported) (void);
};
GType g_local_directory_monitor_get_type (void) G_GNUC_CONST;
GDirectoryMonitor* g_local_directory_monitor_new (const char* dirname,
GFileMonitorFlags flags);
G_END_DECLS
#endif /* __G_LOCAL_DIRECTORY_MONITOR_H__ */

1826
gio/glocalfile.c Normal file

File diff suppressed because it is too large Load Diff

51
gio/glocalfile.h Normal file
View File

@ -0,0 +1,51 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_H__
#define __G_LOCAL_FILE_H__
#include <gio/gfile.h>
G_BEGIN_DECLS
#define G_TYPE_LOCAL_FILE (g_local_file_get_type ())
#define G_LOCAL_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_FILE, GLocalFile))
#define G_LOCAL_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LOCAL_FILE, GLocalFileClass))
#define G_IS_LOCAL_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_FILE))
#define G_IS_LOCAL_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE))
#define G_LOCAL_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LOCAL_FILE, GLocalFileClass))
typedef struct _GLocalFile GLocalFile;
typedef struct _GLocalFileClass GLocalFileClass;
struct _GLocalFileClass
{
GObjectClass parent_class;
};
GType g_local_file_get_type (void) G_GNUC_CONST;
GFile * g_local_file_new (const char *filename);
G_END_DECLS
#endif /* __G_LOCAL_FILE_H__ */

228
gio/glocalfileenumerator.c Normal file
View File

@ -0,0 +1,228 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <glib.h>
#include <glocalfileenumerator.h>
#include <glocalfileinfo.h>
#include "glibintl.h"
/* TODO:
* It would be nice to use the dirent->d_type to check file type without
* needing to stat each files on linux and other systems that support it.
* (question: does that following symlink or not?)
*/
struct _GLocalFileEnumerator
{
GFileEnumerator parent;
GFileAttributeMatcher *matcher;
GDir *dir;
char *filename;
char *attributes;
GFileQueryInfoFlags flags;
gboolean got_parent_info;
GLocalParentFileInfo parent_info;
gboolean follow_symlinks;
};
G_DEFINE_TYPE (GLocalFileEnumerator, g_local_file_enumerator, G_TYPE_FILE_ENUMERATOR);
static GFileInfo *g_local_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
static gboolean g_local_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
static void
g_local_file_enumerator_finalize (GObject *object)
{
GLocalFileEnumerator *local;
local = G_LOCAL_FILE_ENUMERATOR (object);
g_free (local->filename);
g_file_attribute_matcher_unref (local->matcher);
if (local->dir)
{
g_dir_close (local->dir);
local->dir = NULL;
}
if (G_OBJECT_CLASS (g_local_file_enumerator_parent_class)->finalize)
(*G_OBJECT_CLASS (g_local_file_enumerator_parent_class)->finalize) (object);
}
static void
g_local_file_enumerator_class_init (GLocalFileEnumeratorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
gobject_class->finalize = g_local_file_enumerator_finalize;
enumerator_class->next_file = g_local_file_enumerator_next_file;
enumerator_class->close = g_local_file_enumerator_close;
}
static void
g_local_file_enumerator_init (GLocalFileEnumerator *local)
{
}
static void
convert_file_to_io_error (GError **error,
GError *file_error)
{
int new_code;
if (file_error == NULL)
return;
new_code = G_IO_ERROR_FAILED;
if (file_error->domain == G_FILE_ERROR) {
switch (file_error->code) {
case G_FILE_ERROR_NOENT:
new_code = G_IO_ERROR_NOT_FOUND;
break;
case G_FILE_ERROR_ACCES:
new_code = G_IO_ERROR_PERMISSION_DENIED;
break;
case G_FILE_ERROR_NOTDIR:
new_code = G_IO_ERROR_NOT_DIRECTORY;
break;
default:
break;
}
}
g_set_error (error, G_IO_ERROR,
new_code,
"%s", file_error->message);
}
GFileEnumerator *
g_local_file_enumerator_new (const char *filename,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error)
{
GLocalFileEnumerator *local;
GDir *dir;
GError *dir_error;
int new_code;
dir_error = NULL;
dir = g_dir_open (filename, 0, error != NULL ? &dir_error : NULL);
if (dir == NULL) {
convert_file_to_io_error (error, dir_error);
g_error_free (dir_error);
return NULL;
}
local = g_object_new (G_TYPE_LOCAL_FILE_ENUMERATOR, NULL);
local->dir = dir;
local->filename = g_strdup (filename);
local->matcher = g_file_attribute_matcher_new (attributes);
local->flags = flags;
return G_FILE_ENUMERATOR (local);
}
static GFileInfo *
g_local_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
GLocalFileEnumerator *local = G_LOCAL_FILE_ENUMERATOR (enumerator);
const char *filename;
char *path;
GFileInfo *info;
GError *my_error = NULL;
if (!local->got_parent_info)
{
_g_local_file_info_get_parent_info (local->filename, local->matcher, &local->parent_info);
local->got_parent_info = TRUE;
}
next_file:
filename = g_dir_read_name (local->dir);
if (filename == NULL)
return NULL;
path = g_build_filename (local->filename, filename, NULL);
info = _g_local_file_info_get (filename, path,
local->matcher,
local->flags,
&local->parent_info,
&my_error);
g_free (path);
if (info == NULL)
{
/* Failed to get info */
/* If the file does not exist there might have been a race where
* the file was removed between the readdir and the stat, so we
* ignore the file. */
if (my_error->domain == G_IO_ERROR &&
my_error->code == G_IO_ERROR_NOT_FOUND)
{
g_error_free (my_error);
goto next_file;
}
else
g_propagate_error (error, my_error);
}
return info;
}
static gboolean
g_local_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
GLocalFileEnumerator *local = G_LOCAL_FILE_ENUMERATOR (enumerator);
if (local->dir)
{
g_dir_close (local->dir);
local->dir = NULL;
}
return TRUE;
}

View File

@ -0,0 +1,60 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_ENUMERATOR_H__
#define __G_LOCAL_FILE_ENUMERATOR_H__
#include <gfileenumerator.h>
#include <gfileinfo.h>
#include <gfile.h>
G_BEGIN_DECLS
#define G_TYPE_LOCAL_FILE_ENUMERATOR (g_local_file_enumerator_get_type ())
#define G_LOCAL_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_FILE_ENUMERATOR, GLocalFileEnumerator))
#define G_LOCAL_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LOCAL_FILE_ENUMERATOR, GLocalFileEnumeratorClass))
#define G_IS_LOCAL_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_FILE_ENUMERATOR))
#define G_IS_LOCAL_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE_ENUMERATOR))
#define G_LOCAL_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LOCAL_FILE_ENUMERATOR, GLocalFileEnumeratorClass))
typedef struct _GLocalFileEnumerator GLocalFileEnumerator;
typedef struct _GLocalFileEnumeratorClass GLocalFileEnumeratorClass;
typedef struct _GLocalFileEnumeratorPrivate GLocalFileEnumeratorPrivate;
struct _GLocalFileEnumeratorClass
{
GFileEnumeratorClass parent_class;
};
GType g_local_file_enumerator_get_type (void) G_GNUC_CONST;
GFileEnumerator *g_local_file_enumerator_new (const char *filename,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_FILE_LOCAL_FILE_ENUMERATOR_H__ */

2216
gio/glocalfileinfo.c Normal file

File diff suppressed because it is too large Load Diff

68
gio/glocalfileinfo.h Normal file
View File

@ -0,0 +1,68 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_INFO_H__
#define __G_LOCAL_FILE_INFO_H__
#include <gio/gfileinfo.h>
#include <gio/gfile.h>
#include <sys/stat.h>
G_BEGIN_DECLS
typedef struct {
gboolean writable;
gboolean is_sticky;
int owner;
dev_t device;
} GLocalParentFileInfo;
void _g_local_file_info_get_parent_info (const char *dir,
GFileAttributeMatcher *attribute_matcher,
GLocalParentFileInfo *parent_info);
GFileInfo *_g_local_file_info_get (const char *basename,
const char *path,
GFileAttributeMatcher *attribute_matcher,
GFileQueryInfoFlags flags,
GLocalParentFileInfo *parent_info,
GError **error);
GFileInfo *_g_local_file_info_get_from_fd (int fd,
char *attributes,
GError **error);
char * _g_local_file_info_create_etag (struct stat *statbuf);
gboolean _g_local_file_info_set_attribute (char *filename,
const char *attribute,
const GFileAttributeValue *value,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
gboolean _g_local_file_info_set_attributes (char *filename,
GFileInfo *info,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_FILE_LOCAL_FILE_INFO_H__ */

319
gio/glocalfileinputstream.c Normal file
View File

@ -0,0 +1,319 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <glib.h>
#include <glib/gstdio.h>
#include "gioerror.h"
#include "glocalfileinputstream.h"
#include "glocalfileinfo.h"
#include "glibintl.h"
G_DEFINE_TYPE (GLocalFileInputStream, g_local_file_input_stream, G_TYPE_FILE_INPUT_STREAM);
struct _GLocalFileInputStreamPrivate {
int fd;
};
static gssize g_local_file_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gssize g_local_file_input_stream_skip (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_local_file_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
static goffset g_local_file_input_stream_tell (GFileInputStream *stream);
static gboolean g_local_file_input_stream_can_seek (GFileInputStream *stream);
static gboolean g_local_file_input_stream_seek (GFileInputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
static GFileInfo *g_local_file_input_stream_query_info (GFileInputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
static void
g_local_file_input_stream_finalize (GObject *object)
{
GLocalFileInputStream *file;
file = G_LOCAL_FILE_INPUT_STREAM (object);
if (G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize)
(*G_OBJECT_CLASS (g_local_file_input_stream_parent_class)->finalize) (object);
}
static void
g_local_file_input_stream_class_init (GLocalFileInputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (GLocalFileInputStreamPrivate));
gobject_class->finalize = g_local_file_input_stream_finalize;
stream_class->read = g_local_file_input_stream_read;
stream_class->skip = g_local_file_input_stream_skip;
stream_class->close = g_local_file_input_stream_close;
file_stream_class->tell = g_local_file_input_stream_tell;
file_stream_class->can_seek = g_local_file_input_stream_can_seek;
file_stream_class->seek = g_local_file_input_stream_seek;
file_stream_class->query_info = g_local_file_input_stream_query_info;
}
static void
g_local_file_input_stream_init (GLocalFileInputStream *info)
{
info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info,
G_TYPE_LOCAL_FILE_INPUT_STREAM,
GLocalFileInputStreamPrivate);
}
/**
* g_local_file_input_stream_new:
* @fd: File Descriptor.
*
* Returns: #GFileInputStream for the given file descriptor.
**/
GFileInputStream *
g_local_file_input_stream_new (int fd)
{
GLocalFileInputStream *stream;
stream = g_object_new (G_TYPE_LOCAL_FILE_INPUT_STREAM, NULL);
stream->priv->fd = fd;
return G_FILE_INPUT_STREAM (stream);
}
static gssize
g_local_file_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GLocalFileInputStream *file;
gssize res;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
res = -1;
while (1)
{
if (g_cancellable_set_error_if_cancelled (cancellable, error))
break;
res = read (file->priv->fd, buffer, count);
if (res == -1)
{
if (errno == EINTR)
continue;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error reading from file: %s"),
g_strerror (errno));
}
break;
}
return res;
}
static gssize
g_local_file_input_stream_skip (GInputStream *stream,
gsize count,
GCancellable *cancellable,
GError **error)
{
off_t res, start;
GLocalFileInputStream *file;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
start = lseek (file->priv->fd, 0, SEEK_CUR);
if (start == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error seeking in file: %s"),
g_strerror (errno));
return -1;
}
res = lseek (file->priv->fd, count, SEEK_CUR);
if (res == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error seeking in file: %s"),
g_strerror (errno));
return -1;
}
return res - start;
}
static gboolean
g_local_file_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
GLocalFileInputStream *file;
int res;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
if (file->priv->fd == -1)
return TRUE;
while (1)
{
res = close (file->priv->fd);
if (res == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error closing file: %s"),
g_strerror (errno));
}
break;
}
return res != -1;
}
static goffset
g_local_file_input_stream_tell (GFileInputStream *stream)
{
GLocalFileInputStream *file;
off_t pos;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
pos = lseek (file->priv->fd, 0, SEEK_CUR);
if (pos == (off_t)-1)
return 0;
return pos;
}
static gboolean
g_local_file_input_stream_can_seek (GFileInputStream *stream)
{
GLocalFileInputStream *file;
off_t pos;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
pos = lseek (file->priv->fd, 0, SEEK_CUR);
if (pos == (off_t)-1 &&
errno == ESPIPE)
return FALSE;
return TRUE;
}
static int
seek_type_to_lseek (GSeekType type)
{
switch (type)
{
default:
case G_SEEK_CUR:
return SEEK_CUR;
case G_SEEK_SET:
return SEEK_SET;
case G_SEEK_END:
return SEEK_END;
}
}
static gboolean
g_local_file_input_stream_seek (GFileInputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
GLocalFileInputStream *file;
off_t pos;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type));
if (pos == (off_t)-1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error seeking in file: %s"),
g_strerror (errno));
return FALSE;
}
return TRUE;
}
static GFileInfo *
g_local_file_input_stream_query_info (GFileInputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error)
{
GLocalFileInputStream *file;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
return _g_local_file_info_get_from_fd (file->priv->fd,
attributes,
error);
}

View File

@ -0,0 +1,60 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_INPUT_STREAM_H__
#define __G_LOCAL_FILE_INPUT_STREAM_H__
#include <gio/gfileinputstream.h>
G_BEGIN_DECLS
#define G_TYPE_LOCAL_FILE_INPUT_STREAM (g_local_file_input_stream_get_type ())
#define G_LOCAL_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_FILE_INPUT_STREAM, GLocalFileInputStream))
#define G_LOCAL_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LOCAL_FILE_INPUT_STREAM, GLocalFileInputStreamClass))
#define G_IS_LOCAL_FILE_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_FILE_INPUT_STREAM))
#define G_IS_LOCAL_FILE_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE_INPUT_STREAM))
#define G_LOCAL_FILE_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LOCAL_FILE_INPUT_STREAM, GLocalFileInputStreamClass))
typedef struct _GLocalFileInputStream GLocalFileInputStream;
typedef struct _GLocalFileInputStreamClass GLocalFileInputStreamClass;
typedef struct _GLocalFileInputStreamPrivate GLocalFileInputStreamPrivate;
struct _GLocalFileInputStream
{
GFileInputStream parent;
/*< private >*/
GLocalFileInputStreamPrivate *priv;
};
struct _GLocalFileInputStreamClass
{
GFileInputStreamClass parent_class;
};
GType g_local_file_input_stream_get_type (void) G_GNUC_CONST;
GFileInputStream *g_local_file_input_stream_new (int fd);
G_END_DECLS
#endif /* __G_LOCAL_FILE_INPUT_STREAM_H__ */

211
gio/glocalfilemonitor.c Normal file
View File

@ -0,0 +1,211 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include "glocalfilemonitor.h"
#include "giomodule.h"
#include <string.h>
enum
{
PROP_0,
PROP_FILENAME
};
G_DEFINE_ABSTRACT_TYPE (GLocalFileMonitor, g_local_file_monitor, G_TYPE_FILE_MONITOR)
static void
g_local_file_monitor_init (GLocalFileMonitor* local_monitor)
{
}
static void
g_local_file_monitor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
case PROP_FILENAME:
/* Do nothing */
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static GObject *
g_local_file_monitor_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
GLocalFileMonitorClass *klass;
GObjectClass *parent_class;
GLocalFileMonitor *local_monitor;
const gchar *filename = NULL;
gint i;
klass = G_LOCAL_FILE_MONITOR_CLASS (g_type_class_peek (G_TYPE_LOCAL_FILE_MONITOR));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
local_monitor = G_LOCAL_FILE_MONITOR (obj);
for (i = 0; i < n_construct_properties; i++)
{
if (strcmp ("filename", g_param_spec_get_name (construct_properties[i].pspec)) == 0)
{
g_assert (G_VALUE_HOLDS_STRING (construct_properties[i].value));
filename = g_value_get_string (construct_properties[i].value);
break;
}
}
g_assert (filename != NULL);
local_monitor->filename = g_strdup (filename);
return obj;
}
static void
g_local_file_monitor_finalize (GObject *object)
{
GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (object);
if (local_monitor->filename)
{
g_free (local_monitor->filename);
local_monitor->filename = NULL;
}
if (G_OBJECT_CLASS (g_local_file_monitor_parent_class)->finalize)
(*G_OBJECT_CLASS (g_local_file_monitor_parent_class)->finalize) (object);
}
static void
g_local_file_monitor_class_init (GLocalFileMonitorClass* klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = g_local_file_monitor_set_property;
gobject_class->finalize = g_local_file_monitor_finalize;
gobject_class->constructor = g_local_file_monitor_constructor;
g_object_class_install_property (gobject_class, PROP_FILENAME,
g_param_spec_string ("filename", "File name", "File name to monitor",
NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
}
static gint
_compare_monitor_class_by_prio (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
GType *type1 = (GType *) a, *type2 = (GType *) b;
GLocalFileMonitorClass *klass1, *klass2;
gint ret;
klass1 = G_LOCAL_FILE_MONITOR_CLASS (g_type_class_ref (*type1));
klass2 = G_LOCAL_FILE_MONITOR_CLASS (g_type_class_ref (*type2));
ret = klass1->prio - klass2->prio;
g_type_class_unref (klass1);
g_type_class_unref (klass2);
return ret;
}
extern GType g_inotify_file_monitor_get_type (void);
static gpointer
get_default_local_file_monitor (gpointer data)
{
GType *monitor_impls, chosen_type;
guint n_monitor_impls;
gint i;
GType *ret = (GType *) data;
#if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
/* Register Inotify monitor */
g_inotify_file_monitor_get_type ();
#endif
g_io_modules_ensure_loaded (GIO_MODULE_DIR);
monitor_impls = g_type_children (G_TYPE_LOCAL_FILE_MONITOR,
&n_monitor_impls);
chosen_type = G_TYPE_INVALID;
g_qsort_with_data (monitor_impls,
n_monitor_impls,
sizeof (GType),
_compare_monitor_class_by_prio,
NULL);
for (i = n_monitor_impls - 1; i >= 0 && chosen_type == G_TYPE_INVALID; i--)
{
GLocalFileMonitorClass *klass;
klass = G_LOCAL_FILE_MONITOR_CLASS (g_type_class_ref (monitor_impls[i]));
if (klass->is_supported())
chosen_type = monitor_impls[i];
g_type_class_unref (klass);
}
g_free (monitor_impls);
*ret = chosen_type;
return NULL;
}
/**
* g_local_file_monitor_new:
* @pathname: path name to monitor.
* @flags: #GFileMonitorFlags.
*
* Returns: a new #GFileMonitor for the given @pathname.
**/
GFileMonitor*
g_local_file_monitor_new (const char* pathname,
GFileMonitorFlags flags)
{
static GOnce once_init = G_ONCE_INIT;
static GType monitor_type = G_TYPE_INVALID;
g_once (&once_init, get_default_local_file_monitor, &monitor_type);
if (monitor_type != G_TYPE_INVALID)
return G_FILE_MONITOR (g_object_new (monitor_type, "filename", pathname, NULL));
return NULL;
}

59
gio/glocalfilemonitor.h Normal file
View File

@ -0,0 +1,59 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_MONITOR_H__
#define __G_LOCAL_FILE_MONITOR_H__
#include <glib-object.h>
#include <gio/gfilemonitor.h>
G_BEGIN_DECLS
#define G_TYPE_LOCAL_FILE_MONITOR (g_local_file_monitor_get_type ())
#define G_LOCAL_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_FILE_MONITOR, GLocalFileMonitor))
#define G_LOCAL_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_LOCAL_FILE_MONITOR, GLocalFileMonitorClass))
#define G_IS_LOCAL_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_FILE_MONITOR))
#define G_IS_LOCAL_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE_MONITOR))
typedef struct _GLocalFileMonitor GLocalFileMonitor;
typedef struct _GLocalFileMonitorClass GLocalFileMonitorClass;
struct _GLocalFileMonitor
{
GFileMonitor parent_instance;
gchar *filename;
};
struct _GLocalFileMonitorClass {
GFileMonitorClass parent_class;
gint prio;
gboolean (*is_supported) (void);
};
GType g_local_file_monitor_get_type (void) G_GNUC_CONST;
GFileMonitor* g_local_file_monitor_new (const char* pathname,
GFileMonitorFlags flags);
G_END_DECLS
#endif /* __G_LOCAL_FILE_MONITOR_H__ */

View File

@ -0,0 +1,910 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
#include "glibintl.h"
#include "gioerror.h"
#include "glocalfileoutputstream.h"
#include "glocalfileinfo.h"
G_DEFINE_TYPE (GLocalFileOutputStream, g_local_file_output_stream, G_TYPE_FILE_OUTPUT_STREAM);
/* Some of the file replacement code was based on the code from gedit,
* relicenced to LGPL with permissions from the authors.
*/
#define BACKUP_EXTENSION "~"
struct _GLocalFileOutputStreamPrivate {
char *tmp_filename;
char *original_filename;
char *backup_filename;
char *etag;
int fd;
};
static gssize g_local_file_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean g_local_file_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static GFileInfo *g_local_file_output_stream_query_info (GFileOutputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error);
static char * g_local_file_output_stream_get_etag (GFileOutputStream *stream);
static goffset g_local_file_output_stream_tell (GFileOutputStream *stream);
static gboolean g_local_file_output_stream_can_seek (GFileOutputStream *stream);
static gboolean g_local_file_output_stream_seek (GFileOutputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error);
static gboolean g_local_file_output_stream_can_truncate (GFileOutputStream *stream);
static gboolean g_local_file_output_stream_truncate (GFileOutputStream *stream,
goffset size,
GCancellable *cancellable,
GError **error);
static void
g_local_file_output_stream_finalize (GObject *object)
{
GLocalFileOutputStream *file;
file = G_LOCAL_FILE_OUTPUT_STREAM (object);
g_free (file->priv->tmp_filename);
g_free (file->priv->original_filename);
g_free (file->priv->backup_filename);
g_free (file->priv->etag);
if (G_OBJECT_CLASS (g_local_file_output_stream_parent_class)->finalize)
(*G_OBJECT_CLASS (g_local_file_output_stream_parent_class)->finalize) (object);
}
static void
g_local_file_output_stream_class_init (GLocalFileOutputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
GFileOutputStreamClass *file_stream_class = G_FILE_OUTPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (GLocalFileOutputStreamPrivate));
gobject_class->finalize = g_local_file_output_stream_finalize;
stream_class->write = g_local_file_output_stream_write;
stream_class->close = g_local_file_output_stream_close;
file_stream_class->query_info = g_local_file_output_stream_query_info;
file_stream_class->get_etag = g_local_file_output_stream_get_etag;
file_stream_class->tell = g_local_file_output_stream_tell;
file_stream_class->can_seek = g_local_file_output_stream_can_seek;
file_stream_class->seek = g_local_file_output_stream_seek;
file_stream_class->can_truncate = g_local_file_output_stream_can_truncate;
file_stream_class->truncate = g_local_file_output_stream_truncate;
}
static void
g_local_file_output_stream_init (GLocalFileOutputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
G_TYPE_LOCAL_FILE_OUTPUT_STREAM,
GLocalFileOutputStreamPrivate);
}
static gssize
g_local_file_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *file;
gssize res;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
while (1)
{
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
res = write (file->priv->fd, buffer, count);
if (res == -1)
{
if (errno == EINTR)
continue;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error writing to file: %s"),
g_strerror (errno));
}
break;
}
return res;
}
static gboolean
g_local_file_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *file;
struct stat final_stat;
int res;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
if (file->priv->tmp_filename)
{
/* We need to move the temp file to its final place,
* and possibly create the backup file
*/
if (file->priv->backup_filename)
{
if (g_cancellable_set_error_if_cancelled (cancellable, error))
goto err_out;
#ifdef HAVE_LINK
/* create original -> backup link, the original is then renamed over */
if (unlink (file->priv->backup_filename) != 0 &&
errno != ENOENT)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Error removing old backup link: %s"),
g_strerror (errno));
goto err_out;
}
if (link (file->priv->original_filename, file->priv->backup_filename) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Error creating backup link: %s"),
g_strerror (errno));
goto err_out;
}
#else
/* If link not supported, just rename... */
if (!rename (file->priv->original_filename, file->priv->backup_filename) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Error creating backup copy: %s"),
g_strerror (errno));
goto err_out;
}
#endif
}
if (g_cancellable_set_error_if_cancelled (cancellable, error))
goto err_out;
/* tmp -> original */
if (rename (file->priv->tmp_filename, file->priv->original_filename) != 0)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error renamining temporary file: %s"),
g_strerror (errno));
goto err_out;
}
}
if (g_cancellable_set_error_if_cancelled (cancellable, error))
goto err_out;
if (fstat (file->priv->fd, &final_stat) == 0)
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
while (1)
{
res = close (file->priv->fd);
if (res == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error closing file: %s"),
g_strerror (errno));
}
break;
}
return res != -1;
err_out:
/* A simple try to close the fd in case we fail before the actual close */
close (file->priv->fd);
return FALSE;
}
static char *
g_local_file_output_stream_get_etag (GFileOutputStream *stream)
{
GLocalFileOutputStream *file;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
return g_strdup (file->priv->etag);
}
static goffset
g_local_file_output_stream_tell (GFileOutputStream *stream)
{
GLocalFileOutputStream *file;
off_t pos;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
pos = lseek (file->priv->fd, 0, SEEK_CUR);
if (pos == (off_t)-1)
return 0;
return pos;
}
static gboolean
g_local_file_output_stream_can_seek (GFileOutputStream *stream)
{
GLocalFileOutputStream *file;
off_t pos;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
pos = lseek (file->priv->fd, 0, SEEK_CUR);
if (pos == (off_t)-1 &&
errno == ESPIPE)
return FALSE;
return TRUE;
}
static int
seek_type_to_lseek (GSeekType type)
{
switch (type)
{
default:
case G_SEEK_CUR:
return SEEK_CUR;
case G_SEEK_SET:
return SEEK_SET;
case G_SEEK_END:
return SEEK_END;
}
}
static gboolean
g_local_file_output_stream_seek (GFileOutputStream *stream,
goffset offset,
GSeekType type,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *file;
off_t pos;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type));
if (pos == (off_t)-1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error seeking in file: %s"),
g_strerror (errno));
return FALSE;
}
return TRUE;
}
static gboolean
g_local_file_output_stream_can_truncate (GFileOutputStream *stream)
{
/* We can't truncate pipes and stuff where we can't seek */
return g_local_file_output_stream_can_seek (stream);
}
static gboolean
g_local_file_output_stream_truncate (GFileOutputStream *stream,
goffset size,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *file;
int res;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
restart:
res = ftruncate(file->priv->fd, size);
if (res == -1)
{
if (errno == EINTR)
{
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
goto restart;
}
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error truncating file: %s"),
g_strerror (errno));
return FALSE;
}
return TRUE;
}
static GFileInfo *
g_local_file_output_stream_query_info (GFileOutputStream *stream,
char *attributes,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *file;
file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
return _g_local_file_info_get_from_fd (file->priv->fd,
attributes,
error);
}
/**
* g_local_file_output_stream_create:
* @filename:
* @flags:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns: #GFileOutputStream.
**/
GFileOutputStream *
g_local_file_output_stream_create (const char *filename,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *stream;
int mode;
int fd;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
mode = 0600;
else
mode = 0666;
fd = g_open (filename,
O_CREAT | O_EXCL | O_WRONLY,
0666);
if (fd == -1)
{
int errsv = errno;
if (errsv == EINVAL)
/* This must be an invalid filename, on e.g. FAT */
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Invalid filename"));
else
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error opening file '%s': %s"),
filename, g_strerror (errsv));
return NULL;
}
stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
stream->priv->fd = fd;
return G_FILE_OUTPUT_STREAM (stream);
}
/**
* g_local_file_output_stream_append:
* @filename:
* @flags:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns:
**/
GFileOutputStream *
g_local_file_output_stream_append (const char *filename,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *stream;
int mode;
int fd;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
mode = 0600;
else
mode = 0666;
fd = g_open (filename,
O_CREAT | O_APPEND | O_WRONLY,
mode);
if (fd == -1)
{
int errsv = errno;
if (errsv == EINVAL)
/* This must be an invalid filename, on e.g. FAT */
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Invalid filename"));
else
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error opening file '%s': %s"),
filename, g_strerror (errsv));
return NULL;
}
stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
stream->priv->fd = fd;
return G_FILE_OUTPUT_STREAM (stream);
}
static char *
create_backup_filename (const char *filename)
{
return g_strconcat (filename, BACKUP_EXTENSION, NULL);
}
#define BUFSIZE 8192 /* size of normal write buffer */
static gboolean
copy_file_data (gint sfd,
gint dfd,
GError **error)
{
gboolean ret = TRUE;
gpointer buffer;
const gchar *write_buffer;
ssize_t bytes_read;
ssize_t bytes_to_write;
ssize_t bytes_written;
buffer = g_malloc (BUFSIZE);
do
{
bytes_read = read (sfd, buffer, BUFSIZE);
if (bytes_read == -1)
{
if (errno == EINTR)
continue;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error reading from file: %s"),
g_strerror (errno));
ret = FALSE;
break;
}
bytes_to_write = bytes_read;
write_buffer = buffer;
do
{
bytes_written = write (dfd, write_buffer, bytes_to_write);
if (bytes_written == -1)
{
if (errno == EINTR)
continue;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error writing to file: %s"),
g_strerror (errno));
ret = FALSE;
break;
}
bytes_to_write -= bytes_written;
write_buffer += bytes_written;
}
while (bytes_to_write > 0);
} while ((bytes_read != 0) && (ret == TRUE));
g_free (buffer);
return ret;
}
static int
handle_overwrite_open (const char *filename,
const char *etag,
gboolean create_backup,
char **temp_filename,
GCancellable *cancellable,
GError **error)
{
int fd = -1;
struct stat original_stat;
char *current_etag;
gboolean is_symlink;
int open_flags;
/* We only need read access to the original file if we are creating a backup.
* We also add O_CREATE to avoid a race if the file was just removed */
if (create_backup)
open_flags = O_RDWR | O_CREAT;
else
open_flags = O_WRONLY | O_CREAT;
/* Some systems have O_NOFOLLOW, which lets us avoid some races
* when finding out if the file we opened was a symlink */
#ifdef O_NOFOLLOW
is_symlink = FALSE;
fd = g_open (filename, open_flags | O_NOFOLLOW, 0666);
if (fd == -1 && errno == ELOOP)
{
/* Could be a symlink, or it could be a regular ELOOP error,
* but then the next open will fail too. */
is_symlink = TRUE;
fd = g_open (filename, open_flags, 0666);
}
#else
fd = g_open (filename, open_flags, 0666);
/* This is racy, but we do it as soon as possible to minimize the race */
is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK);
#endif
if (fd == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error opening file '%s': %s"),
filename, g_strerror (errno));
return -1;
}
if (fstat (fd, &original_stat) != 0)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error stating file '%s': %s"),
filename, g_strerror (errno));
goto err_out;
}
/* not a regular file */
if (!S_ISREG (original_stat.st_mode))
{
if (S_ISDIR (original_stat.st_mode))
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_IS_DIRECTORY,
_("Target file is a directory"));
else
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_REGULAR_FILE,
_("Target file is not a regular file"));
goto err_out;
}
if (etag != NULL)
{
current_etag = _g_local_file_info_create_etag (&original_stat);
if (strcmp (etag, current_etag) != 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_WRONG_ETAG,
_("The file was externally modified"));
g_free (current_etag);
goto err_out;
}
g_free (current_etag);
}
/* We use two backup strategies.
* The first one (which is faster) consist in saving to a
* tmp file then rename the original file to the backup and the
* tmp file to the original name. This is fast but doesn't work
* when the file is a link (hard or symbolic) or when we can't
* write to the current dir or can't set the permissions on the
* new file.
* The second strategy consist simply in copying the old file
* to a backup file and rewrite the contents of the file.
*/
if (!(original_stat.st_nlink > 1) && !is_symlink)
{
char *dirname, *tmp_filename;
int tmpfd;
dirname = g_path_get_dirname (filename);
tmp_filename = g_build_filename (dirname, ".goutputstream-XXXXXX", NULL);
g_free (dirname);
tmpfd = g_mkstemp (tmp_filename);
if (tmpfd == -1)
{
g_free (tmp_filename);
goto fallback_strategy;
}
/* try to keep permissions */
if (
#ifdef F_CHOWN
fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 ||
#endif
#ifdef F_CHMOD
fchmod (tmpfd, original_stat.st_mode) == -1 ||
#endif
0
)
{
struct stat tmp_statbuf;
/* Check that we really needed to change something */
if (fstat (tmpfd, &tmp_statbuf) != 0 ||
original_stat.st_uid != tmp_statbuf.st_uid ||
original_stat.st_gid != tmp_statbuf.st_gid ||
original_stat.st_mode != tmp_statbuf.st_mode)
{
close (tmpfd);
unlink (tmp_filename);
g_free (tmp_filename);
goto fallback_strategy;
}
}
close (fd);
*temp_filename = tmp_filename;
return tmpfd;
}
fallback_strategy:
if (create_backup)
{
struct stat tmp_statbuf;
char *backup_filename;
int bfd;
backup_filename = create_backup_filename (filename);
if (unlink (backup_filename) == -1 && errno != ENOENT)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
g_free (backup_filename);
goto err_out;
}
bfd = g_open (backup_filename,
O_WRONLY | O_CREAT | O_EXCL,
original_stat.st_mode & 0777);
if (bfd == -1)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
g_free (backup_filename);
goto err_out;
}
/* If needed, Try to set the group of the backup same as the
* original file. If this fails, set the protection
* bits for the group same as the protection bits for
* others. */
#ifdef HAVE_FCHOWN
if (fstat (bfd, &tmp_statbuf) != 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
unlink (backup_filename);
g_free (backup_filename);
goto err_out;
}
if ((original_stat.st_gid != tmp_statbuf.st_gid) &&
fchown (bfd, (uid_t) -1, original_stat.st_gid) != 0)
{
if (fchmod (bfd,
(original_stat.st_mode & 0707) |
((original_stat.st_mode & 07) << 3)) != 0)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
unlink (backup_filename);
close (bfd);
g_free (backup_filename);
goto err_out;
}
}
#endif
if (!copy_file_data (fd, bfd, NULL))
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
unlink (backup_filename);
close (bfd);
g_free (backup_filename);
goto err_out;
}
close (bfd);
g_free (backup_filename);
/* Seek back to the start of the file after the backup copy */
if (lseek (fd, 0, SEEK_SET) == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error seeking in file: %s"),
g_strerror (errno));
goto err_out;
}
}
/* Truncate the file at the start */
if (ftruncate (fd, 0) == -1)
{
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errno),
_("Error truncating file: %s"),
g_strerror (errno));
goto err_out;
}
return fd;
err_out:
close (fd);
return -1;
}
/**
* g_local_file_output_stream_replace:
* @filename: the file name.
* @etag:
* @create_backup: if set, create a backup of the file.
* @flags:
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
* Returns: #GFileOutputStream
**/
GFileOutputStream *
g_local_file_output_stream_replace (const char *filename,
const char *etag,
gboolean create_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error)
{
GLocalFileOutputStream *stream;
int mode;
int fd;
char *temp_file;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return NULL;
temp_file = NULL;
if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
mode = 0600;
else
mode = 0666;
/* If the file doesn't exist, create it */
fd = g_open (filename,
O_CREAT | O_EXCL | O_WRONLY,
mode);
if (fd == -1 && errno == EEXIST)
{
/* The file already exists */
fd = handle_overwrite_open (filename, etag, create_backup, &temp_file,
cancellable, error);
if (fd == -1)
return NULL;
}
else if (fd == -1)
{
int errsv = errno;
if (errsv == EINVAL)
/* This must be an invalid filename, on e.g. FAT */
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_INVALID_FILENAME,
_("Invalid filename"));
else
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error opening file '%s': %s"),
filename, g_strerror (errsv));
return NULL;
}
stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
stream->priv->fd = fd;
stream->priv->tmp_filename = temp_file;
if (create_backup)
stream->priv->backup_filename = create_backup_filename (filename);
stream->priv->original_filename = g_strdup (filename);
return G_FILE_OUTPUT_STREAM (stream);
}

View File

@ -0,0 +1,73 @@
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#ifndef __G_LOCAL_FILE_OUTPUT_STREAM_H__
#define __G_LOCAL_FILE_OUTPUT_STREAM_H__
#include <gio/gfileoutputstream.h>
#include <gio/gfile.h>
G_BEGIN_DECLS
#define G_TYPE_LOCAL_FILE_OUTPUT_STREAM (g_local_file_output_stream_get_type ())
#define G_LOCAL_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_LOCAL_FILE_OUTPUT_STREAM, GLocalFileOutputStream))
#define G_LOCAL_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_LOCAL_FILE_OUTPUT_STREAM, GLocalFileOutputStreamClass))
#define G_IS_LOCAL_FILE_OUTPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_LOCAL_FILE_OUTPUT_STREAM))
#define G_IS_LOCAL_FILE_OUTPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_LOCAL_FILE_OUTPUT_STREAM))
#define G_LOCAL_FILE_OUTPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_LOCAL_FILE_OUTPUT_STREAM, GLocalFileOutputStreamClass))
typedef struct _GLocalFileOutputStream GLocalFileOutputStream;
typedef struct _GLocalFileOutputStreamClass GLocalFileOutputStreamClass;
typedef struct _GLocalFileOutputStreamPrivate GLocalFileOutputStreamPrivate;
struct _GLocalFileOutputStream
{
GFileOutputStream parent;
/*< private >*/
GLocalFileOutputStreamPrivate *priv;
};
struct _GLocalFileOutputStreamClass
{
GFileOutputStreamClass parent_class;
};
GType g_local_file_output_stream_get_type (void) G_GNUC_CONST;
GFileOutputStream *g_local_file_output_stream_create (const char *filename,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
GFileOutputStream *g_local_file_output_stream_append (const char *filename,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
GFileOutputStream *g_local_file_output_stream_replace (const char *filename,
const char *etag,
gboolean create_backup,
GFileCreateFlags flags,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* __G_LOCAL_FILE_OUTPUT_STREAM_H__ */

Some files were not shown because too many files have changed in this diff Show More