2 * lufs interface module file objects implementation for libcaptive
3 * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
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; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <glib/gmessages.h>
23 #include "captivefs-misc.h"
24 #include "captivefs-attr.h"
27 #include <captive/client-vfs.h>
28 #include <captive/client-file.h>
33 /* Read a file/dir's attributes
34 * Fill all relevant data into the fattr structure.
35 * The uid/gid fields are just ownership hints hints:
36 * != 0 => we own the file
37 * == 0 => we don't own it
38 * The credentials structure (if applicable and saved from _init)
39 * can help determine ownership based on remote uids/gids.
42 * If your filesysem doesn't natively support '.' or '..',
43 * don't forget to special-case them here.
44 * It is best to assume that name is a relative path, not an
45 * absolute one. Thus, you need to either be keeping track of the
46 * last accessed directory in readdir, or, as this code does, changing
47 * to the current directory there.
49 int captivefs_stat(CaptiveVfsObject *captive_vfs_object,const char *name,struct lufs_fattr *fattr)
51 GnomeVFSResult errvfsresult;
52 CaptiveFileObject *captive_file_object;
53 GnomeVFSFileInfo file_info;
55 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
56 g_return_val_if_fail(name!=NULL,-1);
57 g_return_val_if_fail(fattr!=NULL,-1);
59 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_stat: name=%s",name);
62 errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,name,GNOME_VFS_OPEN_READ);
64 if (errvfsresult!=GNOME_VFS_OK)
68 errvfsresult=captive_file_file_info_get(captive_file_object,&file_info);
70 if (errvfsresult!=GNOME_VFS_OK)
74 g_object_unref(captive_file_object);
77 if (!captivefs_GnomeVFSFileInfo_to_lufs_fattr(fattr,&file_info))
84 g_object_unref(captive_file_object);
93 int captivefs_create(CaptiveVfsObject *captive_vfs_object,const char *file,int mode)
95 GnomeVFSResult errvfsresult;
96 CaptiveFileObject *captive_file_object;
98 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
99 g_return_val_if_fail(file!=NULL,-1);
101 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_create: file=%s,mode=0x%X",file,mode);
104 errvfsresult=captive_file_new_create(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE,
105 FALSE, /* exclusive */
107 G_UNLOCK(libcaptive);
108 if (errvfsresult!=GNOME_VFS_OK)
112 g_object_unref(captive_file_object);
113 G_UNLOCK(libcaptive);
121 int captivefs_unlink(CaptiveVfsObject *captive_vfs_object,const char *file)
123 GnomeVFSResult errvfsresult;
124 CaptiveFileObject *captive_file_object;
126 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
127 g_return_val_if_fail(file!=NULL,-1);
129 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_unlink: file=%s",file);
132 errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE);
133 G_UNLOCK(libcaptive);
134 if (errvfsresult!=GNOME_VFS_OK)
138 errvfsresult=captive_file_remove(captive_file_object);
139 G_UNLOCK(libcaptive);
140 if (errvfsresult!=GNOME_VFS_OK)
144 g_object_unref(captive_file_object);
145 G_UNLOCK(libcaptive);
151 g_object_unref(captive_file_object);
152 G_UNLOCK(libcaptive);
160 int captivefs_rename(CaptiveVfsObject *captive_vfs_object,const char *old_name,const char *new_name)
162 GnomeVFSResult errvfsresult;
163 CaptiveFileObject *captive_file_object;
165 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
166 g_return_val_if_fail(old_name!=NULL,-1);
167 g_return_val_if_fail(new_name!=NULL,-1);
169 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_rename: old_name=%s,new_name=%s",old_name,new_name);
172 errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,old_name,GNOME_VFS_OPEN_WRITE);
173 G_UNLOCK(libcaptive);
174 if (errvfsresult!=GNOME_VFS_OK)
178 errvfsresult=captive_file_move(captive_file_object,new_name,
179 FALSE); /* force_replace */
180 G_UNLOCK(libcaptive);
181 if (errvfsresult!=GNOME_VFS_OK)
185 g_object_unref(captive_file_object);
186 G_UNLOCK(libcaptive);
192 g_object_unref(captive_file_object);
193 G_UNLOCK(libcaptive);
199 /* map: (const gchar *) -> (CaptiveFileObject *) */
200 static GHashTable *FileHandle_hash;
202 static void FileHandle_hash_value_destroy_func(CaptiveFileObject *captive_file_object)
204 g_return_if_fail(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
206 g_object_unref(captive_file_object);
209 static void FileHandle_hash_init(void)
213 FileHandle_hash=g_hash_table_new_full(g_str_hash,g_str_equal,
214 (GDestroyNotify)g_free, /* key_destroy_func */
215 (GDestroyNotify)FileHandle_hash_value_destroy_func); /* value_destroy_func */
218 static CaptiveFileObject *FileHandle_lookup(const char *name)
220 CaptiveFileObject *captive_file_object;
222 g_return_val_if_fail(name!=NULL,NULL);
224 FileHandle_hash_init();
225 if (!(captive_file_object=g_hash_table_lookup(FileHandle_hash,name))) {
226 g_warning("FileHandle_lookup: FileHandle not found of: %s",name);
230 g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
232 return captive_file_object;
239 * By default, LUFS has no concept of file handles. To implement file
240 * handles, take a look at the atbl class in sshfs - it is easy to cut&paste
241 * for use, and can be easily adapted for whatever purpose you need handles
244 * Unlike the POSIX open command which has both a "mode" variable and
245 * a "flags" variable, this only has a "mode" variable. To convert to the
246 * POSIX version, ->flags=mode^O_ACCMODE and ->mode=mode&O_ACCMODE.
248 int captivefs_open(CaptiveVfsObject *captive_vfs_object,const char *file,unsigned mode)
250 CaptiveFileObject *captive_file_object;
251 GnomeVFSOpenMode gnome_vfs_open_mode;
252 GnomeVFSResult errvfsresult;
254 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
255 g_return_val_if_fail(file!=NULL,-1);
257 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_open: file=%s,mode=0x%X",file,mode);
259 FileHandle_hash_init();
260 if ((captive_file_object=g_hash_table_lookup(FileHandle_hash,file))) {
261 g_assert(CAPTIVE_FILE_IS_OBJECT(captive_file_object));
262 g_warning("captivefs_open: FileHandle already exists of: %s",file);
266 if (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
267 g_warning("captivefs_open: Unrecognized 'mode' 0x%X",mode);
270 switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
271 case O_RDONLY: gnome_vfs_open_mode=GNOME_VFS_OPEN_READ; break;
272 case O_WRONLY: gnome_vfs_open_mode=GNOME_VFS_OPEN_WRITE; break;
273 case O_RDWR: gnome_vfs_open_mode=GNOME_VFS_OPEN_READ|GNOME_VFS_OPEN_WRITE; break;
275 g_warning("captivefs_open: Unrecognized 'mode' 0x%X",mode);
280 errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,
281 gnome_vfs_open_mode|GNOME_VFS_OPEN_RANDOM);
282 G_UNLOCK(libcaptive);
283 if (errvfsresult!=GNOME_VFS_OK)
286 g_hash_table_insert(FileHandle_hash,g_strdup(file),captive_file_object);
292 int captivefs_release(CaptiveVfsObject *captive_vfs_object,const char *file)
294 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
295 g_return_val_if_fail(file!=NULL,-1);
297 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_release: file=%s",file);
299 FileHandle_hash_init();
300 if (!g_hash_table_remove(FileHandle_hash,file)) {
301 g_warning("captivefs_release: FileHandle not found of: %s",file);
309 /* Read from a file. Changed to use the (2) routines not for efficiency,
310 * but to make it work with 64-bit offsets :-(.
312 int captivefs_read(CaptiveVfsObject *captive_vfs_object,const char *file,long long offset,unsigned long count,void *buf)
314 CaptiveFileObject *captive_file_object;
315 GnomeVFSFileSize bytes_read;
316 GnomeVFSResult errvfsresult;
318 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
319 g_return_val_if_fail(file!=NULL,-1);
320 g_return_val_if_fail(buf!=NULL || count==0,-1);
322 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_read: file=%s,offset=%" G_GINT64_FORMAT ",count=0x%lX",
323 file,(gint64)offset,count);
325 if (!(captive_file_object=FileHandle_lookup(file)))
329 errvfsresult=captive_file_seek(captive_file_object,GNOME_VFS_SEEK_START,offset);
330 G_UNLOCK(libcaptive);
331 if (errvfsresult!=GNOME_VFS_OK)
335 errvfsresult=captive_file_read(captive_file_object,buf,count,&bytes_read);
336 G_UNLOCK(libcaptive);
337 if (errvfsresult!=GNOME_VFS_OK)
340 if (bytes_read>INT_MAX) {
341 g_warning("captivefs_read: Read %" G_GUINT64_FORMAT " bytes > INT_MAX=%d; dropped data",
342 (guint64)bytes_read,INT_MAX);
352 int captivefs_write(CaptiveVfsObject *captive_vfs_object,const char *file,long long offset,unsigned long count,const void *buf)
354 CaptiveFileObject *captive_file_object;
355 GnomeVFSFileSize bytes_written;
356 GnomeVFSResult errvfsresult;
358 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
359 g_return_val_if_fail(file!=NULL,-1);
360 g_return_val_if_fail(buf!=NULL || count==0,-1);
362 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_write: file=%s,offset=%" G_GINT64_FORMAT ",count=0x%lX",
363 file,(gint64)offset,count);
365 if (!(captive_file_object=FileHandle_lookup(file)))
369 errvfsresult=captive_file_seek(captive_file_object,GNOME_VFS_SEEK_START,offset);
370 G_UNLOCK(libcaptive);
371 if (errvfsresult!=GNOME_VFS_OK)
375 errvfsresult=captive_file_write(captive_file_object,buf,count,&bytes_written);
376 G_UNLOCK(libcaptive);
377 if (errvfsresult!=GNOME_VFS_OK)
380 if (bytes_written>INT_MAX) {
381 g_warning("captivefs_written: Written %" G_GUINT64_FORMAT " bytes > INT_MAX=%d; dropped data",
382 (guint64)bytes_written,INT_MAX);
383 bytes_written=INT_MAX;
386 return bytes_written;
390 /* Change a file/dir's attributes
392 int captivefs_setattr(CaptiveVfsObject *captive_vfs_object,const char *file,const struct lufs_fattr *fattr)
394 GnomeVFSFileInfo file_info;
395 GnomeVFSResult errvfsresult;
396 CaptiveFileObject *captive_file_object;
398 g_return_val_if_fail(CAPTIVE_VFS_IS_OBJECT(captive_vfs_object),-1);
399 g_return_val_if_fail(file!=NULL,-1);
400 g_return_val_if_fail(fattr!=NULL,-1);
402 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_setattr: file=%s",file);
404 if (!captivefs_lufs_fattr_to_GnomeVFSFileInfo(&file_info,fattr))
408 errvfsresult=captive_file_new_open(&captive_file_object,captive_vfs_object,file,GNOME_VFS_OPEN_WRITE);
409 G_UNLOCK(libcaptive);
410 if (errvfsresult!=GNOME_VFS_OK)
414 errvfsresult=captive_file_file_info_set(captive_file_object,&file_info,file_info.valid_fields);
415 G_UNLOCK(libcaptive);
416 if (errvfsresult!=GNOME_VFS_OK)
420 g_object_unref(captive_file_object);
421 G_UNLOCK(libcaptive);
427 g_object_unref(captive_file_object);
428 G_UNLOCK(libcaptive);