/*--------------------------------------------------------------------------*/ static void read_remote_file_callback( GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer buffer, GnomeVFSFileSize bytes_requested, GnomeVFSFileSize bytes_read, gpointer callback_data ) { DownloadCallbackData *data = (DownloadCallbackData *)callback_data; GnomeVFSFileSize bytes_written; gb_debug (DEBUG_UPDATE, "START"); if ( update_cancel_flag ) { gnome_vfs_async_close( handle, close_remote_file_callback, data ); gb_debug (DEBUG_UPDATE, "END -- CANCEL"); return; } switch (result) { case GNOME_VFS_OK: if ( bytes_read > 0 ) { data->total_bytes_read += bytes_read; data->file_bytes_read += bytes_read; update_progress_bar (GTK_PROGRESS_BAR(file_progress), data->file_bytes_read, data->file_bytes); update_progress_bar (GTK_PROGRESS_BAR(total_progress), data->total_bytes_read, data->total_bytes); gnome_vfs_write( data->local_handle, buffer, bytes_read, &bytes_written ); if ( bytes_written != bytes_read ) { g_warning( "Write failed: %d bytes written != %d bytes read", (gint)bytes_written, (gint)bytes_read ); } gnome_vfs_async_read( handle, data->buffer, data->buffer_length, read_remote_file_callback, data ); } else { gnome_vfs_async_close( handle, close_remote_file_callback, data ); gb_debug (DEBUG_UPDATE, "0 length read"); } break; case GNOME_VFS_ERROR_EOF: gb_debug (DEBUG_UPDATE, "EOF -- %" GNOME_VFS_OFFSET_FORMAT_STR, bytes_read); gnome_vfs_async_close( handle, close_remote_file_callback, data ); break; default: g_warning( "Read failed: %s", gnome_vfs_result_to_string(result) ); break; } gb_debug (DEBUG_UPDATE, "END"); }
/*--------------------------------------------------------------------------*/ static void open_remote_file_callback( GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer callback_data ) { DownloadCallbackData *data = (DownloadCallbackData *)callback_data; GnomeVFSFileInfo *info = (GnomeVFSFileInfo *)data->p->data; gchar *local_path, *local_text_uri, *local_name; GnomeVFSHandle *local_handle; gchar *status_string; GnomeVFSResult ret; gb_debug (DEBUG_UPDATE, "START"); if ( update_cancel_flag ) { gnome_vfs_async_close( handle, close_remote_file_callback, data ); gb_debug (DEBUG_UPDATE, "END -- CANCEL"); return; } switch (result) { case GNOME_VFS_OK: data->file_bytes_read = 0; data->file_bytes = info->size; status_string = g_strdup_printf( _("File: \"%s\" (%d of %d)"), info->name, (data->i+1), data->n ); gtk_label_set_text( GTK_LABEL(file_label), status_string ); g_free( status_string ); update_progress_bar (GTK_PROGRESS_BAR(file_progress), 0, data->file_bytes); update_progress_bar (GTK_PROGRESS_BAR(total_progress), data->total_bytes_read, data->total_bytes); local_name = hash_filename( info->name ); local_path = g_build_filename (gb_util_get_home_data_dir(), local_name, NULL); local_text_uri = gnome_vfs_get_uri_from_local_path( local_path ); ret = gnome_vfs_create( &local_handle, local_text_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0664 ); if ( ret != GNOME_VFS_OK ) { g_warning( "error opening local file %s, %s\n", local_path, gnome_vfs_result_to_string(ret) ); } else { data->local_handle = local_handle; gnome_vfs_async_read( handle, data->buffer, data->buffer_length, read_remote_file_callback, data ); } g_free( local_name ); g_free( local_path ); g_free( local_text_uri ); break; default: g_warning( "Open failed: %s.\n", gnome_vfs_result_to_string(result) ); break; } gb_debug (DEBUG_UPDATE, "END"); }
/* open the file, do stuff necessary to go to PAUSED state */ static gboolean gst_gnome_vfs_src_start (GstBaseSrc * basesrc) { GnomeVFSResult res; GstGnomeVFSSrc *src; src = GST_GNOME_VFS_SRC (basesrc); gst_gnome_vfs_src_push_callbacks (src); src->context = gnome_vfs_context_new (); if (src->uri != NULL) { GnomeVFSOpenMode mode = GNOME_VFS_OPEN_READ; /* this can block... */ res = gnome_vfs_open_uri (&src->handle, src->uri, mode); if (res != GNOME_VFS_OK) goto open_failed; src->own_handle = TRUE; } else if (!src->handle) { goto no_filename; } else { src->own_handle = FALSE; } if (gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_CURRENT, 0) == GNOME_VFS_OK) { src->seekable = TRUE; } else { src->seekable = FALSE; } return TRUE; /* ERRORS */ open_failed: { gchar *filename = gnome_vfs_uri_to_string (src->uri, GNOME_VFS_URI_HIDE_PASSWORD); gst_gnome_vfs_src_pop_callbacks (src); if (res == GNOME_VFS_ERROR_NOT_FOUND || res == GNOME_VFS_ERROR_HOST_NOT_FOUND || res == GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE) { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), ("Could not open vfs file \"%s\" for reading: %s (%d)", filename, gnome_vfs_result_to_string (res), res)); } else { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Could not open vfs file \"%s\" for reading: %s (%d)", filename, gnome_vfs_result_to_string (res), res)); } g_free (filename); return FALSE; } no_filename: { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given")); return FALSE; } }
/* * Read a new buffer from src->reqoffset, takes care of events * and seeking and such. */ static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size, GstBuffer ** buffer) { GnomeVFSResult res; GstBuffer *buf; GnomeVFSFileSize readbytes; guint8 *data; guint todo; GstGnomeVFSSrc *src; gboolean interrupted = FALSE; src = GST_GNOME_VFS_SRC (basesrc); GST_DEBUG ("now at %" G_GINT64_FORMAT ", reading from %" G_GUINT64_FORMAT ", size %u", src->curoffset, offset, size); /* seek if required */ if (G_UNLIKELY (src->curoffset != offset)) { GST_DEBUG ("need to seek"); if (src->seekable) { GST_DEBUG ("seeking to %" G_GUINT64_FORMAT, offset); res = gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_START, offset); if (res != GNOME_VFS_OK) goto seek_failed; src->curoffset = offset; } else { goto cannot_seek; } } buf = gst_buffer_try_new_and_alloc (size); if (G_UNLIKELY (buf == NULL)) { GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size); return GST_FLOW_ERROR; } data = GST_BUFFER_DATA (buf); todo = size; while (!src->interrupted && todo > 0) { /* this can return less that we ask for */ res = gnome_vfs_read_cancellable (src->handle, data, todo, &readbytes, src->context); if (G_UNLIKELY (res == GNOME_VFS_ERROR_CANCELLED)) { GST_DEBUG_OBJECT (src, "interrupted"); /* Just take what we've so far gotten and return */ size = size - todo; GST_BUFFER_SIZE (buf) = size; todo = 0; interrupted = TRUE; break; } if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK && readbytes == 0))) goto eos; if (G_UNLIKELY (res != GNOME_VFS_OK)) goto read_failed; if (readbytes < todo) { data = &data[readbytes]; todo -= readbytes; } else { todo = 0; } GST_LOG (" got size %" G_GUINT64_FORMAT, readbytes); } if (interrupted) goto interrupted; GST_BUFFER_OFFSET (buf) = src->curoffset; src->curoffset += size; /* we're done, return the buffer */ *buffer = buf; return GST_FLOW_OK; seek_failed: { GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), ("Failed to seek to requested position %" G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res))); return GST_FLOW_ERROR; } cannot_seek: { GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), ("Requested seek from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT " on non-seekable stream", src->curoffset, offset)); return GST_FLOW_ERROR; } read_failed: { gst_buffer_unref (buf); GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Failed to read data: %s", gnome_vfs_result_to_string (res))); return GST_FLOW_ERROR; } interrupted: { gst_buffer_unref (buf); return GST_FLOW_WRONG_STATE; } eos: { gst_buffer_unref (buf); GST_DEBUG_OBJECT (src, "Reading data gave EOS"); return GST_FLOW_UNEXPECTED; } }
GnomeVFSResult nsGnomeVFSInputStream::DoOpen() { GnomeVFSResult rv; NS_ASSERTION(mHandle == nsnull, "already open"); // Push a callback handler on the stack for this thread, so we can intercept // authentication requests from GnomeVFS. We'll use the channel to get a // nsIAuthPrompt instance. gnome_vfs_module_callback_push(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION, AuthCallback, mChannel, NULL); // Query the mime type first (this could return NULL). // // XXX We need to do this up-front in order to determine how to open the URI. // Unfortunately, the error code GNOME_VFS_ERROR_IS_DIRECTORY is not // always returned by gnome_vfs_open when we pass it a URI to a directory! // Otherwise, we could have used that as a way to failover to opening the // URI as a directory. Also, it would have been ideal if // gnome_vfs_get_file_info_from_handle were actually implemented by the // smb:// module, since that would have allowed us to potentially save a // round trip to the server to discover the mime type of the document in // the case where gnome_vfs_open would have been used. (Oh well! /me // throws hands up in the air and moves on...) GnomeVFSFileInfo info = {0}; rv = gnome_vfs_get_file_info(mSpec.get(), &info, GnomeVFSFileInfoOptions( GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS)); if (rv == GNOME_VFS_OK) { if (info.type == GNOME_VFS_FILE_TYPE_DIRECTORY) { rv = gnome_vfs_directory_list_load(&mDirList, mSpec.get(), GNOME_VFS_FILE_INFO_DEFAULT); LOG(("gnomevfs: gnome_vfs_directory_list_load returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } else { rv = gnome_vfs_open(&mHandle, mSpec.get(), GNOME_VFS_OPEN_READ); LOG(("gnomevfs: gnome_vfs_open returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } } gnome_vfs_module_callback_pop(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION); if (rv == GNOME_VFS_OK) { if (mHandle) { // Here we set the content type of the channel to the value of the mime // type determined by GnomeVFS. However, if GnomeVFS is telling us that // the document is binary, we'll ignore that and keep the channel's // content type unspecified. That will enable our content type sniffing // algorithms. This should provide more consistent mime type handling. if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0)) SetContentTypeOfChannel(info.mime_type); mBytesRemaining = info.size; // Update the content length attribute on the channel. We do this // synchronously without proxying. This hack is not as bad as it looks! if (mBytesRemaining != PRUint64(-1)) mChannel->SetContentLength(mBytesRemaining); } else { mDirOpen = PR_TRUE; // Sort mDirList mDirList = g_list_sort(mDirList, FileInfoComparator); mDirListPtr = mDirList; // Write base URL (make sure it ends with a '/') mDirBuf.Append("300: "); mDirBuf.Append(mSpec); if (mSpec.get()[mSpec.Length() - 1] != '/') mDirBuf.Append('/'); mDirBuf.Append('\n'); // Write column names mDirBuf.Append("200: filename content-length last-modified file-type\n"); // Write charset (assume UTF-8) // XXX is this correct? mDirBuf.Append("301: UTF-8\n"); SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT); } } gnome_vfs_file_info_clear(&info); return rv; }
gboolean mn_vfs_write_entire_file_uri_safe (GnomeVFSURI *uri, gsize file_size, const char *file_contents, unsigned int perms, GError **err) { GnomeVFSResult result; char *text_uri; GnomeVFSURI *tmp_uri; char *tmp_text_uri; GnomeVFSURI *old_uri; char *old_text_uri; gboolean status = FALSE; gboolean old_exists; g_return_val_if_fail(uri != NULL, FALSE); text_uri = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_PASSWORD); tmp_uri = mn_vfs_uri_append_file_suffix(uri, ".tmp"); tmp_text_uri = gnome_vfs_uri_to_string(tmp_uri, GNOME_VFS_URI_HIDE_PASSWORD); old_uri = mn_vfs_uri_append_file_suffix(uri, ".old"); old_text_uri = gnome_vfs_uri_to_string(old_uri, GNOME_VFS_URI_HIDE_PASSWORD); if (mn_vfs_test(tmp_uri, G_FILE_TEST_EXISTS)) { result = gnome_vfs_unlink_from_uri(tmp_uri); if (result != GNOME_VFS_OK) { g_set_error(err, 0, 0, _("Unable to remove %s: %s."), tmp_text_uri, gnome_vfs_result_to_string(result)); goto end; } } result = mn_vfs_write_entire_file_uri(tmp_uri, file_size, file_contents, TRUE, perms); if (result != GNOME_VFS_OK) { g_set_error(err, 0, 0, _("Unable to write %s: %s."), tmp_text_uri, gnome_vfs_result_to_string(result)); goto end; } old_exists = mn_vfs_test(uri, G_FILE_TEST_EXISTS); if (old_exists) { result = gnome_vfs_move_uri(uri, old_uri, TRUE); if (result != GNOME_VFS_OK) { g_set_error(err, 0, 0, _("Unable to rename %s to %s: %s."), text_uri, old_text_uri, gnome_vfs_result_to_string(result)); goto end; } } result = gnome_vfs_move_uri(tmp_uri, uri, TRUE); if (result != GNOME_VFS_OK) { g_set_error(err, 0, 0, _("Unable to rename %s to %s: %s."), tmp_text_uri, text_uri, gnome_vfs_result_to_string(result)); goto end; } if (old_exists) { GnomeVFSResult this_result; this_result = gnome_vfs_unlink_from_uri(old_uri); if (this_result != GNOME_VFS_OK) /* non fatal */ g_warning(_("unable to delete %s: %s"), old_text_uri, gnome_vfs_result_to_string(this_result)); } status = TRUE; /* success */ end: g_free(text_uri); gnome_vfs_uri_unref(tmp_uri); g_free(tmp_text_uri); gnome_vfs_uri_unref(old_uri); g_free(old_text_uri); return status; }