Documentation/Maemo 5 Developer Guide/Using Generic Platform Components/GnomeVFS File System

= File System - GnomeVFS =

Maemo includes a powerful file system framework, GnomeVFS. This framework enables applications to use a vast number of different file access protocols without having to know anything about the underlying details. Some examples of the supported protocols are: local file system, HTTP, FTP and OBEX over Bluetooth.

In practice, this means that all GnomeVFS file access methods are transparently available for both developer and end user just by using the framework for file operations. The API for file handling is also much more flexible than the standard platform offerings. It features, for example, asynchronous reading and writing, MIME type support and file monitoring.

All user-file access should be done with GnomeVFS in maemo applications, because file access can be remote. In fact, many applications that come with the operating system on the Maemo compatible device do make use of GnomeVFS. Access to files not visible to the user should be done directly for performance reasons.

A good hands-on starting point is taking a look at the GnomeVFS example in maemo-examples package. Detailed API information can be found in the GnomeVFS API reference

GnomeVFS Example
This section uses the following example:
 * hildon_helloworld-8.c

In maemo, GnomeVFS also provides some filename case insensitivity support, so that the end users do not have to care about the UNIX filename conventions, which are case-sensitive.

The GnomeVFS interface attempts to provide a POSIX-like interface, so that where with POSIX you would use open, in GnomeVFS you can use gnome_vfs_open; and instead of write, you can use gnome_vfs_write, etc. The GnomeVFS function names are sometimes a bit more verbose, but otherwise they attempt to implement the basic API. Some POSIX functions, such as mmap, are impossible to implement in the user space, but normally this is not a big problem. Also some functions fail to work over network connections and outside the local filesystem.

For a simple example of using the GnomeVFS interface functions, see below.

In order to save and load data, at least the following functions are needed:


 * gnome_vfs_init : initializes the GnomeVFS library. Needs to be done once at an early stage at program startup.
 * gnome_vfs_shutdown : frees up resources inside the library and closes it down.
 * gnome_vfs_open : opens the given URI (explained below) and returns a file handle for that if successful.
 * gnome_vfs_get_file_info : get information about a file (similar to, but with broader scope than fstat).
 * gnome_vfs_read : read data from an opened file.
 * gnome_vfs_write : write data into an opened file.

In order to differentiate between different protocols, GnomeVFS uses Uniform Resource 2 syntax when accessing resources. For example in file:///tmp/somefile.txt, the file:// is the protocol to use, and the rest is the location within that protocol space for the resource or file to manipulate. Protocols can be stacked inside a single URI, and the URI also supports username and password combinations (these are best demonstrated in the GnomeVFS API documentation).

The following simple demonstration will be using local files.

A simple application will be extended in the following ways:


 * Implement the "Open" command by using GnomeVFS with full error checking.
 * The memory will be allocated and freed with g_malloc0 and g_free, when loading the contents of the file that the user has selected.
 * Data loaded through "Open" will replace the text in the GtkLabel that is in the center area of the HildonWindow. The label will be switched to support Pango simple text markup, which looks a lot like simple HTML.
 * Notification about loading success and failures will be communicated to the user by using a widget called HildonBanner, which will float a small notification dialog (with an optional icon) in the top-right corner for a while, without blocking the application.
 * N.B. Saving into a file is not implemented in this code, as it is a lab exercise (and it is simpler than opening).
 * File loading failures can be simulated by attempting to load an empty file. Since empty files are not wanted, the code will turn this into an error as well. If no empty file is available, one can easily be created with the touch command (under MyDocs, so that the open dialog can find it). It is also possible to attempt to load a file larger than 100 KiB, since the code limits the file size (artificially), and will refuse to load large files.
 * The goto statement should normally be avoided. Team coding guidelines should be checked to see, whether this is an allowed practice. Note how it is used in this example to cut down the possibility of leaked resources (and typing). Another option for this would be using variable finalizers, but not many people know how to use them, or even that they exist. They are gcc extensions into the C language, and you can find more about them by reading gcc info pages (look for variable attributes).
 * Simple GnomeVFS functions are used here. They are all synchronous, which means that if loading the file takes a long time, the application will remain unresponsive during that time. For small files residing in local storage, this is a risk that is taken knowingly. Synchronous API should not be used when loading files over network due to the greater uncertainty.
 * I/O in most cases will be slightly slower than using a controlled approach with POSIX I/O API (controlled meaning that one should know what to use and how). This is a price that has to be paid in order to enable easy switching to other protocols later.

