mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 02:46:16 +01:00
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:
parent
8bdbcb9213
commit
3781343738
18
ChangeLog
18
ChangeLog
@ -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.
|
||||
|
10
Makefile.am
10
Makefile.am
@ -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
|
||||
|
||||
|
199
configure.in
199
configure.in
@ -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
|
||||
|
@ -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:
|
||||
|
@ -1,3 +1,3 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
SUBDIRS = glib gobject
|
||||
SUBDIRS = glib gobject gio
|
||||
|
90
docs/reference/gio/Makefile.am
Normal file
90
docs/reference/gio/Makefile.am
Normal 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
|
106
docs/reference/gio/gio-docs.xml
Normal file
106
docs/reference/gio/gio-docs.xml
Normal 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>
|
1159
docs/reference/gio/gio-sections.txt
Normal file
1159
docs/reference/gio/gio-sections.txt
Normal file
File diff suppressed because it is too large
Load Diff
51
docs/reference/gio/gio.types
Normal file
51
docs/reference/gio/gio.types
Normal 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
|
1
docs/reference/gio/version.xml.in
Normal file
1
docs/reference/gio/version.xml.in
Normal file
@ -0,0 +1 @@
|
||||
@VERSION@
|
6
gio-2.0-uninstalled.pc.in
Normal file
6
gio-2.0-uninstalled.pc.in
Normal 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
11
gio-2.0.pc.in
Normal 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:
|
6
gio-unix-2.0-uninstalled.pc.in
Normal file
6
gio-unix-2.0-uninstalled.pc.in
Normal 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
11
gio-unix-2.0.pc.in
Normal 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
225
gio/Makefile.am
Normal 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
33
gio/fam/Makefile.am
Normal 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
245
gio/fam/fam-helper.c
Normal 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
37
gio/fam/fam-helper.h
Normal 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
41
gio/fam/fam-module.c
Normal 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)
|
||||
{
|
||||
}
|
||||
|
152
gio/fam/gfamdirectorymonitor.c
Normal file
152
gio/fam/gfamdirectorymonitor.c
Normal 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));
|
||||
}
|
||||
|
55
gio/fam/gfamdirectorymonitor.h
Normal file
55
gio/fam/gfamdirectorymonitor.h
Normal 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
150
gio/fam/gfamfilemonitor.c
Normal 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
55
gio/fam/gfamfilemonitor.h
Normal 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
535
gio/gappinfo.c
Normal 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
206
gio/gappinfo.h
Normal 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
163
gio/gasynchelper.c
Normal 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
53
gio/gasynchelper.h
Normal 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
107
gio/gasyncresult.c
Normal 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
59
gio/gasyncresult.h
Normal 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
1230
gio/gbufferedinputstream.c
Normal file
File diff suppressed because it is too large
Load Diff
110
gio/gbufferedinputstream.h
Normal file
110
gio/gbufferedinputstream.h
Normal 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
734
gio/gbufferedoutputstream.c
Normal 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 */
|
76
gio/gbufferedoutputstream.h
Normal file
76
gio/gbufferedoutputstream.h
Normal 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
322
gio/gcancellable.c
Normal 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 (¤t_cancellable);
|
||||
l = g_slist_prepend (l, cancellable);
|
||||
g_static_private_set (¤t_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 (¤t_cancellable);
|
||||
|
||||
g_assert (l != NULL);
|
||||
g_assert (l->data == cancellable);
|
||||
|
||||
l = g_slist_delete_link (l, l);
|
||||
g_static_private_set (¤t_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 (¤t_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
74
gio/gcancellable.h
Normal 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
861
gio/gcontenttype.c
Normal 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, ®_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
50
gio/gcontenttype.h
Normal 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
36
gio/gcontenttypeprivate.h
Normal 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
718
gio/gdatainputstream.c
Normal 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
117
gio/gdatainputstream.h
Normal 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
441
gio/gdataoutputstream.c
Normal 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
108
gio/gdataoutputstream.h
Normal 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
2185
gio/gdesktopappinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
54
gio/gdesktopappinfo.h
Normal file
54
gio/gdesktopappinfo.h
Normal 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
472
gio/gdirectorymonitor.c
Normal 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
86
gio/gdirectorymonitor.h
Normal 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
348
gio/gdrive.c
Normal 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
99
gio/gdrive.h
Normal 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
32
gio/gdriveprivate.h
Normal 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
752
gio/gdummyfile.c
Normal 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
51
gio/gdummyfile.h
Normal 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
4345
gio/gfile.c
Normal file
File diff suppressed because it is too large
Load Diff
676
gio/gfile.h
Normal file
676
gio/gfile.h
Normal 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
704
gio/gfileattribute.c
Normal 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
132
gio/gfileattribute.h
Normal 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
617
gio/gfileenumerator.c
Normal 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
130
gio/gfileenumerator.h
Normal 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
257
gio/gfileicon.c
Normal 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
49
gio/gfileicon.h
Normal 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
1924
gio/gfileinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
280
gio/gfileinfo.h
Normal file
280
gio/gfileinfo.h
Normal 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
481
gio/gfileinputstream.c
Normal 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
110
gio/gfileinputstream.h
Normal 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
380
gio/gfilemonitor.c
Normal 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
97
gio/gfilemonitor.h
Normal 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
489
gio/gfilenamecompleter.c
Normal 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
66
gio/gfilenamecompleter.h
Normal 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
613
gio/gfileoutputstream.c
Normal 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
121
gio/gfileoutputstream.h
Normal 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
391
gio/gfilterinputstream.c
Normal 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
65
gio/gfilterinputstream.h
Normal 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
366
gio/gfilteroutputstream.c
Normal 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
65
gio/gfilteroutputstream.h
Normal 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
118
gio/gicon.c
Normal 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
58
gio/gicon.h
Normal 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
1184
gio/ginputstream.c
Normal file
File diff suppressed because it is too large
Load Diff
165
gio/ginputstream.h
Normal file
165
gio/ginputstream.h
Normal 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
4
gio/gio-marshal.list
Normal 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
155
gio/gioerror.c
Normal 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
78
gio/gioerror.h
Normal 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
237
gio/giomodule.c
Normal 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
52
gio/giomodule.h
Normal 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
372
gio/gioscheduler.c
Normal 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
55
gio/gioscheduler.h
Normal 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
260
gio/gloadableicon.c
Normal 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
83
gio/gloadableicon.h
Normal 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__ */
|
290
gio/glocaldirectorymonitor.c
Normal file
290
gio/glocaldirectorymonitor.c
Normal 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;
|
||||
}
|
||||
|
65
gio/glocaldirectorymonitor.h
Normal file
65
gio/glocaldirectorymonitor.h
Normal 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
1826
gio/glocalfile.c
Normal file
File diff suppressed because it is too large
Load Diff
51
gio/glocalfile.h
Normal file
51
gio/glocalfile.h
Normal 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
228
gio/glocalfileenumerator.c
Normal 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;
|
||||
}
|
||||
|
||||
|
60
gio/glocalfileenumerator.h
Normal file
60
gio/glocalfileenumerator.h
Normal 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
2216
gio/glocalfileinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
68
gio/glocalfileinfo.h
Normal file
68
gio/glocalfileinfo.h
Normal 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
319
gio/glocalfileinputstream.c
Normal 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);
|
||||
}
|
60
gio/glocalfileinputstream.h
Normal file
60
gio/glocalfileinputstream.h
Normal 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
211
gio/glocalfilemonitor.c
Normal 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
59
gio/glocalfilemonitor.h
Normal 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__ */
|
910
gio/glocalfileoutputstream.c
Normal file
910
gio/glocalfileoutputstream.c
Normal 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);
|
||||
}
|
73
gio/glocalfileoutputstream.h
Normal file
73
gio/glocalfileoutputstream.h
Normal 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
Loading…
Reference in New Issue
Block a user