mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

src/mn-vfs.c (9395B) - raw

      1 /*
      2  * Mail Notification
      3  * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License along
     16  * with this program; if not, write to the Free Software Foundation, Inc.,
     17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     18  */
     19 
     20 #include <string.h>
     21 #include <glib/gi18n.h>
     22 #include "mn-vfs.h"
     23 
     24 #ifndef MN_REGRESSION_TEST
     25 #define READ_LINE_BLOCK_SIZE		16384
     26 #endif
     27 
     28 struct _MNVFSReadLineContext
     29 {
     30   GnomeVFSHandle	*handle;
     31   GString		*buf;
     32   char			*terminator;
     33   GnomeVFSResult	last_result;
     34   gboolean		eof;
     35 };
     36 
     37 /* FIXME: must also handle \r and \r\n terminators */
     38 GnomeVFSResult
     39 mn_vfs_read_line (MNVFSReadLineContext **context,
     40 		  GnomeVFSHandle *handle,
     41 		  const char **line)
     42 {
     43   GnomeVFSResult result;
     44   gboolean first_pass = TRUE;
     45 
     46   g_return_val_if_fail(context != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
     47   g_return_val_if_fail(handle != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
     48   g_return_val_if_fail(line != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
     49 
     50   if (*context)
     51     {
     52       g_return_val_if_fail((*context)->handle == handle, GNOME_VFS_ERROR_BAD_PARAMETERS);
     53       if ((*context)->terminator)
     54 	{
     55 	  g_string_erase((*context)->buf, 0, (*context)->terminator - (*context)->buf->str + 1);
     56 	  (*context)->terminator = NULL;
     57 	}
     58       else if ((*context)->eof)
     59 	return GNOME_VFS_ERROR_EOF; /* we're done */
     60     }
     61   else
     62     {
     63       *context = g_new0(MNVFSReadLineContext, 1);
     64       (*context)->handle = handle;
     65       (*context)->buf = g_string_new(NULL);
     66     }
     67 
     68   while (TRUE)
     69     {
     70       if (! (*context)->buf->str[0] || ! first_pass)
     71 	{
     72 	  char buf[READ_LINE_BLOCK_SIZE];
     73 	  GnomeVFSFileSize bytes_read;
     74 
     75 	  result = (*context)->last_result = gnome_vfs_read(handle, buf, sizeof(buf), &bytes_read);
     76 	  if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_EOF)
     77 	    g_string_append_len((*context)->buf, buf, bytes_read);
     78 	  else
     79 	    break;		/* error */
     80 	}
     81 
     82       (*context)->terminator = strchr((*context)->buf->str, '\n');
     83       if ((*context)->terminator || (*context)->last_result == GNOME_VFS_ERROR_EOF)
     84 	{
     85 	  result = (*context)->last_result;
     86 	  if ((*context)->terminator || (*context)->buf->str[0])
     87 	    {
     88 	      *line = (*context)->buf->str;
     89 	      if (result == GNOME_VFS_ERROR_EOF)
     90 		result = GNOME_VFS_OK;
     91 	    }
     92 	  if ((*context)->terminator)
     93 	    (*context)->terminator[0] = 0;
     94 	  else if ((*context)->last_result == GNOME_VFS_ERROR_EOF)
     95 	    (*context)->eof = TRUE;
     96 
     97 	  break;		/* line found, or last line */
     98 	}
     99 
    100       first_pass = FALSE;
    101     }
    102 
    103   return result;
    104 }
    105 
    106 void
    107 mn_vfs_read_line_context_free (MNVFSReadLineContext *context)
    108 {
    109   g_return_if_fail(context != NULL);
    110 
    111   g_string_free(context->buf, TRUE);
    112   g_free(context);
    113 }
    114 
    115 gboolean
    116 mn_vfs_test (GnomeVFSURI *uri, GFileTest test)
    117 {
    118   GnomeVFSFileInfoOptions options;
    119   GnomeVFSFileInfo *file_info;
    120   gboolean status = FALSE;
    121 
    122   g_return_val_if_fail(uri != NULL, FALSE);
    123 
    124   options = GNOME_VFS_FILE_INFO_DEFAULT;
    125   if (! (test & G_FILE_TEST_IS_SYMLINK))
    126     options |= GNOME_VFS_FILE_INFO_FOLLOW_LINKS;
    127   if (test & G_FILE_TEST_IS_EXECUTABLE)
    128     options |= GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS;
    129 
    130   file_info = gnome_vfs_file_info_new();
    131   if (gnome_vfs_get_file_info_uri(uri, file_info, options) == GNOME_VFS_OK)
    132     {
    133       if (file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
    134 	{
    135 	  if (test & G_FILE_TEST_IS_REGULAR)
    136 	    status = file_info->type == GNOME_VFS_FILE_TYPE_REGULAR;
    137 	  if (! status && test & G_FILE_TEST_IS_SYMLINK)
    138 	    status = file_info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
    139 	  if (! status && test & G_FILE_TEST_IS_DIR)
    140 	    status = file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY;
    141 	}
    142       if (file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)
    143 	{
    144 	  if (! status && test & G_FILE_TEST_IS_EXECUTABLE)
    145 	    status = file_info->permissions & GNOME_VFS_PERM_ACCESS_EXECUTABLE;
    146 	}
    147       if (! status && test & G_FILE_TEST_EXISTS)
    148 	status = TRUE; /* gnome_vfs_get_file_info() succeeded, so the file exists */
    149     }
    150   gnome_vfs_file_info_unref(file_info);
    151 
    152   return status;
    153 }
    154 
    155 GnomeVFSResult
    156 mn_vfs_read_entire_file_uri (GnomeVFSURI *uri,
    157 			     int *file_size,
    158 			     char **file_contents)
    159 {
    160   char *text_uri;
    161   GnomeVFSResult result;
    162 
    163   g_return_val_if_fail(uri != NULL, GNOME_VFS_ERROR_BAD_PARAMETERS);
    164 
    165   text_uri = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE);
    166   result = gnome_vfs_read_entire_file(text_uri, file_size, file_contents);
    167   g_free(text_uri);
    168 
    169   return result;
    170 }
    171 
    172 GnomeVFSResult
    173 mn_vfs_write_entire_file_uri (GnomeVFSURI *uri,
    174 			      gsize file_size,
    175 			      const char *file_contents,
    176 			      gboolean exclusive,
    177 			      unsigned int perms)
    178 {
    179   GnomeVFSHandle *handle;
    180   GnomeVFSResult result;
    181   GnomeVFSFileSize bytes_written = 0;
    182 
    183   result = gnome_vfs_create_uri(&handle, uri, GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_TRUNCATE, exclusive, perms);
    184   if (result != GNOME_VFS_OK)
    185     return result;
    186 
    187   while (bytes_written < file_size)
    188     {
    189       GnomeVFSFileSize this_bytes_written;
    190 
    191       result = gnome_vfs_write(handle, file_contents + bytes_written, file_size - bytes_written, &this_bytes_written);
    192       if (result != GNOME_VFS_OK)
    193 	{
    194 	  gnome_vfs_close(handle);
    195 	  return result;
    196 	}
    197 
    198       bytes_written += this_bytes_written;
    199     }
    200 
    201   return gnome_vfs_close(handle);
    202 }
    203 
    204 gboolean
    205 mn_vfs_write_entire_file_uri_safe (GnomeVFSURI *uri,
    206 				   gsize file_size,
    207 				   const char *file_contents,
    208 				   unsigned int perms,
    209 				   GError **err)
    210 {
    211   GnomeVFSResult result;
    212   char *text_uri;
    213   GnomeVFSURI *tmp_uri;
    214   char *tmp_text_uri;
    215   GnomeVFSURI *old_uri;
    216   char *old_text_uri;
    217   gboolean status = FALSE;
    218   gboolean old_exists;
    219 
    220   g_return_val_if_fail(uri != NULL, FALSE);
    221 
    222   text_uri = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_PASSWORD);
    223   tmp_uri = mn_vfs_uri_append_file_suffix(uri, ".tmp");
    224   tmp_text_uri = gnome_vfs_uri_to_string(tmp_uri, GNOME_VFS_URI_HIDE_PASSWORD);
    225   old_uri = mn_vfs_uri_append_file_suffix(uri, ".old");
    226   old_text_uri = gnome_vfs_uri_to_string(old_uri, GNOME_VFS_URI_HIDE_PASSWORD);
    227 
    228   if (mn_vfs_test(tmp_uri, G_FILE_TEST_EXISTS))
    229     {
    230       result = gnome_vfs_unlink_from_uri(tmp_uri);
    231       if (result != GNOME_VFS_OK)
    232 	{
    233 	  g_set_error(err, 0, 0, _("Unable to remove %s: %s."), tmp_text_uri, gnome_vfs_result_to_string(result));
    234 	  goto end;
    235 	}
    236     }
    237 
    238   result = mn_vfs_write_entire_file_uri(tmp_uri, file_size, file_contents, TRUE, perms);
    239   if (result != GNOME_VFS_OK)
    240     {
    241       g_set_error(err, 0, 0, _("Unable to write %s: %s."), tmp_text_uri, gnome_vfs_result_to_string(result));
    242       goto end;
    243     }
    244 
    245   old_exists = mn_vfs_test(uri, G_FILE_TEST_EXISTS);
    246   if (old_exists)
    247     {
    248       result = gnome_vfs_move_uri(uri, old_uri, TRUE);
    249       if (result != GNOME_VFS_OK)
    250 	{
    251 	  g_set_error(err, 0, 0, _("Unable to rename %s to %s: %s."), text_uri, old_text_uri, gnome_vfs_result_to_string(result));
    252 	  goto end;
    253 	}
    254     }
    255 
    256   result = gnome_vfs_move_uri(tmp_uri, uri, TRUE);
    257   if (result != GNOME_VFS_OK)
    258     {
    259       g_set_error(err, 0, 0, _("Unable to rename %s to %s: %s."), tmp_text_uri, text_uri, gnome_vfs_result_to_string(result));
    260       goto end;
    261     }
    262 
    263   if (old_exists)
    264     {
    265       GnomeVFSResult this_result;
    266 
    267       this_result = gnome_vfs_unlink_from_uri(old_uri);
    268       if (this_result != GNOME_VFS_OK) /* non fatal */
    269 	g_warning(_("unable to delete %s: %s"), old_text_uri, gnome_vfs_result_to_string(this_result));
    270     }
    271 
    272   status = TRUE;		/* success */
    273 
    274  end:
    275   g_free(text_uri);
    276   gnome_vfs_uri_unref(tmp_uri);
    277   g_free(tmp_text_uri);
    278   gnome_vfs_uri_unref(old_uri);
    279   g_free(old_text_uri);
    280 
    281   return status;
    282 }
    283 
    284 GnomeVFSURI *
    285 mn_vfs_uri_append_file_suffix (GnomeVFSURI *uri, const char *suffix)
    286 {
    287   GnomeVFSURI *result;
    288 
    289   g_return_val_if_fail(uri != NULL, NULL);
    290   g_return_val_if_fail(suffix != NULL, NULL);
    291 
    292   result = gnome_vfs_uri_dup(uri);
    293   if (result->text)
    294     {
    295       char *new_text;
    296 
    297       new_text = g_strconcat(result->text, suffix, NULL);
    298       g_free(result->text);
    299       result->text = new_text;
    300     }
    301   else
    302     result->text = g_strdup(suffix);
    303 
    304   return result;
    305 }
    306 
    307 char *
    308 mn_vfs_uri_extract_short_name (const char *text_uri)
    309 {
    310   GnomeVFSURI *uri;
    311   char *name;
    312 
    313   g_return_val_if_fail(text_uri != NULL, NULL);
    314 
    315   uri = gnome_vfs_uri_new(text_uri);
    316   if (! uri)
    317     return NULL;
    318 
    319   name = gnome_vfs_uri_extract_short_name(uri);
    320   gnome_vfs_uri_unref(uri);
    321 
    322   return name;
    323 }
    324 
    325 char *
    326 mn_vfs_get_local_path (GnomeVFSURI *uri)
    327 {
    328   char *text_uri;
    329   char *path;
    330 
    331   g_return_val_if_fail(uri != NULL, NULL);
    332 
    333   text_uri = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE);
    334   path = gnome_vfs_get_local_path_from_uri(text_uri);
    335   g_free(text_uri);
    336 
    337   return path;
    338 }
    339 
    340 gboolean
    341 mn_vfs_result_to_g_error (GnomeVFSResult result, GError **err)
    342 {
    343   if (result == GNOME_VFS_OK)
    344     return TRUE;
    345 
    346   g_set_error(err, 0, 0, "%s", gnome_vfs_result_to_string(result));
    347   return FALSE;
    348 }