Implemented sub-second W32 filesystem interface by new: CaptiveFileInfoObject
[captive.git] / src / client / fuse / capfuse_captive_file_info_object.c
1 /* $Id$
2  * Client fuse interface handling of 'GnomeVFSFileInfo' for libcaptive
3  * Copyright (C) 2005 Jan Kratochvil <project-captive@jankratochvil.net>
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; exactly version 2 of June 1991 is required
8  * 
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.
13  * 
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
17  */
18
19
20 #include "config.h"
21
22 #include <glib/gmessages.h>
23 #include <errno.h>
24 #include <sys/stat.h>
25 #include <time.h>
26 #include <sys/time.h>
27
28 #include <captive/client-file-info.h>
29 #include <captive/client-vfs.h>
30
31 #include "capfuse_captive_file_info_object.h"   /* self */
32 #include "gnomevfsresult.h"
33 #include "main.h"
34
35
36 static CaptiveVfsVolumeInfo volume_info;
37 static gboolean volume_info_valid=FALSE;
38
39
40 int capfuse_captive_file_info_object_to_stat(struct stat *stat,CaptiveFileInfoObject *captive_file_info_object)
41 {
42 guint nsec;
43
44         g_return_val_if_fail(stat!=NULL,-EINVAL);
45         g_return_val_if_fail(CAPTIVE_FILE_INFO_IS_OBJECT(captive_file_info_object),-EINVAL);
46
47         if (!volume_info_valid) {
48 GnomeVFSResult errvfsresult;
49
50                 if (GNOME_VFS_OK!=(errvfsresult=captive_vfs_volume_info_get(capfuse_captive_vfs_object,&volume_info)))
51                         return -gnomevfsresult_to_errno(errvfsresult);
52                 volume_info_valid=TRUE;
53                 }
54
55         stat->st_mode=0;
56
57         if (captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_TYPE)
58                 switch (captive_file_info_object->p.type) {
59                         case GNOME_VFS_FILE_TYPE_REGULAR:
60                                 stat->st_mode|=S_IFREG;
61                                 if (1 /* !private */)
62                                         stat->st_mode|=0444;
63                                 break;
64                         case GNOME_VFS_FILE_TYPE_DIRECTORY:
65                                 stat->st_mode|=S_IFDIR;
66                                 if (1 /* !private */)
67                                         stat->st_mode|=0555;
68                                 break;
69                         default:
70                                 g_warning("Unknown GnomeVFSFileInfo.type=%d of: %s",(int)captive_file_info_object->p.type,captive_file_info_object->p.name);
71                                 return -EINVAL;
72                         }
73         if (captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)
74                 stat->st_mode|=captive_file_info_object->p.permissions & 0777;
75         else
76                 stat->st_mode|=0600;
77
78         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT))
79                 stat->st_nlink=1;
80         else
81                 stat->st_nlink=captive_file_info_object->p.link_count;
82
83         stat->st_uid=0; /* we own the file */
84         stat->st_gid=0; /* we own the file */
85
86         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_SIZE))
87                 stat->st_size=0;
88         else
89                 stat->st_size=captive_file_info_object->p.size;
90
91         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_ATIME))
92                 capfuse_timespec_split_get(&stat->st_atime,&nsec);
93         else {
94                 stat->st_atime=captive_file_info_object->p.atime;
95                 nsec=captive_file_info_object->atime_nsec;
96                 }
97 #if defined(HAVE_STRUCT_STAT_ST_ATIM)
98         g_assert(&stat->st_atim.tv_sec==&stat->st_atime);
99         stat->st_atim.tv_nsec=nsec;
100 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
101         stat->st_atimensec=nsec;
102 #endif
103
104         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_MTIME))
105                 capfuse_timespec_split_get(&stat->st_mtime,&nsec);
106         else {
107                 stat->st_mtime=captive_file_info_object->p.mtime;
108                 nsec=captive_file_info_object->mtime_nsec;
109                 }
110 #if defined(HAVE_STRUCT_STAT_ST_MTIM)
111         g_assert(&stat->st_mtim.tv_sec==&stat->st_mtime);
112         stat->st_mtim.tv_nsec=nsec;
113 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
114         stat->st_mtimensec=nsec;
115 #endif
116
117         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_CTIME))
118                 capfuse_timespec_split_get(&stat->st_ctime,&nsec);
119         else {
120                 stat->st_ctime=captive_file_info_object->p.ctime;
121                 nsec=captive_file_info_object->ctime_nsec;
122                 }
123 #if defined(HAVE_STRUCT_STAT_ST_CTIM)
124         g_assert(&stat->st_ctim.tv_sec==&stat->st_ctime);
125         stat->st_ctim.tv_nsec=nsec;
126 #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
127         stat->st_ctimensec=nsec;
128 #endif
129
130         stat->st_blksize=volume_info.block_size;
131
132         if (!(captive_file_info_object->p.valid_fields&GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT)) {
133                 /* Rounding? */
134                 /* 0? */
135                 stat->st_blocks=stat->st_size/volume_info.block_size;
136                 }
137         else
138                 stat->st_blocks=captive_file_info_object->p.block_count;
139
140         stat->st_dev=0;
141         stat->st_rdev=0;        /* Never to be used. */
142         stat->st_ino=0;
143
144         return 0;
145 }
146
147
148 void capfuse_timespec_split_get(time_t *sec_return,guint *nsec_return)
149 {
150 int errint;
151 struct timeval timeval;
152
153         g_return_if_fail(sec_return!=NULL);
154         g_return_if_fail(nsec_return!=NULL);
155
156         errint=gettimeofday(
157                         &timeval,       /* (struct timeval *)tv */
158                         NULL);  /* (struct timezone *)tz */
159         g_assert(!errint);
160
161         *sec_return=timeval.tv_sec;
162         /* FIXME: Where to get 'usec' precision? */
163         *nsec_return=timeval.tv_usec*1000;
164 }