00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <glib.h>
00021 #include <string.h>
00022 #include "vfs.h"
00023 #include "vfs_buffer.h"
00024 #include "vfs_buffered_file.h"
00025
00026 VFSFile *
00027 buffered_file_vfs_fopen_impl(const gchar * path,
00028 const gchar * mode)
00029 {
00030 return NULL;
00031 }
00032
00033 gint
00034 buffered_file_vfs_fclose_impl(VFSFile * file)
00035 {
00036 g_return_val_if_fail(file != NULL, -1);
00037
00038 if (file->handle)
00039 {
00040 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00041
00042 if (handle->fd != NULL)
00043 vfs_fclose(handle->fd);
00044
00045 vfs_fclose(handle->buffer);
00046 g_free(handle->mem);
00047 g_free(handle);
00048 }
00049
00050 return 0;
00051 }
00052
00053 gint64 buffered_file_vfs_fread_impl (void * i_ptr, gint64 size, gint64 nmemb,
00054 VFSFile * file)
00055 {
00056 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00057
00058
00059
00060
00061 if (handle->which == FALSE &&
00062 (vfs_ftell(handle->buffer)) + (size * nmemb) >
00063 ((VFSBuffer *) handle->buffer->handle)->size)
00064 {
00065 if (vfs_fseek (handle->fd, vfs_ftell (handle->buffer), SEEK_SET))
00066 return 0;
00067 handle->which = TRUE;
00068 }
00069
00070 return vfs_fread(i_ptr, size, nmemb, handle->which == TRUE ? handle->fd : handle->buffer);
00071 }
00072
00073 gint64 buffered_file_vfs_fwrite_impl (const void * i_ptr, gint64 size, gint64
00074 nmemb, VFSFile * file)
00075 {
00076 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00077
00078 return vfs_fwrite(i_ptr, size, nmemb, handle->fd);
00079 }
00080
00081 gint
00082 buffered_file_vfs_getc_impl(VFSFile *stream)
00083 {
00084 VFSBufferedFile *handle = (VFSBufferedFile *) stream->handle;
00085
00086
00087
00088
00089 if ((vfs_ftell(handle->buffer)) + 1 >
00090 ((VFSBuffer *) handle->buffer->handle)->size)
00091 {
00092 if (vfs_fseek (handle->fd, vfs_ftell (handle->buffer), SEEK_SET))
00093 return EOF;
00094 handle->which = TRUE;
00095 }
00096
00097 return vfs_getc(handle->which == TRUE ? handle->fd : handle->buffer);
00098 }
00099
00100 gint
00101 buffered_file_vfs_ungetc_impl(gint c, VFSFile *stream)
00102 {
00103 return -1;
00104 }
00105
00106 gint
00107 buffered_file_vfs_fseek_impl(VFSFile * file,
00108 gint64 offset,
00109 gint whence)
00110 {
00111 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00112
00113 if (vfs_fseek (handle->buffer, offset, whence))
00114 return -1;
00115
00116 switch(whence)
00117 {
00118 case SEEK_END:
00119 handle->which = TRUE;
00120 return vfs_fseek (handle->fd, offset, whence);
00121 case SEEK_CUR:
00122 if (vfs_ftell(handle->buffer) + offset >= ((VFSBuffer *) handle->buffer->handle)->size)
00123 {
00124 handle->which = TRUE;
00125 return vfs_fseek (handle->fd, offset, whence);
00126 }
00127 else
00128 {
00129 gint64 noff;
00130
00131 handle->which = FALSE;
00132 noff = ((VFSBuffer *) handle->buffer->handle)->size - (vfs_ftell(handle->buffer) + offset);
00133 return vfs_fseek (handle->buffer, noff, whence);
00134 }
00135 break;
00136 case SEEK_SET:
00137 default:
00138 if (offset > ((VFSBuffer *) handle->buffer->handle)->size)
00139 {
00140 handle->which = TRUE;
00141 return vfs_fseek (handle->fd, offset, whence);
00142 }
00143 else
00144 {
00145 handle->which = FALSE;
00146 return vfs_fseek (handle->buffer, offset, whence);
00147 }
00148 break;
00149 }
00150 return 0;
00151 }
00152
00153 void
00154 buffered_file_vfs_rewind_impl(VFSFile * file)
00155 {
00156 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00157
00158 vfs_rewind(handle->buffer);
00159 vfs_rewind(handle->fd);
00160 handle->which = FALSE;
00161 }
00162
00163 gint64
00164 buffered_file_vfs_ftell_impl(VFSFile * file)
00165 {
00166 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00167
00168 return vfs_ftell(handle->which == TRUE ? handle->fd : handle->buffer);
00169 }
00170
00171 gboolean
00172 buffered_file_vfs_feof_impl(VFSFile * file)
00173 {
00174 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00175
00176 return vfs_feof(handle->which == TRUE ? handle->fd : handle->buffer);
00177 }
00178
00179 gint
00180 buffered_file_vfs_truncate_impl (VFSFile * file, gint64 size)
00181 {
00182 return 0;
00183 }
00184
00185 gint64
00186 buffered_file_vfs_fsize_impl(VFSFile * file)
00187 {
00188 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00189
00190 return vfs_fsize(handle->fd);
00191 }
00192
00193 gchar *
00194 buffered_file_vfs_metadata_impl(VFSFile * file, const gchar * field)
00195 {
00196 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
00197
00198 return vfs_get_metadata(handle->fd, field);
00199 }
00200
00201 VFSConstructor buffered_file_const = {
00202 NULL,
00203 buffered_file_vfs_fopen_impl,
00204 buffered_file_vfs_fclose_impl,
00205 buffered_file_vfs_fread_impl,
00206 buffered_file_vfs_fwrite_impl,
00207 buffered_file_vfs_getc_impl,
00208 buffered_file_vfs_ungetc_impl,
00209 buffered_file_vfs_fseek_impl,
00210 buffered_file_vfs_rewind_impl,
00211 buffered_file_vfs_ftell_impl,
00212 buffered_file_vfs_feof_impl,
00213 buffered_file_vfs_truncate_impl,
00214 buffered_file_vfs_fsize_impl,
00215 buffered_file_vfs_metadata_impl
00216 };
00217
00224 VFSFile *
00225 vfs_buffered_file_new_from_uri(const gchar *uri)
00226 {
00227 VFSFile *handle;
00228 VFSBufferedFile *fd;
00229 gsize sz;
00230
00231 g_return_val_if_fail(uri != NULL, NULL);
00232
00233 handle = g_new0(VFSFile, 1);
00234 fd = g_new0(VFSBufferedFile, 1);
00235 fd->mem = g_malloc0(128000);
00236 fd->fd = vfs_fopen(uri, "rb");
00237
00238 if (fd->fd == NULL)
00239 {
00240 g_free(fd->mem);
00241 g_free(fd);
00242 g_free(handle);
00243
00244 return NULL;
00245 }
00246
00247 sz = vfs_fread(fd->mem, 1, 128000, fd->fd);
00248 vfs_rewind(fd->fd);
00249
00250 if (!sz)
00251 {
00252 vfs_fclose(fd->fd);
00253 g_free(fd->mem);
00254 g_free(fd);
00255 g_free(handle);
00256
00257 return NULL;
00258 }
00259
00260 fd->buffer = vfs_buffer_new(fd->mem, sz);
00261
00262 handle->handle = fd;
00263 handle->base = &buffered_file_const;
00264 handle->uri = g_strdup(uri);
00265 handle->ref = 1;
00266
00267 return handle;
00268 }
00269
00274 VFSFile *
00275 vfs_buffered_file_release_live_fd(VFSFile *fd)
00276 {
00277 VFSBufferedFile *file = (VFSBufferedFile *) fd;
00278 VFSFile *out;
00279
00280 g_return_val_if_fail(file != NULL, NULL);
00281
00282 out = file->fd;
00283 file->fd = NULL;
00284
00285 vfs_fclose(fd);
00286
00287 return out;
00288 }