diff options
Diffstat (limited to 'src/fuse/readdir.c')
-rw-r--r-- | src/fuse/readdir.c | 148 |
1 files changed, 12 insertions, 136 deletions
diff --git a/src/fuse/readdir.c b/src/fuse/readdir.c index 9cb914b..32bd10d 100644 --- a/src/fuse/readdir.c +++ b/src/fuse/readdir.c | |||
@@ -53,153 +53,29 @@ | |||
53 | #include "gnunet-fuse.h" | 53 | #include "gnunet-fuse.h" |
54 | #include "gfs_download.h" | 54 | #include "gfs_download.h" |
55 | 55 | ||
56 | /** | ||
57 | * Closure for 'process_directory_entry'. | ||
58 | */ | ||
59 | struct DepContext | ||
60 | { | ||
61 | /** | ||
62 | * Function to call on each entry. | ||
63 | */ | ||
64 | fuse_fill_dir_t filler; | ||
65 | |||
66 | /** | ||
67 | * 'buf' argument to give to filler. | ||
68 | */ | ||
69 | void *buf; | ||
70 | |||
71 | /** | ||
72 | * Basepath to add for the entries. | ||
73 | */ | ||
74 | const char *path; | ||
75 | }; | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Function used to process entries in a directory. | ||
80 | * | ||
81 | * @param cls closure | ||
82 | * @param filename name of the file in the directory | ||
83 | * @param uri URI of the file | ||
84 | * @param metadata metadata for the file; metadata for | ||
85 | * the directory if everything else is NULL/zero | ||
86 | * @param length length of the available data for the file | ||
87 | * (of type size_t since data must certainly fit | ||
88 | * into memory; if files are larger than size_t | ||
89 | * permits, then they will certainly not be | ||
90 | * embedded with the directory itself). | ||
91 | * @param data data available for the file (length bytes) | ||
92 | */ | ||
93 | static void | ||
94 | process_directory_entry (void *cls, | ||
95 | const char *filename, | ||
96 | const struct GNUNET_FS_Uri * | ||
97 | uri, | ||
98 | const struct | ||
99 | GNUNET_CONTAINER_MetaData * | ||
100 | meta, size_t length, | ||
101 | const void *data) | ||
102 | { | ||
103 | struct DepContext *dc = cls; | ||
104 | struct GNUNET_FUSE_PathInfo *pi; | ||
105 | char *path; | ||
106 | int is_directory; | ||
107 | |||
108 | if (NULL == filename) | ||
109 | return; /* info about the directory itself */ | ||
110 | GNUNET_asprintf (&path, | ||
111 | "%s%s", | ||
112 | dc->path, | ||
113 | filename); | ||
114 | is_directory = GNUNET_FS_meta_data_test_for_directory (meta); | ||
115 | if (GNUNET_SYSERR == is_directory) | ||
116 | is_directory = GNUNET_NO; /* if in doubt, say no */ | ||
117 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
118 | "Listing filename `%s' in directory `%s' (%s)\n", | ||
119 | filename, | ||
120 | dc->path, | ||
121 | path); | ||
122 | pi = GNUNET_FUSE_path_info_create (path, uri, is_directory); | ||
123 | dc->filler (dc->buf, | ||
124 | filename, | ||
125 | &pi->stbuf, | ||
126 | 0); | ||
127 | GNUNET_FUSE_path_info_done (pi); | ||
128 | } | ||
129 | |||
130 | 56 | ||
131 | int | 57 | int |
132 | gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler, | 58 | gn_readdir (const char *path, void *buf, fuse_fill_dir_t filler, |
133 | off_t offset, struct fuse_file_info *fi) | 59 | off_t offset, struct fuse_file_info *fi) |
134 | { | 60 | { |
135 | struct GNUNET_FUSE_PathInfo *path_info; | 61 | struct GNUNET_FUSE_PathInfo *path_info; |
136 | struct DepContext dc; | 62 | struct GNUNET_FUSE_PathInfo *pos; |
137 | size_t size; | 63 | int eno; |
138 | int ret; | ||
139 | void *data; | ||
140 | struct GNUNET_DISK_MapHandle *mh; | ||
141 | struct GNUNET_DISK_FileHandle *fh; | ||
142 | 64 | ||
143 | path_info = GNUNET_FUSE_path_info_get (path); | 65 | path_info = GNUNET_FUSE_path_info_get (path, &eno); |
144 | if (NULL == path_info) | 66 | if (NULL == path_info) |
145 | { | 67 | return - eno; |
146 | /* FIXME: we might need to check which of the ancestors | 68 | if ( (NULL == path_info->tmpfile) && |
147 | exist and possibly download ancestral directories, | 69 | (GNUNET_OK != GNUNET_FUSE_load_directory (path_info, &eno)) ) |
148 | instead of directly giving up here... */ | 70 | return - eno; |
149 | return - ENOENT; | ||
150 | } | ||
151 | |||
152 | if (NULL == path_info->tmpfile) | ||
153 | { | ||
154 | /* store to temporary file */ | ||
155 | path_info->tmpfile = GNUNET_DISK_mktemp ("gnunet-fuse-tempfile"); | ||
156 | if (GNUNET_OK != GNUNET_FUSE_download_file (path_info, | ||
157 | 0, | ||
158 | GNUNET_FS_uri_chk_get_file_size (path_info->uri))) | ||
159 | { | ||
160 | UNLINK (path_info->tmpfile); | ||
161 | GNUNET_free (path_info->tmpfile); | ||
162 | path_info->tmpfile = NULL; | ||
163 | GNUNET_FUSE_path_info_done (path_info); | ||
164 | return - EIO; /* low level IO error */ | ||
165 | } | ||
166 | } | ||
167 | |||
168 | dc.filler = filler; | ||
169 | dc.path = path; | ||
170 | dc.buf = buf; | ||
171 | size = (size_t) GNUNET_FS_uri_chk_get_file_size (path_info->uri); | ||
172 | fh = GNUNET_DISK_file_open (path_info->tmpfile, | ||
173 | GNUNET_DISK_OPEN_READ, | ||
174 | GNUNET_DISK_PERM_NONE); | ||
175 | if (NULL == fh) | ||
176 | { | ||
177 | GNUNET_FUSE_path_info_done (path_info); | ||
178 | return -EBADF; | ||
179 | } | ||
180 | data = GNUNET_DISK_file_map (fh, | ||
181 | &mh, | ||
182 | GNUNET_DISK_MAP_TYPE_READ, | ||
183 | size); | ||
184 | if (NULL == data) | ||
185 | { | ||
186 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); | ||
187 | GNUNET_FUSE_path_info_done (path_info); | ||
188 | return -EBADF; | ||
189 | } | ||
190 | filler (buf, ".", NULL, 0); | 71 | filler (buf, ".", NULL, 0); |
191 | filler (buf, "..", NULL, 0); | 72 | filler (buf, "..", NULL, 0); |
192 | ret = 0; | 73 | for (pos = path_info->child_head; NULL != pos; pos = pos->next) |
193 | if (GNUNET_OK != | 74 | filler (buf, pos->filename, |
194 | GNUNET_FS_directory_list_contents (size, | 75 | &pos->stbuf, |
195 | data, 0LL, | 76 | 0); |
196 | &process_directory_entry, | ||
197 | &dc)) | ||
198 | ret = - EIO; | ||
199 | GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_unmap (mh)); | ||
200 | GNUNET_DISK_file_close (fh); | ||
201 | GNUNET_FUSE_path_info_done (path_info); | 77 | GNUNET_FUSE_path_info_done (path_info); |
202 | return ret; | 78 | return 0; |
203 | } | 79 | } |
204 | 80 | ||
205 | /* end of readdir.c */ | 81 | /* end of readdir.c */ |