Merge from vendor branch OPENSSH:
[dragonfly.git] / sys / vfs / udf / udf_vnops.c
1 /*-
2  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/fs/udf/udf_vnops.c,v 1.33 2003/12/07 05:04:49 scottl Exp $
27  * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.7 2004/08/28 19:02:29 dillon Exp $
28  */
29
30 /* udf_vnops.c */
31 /* Take care of the vnode side of things */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/namei.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/stat.h>
39 #include <sys/module.h>
40 #include <sys/buf.h>
41 #include <sys/iconv.h>
42 #include <sys/mount.h>
43 #include <sys/vnode.h>
44 #include <sys/dirent.h>
45 #include <sys/queue.h>
46 #include <sys/unistd.h>
47
48 #include <vfs/udf/ecma167-udf.h>
49 #include <vfs/udf/osta.h>
50 #include <vfs/udf/udf.h>
51 #include <vfs/udf/udf_mount.h>
52
53 static int udf_access(struct vop_access_args *);
54 static int udf_getattr(struct vop_getattr_args *);
55 static int udf_ioctl(struct vop_ioctl_args *);
56 static int udf_pathconf(struct vop_pathconf_args *);
57 static int udf_read(struct vop_read_args *);
58 static int udf_readdir(struct vop_readdir_args *);
59 static int udf_readlink(struct vop_readlink_args *ap);
60 static int udf_strategy(struct vop_strategy_args *);
61 static int udf_bmap(struct vop_bmap_args *);
62 static int udf_lookup(struct vop_cachedlookup_args *);
63 static int udf_reclaim(struct vop_reclaim_args *);
64 static int udf_readatoffset(struct udf_node *, int *, int, struct buf **, uint8_t **);
65 static int udf_bmap_internal(struct udf_node *, uint32_t, daddr_t *, uint32_t *);
66
67 struct vnodeopv_entry_desc udf_vnodeop_entries[] = {
68         { &vop_default_desc,            vop_defaultop },
69         { &vop_access_desc,             (void *) udf_access },
70         { &vop_bmap_desc,               (void *) udf_bmap },
71         { &vop_cachedlookup_desc,       (void *) udf_lookup },
72         { &vop_getattr_desc,            (void *) udf_getattr },
73         { &vop_ioctl_desc,              (void *) udf_ioctl },
74         { &vop_lookup_desc,             (void *) vfs_cache_lookup },
75         { &vop_pathconf_desc,           (void *) udf_pathconf },
76         { &vop_read_desc,               (void *) udf_read },
77         { &vop_readdir_desc,            (void *) udf_readdir },
78         { &vop_readlink_desc,           (void *) udf_readlink },
79         { &vop_reclaim_desc,            (void *) udf_reclaim },
80         { &vop_strategy_desc,           (void *) udf_strategy },
81         { NULL, NULL }
82 };
83
84 MALLOC_DEFINE(M_UDFFID, "UDF FID", "UDF FileId structure");
85 MALLOC_DEFINE(M_UDFDS, "UDF DS", "UDF Dirstream structure");
86
87 #define UDF_INVALID_BMAP        -1
88
89 /* Look up a udf_node based on the ino_t passed in and return it's vnode */
90 int
91 udf_hashlookup(struct udf_mnt *udfmp, ino_t id, struct vnode **vpp)
92 {
93         struct udf_node *node;
94         struct udf_hash_lh *lh;
95         int error;
96         lwkt_tokref vlock, hashlock;
97
98         *vpp = NULL;
99
100         lwkt_gettoken(&hashlock, &udfmp->hash_token);
101 loop:
102         lh = &udfmp->hashtbl[id % udfmp->hashsz];
103         if (lh == NULL)
104                 return(ENOENT);
105         LIST_FOREACH(node, lh, le) {
106                 if (node->hash_id != id)
107                         continue;
108                 lwkt_gettoken(&vlock, node->i_vnode->v_interlock);
109                 /*
110                  * We must check to see if the inode has been ripped
111                  * out from under us after blocking.
112                  */
113                 lh = &udfmp->hashtbl[id % udfmp->hashsz];
114                 LIST_FOREACH(node, lh, le) {
115                         if (node->hash_id == id)
116                                 break;
117                 }
118                 if (node == NULL) {
119                         lwkt_reltoken(&vlock);
120                         goto loop;
121                 }
122                 error = vget(node->i_vnode, &vlock, LK_EXCLUSIVE | LK_INTERLOCK,
123                              curthread);
124                 if (error == ENOENT)
125                         goto loop;
126                 lwkt_reltoken(&hashlock);
127                 if (error)
128                         return(error);
129                 *vpp = node->i_vnode;
130                 return(0);
131         }
132
133         lwkt_reltoken(&hashlock);
134         return(0);
135 }
136
137 int
138 udf_hashins(struct udf_node *node)
139 {
140         struct udf_mnt *udfmp;
141         struct udf_hash_lh *lh;
142         lwkt_tokref hashlock;
143
144         udfmp = node->udfmp;
145
146         vn_lock(node->i_vnode, NULL, LK_EXCLUSIVE | LK_RETRY, curthread);
147         lwkt_gettoken(&hashlock, &udfmp->hash_token);
148         lh = &udfmp->hashtbl[node->hash_id % udfmp->hashsz];
149         if (lh == NULL)
150                 LIST_INIT(lh);
151         LIST_INSERT_HEAD(lh, node, le);
152         lwkt_reltoken(&hashlock);
153
154         return(0);
155 }
156
157 int
158 udf_hashrem(struct udf_node *node)
159 {
160         struct udf_mnt *udfmp;
161         struct udf_hash_lh *lh;
162         lwkt_tokref hashlock;
163
164         udfmp = node->udfmp;
165
166         lwkt_gettoken(&hashlock, &udfmp->hash_token);
167         lh = &udfmp->hashtbl[node->hash_id % udfmp->hashsz];
168         if (lh == NULL)
169                 panic("hash entry is NULL, node->hash_id= %d\n", node->hash_id);
170         LIST_REMOVE(node, le);
171         lwkt_reltoken(&hashlock);
172
173         return(0);
174 }
175
176 int
177 udf_allocv(struct mount *mp, struct vnode **vpp)
178 {
179         int error;
180         struct vnode *vp;
181
182         error = getnewvnode(VT_UDF, mp, mp->mnt_vn_ops, &vp, 0, 0);
183         if (error) {
184                 printf("udf_allocv: failed to allocate new vnode\n");
185                 return(error);
186         }
187
188         *vpp = vp;
189         return(0);
190 }
191
192 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
193 static mode_t
194 udf_permtomode(struct udf_node *node)
195 {
196         uint32_t perm;
197         uint32_t flags;
198         mode_t mode;
199
200         perm = node->fentry->perm;
201         flags = node->fentry->icbtag.flags;
202
203         mode = perm & UDF_FENTRY_PERM_USER_MASK;
204         mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2);
205         mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
206         mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4);
207         mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6);
208         mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8);
209
210         return(mode);
211 }
212
213 static int
214 udf_access(struct vop_access_args *a)
215 {
216         struct vnode *vp;
217         struct udf_node *node;
218         mode_t a_mode, mode, mask;
219         struct ucred *cred = a->a_cred;
220         gid_t *gp;
221         int i;
222
223         vp = a->a_vp;
224         node = VTON(vp);
225         a_mode = a->a_mode;
226
227         if (a_mode & VWRITE) {
228                 switch (vp->v_type) {
229                 case VDIR:
230                 case VLNK:
231                 case VREG:
232                         return(EROFS);
233                         /* NOT REACHED */
234                 default:
235                         break;
236                 }
237         }
238
239         mode = udf_permtomode(node);
240
241         if (cred->cr_uid == 0)
242                 return(0);
243
244         mask = 0;
245
246         /* Otherwise, check the owner. */
247         if (cred->cr_uid == node->fentry->uid) {
248                 if (a_mode & VEXEC)
249                         mask |= S_IXUSR;
250                 if (a_mode & VREAD)
251                         mask |= S_IRUSR;
252                 if (a_mode & VWRITE)
253                         mask |= S_IWUSR;
254                 return((mode & mask) == mask ? 0 : EACCES);
255         }
256
257         /* Otherwise, check the groups. */
258         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
259                 if (node->fentry->gid == *gp) {
260                         if (a_mode & VEXEC)
261                                 mask |= S_IXGRP;
262                         if (a_mode & VREAD)
263                                 mask |= S_IRGRP;
264                         if (a_mode & VWRITE)
265                                 mask |= S_IWGRP;
266                         return((mode & mask) == mask ? 0 : EACCES);
267                 }
268
269         /* Otherwise, check everyone else. */
270         if (a_mode & VEXEC)
271                 mask |= S_IXOTH;
272         if (a_mode & VREAD)
273                 mask |= S_IROTH;
274         if (a_mode & VWRITE)
275                 mask |= S_IWOTH;
276         return((mode & mask) == mask ? 0 : EACCES);
277 }
278
279 static int mon_lens[2][12] = {
280         {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
281         {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
282 };
283
284 static int
285 udf_isaleapyear(int year)
286 {
287         int i;
288
289         i = (year % 4) ? 0 : 1;
290         i &= (year % 100) ? 1 : 0;
291         i |= (year % 400) ? 0 : 1;
292
293         return(i);
294 }
295
296 /*
297  * XXX This is just a rough hack.  Daylight savings isn't calculated and tv_nsec
298  * is ignored.
299  * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
300  */
301 static void
302 udf_timetotimespec(struct timestamp *time, struct timespec *t)
303 {
304         int i, lpyear, daysinyear;
305         union {
306                 uint16_t        u_tz_offset;
307                 int16_t         s_tz_offset;
308         } tz;
309
310         t->tv_nsec = 0;
311
312         /* DirectCD seems to like using bogus year values */
313         if (time->year < 1970) {
314                 t->tv_sec = 0;
315                 return;
316         }
317
318         /* Calculate the time and day */
319         t->tv_sec = time->second;
320         t->tv_sec += time->minute * 60;
321         t->tv_sec += time->hour * 3600;
322         t->tv_sec += time->day * 3600 * 24;
323
324         /* Calclulate the month */
325         lpyear = udf_isaleapyear(time->year);
326         for (i = 1; i < time->month; i++)
327                 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24;
328
329         /* Speed up the calculation */
330         if (time->year > 1979)
331                 t->tv_sec += 315532800;
332         if (time->year > 1989)
333                 t->tv_sec += 315619200;
334         if (time->year > 1999)
335                 t->tv_sec += 315532800;
336         for (i = 2000; i < time->year; i++) {
337                 daysinyear = udf_isaleapyear(i) + 365 ;
338                 t->tv_sec += daysinyear * 3600 * 24;
339         }
340
341         /*
342          * Calculate the time zone.  The timezone is 12 bit signed 2's
343          * compliment, so we gotta do some extra magic to handle it right.
344          */
345         tz.u_tz_offset = time->type_tz;
346         tz.u_tz_offset &= 0x0fff;
347         if (tz.u_tz_offset & 0x0800)
348                 tz.u_tz_offset |= 0xf000;       /* extend the sign to 16 bits */
349         if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047))
350                 t->tv_sec -= tz.s_tz_offset * 60;
351
352         return;
353 }
354
355 static int
356 udf_getattr(struct vop_getattr_args *a)
357 {
358         struct vnode *vp;
359         struct udf_node *node;
360         struct vattr *vap;
361         struct file_entry *fentry;
362         struct timespec ts;
363
364         ts.tv_sec = 0;
365
366         vp = a->a_vp;
367         vap = a->a_vap;
368         node = VTON(vp);
369         fentry = node->fentry;
370
371         vap->va_fsid = dev2udev(node->i_dev);
372         vap->va_fileid = node->hash_id;
373         vap->va_mode = udf_permtomode(node);
374         vap->va_nlink = fentry->link_cnt;
375         /*
376          * XXX The spec says that -1 is valid for uid/gid and indicates an
377          * invalid uid/gid.  How should this be represented?
378          */
379         vap->va_uid = (fentry->uid == 0xffffffff) ? 0 : fentry->uid;
380         vap->va_gid = (fentry->gid == 0xffffffff) ? 0 : fentry->gid;
381         udf_timetotimespec(&fentry->atime, &vap->va_atime);
382         udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
383         vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */
384         vap->va_rdev = 0; /* XXX */
385         if (vp->v_type & VDIR) {
386                 /*
387                  * Directories that are recorded within their ICB will show
388                  * as having 0 blocks recorded.  Since tradition dictates
389                  * that directories consume at least one logical block,
390                  * make it appear so.
391                  */
392                 if (fentry->logblks_rec != 0)
393                         vap->va_size = fentry->logblks_rec * node->udfmp->bsize;
394                 else
395                         vap->va_size = node->udfmp->bsize;
396         } else
397                 vap->va_size = fentry->inf_len;
398         vap->va_flags = 0;
399         vap->va_gen = 1;
400         vap->va_blocksize = node->udfmp->bsize;
401         vap->va_bytes = fentry->inf_len;
402         vap->va_type = vp->v_type;
403         vap->va_filerev = 0; /* XXX */
404         return(0);
405 }
406
407 /*
408  * File specific ioctls.  DeCSS candidate?
409  */
410 static int
411 udf_ioctl(struct vop_ioctl_args *a)
412 {
413         printf("%s called\n", __FUNCTION__);
414         return(ENOTTY);
415 }
416
417 /*
418  * I'm not sure that this has much value in a read-only filesystem, but
419  * cd9660 has it too.
420  */
421 static int
422 udf_pathconf(struct vop_pathconf_args *a)
423 {
424
425         switch (a->a_name) {
426         case _PC_LINK_MAX:
427                 *a->a_retval = 65535;
428                 return(0);
429         case _PC_NAME_MAX:
430                 *a->a_retval = NAME_MAX;
431                 return(0);
432         case _PC_PATH_MAX:
433                 *a->a_retval = PATH_MAX;
434                 return(0);
435         case _PC_NO_TRUNC:
436                 *a->a_retval = 1;
437                 return(0);
438         default:
439                 return(EINVAL);
440         }
441 }
442
443 static int
444 udf_read(struct vop_read_args *a)
445 {
446         struct vnode *vp = a->a_vp;
447         struct uio *uio = a->a_uio;
448         struct udf_node *node = VTON(vp);
449         struct buf *bp;
450         uint8_t *data;
451         int error = 0;
452         int size, fsize, offset;
453
454         if (uio->uio_offset < 0)
455                 return(EINVAL);
456
457         fsize = node->fentry->inf_len;
458
459         while (uio->uio_offset < fsize && uio->uio_resid > 0) {
460                 offset = uio->uio_offset;
461                 size = uio->uio_resid;
462                 error = udf_readatoffset(node, &size, offset, &bp, &data);
463                 if (error == 0)
464                         error = uiomove(data, size, uio);
465                 if (bp != NULL)
466                         brelse(bp);
467                 if (error)
468                         break;
469         }
470
471         return(error);
472 }
473
474 /*
475  * Call the OSTA routines to translate the name from a CS0 dstring to a
476  * 16-bit Unicode String.  Hooks need to be placed in here to translate from
477  * Unicode to the encoding that the kernel/user expects.  Return the length
478  * of the translated string.
479  */
480 static int
481 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp)
482 {
483         unicode_t *transname;
484         int i, unilen = 0, destlen;
485
486         /* Convert 16-bit Unicode to destname */
487         /* allocate a buffer big enough to hold an 8->16 bit expansion */
488         transname = malloc(MAXNAMLEN * sizeof(unicode_t), M_TEMP, M_WAITOK | M_ZERO);
489
490         if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) {
491                 printf("udf: Unicode translation failed\n");
492                 free(transname, M_TEMP);
493                 return(0);
494         }
495
496         for (i = 0; i < unilen ; i++)
497                 if (transname[i] & 0xff00)
498                         destname[i] = '.';      /* Fudge the 16bit chars */
499                 else
500                         destname[i] = transname[i] & 0xff;
501         free(transname, M_TEMP);
502         destname[unilen] = 0;
503         destlen = unilen;
504
505         return(destlen);
506 }
507
508 /*
509  * Compare a CS0 dstring with a name passed in from the VFS layer.  Return
510  * 0 on a successful match, nonzero therwise.  Unicode work may need to be done
511  * here also.
512  */
513 static int
514 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp)
515 {
516         char *transname;
517         int error = 0;
518
519         /* This is overkill, but not worth creating a new zone */
520         
521         transname = malloc(MAXNAMLEN * sizeof(unicode_t), M_TEMP,
522                            M_WAITOK | M_ZERO);
523
524         cs0len = udf_transname(cs0string, transname, cs0len, udfmp);
525
526         /* Easy check.  If they aren't the same length, they aren't equal */
527         if ((cs0len == 0) || (cs0len != cmplen))
528                 error = -1;
529         else
530                 error = bcmp(transname, cmpname, cmplen);
531
532         free(transname, M_TEMP);
533         return(error);
534 }
535
536 struct udf_uiodir {
537         struct dirent *dirent;
538         u_long *cookies;
539         int ncookies;
540         int acookies;
541         int eofflag;
542 };
543
544 static int
545 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie)
546 {
547         if (uiodir->cookies != NULL) {
548                 if (++uiodir->acookies > uiodir->ncookies) {
549                         uiodir->eofflag = 0;
550                         return (-1);
551                 }
552                 *uiodir->cookies++ = cookie;
553         }
554
555         if (uio->uio_resid < de_size) {
556                 uiodir->eofflag = 0;
557                 return(-1);
558         }
559
560         return(uiomove((caddr_t)uiodir->dirent, de_size, uio));
561 }
562
563 static struct udf_dirstream *
564 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp)
565 {
566         struct udf_dirstream *ds;
567
568         ds = malloc(sizeof(*ds), M_UDFDS, M_WAITOK | M_ZERO);
569
570         ds->node = node;
571         ds->offset = offset;
572         ds->udfmp = udfmp;
573         ds->fsize = fsize;
574
575         return(ds);
576 }
577
578 static struct fileid_desc *
579 udf_getfid(struct udf_dirstream *ds)
580 {
581         struct fileid_desc *fid;
582         int error, frag_size = 0, total_fid_size;
583
584         /* End of directory? */
585         if (ds->offset + ds->off >= ds->fsize) {
586                 ds->error = 0;
587                 return(NULL);
588         }
589
590         /* Grab the first extent of the directory */
591         if (ds->off == 0) {
592                 ds->size = 0;
593                 if (ds->bp != NULL)
594                         brelse(ds->bp);
595                 error = udf_readatoffset(ds->node, &ds->size, ds->offset,
596                     &ds->bp, &ds->data);
597                 if (error) {
598                         ds->error = error;
599                         return(NULL);
600                 }
601         }
602
603         /*
604          * Clean up from a previous fragmented FID.
605          * XXX Is this the right place for this?
606          */
607         if (ds->fid_fragment && ds->buf != NULL) {
608                 ds->fid_fragment = 0;
609                 free(ds->buf, M_UDFFID);
610         }
611
612         fid = (struct fileid_desc*)&ds->data[ds->off];
613
614         /*
615          * Check to see if the fid is fragmented. The first test
616          * ensures that we don't wander off the end of the buffer
617          * looking for the l_iu and l_fi fields.
618          */
619         if (ds->off + UDF_FID_SIZE > ds->size ||
620             ds->off + fid->l_iu + fid->l_fi + UDF_FID_SIZE > ds->size) {
621
622                 /* Copy what we have of the fid into a buffer */
623                 frag_size = ds->size - ds->off;
624                 if (frag_size >= ds->udfmp->bsize) {
625                         printf("udf: invalid FID fragment\n");
626                         ds->error = EINVAL;
627                         return(NULL);
628                 }
629
630                 /*
631                  * File ID descriptors can only be at most one
632                  * logical sector in size.
633                  */
634                 ds->buf = malloc(ds->udfmp->bsize, M_UDFFID, M_WAITOK | M_ZERO);
635                 bcopy(fid, ds->buf, frag_size);
636
637                 /* Reduce all of the casting magic */
638                 fid = (struct fileid_desc*)ds->buf;
639
640                 if (ds->bp != NULL)
641                         brelse(ds->bp);
642
643                 /* Fetch the next allocation */
644                 ds->offset += ds->size;
645                 ds->size = 0;
646                 error = udf_readatoffset(ds->node, &ds->size, ds->offset,
647                     &ds->bp, &ds->data);
648                 if (error) {
649                         ds->error = error;
650                         return(NULL);
651                 }
652
653                 /*
654                  * If the fragment was so small that we didn't get
655                  * the l_iu and l_fi fields, copy those in.
656                  */
657                 if (frag_size < UDF_FID_SIZE)
658                         bcopy(ds->data, &ds->buf[frag_size],
659                             UDF_FID_SIZE - frag_size);
660
661                 /*
662                  * Now that we have enough of the fid to work with,
663                  * copy in the rest of the fid from the new
664                  * allocation.
665                  */
666                 total_fid_size = UDF_FID_SIZE + fid->l_iu + fid->l_fi;
667                 if (total_fid_size > ds->udfmp->bsize) {
668                         printf("udf: invalid FID\n");
669                         ds->error = EIO;
670                         return(NULL);
671                 }
672                 bcopy(ds->data, &ds->buf[frag_size],
673                     total_fid_size - frag_size);
674
675                 ds->fid_fragment = 1;
676         } else
677                 total_fid_size = fid->l_iu + fid->l_fi + UDF_FID_SIZE;
678
679         /*
680          * Update the offset. Align on a 4 byte boundary because the
681          * UDF spec says so.
682          */
683         ds->this_off = ds->off;
684         if (!ds->fid_fragment)
685                 ds->off += (total_fid_size + 3) & ~0x03;
686         else
687                 ds->off = (total_fid_size - frag_size + 3) & ~0x03;
688
689         return(fid);
690 }
691
692 static void
693 udf_closedir(struct udf_dirstream *ds)
694 {
695
696         if (ds->bp != NULL)
697                 brelse(ds->bp);
698
699         if (ds->fid_fragment && ds->buf != NULL)
700                 free(ds->buf, M_UDFFID);
701
702         free(ds, M_UDFDS);
703 }
704
705 static int
706 udf_readdir(struct vop_readdir_args *a)
707 {
708         struct vnode *vp;
709         struct uio *uio;
710         struct dirent dir;
711         struct udf_node *node;
712         struct udf_mnt *udfmp;
713         struct fileid_desc *fid;
714         struct udf_uiodir uiodir;
715         struct udf_dirstream *ds;
716         u_long *cookies = NULL;
717         int ncookies;
718         int error = 0;
719
720         vp = a->a_vp;
721         uio = a->a_uio;
722         node = VTON(vp);
723         udfmp = node->udfmp;
724         uiodir.eofflag = 1;
725
726         if (a->a_ncookies != NULL) {
727                 /*
728                  * Guess how many entries are needed.  If we run out, this
729                  * function will be called again and thing will pick up were
730                  * it left off.
731                  */
732                 ncookies = uio->uio_resid / 8;
733                 cookies = malloc(sizeof(u_long) * ncookies, M_TEMP, M_WAITOK);
734                 uiodir.ncookies = ncookies;
735                 uiodir.cookies = cookies;
736                 uiodir.acookies = 0;
737         } else
738                 uiodir.cookies = NULL;
739
740         /*
741          * Iterate through the file id descriptors.  Give the parent dir
742          * entry special attention.
743          */
744         ds = udf_opendir(node, uio->uio_offset, node->fentry->inf_len,
745                          node->udfmp);
746
747         while ((fid = udf_getfid(ds)) != NULL) {
748
749                 /* XXX Should we return an error on a bad fid? */
750                 if (udf_checktag(&fid->tag, TAGID_FID)) {
751                         printf("Invalid FID tag\n");
752                         error = EIO;
753                         break;
754                 }
755
756                 /* Is this a deleted file? */
757                 if (fid->file_char & UDF_FILE_CHAR_DEL)
758                         continue;
759
760                 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
761                         /* Do up the '.' and '..' entries.  Dummy values are
762                          * used for the cookies since the offset here is
763                          * usually zero, and NFS doesn't like that value
764                          */
765                         dir.d_fileno = node->hash_id;
766                         dir.d_type = DT_DIR;
767                         dir.d_name[0] = '.';
768                         dir.d_namlen = 1;
769                         dir.d_reclen = GENERIC_DIRSIZ(&dir);
770                         uiodir.dirent = &dir;
771                         error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
772                         if (error)
773                                 break;
774
775                         dir.d_fileno = udf_getid(&fid->icb);
776                         dir.d_type = DT_DIR;
777                         dir.d_name[0] = '.';
778                         dir.d_name[1] = '.';
779                         dir.d_namlen = 2;
780                         dir.d_reclen = GENERIC_DIRSIZ(&dir);
781                         uiodir.dirent = &dir;
782                         error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
783                 } else {
784                         dir.d_namlen = udf_transname(&fid->data[fid->l_iu],
785                             &dir.d_name[0], fid->l_fi, udfmp);
786                         dir.d_fileno = udf_getid(&fid->icb);
787                         dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
788                             DT_DIR : DT_UNKNOWN;
789                         dir.d_reclen = GENERIC_DIRSIZ(&dir);
790                         uiodir.dirent = &dir;
791                         error = udf_uiodir(&uiodir, dir.d_reclen, uio,
792                             ds->this_off);
793                 }
794                 if (error) {
795                         printf("uiomove returned %d\n", error);
796                         break;
797                 }
798
799         }
800
801         /* tell the calling layer whether we need to be called again */
802         *a->a_eofflag = uiodir.eofflag;
803         uio->uio_offset = ds->offset + ds->off;
804
805         if (!error)
806                 error = ds->error;
807
808         udf_closedir(ds);
809
810         if (a->a_ncookies != NULL) {
811                 if (error)
812                         free(cookies, M_TEMP);
813                 else {
814                         *a->a_ncookies = uiodir.acookies;
815                         *a->a_cookies = cookies;
816                 }
817         }
818
819         return(error);
820 }
821
822 /* Are there any implementations out there that do soft-links? */
823 static int
824 udf_readlink(struct vop_readlink_args *ap)
825 {
826         printf("%s called\n", __FUNCTION__);
827         return(EOPNOTSUPP);
828 }
829
830 static int
831 udf_strategy(struct vop_strategy_args *a)
832 {
833         struct buf *bp;
834         struct vnode *vp;
835         struct udf_node *node;
836         int maxsize;
837
838         bp = a->a_bp;
839         vp = bp->b_vp;
840         node = VTON(vp);
841
842         KASSERT(a->a_vp == a->a_bp->b_vp, ("%s(%p != %p)",
843                 __func__, a->a_vp, a->a_bp->b_vp));
844         /* cd9660 has this test reversed, but it seems more logical this way */
845         if (bp->b_blkno != bp->b_lblkno) {
846                 /*
847                  * Files that are embedded in the fentry don't translate well
848                  * to a block number.  Reject.
849                  */
850                 if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize,
851                     &bp->b_lblkno, &maxsize)) {
852                         clrbuf(bp);
853                         bp->b_blkno = -1;
854                 }
855         }
856         if ((long)bp->b_blkno == -1) {
857                 biodone(bp);
858                 return(0);
859         }
860         vp = node->i_devvp;
861         bp->b_dev = vp->v_rdev;
862         bp->b_offset = dbtob(bp->b_blkno);
863         VOP_STRATEGY(vp, bp);
864         return(0);
865 }
866
867 static int
868 udf_bmap(struct vop_bmap_args *a)
869 {
870         struct udf_node *node;
871         uint32_t max_size;
872         daddr_t lsector;
873         int error;
874
875         node = VTON(a->a_vp);
876
877         if (a->a_vpp != NULL)
878                 *a->a_vpp = node->i_devvp;
879         if (a->a_bnp == NULL)
880                 return(0);
881         if (a->a_runb)
882                 *a->a_runb = 0;
883
884         error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector,
885                                   &max_size);
886         if (error)
887                 return(error);
888
889         /* Translate logical to physical sector number */
890         *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT);
891
892         /* Punt on read-ahead for now */
893         if (a->a_runp)
894                 *a->a_runp = 0;
895
896         return(0);
897 }
898
899 /*
900  * The all powerful VOP_LOOKUP().
901  */
902 static int
903 udf_lookup(struct vop_cachedlookup_args *a)
904 {
905         struct vnode *dvp;
906         struct vnode *tdp = NULL;
907         struct vnode **vpp = a->a_vpp;
908         struct udf_node *node;
909         struct udf_mnt *udfmp;
910         struct fileid_desc *fid = NULL;
911         struct udf_dirstream *ds;
912         struct thread *td;
913         globaldata_t gd = mycpu;
914         u_long nameiop;
915         u_long flags;
916         char *nameptr;
917         long namelen;
918         ino_t id = 0;
919         int offset, error = 0;
920         int numdirpasses, fsize;
921
922         dvp = a->a_dvp;
923         node = VTON(dvp);
924         udfmp = node->udfmp;
925         nameiop = a->a_cnp->cn_nameiop;
926         flags = a->a_cnp->cn_flags;
927         nameptr = a->a_cnp->cn_nameptr;
928         namelen = a->a_cnp->cn_namelen;
929         fsize = node->fentry->inf_len;
930         td = a->a_cnp->cn_td;
931
932         /*
933          * If this is a LOOKUP and we've already partially searched through
934          * the directory, pick up where we left off and flag that the
935          * directory may need to be searched twice.  For a full description,
936          * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
937          */
938         if (nameiop != NAMEI_LOOKUP || node->diroff == 0 ||
939             node->diroff > fsize) {
940                 offset = 0;
941                 numdirpasses = 1;
942         } else {
943                 offset = node->diroff;
944                 numdirpasses = 2;
945                 gd->gd_nchstats->ncs_2passes++;
946         }
947
948 lookloop:
949         ds = udf_opendir(node, offset, fsize, udfmp);
950
951         while ((fid = udf_getfid(ds)) != NULL) {
952                 /* XXX Should we return an error on a bad fid? */
953                 if (udf_checktag(&fid->tag, TAGID_FID)) {
954                         printf("udf_lookup: Invalid tag\n");
955                         error = EIO;
956                         break;
957                 }
958
959                 /* Is this a deleted file? */
960                 if (fid->file_char & UDF_FILE_CHAR_DEL)
961                         continue;
962
963                 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
964                         if (flags & CNP_ISDOTDOT) {
965                                 id = udf_getid(&fid->icb);
966                                 break;
967                         }
968                 } else {
969                         if (!(udf_cmpname(&fid->data[fid->l_iu],
970                                           nameptr, fid->l_fi, namelen, udfmp))) {
971                                 id = udf_getid(&fid->icb);
972                                 break;
973                         }
974                 }
975         }
976
977         if (!error)
978                 error = ds->error;
979
980         /* XXX Bail out here? */
981         if (error) {
982                 udf_closedir(ds);
983                 return (error);
984         }
985
986         /* Did we have a match? */
987         if (id) {
988                 error = udf_vget(udfmp->im_mountp, id, &tdp);
989                 if (!error) {
990                         /*
991                          * Remember where this entry was if it's the final
992                          * component.
993                          */
994                         if ((flags & CNP_ISLASTCN) && nameiop == NAMEI_LOOKUP)
995                                 node->diroff = ds->offset + ds->off;
996                         if (numdirpasses == 2)
997                                 gd->gd_nchstats->ncs_pass2++;
998                         if (!(flags & CNP_LOCKPARENT) || !(flags & CNP_ISLASTCN)) {
999                                 a->a_cnp->cn_flags |= CNP_PDIRUNLOCK;
1000                                 VOP_UNLOCK(dvp, NULL, 0, td);
1001                         }
1002
1003                         *vpp = tdp;
1004
1005                         /* Put this entry in the cache */
1006                         if (flags & CNP_MAKEENTRY)
1007                                 cache_enter(dvp, NCPNULL, *vpp, a->a_cnp);
1008                 }
1009         } else {
1010                 /* Name wasn't found on this pass.  Do another pass? */
1011                 if (numdirpasses == 2) {
1012                         numdirpasses--;
1013                         offset = 0;
1014                         udf_closedir(ds);
1015                         goto lookloop;
1016                 }
1017
1018                 /* Enter name into cache as non-existant */
1019                 if (flags & CNP_MAKEENTRY)
1020                         cache_enter(dvp, NCPNULL, *vpp, a->a_cnp);
1021
1022                 if ((flags & CNP_ISLASTCN) &&
1023                     (nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME)) {
1024                         error = EROFS;
1025                 } else {
1026                         error = ENOENT;
1027                 }
1028         }
1029
1030         udf_closedir(ds);
1031         return(error);
1032 }
1033
1034 static int
1035 udf_reclaim(struct vop_reclaim_args *a)
1036 {
1037         struct vnode *vp;
1038         struct udf_node *unode;
1039
1040         vp = a->a_vp;
1041         unode = VTON(vp);
1042
1043         if (unode != NULL) {
1044                 udf_hashrem(unode);
1045                 if (unode->i_devvp) {
1046                         vrele(unode->i_devvp);
1047                         unode->i_devvp = 0;
1048                 }
1049
1050                 if (unode->fentry != NULL)
1051                         free(unode->fentry, M_UDFFENTRY);
1052                 free(unode, M_UDFNODE);
1053                 vp->v_data = NULL;
1054         }
1055
1056         return(0);
1057 }
1058
1059 /*
1060  * Read the block and then set the data pointer to correspond with the
1061  * offset passed in.  Only read in at most 'size' bytes, and then set 'size'
1062  * to the number of bytes pointed to.  If 'size' is zero, try to read in a
1063  * whole extent.
1064  *
1065  * Note that *bp may be assigned error or not.
1066  *
1067  * XXX 'size' is limited to the logical block size for now due to problems
1068  * with udf_read()
1069  */
1070 static int
1071 udf_readatoffset(struct udf_node *node, int *size, int offset, struct buf **bp,
1072                  uint8_t **data)
1073 {
1074         struct udf_mnt *udfmp;
1075         struct file_entry *fentry = NULL;
1076         struct buf *bp1;
1077         uint32_t max_size;
1078         daddr_t sector;
1079         int error;
1080
1081         udfmp = node->udfmp;
1082
1083         *bp = NULL;
1084         error = udf_bmap_internal(node, offset, &sector, &max_size);
1085         if (error == UDF_INVALID_BMAP) {
1086                 /*
1087                  * This error means that the file *data* is stored in the
1088                  * allocation descriptor field of the file entry.
1089                  */
1090                 fentry = node->fentry;
1091                 *data = &fentry->data[fentry->l_ea];
1092                 *size = fentry->l_ad;
1093                 return(0);
1094         } else if (error != 0) {
1095                 return(error);
1096         }
1097
1098         /* Adjust the size so that it is within range */
1099         if (*size == 0 || *size > max_size)
1100                 *size = max_size;
1101         *size = min(*size, MAXBSIZE);
1102
1103         if ((error = udf_readlblks(udfmp, sector, *size, bp))) {
1104                 printf("warning: udf_readlblks returned error %d\n", error);
1105                 /* note: *bp may be non-NULL */
1106                 return(error);
1107         }
1108
1109         bp1 = *bp;
1110         *data = (uint8_t *)&bp1->b_data[offset % udfmp->bsize];
1111         return(0);
1112 }
1113
1114 /*
1115  * Translate a file offset into a logical block and then into a physical
1116  * block.
1117  */
1118 static int
1119 udf_bmap_internal(struct udf_node *node, uint32_t offset, daddr_t *sector, uint32_t *max_size)
1120 {
1121         struct udf_mnt *udfmp;
1122         struct file_entry *fentry;
1123         void *icb;
1124         struct icb_tag *tag;
1125         uint32_t icblen = 0;
1126         daddr_t lsector;
1127         int ad_offset, ad_num = 0;
1128         int i, p_offset;
1129
1130         udfmp = node->udfmp;
1131         fentry = node->fentry;
1132         tag = &fentry->icbtag;
1133
1134         switch (tag->strat_type) {
1135         case 4:
1136                 break;
1137
1138         case 4096:
1139                 printf("Cannot deal with strategy4096 yet!\n");
1140                 return(ENODEV);
1141
1142         default:
1143                 printf("Unknown strategy type %d\n", tag->strat_type);
1144                 return(ENODEV);
1145         }
1146
1147         switch (tag->flags & 0x7) {
1148         case 0:
1149                 /*
1150                  * The allocation descriptor field is filled with short_ad's.
1151                  * If the offset is beyond the current extent, look for the
1152                  * next extent.
1153                  */
1154                 do {
1155                         offset -= icblen;
1156                         ad_offset = sizeof(struct short_ad) * ad_num;
1157                         if (ad_offset > fentry->l_ad) {
1158                                 printf("File offset out of bounds\n");
1159                                 return(EINVAL);
1160                         }
1161                         icb = GETICB(long_ad, fentry, fentry->l_ea + ad_offset);
1162                         icblen = GETICBLEN(short_ad, icb);
1163                         ad_num++;
1164                 } while(offset >= icblen);
1165
1166                 lsector = (offset  >> udfmp->bshift) +
1167                     ((struct short_ad *)(icb))->pos;
1168
1169                 *max_size = GETICBLEN(short_ad, icb);
1170
1171                 break;
1172         case 1:
1173                 /*
1174                  * The allocation descriptor field is filled with long_ad's
1175                  * If the offset is beyond the current extent, look for the
1176                  * next extent.
1177                  */
1178                 do {
1179                         offset -= icblen;
1180                         ad_offset = sizeof(struct long_ad) * ad_num;
1181                         if (ad_offset > fentry->l_ad) {
1182                                 printf("File offset out of bounds\n");
1183                                 return(EINVAL);
1184                         }
1185                         icb = GETICB(long_ad, fentry, fentry->l_ea + ad_offset);
1186                         icblen = GETICBLEN(long_ad, icb);
1187                         ad_num++;
1188                 } while(offset >= icblen);
1189
1190                 lsector = (offset >> udfmp->bshift) +
1191                     ((struct long_ad *)(icb))->loc.lb_num;
1192
1193                 *max_size = GETICBLEN(long_ad, icb);
1194
1195                 break;
1196         case 3:
1197                 /*
1198                  * This type means that the file *data* is stored in the
1199                  * allocation descriptor field of the file entry.
1200                  */
1201                 *max_size = 0;
1202                 *sector = node->hash_id + udfmp->part_start;
1203
1204                 return(UDF_INVALID_BMAP);
1205         case 2:
1206                 /* DirectCD does not use extended_ad's */
1207         default:
1208                 printf("Unsupported allocation descriptor %d\n",
1209                        tag->flags & 0x7);
1210                 return(ENODEV);
1211         }
1212
1213         *sector = lsector + udfmp->part_start;
1214
1215         /*
1216          * Check the sparing table.  Each entry represents the beginning of
1217          * a packet.
1218          */
1219         if (udfmp->s_table != NULL) {
1220                 for (i = 0; i< udfmp->s_table_entries; i++) {
1221                         p_offset = lsector - udfmp->s_table->entries[i].org;
1222                         if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) {
1223                                 *sector = udfmp->s_table->entries[i].map +
1224                                     p_offset;
1225                                 break;
1226                         }
1227                 }
1228         }
1229
1230         return(0);
1231 }