N.B. Since GnomeVFS is a separate library from GLib, you will have to add the flags and library options that it requires. The pkg-config package name for the library is.

  /**    * hildon_helloworld-8.c    *    * This maemo code example is licensed under a MIT-style license,    * that can be found in the file called "License" in the same  ''  * directory as this file.    * Copyright (c) 2007-2008 Nokia Corporation. All rights reserved.    * '' ''  * We add file loading support using GnomeVFS. Saving files using '' ''  * GnomeVFS is left as an exercise. We also add a small notification '' ''  * widget (HildonBanner).    * '' ''  * Look for lines with "NEW" or "MODIFIED" in them.    */ ''   #include  <font color="#FF0000">&lt;stdlib.h&gt;  <font color="#000080"> #include  <font color="#FF0000">&lt;hildon/hildon-program.h&gt;  <font color="#000080"> #include  <font color="#FF0000">&lt;hildon/hildon-color-button.h&gt;  <font color="#000080"> #include  <font color="#FF0000">&lt;hildon/hildon-find-toolbar.h&gt;  <font color="#000080"> #include  <font color="#FF0000">&lt;hildon/hildon-file-chooser-dialog.h&gt; '' <font color="#9A1900">/* A small notification window widget (NEW). */ ''  <font color="#000080"> #include   <font color="#FF0000">&lt;hildon/hildon-banner.h&gt; '' <font color="#9A1900">/* Pull in the GnomeVFS headers (NEW). */ ''  <font color="#000080"> #include   <font color="#FF0000">&lt;libgnomevfs/gnome-vfs.h&gt; '' <font color="#9A1900">/* Declare the two slant styles. */ ''  <font color="#0000FF">enum   <font color="#FF0000">{ STYLE_SLANT_NORMAL <font color="#990000"> = <font color="#993399">0  <font color="#990000">, STYLE_SLANT_ITALIC <font color="#FF0000">} <font color="#990000"> ;  <font color="#9A1900">/**  '' <font color="#9A1900"> * The application state.   <font color="#9A1900"> */ ''  <font color="#0000FF">typedef   <font color="#0000FF">struct   <font color="#FF0000">{ gboolean styleUseUnderline <font color="#990000"> ; gboolean styleSlant <font color="#990000"> ; GdkColor currentColor <font color="#990000"> ;  <font color="#9A1900">/* Pointer to the label so that we can modify its contents when a  '' <font color="#9A1900">    file is loaded by the user (NEW). */ ''   GtkWidget <font color="#990000"> * textLabel <font color="#990000"> ; gboolean fullScreen <font color="#990000"> ; GtkWidget <font color="#990000"> * findToolbar <font color="#990000"> ; GtkWidget <font color="#990000"> * mainToolbar <font color="#990000"> ; gboolean findToolbarIsVisible <font color="#990000"> ; gboolean mainToolbarIsVisible <font color="#990000"> ; HildonProgram <font color="#990000"> * program <font color="#990000"> ; HildonWindow <font color="#990000"> * window <font color="#990000"> ; <font color="#FF0000">} ApplicationState <font color="#990000"> ; '' <font color="#9A1900">/*... Listing cut for brevity ...*/ ''  <font color="#9A1900">/**   <font color="#9A1900"> * Utility function to print a GnomeVFS I/O related error message to  '' <font color="#9A1900"> * standard error (not seen by the user in graphical mode) (NEW).   <font color="#9A1900"> */ ''  <font color="#0000FF">static  <font color="#009900">void   <font color="#000000">dbgFileError   <font color="#990000">( GnomeVFSResult errCode <font color="#990000">,   <font color="#0000FF">const  gchar <font color="#990000"> * uri <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Error while accessing '%s': %s  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, uri <font color="#990000">,                <font color="#000000">gnome_vfs_result_to_string   <font color="#990000">( errCode <font color="#990000">)); <font color="#FF0000">}  <font color="#9A1900">/**   <font color="#9A1900"> * MODIFIED (A LOT)   <font color="#9A1900"> *   <font color="#9A1900"> * We read in the file selected by the user if possible and set the  '' <font color="#9A1900"> * contents of the file as the new Label content.   <font color="#9A1900"> * '' '' <font color="#9A1900"> * If reading the file fails, the label will be left unchanged.   <font color="#9A1900"> */ ''  <font color="#0000FF">static  <font color="#009900">void   <font color="#000000">cbActionOpen   <font color="#990000">( GtkWidget <font color="#990000"> * widget <font color="#990000">, ApplicationState <font color="#990000"> * app <font color="#990000">)  <font color="#FF0000">{ gchar <font color="#990000"> * filename <font color="#990000"> = NULL <font color="#990000"> ; '' <font color="#9A1900">/* We need to use URIs with GnomeVFS, so declare one here. */ ''   gchar <font color="#990000"> * uri <font color="#990000"> = NULL <font color="#990000"> ;  <font color="#000000">g_assert  <font color="#990000">( app <font color="#990000"> != NULL <font color="#990000">); '' <font color="#9A1900">/* Bad things will happen if these two widgets don't exist. */ ''    <font color="#000000">g_assert   <font color="#990000">(   <font color="#000000">GTK_IS_LABEL   <font color="#990000">( app <font color="#990000">-&gt; textLabel <font color="#990000">));  <font color="#000000">g_assert  <font color="#990000">(   <font color="#000000">GTK_IS_WINDOW   <font color="#990000">( app <font color="#990000">-&gt; window <font color="#990000">));  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"cbActionOpen invoked  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">); '' <font color="#9A1900">/* Ask the user to select a file to open. */ ''   filename <font color="#990000"> =   <font color="#000000">runFileChooser   <font color="#990000">( app <font color="#990000">, GTK_FILE_CHOOSER_ACTION_OPEN <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( filename <font color="#990000">)  <font color="#FF0000">{ '' <font color="#9A1900">/* This will point to loaded data buffer. */ ''     gchar <font color="#990000"> * buffer <font color="#990000"> = NULL <font color="#990000"> ; '' <font color="#9A1900">/* Pointer to a structure describing an open GnomeVFS "file". */ ''     GnomeVFSHandle <font color="#990000"> * fileHandle <font color="#990000"> = NULL <font color="#990000"> ;  <font color="#9A1900">/* Structure to hold information about a "file", initialized to  '' <font color="#9A1900">      zero. */ ''     GnomeVFSFileInfo fileInfo <font color="#990000"> =  <font color="#FF0000">{}  <font color="#990000"> ; '' <font color="#9A1900">/* Result code from the GnomeVFS operations. */ ''     GnomeVFSResult result <font color="#990000"> ; '' <font color="#9A1900">/* Size of the file (in bytes) that we'll read in. */ ''     GnomeVFSFileSize fileSize <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ; '' <font color="#9A1900">/* Number of bytes that were read in successfully. */ ''     GnomeVFSFileSize readCount <font color="#990000"> =  <font color="#993399">0  <font color="#990000"> ;  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"  you chose to load file '%s'  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, filename <font color="#990000">); '' <font color="#9A1900">/* Convert the filename into an GnomeVFS URI. */ ''     uri <font color="#990000"> =   <font color="#000000">gnome_vfs_get_uri_from_local_path   <font color="#990000">( filename <font color="#990000">); '' <font color="#9A1900">/* We don't need the original filename anymore. */ ''      <font color="#000000">g_free   <font color="#990000">( filename <font color="#990000">); filename <font color="#990000"> = NULL <font color="#990000"> ; '' <font color="#9A1900">/* Should not happen since we got a filename before. */ ''      <font color="#000000">g_assert   <font color="#990000">( uri <font color="#990000"> != NULL <font color="#990000">); '' <font color="#9A1900">/* Attempt to get file size first. We need to get information ''  <font color="#9A1900">      about the file and aren't interested in other than the very  '' <font color="#9A1900">      basic information, so we'll use the INFO_DEFAULT setting. */ ''     result <font color="#990000"> =   <font color="#000000">gnome_vfs_get_file_info   <font color="#990000">( uri <font color="#990000">,  <font color="#990000">&amp; fileInfo <font color="#990000">,                                       GNOME_VFS_FILE_INFO_DEFAULT <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( result <font color="#990000"> != GNOME_VFS_OK <font color="#990000">)  <font color="#FF0000">{ '' <font color="#9A1900">/* There was a failure. Print a debug error message and break '' '' <font color="#9A1900">        out into error handling. */ ''        <font color="#000000">dbgFileError   <font color="#990000">( result <font color="#990000">, uri <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* We got the information (maybe). Let's check whether it '' '' <font color="#9A1900">      contains the data that we need. */ ''      <font color="#0000FF">if   <font color="#990000">( fileInfo <font color="#990000">. valid_fields <font color="#990000">&amp; GNOME_VFS_FILE_INFO_FIELDS_SIZE <font color="#990000">)  <font color="#FF0000">{ '' <font color="#9A1900">/* Yes, we got the file size. */ ''       fileSize <font color="#990000"> = fileInfo <font color="#990000">. size <font color="#990000"> ; <font color="#FF0000">}  <font color="#0000FF">else   <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Couldn't get the size of file!  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* By now we have the file size to read in. Check for some limits '' '' <font color="#9A1900">      first. */ ''      <font color="#0000FF">if   <font color="#990000">( fileSize <font color="#990000">&gt;  <font color="#993399">1024  <font color="#990000"> *  <font color="#993399">100  <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Loading over 100KiB files is not supported!  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Refuse to load empty files. */ ''      <font color="#0000FF">if   <font color="#990000">( fileSize <font color="#990000"> ==  <font color="#993399">0  <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Refusing to load an empty file  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Allocate memory for the contents and fill it with zeroes.   <font color="#9A1900">       NOTE: ''  <font color="#9A1900">        We leave space for the terminating zero so that we can pass   <font color="#9A1900">        this buffer as gchar to string functions and it is   <font color="#9A1900">        guaranteed to be terminated, even if the file doesn't end  '' <font color="#9A1900">        with binary zero (odds of that happening are small). */ ''     buffer <font color="#990000"> =   <font color="#000000">g_malloc0   <font color="#990000">( fileSize <font color="#990000">+  <font color="#993399">1  <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( buffer <font color="#990000"> == NULL <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Failed to allocate %u bytes for buffer  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">,                   <font color="#990000">( guint <font color="#990000">) fileSize <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Open the file.   <font color="#9A1900">       Parameters: ''  <font color="#9A1900">      - A pointer to the location where to store the address of the  '' <font color="#9A1900">        new GnomeVFS file handle (created internally in open).   <font color="#9A1900">       - uri: What to open (needs to be GnomeVFS URI).   <font color="#9A1900">       - open-flags: Flags that tell what we plan to use the handle '' '' <font color="#9A1900">        for. This will affect how permissions are checked by the '' '' <font color="#9A1900">        Linux kernel. */ ''     result <font color="#990000"> =   <font color="#000000">gnome_vfs_open   <font color="#990000">(&amp; fileHandle <font color="#990000">, uri <font color="#990000">, GNOME_VFS_OPEN_READ <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( result <font color="#990000"> != GNOME_VFS_OK <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">dbgFileError  <font color="#990000">( result <font color="#990000">, uri <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* File opened succesfully, read its contents in. */ ''     result <font color="#990000"> =   <font color="#000000">gnome_vfs_read   <font color="#990000">( fileHandle <font color="#990000">, buffer <font color="#990000">, fileSize <font color="#990000">,                              <font color="#990000">&amp; readCount <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( result <font color="#990000"> != GNOME_VFS_OK <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">dbgFileError  <font color="#990000">( result <font color="#990000">, uri <font color="#990000">);  <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">} '' <font color="#9A1900">/* Verify that we got the amount of data that we requested.   <font color="#9A1900">       NOTE: ''  <font color="#9A1900">        With URIs it won't be an error to get less bytes than you  '' <font color="#9A1900">        requested. Getting zero bytes will however signify an '' '' <font color="#9A1900">        End-of-File condition. */ ''      <font color="#0000FF">if   <font color="#990000">( fileSize <font color="#990000"> != readCount <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_printerr  <font color="#990000">(  <font color="#FF0000">"Failed to load the requested amount  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#9A1900">/* We could also attempt to read the missing data until we have   <font color="#9A1900">        filled our buffer, but for simplicity, we'll flag this  '' <font color="#9A1900">        condition as an error. */ ''        <font color="#0000FF">goto  error <font color="#990000"> ; <font color="#FF0000">}  <font color="#9A1900">/* Whew, if we got this far, it means that we actually managed to  '' <font color="#9A1900">      load the file into memory. Let's set the buffer contents as '' '' <font color="#9A1900">      the new label now. */ ''      <font color="#000000">gtk_label_set_markup   <font color="#990000">(   <font color="#000000">GTK_LABEL   <font color="#990000">( app <font color="#990000">-&gt; textLabel <font color="#990000">), buffer <font color="#990000">); '' <font color="#9A1900">/* That's it! Display a message of great joy. For this we'll use ''  <font color="#9A1900">      a dialog (non-modal) designed for displaying short  '' <font color="#9A1900">      informational messages. It will linger around on the screen ''  <font color="#9A1900">      for a while and then disappear (in parallel to our program   '' <font color="#9A1900">       continuing). */       <font color="#000000">hildon_banner_show_information   <font color="#990000">(   <font color="#000000">GTK_WIDGET   <font color="#990000">( app <font color="#990000">-&gt; window <font color="#990000">),        NULL <font color="#990000">,   <font color="#9A1900">/* Use the default icon (info). */ ''        <font color="#FF0000">"File loaded successfully"  <font color="#990000">); '' <font color="#9A1900">/* Jump to the resource releasing phase. */ ''      <font color="#0000FF">goto  release <font color="#990000"> ; error <font color="#990000"> : '' <font color="#9A1900">/* Display a failure message with a stock icon.   <font color="#9A1900">       Please see ''    <font color="#0000FF">http://maemo.org/api_refs/4.0/gtk/gtk-Stock-Items.html '' <font color="#9A1900">      for a full listing of stock items. */       <font color="#000000">hildon_banner_show_information   <font color="#990000">(   <font color="#000000">GTK_WIDGET   <font color="#990000">( app <font color="#990000">-&gt; window <font color="#990000">),        GTK_STOCK_DIALOG_ERROR <font color="#990000">,   <font color="#9A1900">/* Use the stock error icon. */ ''        <font color="#FF0000">"Failed to load the file"  <font color="#990000">); release <font color="#990000"> : '' <font color="#9A1900">/* Close and free all resources that were allocated. */ ''      <font color="#0000FF">if   <font color="#990000">( fileHandle <font color="#990000">)   <font color="#000000">gnome_vfs_close   <font color="#990000">( fileHandle <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( filename <font color="#990000">)   <font color="#000000">g_free   <font color="#990000">( filename <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( uri <font color="#990000">)   <font color="#000000">g_free   <font color="#990000">( uri <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( buffer <font color="#990000">)   <font color="#000000">g_free   <font color="#990000">( buffer <font color="#990000">); '' <font color="#9A1900">/* Zero them all out to prevent stack-reuse-bugs. */ ''     fileHandle <font color="#990000"> = NULL <font color="#990000"> ; filename <font color="#990000"> = NULL <font color="#990000"> ; uri <font color="#990000"> = NULL <font color="#990000"> ; buffer <font color="#990000"> = NULL <font color="#990000"> ;  <font color="#0000FF">return  <font color="#990000"> ; <font color="#FF0000">}  <font color="#0000FF">else   <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"  you didn't choose any file to open  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">); <font color="#FF0000">} <font color="#FF0000">}  <font color="#9A1900">/**   <font color="#9A1900"> * MODIFIED (kind of)   <font color="#9A1900"> *   <font color="#9A1900"> * Function to save the contents of the label (although it doesn't  '' <font color="#9A1900"> * actually save the contents, on purpose). Use gtk_label_get_label ''  <font color="#9A1900"> * to get a gchar pointer into the application label contents   <font color="#9A1900"> * (including current markup), then use gnome_vfs_create and  '' <font color="#9A1900"> * gnome_vfs_write to create the file (left as an exercise).   <font color="#9A1900"> */ ''  <font color="#0000FF">static  <font color="#009900">void   <font color="#000000">cbActionSave   <font color="#990000">( GtkWidget <font color="#990000"> * widget <font color="#990000">, ApplicationState <font color="#990000"> * app <font color="#990000">)  <font color="#FF0000">{ gchar <font color="#990000"> * filename <font color="#990000"> = NULL <font color="#990000"> ;  <font color="#000000">g_assert  <font color="#990000">( app <font color="#990000"> != NULL <font color="#990000">);  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"cbActionSave invoked  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">); filename <font color="#990000"> =  <font color="#000000">runFileChooser   <font color="#990000">( app <font color="#990000">, GTK_FILE_CHOOSER_ACTION_SAVE <font color="#990000">);  <font color="#0000FF">if  <font color="#990000">( filename <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"  you chose to save into '%s'  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">, filename <font color="#990000">); '' <font color="#9A1900">/* Process saving .. */ ''      <font color="#000000">g_free   <font color="#990000">( filename <font color="#990000">); filename <font color="#990000"> = NULL <font color="#990000"> ; <font color="#FF0000">}  <font color="#0000FF">else   <font color="#FF0000">{  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"  you didn't choose a filename to save to  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">); <font color="#FF0000">} <font color="#FF0000">} '' <font color="#9A1900">/*... Listing cut for brevity ...*/ ''  <font color="#9A1900">/**   <font color="#9A1900"> * MODIFIED   <font color="#9A1900"> *   <font color="#9A1900"> * Add support for GnomeVFS (it needs to be initialized before use)   <font color="#9A1900"> * and add support for the Pango markup feature of the GtkLabel  '' <font color="#9A1900"> * widget.   <font color="#9A1900"> */ '' <font color="#009900">int  <font color="#000000">main   <font color="#990000">(  <font color="#009900">int argc <font color="#990000">,  <font color="#009900">char  <font color="#990000"> ** argv <font color="#990000">)  <font color="#FF0000">{ ApplicationState aState <font color="#990000"> = <font color="#FF0000">{}  <font color="#990000"> ; GtkWidget <font color="#990000"> * label <font color="#990000"> = NULL <font color="#990000"> ; GtkWidget <font color="#990000"> * vbox <font color="#990000"> = NULL <font color="#990000"> ; GtkWidget <font color="#990000"> * mainToolbar <font color="#990000"> = NULL <font color="#990000"> ; GtkWidget <font color="#990000"> * findToolbar <font color="#990000"> = NULL <font color="#990000"> ; '' <font color="#9A1900">/* Initialize the GnomeVFS (NEW). */ ''    <font color="#0000FF">if   <font color="#990000">(!   <font color="#000000">gnome_vfs_init   <font color="#990000">)  <font color="#FF0000">{  <font color="#000000">g_error  <font color="#990000">(  <font color="#FF0000">"Failed to initialize GnomeVFS-libraries, exiting  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">); <font color="#FF0000">}  <font color="#9A1900">/* Initialize the GTK+ */   <font color="#000000">gtk_init  <font color="#990000">(&amp; argc <font color="#990000">,  <font color="#990000">&amp; argv <font color="#990000">); '' <font color="#9A1900">/* Setup the HildonProgram, HildonWindow and application name. */ ''   aState <font color="#990000">. program <font color="#990000"> =  <font color="#000000">HILDON_PROGRAM   <font color="#990000">(   <font color="#000000">hildon_program_get_instance   <font color="#990000">);  <font color="#000000">g_set_application_name  <font color="#990000">(  <font color="#FF0000">"Hello Hildon!"  <font color="#990000">); aState <font color="#990000">. window <font color="#990000"> =  <font color="#000000">HILDON_WINDOW   <font color="#990000">(   <font color="#000000">hildon_window_new   <font color="#990000">);  <font color="#000000">hildon_program_add_window  <font color="#990000">( aState <font color="#990000">. program <font color="#990000">,                               <font color="#000000">HILDON_WINDOW   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">)); '' <font color="#9A1900">/* Create the label widget, with Pango marked up content (NEW). */ ''   label <font color="#990000"> =   <font color="#000000">gtk_label_new   <font color="#990000">(  <font color="#FF0000">"&lt;b&gt;Hello&lt;/b&gt; &lt;i&gt;Hildon&lt;/i&gt; (with Hildon" <font color="#FF0000">"&lt;sub&gt;search&lt;/sub&gt; &lt;u&gt;and&lt;/u&gt; GnomeVFS " <font color="#FF0000">"and other tricks&lt;sup&gt;tm&lt;/sup&gt;)!" <font color="#990000">); '' <font color="#9A1900">/* Allow lines to wrap (NEW). */ ''    <font color="#000000">gtk_label_set_line_wrap   <font color="#990000">(   <font color="#000000">GTK_LABEL   <font color="#990000">( label <font color="#990000">), TRUE <font color="#990000">); '' <font color="#9A1900">/* Tell the GtkLabel widget to support the Pango markup (NEW). */ ''    <font color="#000000">gtk_label_set_use_markup   <font color="#990000">(   <font color="#000000">GTK_LABEL   <font color="#990000">( label <font color="#990000">), TRUE <font color="#990000">);  <font color="#9A1900">/* Store the widget pointer into the application state so that the  '' <font color="#9A1900">    contents can be replaced when a file will be loaded (NEW). */ ''   aState <font color="#990000">. textLabel <font color="#990000"> = label <font color="#990000"> ;  <font color="#000000">buildMenu  <font color="#990000">(&amp; aState <font color="#990000">); vbox <font color="#990000"> =  <font color="#000000">gtk_vbox_new   <font color="#990000">( FALSE <font color="#990000">,  <font color="#993399">0  <font color="#990000">);  <font color="#000000">gtk_container_add  <font color="#990000">(   <font color="#000000">GTK_CONTAINER   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">), vbox <font color="#990000">);  <font color="#000000">gtk_box_pack_end  <font color="#990000">(   <font color="#000000">GTK_BOX   <font color="#990000">( vbox <font color="#990000">), label <font color="#990000">, TRUE <font color="#990000">, TRUE <font color="#990000">,  <font color="#993399">0  <font color="#990000">); mainToolbar <font color="#990000"> =  <font color="#000000">buildToolbar   <font color="#990000">(&amp; aState <font color="#990000">); findToolbar <font color="#990000"> =  <font color="#000000">buildFindToolbar   <font color="#990000">(&amp; aState <font color="#990000">); aState <font color="#990000">. mainToolbar <font color="#990000"> = mainToolbar <font color="#990000"> ; aState <font color="#990000">. findToolbar <font color="#990000"> = findToolbar <font color="#990000"> ; '' <font color="#9A1900">/* Connect the termination signals. */ ''    <font color="#000000">g_signal_connect   <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">), <font color="#FF0000">"delete-event"  <font color="#990000">,                      <font color="#000000">G_CALLBACK   <font color="#990000">( cbEventDelete <font color="#990000">),  <font color="#990000">&amp; aState <font color="#990000">);  <font color="#000000">g_signal_connect  <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">), <font color="#FF0000">"destroy"  <font color="#990000">,                      <font color="#000000">G_CALLBACK   <font color="#990000">( cbActionTopDestroy <font color="#990000">),  <font color="#990000">&amp; aState <font color="#990000">); '' <font color="#9A1900">/* Show all widgets that are contained by the Window. */ ''    <font color="#000000">gtk_widget_show_all   <font color="#990000">(   <font color="#000000">GTK_WIDGET   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">)); '' <font color="#9A1900">/* Add the toolbars to the Hildon Window. */ ''    <font color="#000000">hildon_window_add_toolbar   <font color="#990000">(   <font color="#000000">HILDON_WINDOW   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">),                              <font color="#000000">GTK_TOOLBAR   <font color="#990000">( mainToolbar <font color="#990000">));  <font color="#000000">hildon_window_add_toolbar  <font color="#990000">(   <font color="#000000">HILDON_WINDOW   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">),                              <font color="#000000">GTK_TOOLBAR   <font color="#990000">( findToolbar <font color="#990000">)); '' <font color="#9A1900">/* Register a callback to handle key presses. */ ''    <font color="#000000">g_signal_connect   <font color="#990000">(   <font color="#000000">G_OBJECT   <font color="#990000">( aState <font color="#990000">. window <font color="#990000">), <font color="#FF0000">"key_press_event"  <font color="#990000">,                      <font color="#000000">G_CALLBACK   <font color="#990000">( cbKeyPressed <font color="#990000">),  <font color="#990000">&amp; aState <font color="#990000">);  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"main: calling gtk_main  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#000000">gtk_main  <font color="#990000">;  <font color="#000000">g_print  <font color="#990000">(  <font color="#FF0000">"main: returned from gtk_main and exiting with success  <font color="#CC33CC">\n  <font color="#FF0000">"  <font color="#990000">);  <font color="#0000FF">return  EXIT_SUCCESS <font color="#990000"> ; <font color="#FF0000">} </tt>





In order to experiment with loading other content, a simple file can be created, containing Pango markup like this: echo "&lt;b&gt;Hello world&lt;/b&gt;" &gt; MyDocs/hello.txt, and then loading hello.txt.

As can be imagined, these examples have only scratched the surface of GnomeVFS that is quite a rich library, and contains a broad API and a large amount of plug-ins. Many things have been completely avoided, such as directory content iteration, the asynchronous interface, callback signaling on directory content changes etc. Please see GnomeVFS API reference for more information. The API also contains some mini tutorials on various GnomeVFS topics, so it is well worth the time spent reading. It will also show that GnomeVFS has been overloaded with functions, which are not even file operation related (such as ZeroConf and creating TCP/IP connections etc.).

GTK+ does not have to be used in order to use GnomeVFS. One such example program is Midnight Commander (a Norton Commander clone, but better), which is a menu-based "text" mode program. GnomeVFS uses GLib though, so if using GnomeVFS, one should think about using GLib as well, as it will be loaded anyway.