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 }