scoutos / prex-0.9.0 / usr / server / fs / fatfs / fatfs_vnops.c @ 03e9c04a
History | View | Annotate | Download (15.1 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 2005-2008, Kohsuke Ohtani
|
3 |
* All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the author nor the names of any co-contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
#include <sys/prex.h> |
31 |
|
32 |
#include <sys/vnode.h> |
33 |
#include <sys/file.h> |
34 |
#include <sys/mount.h> |
35 |
#include <sys/dirent.h> |
36 |
#include <sys/buf.h> |
37 |
|
38 |
#include <ctype.h> |
39 |
#include <unistd.h> |
40 |
#include <errno.h> |
41 |
#include <string.h> |
42 |
#include <stdlib.h> |
43 |
#include <fcntl.h> |
44 |
|
45 |
#include "fatfs.h" |
46 |
|
47 |
/*
|
48 |
* Time bits: 15-11 hours (0-23), 10-5 min, 4-0 sec /2
|
49 |
* Date bits: 15-9 year - 1980, 8-5 month, 4-0 day
|
50 |
*/
|
51 |
#define TEMP_DATE 0x3021 |
52 |
#define TEMP_TIME 0 |
53 |
|
54 |
#define fatfs_open ((vnop_open_t)vop_nullop)
|
55 |
#define fatfs_close ((vnop_close_t)vop_nullop)
|
56 |
static int fatfs_read (vnode_t, file_t, void *, size_t, size_t *); |
57 |
static int fatfs_write (vnode_t, file_t, void *, size_t, size_t *); |
58 |
#define fatfs_seek ((vnop_seek_t)vop_nullop)
|
59 |
#define fatfs_ioctl ((vnop_ioctl_t)vop_einval)
|
60 |
#define fatfs_fsync ((vnop_fsync_t)vop_nullop)
|
61 |
static int fatfs_readdir(vnode_t, file_t, struct dirent *); |
62 |
static int fatfs_lookup (vnode_t, char *, vnode_t); |
63 |
static int fatfs_create (vnode_t, char *, mode_t); |
64 |
static int fatfs_remove (vnode_t, vnode_t, char *); |
65 |
static int fatfs_rename (vnode_t, vnode_t, char *, vnode_t, vnode_t, char *); |
66 |
static int fatfs_mkdir (vnode_t, char *, mode_t); |
67 |
static int fatfs_rmdir (vnode_t, vnode_t, char *); |
68 |
static int fatfs_getattr(vnode_t, struct vattr *); |
69 |
static int fatfs_setattr(vnode_t, struct vattr *); |
70 |
static int fatfs_inactive(vnode_t); |
71 |
static int fatfs_truncate(vnode_t, off_t); |
72 |
|
73 |
/*
|
74 |
* vnode operations
|
75 |
*/
|
76 |
struct vnops fatfs_vnops = {
|
77 |
fatfs_open, /* open */
|
78 |
fatfs_close, /* close */
|
79 |
fatfs_read, /* read */
|
80 |
fatfs_write, /* write */
|
81 |
fatfs_seek, /* seek */
|
82 |
fatfs_ioctl, /* ioctl */
|
83 |
fatfs_fsync, /* fsync */
|
84 |
fatfs_readdir, /* readdir */
|
85 |
fatfs_lookup, /* lookup */
|
86 |
fatfs_create, /* create */
|
87 |
fatfs_remove, /* remove */
|
88 |
fatfs_rename, /* remame */
|
89 |
fatfs_mkdir, /* mkdir */
|
90 |
fatfs_rmdir, /* rmdir */
|
91 |
fatfs_getattr, /* getattr */
|
92 |
fatfs_setattr, /* setattr */
|
93 |
fatfs_inactive, /* inactive */
|
94 |
fatfs_truncate, /* truncate */
|
95 |
}; |
96 |
|
97 |
/*
|
98 |
* Read one cluster to buffer.
|
99 |
*/
|
100 |
static int |
101 |
fat_read_cluster(struct fatfsmount *fmp, u_long cluster)
|
102 |
{ |
103 |
u_long sec; |
104 |
size_t size; |
105 |
|
106 |
sec = cl_to_sec(fmp, cluster); |
107 |
size = fmp->sec_per_cl * SEC_SIZE; |
108 |
return device_read(fmp->dev, fmp->io_buf, &size, sec);
|
109 |
} |
110 |
|
111 |
/*
|
112 |
* Write one cluster from buffer.
|
113 |
*/
|
114 |
static int |
115 |
fat_write_cluster(struct fatfsmount *fmp, u_long cluster)
|
116 |
{ |
117 |
u_long sec; |
118 |
size_t size; |
119 |
|
120 |
sec = cl_to_sec(fmp, cluster); |
121 |
size = fmp->sec_per_cl * SEC_SIZE; |
122 |
return device_write(fmp->dev, fmp->io_buf, &size, sec);
|
123 |
} |
124 |
|
125 |
/*
|
126 |
* Lookup vnode for the specified file/directory.
|
127 |
* The vnode data will be set properly.
|
128 |
*/
|
129 |
static int |
130 |
fatfs_lookup(vnode_t dvp, char *name, vnode_t vp)
|
131 |
{ |
132 |
struct fatfsmount *fmp;
|
133 |
struct fat_dirent *de;
|
134 |
struct fatfs_node *np;
|
135 |
int error;
|
136 |
|
137 |
if (*name == '\0') |
138 |
return ENOENT;
|
139 |
|
140 |
fmp = vp->v_mount->m_data; |
141 |
mutex_lock(&fmp->lock); |
142 |
|
143 |
DPRINTF(("fatfs_lookup: name=%s\n", name));
|
144 |
|
145 |
np = vp->v_data; |
146 |
error = fatfs_lookup_node(dvp, name, np); |
147 |
if (error) {
|
148 |
DPRINTF(("fatfs_lookup: failed!! name=%s\n", name));
|
149 |
mutex_unlock(&fmp->lock); |
150 |
return error;
|
151 |
} |
152 |
de = &np->dirent; |
153 |
vp->v_type = IS_DIR(de) ? VDIR : VREG; |
154 |
fat_attr_to_mode(de->attr, &vp->v_mode); |
155 |
vp->v_mode = ALLPERMS; |
156 |
vp->v_size = de->size; |
157 |
vp->v_blkno = de->cluster; |
158 |
|
159 |
DPRINTF(("fatfs_lookup: cl=%d\n", de->cluster));
|
160 |
mutex_unlock(&fmp->lock); |
161 |
return 0; |
162 |
} |
163 |
|
164 |
static int |
165 |
fatfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
|
166 |
{ |
167 |
struct fatfsmount *fmp;
|
168 |
int nr_read, nr_copy, buf_pos, error;
|
169 |
u_long cl, file_pos; |
170 |
|
171 |
DPRINTF(("fatfs_read: vp=%x\n", vp));
|
172 |
|
173 |
*result = 0;
|
174 |
fmp = vp->v_mount->m_data; |
175 |
|
176 |
if (vp->v_type == VDIR)
|
177 |
return EISDIR;
|
178 |
if (vp->v_type != VREG)
|
179 |
return EINVAL;
|
180 |
|
181 |
/* Check if current file position is already end of file. */
|
182 |
file_pos = fp->f_offset; |
183 |
if (file_pos >= vp->v_size)
|
184 |
return 0; |
185 |
|
186 |
mutex_lock(&fmp->lock); |
187 |
|
188 |
/* Get the actual read size. */
|
189 |
if (vp->v_size - file_pos < size)
|
190 |
size = vp->v_size - file_pos; |
191 |
|
192 |
/* Seek to the cluster for the file offset */
|
193 |
error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl); |
194 |
if (error)
|
195 |
goto out;
|
196 |
|
197 |
/* Read and copy data */
|
198 |
nr_read = 0;
|
199 |
buf_pos = file_pos % fmp->cluster_size; |
200 |
do {
|
201 |
if (fat_read_cluster(fmp, cl)) {
|
202 |
error = EIO; |
203 |
goto out;
|
204 |
} |
205 |
|
206 |
nr_copy = fmp->cluster_size; |
207 |
if (buf_pos > 0) |
208 |
nr_copy -= buf_pos; |
209 |
if (buf_pos + size < fmp->cluster_size)
|
210 |
nr_copy = size; |
211 |
memcpy(buf, fmp->io_buf + buf_pos, nr_copy); |
212 |
|
213 |
file_pos += nr_copy; |
214 |
nr_read += nr_copy; |
215 |
size -= nr_copy; |
216 |
if (size <= 0) |
217 |
break;
|
218 |
|
219 |
error = fat_next_cluster(fmp, cl, &cl); |
220 |
if (error)
|
221 |
goto out;
|
222 |
|
223 |
buf = (void *)((u_long)buf + nr_copy);
|
224 |
buf_pos = 0;
|
225 |
} while (!IS_EOFCL(fmp, cl));
|
226 |
|
227 |
fp->f_offset = file_pos; |
228 |
*result = nr_read; |
229 |
error = 0;
|
230 |
out:
|
231 |
mutex_unlock(&fmp->lock); |
232 |
return error;
|
233 |
} |
234 |
|
235 |
static int |
236 |
fatfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
|
237 |
{ |
238 |
struct fatfsmount *fmp;
|
239 |
struct fatfs_node *np;
|
240 |
struct fat_dirent *de;
|
241 |
int nr_copy, nr_write, buf_pos, i, cl_size, error;
|
242 |
u_long file_pos, end_pos; |
243 |
u_long cl; |
244 |
|
245 |
DPRINTF(("fatfs_write: vp=%x\n", vp));
|
246 |
|
247 |
*result = 0;
|
248 |
fmp = vp->v_mount->m_data; |
249 |
|
250 |
if (vp->v_type == VDIR)
|
251 |
return EISDIR;
|
252 |
if (vp->v_type != VREG)
|
253 |
return EINVAL;
|
254 |
|
255 |
mutex_lock(&fmp->lock); |
256 |
|
257 |
/* Check if file position exceeds the end of file. */
|
258 |
end_pos = vp->v_size; |
259 |
file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset; |
260 |
if (file_pos + size > end_pos) {
|
261 |
/* Expand the file size before writing to it */
|
262 |
end_pos = file_pos + size; |
263 |
error = fat_expand_file(fmp, vp->v_blkno, end_pos); |
264 |
if (error) {
|
265 |
error = EIO; |
266 |
goto out;
|
267 |
} |
268 |
|
269 |
/* Update directory entry */
|
270 |
np = vp->v_data; |
271 |
de = &np->dirent; |
272 |
de->size = end_pos; |
273 |
error = fatfs_put_node(fmp, np); |
274 |
if (error)
|
275 |
goto out;
|
276 |
vp->v_size = end_pos; |
277 |
} |
278 |
|
279 |
/* Seek to the cluster for the file offset */
|
280 |
error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl); |
281 |
if (error)
|
282 |
goto out;
|
283 |
|
284 |
buf_pos = file_pos % fmp->cluster_size; |
285 |
cl_size = size / fmp->cluster_size + 1;
|
286 |
nr_write = 0;
|
287 |
i = 0;
|
288 |
do {
|
289 |
/* First and last cluster must be read before write */
|
290 |
if (i == 0 || i == cl_size) { |
291 |
if (fat_read_cluster(fmp, cl)) {
|
292 |
error = EIO; |
293 |
goto out;
|
294 |
} |
295 |
} |
296 |
nr_copy = fmp->cluster_size; |
297 |
if (buf_pos > 0) |
298 |
nr_copy -= buf_pos; |
299 |
if (buf_pos + size < fmp->cluster_size)
|
300 |
nr_copy = size; |
301 |
memcpy(fmp->io_buf + buf_pos, buf, nr_copy); |
302 |
|
303 |
if (fat_write_cluster(fmp, cl)) {
|
304 |
error = EIO; |
305 |
goto out;
|
306 |
} |
307 |
file_pos += nr_copy; |
308 |
nr_write += nr_copy; |
309 |
size -= nr_copy; |
310 |
if (size <= 0) |
311 |
break;
|
312 |
|
313 |
error = fat_next_cluster(fmp, cl, &cl); |
314 |
if (error)
|
315 |
goto out;
|
316 |
|
317 |
buf = (void *)((u_long)buf + nr_copy);
|
318 |
buf_pos = 0;
|
319 |
i++; |
320 |
} while (!IS_EOFCL(fmp, cl));
|
321 |
|
322 |
fp->f_offset = file_pos; |
323 |
|
324 |
/*
|
325 |
* XXX: Todo!
|
326 |
* de.time = ?
|
327 |
* de.date = ?
|
328 |
* if (dirent_set(fp, &de))
|
329 |
* return EIO;
|
330 |
*/
|
331 |
*result = nr_write; |
332 |
error = 0;
|
333 |
out:
|
334 |
mutex_unlock(&fmp->lock); |
335 |
return error;
|
336 |
} |
337 |
|
338 |
static int |
339 |
fatfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
|
340 |
{ |
341 |
struct fatfsmount *fmp;
|
342 |
struct fatfs_node np;
|
343 |
struct fat_dirent *de;
|
344 |
int error;
|
345 |
|
346 |
fmp = vp->v_mount->m_data; |
347 |
mutex_lock(&fmp->lock); |
348 |
|
349 |
error = fatfs_get_node(vp, fp->f_offset, &np); |
350 |
if (error)
|
351 |
goto out;
|
352 |
de = &np.dirent; |
353 |
fat_restore_name((char *)&de->name, dir->d_name);
|
354 |
|
355 |
if (de->attr & FA_SUBDIR)
|
356 |
dir->d_type = DT_DIR; |
357 |
else if (de->attr & FA_DEVICE) |
358 |
dir->d_type = DT_BLK; |
359 |
else
|
360 |
dir->d_type = DT_REG; |
361 |
|
362 |
dir->d_fileno = fp->f_offset; |
363 |
dir->d_namlen = strlen(dir->d_name); |
364 |
|
365 |
fp->f_offset++; |
366 |
error = 0;
|
367 |
out:
|
368 |
mutex_unlock(&fmp->lock); |
369 |
return error;
|
370 |
} |
371 |
|
372 |
/*
|
373 |
* Create empty file.
|
374 |
*/
|
375 |
static int |
376 |
fatfs_create(vnode_t dvp, char *name, mode_t mode)
|
377 |
{ |
378 |
struct fatfsmount *fmp;
|
379 |
struct fatfs_node np;
|
380 |
struct fat_dirent *de;
|
381 |
u_long cl; |
382 |
int error;
|
383 |
|
384 |
DPRINTF(("fatfs_create: %s\n", name));
|
385 |
|
386 |
if (!S_ISREG(mode))
|
387 |
return EINVAL;
|
388 |
|
389 |
if (!fat_valid_name(name))
|
390 |
return EINVAL;
|
391 |
|
392 |
fmp = dvp->v_mount->m_data; |
393 |
mutex_lock(&fmp->lock); |
394 |
|
395 |
/* Allocate free cluster for new file. */
|
396 |
error = fat_alloc_cluster(fmp, 0, &cl);
|
397 |
if (error)
|
398 |
goto out;
|
399 |
|
400 |
de = &np.dirent; |
401 |
memset(de, 0, sizeof(struct fat_dirent)); |
402 |
fat_convert_name(name, (char *)de->name);
|
403 |
de->cluster = cl; |
404 |
de->time = TEMP_TIME; |
405 |
de->date = TEMP_DATE; |
406 |
fat_mode_to_attr(mode, &de->attr); |
407 |
error = fatfs_add_node(dvp, &np); |
408 |
if (error)
|
409 |
goto out;
|
410 |
error = fat_set_cluster(fmp, cl, fmp->fat_eof); |
411 |
out:
|
412 |
mutex_unlock(&fmp->lock); |
413 |
return error;
|
414 |
} |
415 |
|
416 |
static int |
417 |
fatfs_remove(vnode_t dvp, vnode_t vp, char *name)
|
418 |
{ |
419 |
struct fatfsmount *fmp;
|
420 |
struct fatfs_node np;
|
421 |
struct fat_dirent *de;
|
422 |
int error;
|
423 |
|
424 |
if (*name == '\0') |
425 |
return ENOENT;
|
426 |
|
427 |
fmp = dvp->v_mount->m_data; |
428 |
mutex_lock(&fmp->lock); |
429 |
|
430 |
error = fatfs_lookup_node(dvp, name, &np); |
431 |
if (error)
|
432 |
goto out;
|
433 |
de = &np.dirent; |
434 |
if (IS_DIR(de)) {
|
435 |
error = EISDIR; |
436 |
goto out;
|
437 |
} |
438 |
if (!IS_FILE(de)) {
|
439 |
error = EPERM; |
440 |
goto out;
|
441 |
} |
442 |
|
443 |
/* Remove clusters */
|
444 |
error = fat_free_clusters(fmp, de->cluster); |
445 |
if (error)
|
446 |
goto out;
|
447 |
|
448 |
/* remove directory */
|
449 |
de->name[0] = 0xe5; |
450 |
error = fatfs_put_node(fmp, &np); |
451 |
out:
|
452 |
mutex_unlock(&fmp->lock); |
453 |
return error;
|
454 |
} |
455 |
|
456 |
static int |
457 |
fatfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,
|
458 |
vnode_t dvp2, vnode_t vp2, char *name2)
|
459 |
{ |
460 |
struct fatfsmount *fmp;
|
461 |
struct fatfs_node np1;
|
462 |
struct fat_dirent *de1, *de2;
|
463 |
int error;
|
464 |
|
465 |
fmp = dvp1->v_mount->m_data; |
466 |
mutex_lock(&fmp->lock); |
467 |
|
468 |
error = fatfs_lookup_node(dvp1, name1, &np1); |
469 |
if (error)
|
470 |
goto out;
|
471 |
de1 = &np1.dirent; |
472 |
|
473 |
if (IS_FILE(de1)) {
|
474 |
/* Remove destination file, first */
|
475 |
error = fatfs_remove(dvp2, vp1, name2); |
476 |
if (error == EIO)
|
477 |
goto out;
|
478 |
|
479 |
/* Change file name of directory entry */
|
480 |
fat_convert_name(name2, (char *)de1->name);
|
481 |
|
482 |
/* Same directory ? */
|
483 |
if (dvp1 == dvp2) {
|
484 |
/* Change the name of existing file */
|
485 |
error = fatfs_put_node(fmp, &np1); |
486 |
if (error)
|
487 |
goto out;
|
488 |
} else {
|
489 |
/* Create new directory entry */
|
490 |
error = fatfs_add_node(dvp2, &np1); |
491 |
if (error)
|
492 |
goto out;
|
493 |
|
494 |
/* Remove souce file */
|
495 |
error = fatfs_remove(dvp1, vp2, name1); |
496 |
if (error)
|
497 |
goto out;
|
498 |
} |
499 |
} else {
|
500 |
|
501 |
/* remove destination directory */
|
502 |
error = fatfs_rmdir(dvp2, NULL, name2);
|
503 |
if (error == EIO)
|
504 |
goto out;
|
505 |
|
506 |
/* Change file name of directory entry */
|
507 |
fat_convert_name(name2, (char *)de1->name);
|
508 |
|
509 |
/* Same directory ? */
|
510 |
if (dvp1 == dvp2) {
|
511 |
/* Change the name of existing directory */
|
512 |
error = fatfs_put_node(fmp, &np1); |
513 |
if (error)
|
514 |
goto out;
|
515 |
} else {
|
516 |
/* Create new directory entry */
|
517 |
error = fatfs_add_node(dvp2, &np1); |
518 |
if (error)
|
519 |
goto out;
|
520 |
|
521 |
/* Update "." and ".." for renamed directory */
|
522 |
if (fat_read_cluster(fmp, de1->cluster)) {
|
523 |
error = EIO; |
524 |
goto out;
|
525 |
} |
526 |
|
527 |
de2 = (struct fat_dirent *)fmp->io_buf;
|
528 |
de2->cluster = de1->cluster; |
529 |
de2->time = TEMP_TIME; |
530 |
de2->date = TEMP_DATE; |
531 |
de2++; |
532 |
de2->cluster = dvp2->v_blkno; |
533 |
de2->time = TEMP_TIME; |
534 |
de2->date = TEMP_DATE; |
535 |
|
536 |
if (fat_write_cluster(fmp, de1->cluster)) {
|
537 |
error = EIO; |
538 |
goto out;
|
539 |
} |
540 |
|
541 |
/* Remove souce directory */
|
542 |
error = fatfs_rmdir(dvp1, NULL, name1);
|
543 |
if (error)
|
544 |
goto out;
|
545 |
} |
546 |
} |
547 |
out:
|
548 |
mutex_unlock(&fmp->lock); |
549 |
return error;
|
550 |
} |
551 |
|
552 |
static int |
553 |
fatfs_mkdir(vnode_t dvp, char *name, mode_t mode)
|
554 |
{ |
555 |
struct fatfsmount *fmp;
|
556 |
struct fatfs_node np;
|
557 |
struct fat_dirent *de;
|
558 |
u_long cl; |
559 |
int error;
|
560 |
|
561 |
if (!S_ISDIR(mode))
|
562 |
return EINVAL;
|
563 |
|
564 |
if (!fat_valid_name(name))
|
565 |
return ENOTDIR;
|
566 |
|
567 |
fmp = dvp->v_mount->m_data; |
568 |
mutex_lock(&fmp->lock); |
569 |
|
570 |
/* Allocate free cluster for directory data */
|
571 |
error = fat_alloc_cluster(fmp, 0, &cl);
|
572 |
if (error)
|
573 |
goto out;
|
574 |
|
575 |
memset(&np, 0, sizeof(struct fatfs_node)); |
576 |
de = &np.dirent; |
577 |
fat_convert_name(name, (char *)&de->name);
|
578 |
de->cluster = cl; |
579 |
de->time = TEMP_TIME; |
580 |
de->date = TEMP_DATE; |
581 |
fat_mode_to_attr(mode, &de->attr); |
582 |
error = fatfs_add_node(dvp, &np); |
583 |
if (error)
|
584 |
goto out;
|
585 |
|
586 |
/* Initialize "." and ".." for new directory */
|
587 |
memset(fmp->io_buf, 0, fmp->cluster_size);
|
588 |
|
589 |
de = (struct fat_dirent *)fmp->io_buf;
|
590 |
memcpy(de->name, ". ", 11); |
591 |
de->attr = FA_SUBDIR; |
592 |
de->cluster = cl; |
593 |
de->time = TEMP_TIME; |
594 |
de->date = TEMP_DATE; |
595 |
de++; |
596 |
memcpy(de->name, ".. ", 11); |
597 |
de->attr = FA_SUBDIR; |
598 |
de->cluster = dvp->v_blkno; |
599 |
de->time = TEMP_TIME; |
600 |
de->date = TEMP_DATE; |
601 |
|
602 |
if (fat_write_cluster(fmp, cl)) {
|
603 |
error = EIO; |
604 |
goto out;
|
605 |
} |
606 |
/* Add eof */
|
607 |
error = fat_set_cluster(fmp, cl, fmp->fat_eof); |
608 |
out:
|
609 |
mutex_unlock(&fmp->lock); |
610 |
return error;
|
611 |
} |
612 |
|
613 |
/*
|
614 |
* remove can be done only with empty directory
|
615 |
*/
|
616 |
static int |
617 |
fatfs_rmdir(vnode_t dvp, vnode_t vp, char *name)
|
618 |
{ |
619 |
struct fatfsmount *fmp;
|
620 |
struct fatfs_node np;
|
621 |
struct fat_dirent *de;
|
622 |
int error;
|
623 |
|
624 |
if (*name == '\0') |
625 |
return ENOENT;
|
626 |
|
627 |
fmp = dvp->v_mount->m_data; |
628 |
mutex_lock(&fmp->lock); |
629 |
|
630 |
error = fatfs_lookup_node(dvp, name, &np); |
631 |
if (error)
|
632 |
goto out;
|
633 |
|
634 |
de = &np.dirent; |
635 |
if (!IS_DIR(de)) {
|
636 |
error = ENOTDIR; |
637 |
goto out;
|
638 |
} |
639 |
|
640 |
/* Remove clusters */
|
641 |
error = fat_free_clusters(fmp, de->cluster); |
642 |
if (error)
|
643 |
goto out;
|
644 |
|
645 |
/* remove directory */
|
646 |
de->name[0] = 0xe5; |
647 |
|
648 |
error = fatfs_put_node(fmp, &np); |
649 |
out:
|
650 |
mutex_unlock(&fmp->lock); |
651 |
return error;
|
652 |
} |
653 |
|
654 |
static int |
655 |
fatfs_getattr(vnode_t vp, struct vattr *vap)
|
656 |
{ |
657 |
/* XXX */
|
658 |
return 0; |
659 |
} |
660 |
|
661 |
static int |
662 |
fatfs_setattr(vnode_t vp, struct vattr *vap)
|
663 |
{ |
664 |
/* XXX */
|
665 |
return 0; |
666 |
} |
667 |
|
668 |
|
669 |
static int |
670 |
fatfs_inactive(vnode_t vp) |
671 |
{ |
672 |
|
673 |
free(vp->v_data); |
674 |
return 0; |
675 |
} |
676 |
|
677 |
static int |
678 |
fatfs_truncate(vnode_t vp, off_t length) |
679 |
{ |
680 |
struct fatfsmount *fmp;
|
681 |
struct fatfs_node *np;
|
682 |
struct fat_dirent *de;
|
683 |
int error;
|
684 |
|
685 |
fmp = vp->v_mount->m_data; |
686 |
mutex_lock(&fmp->lock); |
687 |
|
688 |
np = vp->v_data; |
689 |
de = &np->dirent; |
690 |
|
691 |
if (length == 0) { |
692 |
/* Remove clusters */
|
693 |
error = fat_free_clusters(fmp, de->cluster); |
694 |
if (error)
|
695 |
goto out;
|
696 |
} else if (length > vp->v_size) { |
697 |
error = fat_expand_file(fmp, vp->v_blkno, length); |
698 |
if (error) {
|
699 |
error = EIO; |
700 |
goto out;
|
701 |
} |
702 |
} |
703 |
|
704 |
/* Update directory entry */
|
705 |
de->size = length; |
706 |
error = fatfs_put_node(fmp, np); |
707 |
if (error)
|
708 |
goto out;
|
709 |
vp->v_size = length; |
710 |
out:
|
711 |
mutex_unlock(&fmp->lock); |
712 |
return error;
|
713 |
} |
714 |
|
715 |
int
|
716 |
fatfs_init(void)
|
717 |
{ |
718 |
return 0; |
719 |
} |