readdir was rewritten in Ruby just before the end of the hackfest
[hurd/trovefs.git] / netfs.c
1 /*
2  * Copyright (C) 1997, 1998, 1999, 2001, 2007 Free Software Foundation, Inc.
3  * Copyright (C) 2013  Steven McDonald <steven@steven-mcdonald.id.au>
4  *
5  * ftpfs translator written by Miles Bader <miles@gnu.org>
6  * Modified for trovefs by Steven McDonald <steven@steven-mcdonald.id.au>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This software is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  */
22
23 #include <stdio.h>
24 #include <stddef.h>
25 #include <sys/mman.h>
26 #include <dirent.h>
27 #include <hurd/netfs.h>
28
29 #include "trovefs.h"
30
31 error_t
32 netfs_attempt_link (struct iouser *user, struct node *dir, struct node *file, char *name, int excl)
33 {
34         fprintf (stderr, "a\n");
35         return EOPNOTSUPP;
36 }
37
38 error_t
39 netfs_attempt_create_file (struct iouser *user, struct node *dir, char *name, mode_t mode, struct node **node)
40 {
41         fprintf (stderr, "b\n");
42         return EOPNOTSUPP;
43 }
44
45 error_t
46 netfs_attempt_chown (struct iouser *cred, struct node *node, uid_t uid, uid_t gid)
47 {
48         fprintf (stderr, "c\n");
49         return EOPNOTSUPP;
50 }
51
52 void
53 netfs_node_norefs (struct node *node)
54 {
55         fprintf (stderr, "d\n");
56         return;
57 }
58
59 error_t
60 netfs_attempt_mksymlink (struct iouser *cred, struct node *node, char *name)
61 {
62         fprintf (stderr, "e\n");
63         return EOPNOTSUPP;
64 }
65
66 error_t
67 netfs_attempt_unlink (struct iouser *user, struct node *dir, char *name)
68 {
69         fprintf (stderr, "f\n");
70         return EOPNOTSUPP;
71 }
72
73 error_t
74 netfs_attempt_syncfs (struct iouser *cred, int wait)
75 {
76         return 0;
77 }
78
79 error_t
80 netfs_attempt_lookup (struct iouser *user, struct node *dir, char *name, struct node **node)
81 {
82         fprintf (stderr, "h\n");
83         return EOPNOTSUPP;
84 }
85
86 error_t
87 netfs_attempt_chauthor (struct iouser *cred, struct node *node, uid_t author)
88 {
89         fprintf (stderr, "i\n");
90         return EOPNOTSUPP;
91 }
92
93 error_t
94 netfs_attempt_mkdir (struct iouser *user, struct node *dir, char *name, mode_t mode)
95 {
96         fprintf (stderr, "j\n");
97         return EOPNOTSUPP;
98 }
99
100 error_t
101 netfs_attempt_mkfile (struct iouser *user, struct node *dir, mode_t mode, struct node **node)
102 {
103         fprintf (stderr, "k\n");
104         return EOPNOTSUPP;
105 }
106
107 error_t
108 netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf)
109 {
110         fprintf (stderr, "l\n");
111         return EOPNOTSUPP;
112 }
113
114 error_t
115 netfs_attempt_sync (struct iouser *cred, struct node *node, int wait)
116 {
117         fprintf (stderr, "m\n");
118         return EOPNOTSUPP;
119 }
120
121 error_t
122 netfs_attempt_statfs (struct iouser *cred, struct node *node, fsys_statfsbuf_t *st)
123 {
124         fprintf (stderr, "n\n");
125         return EOPNOTSUPP;
126 }
127
128 error_t
129 netfs_validate_stat (struct node *node, struct iouser *cred)
130 {
131         return trovefs_refresh_node (node);
132 }
133
134 error_t
135 netfs_attempt_chmod (struct iouser *cred, struct node *node, mode_t mode)
136 {
137         fprintf (stderr, "p\n");
138         return EOPNOTSUPP;
139 }
140
141 error_t
142 netfs_attempt_set_size (struct iouser *cred, struct node *node, loff_t size)
143 {
144         fprintf (stderr, "q\n");
145         return EOPNOTSUPP;
146 }
147
148 error_t
149 netfs_attempt_rmdir (struct iouser *user, struct node *dir, char *name)
150 {
151         fprintf (stderr, "r\n");
152         return EOPNOTSUPP;
153 }
154
155 #define DIRENTS_CHUNK_SIZE (8*1024)
156 #define DIRENT_ALIGN 4
157 #define DIRENT_NAME_OFFS offsetof (struct dirent, d_name)
158 #define DIRENT_LEN(name_len) ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) & ~(DIRENT_ALIGN - 1))
159 error_t
160 netfs_get_dirents (struct iouser *cred, struct node *dir, int first_entry, int max_entries, char **data, mach_msg_type_number_t *data_len, vm_size_t max_data_len, int *data_entries)
161 {
162         error_t err = trovefs_refresh_node (dir);
163
164         if (err)
165                 return err;
166
167         struct trovefs_dir *realdir = dir->nn->dir_entry->dir;
168
169         if (! realdir)
170                 return ENOTDIR;
171
172         struct trovefs_dir_entry *e;
173         e = realdir->ordered;
174
175         while (first_entry-- > 0)
176                 if (! e)
177                 {
178                         max_entries = 0;
179                         break;
180                 }
181                 else
182                         e = e->ordered_next;
183
184         if (max_entries != 0)
185         {
186                 size_t size = (max_data_len == 0 || max_data_len > DIRENTS_CHUNK_SIZE ? DIRENTS_CHUNK_SIZE : max_data_len);
187                 *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
188                 err = ((void *) *data == (void *) -1) ? errno : 0;
189
190                 if (! err)
191                 {
192                         char *p = *data;
193                         int count = 0;
194
195                         while ((max_entries == -1 || count < max_entries) && e)
196                         {
197                                 struct dirent hdr;
198                                 size_t name_len = strlen (e->name);
199                                 size_t sz = DIRENT_LEN (name_len);
200                                 int entry_type = e->stat_timestamp ? IFTODT (e->stat.st_mode) : DT_UNKNOWN;
201
202                                 if ((p - *data) + sz > size)
203                                 {
204                                         if (max_data_len > 0)
205                                                 break;
206                                         else
207                                         {
208                                                 vm_address_t extension = (vm_address_t)(*data + size);
209                                                 err = vm_allocate (mach_task_self (), &extension, DIRENTS_CHUNK_SIZE, 0);
210                                                 if (err)
211                                                         break;
212                                                 size += DIRENTS_CHUNK_SIZE;
213                                         }
214                                 }
215
216                                 hdr.d_namlen = name_len;
217                                 hdr.d_fileno = e->stat.st_ino;
218                                 hdr.d_reclen = sz;
219                                 hdr.d_type = entry_type;
220
221                                 memcpy (p, &hdr, DIRENT_NAME_OFFS);
222                                 strcpy (p + DIRENT_NAME_OFFS, e->name);
223                                 p += sz;
224
225                                 count++;
226                                 e = e->ordered_next;
227                         }
228
229                         if (err)
230                                 munmap (*data, size);
231                         else
232                         {
233                                 vm_address_t alloc_end = (vm_address_t)(*data + size);
234                                 vm_address_t real_end = round_page (p);
235                                 if (alloc_end > real_end)
236                                         munmap ((caddr_t) real_end, alloc_end - real_end);
237                                 *data_len = p - *data;
238                                 *data_entries = count;
239                         }
240                 }
241         }
242         else
243         {
244                 *data_len = 0;
245                 *data_entries = 0;
246         }
247
248         return err;
249 }
250
251 error_t
252 netfs_attempt_chflags (struct iouser *cred, struct node *node, int flags)
253 {
254         fprintf (stderr, "t\n");
255         return EOPNOTSUPP;
256 }
257
258 error_t
259 netfs_attempt_write (struct iouser *cred, struct node *node, loff_t offset, size_t *len, void *data)
260 {
261         fprintf (stderr, "u\n");
262         return EOPNOTSUPP;
263 }
264
265 error_t
266 netfs_attempt_read (struct iouser *cred, struct node *node, loff_t offset, size_t *len, void *data)
267 {
268         fprintf (stderr, "v\n");
269         return EOPNOTSUPP;
270 }
271
272 error_t
273 netfs_report_access (struct iouser *cred, struct node *node, int *types)
274 {
275         fprintf (stderr, "w\n");
276         return EOPNOTSUPP;
277 }
278
279 error_t
280 netfs_attempt_mkdev (struct iouser *cred, struct node *node, mode_t type, dev_t indexes)
281 {
282         fprintf (stderr, "x\n");
283         return EOPNOTSUPP;
284 }
285
286 error_t
287 netfs_attempt_utimes (struct iouser *cred, struct node *node, struct timespec *atime, struct timespec *mtime)
288 {
289         fprintf (stderr, "y\n");
290         return EOPNOTSUPP;
291 }
292
293 error_t
294 netfs_check_open_permissions (struct iouser *user, struct node *node, int flags, int newnode)
295 {
296         return 0;
297 }
298
299 error_t
300 netfs_attempt_rename (struct iouser *user, struct node *fromdir, char *fromname, struct node *todir, char *toname, int excl)
301 {
302         fprintf (stderr, "=\n");
303         return EOPNOTSUPP;
304 }