· 11 years ago · Jul 25, 2015, 10:14 PM
1--- sbin/Makefile 2015-07-04 07:26:20.000000000 -0700
2+++ updates/src/sbin/Makefile 2015-07-04 10:47:16.664406000 -0700
3@@ -49,6 +49,7 @@
4 mount_nfs \
5 mount_nullfs \
6 mount_udf \
7+ mount_udf2 \
8 mount_unionfs \
9 newfs \
10 newfs_msdos \
11
12--- sbin/mount/mount.c 2015-07-04 07:26:15.000000000 -0700
13+++ updates/sbin/mount/mount.c 2015-07-04 08:41:35.000000000 -0700
14@@ -144,7 +144,7 @@
15 unsigned int i;
16 const char *fs[] = {
17 "cd9660", "mfs", "msdosfs", "nfs",
18- "nullfs", "smbfs", "udf", "unionfs",
19+ "nullfs", "smbfs", "udf", "udf2", "unionfs",
20 NULL
21 };
22
23--- sbin/mount_udf2/Makefile 1969-12-31 16:00:00.000000000 -0800
24+++ updates/sbin/mount_udf2/Makefile 2014-11-16 16:27:23.000000000 -0800
25@@ -0,0 +1,23 @@
26+# $FreeBSD: src/sbin/mount_udf/Makefile,v 1.6 2006/07/17 20:53:25 stefanf Exp $
27+
28+PROG= mount_udf2
29+SRCS= mount_udf.c getmntopts.c
30+MAN= mount_udf2.8
31+DPADD= ${LIBKICONV}
32+LDADD= -lkiconv
33+
34+#MOUNT= ${.CURDIR}/../mount
35+#CFLAGS+= -I${MOUNT} -I${.CURDIR}/../../sys
36+#.PATH: ${MOUNT}
37+WARNS?= 1
38+
39+# Needs to be dynamically linked for optional dlopen() access to
40+# userland libiconv
41+NO_SHARED?= NO
42+
43+BINDIR=/sbin
44+
45+CFLAGS+=-g
46+CXXFLAGS+=-g
47+
48+.include <bsd.prog.mk>
49
50--- sbin/mount_udf2/getmntopts.c 1969-12-31 16:00:00.000000000 -0800
51+++ updates/sbin/mount_udf2/getmntopts.c 2014-11-16 16:27:23.000000000 -0800
52@@ -0,0 +1,182 @@
53+/*-
54+ * Copyright (c) 1994
55+ * The Regents of the University of California. All rights reserved.
56+ *
57+ * Redistribution and use in source and binary forms, with or without
58+ * modification, are permitted provided that the following conditions
59+ * are met:
60+ * 1. Redistributions of source code must retain the above copyright
61+ * notice, this list of conditions and the following disclaimer.
62+ * 2. Redistributions in binary form must reproduce the above copyright
63+ * notice, this list of conditions and the following disclaimer in the
64+ * documentation and/or other materials provided with the distribution.
65+ * 4. Neither the name of the University nor the names of its contributors
66+ * may be used to endorse or promote products derived from this software
67+ * without specific prior written permission.
68+ *
69+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79+ * SUCH DAMAGE.
80+ */
81+
82+#if 0
83+#ifndef lint
84+static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
85+#endif /* not lint */
86+#endif
87+#include <sys/cdefs.h>
88+__FBSDID("$FreeBSD: src/sbin/mount/getmntopts.c,v 1.19 2008/12/26 22:55:38 obrien Exp $");
89+
90+#include <sys/param.h>
91+#include <sys/mount.h>
92+#include <sys/stat.h>
93+#include <sys/uio.h>
94+
95+#include <err.h>
96+#include <errno.h>
97+#include <stdarg.h>
98+#include <stdio.h>
99+#include <stdlib.h>
100+#include <string.h>
101+#include <sysexits.h>
102+
103+#include "mntopts.h"
104+
105+int getmnt_silent = 0;
106+
107+void
108+getmntopts(const char *options, const struct mntopt *m0, int *flagp,
109+ int *altflagp)
110+{
111+ const struct mntopt *m;
112+ int negative, len;
113+ char *opt, *optbuf, *p;
114+ int *thisflagp;
115+
116+ /* Copy option string, since it is about to be torn asunder... */
117+ if ((optbuf = strdup(options)) == NULL)
118+ err(1, NULL);
119+
120+ for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
121+ /* Check for "no" prefix. */
122+ if (opt[0] == 'n' && opt[1] == 'o') {
123+ negative = 1;
124+ opt += 2;
125+ } else
126+ negative = 0;
127+
128+ /*
129+ * for options with assignments in them (ie. quotas)
130+ * ignore the assignment as it's handled elsewhere
131+ */
132+ p = strchr(opt, '=');
133+ if (p != NULL)
134+ *++p = '\0';
135+
136+ /* Scan option table. */
137+ for (m = m0; m->m_option != NULL; ++m) {
138+ len = strlen(m->m_option);
139+ if (strncasecmp(opt, m->m_option, len) == 0)
140+ if (opt[len] == '\0' || opt[len] == '=')
141+ break;
142+ }
143+
144+ /* Save flag, or fail if option is not recognized. */
145+ if (m->m_option) {
146+ thisflagp = m->m_altloc ? altflagp : flagp;
147+ if (negative == m->m_inverse)
148+ *thisflagp |= m->m_flag;
149+ else
150+ *thisflagp &= ~m->m_flag;
151+ } else if (!getmnt_silent) {
152+ errx(1, "-o %s: option not supported", opt);
153+ }
154+ }
155+
156+ free(optbuf);
157+}
158+
159+void
160+rmslashes(char *rrpin, char *rrpout)
161+{
162+ char *rrpoutstart;
163+
164+ *rrpout = *rrpin;
165+ for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) {
166+
167+ /* skip all double slashes */
168+ while (*rrpin == '/' && *(rrpin + 1) == '/')
169+ rrpin++;
170+ }
171+
172+ /* remove trailing slash if necessary */
173+ if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/')
174+ *(rrpout - 1) = '\0';
175+ else
176+ *rrpout = '\0';
177+}
178+
179+void
180+checkpath(const char *path, char *resolved)
181+{
182+ struct stat sb;
183+
184+ if (realpath(path, resolved) != NULL && stat(resolved, &sb) == 0) {
185+ if (!S_ISDIR(sb.st_mode))
186+ errx(EX_USAGE, "%s: not a directory", resolved);
187+ } else
188+ errx(EX_USAGE, "%s: %s", resolved, strerror(errno));
189+}
190+
191+void
192+build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
193+ size_t len)
194+{
195+ int i;
196+
197+ if (*iovlen < 0)
198+ return;
199+ i = *iovlen;
200+ *iov = realloc(*iov, sizeof **iov * (i + 2));
201+ if (*iov == NULL) {
202+ *iovlen = -1;
203+ return;
204+ }
205+ (*iov)[i].iov_base = strdup(name);
206+ (*iov)[i].iov_len = strlen(name) + 1;
207+ i++;
208+ (*iov)[i].iov_base = val;
209+ if (len == (size_t)-1) {
210+ if (val != NULL)
211+ len = strlen(val) + 1;
212+ else
213+ len = 0;
214+ }
215+ (*iov)[i].iov_len = (int)len;
216+ *iovlen = ++i;
217+}
218+
219+/*
220+ * This function is needed for compatibility with parameters
221+ * which used to use the mount_argf() command for the old mount() syscall.
222+ */
223+void
224+build_iovec_argf(struct iovec **iov, int *iovlen, const char *name,
225+ const char *fmt, ...)
226+{
227+ va_list ap;
228+ char val[255] = { 0 };
229+
230+ va_start(ap, fmt);
231+ vsnprintf(val, sizeof(val), fmt, ap);
232+ va_end(ap);
233+ build_iovec(iov, iovlen, name, strdup(val), (size_t)-1);
234+}
235
236--- sbin/mount_udf2/mntopts.h 1969-12-31 16:00:00.000000000 -0800
237+++ updates/sbin/mount_udf2/mntopts.h 2014-11-16 16:27:23.000000000 -0800
238@@ -0,0 +1,99 @@
239+/*-
240+ * Copyright (c) 1994
241+ * The Regents of the University of California. All rights reserved.
242+ *
243+ * Redistribution and use in source and binary forms, with or without
244+ * modification, are permitted provided that the following conditions
245+ * are met:
246+ * 1. Redistributions of source code must retain the above copyright
247+ * notice, this list of conditions and the following disclaimer.
248+ * 2. Redistributions in binary form must reproduce the above copyright
249+ * notice, this list of conditions and the following disclaimer in the
250+ * documentation and/or other materials provided with the distribution.
251+ * 4. Neither the name of the University nor the names of its contributors
252+ * may be used to endorse or promote products derived from this software
253+ * without specific prior written permission.
254+ *
255+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
256+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
257+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
260+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
264+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265+ * SUCH DAMAGE.
266+ *
267+ * @(#)mntopts.h 8.7 (Berkeley) 3/29/95
268+ * $FreeBSD: src/sbin/mount/mntopts.h,v 1.30 2009/12/21 19:39:10 trasz Exp $
269+ */
270+
271+struct mntopt {
272+ const char *m_option; /* option name */
273+ int m_inverse; /* if a negative option, e.g. "atime" */
274+ int m_flag; /* bit to set, e.g. MNT_RDONLY */
275+ int m_altloc; /* 1 => set bit in altflags */
276+};
277+
278+/* User-visible MNT_ flags. */
279+#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
280+#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0 }
281+#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
282+#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
283+#define MOPT_NOSYMFOLLOW { "symfollow", 1, MNT_NOSYMFOLLOW, 0 }
284+#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
285+#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
286+#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
287+#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
288+#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
289+#define MOPT_NOCLUSTERR { "clusterr", 1, MNT_NOCLUSTERR, 0 }
290+#define MOPT_NOCLUSTERW { "clusterw", 1, MNT_NOCLUSTERW, 0 }
291+#define MOPT_SUIDDIR { "suiddir", 0, MNT_SUIDDIR, 0 }
292+#define MOPT_SNAPSHOT { "snapshot", 0, MNT_SNAPSHOT, 0 }
293+#define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 }
294+#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 }
295+#define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 }
296+
297+/* Control flags. */
298+#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
299+#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
300+#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
301+#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
302+
303+/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
304+#define MOPT_AUTO { "auto", 0, 0, 0 }
305+
306+/* A handy macro as terminator of MNT_ array. */
307+#define MOPT_END { NULL, 0, 0, 0 }
308+
309+#define MOPT_FSTAB_COMPAT \
310+ MOPT_RO, \
311+ MOPT_RW, \
312+ MOPT_AUTO
313+
314+/* Standard options which all mounts can understand. */
315+#define MOPT_STDOPTS \
316+ MOPT_USERQUOTA, \
317+ MOPT_GROUPQUOTA, \
318+ MOPT_FSTAB_COMPAT, \
319+ MOPT_NOATIME, \
320+ MOPT_NOEXEC, \
321+ MOPT_SUIDDIR, /* must be before MOPT_NOSUID */ \
322+ MOPT_NOSUID, \
323+ MOPT_NOSYMFOLLOW, \
324+ MOPT_RDONLY, \
325+ MOPT_UNION, \
326+ MOPT_NOCLUSTERR, \
327+ MOPT_NOCLUSTERW, \
328+ MOPT_MULTILABEL, \
329+ MOPT_ACLS, \
330+ MOPT_NFS4ACLS
331+
332+void getmntopts(const char *, const struct mntopt *, int *, int *);
333+void rmslashes(char *, char *);
334+void checkpath(const char *, char resolved_path[]);
335+extern int getmnt_silent;
336+void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len);
337+void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...);
338
339--- sbin/mount_udf2/mount_udf.c 1969-12-31 16:00:00.000000000 -0800
340+++ updates/sbin/mount_udf2/mount_udf.c 2014-11-16 16:27:23.000000000 -0800
341@@ -0,0 +1,388 @@
342+/*-
343+ * Copyright (c) 1992, 1993, 1994
344+ * The Regents of the University of California. All rights reserved.
345+ * Copyright (c) 2002 Scott Long
346+ * Copyright (c) 2012 Will DeVries
347+ *
348+ * This code is derived from software contributed to Berkeley
349+ * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
350+ * Support code is derived from software contributed to Berkeley
351+ * by Atsushi Murai (amurai@spec.co.jp).
352+ *
353+ * Redistribution and use in source and binary forms, with or without
354+ * modification, are permitted provided that the following conditions
355+ * are met:
356+ * 1. Redistributions of source code must retain the above copyright
357+ * notice, this list of conditions and the following disclaimer.
358+ * 2. Redistributions in binary form must reproduce the above copyright
359+ * notice, this list of conditions and the following disclaimer in the
360+ * documentation and/or other materials provided with the distribution.
361+ * 4. Neither the name of the University nor the names of its contributors
362+ * may be used to endorse or promote products derived from this software
363+ * without specific prior written permission.
364+ *
365+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
366+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
367+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
368+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
369+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
370+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
371+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
372+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
373+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
374+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
375+ * SUCH DAMAGE.
376+ *
377+ * $FreeBSD: src/sbin/mount_udf/mount_udf.c,v 1.13 2005/06/10 09:51:43 delphij Exp $
378+ */
379+
380+/*
381+ * This is just a rip-off of mount_iso9660.c. It's been vastly simplified
382+ * because UDF doesn't take any options at this time.
383+ */
384+
385+#include <sys/cdio.h>
386+#include <sys/file.h>
387+#include <sys/iconv.h>
388+#include <sys/param.h>
389+#include <sys/linker.h>
390+#include <sys/module.h>
391+#include <sys/mount.h>
392+#include <sys/uio.h>
393+#include <sys/endian.h>
394+#include <sys/ioctl.h>
395+#include <sys/udfio.h>
396+#include <sys/types.h>
397+
398+#include <err.h>
399+#include <errno.h>
400+#include <stdlib.h>
401+#include <stdio.h>
402+#include <string.h>
403+#include <sysexits.h>
404+#include <unistd.h>
405+#include <fcntl.h>
406+#include <pwd.h>
407+#include <grp.h>
408+
409+#include "mntopts.h"
410+
411+struct mntopt mopts[] = {
412+ MOPT_STDOPTS,
413+ MOPT_UPDATE,
414+ MOPT_END
415+};
416+
417+static void get_session_info(char *dev, struct udf_session_info *usi,
418+ int session_num);
419+static void print_session_info(char *dev, int session_num);
420+static int set_charset(char *, const char *);
421+static void usage(void);
422+static int get_uid(char *u, uid_t *uid);
423+static int get_gid(char *g, gid_t *gid);
424+static int get_mode(char *m, mode_t *mode);
425+
426+int
427+main(int argc, char **argv)
428+{
429+ struct udf_session_info usi;
430+ struct iovec *iov;
431+ struct passwd *nobody;
432+ long session_num;
433+ gid_t anon_gid, override_gid;
434+ int iovlen, ch, mntflags, opts, sessioninfo;
435+ uid_t anon_uid, override_uid;
436+ mode_t mode, dirmode;
437+ char cs_local[ICONV_CSNMAXLEN];
438+ char *dev, *dir, *endp, mntpath[MAXPATHLEN];
439+ uint8_t use_nobody_gid, use_nobody_uid;
440+ uint8_t use_override_gid, use_override_uid;
441+ uint8_t use_mode, use_dirmode;
442+
443+ cs_local[0] = '\0';
444+ session_num = 0;
445+ sessioninfo = 0;
446+ use_nobody_uid = use_nobody_gid = 1;
447+ use_override_uid = use_override_gid = 0;
448+ use_mode = use_dirmode = 0;
449+ iov = NULL;
450+ iovlen = 0;
451+ mntflags = opts = 0;
452+
453+ while ((ch = getopt(argc, argv, "C:G:g:M:m:o:ps:U:u:")) != -1)
454+ switch (ch) {
455+ case 'C':
456+ set_charset(cs_local, optarg);
457+ break;
458+ case 'G':
459+ if (get_gid(optarg, &anon_gid) == -1)
460+ errx(EX_USAGE, "invalid gid in option G: %s",
461+ optarg);
462+ use_nobody_gid = 0;
463+ break;
464+ case 'g':
465+ if (get_gid(optarg, &override_gid) == -1)
466+ errx(EX_USAGE, "invalid gid in option g: %s",
467+ optarg);
468+ use_override_gid = 1;
469+ break;
470+ case 'M':
471+ if (get_mode(optarg, &dirmode) == -1)
472+ errx(EX_USAGE, "invalid mode in option M: %s",
473+ optarg);
474+ use_dirmode = 1;
475+ break;
476+ case 'm':
477+ if (get_mode(optarg, &mode) == -1)
478+ errx(EX_USAGE, "invalid mode in option m: %s",
479+ optarg);
480+ use_mode = 1;
481+ break;
482+ case 'o':
483+ getmntopts(optarg, mopts, &mntflags, &opts);
484+ break;
485+ case 'p':
486+ sessioninfo = 1;
487+ break;
488+ case 's':
489+ session_num = strtol(optarg, &endp, 10);
490+ if (optarg == endp || *endp != '\0')
491+ errx(EX_USAGE, "invalid number in option s: %s",
492+ optarg);
493+ break;
494+ case 'U':
495+ if (get_uid(optarg, &anon_uid) == -1)
496+ errx(EX_USAGE, "invalid uid in option U: %s",
497+ optarg);
498+ use_nobody_uid = 0;
499+ break;
500+ case 'u':
501+ if (get_uid(optarg, &override_uid) == -1)
502+ errx(EX_USAGE, "invalid uid in option u: %s",
503+ optarg);
504+ use_override_uid = 1;
505+ break;
506+ case '?':
507+ default:
508+ usage();
509+ }
510+ argc -= optind;
511+ argv += optind;
512+
513+ if (sessioninfo == 1) {
514+ if (argc != 1)
515+ usage();
516+ print_session_info(argv[0], session_num);
517+ }
518+
519+ if (argc != 2)
520+ usage();
521+
522+ dev = argv[0];
523+ dir = argv[1];
524+
525+ /*
526+ * Resolve the mountpoint with realpath(3) and remove unnecessary
527+ * slashes from the devicename if there are any.
528+ */
529+ (void)checkpath(dir, mntpath);
530+ (void)rmslashes(dev, dev);
531+
532+ /*
533+ * Get session info from device
534+ */
535+ get_session_info(dev, &usi, session_num);
536+
537+
538+ /*
539+ * Use nobody for uid and gid if not given above.
540+ */
541+ if (use_nobody_gid == 1 && use_override_gid == 0) {
542+ if (get_gid("nobody", &anon_gid) == -1)
543+ errx(EX_USAGE, "There is no group 'nobody'; use the G "
544+ "option to specify a default gid.");
545+ } else if (use_override_gid == 1)
546+ anon_gid = override_gid;
547+
548+ if (use_nobody_uid == 1 && use_override_uid == 0) {
549+ if (get_uid("nobody", &anon_uid) == -1)
550+ errx(EX_USAGE, "There is no user 'nobody'; use the U "
551+ "option to specify a default uid.");
552+ } else if (use_override_uid == 1)
553+ anon_uid = override_uid;
554+
555+ /* UDF file systems are not writeable. */
556+ mntflags |= MNT_RDONLY;
557+
558+ build_iovec(&iov, &iovlen, "fstype", "udf2", (size_t) - 1);
559+ build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t) - 1);
560+ build_iovec(&iov, &iovlen, "from", dev, (size_t) - 1);
561+ build_iovec(&iov, &iovlen, "uid", &anon_uid, sizeof(anon_uid));
562+ if (use_override_uid == 1)
563+ build_iovec(&iov, &iovlen, "override_uid", NULL, 0);
564+ build_iovec(&iov, &iovlen, "gid", &anon_gid, sizeof(anon_gid));
565+ if (use_override_gid == 1)
566+ build_iovec(&iov, &iovlen, "override_gid", NULL, 0);
567+ if (use_mode)
568+ build_iovec(&iov, &iovlen, "mode", &mode, sizeof(mode_t));
569+ if (use_dirmode)
570+ build_iovec(&iov, &iovlen, "dirmode", &dirmode, sizeof(mode_t));
571+
572+ build_iovec(&iov, &iovlen, "first_trackblank",
573+ &usi.session_first_track_blank, sizeof(uint8_t));
574+ build_iovec(&iov, &iovlen, "session_start_addr",
575+ &usi.session_start_addr, sizeof(uint32_t));
576+ build_iovec(&iov, &iovlen, "session_end_addr", &usi.session_end_addr,
577+ sizeof(uint32_t));
578+ build_iovec(&iov, &iovlen, "session_last_written",
579+ &usi.session_last_written, sizeof(uint32_t));
580+
581+ if (cs_local[0] != '\0') {
582+ build_iovec(&iov, &iovlen, "cs_local", cs_local, (size_t) - 1);
583+ }
584+
585+ if (nmount(iov, iovlen, mntflags) < 0)
586+ err(1, "%s", dev);
587+
588+ free(iov);
589+ exit(0);
590+}
591+
592+static int
593+get_uid(char *u, uid_t *uid)
594+{
595+ struct passwd *usr;
596+ char *endp;
597+
598+ usr = getpwnam(u);
599+ if (usr != NULL)
600+ *uid = usr->pw_gid;
601+ else {
602+ *uid = strtoul(u, &endp, 10);
603+
604+ if (u == endp || *endp != '\0')
605+ return (-1);
606+ }
607+
608+ return (0);
609+}
610+
611+static int
612+get_gid(char *g, gid_t *gid)
613+{
614+ struct group *grp;
615+ char *endp;
616+
617+ grp = getgrnam(g);
618+ if (grp != NULL)
619+ *gid = grp->gr_gid;
620+ else {
621+ *gid = strtoul(g, &endp, 10);
622+
623+ if (g == endp || *endp != '\0')
624+ return (-1);
625+ }
626+
627+ return (0);
628+}
629+
630+static int
631+get_mode(char *m, mode_t *mode)
632+{
633+ char *endp;
634+
635+ *mode = strtoul(m, &endp, 8);
636+ if (m == endp || *endp != '\0')
637+ return (-1);
638+ return (0);
639+}
640+
641+static int
642+set_charset(char *cs_local, const char *localcs)
643+{
644+ int error;
645+
646+ if (modfind("udf2_iconv") < 0)
647+ if (kldload("udf2_iconv") < 0 || modfind("udf2_iconv") < 0) {
648+ errx(EX_OSERR, "cannot find or load \"udf2_iconv\" "
649+ "kernel module");
650+ }
651+
652+ strncpy(cs_local, localcs, ICONV_CSNMAXLEN);
653+ error = kiconv_add_xlat16_cspairs(ENCODING_UNICODE, cs_local);
654+ if (error != 0)
655+ err(EX_OSERR, "udf2_iconv");
656+
657+ return (0);
658+}
659+
660+static void
661+get_session_info(char *dev, struct udf_session_info *usi, int session_num)
662+{
663+ int fd, error;
664+ unsigned int out;
665+
666+ fd = open(dev, O_RDONLY, 0);
667+ if (fd < 0)
668+ err(1, "open");
669+
670+ bzero(usi, sizeof(struct udf_session_info));
671+ usi->session_num = session_num;
672+ error = ioctl(fd, UDFIOREADSESSIONINFO, usi);
673+ if (error != 0) {
674+ if (session_num != 0)
675+ errx(EX_USAGE, "Cannot mount selected session. This "
676+ "device does not properly support multi-sessions "
677+ "disc.");
678+
679+ /* Other fatal errors besides EIO and ENXIO may exist, but
680+ trying to mount an invalid device shouldn't result in anything
681+ to bad. */
682+ if (errno == EIO)
683+ errx(EX_IOERR, "Device not ready.");
684+ else if (errno == ENXIO)
685+ errx(EX_IOERR, "No media present.");
686+ else
687+ warnx("Warning, this device does not properly support "
688+ "multi-sessions disc.");
689+
690+ /* We populate the end address inside the kernel. */
691+ usi->session_start_addr = 0;
692+ usi->session_end_addr = 0;
693+ }
694+
695+ close(fd);
696+}
697+
698+static void
699+print_session_info(char *dev, int session_num)
700+{
701+ struct udf_session_info usi;
702+
703+ rmslashes(dev, dev);
704+ get_session_info(dev, &usi, session_num);
705+
706+ printf("Number of Sessions: %u\n", usi.num_sessions);
707+ printf("Number of Tracks: %u\n", usi.num_tracks);
708+ printf("First Track Number: %u\n", usi.first_track);
709+ printf("Sector Size: %u\n", usi.sector_size);
710+
711+ printf("Session Number: %u\n", usi.session_num);
712+ printf("Session Start Address: %u\n", usi.session_start_addr);
713+ printf("Session End Address: %u\n", usi.session_end_addr);
714+ printf("Last Written Address in Session: %u\n", usi.session_last_written);
715+ printf("First Track Number of Session: %u\n", usi.session_first_track);
716+ printf("Last Track of Session: %u\n", usi.session_last_track);
717+
718+ exit(0);
719+}
720+
721+static void
722+usage(void)
723+{
724+
725+ (void)fprintf(stderr, "usage: mount_udf [-v] [-C charset] [-G gid] "
726+ "[-o options] [-s session] [-U uid] special node\n");
727+ (void)fprintf(stderr, "usage: mount_udf [-p] [-s session] special\n");
728+ exit(EX_USAGE);
729+}
730
731--- sbin/mount_udf2/mount_udf2.8 1969-12-31 16:00:00.000000000 -0800
732+++ updates/sbin/mount_udf2/mount_udf2.8 2014-11-16 16:27:23.000000000 -0800
733@@ -0,0 +1,128 @@
734+.\" Copyright (c) 2002
735+.\" Scott Long <scottl@FreeBSD.org>
736+.\" Jeroen Ruigrok van der Werven <asmodai@wxs.nl>
737+.\" All rights reserved.
738+.\"
739+.\" Redistribution and use in source and binary forms, with or without
740+.\" modification, are permitted provided that the following conditions
741+.\" are met:
742+.\" 1. Redistributions of source code must retain the above copyright
743+.\" notice, this list of conditions and the following disclaimer.
744+.\" 2. Redistributions in binary form must reproduce the above copyright
745+.\" notice, this list of conditions and the following disclaimer in the
746+.\" documentation and/or other materials provided with the distribution.
747+.\"
748+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
749+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
750+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
751+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
752+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
753+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
754+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
755+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
756+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
757+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
758+.\" SUCH DAMAGE.
759+.\"
760+.\" $FreeBSD: src/sbin/mount_udf/mount_udf.8,v 1.6 2005/02/10 09:19:31 ru Exp $
761+.\"
762+.Dd January 13, 2013
763+.Dt MOUNT_UDF2 8
764+.Os
765+.Sh NAME
766+.Nm mount_udf2
767+.Nd mount a UDF file system
768+.Sh SYNOPSIS
769+.Nm
770+.Op Fl o Ar options
771+.Op Fl C Ar charset
772+.Op Fl G Ar gid
773+.Op Fl g Ar gid
774+.Op Fl M Ar permissions
775+.Op Fl m Ar permissions
776+.Op Fl s Ar session
777+.Op Fl U Ar uid
778+.Op Fl u Ar uid
779+.Ar special node
780+.Nm
781+.Op Fl p
782+.Op Fl s Ar session
783+.Ar special
784+.Sh DESCRIPTION
785+The
786+.Nm
787+utility attaches the UDF file system residing on the device
788+.Pa special
789+to the global file system namespace at the location indicated by
790+.Ar node .
791+.Pp
792+The options are as follows:
793+.Bl -tag -width indent
794+.It Fl C Ar charset
795+Specify local
796+.Ar charset
797+to convert Unicode file names. By default UTF-8 is used.
798+.It Fl G Ar gid
799+Set the group used for files and directories without defined groups to
800+.Ar gid .
801+By default this is set to the 'nobody' group. (UDF allows for files
802+and directories without groups.)
803+.It Fl g Ar gid
804+Set the group for all files and directories in the file system to
805+.Ar gid .
806+If this option is specified, the
807+.Fl G
808+option has no effect.
809+.It Fl M Ar permissions
810+Set the mode used for all directories in the file system to
811+.Ar permissions .
812+This value should be specified as an octal number according to the rules in
813+chmod(1).
814+.It Fl m Ar permissions
815+Set the mode used for all files in the file system to
816+.Ar permissions .
817+This value should be specified as an octal number according to the rules in
818+chmod(1).
819+.It Fl o
820+Options are specified with a
821+.Fl o
822+flag followed by a comma separated string of options.
823+See the
824+.Xr mount 8
825+man page for possible options and their meanings.
826+.It Fl p
827+Print information about sessions on cd. This option may be used to determine
828+the number of sessions on the disk. Sessions are numbered starting with 1, and
829+by default information will be displayed for the largest non-empty session.
830+.It Fl s Ar session
831+Specify the
832+.Ar session
833+to mount or display information about.
834+This must be a positive integer greater than zero. Valid values may be
835+determined using the
836+.Fl p
837+option.
838+.It Fl U Ar uid
839+Set the user used for files and directories without defined owners to
840+.Ar uid .
841+By default this is set to the user 'nobody'. (UDF allows for files
842+and directories without owners.)
843+.It Fl u Ar uid
844+Set the owner for all files and directories in the file system to
845+.Ar uid .
846+If this option is specified, the
847+.Fl U
848+option has no effect.
849+
850+.El
851+.Sh SEE ALSO
852+.Xr cdcontrol 1 ,
853+.Xr mount 2 ,
854+.Xr unmount 2 ,
855+.Xr fstab 5 ,
856+.Xr mount 8
857+.Sh HISTORY
858+The
859+.Nm
860+utility first appeared in
861+.Fx 5.0 .
862
863--- sys/fs/udf2/ecma167-udf.h 1969-12-31 16:00:00.000000000 -0800
864+++ udpates/sys/fs/udf2/ecma167-udf.h 2014-11-16 16:27:23.000000000 -0800
865@@ -0,0 +1,833 @@
866+/*-
867+ * Copyright (c) 2003, 2004, 2005, 2006, 2008, 2009
868+ * Reinoud Zandijk * <reinoud@NetBSD.org>
869+ * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
870+ * All rights reserved.
871+ *
872+ * Redistribution and use in source and binary forms, with or without
873+ * modification, are permitted provided that the following conditions
874+ * are met:
875+ * 1. Redistributions of source code must retain the above copyright
876+ * notice, this list of conditions and the following disclaimer.
877+ * 2. Redistributions in binary form must reproduce the above copyright
878+ * notice, this list of conditions and the following disclaimer in the
879+ * documentation and/or other materials provided with the distribution.
880+ *
881+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
882+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
883+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
884+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
885+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
886+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
887+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
888+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
889+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
890+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
891+ * SUCH DAMAGE.
892+ *
893+ *
894+ * Extended and adapted for UDFv2.50+ bij Reinoud Zandijk based on the
895+ * origional by Scott Long.
896+ *
897+ * 20030508 Made some small typo and explainatory comments
898+ * 20030510 Added UDF 2.01 structures
899+ * 20030519 Added/correct comments on multi-partitioned logical volume space
900+ * 20050616 Added pseudo overwrite
901+ * 20050624 Added the missing extended attribute types and `magic values'.
902+ * 20051106 Reworked some implementation use parts
903+ *
904+ */
905+
906+
907+#ifndef _FS_UDF_ECMA167_UDF_H_
908+#define _FS_UDF_ECMA167_UDF_H_
909+
910+
911+/*
912+ * in case of an older gcc versions, define the __packed as explicit
913+ * attribute
914+ */
915+
916+/*
917+ * You may specify the `aligned' and `transparent_union' attributes either in
918+ * a `typedef' declaration or just past the closing curly brace of a complete
919+ * enum, struct or union type _definition_ and the `packed' attribute only
920+ * past the closing brace of a definition. You may also specify attributes
921+ * between the enum, struct or union tag and the name of the type rather than
922+ * after the closing brace.
923+*/
924+
925+#ifndef __packed
926+#define __packed __attribute__((packed))
927+#endif
928+
929+
930+/* ecma167-udf.h */
931+
932+/* Volume recognition sequence ECMA 167 rev. 3 16.1 */
933+struct vrs_desc {
934+ uint8_t struct_type;
935+ uint8_t identifier[5];
936+ uint8_t version;
937+ uint8_t data[2041];
938+} __packed;
939+
940+
941+#define VRS_NSR02 "NSR02"
942+#define VRS_NSR03 "NSR03"
943+#define VRS_BEA01 "BEA01"
944+#define VRS_TEA01 "TEA01"
945+#define VRS_CD001 "CD001"
946+#define VRS_CDW02 "CDW02"
947+
948+
949+/* Structure/definitions/constants a la ECMA 167 rev. 3 */
950+
951+
952+#define MAX_TAGID_VOLUMES 9
953+/* Tag identifiers */
954+enum {
955+ TAGID_SPARING_TABLE = 0,
956+ TAGID_PRI_VOL = 1,
957+ TAGID_ANCHOR = 2,
958+ TAGID_VOL = 3,
959+ TAGID_IMP_VOL = 4,
960+ TAGID_PARTITION = 5,
961+ TAGID_LOGVOL = 6,
962+ TAGID_UNALLOC_SPACE = 7,
963+ TAGID_TERM = 8,
964+ TAGID_LOGVOL_INTEGRITY= 9,
965+ TAGID_FSD = 256,
966+ TAGID_FID = 257,
967+ TAGID_ALLOCEXTENT = 258,
968+ TAGID_INDIRECTENTRY = 259,
969+ TAGID_ICB_TERM = 260,
970+ TAGID_FENTRY = 261,
971+ TAGID_EXTATTR_HDR = 262,
972+ TAGID_UNALL_SP_ENTRY = 263,
973+ TAGID_SPACE_BITMAP = 264,
974+ TAGID_PART_INTEGRETY = 265,
975+ TAGID_EXTFENTRY = 266,
976+ TAGID_MAX = 266
977+};
978+
979+
980+enum {
981+ UDF_DOMAIN_FLAG_HARD_WRITE_PROTECT = 1,
982+ UDF_DOMAIN_FLAG_SOFT_WRITE_PROTECT = 2
983+};
984+
985+
986+enum {
987+ UDF_ACCESSTYPE_NOT_SPECIFIED = 0, /* unknown */
988+ UDF_ACCESSTYPE_PSEUDO_OVERWITE = 0, /* Pseudo overwritable, f.e. BD-R's LOW */
989+ UDF_ACCESSTYPE_READ_ONLY = 1, /* really only readable */
990+ UDF_ACCESSTYPE_WRITE_ONCE = 2, /* write once and you're done */
991+ UDF_ACCESSTYPE_REWRITEABLE = 3, /* may need extra work to rewrite */
992+ UDF_ACCESSTYPE_OVERWRITABLE = 4 /* no limits on rewriting; harddisc f.e.*/
993+};
994+
995+
996+/* Descriptor tag [3/7.2] */
997+struct desc_tag {
998+ uint16_t id;
999+ uint16_t descriptor_ver;
1000+ uint8_t cksum;
1001+ uint8_t reserved;
1002+ uint16_t serial_num;
1003+ uint16_t desc_crc;
1004+ uint16_t desc_crc_len;
1005+ uint32_t tag_loc;
1006+} __packed;
1007+#define UDF_DESC_TAG_LENGTH 16
1008+
1009+
1010+/* Recorded Address [4/7.1] */
1011+struct lb_addr { /* within partition space */
1012+ uint32_t lb_num;
1013+ uint16_t part_num;
1014+} __packed;
1015+
1016+
1017+/* Extent Descriptor [3/7.1] */
1018+struct extent_ad {
1019+ uint32_t len;
1020+ uint32_t loc;
1021+} __packed;
1022+
1023+
1024+/* Short Allocation Descriptor [4/14.14.1] */
1025+struct short_ad {
1026+ uint32_t len;
1027+ uint32_t lb_num;
1028+} __packed;
1029+
1030+
1031+/* Long Allocation Descriptor [4/14.14.2] */
1032+struct UDF_ADImp_use {
1033+ uint16_t flags;
1034+ uint32_t unique_id;
1035+} __packed;
1036+#define UDF_ADIMP_FLAGS_EXTENT_ERASED 1
1037+
1038+
1039+struct long_ad {
1040+ uint32_t len;
1041+ struct lb_addr loc; /* within a logical volume mapped partition space !! */
1042+ union {
1043+ uint8_t bytes[6];
1044+ struct UDF_ADImp_use im_used;
1045+ } impl;
1046+} __packed;
1047+#define longad_uniqueid impl.im_used.unique_id
1048+
1049+
1050+/* Extended Allocation Descriptor [4/14.14.3] ; identifies an extent of allocation descriptors ; also in UDF ? */
1051+struct ext_ad {
1052+ uint32_t ex_len;
1053+ uint32_t rec_len;
1054+ uint32_t inf_len;
1055+ struct lb_addr ex_loc;
1056+ uint8_t reserved[2];
1057+} __packed;
1058+
1059+
1060+/* ICB : Information Control Block; positioning */
1061+union icb {
1062+ struct short_ad s_ad;
1063+ struct long_ad l_ad;
1064+ struct ext_ad e_ad;
1065+};
1066+
1067+
1068+/* short/long/ext extent have flags encoded in length */
1069+#define UDF_EXT_ALLOCATED (0<<30)
1070+#define UDF_EXT_FREED (1<<30)
1071+#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1<<30)
1072+#define UDF_EXT_FREE (2<<30)
1073+#define UDF_EXT_REDIRECT (3<<30)
1074+#define UDF_EXT_FLAGS(len) ((len) & (3<<30))
1075+#define UDF_EXT_LEN(len) ((len) & ((1<<30)-1))
1076+#define UDF_EXT_MAXLEN ((1<<30)-1)
1077+
1078+
1079+/* Character set spec [1/7.2.1] */
1080+struct charspec {
1081+ uint8_t type;
1082+ uint8_t inf[63];
1083+} __packed;
1084+
1085+
1086+struct pathcomp {
1087+ uint8_t type;
1088+ uint8_t l_ci;
1089+ uint16_t comp_filever;
1090+ uint8_t ident[256];
1091+} __packed;
1092+#define UDF_PATH_COMP_SIZE 4
1093+#define UDF_PATH_COMP_RESERVED 0
1094+#define UDF_PATH_COMP_ROOT 1
1095+#define UDF_PATH_COMP_MOUNTROOT 2
1096+#define UDF_PATH_COMP_PARENTDIR 3
1097+#define UDF_PATH_COMP_CURDIR 4
1098+#define UDF_PATH_COMP_NAME 5
1099+
1100+
1101+/* Timestamp [1/7.3] */
1102+struct timestamp {
1103+ uint16_t type_tz;
1104+ uint16_t year;
1105+ uint8_t month;
1106+ uint8_t day;
1107+ uint8_t hour;
1108+ uint8_t minute;
1109+ uint8_t second;
1110+ uint8_t centisec;
1111+ uint8_t hund_usec;
1112+ uint8_t usec;
1113+} __packed;
1114+#define UDF_TIMESTAMP_SIZE 12
1115+
1116+
1117+/* Entity Identifier [1/7.4] */
1118+#define UDF_REGID_ID_SIZE 23
1119+struct regid {
1120+ uint8_t flags;
1121+ uint8_t id[UDF_REGID_ID_SIZE];
1122+ uint8_t id_suffix[8];
1123+} __packed;
1124+
1125+
1126+/* ICB Tag [4/14.6] */
1127+struct icb_tag {
1128+ uint32_t prev_num_dirs;
1129+ uint16_t strat_type;
1130+ uint8_t strat_param[2];
1131+ uint16_t max_num_entries;
1132+ uint8_t reserved;
1133+ uint8_t file_type;
1134+ struct lb_addr parent_icb;
1135+ uint16_t flags;
1136+} __packed;
1137+#define UDF_ICB_TAG_FLAGS_ALLOC_MASK 0x03
1138+#define UDF_ICB_SHORT_ALLOC 0x00
1139+#define UDF_ICB_LONG_ALLOC 0x01
1140+#define UDF_ICB_EXT_ALLOC 0x02
1141+#define UDF_ICB_INTERN_ALLOC 0x03
1142+
1143+#define UDF_ICB_TAG_FLAGS_DIRORDERED (1<< 3)
1144+#define UDF_ICB_TAG_FLAGS_NONRELOC (1<< 4)
1145+#define UDF_ICB_TAG_FLAGS_CONTIGUES (1<< 9)
1146+#define UDF_ICB_TAG_FLAGS_MULTIPLEVERS (1<<12)
1147+
1148+#define UDF_ICB_TAG_FLAGS_SETUID (1<< 6)
1149+#define UDF_ICB_TAG_FLAGS_SETGID (1<< 7)
1150+#define UDF_ICB_TAG_FLAGS_STICKY (1<< 8)
1151+
1152+#define UDF_ICB_FILETYPE_UNKNOWN 0
1153+#define UDF_ICB_FILETYPE_UNALLOCSPACE 1
1154+#define UDF_ICB_FILETYPE_PARTINTEGRITY 2
1155+#define UDF_ICB_FILETYPE_INDIRECTENTRY 3
1156+#define UDF_ICB_FILETYPE_DIRECTORY 4
1157+#define UDF_ICB_FILETYPE_RANDOMACCESS 5
1158+#define UDF_ICB_FILETYPE_BLOCKDEVICE 6
1159+#define UDF_ICB_FILETYPE_CHARDEVICE 7
1160+#define UDF_ICB_FILETYPE_EXTATTRREC 8
1161+#define UDF_ICB_FILETYPE_FIFO 9
1162+#define UDF_ICB_FILETYPE_SOCKET 10
1163+#define UDF_ICB_FILETYPE_TERM 11
1164+#define UDF_ICB_FILETYPE_SYMLINK 12
1165+#define UDF_ICB_FILETYPE_STREAMDIR 13
1166+#define UDF_ICB_FILETYPE_VAT 248
1167+#define UDF_ICB_FILETYPE_REALTIME 249
1168+#define UDF_ICB_FILETYPE_META_MAIN 250
1169+#define UDF_ICB_FILETYPE_META_MIRROR 251
1170+#define UDF_ICB_FILETYPE_META_BITMAP 252
1171+
1172+
1173+/* Anchor Volume Descriptor Pointer [3/10.2] */
1174+struct anchor_vdp {
1175+ struct desc_tag tag;
1176+ struct extent_ad main_vds_ex; /* to main volume descriptor set ; 16 sectors min */
1177+ struct extent_ad reserve_vds_ex; /* copy of main volume descriptor set ; 16 sectors min */
1178+} __packed;
1179+
1180+
1181+/* Volume Descriptor Pointer [3/10.3] */
1182+struct vol_desc_ptr {
1183+ struct desc_tag tag; /* use for extending the volume descriptor space */
1184+ uint32_t vds_number;
1185+ struct extent_ad next_vds_ex; /* points to the next block for volume descriptor space */
1186+} __packed;
1187+
1188+
1189+/* Primary Volume Descriptor [3/10.1] */
1190+struct pri_vol_desc {
1191+ struct desc_tag tag;
1192+ uint32_t seq_num; /* MAX prevail */
1193+ uint32_t pvd_num; /* assigned by author; 0 is special as in it may only occure once */
1194+ char vol_id[32]; /* KEY ; main identifier of this disc */
1195+ uint16_t vds_num; /* volume descriptor number; i.e. what volume number is it */
1196+ uint16_t max_vol_seq; /* maximum volume descriptor number known */
1197+ uint16_t ichg_lvl;
1198+ uint16_t max_ichg_lvl;
1199+ uint32_t charset_list;
1200+ uint32_t max_charset_list;
1201+ char volset_id[128]; /* KEY ; if part of a multi-disc set or a band of volumes */
1202+ struct charspec desc_charset; /* KEY according to ECMA 167 */
1203+ struct charspec explanatory_charset;
1204+ struct extent_ad vol_abstract;
1205+ struct extent_ad vol_copyright;
1206+ struct regid app_id;
1207+ struct timestamp time;
1208+ struct regid imp_id;
1209+ uint8_t imp_use[64];
1210+ uint32_t prev_vds_loc; /* location of predecessor _lov ? */
1211+ uint16_t flags; /* bit 0 : if set indicates volume set name is meaningfull */
1212+ uint8_t reserved[22];
1213+} __packed;
1214+
1215+
1216+/* UDF specific implementation use part of the implementation use volume descriptor */
1217+struct udf_lv_info {
1218+ struct charspec lvi_charset;
1219+ char logvol_id[128];
1220+
1221+ char lvinfo1[36];
1222+ char lvinfo2[36];
1223+ char lvinfo3[36];
1224+
1225+ struct regid impl_id;
1226+ uint8_t impl_use[128];
1227+} __packed;
1228+
1229+
1230+/* Implementation use Volume Descriptor */
1231+struct impvol_desc {
1232+ struct desc_tag tag;
1233+ uint32_t seq_num;
1234+ struct regid impl_id;
1235+ union {
1236+ struct udf_lv_info lv_info;
1237+ char impl_use[460];
1238+ } _impl_use;
1239+} __packed;
1240+
1241+
1242+/* Logical Volume Descriptor [3/10.6] */
1243+struct logvol_desc {
1244+ struct desc_tag tag;
1245+ uint32_t seq_num; /* MAX prevail */
1246+ struct charspec desc_charset; /* KEY */
1247+ char logvol_id[128]; /* KEY */
1248+ uint32_t lb_size;
1249+ struct regid domain_id;
1250+ union {
1251+ struct long_ad fsd_loc; /* to fileset descriptor SEQUENCE */
1252+ uint8_t logvol_content_use[16];
1253+ } _lvd_use;
1254+ uint32_t mt_l; /* Partition map length */
1255+ uint32_t n_pm; /* Number of partition maps */
1256+ struct regid imp_id;
1257+ uint8_t imp_use[128];
1258+ struct extent_ad integrity_seq_loc;
1259+ uint8_t maps[1];
1260+} __packed;
1261+#define lv_fsd_loc _lvd_use.fsd_loc
1262+
1263+#define UDF_INTEGRITY_OPEN 0
1264+#define UDF_INTEGRITY_CLOSED 1
1265+
1266+
1267+#define UDF_PMAP_SIZE 64
1268+
1269+/* Type 1 Partition Map [3/10.7.2] */
1270+struct part_map_1 {
1271+ uint8_t type;
1272+ uint8_t len;
1273+ uint16_t vol_seq_num;
1274+ uint16_t part_num;
1275+} __packed;
1276+
1277+
1278+/* Type 2 Partition Map [3/10.7.3] */
1279+struct part_map_2 {
1280+ uint8_t type;
1281+ uint8_t len;
1282+ uint8_t reserved[2];
1283+ struct regid part_id;
1284+ uint16_t vol_seq_num;
1285+ uint16_t part_num;
1286+ uint8_t reserved2[24];
1287+} __packed;
1288+
1289+
1290+/* Virtual Partition Map [UDF 2.01/2.2.8] */
1291+struct part_map_virt {
1292+ uint8_t type;
1293+ uint8_t len;
1294+ uint8_t reserved[2];
1295+ struct regid id;
1296+ uint16_t vol_seq_num;
1297+ uint16_t part_num;
1298+ uint8_t reserved1[24];
1299+} __packed;
1300+
1301+
1302+/* Sparable Partition Map [UDF 2.01/2.2.9] */
1303+struct part_map_spare {
1304+ uint8_t type;
1305+ uint8_t len;
1306+ uint8_t reserved[2];
1307+ struct regid id;
1308+ uint16_t vol_seq_num;
1309+ uint16_t part_num;
1310+ uint16_t packet_len;
1311+ uint8_t n_st; /* Number of redundant sparing tables range 1-4 */
1312+ uint8_t reserved1;
1313+ uint32_t st_size; /* size of EACH sparing table */
1314+ uint32_t st_loc[1]; /* locations of sparing tables */
1315+} __packed;
1316+
1317+
1318+/* Metadata Partition Map [UDF 2.50/2.2.10] */
1319+struct part_map_meta {
1320+ uint8_t type;
1321+ uint8_t len;
1322+ uint8_t reserved[2];
1323+ struct regid id;
1324+ uint16_t vol_seq_num;
1325+ uint16_t part_num;
1326+ uint32_t meta_file_lbn; /* logical block number for file entry within part_num */
1327+ uint32_t meta_mirror_file_lbn;
1328+ uint32_t meta_bitmap_file_lbn;
1329+ uint32_t alloc_unit_size; /* allocation unit size in blocks */
1330+ uint16_t alignment_unit_size; /* alignment nessisary in blocks */
1331+ uint8_t flags;
1332+ uint8_t reserved1[5];
1333+} __packed;
1334+#define METADATA_DUPLICATED 1
1335+
1336+
1337+union udf_pmap {
1338+ uint8_t data[UDF_PMAP_SIZE];
1339+ struct part_map_1 pm1;
1340+ struct part_map_2 pm2;
1341+ struct part_map_virt pmv;
1342+ struct part_map_spare pms;
1343+ struct part_map_meta pmm;
1344+};
1345+
1346+
1347+/* Sparing Map Entry [UDF 2.01/2.2.11] */
1348+struct spare_map_entry {
1349+ uint32_t org; /* partition relative address */
1350+ uint32_t map; /* absolute disc address (!) can be in partition, but doesn't have to be */
1351+} __packed;
1352+
1353+
1354+/* Sparing Table [UDF 2.01/2.2.11] */
1355+struct udf_sparing_table {
1356+ struct desc_tag tag;
1357+ struct regid id;
1358+ uint16_t rt_l; /* Relocation Table len */
1359+ uint8_t reserved[2];
1360+ uint32_t seq_num;
1361+ struct spare_map_entry entries[1];
1362+} __packed;
1363+
1364+
1365+#define UDF_NO_PREV_VAT 0xffffffff
1366+/* UDF 1.50 VAT suffix [UDF 2.2.10 (UDF 1.50 spec)] */
1367+struct udf_oldvat_tail {
1368+ struct regid id; /* "*UDF Virtual Alloc Tbl" */
1369+ uint32_t prev_vat;
1370+} __packed;
1371+
1372+
1373+/* VAT table [UDF 2.0.1/2.2.10] */
1374+struct udf_vat {
1375+ uint16_t header_len;
1376+ uint16_t impl_use_len;
1377+ char logvol_id[128]; /* newer version of the LVD one */
1378+ uint32_t prev_vat;
1379+ uint32_t num_files;
1380+ uint32_t num_directories;
1381+ uint16_t min_udf_readver;
1382+ uint16_t min_udf_writever;
1383+ uint16_t max_udf_writever;
1384+ uint16_t reserved;
1385+ uint8_t data[1]; /* impl.use followed by VAT entries (uint32_t) */
1386+} __packed;
1387+
1388+
1389+/* Space bitmap descriptor as found in the partition header descriptor */
1390+struct space_bitmap_desc {
1391+ struct desc_tag tag; /* TagId 264 */
1392+ uint32_t num_bits; /* number of bits */
1393+ uint32_t num_bytes; /* bytes that contain it */
1394+ uint8_t data[1];
1395+} __packed;
1396+
1397+
1398+/* Unalloc space entry as found in the partition header descriptor */
1399+struct space_entry_desc {
1400+ struct desc_tag tag; /* TagId 263 */
1401+ struct icb_tag icbtag; /* type 1 */
1402+ uint32_t l_ad; /* in bytes */
1403+ uint8_t entry[1];
1404+} __packed;
1405+
1406+
1407+/* Partition header descriptor; in the contents_use of part_desc */
1408+struct part_hdr_desc {
1409+ struct short_ad unalloc_space_table;
1410+ struct short_ad unalloc_space_bitmap;
1411+ struct short_ad part_integrety_table; /* has to be ZERO for UDF */
1412+ struct short_ad freed_space_table;
1413+ struct short_ad freed_space_bitmap;
1414+ uint8_t reserved[88];
1415+} __packed;
1416+
1417+
1418+/* Partition Descriptor [3/10.5] */
1419+struct part_desc {
1420+ struct desc_tag tag;
1421+ uint32_t seq_num; /* MAX prevailing */
1422+ uint16_t flags; /* bit 0 : if set the space is allocated */
1423+ uint16_t part_num; /* KEY */
1424+ struct regid contents;
1425+ union {
1426+ struct part_hdr_desc part_hdr;
1427+ uint8_t contents_use[128];
1428+ } _impl_use;
1429+ uint32_t access_type; /* R/W, WORM etc. */
1430+ uint32_t start_loc; /* start of partition with given length */
1431+ uint32_t part_len;
1432+ struct regid imp_id;
1433+ uint8_t imp_use[128];
1434+ uint8_t reserved[156];
1435+} __packed;
1436+#define pd_part_hdr _impl_use.part_hdr
1437+#define UDF_PART_FLAG_ALLOCATED 1
1438+
1439+
1440+/* Unallocated Space Descriptor (UDF 2.01/2.2.5) */
1441+struct unalloc_sp_desc {
1442+ struct desc_tag tag;
1443+ uint32_t seq_num; /* MAX prevailing */
1444+ uint32_t alloc_desc_num;
1445+ struct extent_ad alloc_desc[1];
1446+} __packed;
1447+
1448+
1449+/* Logical Volume Integrity Descriptor [3/30.10] */
1450+struct logvolhdr {
1451+ uint64_t next_unique_id;
1452+ /* rest reserved */
1453+} __packed;
1454+
1455+
1456+struct udf_logvol_info {
1457+ struct regid impl_id;
1458+ uint32_t num_files;
1459+ uint32_t num_directories;
1460+ uint16_t min_udf_readver;
1461+ uint16_t min_udf_writever;
1462+ uint16_t max_udf_writever;
1463+} __packed;
1464+
1465+
1466+struct logvol_int_desc {
1467+ struct desc_tag tag;
1468+ struct timestamp time;
1469+ uint32_t integrity_type;
1470+ struct extent_ad next_extent;
1471+ union {
1472+ struct logvolhdr logvolhdr;
1473+ int8_t reserved[32];
1474+ } _impl_use;
1475+ uint32_t num_part;
1476+ uint32_t l_iu;
1477+ uint32_t tables[1]; /* Freespace table, Sizetable, Implementation use */
1478+} __packed;
1479+#define lvint_next_unique_id _impl_use.logvolhdr.next_unique_id
1480+
1481+
1482+/* File Set Descriptor [4/14.1] */
1483+struct fileset_desc {
1484+ struct desc_tag tag;
1485+ struct timestamp time;
1486+ uint16_t ichg_lvl;
1487+ uint16_t max_ichg_lvl;
1488+ uint32_t charset_list;
1489+ uint32_t max_charset_list;
1490+ uint32_t fileset_num; /* key! */
1491+ uint32_t fileset_desc_num;
1492+ struct charspec logvol_id_charset;
1493+ char logvol_id[128]; /* for recovery */
1494+ struct charspec fileset_charset;
1495+ char fileset_id[32]; /* Mountpoint !! */
1496+ char copyright_file_id[32];
1497+ char abstract_file_id[32];
1498+ struct long_ad rootdir_icb; /* to rootdir; icb->virtual ? */
1499+ struct regid domain_id;
1500+ struct long_ad next_ex; /* to the next fileset_desc extent */
1501+ struct long_ad streamdir_icb; /* streamdir; needed? */
1502+ uint8_t reserved[32];
1503+} __packed;
1504+
1505+
1506+/* File Identifier Descriptor [4/14.4] */
1507+struct fileid_desc {
1508+ struct desc_tag tag;
1509+ uint16_t file_version_num;
1510+ uint8_t file_char;
1511+ uint8_t l_fi; /* Length of file identifier area */
1512+ struct long_ad icb;
1513+ uint16_t l_iu; /* Length of implementation use area */
1514+ uint8_t data[0];
1515+} __packed;
1516+#define UDF_FID_SIZE 38
1517+#define UDF_FILE_CHAR_VIS (1 << 0) /* Invisible */
1518+#define UDF_FILE_CHAR_DIR (1 << 1) /* Directory */
1519+#define UDF_FILE_CHAR_DEL (1 << 2) /* Deleted */
1520+#define UDF_FILE_CHAR_PAR (1 << 3) /* Parent Directory */
1521+#define UDF_FILE_CHAR_META (1 << 4) /* Stream metadata */
1522+
1523+
1524+/* Extended attributes [4/14.10.1] */
1525+struct extattrhdr_desc {
1526+ struct desc_tag tag;
1527+ uint32_t impl_attr_loc; /* offsets within this descriptor */
1528+ uint32_t appl_attr_loc; /* ditto */
1529+} __packed;
1530+#define UDF_IMPL_ATTR_LOC_NOT_PRESENT 0xffffffff
1531+#define UDF_APPL_ATTR_LOC_NOT_PRESENT 0xffffffff
1532+
1533+
1534+/* Extended attribute entry [4/48.10.2] */
1535+struct extattr_entry {
1536+ uint32_t type;
1537+ uint8_t subtype;
1538+ uint8_t reserved[3];
1539+ uint32_t a_l;
1540+} __packed;
1541+
1542+
1543+/* Extended attribute entry; type 2048 [4/48.10.8] */
1544+struct impl_extattr_entry {
1545+ struct extattr_entry hdr;
1546+ uint32_t iu_l;
1547+ struct regid imp_id;
1548+ uint8_t data[1];
1549+} __packed;
1550+
1551+
1552+/* Extended attribute entry; type 65 536 [4/48.10.9] */
1553+struct appl_extattr_entry {
1554+ struct extattr_entry hdr;
1555+ uint32_t au_l;
1556+ struct regid appl_id;
1557+ uint8_t data[1];
1558+} __packed;
1559+
1560+
1561+/* File Times attribute entry; type 5 or type 6 [4/48.10.5], [4/48.10.6] */
1562+struct filetimes_extattr_entry {
1563+ struct extattr_entry hdr;
1564+ uint32_t d_l; /* length of times[] data following */
1565+ uint32_t existence; /* bitmask */
1566+ struct timestamp times[1]; /* in order of assending bits */
1567+} __packed;
1568+#define UDF_FILETIMES_ATTR_NO 5
1569+#define UDF_FILETIMES_FILE_CREATION 1
1570+#define UDF_FILETIMES_FILE_DELETION 4
1571+#define UDF_FILETIMES_FILE_EFFECTIVE 8
1572+#define UDF_FILETIMES_FILE_BACKUPED 16
1573+#define UDF_FILETIMES_ATTR_SIZE(no) (20 + (no)*sizeof(struct timestamp))
1574+
1575+
1576+/* Device Specification Extended Attribute [4/4.10.7] */
1577+struct device_extattr_entry {
1578+ struct extattr_entry hdr;
1579+ uint32_t iu_l; /* length of implementation use */
1580+ uint32_t major;
1581+ uint32_t minor;
1582+ uint8_t data[1]; /* UDF: if nonzero length, contain developer ID regid */
1583+} __packed;
1584+#define UDF_DEVICESPEC_ATTR_NO 12
1585+
1586+
1587+/* VAT LV extension Extended Attribute [UDF 3.3.4.5.1.3] 1.50 errata */
1588+struct vatlvext_extattr_entry {
1589+ uint64_t unique_id_chk; /* needs to be copy of ICB's */
1590+ uint32_t num_files;
1591+ uint32_t num_directories;
1592+ char logvol_id[128]; /* replaces logvol name */
1593+} __packed;
1594+
1595+
1596+/* File Entry [4/14.9] */
1597+struct file_entry {
1598+ struct desc_tag tag;
1599+ struct icb_tag icbtag;
1600+ uint32_t uid;
1601+ uint32_t gid;
1602+ uint32_t perm;
1603+ uint16_t link_cnt;
1604+ uint8_t rec_format;
1605+ uint8_t rec_disp_attr;
1606+ uint32_t rec_len;
1607+ uint64_t inf_len;
1608+ uint64_t logblks_rec;
1609+ struct timestamp atime;
1610+ struct timestamp mtime;
1611+ struct timestamp attrtime;
1612+ uint32_t ckpoint;
1613+ struct long_ad ex_attr_icb;
1614+ struct regid imp_id;
1615+ uint64_t unique_id;
1616+ uint32_t l_ea; /* Length of extended attribute area */
1617+ uint32_t l_ad; /* Length of allocation descriptors */
1618+ uint8_t data[1];
1619+} __packed;
1620+#define UDF_FENTRY_SIZE 176
1621+#define UDF_FENTRY_PERM_USER_MASK 0x07
1622+#define UDF_FENTRY_PERM_GRP_MASK 0xE0
1623+#define UDF_FENTRY_PERM_OWNER_MASK 0x1C00
1624+
1625+
1626+/* Extended File Entry [4/48.17] */
1627+struct extfile_entry {
1628+ struct desc_tag tag;
1629+ struct icb_tag icbtag;
1630+ uint32_t uid;
1631+ uint32_t gid;
1632+ uint32_t perm;
1633+ uint16_t link_cnt;
1634+ uint8_t rec_format;
1635+ uint8_t rec_disp_attr;
1636+ uint32_t rec_len;
1637+ uint64_t inf_len;
1638+ uint64_t obj_size;
1639+ uint64_t logblks_rec;
1640+ struct timestamp atime;
1641+ struct timestamp mtime;
1642+ struct timestamp ctime;
1643+ struct timestamp attrtime;
1644+ uint32_t ckpoint;
1645+ uint32_t reserved1;
1646+ struct long_ad ex_attr_icb;
1647+ struct long_ad streamdir_icb;
1648+ struct regid imp_id;
1649+ uint64_t unique_id;
1650+ uint32_t l_ea; /* Length of extended attribute area */
1651+ uint32_t l_ad; /* Length of allocation descriptors */
1652+ uint8_t data[1];
1653+} __packed;
1654+#define UDF_EXTFENTRY_SIZE 216
1655+
1656+
1657+/* Indirect entry [ecma 48.7] */
1658+struct indirect_entry {
1659+ struct desc_tag tag;
1660+ struct icb_tag icbtag;
1661+ struct long_ad indirect_icb;
1662+} __packed;
1663+
1664+
1665+/* Allocation extent descriptor [ecma 48.5] */
1666+struct alloc_ext_entry {
1667+ struct desc_tag tag;
1668+ uint32_t prev_entry;
1669+ uint32_t l_ad;
1670+ uint8_t data[1];
1671+} __packed;
1672+
1673+
1674+union dscrptr {
1675+ struct desc_tag tag;
1676+ struct anchor_vdp avdp;
1677+ struct vol_desc_ptr vdp;
1678+ struct pri_vol_desc pvd;
1679+ struct logvol_desc lvd;
1680+ struct unalloc_sp_desc usd;
1681+ struct logvol_int_desc lvid;
1682+ struct impvol_desc ivd;
1683+ struct part_desc pd;
1684+ struct fileset_desc fsd;
1685+ struct fileid_desc fid;
1686+ struct file_entry fe;
1687+ struct extfile_entry efe;
1688+ struct extattrhdr_desc eahd;
1689+ struct indirect_entry inde;
1690+ struct alloc_ext_entry aee;
1691+ struct udf_sparing_table spt;
1692+ struct space_bitmap_desc sbd;
1693+ struct space_entry_desc sed;
1694+};
1695+
1696+
1697+#endif /* !_FS_UDF_ECMA167_UDF_H_ */
1698+
1699
1700--- sys/fs/udf2/udf.h 1969-12-31 16:00:00.000000000 -0800
1701+++ updates/sys/fs/udf2/udf.h 2014-11-16 16:27:23.000000000 -0800
1702@@ -0,0 +1,174 @@
1703+/*-
1704+ * Copyright (c) 2006, 2008 Reinoud Zandijk
1705+ * All rights reserved.
1706+ *
1707+ * Redistribution and use in source and binary forms, with or without
1708+ * modification, are permitted provided that the following conditions
1709+ * are met:
1710+ * 1. Redistributions of source code must retain the above copyright
1711+ * notice, this list of conditions and the following disclaimer.
1712+ * 2. Redistributions in binary form must reproduce the above copyright
1713+ * notice, this list of conditions and the following disclaimer in the
1714+ * documentation and/or other materials provided with the distribution.
1715+ *
1716+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1717+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1718+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1719+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1720+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1721+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1722+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1723+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1724+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1725+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1726+ *
1727+ */
1728+
1729+#ifndef _FS_UDF_UDF_H_
1730+#define _FS_UDF_UDF_H_
1731+
1732+#include "udf_osta.h"
1733+
1734+/* constants to identify what kind of identifier we are dealing with */
1735+#define UDF_REGID_DOMAIN 1
1736+#define UDF_REGID_UDF 2
1737+#define UDF_REGID_IMPLEMENTATION 3
1738+#define UDF_REGID_APPLICATION 4
1739+#define UDF_REGID_NAME 99
1740+
1741+/* Configuration values */
1742+#define UDF_VAT_ALLOC_LIMIT 104857600 /* picked at random */
1743+#define UDF_VAT_CHUNKSIZE (64*1024) /* picked */
1744+#define UDF_SYMLINKBUFLEN (64*1024) /* picked */
1745+
1746+#define UDF_DISC_SLACK (128) /* picked, at least 64 kb or 128 */
1747+
1748+/* structure space */
1749+#define UDF_ANCHORS 4 /* 256, 512, N-256, N */
1750+#define UDF_PARTITIONS 4 /* overkill */
1751+#define UDF_PMAPS 5 /* overkill */
1752+#define UDF_MAX_ALLOC_EXTENTS 50 /* overkill */
1753+
1754+/* constants */
1755+#define UDF_MAX_NAMELEN 255 /* as per SPEC */
1756+#define UDF_TRAN_EXTERNAL 0
1757+#define UDF_TRAN_INTERN 1
1758+#define UDF_TRAN_ZERO 2
1759+
1760+/* RW content hint for allocation and other purposes */
1761+#define UDF_C_DSCR 2 /* update sectornr and CRC */
1762+
1763+/* virtual to physical mapping types */
1764+#define UDF_VTOP_RAWPART UDF_PMAPS /* [0..UDF_PMAPS> are normal */
1765+
1766+#define UDF_VTOP_TYPE_RAW 0
1767+#define UDF_VTOP_TYPE_UNKNOWN 0
1768+#define UDF_VTOP_TYPE_PHYS 1
1769+#define UDF_VTOP_TYPE_VIRT 2
1770+#define UDF_VTOP_TYPE_SPARABLE 3
1771+#define UDF_VTOP_TYPE_META 4
1772+
1773+/* logical volume error handling actions */
1774+#define UDF_UPDATE_TRACKINFO 0x01 /* update trackinfo and re-shedule */
1775+#define UDF_REMAP_BLOCK 0x02 /* remap the failing block length */
1776+
1777+/* mounting options */
1778+#define UDFMNT_KICONV 1
1779+#define UDFMNT_OVERRIDE_UID 2
1780+#define UDFMNT_OVERRIDE_GID 4
1781+#define UDFMNT_USE_MASK 8
1782+#define UDFMNT_USE_DIRMASK 16
1783+
1784+/* malloc pools */
1785+MALLOC_DECLARE(M_UDFTEMP);
1786+
1787+struct udf_node;
1788+
1789+struct udf_lvintq {
1790+ uint32_t start;
1791+ uint32_t end;
1792+ uint32_t pos;
1793+ uint32_t wpos;
1794+};
1795+
1796+struct udf_mount {
1797+ struct mount *vfs_mountp;
1798+ struct vnode *devvp;
1799+ struct g_consumer *geomcp;
1800+ uint32_t sector_size;
1801+ uint64_t flags;
1802+ uid_t anon_uid;
1803+ gid_t anon_gid;
1804+ void *iconv_d2l; /* disk to local */
1805+ mode_t mode;
1806+ mode_t dirmode;
1807+
1808+ /* Used in mounting */
1809+ uint32_t first_trackblank;
1810+ uint32_t session_start;
1811+ uint32_t session_end;
1812+ uint32_t session_last_written;
1813+
1814+ /* format descriptors */
1815+ struct anchor_vdp *anchors[UDF_ANCHORS]; /* anchors to VDS */
1816+ struct pri_vol_desc *primary_vol; /* identification */
1817+ struct logvol_desc *logical_vol; /* main mapping v->p */
1818+ struct unalloc_sp_desc *unallocated; /* free UDF space */
1819+ struct impvol_desc *implementation; /* likely reduntant */
1820+ struct logvol_int_desc *logvol_integrity; /* current integrity */
1821+ struct part_desc *partitions[UDF_PARTITIONS]; /* partitions */
1822+ /* logvol_info is derived; points *into* other structures */
1823+ struct udf_logvol_info *logvol_info; /* integrity descr. */
1824+
1825+ /* fileset and root directories */
1826+ struct fileset_desc *fileset_desc; /* normally one */
1827+
1828+ /* logical to physical translations */
1829+ int vtop[UDF_PMAPS+1]; /* vpartnr trans */
1830+ int vtop_tp[UDF_PMAPS+1]; /* type of trans */
1831+
1832+ /* VAT */
1833+ uint32_t first_possible_vat_location;
1834+ uint32_t last_possible_vat_location;
1835+ uint32_t vat_entries;
1836+ uint32_t vat_offset; /* offset in table */
1837+ uint32_t vat_table_alloc_len;
1838+ uint8_t *vat_table;
1839+
1840+ /* sparable */
1841+ uint32_t sparable_packet_size;
1842+ struct udf_sparing_table *sparing_table;
1843+
1844+ /* meta */
1845+ struct udf_node *metadata_node; /* system node */
1846+};
1847+
1848+/*
1849+ * UDF node describing a file/directory.
1850+ *
1851+ * BUGALERT claim node_mutex before reading/writing to prevent inconsistencies !
1852+ */
1853+struct udf_node {
1854+ struct vnode *vnode; /* vnode associated */
1855+ struct udf_mount *ump;
1856+
1857+ ino_t hash_id; /* should contain inode */
1858+ int diroff; /* used in lookup */
1859+
1860+ /* one of `fe' or `efe' can be set, not both (UDF file entry dscr.) */
1861+ struct file_entry *fe;
1862+ struct extfile_entry *efe;
1863+ struct alloc_ext_entry *ext[UDF_MAX_ALLOC_EXTENTS];
1864+ int num_extensions;
1865+
1866+ /* location found, recording location & hints */
1867+ struct long_ad loc; /* FID/hash loc. */
1868+};
1869+
1870+struct udf_fid {
1871+ u_short len; /* length of data in bytes */
1872+ u_short padding; /* force longword alignment */
1873+ ino_t ino;
1874+};
1875+
1876+#endif /* !_FS_UDF_UDF_H_ */
1877
1878--- sys/fs/udf2/udf_allocation.c 1969-12-31 16:00:00.000000000 -0800
1879+++ updates/sys/fs/udf2/udf_allocation.c 2014-11-16 16:27:23.000000000 -0800
1880@@ -0,0 +1,443 @@
1881+/*-
1882+ * Copyright (c) 2012 Will DeVries
1883+ * Copyright (c) 2006, 2008 Reinoud Zandijk
1884+ * All rights reserved.
1885+ *
1886+ * Redistribution and use in source and binary forms, with or without
1887+ * modification, are permitted provided that the following conditions
1888+ * are met:
1889+ * 1. Redistributions of source code must retain the above copyright
1890+ * notice, this list of conditions and the following disclaimer.
1891+ * 2. Redistributions in binary form must reproduce the above copyright
1892+ * notice, this list of conditions and the following disclaimer in the
1893+ * documentation and/or other materials provided with the distribution.
1894+ *
1895+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1896+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1897+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1898+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1899+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1900+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1901+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1902+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1903+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1904+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1905+ *
1906+ */
1907+
1908+#include <sys/cdefs.h>
1909+#include <sys/endian.h>
1910+#include <sys/param.h>
1911+#include <sys/systm.h>
1912+#include <sys/limits.h>
1913+#include <sys/malloc.h>
1914+
1915+#include "ecma167-udf.h"
1916+#include "udf.h"
1917+#include "udf_subr.h"
1918+
1919+
1920+void
1921+udf_calc_freespace(struct udf_mount *ump, uint64_t *sizeblks,
1922+ uint64_t *freeblks)
1923+{
1924+ struct logvol_int_desc *lvid;
1925+ int num_vpart, vpart;
1926+ uint32_t *pos1, *pos2;
1927+
1928+ lvid = ump->logvol_integrity;
1929+ *freeblks = *sizeblks = 0;
1930+
1931+ /*
1932+ * Sequentials media report free space directly (CD/DVD/BD-R), for the
1933+ * other media we need the logical volume integrity.
1934+ *
1935+ * We sum all free space up here regardless of type.
1936+ */
1937+
1938+ num_vpart = le32toh(lvid->num_part);
1939+
1940+#if 0
1941+ if (ump->discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
1942+ /* use track info directly summing if there are 2 open */
1943+ /* XXX assumption at most two tracks open */
1944+ *freeblks = ump->data_track.free_blocks;
1945+ if (ump->data_track.tracknr != ump->metadata_track.tracknr)
1946+ *freeblks += ump->metadata_track.free_blocks;
1947+ *sizeblks = ump->discinfo.last_possible_lba;
1948+ } else {
1949+#endif
1950+ /* free and used space for mountpoint based on logvol integrity */
1951+ for (vpart = 0; vpart < num_vpart; vpart++) {
1952+ pos1 = &lvid->tables[0] + vpart;
1953+ pos2 = &lvid->tables[0] + num_vpart + vpart;
1954+ if (le32toh(*pos1) != (uint32_t) -1) {
1955+ *freeblks += le32toh(*pos1);
1956+ *sizeblks += le32toh(*pos2);
1957+ }
1958+ }
1959+#if 0
1960+ }
1961+#endif
1962+
1963+ if (*freeblks > UDF_DISC_SLACK)
1964+ *freeblks -= UDF_DISC_SLACK;
1965+ else
1966+ *freeblks = 0;
1967+}
1968+
1969+int
1970+udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc,
1971+ uint32_t *lb_numres, uint32_t *extres)
1972+{
1973+ struct part_desc *pdesc;
1974+ struct spare_map_entry *sme;
1975+ struct long_ad s_icb_loc;
1976+ uint64_t end_foffset, foffset;
1977+ int eof, error, flags, part, rel, slot;
1978+ uint32_t lb_num, lb_packet, lb_rel, lb_size, len;
1979+ uint32_t ext_offset, udf_rw32_lbmap;
1980+ uint16_t vpart;
1981+
1982+ KASSERT(ump && icb_loc && lb_numres,("ump && icb_loc && lb_numres"));
1983+
1984+ vpart = le16toh(icb_loc->loc.part_num);
1985+ lb_num = le32toh(icb_loc->loc.lb_num);
1986+ if (vpart > UDF_VTOP_RAWPART)
1987+ return (EINVAL);
1988+
1989+translate_again:
1990+ part = ump->vtop[vpart];
1991+ pdesc = ump->partitions[part];
1992+
1993+ switch (ump->vtop_tp[vpart]) {
1994+ case UDF_VTOP_TYPE_RAW:
1995+ /* 1:1 to the end of the device */
1996+ *lb_numres = lb_num;
1997+ *extres = INT_MAX;
1998+ return (0);
1999+ case UDF_VTOP_TYPE_PHYS:
2000+ /* transform into its disc logical block */
2001+ if (lb_num > le32toh(pdesc->part_len))
2002+ return (EINVAL);
2003+ *lb_numres = lb_num + le32toh(pdesc->start_loc);
2004+
2005+ /* extent from here to the end of the partition */
2006+ *extres = le32toh(pdesc->part_len) - lb_num;
2007+ return (0);
2008+ case UDF_VTOP_TYPE_VIRT:
2009+ /* only maps one logical block, lookup in VAT */
2010+ if (lb_num >= ump->vat_entries) /* XXX > or >= ? */
2011+ return (EINVAL);
2012+
2013+ /* lookup in virtual allocation table file */
2014+ error = udf_vat_read(ump, (uint8_t *)&udf_rw32_lbmap, 4,
2015+ ump->vat_offset + lb_num * 4);
2016+ if (error != 0)
2017+ return (error);
2018+
2019+ lb_num = le32toh(udf_rw32_lbmap);
2020+
2021+ /* transform into its disc logical block */
2022+ if (lb_num > le32toh(pdesc->part_len))
2023+ return (EINVAL);
2024+ *lb_numres = lb_num + le32toh(pdesc->start_loc);
2025+
2026+ /* just one logical block */
2027+ *extres = 1;
2028+ return (0);
2029+ case UDF_VTOP_TYPE_SPARABLE:
2030+ /* check if the packet containing the lb_num is remapped */
2031+ lb_packet = lb_num / ump->sparable_packet_size;
2032+ lb_rel = lb_num % ump->sparable_packet_size;
2033+
2034+ for (rel = 0; rel < le16toh(ump->sparing_table->rt_l); rel++) {
2035+ sme = &ump->sparing_table->entries[rel];
2036+ if (lb_packet == le32toh(sme->org)) {
2037+ /* NOTE maps to absolute disc logical block! */
2038+ *lb_numres = le32toh(sme->map) + lb_rel;
2039+ *extres = ump->sparable_packet_size - lb_rel;
2040+ return (0);
2041+ }
2042+ }
2043+
2044+ /* transform into its disc logical block */
2045+ if (lb_num > le32toh(pdesc->part_len))
2046+ return (EINVAL);
2047+ *lb_numres = lb_num + le32toh(pdesc->start_loc);
2048+
2049+ /* rest of block */
2050+ *extres = ump->sparable_packet_size - lb_rel;
2051+ return (0);
2052+ case UDF_VTOP_TYPE_META:
2053+ /* we have to look into the file's allocation descriptors */
2054+
2055+ /* use metadatafile allocation mutex */
2056+ lb_size = le32toh(ump->logical_vol->lb_size);
2057+
2058+ UDF_LOCK_NODE(ump->metadata_node, 0);
2059+
2060+ /* get first overlapping extent */
2061+ foffset = 0;
2062+ slot = 0;
2063+ for (;;) {
2064+ udf_get_adslot(ump->metadata_node, slot, &s_icb_loc,
2065+ &eof);
2066+ if (eof) {
2067+ UDF_UNLOCK_NODE(ump->metadata_node, 0);
2068+ return (EINVAL);
2069+ }
2070+ len = le32toh(s_icb_loc.len);
2071+ flags = UDF_EXT_FLAGS(len);
2072+ len = UDF_EXT_LEN(len);
2073+
2074+ if (flags == UDF_EXT_REDIRECT) {
2075+ slot++;
2076+ continue;
2077+ }
2078+
2079+ end_foffset = foffset + len;
2080+
2081+ if (end_foffset > lb_num * lb_size)
2082+ break; /* found */
2083+ foffset = end_foffset;
2084+ slot++;
2085+ }
2086+ /* found overlapping slot */
2087+ ext_offset = lb_num * lb_size - foffset;
2088+
2089+ /* process extent offset */
2090+ lb_num = le32toh(s_icb_loc.loc.lb_num);
2091+ vpart = le16toh(s_icb_loc.loc.part_num);
2092+ lb_num += (ext_offset + lb_size -1) / lb_size;
2093+ ext_offset = 0;
2094+
2095+ UDF_UNLOCK_NODE(ump->metadata_node, 0);
2096+ if (flags != UDF_EXT_ALLOCATED)
2097+ return (EINVAL);
2098+
2099+ /*
2100+ * vpart and lb_num are updated, translate again since we
2101+ * might be mapped on sparable media
2102+ */
2103+ goto translate_again;
2104+ default:
2105+ printf("UDF vtop translation scheme %d unimplemented yet\n",
2106+ ump->vtop_tp[vpart]);
2107+ }
2108+
2109+ return (EINVAL);
2110+}
2111+
2112+/*
2113+ * This is a simplified version of the udf_translate_file_extent function.
2114+ */
2115+int
2116+udf_bmap_translate(struct udf_node *udf_node, uint32_t block,
2117+ int *exttype, uint64_t *lsector, uint32_t *maxblks)
2118+{
2119+ struct udf_mount *ump;
2120+ struct icb_tag *icbtag;
2121+ struct long_ad s_ad, t_ad;
2122+ uint64_t foffset, new_foffset;
2123+ int addr_type, eof, error, flags, icbflags, slot;
2124+ uint32_t ext_offset, ext_remain, lb_num, lb_size, len, transsec32;
2125+ uint32_t translen;
2126+ uint16_t vpart_num;
2127+
2128+
2129+ if (udf_node == NULL)
2130+ return (ENOENT);
2131+
2132+ KASSERT(num_lb > 0,("num_lb > 0"));
2133+
2134+ UDF_LOCK_NODE(udf_node, 0);
2135+
2136+ /* initialise derivative vars */
2137+ ump = udf_node->ump;
2138+ lb_size = le32toh(ump->logical_vol->lb_size);
2139+
2140+ if (udf_node->fe != NULL)
2141+ icbtag = &udf_node->fe->icbtag;
2142+ else
2143+ icbtag = &udf_node->efe->icbtag;
2144+
2145+ icbflags = le16toh(icbtag->flags);
2146+ addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2147+
2148+ /* do the work */
2149+ if (addr_type == UDF_ICB_INTERN_ALLOC) {
2150+ *exttype = UDF_TRAN_INTERN;
2151+ *maxblks = 1;
2152+ UDF_UNLOCK_NODE(udf_node, 0);
2153+ return (0);
2154+ }
2155+
2156+ /* find first overlapping extent */
2157+ foffset = 0;
2158+ slot = 0;
2159+ for (;;) {
2160+ udf_get_adslot(udf_node, slot, &s_ad, &eof);
2161+ if (eof) {
2162+ UDF_UNLOCK_NODE(udf_node, 0);
2163+ return (EINVAL);
2164+ }
2165+ len = le32toh(s_ad.len);
2166+ flags = UDF_EXT_FLAGS(len);
2167+ len = UDF_EXT_LEN(len);
2168+
2169+ if (flags == UDF_EXT_REDIRECT) {
2170+ slot++;
2171+ continue;
2172+ }
2173+
2174+ new_foffset = foffset + len;
2175+
2176+ if (new_foffset > block * lb_size)
2177+ break; /* found */
2178+ foffset = new_foffset;
2179+ slot++;
2180+ }
2181+ /* found overlapping slot */
2182+
2183+ lb_num = le32toh(s_ad.loc.lb_num);
2184+ vpart_num = le16toh(s_ad.loc.part_num);
2185+
2186+ ext_offset = block * lb_size - foffset;
2187+ lb_num += (ext_offset + lb_size - 1) / lb_size;
2188+ ext_remain = (len - ext_offset + lb_size - 1) / lb_size;
2189+
2190+ /*
2191+ * note that the while(){} is nessisary for the extent that
2192+ * the udf_translate_vtop() returns doens't have to span the
2193+ * whole extent.
2194+ */
2195+ switch (flags) {
2196+ case UDF_EXT_FREE:
2197+ case UDF_EXT_ALLOCATED_BUT_NOT_USED:
2198+ *exttype = UDF_TRAN_ZERO;
2199+ *maxblks = ext_remain;
2200+ break;
2201+ case UDF_EXT_ALLOCATED:
2202+ *exttype = UDF_TRAN_EXTERNAL;
2203+ t_ad.loc.lb_num = htole32(lb_num);
2204+ t_ad.loc.part_num = htole16(vpart_num);
2205+ error = udf_translate_vtop(ump, &t_ad, &transsec32, &translen);
2206+ if (error != 0) {
2207+ UDF_UNLOCK_NODE(udf_node, 0);
2208+ return (error);
2209+ }
2210+ *lsector = transsec32;
2211+ *maxblks = MIN(ext_remain, translen);
2212+ break;
2213+ default:
2214+ UDF_UNLOCK_NODE(udf_node, 0);
2215+ return (EINVAL);
2216+ }
2217+
2218+ UDF_UNLOCK_NODE(udf_node, 0);
2219+
2220+ return (0);
2221+}
2222+
2223+void
2224+udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
2225+ int *eof) {
2226+ struct file_entry *fe;
2227+ struct extfile_entry *efe;
2228+ struct alloc_ext_entry *ext;
2229+ struct icb_tag *icbtag;
2230+ struct short_ad *short_ad;
2231+ struct long_ad *long_ad, l_icb;
2232+ int addr_type, adlen, extnr, icbflags;
2233+ uint32_t dscr_size, flags, lb_size, l_ad, l_ea, offset;
2234+ uint8_t *data_pos;
2235+
2236+ /* determine what descriptor we are in */
2237+ lb_size = le32toh(udf_node->ump->logical_vol->lb_size);
2238+
2239+ fe = udf_node->fe;
2240+ efe = udf_node->efe;
2241+ if (fe != NULL) {
2242+ icbtag = &fe->icbtag;
2243+ dscr_size = sizeof(struct file_entry) -1;
2244+ l_ea = le32toh(fe->l_ea);
2245+ l_ad = le32toh(fe->l_ad);
2246+ data_pos = (uint8_t *)fe + dscr_size + l_ea;
2247+ } else {
2248+ icbtag = &efe->icbtag;
2249+ dscr_size = sizeof(struct extfile_entry) -1;
2250+ l_ea = le32toh(efe->l_ea);
2251+ l_ad = le32toh(efe->l_ad);
2252+ data_pos = (uint8_t *)efe + dscr_size + l_ea;
2253+ }
2254+
2255+ icbflags = le16toh(icbtag->flags);
2256+ addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2257+
2258+ /* just in case we're called on an intern, its EOF */
2259+ if (addr_type == UDF_ICB_INTERN_ALLOC) {
2260+ memset(icb, 0, sizeof(struct long_ad));
2261+ *eof = 1;
2262+ return;
2263+ }
2264+
2265+ adlen = 0;
2266+ if (addr_type == UDF_ICB_SHORT_ALLOC)
2267+ adlen = sizeof(struct short_ad);
2268+ else if (addr_type == UDF_ICB_LONG_ALLOC)
2269+ adlen = sizeof(struct long_ad);
2270+
2271+ /* if offset too big, we go to the allocation extensions */
2272+ offset = slot * adlen;
2273+ extnr = -1;
2274+ while (offset >= l_ad) {
2275+ /* check if our last entry is a redirect */
2276+ if (addr_type == UDF_ICB_SHORT_ALLOC) {
2277+ short_ad = (struct short_ad *)(data_pos + l_ad-adlen);
2278+ l_icb.len = short_ad->len;
2279+ l_icb.loc.part_num = udf_node->loc.loc.part_num;
2280+ l_icb.loc.lb_num = short_ad->lb_num;
2281+ } else {
2282+ KASSERT(addr_type == UDF_ICB_LONG_ALLOC,
2283+ ("addr_type == UDF_ICB_LONG_ALLOC"));
2284+ long_ad = (struct long_ad *)(data_pos + l_ad-adlen);
2285+ l_icb = *long_ad;
2286+ }
2287+ flags = UDF_EXT_FLAGS(le32toh(l_icb.len));
2288+ if (flags != UDF_EXT_REDIRECT) {
2289+ l_ad = 0; /* force EOF */
2290+ break;
2291+ }
2292+
2293+ /* advance to next extent */
2294+ extnr++;
2295+ if (extnr >= udf_node->num_extensions) {
2296+ l_ad = 0; /* force EOF */
2297+ break;
2298+ }
2299+ offset = offset - l_ad;
2300+ ext = udf_node->ext[extnr];
2301+ dscr_size = sizeof(struct alloc_ext_entry) - 1;
2302+ l_ad = le32toh(ext->l_ad);
2303+ data_pos = (uint8_t *)ext + dscr_size;
2304+ }
2305+
2306+ /* XXX l_ad == 0 should be enough to check */
2307+ *eof = (offset >= l_ad) || (l_ad == 0);
2308+ if (*eof) {
2309+ memset(icb, 0, sizeof(struct long_ad));
2310+ return;
2311+ }
2312+
2313+ /* get the element */
2314+ if (addr_type == UDF_ICB_SHORT_ALLOC) {
2315+ short_ad = (struct short_ad *)(data_pos + offset);
2316+ icb->len = short_ad->len;
2317+ icb->loc.part_num = udf_node->loc.loc.part_num;
2318+ icb->loc.lb_num = short_ad->lb_num;
2319+ } else if (addr_type == UDF_ICB_LONG_ALLOC) {
2320+ long_ad = (struct long_ad *)(data_pos + offset);
2321+ *icb = *long_ad;
2322+ }
2323+}
2324
2325--- sys/fs/udf2/udf_filenames.c 1969-12-31 16:00:00.000000000 -0800
2326+++ updates/sys/fs/udf2/udf_filenames.c 2014-11-16 16:27:23.000000000 -0800
2327@@ -0,0 +1,276 @@
2328+/*-
2329+ * Copyright (c) 2012 Will DeVries
2330+ * All rights reserved.
2331+ *
2332+ * Redistribution and use in source and binary forms, with or without
2333+ * modification, are permitted provided that the following conditions
2334+ * are met:
2335+ * 1. Redistributions of source code must retain the above copyright
2336+ * notice, this list of conditions and the following disclaimer.
2337+ * 2. Redistributions in binary form must reproduce the above copyright
2338+ * notice, this list of conditions and the following disclaimer in the
2339+ * documentation and/or other materials provided with the distribution.
2340+ *
2341+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2342+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2343+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2344+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2345+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2346+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2347+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2348+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2349+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2350+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2351+ *
2352+ */
2353+
2354+#include <sys/param.h>
2355+#include <sys/malloc.h>
2356+#include <sys/iconv.h>
2357+#include <sys/systm.h>
2358+
2359+#include "ecma167-udf.h"
2360+#include "udf.h"
2361+#include "udf_subr.h"
2362+
2363+extern struct iconv_functions *udf2_iconv;
2364+
2365+static int
2366+udf_to_utf8(char **result, size_t *rrem, uint32_t ch)
2367+{
2368+ int n = 0;
2369+ char *rp = *result;
2370+
2371+ if ((ch & 0xFFFFFF80) == 0) {
2372+ if (*rrem < 1)
2373+ return (0);
2374+
2375+ n = 1;
2376+ rp[0] = ch & 0x7F;
2377+ } else if ((ch & 0xFFFFF800) == 0) {
2378+ if (*rrem < 2)
2379+ return (0);
2380+
2381+ n = 2;
2382+ rp[0] = 0xC0 | (ch >> 6);
2383+ rp[1] = 0x80 | (0x3F & ch);
2384+ } else if ((ch & 0xFFFF0000) == 0) {
2385+ if (*rrem < 3)
2386+ return (0);
2387+
2388+ n = 3;
2389+ rp[0] = 0xE0 | (ch >> 12);
2390+ rp[1] = 0x80 | (0x3F & (ch >> 6));
2391+ rp[2] = 0x80 | (0x3F & ch);
2392+ } else if ((ch & 0xFFE00000) == 0) {
2393+ if (*rrem < 4)
2394+ return (0);
2395+
2396+ n = 4;
2397+ rp[0] = 0xF0 | (ch >> 18);
2398+ rp[1] = 0x80 | (0x3F & (ch >> 12));
2399+ rp[2] = 0x80 | (0x3F & (ch >> 6));
2400+ rp[3] = 0x80 | (0x3F & ch);
2401+ } else {
2402+ /* do not convert points above 21 bits. */
2403+ return (0);
2404+ }
2405+
2406+ *rrem -= n;
2407+ *result += n;
2408+ return (n);
2409+}
2410+
2411+static void
2412+udf_convert_str(struct udf_mount *ump, char *result, int *result_len,
2413+ uint8_t *id, int id_len, uint16_t *index, int *needsCRC, int *extloc,
2414+ int eightbit)
2415+{
2416+ size_t chrem, rrem;
2417+ int endi, i, invalid;
2418+ uint32_t uch;
2419+ char ch[2], *rp;
2420+ const char *chp;
2421+
2422+ if (eightbit)
2423+ endi = id_len;
2424+ else
2425+ endi = (id_len - 1 > 0) ? id_len - 1 : 0;
2426+
2427+ *extloc = 0;
2428+ *needsCRC = 0;
2429+ invalid = 0;
2430+ rp = result;
2431+ rrem = *result_len - 1; /* for the null */
2432+ for (i = 0; i < endi;) {
2433+ if (eightbit) {
2434+ uch = id[i];
2435+ if (index)
2436+ index[i] = *result_len - 1 - rrem;
2437+ } else {
2438+ uch = id[i] << 8 | id[i+1];
2439+ if (index)
2440+ index[i/2] = *result_len - 1 - rrem;
2441+ }
2442+
2443+ //id[i] starts at this place in result
2444+
2445+ if (rrem == 0) {
2446+ /* no more space, we need to truncate it. */
2447+ *needsCRC = 1;
2448+ } else if (uch == 0 || uch == 0x2F) {
2449+ /* do not allow nulls or slashes */
2450+ invalid++;
2451+ } else if (ump->flags & UDFMNT_KICONV && udf2_iconv) {
2452+ /* it might be a valid character */
2453+ chrem = 2;
2454+ chp = ch;
2455+ ch[0] = uch >> 8;
2456+ ch[1] = uch & 0x00FF;
2457+ udf2_iconv->convchr(ump->iconv_d2l, &chp, &chrem, &rp,
2458+ &rrem);
2459+ if (chrem > 0) {
2460+ /* not printable or doesn't fit */
2461+ invalid++;
2462+ *needsCRC = 1;
2463+ } else
2464+ invalid = 0;
2465+ } else {
2466+ /* utf8 output */
2467+ /* it is a valid character */
2468+ if (udf_to_utf8(&rp, &rrem, uch) == 0) {
2469+ /* doesn't fit or too large */
2470+ invalid++;
2471+ *needsCRC = 1;
2472+ } else
2473+ invalid = 0;
2474+ }
2475+
2476+ if (uch == 0x002E && i != 1) {
2477+ /* record locations of periods where they occur within
2478+ 5 char of the end, but not at the end or start */
2479+ if (eightbit && id_len - 6 < i && i + 1 != endi)
2480+ *extloc = i;
2481+ else if (!eightbit && id_len - 12 < i && i + 2 != endi)
2482+ *extloc = i;
2483+ }
2484+
2485+ if (rrem > 0 && invalid == 1) {
2486+ uch = 0x5F; // underscore
2487+
2488+ /* if the result doesn't have space this may not fit */
2489+ if (ump->flags & UDFMNT_KICONV && udf2_iconv) {
2490+ chrem = 2;
2491+ chp = ch;
2492+ ch[0] = uch >> 8;
2493+ ch[1] = uch & 0x00FF;
2494+ udf2_iconv->convchr(ump->iconv_d2l, &chp,
2495+ &chrem, &rp, &rrem);
2496+ } else
2497+ udf_to_utf8(&rp, &rrem, uch);
2498+
2499+ invalid++;
2500+ }
2501+
2502+ if (eightbit)
2503+ i++;
2504+ else
2505+ i += 2;
2506+ }
2507+
2508+ // this is the null placement
2509+ if (index) {
2510+ if (eightbit)
2511+ index[i] = *result_len - 1 - rrem;
2512+ else
2513+ index[i/2] = *result_len - 1 - rrem;
2514+ }
2515+
2516+ *rp = '\0';
2517+ *result_len -= rrem;
2518+}
2519+
2520+/*
2521+ * The result_len is assumed to include the zero.
2522+ * id_len - 1 is character, not \0.
2523+ */
2524+void
2525+udf_to_unix_name(struct udf_mount *ump, char *result, int result_len,
2526+ uint8_t *id, int id_len)
2527+{
2528+ int crclen, eightbit, extlen, extloc, i, junkloc, mainlen, maxmainlen;
2529+ int maxnpart, needsCRC;
2530+ uint16_t crcsum, *index;
2531+ char *crc, crcbuf[6], *ext;
2532+
2533+ if (id[0] != 8 && id[0] != 16) {
2534+ /* this is either invalid or an empty string */
2535+ result_len = 0;
2536+ return;
2537+ }
2538+
2539+ if (id[0] == 8)
2540+ eightbit = 1;
2541+ else
2542+ eightbit = 0;
2543+
2544+ /* remove marker byte from start of string */
2545+ id++;
2546+ id_len--;
2547+
2548+ index = malloc((id_len + 1) * sizeof(uint16_t), M_UDFTEMP, M_WAITOK);
2549+
2550+ mainlen = result_len;
2551+ udf_convert_str(ump, result, &mainlen, id, id_len, index, &needsCRC,
2552+ &extloc, eightbit);
2553+
2554+ if (needsCRC) {
2555+ if (extloc) {
2556+ //build ext
2557+ ext = malloc(result_len, M_UDFTEMP, M_WAITOK | M_ZERO);
2558+ extlen = result_len;
2559+ udf_convert_str(ump, ext, &extlen, id + extloc,
2560+ id_len - extloc, NULL, &needsCRC, &junkloc,
2561+ eightbit);
2562+ } else {
2563+ ext = NULL;
2564+ extlen = 1;
2565+ }
2566+
2567+ crcsum = udf_cksum(id, id_len);
2568+ crcbuf[0] = '#';
2569+ crcbuf[1] = "0123456789ABCDEF"[(crcsum >> 12) & 0x000F];
2570+ crcbuf[2] = "0123456789ABCDEF"[(crcsum >> 8) & 0x000F];
2571+ crcbuf[3] = "0123456789ABCDEF"[(crcsum >> 4) & 0x000F];
2572+ crcbuf[4] = "0123456789ABCDEF"[crcsum & 0x000F];
2573+ crcbuf[5] = '\0';
2574+
2575+ crc = malloc(result_len, M_UDFTEMP, M_WAITOK | M_ZERO);
2576+ crclen = result_len;
2577+ udf_convert_str(ump, crc, &crclen, crcbuf, 5, NULL, &needsCRC,
2578+ &junkloc, 1);
2579+
2580+ // find index of last character to be written into filename.
2581+ maxnpart = result_len - crclen - extlen - 3;
2582+ if (extloc)
2583+ maxmainlen = (eightbit) ? extloc : extloc / 2;
2584+ else
2585+ maxmainlen = (eightbit) ? id_len : id_len / 2;
2586+
2587+ for (i = 0; i < maxmainlen; i++)
2588+ if (index[i + 1] - 1 > maxnpart)
2589+ break;
2590+ i--;
2591+
2592+ memcpy(result + index[i + 1], crc, crclen - 1);
2593+ if (ext)
2594+ memcpy(result + index[i + 1] + crclen - 1, ext, extlen);
2595+ result[index[i + 1] + crclen + extlen - 2] = '\0';
2596+
2597+ if (ext)
2598+ free(ext, M_UDFTEMP);
2599+ free(crc, M_UDFTEMP);
2600+ }
2601+
2602+ free(index, M_UDFTEMP);
2603+}
2604
2605--- sys/fs/udf2/udf_iconv.c 1969-12-31 16:00:00.000000000 -0800
2606+++ updates/sys/fs/udf2/udf_iconv.c 2014-11-16 16:27:23.000000000 -0800
2607@@ -0,0 +1,36 @@
2608+/*-
2609+ * Copyright (c) 2003 Ryuichiro Imura
2610+ * All rights reserved.
2611+ *
2612+ * Redistribution and use in source and binary forms, with or without
2613+ * modification, are permitted provided that the following conditions
2614+ * are met:
2615+ * 1. Redistributions of source code must retain the above copyright
2616+ * notice, this list of conditions and the following disclaimer.
2617+ * 2. Redistributions in binary form must reproduce the above copyright
2618+ * notice, this list of conditions and the following disclaimer in the
2619+ * documentation and/or other materials provided with the distribution.
2620+ *
2621+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2622+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2623+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2624+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2625+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2626+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2627+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2628+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2629+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2630+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2631+ * SUCH DAMAGE.
2632+ */
2633+
2634+#include <sys/cdefs.h>
2635+__FBSDID("$FreeBSD: src/sys/fs/udf/udf_iconv.c,v 1.1 2003/11/05 06:56:08 scottl Exp $");
2636+
2637+#include <sys/param.h>
2638+#include <sys/iconv.h>
2639+#include <sys/kernel.h>
2640+#include <sys/module.h>
2641+#include <sys/mount.h>
2642+
2643+VFS_DECLARE_ICONV(udf2);
2644
2645--- sys/fs/udf2/udf_osta.c 1969-12-31 16:00:00.000000000 -0800
2646+++ updates/sys/fs/udf2/udf_osta.c 2014-11-16 16:27:23.000000000 -0800
2647@@ -0,0 +1,92 @@
2648+/*
2649+ * Various routines from the OSTA 2.01 specs. Copyrights are included with
2650+ * each code segment. Slight whitespace modifications have been made for
2651+ * formatting purposes. Typos/bugs have been fixed.
2652+ *
2653+ * Copyright to this code held by AT&T.
2654+ */
2655+
2656+#include "udf_osta.h"
2657+
2658+/*
2659+ * CRC 010041
2660+ */
2661+static uint16_t crc_table[256] = {
2662+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
2663+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
2664+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
2665+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
2666+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
2667+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
2668+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
2669+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
2670+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
2671+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
2672+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
2673+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
2674+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
2675+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
2676+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
2677+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
2678+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
2679+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
2680+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
2681+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
2682+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
2683+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
2684+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
2685+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
2686+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
2687+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
2688+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
2689+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
2690+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
2691+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
2692+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
2693+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
2694+};
2695+
2696+uint16_t
2697+udf_cksum(unsigned char *s, int n)
2698+{
2699+ uint16_t crc = 0;
2700+
2701+ while (n-- > 0)
2702+ crc = crc_table[(crc >> 8 ^ *s++) & 0xff] ^ (crc << 8);
2703+
2704+ return (crc);
2705+}
2706+
2707+/*
2708+ * Calculates a 16-bit checksum of the Implementation Use
2709+ * Extended Attribute header or Application Use Extended Attribute
2710+ * header. The fields AttributeType through ImplementationIdentifier
2711+ * (or ApplicationIdentifier) inclusively represent the
2712+ * data covered by the checksum (48 bytes).
2713+ *
2714+ */
2715+uint16_t udf_ea_cksum(uint8_t *data) {
2716+ int count;
2717+ uint16_t checksum = 0;
2718+
2719+ for (count = 0; count < 48; count++)
2720+ checksum += *data++;
2721+
2722+ return (checksum);
2723+}
2724+
2725+#ifdef MAIN
2726+unsigned char bytes[] = { 0x70, 0x6A, 0x77 };
2727+
2728+main(void)
2729+{
2730+ unsigned short x;
2731+
2732+ x = udf_cksum(bytes, sizeof bytes);
2733+ printf("checksum: calculated=%4.4x, correct=%4.4x\en", x, 0x3299);
2734+
2735+ exit(0);
2736+}
2737+#endif
2738+
2739+
2740
2741--- sys/fs/udf2/udf_osta.h 1969-12-31 16:00:00.000000000 -0800
2742+++ updates/sys/fs/udf2/udf_osta.h 2014-11-16 16:27:23.000000000 -0800
2743@@ -0,0 +1,14 @@
2744+/*
2745+ * Prototypes for the OSTA functions
2746+ */
2747+
2748+
2749+#ifndef _FS_UDF_OSTA_H_
2750+#define _FS_UDF_OSTA_H_
2751+
2752+#include <sys/types.h>
2753+
2754+unsigned short udf_cksum(unsigned char *, int);
2755+uint16_t udf_ea_cksum(uint8_t *data);
2756+
2757+#endif /* _FS_UDF_OSTA_H_ */
2758
2759--- sys/fs/udf2/udf_readwrite.c 1969-12-31 16:00:00.000000000 -0800
2760+++ updates/sys/fs/udf2/udf_readwrite.c 2014-11-16 16:27:23.000000000 -0800
2761@@ -0,0 +1,234 @@
2762+/*-
2763+ * Copyright (c) 2012 Will DeVries
2764+ * Copyright (c) 2007, 2008 Reinoud Zandijk
2765+ * All rights reserved.
2766+ *
2767+ * Redistribution and use in source and binary forms, with or without
2768+ * modification, are permitted provided that the following conditions
2769+ * are met:
2770+ * 1. Redistributions of source code must retain the above copyright
2771+ * notice, this list of conditions and the following disclaimer.
2772+ * 2. Redistributions in binary form must reproduce the above copyright
2773+ * notice, this list of conditions and the following disclaimer in the
2774+ * documentation and/or other materials provided with the distribution.
2775+ *
2776+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2777+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2778+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2779+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2780+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2781+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2782+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2783+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2784+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2785+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2786+ *
2787+ */
2788+
2789+#include <sys/cdefs.h>
2790+#include <sys/endian.h>
2791+#include <sys/param.h>
2792+#include <sys/systm.h>
2793+#include <sys/vnode.h>
2794+#include <sys/buf.h>
2795+#include <sys/malloc.h>
2796+
2797+#include "ecma167-udf.h"
2798+#include "udf.h"
2799+#include "udf_subr.h"
2800+
2801+
2802+static int udf_read_phys_sectors(struct udf_mount *ump, int what,
2803+ void *blob, uint32_t start, uint32_t sectors);
2804+
2805+/*
2806+ * Set of generic descriptor readers and writers and their helper functions.
2807+ * Descriptors inside `logical space' i.e. inside logically mapped partitions
2808+ * can never be longer than one logical sector.
2809+ *
2810+ * NOTE that these functions *can* be used by the sheduler backends to read
2811+ * node descriptors too.
2812+ *
2813+ * For reading, the size of allocated piece is returned in multiple of sector
2814+ * size due to udf_calc_udf_malloc_size().
2815+ */
2816+int
2817+udf_read_node(struct udf_node *unode, uint8_t *blob, off_t start, int length)
2818+{
2819+ struct vnode *devvp = unode->ump->devvp;
2820+ struct buf *bp;
2821+ uint64_t file_size, lsect;
2822+ int addr_type, exttype, error, icbflags;
2823+ uint32_t blkinsect, fileblk, fileblkoff, numb, numlsect, sector_size;
2824+ uint8_t *pos;
2825+
2826+ error = 0;
2827+ sector_size = unode->ump->sector_size;
2828+ blkinsect = sector_size / DEV_BSIZE;
2829+
2830+ if (unode->fe != NULL) {
2831+ pos = &unode->fe->data[0] + le32toh(unode->fe->l_ea);
2832+ icbflags = le16toh(unode->fe->icbtag.flags);
2833+ file_size = le64toh(unode->fe->inf_len);
2834+ } else {
2835+ pos = &unode->efe->data[0] + le32toh(unode->efe->l_ea);
2836+ icbflags = le16toh(unode->efe->icbtag.flags);
2837+ file_size = le64toh(unode->efe->inf_len);
2838+ }
2839+
2840+ length = min(file_size - start, length);
2841+ fileblk = start / sector_size;
2842+ fileblkoff = start % sector_size;
2843+
2844+ addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
2845+ if (addr_type == UDF_ICB_INTERN_ALLOC) {
2846+ numb = min(length, file_size - fileblkoff);
2847+ memcpy(blob, pos + fileblkoff, numb);
2848+ return (error);
2849+ }
2850+
2851+ while (length) {
2852+ error = udf_bmap_translate(unode, fileblk, &exttype, &lsect,
2853+ &numlsect);
2854+ if (error != 0)
2855+ return (error);
2856+
2857+ if (exttype == UDF_TRAN_ZERO) {
2858+ numb = min(length, sector_size * numlsect - fileblkoff);
2859+ memset(blob, 0, numb);
2860+ length -= numb;
2861+ blob += numb;
2862+ fileblkoff = 0;
2863+ } else if (exttype == UDF_TRAN_INTERN)
2864+ return (EDOOFUS);
2865+ else {
2866+ while (numlsect > 0) {
2867+ error = bread(devvp, lsect * blkinsect,
2868+ sector_size, NOCRED, &bp);
2869+ if (error != 0) {
2870+ if (buf != NULL)
2871+ brelse(bp);
2872+ return (error);
2873+ }
2874+
2875+ numb = min(length, sector_size - fileblkoff);
2876+ bcopy(bp->b_data + fileblkoff, blob, numb);
2877+ brelse(bp);
2878+ bp = NULL;
2879+
2880+ blob += numb;
2881+ length -= numb;
2882+ lsect++;
2883+ numlsect--;
2884+ fileblkoff = 0;
2885+ }
2886+ }
2887+
2888+ fileblk += numlsect;
2889+ }
2890+
2891+ return (0);
2892+}
2893+
2894+/* SYNC reading of n blocks from specified sector */
2895+static int
2896+udf_read_phys_sectors(struct udf_mount *ump, int what, void *blob,
2897+ uint32_t start, uint32_t sectors)
2898+{
2899+ struct vnode *devvp = ump->devvp;
2900+ struct buf *bp;
2901+ int error = 0;
2902+ uint32_t blks, sector_size;
2903+
2904+ sector_size = ump->sector_size;
2905+ blks = sector_size / DEV_BSIZE;
2906+
2907+ while (sectors > 0 && error == 0) {
2908+ error = bread(devvp, start * blks, sector_size, NOCRED, &bp);
2909+ if (error != 0) {
2910+ if (buf != NULL)
2911+ brelse(bp);
2912+ return (error);
2913+ }
2914+
2915+ bcopy(bp->b_data, blob, sector_size);
2916+ brelse(bp);
2917+ bp = NULL;
2918+
2919+ blob = (void *)((uint8_t *)blob + sector_size);
2920+ start++;
2921+ sectors--;
2922+ }
2923+
2924+ return (0);
2925+}
2926+
2927+/* synchronous generic descriptor read */
2928+int
2929+udf_read_phys_dscr(struct udf_mount *ump, uint32_t sector,
2930+ struct malloc_type *mtype, union dscrptr **dstp)
2931+{
2932+ union dscrptr *dst, *new_dst;
2933+ int dscrlen, error, i, sectors, sector_size;
2934+ uint8_t *pos;
2935+
2936+ sector_size = ump->sector_size;
2937+
2938+ *dstp = dst = NULL;
2939+ dscrlen = sector_size;
2940+
2941+ /* read initial piece */
2942+ dst = malloc(sector_size, mtype, M_WAITOK);
2943+ error = udf_read_phys_sectors(ump, UDF_C_DSCR, dst, sector, 1);
2944+
2945+ if (error == 0) {
2946+ /* check if its a valid tag */
2947+ error = udf_check_tag(dst);
2948+ if (error != 0) {
2949+ /* check if its an empty block */
2950+ pos = (uint8_t *)dst;
2951+ for (i = 0; i < sector_size; i++, pos++)
2952+ if (*pos)
2953+ break;
2954+
2955+ if (i == sector_size) {
2956+ /* return no error but with no dscrptr */
2957+ /* dispose first block */
2958+ free(dst, mtype);
2959+ return (0);
2960+ }
2961+ }
2962+ /* calculate descriptor size */
2963+ dscrlen = udf_tagsize(dst, sector_size);
2964+ }
2965+
2966+ if (!error && (dscrlen > sector_size)) {
2967+ /*
2968+ * Read the rest of descriptor. Since it is only used at mount
2969+ * time its overdone to define and use a specific udf_intbreadn
2970+ * for this alone.
2971+ */
2972+
2973+ new_dst = realloc(dst, dscrlen, mtype, M_WAITOK);
2974+ if (new_dst == NULL) {
2975+ free(dst, mtype);
2976+ return (ENOMEM);
2977+ }
2978+ dst = new_dst;
2979+
2980+ sectors = (dscrlen + sector_size - 1) / sector_size;
2981+
2982+ pos = (uint8_t *)dst + sector_size;
2983+ error = udf_read_phys_sectors(ump, UDF_C_DSCR, pos, sector + 1,
2984+ sectors - 1);
2985+ }
2986+ if (error == 0)
2987+ error = udf_check_tag_payload(dst, dscrlen);
2988+ if (error && dst) {
2989+ free(dst, mtype);
2990+ dst = NULL;
2991+ }
2992+ *dstp = dst;
2993+
2994+ return (error);
2995+}
2996
2997--- sys/fs/udf2/udf_subr.c 1969-12-31 16:00:00.000000000 -0800
2998+++ updates/sys/fs/udf2/udf_subr.c 2014-11-16 16:27:23.000000000 -0800
2999@@ -0,0 +1,1929 @@
3000+/*-
3001+ * Copyright (c) 2012 Will DeVries
3002+ * Copyright (c) 2006, 2008 Reinoud Zandijk
3003+ * All rights reserved.
3004+ *
3005+ * Redistribution and use in source and binary forms, with or without
3006+ * modification, are permitted provided that the following conditions
3007+ * are met:
3008+ * 1. Redistributions of source code must retain the above copyright
3009+ * notice, this list of conditions and the following disclaimer.
3010+ * 2. Redistributions in binary form must reproduce the above copyright
3011+ * notice, this list of conditions and the following disclaimer in the
3012+ * documentation and/or other materials provided with the distribution.
3013+ *
3014+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3015+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3016+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3017+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3018+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3019+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3020+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3021+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3022+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3023+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3024+ *
3025+ */
3026+
3027+
3028+#include <sys/cdefs.h>
3029+#include <sys/endian.h>
3030+#include <sys/param.h>
3031+#include <sys/systm.h>
3032+#include <sys/vnode.h>
3033+#include <sys/malloc.h>
3034+#include <sys/stat.h>
3035+#include <sys/mount.h>
3036+#include <sys/iconv.h>
3037+
3038+#include "ecma167-udf.h"
3039+#include "udf.h"
3040+#include "udf_subr.h"
3041+
3042+#define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
3043+
3044+static int udf_leapyear(int year);
3045+
3046+/*
3047+ * Check if the blob starts with a good UDF tag. Tags are protected by a
3048+ * checksum over the reader except one byte at position 4 that is the checksum
3049+ * itself.
3050+ */
3051+int
3052+udf_check_tag(void *blob)
3053+{
3054+ struct desc_tag *tag = blob;
3055+ uint8_t cnt, *pos, sum;
3056+
3057+ /* check TAG header checksum */
3058+ pos = (uint8_t *)tag;
3059+ sum = 0;
3060+
3061+ for (cnt = 0; cnt < 16; cnt++) {
3062+ if (cnt != 4)
3063+ sum += *pos;
3064+ pos++;
3065+ }
3066+ if (sum != tag->cksum) {
3067+ /* bad tag header checksum; this is not a valid tag */
3068+ return (EINVAL);
3069+ }
3070+
3071+ return (0);
3072+}
3073+
3074+/*
3075+ * check tag payload will check descriptor CRC as specified.
3076+ * If the descriptor is too long, it will return EIO otherwise EINVAL.
3077+ */
3078+int
3079+udf_check_tag_payload(void *blob, uint32_t max_length)
3080+{
3081+ struct desc_tag *tag = blob;
3082+ uint16_t crc, crc_len;
3083+
3084+ crc_len = le16toh(tag->desc_crc_len);
3085+
3086+ /* check payload CRC if applicable */
3087+ if (crc_len == 0)
3088+ return (0);
3089+
3090+ if (crc_len > max_length)
3091+ return (EIO);
3092+
3093+ crc = udf_cksum(((uint8_t *)tag) + UDF_DESC_TAG_LENGTH, crc_len);
3094+ if (crc != le16toh(tag->desc_crc)) {
3095+ /* bad payload CRC; this is a broken tag */
3096+ return (EINVAL);
3097+ }
3098+
3099+ return (0);
3100+}
3101+
3102+#if 0
3103+void
3104+udf_validate_tag_sum(void *blob)
3105+{
3106+ struct desc_tag *tag = blob;
3107+ uint8_t cnt, *pos, sum;
3108+
3109+ /* calculate TAG header checksum */
3110+ pos = (uint8_t *)tag;
3111+ sum = 0;
3112+
3113+ for (cnt = 0; cnt < 16; cnt++) {
3114+ if (cnt != 4) sum += *pos;
3115+ pos++;
3116+ }
3117+ tag->cksum = sum; /* 8 bit */
3118+}
3119+
3120+/* assumes sector number of descriptor to be saved already present */
3121+void
3122+udf_validate_tag_and_crc_sums(void *blob)
3123+{
3124+ struct desc_tag *tag = blob;
3125+ uint16_t crc, crc_len;
3126+ uint8_t *btag = (uint8_t *)tag;
3127+
3128+ crc_len = le16toh(tag->desc_crc_len);
3129+
3130+ /* check payload CRC if applicable */
3131+ if (crc_len > 0) {
3132+ crc = udf_cksum(btag + UDF_DESC_TAG_LENGTH, crc_len);
3133+ tag->desc_crc = htole16(crc);
3134+ }
3135+
3136+ /* calculate TAG header checksum */
3137+ udf_validate_tag_sum(blob);
3138+}
3139+#endif
3140+
3141+/*
3142+ * XXX note the different semantics from udfclient: for FIDs it still rounds
3143+ * up to sectors. Use udf_fidsize() for a correct length.
3144+ */
3145+int
3146+udf_tagsize(union dscrptr *dscr, uint32_t lb_size)
3147+{
3148+ uint32_t elmsz, num_lb, size, tag_id;
3149+
3150+ tag_id = le16toh(dscr->tag.id);
3151+
3152+ switch (tag_id) {
3153+ case TAGID_LOGVOL:
3154+ size = sizeof(struct logvol_desc) - 1;
3155+ size += le32toh(dscr->lvd.mt_l);
3156+ break;
3157+ case TAGID_UNALLOC_SPACE:
3158+ elmsz = sizeof(struct extent_ad);
3159+ size = sizeof(struct unalloc_sp_desc) - elmsz;
3160+ size += le32toh(dscr->usd.alloc_desc_num) * elmsz;
3161+ break;
3162+ case TAGID_FID:
3163+ size = UDF_FID_SIZE + dscr->fid.l_fi + le16toh(dscr->fid.l_iu);
3164+ size = (size + 3) & ~3;
3165+ break;
3166+ case TAGID_LOGVOL_INTEGRITY:
3167+ size = sizeof(struct logvol_int_desc) - sizeof(uint32_t);
3168+ size += le32toh(dscr->lvid.l_iu);
3169+ size += (2 * le32toh(dscr->lvid.num_part) * sizeof(uint32_t));
3170+ break;
3171+ case TAGID_SPACE_BITMAP:
3172+ size = sizeof(struct space_bitmap_desc) - 1;
3173+ size += le32toh(dscr->sbd.num_bytes);
3174+ break;
3175+ case TAGID_SPARING_TABLE:
3176+ elmsz = sizeof(struct spare_map_entry);
3177+ size = sizeof(struct udf_sparing_table) - elmsz;
3178+ size += le16toh(dscr->spt.rt_l) * elmsz;
3179+ break;
3180+ case TAGID_FENTRY:
3181+ size = sizeof(struct file_entry);
3182+ size += le32toh(dscr->fe.l_ea) + le32toh(dscr->fe.l_ad)-1;
3183+ break;
3184+ case TAGID_EXTFENTRY:
3185+ size = sizeof(struct extfile_entry);
3186+ size += le32toh(dscr->efe.l_ea) + le32toh(dscr->efe.l_ad)-1;
3187+ break;
3188+ case TAGID_FSD:
3189+ size = sizeof(struct fileset_desc);
3190+ break;
3191+ default:
3192+ size = sizeof(union dscrptr);
3193+ break;
3194+ }
3195+
3196+ if ((size == 0) || (lb_size == 0))
3197+ return (0);
3198+
3199+ if (lb_size == 1)
3200+ return (size);
3201+
3202+ /* round up in sectors */
3203+ num_lb = (size + lb_size -1) / lb_size;
3204+
3205+ return (num_lb * lb_size);
3206+}
3207+
3208+int
3209+udf_fidsize(struct fileid_desc *fid)
3210+{
3211+ uint32_t size;
3212+
3213+ if (le16toh(fid->tag.id) != TAGID_FID)
3214+ panic("got udf_fidsize on non FID\n");
3215+
3216+ size = UDF_FID_SIZE + fid->l_fi + le16toh(fid->l_iu);
3217+ size = (size + 3) & ~3;
3218+
3219+ /* We know this value will fit in an int. */
3220+ return (size);
3221+}
3222+
3223+void
3224+udf_lock_node(struct udf_node *udf_node, int flag, char const *fname,
3225+ const int lineno)
3226+{
3227+#if 0
3228+ int ret;
3229+
3230+ mutex_enter(&udf_node->node_mutex);
3231+ /* wait until free */
3232+ while (udf_node->i_flags & IN_LOCKED) {
3233+ ret = cv_timedwait(&udf_node->node_lock, &udf_node->node_mutex, hz/8);
3234+ /* TODO check if we should return error; abort */
3235+ if (ret == EWOULDBLOCK) {
3236+ DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block "
3237+ "wanted at %s:%d, previously locked at %s:%d\n",
3238+ udf_node, fname, lineno,
3239+ udf_node->lock_fname, udf_node->lock_lineno));
3240+ }
3241+ }
3242+ /* grab */
3243+ udf_node->i_flags |= IN_LOCKED | flag;
3244+ /* debug */
3245+ udf_node->lock_fname = fname;
3246+ udf_node->lock_lineno = lineno;
3247+
3248+ mutex_exit(&udf_node->node_mutex);
3249+#endif
3250+}
3251+
3252+void
3253+udf_unlock_node(struct udf_node *udf_node, int flag)
3254+{
3255+#if 0
3256+ mutex_enter(&udf_node->node_mutex);
3257+ udf_node->i_flags &= ~(IN_LOCKED | flag);
3258+ cv_broadcast(&udf_node->node_lock);
3259+ mutex_exit(&udf_node->node_mutex);
3260+#endif
3261+}
3262+
3263+static int
3264+udf_read_anchor(struct udf_mount *ump, uint32_t sector, struct anchor_vdp **dst)
3265+{
3266+ int error;
3267+
3268+ error = udf_read_phys_dscr(ump, sector, M_UDFTEMP,
3269+ (union dscrptr **)dst);
3270+ if (error == 0) {
3271+ /* blank terminator blocks are not allowed here */
3272+ if (*dst == NULL)
3273+ return (ENOENT);
3274+ if (le16toh((*dst)->tag.id) != TAGID_ANCHOR) {
3275+ error = ENOENT;
3276+ free(*dst, M_UDFTEMP);
3277+ *dst = NULL;
3278+ }
3279+ }
3280+
3281+ return (error);
3282+}
3283+
3284+int
3285+udf_read_anchors(struct udf_mount *ump)
3286+{
3287+ struct anchor_vdp **anchorsp;
3288+ int first_anchor, anch, error, ok;
3289+ uint32_t positions[4], session_end, session_start;
3290+
3291+ session_start = ump->session_start;
3292+ session_end = ump->session_end;
3293+
3294+ /* read anchors start+256, start+512, end-256, end */
3295+ positions[0] = session_start + 256;
3296+ positions[1] = session_end - 256;
3297+ positions[2] = session_end;
3298+ /* XXX shouldn't +512 be prefered above +256 for compat with Roxio CD */
3299+ positions[3] = session_start + 512; /* [UDF 2.60/6.11.2] */
3300+
3301+ ok = 0;
3302+ anchorsp = ump->anchors;
3303+ first_anchor = 0;
3304+ if (ump->first_trackblank)
3305+ first_anchor = 1;
3306+ for (anch = first_anchor; anch < 4; anch++) {
3307+ if (positions[anch] <= session_end) {
3308+ error = udf_read_anchor(ump, positions[anch], anchorsp);
3309+ if (error == 0) {
3310+ anchorsp++;
3311+ ok++;
3312+ }
3313+ }
3314+ }
3315+
3316+ return (ok);
3317+}
3318+
3319+/* we dont try to be smart; we just record the parts */
3320+#define UDF_UPDATE_DSCR(name, dscr) \
3321+ if (name) \
3322+ free(name, M_UDFTEMP); \
3323+ name = dscr;
3324+
3325+static int
3326+udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr)
3327+{
3328+ struct part_desc *part;
3329+ uint16_t phys_part, raw_phys_part;
3330+
3331+ switch (le16toh(dscr->tag.id)) {
3332+ case TAGID_PRI_VOL: /* primary partition */
3333+ UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd);
3334+ break;
3335+ case TAGID_LOGVOL: /* logical volume */
3336+ UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd);
3337+ break;
3338+ case TAGID_UNALLOC_SPACE: /* unallocated space */
3339+ UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd);
3340+ break;
3341+ case TAGID_IMP_VOL: /* implementation */
3342+ /* XXX do we care about multiple impl. descr ? */
3343+ UDF_UPDATE_DSCR(ump->implementation, &dscr->ivd);
3344+ break;
3345+ case TAGID_PARTITION: /* physical partition */
3346+ /* not much use if its not allocated */
3347+ if ((le16toh(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
3348+ free(dscr, M_UDFTEMP);
3349+ break;
3350+ }
3351+
3352+ /*
3353+ * BUGALERT: some rogue implementations use random physical
3354+ * partition numbers to break other implementations so lookup
3355+ * the number.
3356+ */
3357+ raw_phys_part = le16toh(dscr->pd.part_num);
3358+ for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
3359+ part = ump->partitions[phys_part];
3360+ if (part == NULL)
3361+ break;
3362+ if (le16toh(part->part_num) == raw_phys_part)
3363+ break;
3364+ }
3365+ if (phys_part == UDF_PARTITIONS) {
3366+ free(dscr, M_UDFTEMP);
3367+ return (EINVAL);
3368+ }
3369+
3370+ UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd);
3371+ break;
3372+ case TAGID_VOL: /* volume space extender; rare */
3373+ free(dscr, M_UDFTEMP);
3374+ break;
3375+ default:
3376+ free(dscr, M_UDFTEMP);
3377+ }
3378+
3379+ return (0);
3380+}
3381+#undef UDF_UPDATE_DSCR
3382+
3383+static int
3384+udf_read_vds_extent(struct udf_mount *ump, uint32_t loc, uint32_t len)
3385+{
3386+ union dscrptr *dscr;
3387+ int error;
3388+ uint32_t dscr_size, sector_size;
3389+
3390+ sector_size = ump->sector_size;
3391+
3392+ /* loc is sectornr, len is in bytes */
3393+ error = EIO;
3394+ while (len > 0) {
3395+ error = udf_read_phys_dscr(ump, loc, M_UDFTEMP, &dscr);
3396+ if (error != 0) {
3397+ if (!dscr)
3398+ free(dscr, M_UDFTEMP);
3399+ return (error);
3400+ }
3401+
3402+ /* blank block is a terminator */
3403+ if (dscr == NULL)
3404+ return (0);
3405+
3406+ /* TERM descriptor is a terminator */
3407+ if (le16toh(dscr->tag.id) == TAGID_TERM) {
3408+ free(dscr, M_UDFTEMP);
3409+ return (0);
3410+ }
3411+
3412+ /* process all others */
3413+ dscr_size = udf_tagsize(dscr, sector_size);
3414+
3415+ /* dscr is assigned into ump */
3416+ error = udf_process_vds_descriptor(ump, dscr);
3417+ if (error != 0)
3418+ break;
3419+
3420+ len -= dscr_size;
3421+ loc += dscr_size / sector_size;
3422+ }
3423+
3424+ return (error);
3425+}
3426+
3427+int
3428+udf_read_vds_space(struct udf_mount *ump)
3429+{
3430+ /* struct udf_args *args = &ump->mount_args; */
3431+ struct anchor_vdp *anchor, *anchor2;
3432+ size_t size;
3433+ int error;
3434+ uint32_t main_len, main_loc, reserve_len, reserve_loc;
3435+
3436+ /*
3437+ * read in VDS space provided by the anchors; if one descriptor read
3438+ * fails, try the mirror sector.
3439+ *
3440+ * check if 2nd anchor is different from 1st; if so, go for 2nd. This
3441+ * avoids the `compatibility features' of DirectCD that may confuse
3442+ * stuff completely.
3443+ */
3444+
3445+ anchor = ump->anchors[0];
3446+ anchor2 = ump->anchors[1];
3447+
3448+ if (anchor2) {
3449+ size = sizeof(struct extent_ad);
3450+ if (memcmp(&anchor->main_vds_ex, &anchor2->main_vds_ex, size))
3451+ anchor = anchor2;
3452+ /* reserve is specified to be a literal copy of main */
3453+ }
3454+
3455+ main_loc = le32toh(anchor->main_vds_ex.loc);
3456+ main_len = le32toh(anchor->main_vds_ex.len);
3457+
3458+ reserve_loc = le32toh(anchor->reserve_vds_ex.loc);
3459+ reserve_len = le32toh(anchor->reserve_vds_ex.len);
3460+
3461+ error = udf_read_vds_extent(ump, main_loc, main_len);
3462+ if (error != 0) {
3463+ printf("UDF mount: reading in reserve VDS extent\n");
3464+ error = udf_read_vds_extent(ump, reserve_loc, reserve_len);
3465+ }
3466+
3467+ return (error);
3468+}
3469+
3470+/*
3471+ * Read in the logical volume integrity sequence pointed to by our logical
3472+ * volume descriptor. Its a sequence that can be extended using fields in the
3473+ * integrity descriptor itself. On sequential media only one is found, on
3474+ * rewritable media a sequence of descriptors can be found as a form of
3475+ * history keeping and on non sequential write-once media the chain is vital
3476+ * to allow more and more descriptors to be written. The last descriptor
3477+ * written in an extent needs to claim space for a new extent.
3478+ *
3479+ * Note: this may not return in the media is malformed.
3480+ */
3481+static int
3482+udf_retrieve_lvint(struct udf_mount *ump)
3483+{
3484+ union dscrptr *dscr;
3485+ struct logvol_int_desc *lvint;
3486+ int dscr_type, error;
3487+ uint32_t lbnum, lb_size, len;
3488+
3489+ lb_size = le32toh(ump->logical_vol->lb_size);
3490+ len = le32toh(ump->logical_vol->integrity_seq_loc.len);
3491+ lbnum = le32toh(ump->logical_vol->integrity_seq_loc.loc);
3492+
3493+ lvint = NULL;
3494+ dscr = NULL;
3495+ error = 0;
3496+ while (len > 0) {
3497+ /* read in our integrity descriptor */
3498+ error = udf_read_phys_dscr(ump, lbnum, M_UDFTEMP, &dscr);
3499+ if (error == 0) {
3500+ if (dscr == NULL)
3501+ break; /* empty terminates */
3502+ dscr_type = le16toh(dscr->tag.id);
3503+ if (dscr_type == TAGID_TERM)
3504+ break; /* clean terminator */
3505+ if (dscr_type != TAGID_LOGVOL_INTEGRITY) {
3506+ printf("UDF mount: Invalid logical volume "
3507+ "integrity sequence entry found.\n");
3508+#if 0
3509+ /* fatal... corrupt disc */
3510+ error = ENOENT;
3511+#endif
3512+ break;
3513+ }
3514+ if (lvint)
3515+ free(lvint, M_UDFTEMP);
3516+ lvint = &dscr->lvid;
3517+ dscr = NULL;
3518+ } /* else hope for the best... maybe the next is ok */
3519+
3520+ /* proceed sequential */
3521+ lbnum += 1;
3522+ len -= lb_size;
3523+
3524+ /* are we linking to a new piece? */
3525+ if (dscr && lvint->next_extent.len) {
3526+ len = le32toh(lvint->next_extent.len);
3527+ lbnum = le32toh(lvint->next_extent.loc);
3528+ }
3529+ }
3530+
3531+ /* clean up the mess, esp. when there is an error */
3532+ if (dscr)
3533+ free(dscr, M_UDFTEMP);
3534+
3535+ if (error != 0 && lvint != NULL) {
3536+ free(lvint, M_UDFTEMP);
3537+ lvint = NULL;
3538+ } else if (lvint == NULL) {
3539+ printf("UDF mount: No logical volume integrity sequence entries"
3540+ " found.\n");
3541+ error = ENOENT;
3542+ }
3543+
3544+ ump->logvol_integrity = lvint;
3545+
3546+ return (error);
3547+}
3548+
3549+/*
3550+ * Checks if ump's vds information is correct and complete
3551+ */
3552+int
3553+udf_process_vds(struct udf_mount *ump) {
3554+ /* struct udf_args *args = &ump->mount_args; */
3555+ union udf_pmap *mapping;
3556+ struct logvol_int_desc *lvint;
3557+ struct part_desc *part;
3558+ struct udf_logvol_info *lvinfo;
3559+ int error, log_part, phys_part, pmap_size, pmap_stype, pmap_type;
3560+ int len, n_meta, n_phys, n_spar, n_virt, raw_phys_part;
3561+ uint32_t mt_l, n_pm;
3562+ char *domain_name, *map_name; /* bits[128]; */
3563+ const char *check_name;
3564+ uint8_t *pmap_pos;
3565+
3566+ /* we need at least one primary and one logical volume descriptor */
3567+ if ((ump->primary_vol == NULL) || (ump->logical_vol) == NULL)
3568+ return (EINVAL);
3569+
3570+ /* we need at least one partition descriptor */
3571+ if (ump->partitions[0] == NULL)
3572+ return (EINVAL);
3573+
3574+ /* check logical volume sector size verses device sector size */
3575+ if (le32toh(ump->logical_vol->lb_size) != ump->sector_size) {
3576+ printf("UDF mount: format violation, lb_size != sector size\n");
3577+ return (EINVAL);
3578+ }
3579+
3580+ /* check domain name */
3581+ domain_name = ump->logical_vol->domain_id.id;
3582+ if (strncmp(domain_name, "*OSTA UDF Compliant", 20)) {
3583+ printf("UDF mount: disc not OSTA UDF Compliant, aborting\n");
3584+ return (EINVAL);
3585+ }
3586+
3587+ /*
3588+ * We need at least one logvol integrity descriptor recorded. Note
3589+ * that its OK to have an open logical volume integrity here. The VAT
3590+ * will close/update the integrity.
3591+ */
3592+ error = udf_retrieve_lvint(ump);
3593+ if (error != 0)
3594+ return (EINVAL); // previously it always returned this on error.
3595+
3596+ /* process derived structures */
3597+ n_pm = le32toh(ump->logical_vol->n_pm); /* num partmaps */
3598+ lvint = ump->logvol_integrity;
3599+ lvinfo = (struct udf_logvol_info *)(&lvint->tables[2 * n_pm]);
3600+ ump->logvol_info = lvinfo;
3601+
3602+ /* TODO check udf versions? */
3603+
3604+ /*
3605+ * check logvol mappings: effective virt->log partmap translation
3606+ * check and recording of the mapping results. Saves expensive
3607+ * strncmp() in tight places.
3608+ */
3609+ n_pm = le32toh(ump->logical_vol->n_pm); /* num partmaps */
3610+ mt_l = le32toh(ump->logical_vol->mt_l); /* partmaps data length */
3611+ pmap_pos = ump->logical_vol->maps;
3612+
3613+ if (n_pm > UDF_PMAPS) {
3614+ printf("UDF mount: too many mappings\n");
3615+ return (EINVAL);
3616+ }
3617+
3618+ /* count types and set partition numbers */
3619+ n_phys = n_virt = n_spar = n_meta = 0;
3620+ for (log_part = 0; log_part < n_pm; log_part++) {
3621+ mapping = (union udf_pmap *)pmap_pos;
3622+ pmap_stype = pmap_pos[0];
3623+ pmap_size = pmap_pos[1];
3624+
3625+ switch (pmap_stype) {
3626+ case 1: /* physical mapping */
3627+ /* volseq = le16toh(mapping->pm1.vol_seq_num); */
3628+ raw_phys_part = le16toh(mapping->pm1.part_num);
3629+ pmap_type = UDF_VTOP_TYPE_PHYS;
3630+ n_phys++;
3631+ break;
3632+ case 2: /* virtual/sparable/meta mapping */
3633+ map_name = mapping->pm2.part_id.id;
3634+ /* volseq = le16toh(mapping->pm2.vol_seq_num); */
3635+ raw_phys_part = le16toh(mapping->pm2.part_num);
3636+ pmap_type = UDF_VTOP_TYPE_UNKNOWN;
3637+ len = UDF_REGID_ID_SIZE;
3638+
3639+ check_name = "*UDF Virtual Partition";
3640+ if (strncmp(map_name, check_name, len) == 0) {
3641+ pmap_type = UDF_VTOP_TYPE_VIRT;
3642+ n_virt++;
3643+ break;
3644+ }
3645+ check_name = "*UDF Sparable Partition";
3646+ if (strncmp(map_name, check_name, len) == 0) {
3647+ pmap_type = UDF_VTOP_TYPE_SPARABLE;
3648+ n_spar++;
3649+ break;
3650+ }
3651+ check_name = "*UDF Metadata Partition";
3652+ if (strncmp(map_name, check_name, len) == 0) {
3653+ pmap_type = UDF_VTOP_TYPE_META;
3654+ n_meta++;
3655+ break;
3656+ }
3657+ break;
3658+ default:
3659+ return (EINVAL);
3660+ }
3661+
3662+ /*
3663+ * BUGALERT: some rogue implementations use random physical
3664+ * partition numbers to break other implementations so lookup
3665+ * the number.
3666+ */
3667+ for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
3668+ part = ump->partitions[phys_part];
3669+ if (part == NULL)
3670+ continue;
3671+ if (le16toh(part->part_num) == raw_phys_part)
3672+ break;
3673+ }
3674+
3675+ if (phys_part == UDF_PARTITIONS)
3676+ return (EINVAL);
3677+ if (pmap_type == UDF_VTOP_TYPE_UNKNOWN)
3678+ return (EINVAL);
3679+
3680+ ump->vtop[log_part] = phys_part;
3681+ ump->vtop_tp[log_part] = pmap_type;
3682+
3683+ pmap_pos += pmap_size;
3684+ }
3685+ /* not winning the beauty contest */
3686+ ump->vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW;
3687+
3688+ /* test some basic UDF assertions/requirements */
3689+ if ((n_virt > 1) || (n_spar > 1) || (n_meta > 1))
3690+ return (EINVAL);
3691+
3692+ if (n_virt) {
3693+ if ((n_phys == 0) || n_spar || n_meta)
3694+ return (EINVAL);
3695+ }
3696+ if (n_spar + n_phys == 0)
3697+ return (EINVAL);
3698+
3699+ /* signal its OK for now */
3700+ return (0);
3701+}
3702+
3703+/*
3704+ * Update logical volume name in all structures that keep a record of it. We
3705+ * use memmove since each of them might be specified as a source.
3706+ *
3707+ * Note that it doesn't update the VAT structure!
3708+ */
3709+static void
3710+udf_update_logvolname(struct udf_mount *ump, char *logvol_id)
3711+{
3712+ struct logvol_desc *lvd = NULL;
3713+ struct fileset_desc *fsd = NULL;
3714+ struct udf_lv_info *lvi = NULL;
3715+
3716+ lvd = ump->logical_vol;
3717+ fsd = ump->fileset_desc;
3718+ if (ump->implementation)
3719+ lvi = &ump->implementation->_impl_use.lv_info;
3720+
3721+ /* logvol's id might be specified as origional so use memmove here */
3722+ memmove(lvd->logvol_id, logvol_id, 128);
3723+ if (fsd)
3724+ memmove(fsd->logvol_id, logvol_id, 128);
3725+ if (lvi)
3726+ memmove(lvi->logvol_id, logvol_id, 128);
3727+}
3728+
3729+/*
3730+ * Extended attribute support. UDF knows of 3 places for extended attributes:
3731+ *
3732+ * (a) inside the file's (e)fe in the length of the extended attribute area
3733+ * before the allocation descriptors/filedata
3734+ *
3735+ * (b) in a file referenced by (e)fe->ext_attr_icb and
3736+ *
3737+ * (c) in the e(fe)'s associated stream directory that can hold various
3738+ * sub-files. In the stream directory a few fixed named subfiles are reserved
3739+ * for NT/Unix ACL's and OS/2 attributes.
3740+ *
3741+ * NOTE: Extended attributes are read randomly but allways written
3742+ * *atomicaly*. For ACL's this interface is propably different but not known
3743+ * to me yet.
3744+ *
3745+ * Order of extended attributes in a space :
3746+ * ECMA 167 EAs
3747+ * Non block aligned Implementation Use EAs
3748+ * Block aligned Implementation Use EAs
3749+ * Application Use EAs
3750+ */
3751+
3752+static int
3753+udf_impl_extattr_check(struct impl_extattr_entry *implext)
3754+{
3755+ uint16_t *spos;
3756+
3757+ if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) {
3758+ /* checksum valid? */
3759+ spos = (uint16_t *)implext->data;
3760+ if (le16toh(*spos) != udf_ea_cksum((uint8_t *)implext))
3761+ return (EINVAL);
3762+ }
3763+
3764+ return (0);
3765+}
3766+
3767+static void
3768+udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext)
3769+{
3770+ uint16_t *spos;
3771+
3772+ if (strncmp(implext->imp_id.id, "*UDF", 4) == 0) {
3773+ /* set checksum */
3774+ spos = (uint16_t *)implext->data;
3775+ *spos = le16toh(udf_ea_cksum((uint8_t *)implext));
3776+ }
3777+}
3778+
3779+int
3780+udf_extattr_search_intern(struct udf_node *node, uint32_t sattr,
3781+ char const *sattrname, uint32_t *offsetp, uint32_t *lengthp)
3782+{
3783+ struct extattrhdr_desc *eahdr;
3784+ struct extattr_entry *attrhdr;
3785+ struct impl_extattr_entry *implext;
3786+ int error;
3787+ int32_t l_ea;
3788+ uint32_t a_l, offset, sector_size;
3789+ uint8_t *pos;
3790+
3791+ /* get mountpoint */
3792+ sector_size = node->ump->sector_size;
3793+
3794+ /* get information from fe/efe */
3795+ if (node->fe != NULL) {
3796+ l_ea = le32toh(node->fe->l_ea);
3797+ eahdr = (struct extattrhdr_desc *) node->fe->data;
3798+ } else {
3799+ l_ea = le32toh(node->efe->l_ea);
3800+ eahdr = (struct extattrhdr_desc *) node->efe->data;
3801+ }
3802+
3803+ /* something recorded here? */
3804+ if (l_ea == 0)
3805+ return (ENOENT);
3806+
3807+ /* check extended attribute tag; what to do if it fails? */
3808+ error = udf_check_tag(eahdr);
3809+ if (error != 0)
3810+ return (EINVAL);
3811+ if (le16toh(eahdr->tag.id) != TAGID_EXTATTR_HDR)
3812+ return (EINVAL);
3813+ error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
3814+ if (error != 0)
3815+ return (EINVAL);
3816+
3817+ /* looking for Ecma-167 attributes? */
3818+ offset = sizeof(struct extattrhdr_desc);
3819+
3820+ /* looking for either implemenation use or application use */
3821+ if (sattr == 2048) { /* [4/48.10.8] */
3822+ offset = le32toh(eahdr->impl_attr_loc);
3823+ if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
3824+ return (ENOENT);
3825+ }
3826+ if (sattr == 65536) { /* [4/48.10.9] */
3827+ offset = le32toh(eahdr->appl_attr_loc);
3828+ if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT)
3829+ return (ENOENT);
3830+ }
3831+
3832+ /* paranoia check offset and l_ea */
3833+ if (l_ea + offset >= sector_size - sizeof(struct extattr_entry))
3834+ return (EINVAL);
3835+
3836+ /* find our extended attribute */
3837+ l_ea -= offset;
3838+ pos = (uint8_t *)eahdr + offset;
3839+
3840+ while (l_ea >= sizeof(struct extattr_entry)) {
3841+ attrhdr = (struct extattr_entry *)pos;
3842+ implext = (struct impl_extattr_entry *)pos;
3843+
3844+ /* get complete attribute length and check for roque values */
3845+ a_l = le32toh(attrhdr->a_l);
3846+ if ((a_l == 0) || (a_l > l_ea))
3847+ return (EINVAL);
3848+
3849+ if (attrhdr->type != sattr)
3850+ goto next_attribute;
3851+
3852+ /* we might have found it! */
3853+ if (attrhdr->type < 2048) { /* Ecma-167 attribute */
3854+ *offsetp = offset;
3855+ *lengthp = a_l;
3856+ return (0); /* success */
3857+ }
3858+
3859+ /*
3860+ * Implementation use and application use extended attributes
3861+ * have a name to identify. They share the same structure only
3862+ * UDF implementation use extended attributes have a checksum
3863+ * we need to check
3864+ */
3865+
3866+ if (strcmp(implext->imp_id.id, sattrname) == 0) {
3867+ /* we have found our appl/implementation attribute */
3868+ *offsetp = offset;
3869+ *lengthp = a_l;
3870+ return (0); /* success */
3871+ }
3872+
3873+next_attribute:
3874+ /* next attribute */
3875+ pos += a_l;
3876+ l_ea -= a_l;
3877+ offset += a_l;
3878+ }
3879+ /* not found */
3880+ return (ENOENT);
3881+}
3882+
3883+static int
3884+udf_update_lvid_from_vat_extattr(struct udf_node *vat_node)
3885+{
3886+ struct impl_extattr_entry *implext;
3887+ struct vatlvext_extattr_entry lvext;
3888+ struct udf_mount *ump;
3889+ struct udf_logvol_info *lvinfo;
3890+ uint64_t vat_uniqueid;
3891+ int error;
3892+ uint32_t a_l, offset;
3893+ const char *extstr = "*UDF VAT LVExtension";
3894+ uint8_t *ea_start, *lvextpos;
3895+
3896+ /* get mountpoint and lvinfo */
3897+ ump = vat_node->ump;
3898+ lvinfo = ump->logvol_info;
3899+
3900+ /* get information from fe/efe */
3901+ if (vat_node->fe != NULL) {
3902+ vat_uniqueid = le64toh(vat_node->fe->unique_id);
3903+ ea_start = vat_node->fe->data;
3904+ } else {
3905+ vat_uniqueid = le64toh(vat_node->efe->unique_id);
3906+ ea_start = vat_node->efe->data;
3907+ }
3908+
3909+ error = udf_extattr_search_intern(vat_node, 2048, extstr, &offset,
3910+ &a_l);
3911+ if (error !=0)
3912+ return (error);
3913+
3914+ implext = (struct impl_extattr_entry *)(ea_start + offset);
3915+ error = udf_impl_extattr_check(implext);
3916+ if (error != 0)
3917+ return (error);
3918+
3919+ /* paranoia */
3920+ if (a_l != sizeof(*implext) - 1 + le32toh(implext->iu_l) +
3921+ sizeof(lvext))
3922+ return (EINVAL);
3923+
3924+ /*
3925+ * we have found our "VAT LVExtension attribute. BUT due to a
3926+ * bug in the specification it might not be word aligned so
3927+ * copy first to avoid panics on some machines (!!)
3928+ */
3929+ lvextpos = implext->data + le32toh(implext->iu_l);
3930+ memcpy(&lvext, lvextpos, sizeof(lvext));
3931+
3932+ /* check if it was updated the last time */
3933+ if (le64toh(lvext.unique_id_chk) == vat_uniqueid) {
3934+ lvinfo->num_files = lvext.num_files;
3935+ lvinfo->num_directories = lvext.num_directories;
3936+ udf_update_logvolname(ump, lvext.logvol_id);
3937+ } else {
3938+ /* replace VAT LVExt by free space EA */
3939+ memset(implext->imp_id.id, 0, UDF_REGID_ID_SIZE);
3940+ strcpy(implext->imp_id.id, "*UDF FreeEASpace");
3941+ udf_calc_impl_extattr_checksum(implext);
3942+ }
3943+
3944+ return (0);
3945+}
3946+
3947+int
3948+udf_vat_read(struct udf_mount *ump, uint8_t *blob, int size,
3949+ uint32_t offset)
3950+{
3951+/* mutex_enter(&ump->allocate_mutex); */
3952+ if (offset + size > ump->vat_offset + ump->vat_entries * 4)
3953+ return (EINVAL);
3954+ memcpy(blob, ump->vat_table + offset, size);
3955+/* mutex_exit(&ump->allocate_mutex); */
3956+
3957+ return (0);
3958+}
3959+
3960+/*
3961+ * Read in relevant pieces of VAT file and check if its indeed a VAT file
3962+ * descriptor. If OK, read in complete VAT file.
3963+ */
3964+
3965+static int
3966+udf_check_for_vat(struct udf_node *vat_node)
3967+{
3968+ struct udf_mount *ump;
3969+ struct icb_tag *icbtag;
3970+ struct timestamp *mtime;
3971+ struct udf_vat *vat;
3972+ struct udf_oldvat_tail *oldvat_tl;
3973+ struct udf_logvol_info *lvinfo;
3974+ uint64_t unique_id;
3975+ int error, filetype;
3976+ uint32_t vat_entries, vat_length, vat_offset, vat_table_alloc_len;
3977+ uint32_t *raw_vat, sector_size;
3978+ char *regid_name;
3979+ uint8_t *vat_table;
3980+
3981+ /* vat_length is really 64 bits though impossible */
3982+
3983+ if (vat_node == NULL)
3984+ return (ENOENT);
3985+
3986+ /* get mount info */
3987+ ump = vat_node->ump;
3988+ sector_size = le32toh(ump->logical_vol->lb_size);
3989+
3990+ /* get information from fe/efe */
3991+ if (vat_node->fe != NULL) {
3992+ vat_length = le64toh(vat_node->fe->inf_len);
3993+ icbtag = &vat_node->fe->icbtag;
3994+ mtime = &vat_node->fe->mtime;
3995+ unique_id = le64toh(vat_node->fe->unique_id);
3996+ } else {
3997+ vat_length = le64toh(vat_node->efe->inf_len);
3998+ icbtag = &vat_node->efe->icbtag;
3999+ mtime = &vat_node->efe->mtime;
4000+ unique_id = le64toh(vat_node->efe->unique_id);
4001+ }
4002+
4003+ /* Check icb filetype! it has to be 0 or UDF_ICB_FILETYPE_VAT */
4004+ filetype = icbtag->file_type;
4005+ if ((filetype != 0) && (filetype != UDF_ICB_FILETYPE_VAT))
4006+ return (ENOENT);
4007+
4008+ vat_table_alloc_len =
4009+ ((vat_length + UDF_VAT_CHUNKSIZE - 1) / UDF_VAT_CHUNKSIZE)
4010+ * UDF_VAT_CHUNKSIZE;
4011+
4012+ if (vat_table_alloc_len > UDF_VAT_ALLOC_LIMIT) {
4013+ printf("UDF mount: VAT table length of %d bytes exceeds "
4014+ "implementation limit.\n", vat_table_alloc_len);
4015+ return (ENOMEM);
4016+ }
4017+ vat_table = malloc(vat_table_alloc_len, M_UDFTEMP, M_WAITOK);
4018+
4019+ /* allocate piece to read in head or tail of VAT file */
4020+ raw_vat = malloc(sector_size, M_UDFTEMP, M_WAITOK);
4021+
4022+ /*
4023+ * check contents of the file if its the old 1.50 VAT table format.
4024+ * Its notoriously broken and allthough some implementations support an
4025+ * extention as defined in the UDF 1.50 errata document, its doubtfull
4026+ * to be useable since a lot of implementations don't maintain it.
4027+ */
4028+ lvinfo = ump->logvol_info;
4029+
4030+ if (filetype == 0) {
4031+ /* definition */
4032+ vat_offset = 0;
4033+ vat_entries = (vat_length - 36) / 4;
4034+
4035+ /* read in tail of virtual allocation table file */
4036+ error = udf_read_node(vat_node, (uint8_t *)raw_vat,
4037+ vat_entries * 4, sizeof(struct udf_oldvat_tail));
4038+ if (error != 0)
4039+ goto out;
4040+
4041+ /* check 1.50 VAT */
4042+ oldvat_tl = (struct udf_oldvat_tail *)raw_vat;
4043+ regid_name = (char *)oldvat_tl->id.id;
4044+ error = strncmp(regid_name, "*UDF Virtual Alloc Tbl", 22);
4045+ if (error != 0) {
4046+ error = ENOENT;
4047+ goto out;
4048+ }
4049+
4050+ /*
4051+ * update LVID from "*UDF VAT LVExtension" extended attribute
4052+ * if present.
4053+ */
4054+ udf_update_lvid_from_vat_extattr(vat_node);
4055+ } else {
4056+ /* read in head of virtual allocation table file */
4057+ error = udf_read_node(vat_node, (uint8_t *)raw_vat, 0,
4058+ sizeof(struct udf_vat));
4059+ if (error != 0)
4060+ goto out;
4061+
4062+ /* definition */
4063+ vat = (struct udf_vat *)raw_vat;
4064+ vat_offset = vat->header_len;
4065+ vat_entries = (vat_length - vat_offset) / 4;
4066+
4067+ lvinfo->num_files = vat->num_files;
4068+ lvinfo->num_directories = vat->num_directories;
4069+ lvinfo->min_udf_readver = vat->min_udf_readver;
4070+ lvinfo->min_udf_writever = vat->min_udf_writever;
4071+ lvinfo->max_udf_writever = vat->max_udf_writever;
4072+
4073+ udf_update_logvolname(ump, vat->logvol_id);
4074+ }
4075+
4076+ /* read in complete VAT file */
4077+ error = udf_read_node(vat_node, vat_table, 0, vat_length);
4078+ if (error != 0)
4079+ printf("UDF mount: Error reading in of complete VAT file."
4080+ " (error %d)\n", error);
4081+ if (error != 0)
4082+ goto out;
4083+
4084+ ump->logvol_integrity->lvint_next_unique_id = htole64(unique_id);
4085+ ump->logvol_integrity->integrity_type = htole32(UDF_INTEGRITY_CLOSED);
4086+ ump->logvol_integrity->time = *mtime;
4087+
4088+ ump->vat_table_alloc_len = vat_table_alloc_len;
4089+ ump->vat_table = vat_table;
4090+ ump->vat_offset = vat_offset;
4091+ ump->vat_entries = vat_entries;
4092+
4093+out:
4094+ if (error != 0) {
4095+ if (vat_table != NULL)
4096+ free(vat_table, M_UDFTEMP);
4097+ }
4098+ free(raw_vat, M_UDFTEMP);
4099+
4100+ return (error);
4101+}
4102+
4103+static int
4104+udf_search_vat(struct udf_mount *ump)
4105+{
4106+ union dscrptr *dscr;
4107+ struct long_ad icb_loc;
4108+ struct udf_node *vat_node;
4109+ int error;
4110+ uint32_t early_vat_loc, vat_loc;
4111+ uint16_t tagid;
4112+ uint8_t file_type;
4113+
4114+ vat_node = NULL;
4115+
4116+ early_vat_loc = ump->first_possible_vat_location;
4117+ vat_loc = ump->last_possible_vat_location;
4118+
4119+ /* start looking from the end of the range */
4120+ do {
4121+ error = udf_read_phys_dscr(ump, vat_loc, M_UDFTEMP, &dscr);
4122+ if (!error && dscr) { /* dscr will be null if zeros were read */
4123+ tagid = le16toh(dscr->tag.id);
4124+ file_type = 0;
4125+ if (tagid == TAGID_FENTRY)
4126+ file_type = dscr->fe.icbtag.file_type;
4127+ else if (tagid == TAGID_EXTFENTRY)
4128+ file_type = dscr->efe.icbtag.file_type;
4129+ free(dscr, M_UDFTEMP);
4130+
4131+ if (file_type == 248)
4132+ {
4133+ icb_loc.loc.part_num =
4134+ htole16(UDF_VTOP_RAWPART);
4135+ icb_loc.loc.lb_num = htole32(vat_loc);
4136+ error = udf_get_node(ump, icb_loc, &vat_node);
4137+ if (error == 0)
4138+ error = udf_check_for_vat(vat_node);
4139+ if (error == 0) {
4140+ udf_dispose_node(vat_node);
4141+ break;
4142+ }
4143+ }
4144+ }
4145+
4146+ if (vat_node != NULL) {
4147+ udf_dispose_node(vat_node);
4148+ vat_node = NULL;
4149+ }
4150+
4151+ if (vat_loc == ump->last_possible_vat_location)
4152+ printf("UDF mount: VAT not found at last written "
4153+ "location\n");
4154+
4155+ vat_loc--;
4156+ } while (vat_loc >= early_vat_loc);
4157+
4158+ return (error);
4159+}
4160+
4161+static int
4162+udf_read_sparables(struct udf_mount *ump, union udf_pmap *mapping)
4163+{
4164+ union dscrptr *dscr;
4165+ struct part_map_spare *pms = &mapping->pms;
4166+ int error, spar;
4167+ uint32_t lb_num;
4168+
4169+ /*
4170+ * The partition mapping passed on to us specifies the information we
4171+ * need to locate and initialise the sparable partition mapping
4172+ * information we need.
4173+ */
4174+
4175+ ump->sparable_packet_size = le16toh(pms->packet_len);
4176+
4177+ for (spar = 0; spar < pms->n_st; spar++) {
4178+ lb_num = pms->st_loc[spar];
4179+ error = udf_read_phys_dscr(ump, lb_num, M_UDFTEMP, &dscr);
4180+ if (!error && dscr) {
4181+ if (le16toh(dscr->tag.id) == TAGID_SPARING_TABLE) {
4182+ if (ump->sparing_table)
4183+ free(ump->sparing_table, M_UDFTEMP);
4184+ ump->sparing_table = &dscr->spt;
4185+ dscr = NULL;
4186+ break; /* we're done */
4187+ }
4188+ }
4189+ if (dscr)
4190+ free(dscr, M_UDFTEMP);
4191+ }
4192+
4193+ if (ump->sparing_table)
4194+ return (0);
4195+
4196+ return (ENOENT);
4197+}
4198+
4199+static int
4200+udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
4201+{
4202+ struct part_map_meta *pmm = &mapping->pmm;
4203+ struct long_ad icb_loc;
4204+ int error = 0;
4205+ char *windows_id = "*Microsoft Windows";
4206+
4207+ /*
4208+ * The mappings come from the logical volume descripor, and Windows does
4209+ * not write a usable partion number into the metadata map descriptor.
4210+ */
4211+ if (strncmp(windows_id, ump->logical_vol->imp_id.id, 23) == 0)
4212+ icb_loc.loc.part_num = 0;
4213+ else
4214+ icb_loc.loc.part_num = pmm->part_num;
4215+
4216+ icb_loc.loc.lb_num = pmm->meta_file_lbn;
4217+ udf_get_node(ump, icb_loc, &ump->metadata_node);
4218+
4219+ if (ump->metadata_node == NULL) {
4220+ icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn;
4221+ if (icb_loc.loc.lb_num != -1)
4222+ udf_get_node(ump, icb_loc, &ump->metadata_node);
4223+
4224+ if (ump->metadata_node != NULL)
4225+ printf("UDF mount: Metadata file not readable, "
4226+ "substituting Metadata copy file\n");
4227+ }
4228+
4229+ /* if we're mounting read-only we relax the requirements */
4230+ if (ump->metadata_node == NULL)
4231+ error = EFAULT;
4232+
4233+ return (error);
4234+}
4235+
4236+int
4237+udf_read_vds_tables(struct udf_mount *ump)
4238+{
4239+ union udf_pmap *mapping;
4240+ int pmap_size, error;
4241+ uint32_t log_part, mt_l, n_pm;
4242+ uint8_t *pmap_pos;
4243+
4244+ error = 0;
4245+
4246+ /* Iterate (again) over the part mappings for locations */
4247+ n_pm = le32toh(ump->logical_vol->n_pm); /* num partmaps */
4248+ mt_l = le32toh(ump->logical_vol->mt_l); /* partmaps data length */
4249+ pmap_pos = ump->logical_vol->maps;
4250+
4251+ for (log_part = 0; log_part < n_pm; log_part++) {
4252+ mapping = (union udf_pmap *) pmap_pos;
4253+ switch (ump->vtop_tp[log_part]) {
4254+ case UDF_VTOP_TYPE_PHYS:
4255+ /* nothing */
4256+ break;
4257+ case UDF_VTOP_TYPE_VIRT:
4258+ /* search and load VAT */
4259+ error = udf_search_vat(ump);
4260+ if (error != 0)
4261+ return (ENOENT);
4262+ break;
4263+ case UDF_VTOP_TYPE_SPARABLE:
4264+ /* load one of the sparable tables */
4265+ error = udf_read_sparables(ump, mapping);
4266+ if (error != 0)
4267+ return (ENOENT);
4268+ break;
4269+ case UDF_VTOP_TYPE_META:
4270+ /* load the associated file descriptors */
4271+ error = udf_read_metadata_nodes(ump, mapping);
4272+ if (error != 0)
4273+ return (ENOENT);
4274+ break;
4275+ default:
4276+ break;
4277+ }
4278+ pmap_size = pmap_pos[1];
4279+ pmap_pos += pmap_size;
4280+ }
4281+
4282+ return (0);
4283+}
4284+
4285+int
4286+udf_read_rootdirs(struct udf_mount *ump)
4287+{
4288+ union dscrptr *dscr;
4289+ struct mount *mp;
4290+ struct vnode *rootdir_node, *streamdir_node;
4291+ struct long_ad *dir_loc, fsd_loc;
4292+ ino_t ino;
4293+ int dscr_type, error;
4294+ uint32_t dummy, fsd_len, lb_num;
4295+
4296+ mp = ump->vfs_mountp;
4297+
4298+ /* TODO implement FSD reading in separate function like integrity? */
4299+ /* get fileset descriptor sequence */
4300+ fsd_loc = ump->logical_vol->lv_fsd_loc;
4301+ fsd_len = le32toh(fsd_loc.len);
4302+
4303+ dscr = NULL;
4304+ error = 0;
4305+ while (fsd_len > 0 || error != 0) {
4306+ /* translate fsd_loc to lb_num */
4307+ error = udf_translate_vtop(ump, &fsd_loc, &lb_num, &dummy);
4308+ if (error != 0)
4309+ break;
4310+ error = udf_read_phys_dscr(ump, lb_num, M_UDFTEMP, &dscr);
4311+ /* end markers */
4312+ if (error != 0 || dscr == NULL)
4313+ break;
4314+
4315+ /* analyse */
4316+ dscr_type = le16toh(dscr->tag.id);
4317+ if (dscr_type == TAGID_TERM)
4318+ break;
4319+ if (dscr_type != TAGID_FSD) {
4320+ free(dscr, M_UDFTEMP);
4321+ return (ENOENT);
4322+ }
4323+
4324+ /*
4325+ * TODO check for multiple fileset descriptors; its only
4326+ * picking the last now. Also check for FSD
4327+ * correctness/interpretability
4328+ */
4329+
4330+ /* update */
4331+ if (ump->fileset_desc != NULL) {
4332+ free(ump->fileset_desc, M_UDFTEMP);
4333+ }
4334+ ump->fileset_desc = &dscr->fsd;
4335+ dscr = NULL;
4336+
4337+ /* continue to the next fsd */
4338+ fsd_len -= ump->sector_size;
4339+ fsd_loc.loc.lb_num = htole32(le32toh(fsd_loc.loc.lb_num) + 1);
4340+
4341+ /* follow up to fsd->next_ex (long_ad) if its not null */
4342+ if (le32toh(ump->fileset_desc->next_ex.len)) {
4343+ fsd_loc = ump->fileset_desc->next_ex;
4344+ fsd_len = le32toh(ump->fileset_desc->next_ex.len);
4345+ }
4346+ }
4347+ if (dscr != NULL)
4348+ free(dscr, M_UDFTEMP);
4349+
4350+ /* there has to be one */
4351+ if (ump->fileset_desc == NULL)
4352+ return (ENOENT);
4353+
4354+ udf_update_logvolname(ump, ump->logical_vol->logvol_id);
4355+
4356+ /*
4357+ * Now the FSD is known, read in the rootdirectory and if one exists,
4358+ * the system stream dir. Some files in the system streamdir are not
4359+ * wanted in this implementation since they are not maintained. If
4360+ * writing is enabled we'll delete these files if they exist.
4361+ */
4362+
4363+ rootdir_node = streamdir_node = NULL;
4364+ dir_loc = NULL;
4365+
4366+ /* try to read in the rootdir */
4367+ dir_loc = &ump->fileset_desc->rootdir_icb;
4368+ error = udf_get_node_id(*dir_loc, &ino);
4369+ if (error == 0)
4370+ error = udf_vget(mp, ino, LK_EXCLUSIVE, &rootdir_node);
4371+ if (error != 0)
4372+ return (ENOENT);
4373+
4374+ /*
4375+ * Try the system stream directory; not very likely in the ones we
4376+ * test, but for completeness.
4377+ */
4378+ dir_loc = &ump->fileset_desc->streamdir_icb;
4379+ if (le32toh(dir_loc->len)) {
4380+ error = udf_get_node_id(*dir_loc, &ino);
4381+ if (error == 0)
4382+ error = udf_vget(mp, ino, LK_EXCLUSIVE,
4383+ &streamdir_node);
4384+ if (error != 0)
4385+ printf("UDF mount: streamdir defined but error in "
4386+ "streamdir reading\n");
4387+#if 0
4388+ else {
4389+ printf("UDF mount: streamdir defined but ignored\n");
4390+ /*
4391+ * TODO process streamdir `baddies' i.e. files we dont
4392+ * want if R/W
4393+ */
4394+ }
4395+#endif
4396+ }
4397+
4398+ /* release the vnodes again; they'll be auto-recycled later */
4399+ if (streamdir_node != NULL) {
4400+ /* This is not used later. */
4401+ vgone(streamdir_node);
4402+ vput(streamdir_node);
4403+ }
4404+ if (rootdir_node != NULL) {
4405+ /* Vnodes are not initialized correctly until mounting is
4406+ complete. */
4407+ vgone(rootdir_node);
4408+ vput(rootdir_node);
4409+ }
4410+
4411+ return (0);
4412+}
4413+
4414+/*
4415+ * To make absolutely sure we are NOT returning zero, add one. This can fail,
4416+ * but in final version should probably never fail.
4417+ */
4418+int
4419+udf_get_node_id(const struct long_ad icbptr, ino_t *ino)
4420+{
4421+ uint32_t blkn;
4422+ uint16_t part;
4423+
4424+ /* Just for now, this should be done in another way. */
4425+ blkn = le32toh(icbptr.loc.lb_num);
4426+ part = le16toh(icbptr.loc.part_num);
4427+
4428+ if ((blkn + 1) & 0xE0000000) {
4429+ printf("UDF: Block number too large to convert to inode "
4430+ "number.\n");
4431+ return EDOOFUS;
4432+ }
4433+ if (part & 0xFFF8) {
4434+ printf("UDF: Partition number too large to convert to inode "
4435+ "number.\n");
4436+ return EDOOFUS;
4437+ }
4438+
4439+ *ino = (blkn + 1) | (part << 29);
4440+
4441+ return (0);
4442+}
4443+
4444+void
4445+udf_get_node_longad(const ino_t ino, struct long_ad *icbptr)
4446+{
4447+ uint32_t blkn, ino2;
4448+ uint16_t part;
4449+
4450+ /* Just for now, this should be done in another way. */
4451+ ino2 = ino;
4452+ blkn = (ino2 & 0x1FFFFFFF) - 1;
4453+ part = (ino2 & 0xE0000000) >> 29;
4454+
4455+ icbptr->loc.lb_num = htole32(blkn);
4456+ icbptr->loc.part_num = htole16(part);
4457+}
4458+
4459+/* UDF<->unix converters */
4460+
4461+static mode_t
4462+udf_perm_to_unix_mode(uint32_t perm)
4463+{
4464+ mode_t mode;
4465+
4466+ mode = ((perm & UDF_FENTRY_PERM_USER_MASK));
4467+ mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2);
4468+ mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
4469+
4470+ return (mode);
4471+}
4472+
4473+static uint32_t
4474+udf_icb_to_unix_filetype(uint32_t icbftype)
4475+{
4476+ switch (icbftype) {
4477+ case UDF_ICB_FILETYPE_DIRECTORY:
4478+ case UDF_ICB_FILETYPE_STREAMDIR:
4479+ return (S_IFDIR);
4480+ case UDF_ICB_FILETYPE_FIFO:
4481+ return (S_IFIFO);
4482+ case UDF_ICB_FILETYPE_CHARDEVICE:
4483+ return (S_IFCHR);
4484+ case UDF_ICB_FILETYPE_BLOCKDEVICE:
4485+ return (S_IFBLK);
4486+ case UDF_ICB_FILETYPE_RANDOMACCESS:
4487+ case UDF_ICB_FILETYPE_REALTIME:
4488+ return (S_IFREG);
4489+ case UDF_ICB_FILETYPE_SYMLINK:
4490+ return (S_IFLNK);
4491+ case UDF_ICB_FILETYPE_SOCKET:
4492+ return (S_IFSOCK);
4493+ }
4494+ /* no idea what this is */
4495+ return (0);
4496+}
4497+
4498+/* These timestamp_to_timespec functions are done. */
4499+
4500+static int
4501+udf_leapyear(int year)
4502+{
4503+ int i;
4504+
4505+ i = (year % 400 == 0) ? 1 : 0;
4506+ i |= (year % 100 == 0) ? 0 : 1;
4507+ i &= (year % 4 == 0) ? 1 : 0;
4508+
4509+ return (i);
4510+}
4511+
4512+void
4513+udf_timestamp_to_timespec(struct udf_mount *ump,
4514+ struct timestamp *timestamp,
4515+ struct timespec *timespec)
4516+{
4517+ time_t secs;
4518+ const int days_to_mon[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243,
4519+ 273, 304, 334};
4520+ uint32_t nsecs, usecs;
4521+ uint16_t tz, year;
4522+
4523+ year = le16toh(timestamp->year);
4524+ if (year < 1970 || timestamp->month < 1 || timestamp->month > 12) {
4525+ timespec->tv_sec = 0;
4526+ timespec->tv_nsec = 0;
4527+ return;
4528+ }
4529+
4530+ secs = timestamp->second;
4531+ secs += timestamp->minute * 60;
4532+ secs += timestamp->hour * 3600;
4533+ secs += (timestamp->day - 1) * 3600 * 24;
4534+ secs += days_to_mon[timestamp->month - 1] * 3600 * 24;
4535+
4536+ secs += (year - 1970) * 365 * 3600 * 24;
4537+ secs += ((year - 1 - 1968) / 4) * 3600 * 24;
4538+
4539+ if (year > 2100) {
4540+ secs -= (((year - 1 - 2100) / 100) + 1) * 3600 * 24;
4541+ }
4542+ if (year > 2400) {
4543+ secs += (((year - 1 - 2400) / 400) + 1) * 3600 * 24;
4544+ }
4545+ if (timestamp->month > 2) {
4546+ secs += (time_t)udf_leapyear(year) * 3600 * 24;
4547+ }
4548+
4549+ usecs = timestamp->usec + 100 * timestamp->hund_usec +
4550+ 10000 * timestamp->centisec;
4551+ nsecs = usecs * 1000;
4552+
4553+ /*
4554+ * Calculate the time zone. The timezone is 12 bit signed 2's
4555+ * compliment, so we gotta do some extra magic to handle it right.
4556+ */
4557+ tz = le16toh(timestamp->type_tz);
4558+ tz &= 0x0fff; /* only lower 12 bits are significant */
4559+ if (tz & 0x0800) /* sign extention */
4560+ tz |= 0xf000;
4561+
4562+ /*
4563+ * TODO check timezone conversion
4564+ * check if we are specified a timezone to convert
4565+ */
4566+ if (le16toh(timestamp->type_tz) & 0x1000) {
4567+ if ((int16_t)tz != -2047)
4568+ secs -= (int16_t)tz * 60;
4569+ } /* else {
4570+ secs -= ump->mount_args.gmtoff;
4571+ } */
4572+
4573+ timespec->tv_sec = secs;
4574+ timespec->tv_nsec = nsecs;
4575+}
4576+
4577+/*
4578+ * Attribute and filetypes converters with get/set pairs
4579+ */
4580+
4581+uint32_t
4582+udf_getaccessmode(struct udf_node *udf_node)
4583+{
4584+ struct file_entry *fe = udf_node->fe;
4585+ struct extfile_entry *efe = udf_node->efe;
4586+ uint32_t ftype, icbftype, mode, udf_perm;
4587+ uint16_t icbflags;
4588+
4589+ UDF_LOCK_NODE(udf_node, 0);
4590+
4591+ if (fe != NULL) {
4592+ udf_perm = le32toh(fe->perm);
4593+ icbftype = fe->icbtag.file_type;
4594+ icbflags = le16toh(fe->icbtag.flags);
4595+ } else {
4596+ /*assert(udf_node->efe != NULL); */
4597+ udf_perm = le32toh(efe->perm);
4598+ icbftype = efe->icbtag.file_type;
4599+ icbflags = le16toh(efe->icbtag.flags);
4600+ }
4601+
4602+ mode = udf_perm_to_unix_mode(udf_perm);
4603+ ftype = udf_icb_to_unix_filetype(icbftype);
4604+
4605+ /* set suid, sgid, sticky from flags in fe/efe */
4606+ if (icbflags & UDF_ICB_TAG_FLAGS_SETUID)
4607+ mode |= S_ISUID;
4608+ if (icbflags & UDF_ICB_TAG_FLAGS_SETGID)
4609+ mode |= S_ISGID;
4610+ if (icbflags & UDF_ICB_TAG_FLAGS_STICKY)
4611+ mode |= S_ISVTX;
4612+
4613+ UDF_UNLOCK_NODE(udf_node, 0);
4614+
4615+ return (mode | ftype);
4616+}
4617+
4618+/*
4619+ * Each node can have an attached streamdir node though not recursively. These
4620+ * are otherwise known as named substreams/named extended attributes that have
4621+ * no size limitations.
4622+ *
4623+ * `Normal' extended attributes are indicated with a number and are recorded
4624+ * in either the fe/efe descriptor itself for small descriptors or recorded in
4625+ * the attached extended attribute file. Since these spaces can get
4626+ * fragmented, care ought to be taken.
4627+ *
4628+ * Since the size of the space reserved for allocation descriptors is limited,
4629+ * there is a mechanim provided for extending this space; this is done by a
4630+ * special extent to allow schrinking of the allocations without breaking the
4631+ * linkage to the allocation extent descriptor.
4632+ */
4633+
4634+int
4635+udf_get_node(struct udf_mount *ump, struct long_ad icb_loc,
4636+ struct udf_node **ppunode)
4637+{
4638+ union dscrptr *dscr;
4639+ struct long_ad last_fe_icb_loc;
4640+ struct udf_node *udf_node;
4641+ uint64_t file_size;
4642+ int dscr_type, eof, error, slot, strat, strat4096;
4643+ uint32_t dummy, lb_size, sector;
4644+ uint8_t *file_data;
4645+
4646+ /* garbage check: translate udf_node_icb_loc to sectornr */
4647+ error = udf_translate_vtop(ump, &icb_loc, §or, &dummy);
4648+ if (error != 0)
4649+ return (EINVAL);
4650+
4651+ /* initialise crosslinks, note location of fe/efe for hashing */
4652+ udf_node = udf_alloc_node();
4653+ udf_node->ump = ump;
4654+ udf_node->loc = icb_loc;
4655+/* mutex_init(&udf_node->node_mutex, MUTEX_DEFAULT, IPL_NONE); */
4656+/* cv_init(&udf_node->node_lock, "udf_nlk"); */
4657+
4658+ /* safe to unlock, the entry is in the hash table, vnode is locked */
4659+/* mutex_exit(&ump->get_node_lock); */
4660+
4661+ strat4096 = 0;
4662+ file_size = 0;
4663+ file_data = NULL;
4664+ lb_size = le32toh(ump->logical_vol->lb_size);
4665+
4666+ do {
4667+ /* try to read in fe/efe */
4668+ error = udf_translate_vtop(ump, &icb_loc, §or, &dummy);
4669+ if (error == 0)
4670+ error = udf_read_phys_dscr(ump, sector, M_UDFTEMP,
4671+ &dscr);
4672+
4673+ /* blank sector marks end of sequence, check this */
4674+ if (dscr == NULL && strat4096 == 0)
4675+ error = ENOENT;
4676+
4677+ /* break if read error or blank sector */
4678+ if (error != 0 || dscr == NULL)
4679+ break;
4680+
4681+ /* process descriptor based on the descriptor type */
4682+ dscr_type = le16toh(dscr->tag.id);
4683+
4684+ /* if dealing with an indirect entry, follow the link */
4685+ if (dscr_type == TAGID_INDIRECTENTRY) {
4686+ free(dscr, M_UDFTEMP);
4687+ icb_loc = dscr->inde.indirect_icb;
4688+ continue;
4689+ }
4690+
4691+ /* only file entries and extended file entries allowed here */
4692+ if ((dscr_type != TAGID_FENTRY) &&
4693+ (dscr_type != TAGID_EXTFENTRY)) {
4694+ free(dscr, M_UDFTEMP);
4695+ error = ENOENT;
4696+ break;
4697+ }
4698+
4699+ /* choose this one */
4700+ last_fe_icb_loc = icb_loc;
4701+
4702+ /* record and process/update (ext)fentry */
4703+ file_data = NULL;
4704+ if (dscr_type == TAGID_FENTRY) {
4705+ if (udf_node->fe != NULL)
4706+ free(udf_node->fe, M_UDFTEMP);
4707+ udf_node->fe = &dscr->fe;
4708+ strat = le16toh(udf_node->fe->icbtag.strat_type);
4709+ file_size = le64toh(udf_node->fe->inf_len);
4710+ file_data = udf_node->fe->data;
4711+ } else {
4712+ if (udf_node->efe != NULL)
4713+ free(udf_node->efe, M_UDFTEMP);
4714+ udf_node->efe = &dscr->efe;
4715+ strat = le16toh(udf_node->efe->icbtag.strat_type);
4716+ file_size = le64toh(udf_node->efe->inf_len);
4717+ file_data = udf_node->efe->data;
4718+ }
4719+
4720+ /* check recording strategy (structure) */
4721+
4722+ /*
4723+ * Strategy 4096 is a daisy linked chain terminating with an
4724+ * unrecorded sector or a TERM descriptor. The next
4725+ * descriptor is to be found in the sector that follows the
4726+ * current sector.
4727+ */
4728+ if (strat == 4096) {
4729+ strat4096 = 1;
4730+ icb_loc.loc.lb_num = le32toh(icb_loc.loc.lb_num) + 1;
4731+ }
4732+
4733+ /*
4734+ * Strategy 4 is the normal strategy and terminates, but if
4735+ * we're in strategy 4096, we can't have strategy 4 mixed in
4736+ */
4737+
4738+ if (strat == 4) {
4739+ if (strat4096 != 0) {
4740+ error = EINVAL;
4741+ break;
4742+ }
4743+ break; /* done */
4744+ }
4745+ } while (!error);
4746+
4747+ /* first round of cleanup code */
4748+ if (error != 0) {
4749+ udf_dispose_node(udf_node);
4750+ return (EINVAL);
4751+ }
4752+
4753+ /*
4754+ * Go trough all allocations extents of this descriptor and when
4755+ * encountering a redirect read in the allocation extension. These are
4756+ * daisy-chained.
4757+ */
4758+ UDF_LOCK_NODE(udf_node, 0);
4759+ udf_node->num_extensions = 0;
4760+
4761+ error = 0;
4762+ slot = 0;
4763+ for (;;) {
4764+ udf_get_adslot(udf_node, slot, &icb_loc, &eof);
4765+ if (eof != 0)
4766+ break;
4767+ slot++;
4768+
4769+ if (UDF_EXT_FLAGS(le32toh(icb_loc.len)) != UDF_EXT_REDIRECT)
4770+ continue;
4771+
4772+ if (udf_node->num_extensions >= UDF_MAX_ALLOC_EXTENTS) {
4773+ error = EINVAL;
4774+ break;
4775+ }
4776+
4777+ /* length can only be *one* lb : UDF 2.50/2.3.7.1 */
4778+ if (UDF_EXT_LEN(le32toh(icb_loc.len)) != lb_size) {
4779+ error = EINVAL;
4780+ break;
4781+ }
4782+
4783+ /* load in allocation extent */
4784+ error = udf_translate_vtop(ump, &icb_loc, §or, &dummy);
4785+ if (error == 0)
4786+ error = udf_read_phys_dscr(ump, sector, M_UDFTEMP,
4787+ &dscr);
4788+ if (error != 0 || dscr == NULL)
4789+ break;
4790+
4791+ /* process read-in descriptor */
4792+ dscr_type = le16toh(dscr->tag.id);
4793+
4794+ if (dscr_type != TAGID_ALLOCEXTENT) {
4795+ free(dscr, M_UDFTEMP);
4796+ error = ENOENT;
4797+ break;
4798+ }
4799+
4800+ udf_node->ext[udf_node->num_extensions] = &dscr->aee;
4801+
4802+ udf_node->num_extensions++;
4803+
4804+ } /* while */
4805+ UDF_UNLOCK_NODE(udf_node, 0);
4806+
4807+ /* second round of cleanup code */
4808+ if (error != 0) {
4809+ /* recycle udf_node */
4810+ udf_dispose_node(udf_node);
4811+ return (EINVAL); /* error code ok? */
4812+ }
4813+
4814+ /* TODO ext attr and streamdir udf_nodes */
4815+
4816+ *ppunode = udf_node;
4817+
4818+ return (0);
4819+}
4820+
4821+int
4822+udf_dispose_node(struct udf_node *udf_node)
4823+{
4824+ int extnr;
4825+
4826+ if (udf_node == NULL)
4827+ return (0);
4828+
4829+ /* TODO extended attributes and streamdir */
4830+
4831+ /* free associated memory and the node itself */
4832+ for (extnr = 0; extnr < udf_node->num_extensions; extnr++) {
4833+ free(udf_node->ext[extnr], M_UDFTEMP);
4834+ udf_node->ext[extnr] = (void *)0xdeadcccc;
4835+ }
4836+
4837+ if (udf_node->fe != NULL)
4838+ free(udf_node->fe, M_UDFTEMP);
4839+
4840+ if (udf_node->efe != NULL)
4841+ free(udf_node->efe, M_UDFTEMP);
4842+
4843+ udf_node->fe = (void *)0xdeadaaaa;
4844+ udf_node->efe = (void *)0xdeadbbbb;
4845+ udf_node->ump = (void *)0xdeadbeef;
4846+ udf_free_node(udf_node);
4847+
4848+ return (0);
4849+}
4850+
4851+/*
4852+ * Read one fid and process it into a dirent and advance to the next (*fid)
4853+ * has to be allocated a logical block in size, (*dirent) struct dirent length
4854+ */
4855+
4856+int
4857+udf_validate_fid(struct fileid_desc *fid, int *realsize)
4858+{
4859+ int error, fid_size;
4860+
4861+ /* check if our FID header is OK */
4862+ if ((error = udf_check_tag(fid)) != 0)
4863+ goto brokendir;
4864+
4865+ if (le16toh(fid->tag.id) != TAGID_FID) {
4866+ error = EIO;
4867+ goto brokendir;
4868+ }
4869+
4870+ /* check for length */
4871+ fid_size = udf_fidsize(fid);
4872+ if (*realsize < fid_size) {
4873+ error = EIO;
4874+ goto brokendir;
4875+ }
4876+
4877+ /* check FID contents */
4878+ error = udf_check_tag_payload((union dscrptr *)fid, *realsize);
4879+
4880+ *realsize = fid_size;
4881+brokendir:
4882+ if (error != 0)
4883+ return (EIO);
4884+
4885+ return (error);
4886+}
4887+
4888+/*
4889+ * Read and write file extent in/from the buffer.
4890+ *
4891+ * The splitup of the extent into seperate request-buffers is to minimise
4892+ * copying around as much as possible.
4893+ *
4894+ * block based file reading and writing
4895+ */
4896+
4897+int
4898+udf_read_internal(struct udf_node *node, uint8_t *blob)
4899+{
4900+ struct file_entry *fe = node->fe;
4901+ struct extfile_entry *efe = node->efe;
4902+ struct udf_mount *ump;
4903+ uint64_t inflen;
4904+ int addr_type, icbflags;
4905+ uint32_t sector_size;
4906+ uint8_t *pos;
4907+
4908+ /* get extent and do some paranoia checks */
4909+ ump = node->ump;
4910+ sector_size = ump->sector_size;
4911+
4912+ if (fe != NULL) {
4913+ inflen = le64toh(fe->inf_len);
4914+ pos = &fe->data[0] + le32toh(fe->l_ea);
4915+ icbflags = le16toh(fe->icbtag.flags);
4916+ } else {
4917+ inflen = le64toh(efe->inf_len);
4918+ pos = &efe->data[0] + le32toh(efe->l_ea);
4919+ icbflags = le16toh(efe->icbtag.flags);
4920+ }
4921+ addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
4922+
4923+ /* copy out info */
4924+ memset(blob, 0, sector_size);
4925+ memcpy(blob, pos, inflen);
4926+
4927+ return (0);
4928+}
4929
4930--- sys/fs/udf2/udf_subr.h 1969-12-31 16:00:00.000000000 -0800
4931+++ updates/sys/fs/udf2/udf_subr.h 2014-11-16 16:27:23.000000000 -0800
4932@@ -0,0 +1,122 @@
4933+/*-
4934+ * Copyright (c) 2006, 2008 Reinoud Zandijk
4935+ * All rights reserved.
4936+ *
4937+ * Redistribution and use in source and binary forms, with or without
4938+ * modification, are permitted provided that the following conditions
4939+ * are met:
4940+ * 1. Redistributions of source code must retain the above copyright
4941+ * notice, this list of conditions and the following disclaimer.
4942+ * 2. Redistributions in binary form must reproduce the above copyright
4943+ * notice, this list of conditions and the following disclaimer in the
4944+ * documentation and/or other materials provided with the distribution.
4945+ *
4946+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4947+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4948+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4949+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4950+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4951+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4952+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
4953+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
4954+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
4955+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4956+ *
4957+ */
4958+
4959+#ifndef _FS_UDF_UDF_SUBR_H_
4960+#define _FS_UDF_UDF_SUBR_H_
4961+
4962+/* handies */
4963+#define VFSTOUDF(mp) ((struct udf_mount *)mp->mnt_data)
4964+#define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
4965+
4966+struct buf;
4967+struct long_ad;
4968+
4969+/* tags operations */
4970+int udf_fidsize(struct fileid_desc *fid);
4971+int udf_check_tag(void *blob);
4972+int udf_check_tag_payload(void *blob, uint32_t max_length);
4973+void udf_validate_tag_sum(void *blob);
4974+void udf_validate_tag_and_crc_sums(void *blob);
4975+int udf_tagsize(union dscrptr *dscr, uint32_t udf_sector_size);
4976+
4977+/* read/write descriptors */
4978+int udf_read_phys_dscr(struct udf_mount *ump, uint32_t sector,
4979+ struct malloc_type *mtype, union dscrptr **dstp);
4980+
4981+/* volume descriptors readers and checkers */
4982+int udf_read_anchors(struct udf_mount *ump);
4983+int udf_read_vds_space(struct udf_mount *ump);
4984+int udf_process_vds(struct udf_mount *ump);
4985+int udf_read_vds_tables(struct udf_mount *ump);
4986+int udf_read_rootdirs(struct udf_mount *ump);
4987+
4988+/* open/close and sync volumes */
4989+int udf_open_logvol(struct udf_mount *ump);
4990+int udf_close_logvol(struct udf_mount *ump, int mntflags);
4991+
4992+/* translation services */
4993+int udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc,
4994+ uint32_t *lb_numres, uint32_t *extres);
4995+int udf_bmap_translate(struct udf_node *udf_node, uint32_t block,
4996+ int *exttype, uint64_t *lsector, uint32_t *maxblks);
4997+void udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb,
4998+ int *eof);
4999+int udf_append_adslot(struct udf_node *udf_node, int *slot,
5000+ struct long_ad *icb);
5001+
5002+int udf_vat_read(struct udf_mount *ump, uint8_t *blob, int size,
5003+ uint32_t offset);
5004+
5005+/* disc allocation */
5006+int udf_get_c_type(struct udf_node *udf_node);
5007+int udf_get_record_vpart(struct udf_mount *ump, int udf_c_type);
5008+void udf_calc_freespace(struct udf_mount *ump, uint64_t *sizeblks,
5009+ uint64_t *freeblks);
5010+
5011+/* node readers and writers */
5012+#define UDF_LOCK_NODE(udf_node, flag) udf_lock_node(udf_node, (flag), __FILE__, __LINE__)
5013+#define UDF_UNLOCK_NODE(udf_node, flag) udf_unlock_node(udf_node, (flag))
5014+void udf_lock_node(struct udf_node *udf_node, int flag, char const *fname,
5015+ const int lineno);
5016+void udf_unlock_node(struct udf_node *udf_node, int flag);
5017+
5018+int udf_get_node(struct udf_mount *ump, struct long_ad icb_loc,
5019+ struct udf_node **ppunode);
5020+int udf_dispose_node(struct udf_node *node);
5021+
5022+/* node ops */
5023+int udf_extattr_search_intern(struct udf_node *node, uint32_t sattr,
5024+ char const *sattrname, uint32_t *offsetp, uint32_t *lengthp);
5025+
5026+/* node data buffer read/write */
5027+void udf_read_filebuf(struct udf_node *node, struct buf *buf);
5028+
5029+/* directory operations and helpers */
5030+void udf_osta_charset(struct charspec *charspec);
5031+int udf_validate_fid(struct fileid_desc *fid, int *realsize);
5032+int udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
5033+ struct long_ad *icb_loc, int *found);
5034+
5035+/* helpers and converters */
5036+int udf_get_node_id(const struct long_ad icbptr, ino_t *ino);
5037+void udf_get_node_longad(const ino_t ino, struct long_ad *icbptr);
5038+uint32_t udf_getaccessmode(struct udf_node *node);
5039+void udf_to_unix_name(struct udf_mount *ump, char *result, int result_len,
5040+ uint8_t *id, int len);
5041+void udf_timestamp_to_timespec(struct udf_mount *ump,
5042+ struct timestamp *timestamp, struct timespec *timespec);
5043+
5044+/* vnode operations */
5045+int udf_getanode(struct mount *mp, struct vnode **vpp);
5046+int udf_read_internal(struct udf_node *node, uint8_t *blob);
5047+
5048+/* Created by for testing */
5049+struct udf_node * udf_alloc_node(void);
5050+void udf_free_node(struct udf_node *unode);
5051+int udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp);
5052+int udf_read_node(struct udf_node *unode, uint8_t *blob, off_t start,
5053+ int length);
5054+#endif /* !_FS_UDF_UDF_SUBR_H_ */
5055
5056--- sys/fs/udf2/udf_vfsops.c 1969-12-31 16:00:00.000000000 -0800
5057+++ updates/sys/fs/udf2/udf_vfsops.c 2014-11-16 16:27:23.000000000 -0800
5058@@ -0,0 +1,774 @@
5059+/*-
5060+ * Copyright (c) 2012 Will DeVries
5061+ * Copyright (c) 2006, 2008 Reinoud Zandijk
5062+ * All rights reserved.
5063+ *
5064+ * Redistribution and use in source and binary forms, with or without
5065+ * modification, are permitted provided that the following conditions
5066+ * are met:
5067+ * 1. Redistributions of source code must retain the above copyright
5068+ * notice, this list of conditions and the following disclaimer.
5069+ * 2. Redistributions in binary form must reproduce the above copyright
5070+ * notice, this list of conditions and the following disclaimer in the
5071+ * documentation and/or other materials provided with the distribution.
5072+ *
5073+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5074+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5075+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5076+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5077+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5078+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5079+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5080+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5081+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5082+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5083+ *
5084+ */
5085+
5086+#include <sys/param.h>
5087+#include <sys/endian.h>
5088+#include <sys/cdefs.h>
5089+#include <sys/kernel.h>
5090+#include <sys/malloc.h>
5091+#include <sys/systm.h>
5092+#include <sys/fcntl.h>
5093+#include <sys/namei.h>
5094+#include <sys/proc.h>
5095+#include <sys/vnode.h>
5096+#include <sys/mount.h>
5097+#include <sys/conf.h>
5098+#include <sys/module.h>
5099+#include <sys/priv.h>
5100+#include <sys/iconv.h>
5101+#include <sys/stat.h>
5102+#if 0
5103+#include <sys/udfio.h>
5104+#endif
5105+#include <geom/geom.h>
5106+#include <geom/geom_vfs.h>
5107+
5108+#include "ecma167-udf.h"
5109+#include "udf.h"
5110+#include "udf_subr.h"
5111+
5112+MALLOC_DEFINE(M_UDFTEMP, "UDF temp", "UDF allocation space");
5113+uma_zone_t udf_zone_node = NULL;
5114+
5115+struct iconv_functions *udf2_iconv = NULL;
5116+
5117+static int udf_mountfs(struct vnode *, struct mount *);
5118+
5119+
5120+/* predefine vnode-op list descriptor */
5121+
5122+static vfs_fhtovp_t udf_fhtovp;
5123+static vfs_init_t udf_init;
5124+static vfs_mount_t udf_mount;
5125+static vfs_root_t udf_root;
5126+static vfs_statfs_t udf_statfs;
5127+static vfs_uninit_t udf_uninit;
5128+static vfs_unmount_t udf_unmount;
5129+
5130+static struct vfsops udf_vfsops = {
5131+ .vfs_init = udf_init,
5132+ .vfs_uninit = udf_uninit,
5133+ .vfs_mount = udf_mount,
5134+ .vfs_root = udf_root,
5135+ .vfs_statfs = udf_statfs,
5136+ .vfs_unmount = udf_unmount,
5137+ .vfs_fhtovp = udf_fhtovp,
5138+ .vfs_vget = udf_vget
5139+};
5140+VFS_SET(udf_vfsops, udf2, VFCF_READONLY);
5141+
5142+MODULE_VERSION(udf2, 1);
5143+
5144+
5145+static int
5146+udf_init(struct vfsconf *notused)
5147+{
5148+ /* init node pools */
5149+ udf_zone_node = uma_zcreate("UDF Node Pool Zone",
5150+ sizeof(struct udf_node), NULL, NULL, NULL, NULL, 0, 0);
5151+
5152+ if (udf_zone_node == NULL) {
5153+ printf("UDF mount: Cannot create node pool zone.");
5154+ return (ENOMEM);
5155+ }
5156+
5157+ return (0);
5158+}
5159+
5160+static int
5161+udf_uninit(struct vfsconf *notused)
5162+{
5163+ /* remove pools */
5164+ if (udf_zone_node != NULL) {
5165+ uma_zdestroy(udf_zone_node);
5166+ udf_zone_node = NULL;
5167+ }
5168+
5169+ return (0);
5170+}
5171+
5172+#define MPFREE(a, lst) \
5173+ if ((a)) free((a), lst);
5174+static void
5175+free_udf_mountinfo(struct mount *mp)
5176+{
5177+ struct udf_mount *ump;
5178+ int i;
5179+
5180+ if (mp == NULL)
5181+ return;
5182+
5183+ ump = VFSTOUDF(mp);
5184+ if (ump != NULL) {
5185+ /* Metadata partition support */
5186+ if (ump->metadata_node != NULL)
5187+ udf_dispose_node(ump->metadata_node);
5188+
5189+ /* clear our data */
5190+ for (i = 0; i < UDF_ANCHORS; i++)
5191+ MPFREE(ump->anchors[i], M_UDFTEMP);
5192+ MPFREE(ump->primary_vol, M_UDFTEMP);
5193+ MPFREE(ump->logical_vol, M_UDFTEMP);
5194+ MPFREE(ump->unallocated, M_UDFTEMP);
5195+ MPFREE(ump->implementation, M_UDFTEMP);
5196+ MPFREE(ump->logvol_integrity, M_UDFTEMP);
5197+ for (i = 0; i < UDF_PARTITIONS; i++) {
5198+ MPFREE(ump->partitions[i], M_UDFTEMP);
5199+ }
5200+ MPFREE(ump->fileset_desc, M_UDFTEMP);
5201+ MPFREE(ump->sparing_table, M_UDFTEMP);
5202+ MPFREE(ump->vat_table, M_UDFTEMP);
5203+
5204+ free(ump, M_UDFTEMP);
5205+ }
5206+}
5207+#undef MPFREE
5208+
5209+static int
5210+udf_mount(struct mount *mp)
5211+{
5212+ struct thread *td;
5213+ struct vnode *devvp;
5214+ struct nameidata nd;
5215+ int error, len;
5216+ char *fspec;
5217+
5218+ td = curthread;
5219+
5220+ MNT_ILOCK(mp);
5221+ mp->mnt_flag |= MNT_RDONLY;
5222+ MNT_IUNLOCK(mp);
5223+
5224+ if (mp->mnt_flag & MNT_ROOTFS)
5225+ return (ENOTSUP);
5226+
5227+ /* handle request for updating mount parameters */
5228+ /* TODO can't update my mountpoint yet */
5229+ if (mp->mnt_flag & MNT_UPDATE)
5230+ return (0);
5231+
5232+ fspec = NULL;
5233+ error = vfs_getopt(mp->mnt_optnew, "from", (void **)&fspec, &len);
5234+ if (!error && fspec[len - 1] != '\0')
5235+ return (EINVAL);
5236+ if (fspec == NULL)
5237+ return (EINVAL);
5238+
5239+ /* lookup name to get its vnode */
5240+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
5241+ if ((error = namei(&nd)))
5242+ return (error);
5243+ NDFREE(&nd, NDF_ONLY_PNBUF);
5244+ devvp = nd.ni_vp;
5245+ if (vn_isdisk(devvp, &error) == 0) {
5246+ vput(devvp);
5247+ return (error);
5248+ }
5249+
5250+ error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td);
5251+ if (error != 0)
5252+ error = priv_check(td, PRIV_VFS_MOUNT_PERM);
5253+ if (error != 0) {
5254+ vput(devvp);
5255+ return (error);
5256+ }
5257+
5258+ /*
5259+ * Open device and try to mount it!
5260+ */
5261+ error = udf_mountfs(devvp, mp);
5262+ if (error != 0) {
5263+ vrele(devvp);
5264+ return (error);
5265+ }
5266+
5267+ vfs_mountedfrom(mp, fspec);
5268+ return (0);
5269+}
5270+
5271+
5272+int
5273+udf_unmount(struct mount *mp, int mntflags)
5274+{
5275+ struct udf_mount *ump;
5276+ int error, flags;
5277+
5278+ ump = VFSTOUDF(mp);
5279+ if (ump == NULL)
5280+ panic("UDF unmount: empty ump\n");
5281+
5282+ flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0;
5283+
5284+ error = vflush(mp, 0, flags, curthread);
5285+ if (error != 0)
5286+ return (error);
5287+
5288+ if (ump->iconv_d2l != NULL)
5289+ udf2_iconv->close(ump->iconv_d2l);
5290+
5291+ DROP_GIANT();
5292+ g_topology_lock();
5293+ g_vfs_close(ump->geomcp);
5294+ g_topology_unlock();
5295+ PICKUP_GIANT();
5296+ vrele(ump->devvp);
5297+ dev_rel(ump->devvp->v_rdev);
5298+
5299+ /* free our ump */
5300+ free_udf_mountinfo(mp);
5301+
5302+ /* free ump struct references */
5303+ mp->mnt_data = NULL;
5304+ MNT_ILOCK(mp);
5305+ mp->mnt_flag &= ~MNT_LOCAL;
5306+ MNT_IUNLOCK(mp);
5307+
5308+ return (0);
5309+}
5310+
5311+#if 0
5312+static int
5313+get_session_info(struct g_consumer *cp, struct udf_session_info *usi,
5314+ int session_num)
5315+{
5316+ int error;
5317+
5318+ bzero(usi, sizeof(struct udf_session_info));
5319+ usi->session_num = session_num;
5320+
5321+ error = cp->provider->geom->ioctl(cp->provider, UDFIOREADSESSIONINFO,
5322+ usi, 0, curthread);
5323+ if (error != 0) {
5324+ if (session_num != 0)
5325+ printf("Cannot mount selected session. This "
5326+ "device does not properly support multi-sessions "
5327+ "disc.");
5328+
5329+ printf("Warning, this device does not properly support "
5330+ "multi-sessions disc.");
5331+
5332+ return (error);
5333+ }
5334+
5335+ printf("Number of Sessions: %u\n", usi->num_sessions);
5336+ printf("Number of Tracks: %u\n", usi->num_tracks);
5337+ printf("First Track Number: %u\n", usi->first_track);
5338+ printf("Sector Size: %u\n", usi->sector_size);
5339+
5340+ printf("Session Number: %u\n", usi->session_num);
5341+ printf("Session Start Address: %u\n", usi->session_start_addr);
5342+ printf("Session End Address: %u\n", usi->session_end_addr);
5343+ printf("Last Written Address in Session: %u\n", usi->session_last_written);
5344+ printf("First Track Number of Session: %u\n", usi->session_first_track);
5345+ printf("Last Track of Session: %u\n", usi->session_last_track);
5346+
5347+ return (0);
5348+}
5349+#endif
5350+
5351+/*
5352+ * Helper function of udf_mount() that actually mounts the disc.
5353+ */
5354+static int
5355+udf_mountfs(struct vnode *devvp, struct mount *mp)
5356+{
5357+ struct g_consumer *cp;
5358+ struct udf_mount *ump = NULL;
5359+#if 0
5360+ struct udf_session_info usi;
5361+#endif
5362+ int error, len, num_anchors;
5363+ uint32_t bshift, logvol_integrity, numsecs; /*lb_size,*/
5364+ char *cs_local;
5365+ void *optdata = NULL;
5366+
5367+ /* Open a consumer. */
5368+ dev_ref(devvp->v_rdev);
5369+ DROP_GIANT();
5370+ g_topology_lock();
5371+ error = g_vfs_open(devvp, &cp, "udf2", 0);
5372+ g_topology_unlock();
5373+ PICKUP_GIANT();
5374+ VOP_UNLOCK(devvp, 0);
5375+ if (error != 0)
5376+ goto fail;
5377+
5378+ /* setup basic mount information */
5379+ mp->mnt_stat.f_fsid.val[0] = dev2udev(devvp->v_rdev);
5380+ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
5381+ mp->mnt_stat.f_namemax = UDF_MAX_NAMELEN;
5382+ if (devvp->v_rdev->si_iosize_max != 0)
5383+ mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
5384+ if (mp->mnt_iosize_max > MAXPHYS)
5385+ mp->mnt_iosize_max = MAXPHYS;
5386+ MNT_ILOCK(mp);
5387+ mp->mnt_flag |= MNT_LOCAL;
5388+#if __FreeBSD__ < 10
5389+ mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
5390+ MNTK_EXTENDED_SHARED;
5391+#else
5392+ mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED;
5393+#endif
5394+ MNT_IUNLOCK(mp);
5395+
5396+ ump = malloc(sizeof(struct udf_mount), M_UDFTEMP, M_WAITOK | M_ZERO);
5397+
5398+#if 0
5399+ /* init locks */
5400+ mutex_init(&ump->logvol_mutex, MUTEX_DEFAULT, IPL_NONE);
5401+ mutex_init(&ump->ihash_lock, MUTEX_DEFAULT, IPL_NONE);
5402+ mutex_init(&ump->get_node_lock, MUTEX_DEFAULT, IPL_NONE);
5403+ mutex_init(&ump->allocate_mutex, MUTEX_DEFAULT, IPL_NONE);
5404+ cv_init(&ump->dirtynodes_cv, "udfsync2");
5405+#endif
5406+
5407+ /* set up linkage */
5408+ mp->mnt_data = ump;
5409+ ump->vfs_mountp = mp;
5410+ ump->devvp = devvp;
5411+ ump->geomcp = cp;
5412+
5413+ /* read in options */
5414+ error = vfs_getopt(mp->mnt_optnew, "uid", &optdata, &len);
5415+ if (error != 0 || len != sizeof(uid_t)) {
5416+ error = EINVAL;
5417+ goto fail;
5418+ }
5419+ ump->anon_uid = *(uid_t *)optdata;
5420+
5421+ vfs_flagopt(mp->mnt_optnew, "override_uid", &ump->flags,
5422+ UDFMNT_OVERRIDE_UID);
5423+
5424+ error = vfs_getopt(mp->mnt_optnew, "gid", &optdata, &len);
5425+ if (error != 0 || len != sizeof(gid_t)) {
5426+ error = EINVAL;
5427+ goto fail;
5428+ }
5429+ ump->anon_gid = *(gid_t *)optdata;
5430+
5431+ vfs_flagopt(mp->mnt_optnew, "override_gid", &ump->flags,
5432+ UDFMNT_OVERRIDE_GID);
5433+
5434+ if (vfs_getopt(mp->mnt_optnew, "mode", &optdata, &len) == 0) {
5435+ if (len != sizeof(mode_t)) {
5436+ error = EINVAL;
5437+ goto fail;
5438+ }
5439+ ump->mode = *(gid_t *)optdata & ALLPERMS;
5440+ ump->flags |= UDFMNT_USE_MASK;
5441+ }
5442+
5443+ if (vfs_getopt(mp->mnt_optnew, "dirmode", &optdata, &len) == 0) {
5444+ if (len != sizeof(mode_t)) {
5445+ error = EINVAL;
5446+ goto fail;
5447+ }
5448+ ump->dirmode = *(gid_t *)optdata & ALLPERMS;
5449+ ump->flags |= UDFMNT_USE_DIRMASK;
5450+ }
5451+
5452+#if 0
5453+ printf("si_name: %s\n", devvp->v_rdev->si_name);
5454+ if (devvp->v_rdev->si_name[0] == 'c' &&
5455+ devvp->v_rdev->si_name[1] == 'd')
5456+ {
5457+ error = get_session_info(cp, &usi, 0);
5458+ if (error != 0)
5459+ goto fail;
5460+
5461+ ump->first_trackblank = usi.session_first_track_blank;
5462+ ump->session_start = usi.session_start_addr;
5463+ ump->session_end = usi.session_end_addr;
5464+ ump->session_last_written = usi.session_last_written;
5465+ } else {
5466+ ump->first_trackblank = 0;
5467+ ump->session_start = 0;
5468+ numsecs = cp->provider->mediasize / cp->provider->sectorsize;
5469+ ump->session_end = numsecs;
5470+ ump->session_last_written = numsecs;
5471+ }
5472+#endif
5473+
5474+ error = vfs_getopt(mp->mnt_optnew, "first_trackblank", &optdata, &len);
5475+ if (error != 0 || len != sizeof(uint8_t)) {
5476+ error = EINVAL;
5477+ goto fail;
5478+ }
5479+ ump->first_trackblank = *(uint8_t *)optdata;
5480+
5481+ error = vfs_getopt(mp->mnt_optnew, "session_start_addr", &optdata,
5482+ &len);
5483+ if (error != 0 || len != sizeof(uint32_t)) {
5484+ error = EINVAL;
5485+ goto fail;
5486+ }
5487+ ump->session_start = *(uint32_t *)optdata;
5488+
5489+ error = vfs_getopt(mp->mnt_optnew, "session_end_addr", &optdata, &len);
5490+ if (error != 0 || len != sizeof(uint32_t)) {
5491+ error = EINVAL;
5492+ goto fail;
5493+ }
5494+ ump->session_end = *(uint32_t *)optdata;
5495+
5496+ error = vfs_getopt(mp->mnt_optnew, "session_last_written", &optdata,
5497+ &len);
5498+ if (error != 0 || len != sizeof(uint32_t)) {
5499+ error = EINVAL;
5500+ goto fail;
5501+ }
5502+ ump->session_last_written = *(uint32_t *)optdata;
5503+
5504+ /* We do not want the session_end value to be zero. */
5505+ numsecs = cp->provider->mediasize / cp->provider->sectorsize;
5506+ if (ump->session_end == 0)
5507+ ump->session_end = numsecs;
5508+
5509+ /* We should only need to search one, so this is also a hack. */
5510+ if (ump->session_end - ump->session_start > 25)
5511+ ump->first_possible_vat_location = ump->session_last_written -
5512+ 25;
5513+ else
5514+ ump->first_possible_vat_location = ump->session_start;
5515+ ump->last_possible_vat_location = ump->session_last_written;
5516+
5517+ error = vfs_getopt(mp->mnt_optnew, "cs_local", (void **)&cs_local,
5518+ &len);
5519+ if (error == 0 && udf2_iconv != NULL) {
5520+ ump->flags |= UDFMNT_KICONV;
5521+
5522+ if (cs_local[len-1] != '\0') {
5523+ error = EINVAL;
5524+ goto fail;
5525+ }
5526+
5527+ udf2_iconv->open(cs_local, "UTF-16BE", &ump->iconv_d2l);
5528+ }
5529+
5530+ /* inspect sector size */
5531+ ump->sector_size = cp->provider->sectorsize;
5532+
5533+ bshift = 1;
5534+ while ((1 << bshift) < ump->sector_size)
5535+ bshift++;
5536+ if ((1 << bshift) != ump->sector_size) {
5537+ printf("UDF mount: hit implementation fence on sector size\n");
5538+ return (EIO);
5539+ }
5540+
5541+ /* temporary check to overcome sectorsize >= 8192 bytes panic */
5542+ if (ump->sector_size >= 8192) {
5543+ printf("UDF mount: hit implementation limit, sectorsize to "
5544+ "big\n");
5545+ return (EIO);
5546+ }
5547+
5548+
5549+ /* read all anchors to get volume descriptor sequence */
5550+ num_anchors = udf_read_anchors(ump);
5551+ if (num_anchors == 0) {
5552+ printf("UDF mount: error reading anchors\n");
5553+ error = EINVAL;
5554+ goto fail;
5555+ }
5556+
5557+ /* read in volume descriptor sequence */
5558+ error = udf_read_vds_space(ump);
5559+ if (error != 0) {
5560+ printf("UDF mount: error reading volume space\n");
5561+ goto fail;
5562+ }
5563+
5564+ /* check consistency and completeness */
5565+ error = udf_process_vds(ump);
5566+ if (error != 0) {
5567+ printf( "UDF mount: disc not properly formatted (bad VDS)\n");
5568+ goto fail;
5569+ }
5570+
5571+ /* note that the mp info needs to be initialised for reading! */
5572+ /* read vds support tables like VAT, sparable etc. */
5573+ error = udf_read_vds_tables(ump);
5574+ if (error != 0) {
5575+ printf("UDF mount: error in format or damaged disc "
5576+ "(VDS tables failing)\n");
5577+ goto fail;
5578+ }
5579+
5580+ /* check if volume integrity is closed otherwise its dirty */
5581+ logvol_integrity = le32toh(ump->logvol_integrity->integrity_type);
5582+ if (logvol_integrity != UDF_INTEGRITY_CLOSED) {
5583+ printf("UDF mount: file system was not cleanly unmounted.\n");
5584+#if 0
5585+ error = EPERM;
5586+ goto fail;
5587+#endif
5588+ }
5589+
5590+ /* read root directory */
5591+ error = udf_read_rootdirs(ump);
5592+ if (error != 0) {
5593+ printf("UDF mount: disc not properly formatted or damaged disc "
5594+ "(rootdirs failing)\n");
5595+ goto fail;
5596+ }
5597+
5598+ /* success! */
5599+ return (0);
5600+
5601+fail:
5602+ if (cp != NULL) {
5603+ DROP_GIANT();
5604+ g_topology_lock();
5605+ g_vfs_close(cp);
5606+ g_topology_unlock();
5607+ PICKUP_GIANT();
5608+ }
5609+ dev_rel(devvp->v_rdev);
5610+ if (ump != NULL)
5611+ free_udf_mountinfo(mp);
5612+
5613+ return (error);
5614+}
5615+
5616+int
5617+udf_root(struct mount *mp, int flags, struct vnode **vpp)
5618+{
5619+ struct udf_mount *ump = VFSTOUDF(mp);
5620+ ino_t ino;
5621+ int error;
5622+
5623+ error = udf_get_node_id(ump->fileset_desc->rootdir_icb, &ino);
5624+ if (error == 0)
5625+ error = udf_vget(mp, ino, flags, vpp);
5626+ if (error != 0 && ((*vpp)->v_vflag & VV_ROOT) == 0) {
5627+ printf("UDF: Internal error: invalid root node.");
5628+ return (EDOOFUS);
5629+ }
5630+
5631+ return (error);
5632+}
5633+
5634+int
5635+udf_statfs(struct mount *mp, struct statfs *sbp)
5636+{
5637+ struct udf_mount *ump = VFSTOUDF(mp);
5638+ struct logvol_int_desc *lvid;
5639+ struct udf_logvol_info *impl;
5640+ uint64_t files, freeblks, sizeblks;
5641+ int num_part;
5642+
5643+ udf_calc_freespace(ump, &sizeblks, &freeblks);
5644+
5645+ files = 0;
5646+ lvid = ump->logvol_integrity;
5647+ num_part = le32toh(lvid->num_part);
5648+ impl = (struct udf_logvol_info *)(lvid->tables + 2 * num_part);
5649+ if (impl != NULL) {
5650+ files = le32toh(impl->num_files);
5651+ files += le32toh(impl->num_directories);
5652+ }
5653+
5654+ sbp->f_version = STATFS_VERSION; /* structure version number */
5655+ /*uint32_t f_type;*/ /* type of filesystem */
5656+ sbp->f_flags = mp->mnt_flag; /* copy of mount exported flags */
5657+ sbp->f_bsize = ump->sector_size; /* filesystem fragment size */
5658+ sbp->f_iosize = ump->sector_size; /* optimal transfer block size */
5659+ sbp->f_blocks = sizeblks; /* total data blocks in filesystem */
5660+ sbp->f_bfree = freeblks; /* free blocks in filesystem */
5661+ sbp->f_bavail = 0; /* free blocks avail to non-superuser */
5662+ sbp->f_files = files; /* total file nodes in filesystem */
5663+ sbp->f_ffree = 0; /* free nodes avail to non-superuser */
5664+ /*uint64_t f_syncwrites;*/ /* count of sync writes since mount */
5665+ /*uint64_t f_asyncwrites;*/ /* count of async writes since mount */
5666+ /*uint64_t f_syncreads;*/ /* count of sync reads since mount */
5667+ /*uint64_t f_asyncreads;*/ /* count of async reads since mount */
5668+ /*uint64_t f_spare[10];*/ /* unused spare */
5669+ /*uint32_t f_namemax;*/ /* maximum filename length */
5670+ /*uid_t f_owner;*/ /* user that mounted the filesystem */
5671+ /*fsid_t f_fsid;*/ /* filesystem id */
5672+ /*char f_charspare[80];*/ /* spare string space */
5673+ /*char f_fstypename[MFSNAMELEN];*/ /* filesystem type name */
5674+ /*char f_mntfromname[MNAMELEN];*/ /* mounted filesystem */
5675+ /*char f_mntonname[MNAMELEN];*/ /* directory on which mounted */
5676+
5677+ return (0);
5678+}
5679+
5680+struct udf_node *
5681+udf_alloc_node()
5682+{
5683+ return (uma_zalloc(udf_zone_node, M_WAITOK | M_ZERO));
5684+}
5685+
5686+void
5687+udf_free_node(struct udf_node *unode)
5688+{
5689+ uma_zfree(udf_zone_node, unode);
5690+}
5691+
5692+/*
5693+ * Get vnode for the file system type specific file id ino for the fs. Its
5694+ * used for reference to files by unique ID and for NFSv3.
5695+ * (optional) TODO lookup why some sources state NFSv3
5696+ */
5697+int
5698+udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
5699+{
5700+ struct vnode *nvp;
5701+ struct udf_node *unode;
5702+ struct udf_mount *ump;
5703+ struct long_ad icb;
5704+ int error, udf_file_type;
5705+
5706+ error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
5707+ if (error != 0 || *vpp != NULL)
5708+ return (error);
5709+
5710+ if ((flags & LK_TYPE_MASK) == LK_SHARED) {
5711+ flags &= ~LK_TYPE_MASK;
5712+ flags |= LK_EXCLUSIVE;
5713+ }
5714+
5715+ ump = VFSTOUDF(mp);
5716+ error = udf_getanode(mp, &nvp);
5717+ if (error != 0)
5718+ return (error);
5719+
5720+ lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL);
5721+ error = insmntque(nvp, mp);
5722+ if (error != 0)
5723+ return (error);
5724+
5725+ error = vfs_hash_insert(nvp, ino, flags, curthread, vpp, NULL, NULL);
5726+ if (error != 0 || *vpp != NULL)
5727+ return (error);
5728+
5729+ /*
5730+ * Load read and set up the unode structure.
5731+ */
5732+ udf_get_node_longad(ino, &icb);
5733+ error = udf_get_node(ump, icb, &unode);
5734+ if (error != 0) {
5735+ vput(nvp);
5736+ return (error);
5737+ }
5738+ nvp->v_data = unode;
5739+ unode->vnode = nvp;
5740+ unode->hash_id = ino;
5741+
5742+ /* mark the root node as such */
5743+ if (ump->fileset_desc &&
5744+ icb.loc.lb_num == ump->fileset_desc->rootdir_icb.loc.lb_num &&
5745+ icb.loc.part_num == ump->fileset_desc->rootdir_icb.loc.part_num)
5746+ nvp->v_vflag |= VV_ROOT;
5747+
5748+ /*
5749+ * Translate UDF filetypes into vnode types.
5750+ *
5751+ * Systemfiles like the meta main and mirror files are not treated as
5752+ * normal files, so we type them as having no type. UDF dictates that
5753+ * they are not allowed to be visible.
5754+ */
5755+ if (unode->fe != NULL)
5756+ udf_file_type = unode->fe->icbtag.file_type;
5757+ else
5758+ udf_file_type = unode->efe->icbtag.file_type;
5759+
5760+ switch (udf_file_type) {
5761+ case UDF_ICB_FILETYPE_DIRECTORY:
5762+ case UDF_ICB_FILETYPE_STREAMDIR:
5763+ nvp->v_type = VDIR;
5764+ break;
5765+ case UDF_ICB_FILETYPE_BLOCKDEVICE:
5766+ nvp->v_type = VBLK;
5767+ break;
5768+ case UDF_ICB_FILETYPE_CHARDEVICE:
5769+ nvp->v_type = VCHR;
5770+ break;
5771+ case UDF_ICB_FILETYPE_SOCKET:
5772+ nvp->v_type = VSOCK;
5773+ break;
5774+ case UDF_ICB_FILETYPE_FIFO:
5775+ nvp->v_type = VFIFO;
5776+ break;
5777+ case UDF_ICB_FILETYPE_SYMLINK:
5778+ nvp->v_type = VLNK;
5779+ break;
5780+ case UDF_ICB_FILETYPE_VAT:
5781+ case UDF_ICB_FILETYPE_META_MAIN:
5782+ case UDF_ICB_FILETYPE_META_MIRROR:
5783+ nvp->v_type = VNON;
5784+ break;
5785+ case UDF_ICB_FILETYPE_RANDOMACCESS:
5786+ case UDF_ICB_FILETYPE_REALTIME:
5787+ nvp->v_type = VREG;
5788+ break;
5789+ default:
5790+ /* YIKES, something else */
5791+ nvp->v_type = VNON;
5792+ }
5793+
5794+ if (nvp->v_type != VFIFO)
5795+ VN_LOCK_ASHARE(nvp);
5796+
5797+ *vpp = nvp;
5798+
5799+ return (0);
5800+}
5801+
5802+/*
5803+ * Lookup vnode for file handle specified
5804+ */
5805+int
5806+udf_fhtovp(struct mount *mp, struct fid *fhp, int flags,
5807+ struct vnode **vpp)
5808+{
5809+ struct vnode *vp;
5810+ struct udf_fid *ufid = (struct udf_fid*)fhp;
5811+ struct udf_node *udf_node;
5812+ uint64_t filelen;
5813+ int error;
5814+
5815+ error = VFS_VGET(mp, ufid->ino, LK_EXCLUSIVE, &vp);
5816+ if (error != 0) {
5817+ *vpp = NULLVP;
5818+ return (error);
5819+ }
5820+
5821+ udf_node = VTOI(vp);
5822+ if (udf_node->efe != NULL)
5823+ filelen = le64toh(udf_node->efe->inf_len);
5824+ else
5825+ filelen = le64toh(udf_node->fe->inf_len);
5826+
5827+ vnode_create_vobject(vp, filelen, curthread);
5828+ *vpp = vp;
5829+
5830+ return (0);
5831+}
5832+
5833
5834--- sys/fs/udf2/udf_vnops.c 1969-12-31 16:00:00.000000000 -0800
5835+++ updates/sys/fs/udf2/udf_vnops.c 2014-11-16 16:27:23.000000000 -0800
5836@@ -0,0 +1,1337 @@
5837+/*-
5838+ * Copyright (c) 2013 Will DeVries
5839+ * Copyright (c) 2006, 2008 Reinoud Zandijk
5840+ * All rights reserved.
5841+ *
5842+ * Redistribution and use in source and binary forms, with or without
5843+ * modification, are permitted provided that the following conditions
5844+ * are met:
5845+ * 1. Redistributions of source code must retain the above copyright
5846+ * notice, this list of conditions and the following disclaimer.
5847+ * 2. Redistributions in binary form must reproduce the above copyright
5848+ * notice, this list of conditions and the following disclaimer in the
5849+ * documentation and/or other materials provided with the distribution.
5850+ *
5851+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5852+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5853+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5854+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5855+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5856+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5857+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5858+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5859+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5860+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5861+ *
5862+ * Generic parts are derived from software contributed to The NetBSD Foundation
5863+ * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
5864+ * 2005 program.
5865+ *
5866+ */
5867+
5868+#include <sys/param.h>
5869+#include <sys/cdefs.h>
5870+#include <sys/endian.h>
5871+#include <sys/systm.h>
5872+#include <sys/namei.h>
5873+#include <sys/buf.h>
5874+#include <sys/mount.h>
5875+#include <sys/vnode.h>
5876+#include <sys/malloc.h>
5877+#include <sys/dirent.h>
5878+#include <sys/unistd.h>
5879+#include <sys/bio.h>
5880+#include <sys/stat.h>
5881+#include <sys/rwlock.h>
5882+
5883+#include <vm/vm.h>
5884+#include <vm/vm_page.h>
5885+#include <vm/vm_object.h>
5886+#include <vm/vm_pager.h>
5887+
5888+#if __FreeBSD__ < 10
5889+#include <fs/fifofs/fifo.h>
5890+#endif
5891+
5892+#include "ecma167-udf.h"
5893+#include "udf.h"
5894+#include "udf_subr.h"
5895+
5896+static int udf_pbuf_freecnt = -1;
5897+
5898+static vop_access_t udf_access;
5899+static vop_bmap_t udf_bmap;
5900+static vop_cachedlookup_t udf_cachedlookup;
5901+static vop_getattr_t udf_getattr;
5902+static vop_ioctl_t udf_ioctl;
5903+static vop_open_t udf_open;
5904+static vop_pathconf_t udf_pathconf;
5905+static vop_print_t udf_print;
5906+static vop_read_t udf_read;
5907+static vop_readdir_t udf_readdir;
5908+static vop_readlink_t udf_readlink;
5909+static vop_reclaim_t udf_reclaim;
5910+static vop_setattr_t udf_setattr;
5911+static vop_strategy_t udf_strategy;
5912+static vop_vptofh_t udf_vptofh;
5913+static vop_getpages_t udf_getpages;
5914+
5915+static struct vop_vector udf_vnodeops = {
5916+ .vop_default = &default_vnodeops,
5917+ .vop_access = udf_access,
5918+ .vop_getattr = udf_getattr,
5919+ .vop_open = udf_open,
5920+ .vop_ioctl = udf_ioctl,
5921+ .vop_pathconf = udf_pathconf,
5922+ .vop_print = udf_print,
5923+ .vop_read = udf_read,
5924+ .vop_readdir = udf_readdir,
5925+ .vop_readlink = udf_readlink,
5926+ .vop_setattr = udf_setattr,
5927+ .vop_strategy = udf_strategy,
5928+ .vop_bmap = udf_bmap,
5929+ .vop_cachedlookup = udf_cachedlookup,
5930+ .vop_reclaim = udf_reclaim,
5931+ .vop_vptofh = udf_vptofh,
5932+ .vop_lookup = vfs_cache_lookup,
5933+ .vop_getpages = udf_getpages
5934+};
5935+
5936+struct vop_vector udf_fifoops = {
5937+ .vop_access = udf_access,
5938+ .vop_getattr = udf_getattr,
5939+ .vop_print = udf_print,
5940+ .vop_setattr = udf_setattr,
5941+ .vop_reclaim = udf_reclaim,
5942+ .vop_vptofh = udf_vptofh,
5943+ .vop_default = &fifo_specops,
5944+};
5945+
5946+/* implementations of vnode functions; table follows at end */
5947+
5948+
5949+int
5950+udf_getanode(struct mount *mp, struct vnode **vpp)
5951+{
5952+ return (getnewvnode("udf2", mp, &udf_vnodeops, vpp));
5953+}
5954+
5955+static int
5956+udf_reclaim(struct vop_reclaim_args *ap)
5957+{
5958+ struct vnode *vp = ap->a_vp;
5959+ struct udf_node *udf_node = VTOI(vp);
5960+
5961+ vnode_destroy_vobject(vp);
5962+
5963+ if (udf_node == NULL)
5964+ return (0);
5965+
5966+ /* dispose all node knowledge */
5967+ vfs_hash_remove(vp);
5968+ udf_dispose_node(udf_node);
5969+ vp->v_data = NULL;
5970+
5971+ return (0);
5972+}
5973+
5974+static int
5975+udf_read(struct vop_read_args *ap)
5976+{
5977+ struct vnode *vp = ap->a_vp;
5978+ struct uio *uio = ap->a_uio;
5979+ struct buf *bp;
5980+ struct udf_node *udf_node = VTOI(vp);
5981+ uint64_t fsize;
5982+ int seqcount, lbn, n, on, sector_size;
5983+ int error = 0;
5984+ uint8_t *zerobuf;
5985+
5986+ /* can this happen? some filingsystems have this check */
5987+ if (uio->uio_offset < 0)
5988+ return (EINVAL);
5989+ if (uio->uio_resid == 0)
5990+ return (0);
5991+
5992+#ifdef INVARIANTS
5993+ /* As in ffs_read() */
5994+ if (vp->v_type != VDIR && vp->v_type != VREG)
5995+ panic("udf_read: type %d", vp->v_type);
5996+#endif
5997+
5998+ /* get file/directory filesize */
5999+ if (udf_node->fe != NULL)
6000+ fsize = le64toh(udf_node->fe->inf_len);
6001+ else
6002+ fsize = le64toh(udf_node->efe->inf_len);
6003+
6004+ sector_size = udf_node->ump->sector_size;
6005+
6006+ seqcount = ap->a_ioflag >> IO_SEQSHIFT;
6007+
6008+ while (error == 0 && uio->uio_resid > 0 && fsize > uio->uio_offset) {
6009+ lbn = uio->uio_offset / sector_size;
6010+ on = uio->uio_offset % sector_size;
6011+
6012+ n = min(sector_size - on, uio->uio_resid);
6013+ n = min(n, fsize - uio->uio_offset);
6014+
6015+ if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0 &&
6016+ sector_size * (lbn + 1) < fsize) {
6017+#if __FreeBSD__ < 10
6018+ error = cluster_read(vp, fsize, lbn, sector_size,
6019+ NOCRED, on + uio->uio_resid, seqcount, &bp);
6020+#else
6021+ error = cluster_read(vp, fsize, lbn, sector_size,
6022+ NOCRED, on + uio->uio_resid, seqcount, 0, &bp);
6023+#endif
6024+ } else {
6025+ error = bread(vp, lbn, sector_size, NOCRED, &bp);
6026+ }
6027+
6028+ n = min(n, sector_size - bp->b_resid);
6029+
6030+ if (error == 0)
6031+ error = uiomove(bp->b_data + on, n, uio);
6032+
6033+ brelse(bp);
6034+ }
6035+
6036+ if (vp->v_type == VDIR && fsize <= uio->uio_offset &&
6037+ uio->uio_resid > 0) {
6038+ zerobuf = malloc(2048, M_UDFTEMP, M_WAITOK | M_ZERO);
6039+ while (error == 0 && uio->uio_resid > 0) {
6040+ n = min(2048, uio->uio_resid);
6041+ error = uiomove(zerobuf, n, uio);
6042+ }
6043+ free(zerobuf, M_UDFTEMP);
6044+ }
6045+
6046+ return (error);
6047+}
6048+
6049+static int
6050+udf_bmap(struct vop_bmap_args /* {
6051+ struct vnode *a_vp;
6052+ daddr_t a_bn;
6053+ struct bufobj **a_bop;
6054+ daddr_t *a_bnp;
6055+ int *a_runp;
6056+ int *a_runb;
6057+ } */ *ap)
6058+{
6059+ struct vnode *vp = ap->a_vp;
6060+ struct udf_node *udf_node = VTOI(vp);
6061+ uint64_t lsector;
6062+ int error, exttype;
6063+ uint32_t maxblks;
6064+
6065+ if (ap->a_bop != NULL)
6066+ *ap->a_bop = &ap->a_vp->v_bufobj;
6067+
6068+ if (ap->a_bnp == NULL)
6069+ return (0);
6070+
6071+ /* get logical block and run */
6072+ error = udf_bmap_translate(udf_node, ap->a_bn, &exttype, &lsector,
6073+ &maxblks);
6074+ if (error != 0)
6075+ return (error);
6076+
6077+ /* convert to dev blocks */
6078+ if (exttype == UDF_TRAN_INTERN)
6079+ *ap->a_bnp = INT64_MAX - 2;
6080+ else if (exttype == UDF_TRAN_ZERO)
6081+ *ap->a_bnp = INT64_MAX - 1; /* zero the buffer */
6082+ else
6083+ *ap->a_bnp = lsector * (udf_node->ump->sector_size/DEV_BSIZE);
6084+
6085+ /* set runlength of maximum block size */
6086+ if (ap->a_runp != NULL)
6087+ *ap->a_runp = maxblks - 1;
6088+
6089+ if (ap->a_runb != NULL)
6090+ *ap->a_runb = 0;
6091+
6092+ /* return success */
6093+ return (0);
6094+}
6095+
6096+static int
6097+udf_strategy(struct vop_strategy_args *ap)
6098+{
6099+ struct vnode *vp = ap->a_vp;
6100+ struct buf *bp = ap->a_bp;
6101+ struct udf_node *udf_node = VTOI(vp);
6102+ struct bufobj *bo = &udf_node->ump->devvp->v_bufobj;
6103+ uint64_t lsector;
6104+ int error, exttype;
6105+ uint32_t sector_size, maxblks;
6106+
6107+ if (vp->v_type == VBLK || vp->v_type == VCHR)
6108+ panic("udf_strategy: spec");
6109+
6110+ /* get sector size */
6111+ sector_size = udf_node->ump->sector_size;
6112+
6113+
6114+ /* get logical block and run */
6115+ if (bp->b_blkno == bp->b_lblkno) {
6116+ error = udf_bmap_translate(udf_node, bp->b_lblkno, &exttype,
6117+ &lsector, &maxblks);
6118+
6119+ if (error != 0) {
6120+ bp->b_error = error;
6121+ bp->b_ioflags |= BIO_ERROR;
6122+ bufdone(bp);
6123+ return (error);
6124+ }
6125+
6126+ if (exttype == UDF_TRAN_ZERO) {
6127+ bp->b_blkno = INT64_MAX - 1;
6128+ vfs_bio_clrbuf(bp);
6129+ }
6130+ else if (exttype == UDF_TRAN_INTERN)
6131+ bp->b_blkno = INT64_MAX - 2;
6132+ else
6133+ bp->b_blkno = lsector * (sector_size / DEV_BSIZE);
6134+ }
6135+
6136+ if ((bp->b_iocmd & BIO_READ) == 0)
6137+ return (ENOTSUP);
6138+
6139+ if (bp->b_blkno == INT64_MAX - 1) {
6140+ bufdone(bp);
6141+//printf("UDF: Hole in file found. (This is a debuging statement, not an error.\n");
6142+ } else if (bp->b_blkno == INT64_MAX - 2) {
6143+ error = udf_read_internal(udf_node, (uint8_t *)bp->b_data);
6144+ if (error != 0) {
6145+ bp->b_error = error;
6146+ bp->b_ioflags |= BIO_ERROR;
6147+ }
6148+ bufdone(bp);
6149+ } else {
6150+ bp->b_iooffset = dbtob(bp->b_blkno);
6151+ BO_STRATEGY(bo, bp);
6152+ }
6153+
6154+ return (bp->b_error);
6155+}
6156+
6157+static int
6158+udf_readdir(struct vop_readdir_args *ap)
6159+{
6160+ struct uio *uio;
6161+ struct vnode *vp;
6162+ struct fileid_desc *fid;
6163+ struct dirent *dirent;
6164+ struct udf_mount *ump;
6165+ struct udf_node *udf_node;
6166+ uint64_t file_size;
6167+ u_long *cookies, *cookiesp;
6168+ off_t diroffset, transoffset;
6169+ int acookies, error, ncookies, size;
6170+ uint32_t lb_size;
6171+ uint8_t *fid_name;
6172+
6173+ error = 0;
6174+ uio = ap->a_uio;
6175+ vp = ap->a_vp;
6176+ udf_node = VTOI(vp);
6177+ ump = udf_node->ump;
6178+ transoffset = uio->uio_offset;
6179+
6180+ /* This operation only makes sense on directory nodes. */
6181+ if (vp->v_type != VDIR)
6182+ return (ENOTDIR);
6183+
6184+ /* get directory filesize */
6185+ if (udf_node->fe != NULL)
6186+ file_size = le64toh(udf_node->fe->inf_len);
6187+ else
6188+ file_size = le64toh(udf_node->efe->inf_len);
6189+
6190+ dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK | M_ZERO);
6191+ if (ap->a_ncookies != NULL) {
6192+ /* is this the max number possible? */
6193+ ncookies = uio->uio_resid / 8;
6194+ if (ncookies > 1024)
6195+ ncookies = 1024;
6196+ cookies = malloc(sizeof(u_long) * ncookies, M_TEMP,
6197+ M_WAITOK | M_ZERO);
6198+ cookiesp = cookies;
6199+ } else {
6200+ ncookies = 0;
6201+ cookies = NULL;
6202+ cookiesp = NULL;
6203+ }
6204+ acookies = 0;
6205+
6206+ /* The directory '.' is not in the fid stream. */
6207+ if (transoffset == 0) {
6208+ memset(dirent, 0, sizeof(struct dirent));
6209+ dirent->d_fileno = udf_node->hash_id;
6210+ dirent->d_type = DT_DIR;
6211+ dirent->d_name[0] = '.';
6212+ dirent->d_name[1] = '\0';
6213+ dirent->d_namlen = 1;
6214+ dirent->d_reclen = GENERIC_DIRSIZ(dirent);
6215+
6216+ if (uio->uio_resid >= dirent->d_reclen)
6217+ {
6218+ if (cookiesp != NULL) {
6219+ acookies++;
6220+ *cookiesp++ = 1; // next one
6221+ }
6222+ error = uiomove(dirent, dirent->d_reclen, uio);
6223+ if (error != 0)
6224+ goto bail;
6225+
6226+ transoffset = 1;
6227+ }
6228+ }
6229+
6230+ /* allocate temporary space for fid */
6231+ lb_size = ump->sector_size;
6232+ fid = malloc(lb_size, M_UDFTEMP, M_WAITOK);
6233+
6234+ /* we are called just as long as we keep on pushing data in */
6235+ if (transoffset == 1)
6236+ diroffset = 0;
6237+ else
6238+ diroffset = transoffset;
6239+
6240+ while (diroffset < file_size) {
6241+ /* transfer a new fid/dirent */
6242+ memset(fid, 0, lb_size);
6243+ size = MIN(file_size - diroffset, lb_size);
6244+
6245+ error = vn_rdwr(UIO_READ, vp, fid, size, diroffset,
6246+ UIO_SYSSPACE, IO_NODELOCKED, FSCRED, NULL, NULL,
6247+ curthread);
6248+ if (error != 0) {
6249+ printf("UDF: Error reading fid: %d\n", error);
6250+ break;
6251+ }
6252+
6253+ error = udf_validate_fid(fid, &size);
6254+ if (error != 0) {
6255+ printf("UDF: Invalid fid found: %d\n", error);
6256+ break;
6257+ }
6258+
6259+ diroffset += size;
6260+
6261+ /* skip deleted and not visible files */
6262+ if (fid->file_char & UDF_FILE_CHAR_DEL ||
6263+ fid->file_char & UDF_FILE_CHAR_VIS) {
6264+ transoffset = diroffset;
6265+ if (cookiesp != NULL && acookies > 0)
6266+ *(cookiesp - 1) = transoffset;
6267+ continue;
6268+ }
6269+
6270+ /* create resulting dirent structure */
6271+ memset(dirent, 0, sizeof(struct dirent));
6272+ error = udf_get_node_id(fid->icb, &dirent->d_fileno); /* inode hash XXX */
6273+ if (error != 0)
6274+ break;
6275+
6276+ /* Going for the filetypes now is too expensive. */
6277+ dirent->d_type = DT_UNKNOWN;
6278+ if (fid->file_char & UDF_FILE_CHAR_DIR)
6279+ dirent->d_type = DT_DIR;
6280+
6281+ /* '..' has no name, so provide one */
6282+ if (fid->file_char & UDF_FILE_CHAR_PAR) {
6283+ dirent->d_name[0] = '.';
6284+ dirent->d_name[1] = '.';
6285+ dirent->d_name[2] = '\0';
6286+ dirent->d_namlen = 2;
6287+ } else {
6288+ fid_name = fid->data + le16toh(fid->l_iu);
6289+ udf_to_unix_name(ump, dirent->d_name, MAXNAMLEN,
6290+ fid_name, fid->l_fi);
6291+ dirent->d_namlen = strlen(dirent->d_name);
6292+ }
6293+
6294+ dirent->d_reclen = GENERIC_DIRSIZ(dirent);
6295+
6296+ /*
6297+ * If there isn't enough space in the uio to return a
6298+ * whole dirent, break off read
6299+ */
6300+ if (uio->uio_resid < dirent->d_reclen)
6301+ break;
6302+
6303+ /* copy dirent to the caller */
6304+ if (cookiesp != NULL) {
6305+ if (acookies + 1 > ncookies)
6306+ break;
6307+ acookies++;
6308+ *cookiesp++ = diroffset;
6309+ }
6310+
6311+ /* remember the last entry we transfered */
6312+ transoffset = diroffset;
6313+
6314+ error = uiomove(dirent, dirent->d_reclen, uio);
6315+ if (error != 0)
6316+ break;
6317+ }
6318+
6319+ /* pass on last transfered offset */
6320+ /* We lied for '.', so tell more lies. */
6321+ free(fid, M_UDFTEMP);
6322+
6323+ uio->uio_offset = transoffset;
6324+
6325+bail:
6326+ if (ap->a_eofflag != NULL)
6327+ *ap->a_eofflag = uio->uio_offset >= file_size;
6328+
6329+ if (ap->a_ncookies != NULL) {
6330+ if (error != 0)
6331+ free(cookies, M_UDFTEMP);
6332+ else {
6333+ *ap->a_ncookies = acookies;
6334+ *ap->a_cookies = cookies;
6335+ }
6336+ }
6337+ free(dirent, M_UDFTEMP);
6338+
6339+ return (error);
6340+}
6341+
6342+static int
6343+udf_cachedlookup(struct vop_cachedlookup_args *ap)
6344+{
6345+ struct vnode *dvp = ap->a_dvp;
6346+ struct vnode **vpp = ap->a_vpp;
6347+ struct vnode *tdp = NULL;
6348+ struct componentname *cnp = ap->a_cnp;
6349+ struct fileid_desc *fid;
6350+ struct udf_node *dir_node;
6351+ struct udf_mount *ump;
6352+ uint64_t file_size, offset;
6353+ ino_t id = 0;
6354+ int error, islastcn, ltype, mounted_ro, nameiop, numpasses, unix_len;
6355+ int size;
6356+ uint8_t *fid_name;
6357+ char *unix_name;
6358+
6359+ dir_node = VTOI(dvp);
6360+ ump = dir_node->ump;
6361+ *vpp = NULL;
6362+ error = 0;
6363+
6364+ /* simplify/clarification flags */
6365+ nameiop = cnp->cn_nameiop;
6366+ islastcn = cnp->cn_flags & ISLASTCN;
6367+ mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY;
6368+
6369+ /*
6370+ * If requesting a modify on the last path element on a read-only
6371+ * filingsystem, reject lookup; XXX why is this repeated in every FS ?
6372+ */
6373+ if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
6374+ return (EROFS);
6375+
6376+ /* get directory filesize */
6377+ if (dir_node->fe != NULL)
6378+ file_size = le64toh(dir_node->fe->inf_len);
6379+ else
6380+ file_size = le64toh(dir_node->efe->inf_len);
6381+
6382+ if (nameiop != LOOKUP || dir_node->diroff == 0 ||
6383+ dir_node->diroff > file_size) {
6384+ offset = 0;
6385+ numpasses = 1;
6386+ }
6387+ else {
6388+ offset = dir_node->diroff;
6389+ numpasses = 2;
6390+ nchstats.ncs_2passes++;
6391+ }
6392+
6393+ fid = malloc(ump->sector_size, M_UDFTEMP, M_WAITOK);
6394+ unix_name = malloc(MAXNAMLEN, M_UDFTEMP, M_WAITOK);
6395+lookuploop:
6396+ while (offset < file_size) {
6397+ /* transfer a new fid/dirent */
6398+ memset(fid, 0, ump->sector_size);
6399+ size = MIN(file_size - offset, ump->sector_size);
6400+
6401+ error = vn_rdwr(UIO_READ, dvp, fid, size, offset, UIO_SYSSPACE,
6402+ IO_NODELOCKED, FSCRED, NULL, NULL, curthread);
6403+ if (error != 0) {
6404+ printf("UDF: Error reading fid: %d\n", error);
6405+ break;
6406+ }
6407+
6408+ error = udf_validate_fid(fid, &size);
6409+ if (error != 0) {
6410+ printf("UDF: Invalid fid found: %d\n", error);
6411+ break;
6412+ }
6413+
6414+ offset += size;
6415+
6416+ /* skip deleted entries */
6417+ if (fid->file_char & UDF_FILE_CHAR_DEL)
6418+ continue;
6419+
6420+ /* skip not visible files */
6421+ if (fid->file_char & UDF_FILE_CHAR_VIS)
6422+ continue;
6423+
6424+ if (fid->file_char & UDF_FILE_CHAR_PAR) {
6425+ if (cnp->cn_flags & ISDOTDOT) {
6426+ error = udf_get_node_id(fid->icb, &id);
6427+ break;
6428+ }
6429+ }
6430+ else {
6431+ fid_name = fid->data + le16toh(fid->l_iu);
6432+ udf_to_unix_name(ump, unix_name, MAXNAMLEN, fid_name,
6433+ fid->l_fi);
6434+ unix_len = strlen(unix_name);
6435+
6436+ if (unix_len == cnp->cn_namelen) {
6437+ if (!strncmp(unix_name, cnp->cn_nameptr,
6438+ cnp->cn_namelen)) {
6439+ error = udf_get_node_id(fid->icb, &id);
6440+ break;
6441+ }
6442+ }
6443+ }
6444+ }
6445+
6446+ if (error != 0)
6447+ goto exit;
6448+
6449+ if (id != 0) {
6450+ if ((cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == LOOKUP)
6451+ dir_node->diroff = offset;
6452+ if (numpasses == 2)
6453+ nchstats.ncs_pass2++;
6454+
6455+ if (cnp->cn_flags & ISDOTDOT)
6456+ vn_vget_ino(dvp, id, cnp->cn_lkflags, &tdp);
6457+ else if (dir_node->hash_id == id) {
6458+ /* through a glass darkly... */
6459+ VREF(dvp);
6460+ ltype = cnp->cn_lkflags & LK_TYPE_MASK;
6461+ if (ltype != VOP_ISLOCKED(dvp)) {
6462+ if (ltype == LK_EXCLUSIVE)
6463+ vn_lock(dvp, LK_UPGRADE | LK_RETRY);
6464+ else
6465+ vn_lock(dvp, LK_DOWNGRADE | LK_RETRY);
6466+ }
6467+ tdp = dvp;
6468+ } else
6469+ error = udf_vget(ump->vfs_mountp, id, cnp->cn_lkflags,
6470+ &tdp);
6471+
6472+ if (error == 0) {
6473+ *vpp = tdp;
6474+ if (cnp->cn_flags & MAKEENTRY)
6475+ cache_enter(dvp, *vpp, cnp);
6476+ }
6477+ }
6478+ else {
6479+ if (numpasses-- == 2) {
6480+ offset = 0;
6481+ goto lookuploop;
6482+ }
6483+
6484+ if (cnp->cn_flags & MAKEENTRY)
6485+ cache_enter(dvp, *vpp, cnp);
6486+
6487+ if ((cnp->cn_flags & ISLASTCN) &&
6488+ (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
6489+ error = EROFS;
6490+ else
6491+ error = ENOENT;
6492+ }
6493+
6494+exit:
6495+ free(fid, M_UDFTEMP);
6496+ free(unix_name, M_UDFTEMP);
6497+
6498+ return (error);
6499+}
6500+
6501+static int
6502+udf_getattr(struct vop_getattr_args *ap)
6503+{
6504+ struct vnode *vp = ap->a_vp;
6505+ struct udf_node *udf_node = VTOI(vp);
6506+ struct file_entry *fe = udf_node->fe;
6507+ struct extfile_entry *efe = udf_node->efe;
6508+ struct filetimes_extattr_entry *ft_extattr;
6509+ struct device_extattr_entry *devattr;
6510+ struct vattr *vap = ap->a_vap;
6511+ struct timestamp *atime, *attrtime, *creatime, *mtime;
6512+ struct udf_mount *ump = udf_node->ump;
6513+ uint64_t blkssize, filesize;
6514+ gid_t gid;
6515+ int error;
6516+ uid_t uid;
6517+ uint32_t a_l, nlink, offset;
6518+ uint8_t *filedata;
6519+
6520+ /* get descriptor information */
6521+ if (fe != NULL) {
6522+ nlink = le16toh(fe->link_cnt);
6523+ uid = (uid_t)le32toh(fe->uid);
6524+ gid = (gid_t)le32toh(fe->gid);
6525+ filesize = le64toh(fe->inf_len);
6526+ blkssize = le64toh(fe->logblks_rec);
6527+ atime = &fe->atime;
6528+ mtime = &fe->mtime;
6529+ attrtime = &fe->attrtime;
6530+ filedata = fe->data;
6531+
6532+ /* initial guess */
6533+ creatime = mtime;
6534+
6535+ /* check our extended attribute if present */
6536+ error = udf_extattr_search_intern(udf_node,
6537+ UDF_FILETIMES_ATTR_NO, "", &offset, &a_l);
6538+ if (error == 0) {
6539+ ft_extattr = (struct filetimes_extattr_entry *)
6540+ (filedata + offset);
6541+ if (ft_extattr->existence & UDF_FILETIMES_FILE_CREATION)
6542+ creatime = &ft_extattr->times[0];
6543+ }
6544+ } else {
6545+ nlink = le16toh(efe->link_cnt);
6546+ uid = (uid_t)le32toh(efe->uid);
6547+ gid = (gid_t)le32toh(efe->gid);
6548+ filesize = le64toh(efe->inf_len); /* XXX or obj_size? */
6549+ blkssize = le64toh(efe->logblks_rec);
6550+ atime = &efe->atime;
6551+ mtime = &efe->mtime;
6552+ attrtime = &efe->attrtime;
6553+ creatime = &efe->ctime;
6554+ filedata = efe->data;
6555+ }
6556+
6557+ /* do the uid/gid translation game */
6558+ if (uid == (uid_t)-1 || ump->flags & UDFMNT_OVERRIDE_UID)
6559+ uid = ump->anon_uid;
6560+ if (gid == (gid_t)-1 || ump->flags & UDFMNT_OVERRIDE_GID)
6561+ gid = ump->anon_gid;
6562+
6563+ /*
6564+ * BUG-ALERT: UDF doesn't count '.' as an entry, so we'll have to add
6565+ * 1 to the link count if its a directory we're requested attributes
6566+ * of.
6567+ */
6568+ if (vp->v_type == VDIR) {
6569+ nlink++;
6570+
6571+ /* directories should be at least a single block? */
6572+ if (blkssize != 0)
6573+ filesize = blkssize * ump->sector_size;
6574+ else
6575+ filesize = ump->sector_size;
6576+ }
6577+
6578+ /* fill in struct vattr with values from the node */
6579+ vattr_null(vap);
6580+ vap->va_type = vp->v_type;
6581+ vap->va_mode = udf_getaccessmode(udf_node);
6582+ if (vap->va_type == VDIR && ump->flags & UDFMNT_USE_DIRMASK)
6583+ vap->va_mode = (vap->va_mode & ~ALLPERMS) | ump->dirmode;
6584+ else if (vap->va_type != VDIR && ump->flags & UDFMNT_USE_MASK)
6585+ vap->va_mode = (vap->va_mode & ~ALLPERMS) | ump->mode;
6586+ vap->va_nlink = nlink;
6587+ vap->va_uid = uid;
6588+ vap->va_gid = gid;
6589+ vap->va_fsid = dev2udev(ump->devvp->v_rdev);
6590+ vap->va_fileid = udf_node->hash_id;
6591+ vap->va_size = filesize;
6592+ vap->va_blocksize = ump->sector_size; /* wise? */
6593+
6594+ /* access times */
6595+ udf_timestamp_to_timespec(ump, atime, &vap->va_atime);
6596+ udf_timestamp_to_timespec(ump, mtime, &vap->va_mtime);
6597+ udf_timestamp_to_timespec(ump, attrtime, &vap->va_ctime);
6598+ udf_timestamp_to_timespec(ump, creatime, &vap->va_birthtime);
6599+
6600+ vap->va_gen = 1; /* no multiple generations yes (!?) */
6601+ vap->va_flags = 0;
6602+ vap->va_bytes = blkssize * ump->sector_size;
6603+ vap->va_filerev = 0; /* TODO file revision numbers? */
6604+ vap->va_vaflags = 0;
6605+ /* TODO get vaflags from the extended attributes? */
6606+
6607+ if (vap->va_type == VBLK || vap->va_type == VCHR) {
6608+ error = udf_extattr_search_intern(udf_node,
6609+ UDF_DEVICESPEC_ATTR_NO, "", &offset, &a_l);
6610+ /* if error, deny access */
6611+ if (error != 0 || filedata == NULL)
6612+ vap->va_mode = 0; /* or v_type = VNON? */
6613+ else {
6614+ devattr = (struct device_extattr_entry *)filedata +
6615+ offset;
6616+ vap->va_rdev = makedev(le32toh(devattr->major),
6617+ le32toh(devattr->minor));
6618+ /* TODO we could check the implementator */
6619+ }
6620+ }
6621+
6622+ return (0);
6623+}
6624+
6625+static int
6626+udf_setattr(struct vop_setattr_args *ap)
6627+{
6628+ struct vattr *vap = ap->a_vap;
6629+
6630+ /* Abort if any unsettable attribute is given. */
6631+ if (vap->va_type != VNON ||
6632+ vap->va_nlink != VNOVAL ||
6633+ vap->va_fsid != VNOVAL ||
6634+ vap->va_fileid != VNOVAL ||
6635+ vap->va_blocksize != VNOVAL ||
6636+ vap->va_gen != VNOVAL ||
6637+ vap->va_rdev != VNOVAL ||
6638+ vap->va_bytes != VNOVAL)
6639+ return (EINVAL);
6640+
6641+ if (vap->va_flags != VNOVAL ||
6642+ vap->va_mode != (mode_t)VNOVAL ||
6643+ vap->va_atime.tv_sec != VNOVAL ||
6644+ vap->va_mtime.tv_sec != VNOVAL ||
6645+ vap->va_uid != VNOVAL ||
6646+ vap->va_gid != VNOVAL) {
6647+ return (EROFS);
6648+ }
6649+
6650+ if (vap->va_size != VNOVAL) {
6651+ if (vap->va_type == VDIR)
6652+ return (EISDIR);
6653+ if (vap->va_type == VLNK || vap->va_type == VREG)
6654+ return (EROFS);
6655+ }
6656+
6657+ return (0);
6658+}
6659+
6660+/*
6661+ * Return POSIX pathconf information for UDF file systems.
6662+ */
6663+static int
6664+udf_pathconf(struct vop_pathconf_args *ap)
6665+{
6666+ switch (ap->a_name) {
6667+ case _PC_LINK_MAX:
6668+ *ap->a_retval = (1 << 16) - 1; /* 16 bits */
6669+ return (0);
6670+ case _PC_NAME_MAX:
6671+ *ap->a_retval = NAME_MAX;
6672+ return (0);
6673+ case _PC_PATH_MAX:
6674+ *ap->a_retval = PATH_MAX;
6675+ return (0);
6676+ case _PC_PIPE_BUF:
6677+ *ap->a_retval = PIPE_BUF;
6678+ return (0);
6679+ case _PC_CHOWN_RESTRICTED:
6680+ *ap->a_retval = 1;
6681+ return (0);
6682+ case _PC_NO_TRUNC:
6683+ *ap->a_retval = 1;
6684+ return (0);
6685+ case _PC_SYNC_IO:
6686+ *ap->a_retval = 0; /* synchronised is off for performance */
6687+ return (0);
6688+ case _PC_FILESIZEBITS:
6689+ /* 64 bit file offsets -> 2+floor(2log(2^64-1)) = 2 + 63 = 65 */
6690+ *ap->a_retval = 64; /* XXX ought to deliver 65 */
6691+ return (0);
6692+ }
6693+
6694+ return (EINVAL);
6695+}
6696+
6697+static int
6698+udf_open(struct vop_open_args *ap)
6699+{
6700+ struct udf_node *udf_node;
6701+ off_t file_size;
6702+
6703+ udf_node = VTOI(ap->a_vp);
6704+
6705+ if (udf_node->fe != NULL)
6706+ file_size = le64toh(udf_node->fe->inf_len);
6707+ else
6708+ file_size = le64toh(udf_node->efe->inf_len);
6709+
6710+ vnode_create_vobject(ap->a_vp, file_size, ap->a_td);
6711+
6712+ return (0);
6713+}
6714+
6715+static int
6716+udf_access(struct vop_access_args *ap)
6717+{
6718+ struct vnode *vp;
6719+ struct udf_node *udf_node;
6720+ struct udf_mount *ump;
6721+ accmode_t accmode;
6722+ gid_t gid;
6723+ mode_t mode;
6724+ uid_t uid;
6725+
6726+ vp = ap->a_vp;
6727+ udf_node = VTOI(vp);
6728+ accmode = ap->a_accmode;
6729+ ump = udf_node->ump;
6730+
6731+ /* check if we are allowed to write */
6732+ switch (vp->v_type) {
6733+ case VDIR:
6734+ case VLNK:
6735+ case VREG:
6736+ /*
6737+ * normal nodes: check if we're on a read-only mounted
6738+ * filingsystem and bomb out if we're trying to write.
6739+ */
6740+ if (accmode & VWRITE)
6741+ return (EROFS); /* check that this works */
6742+ break;
6743+ case VBLK:
6744+ case VCHR:
6745+ case VSOCK:
6746+ case VFIFO:
6747+ /*
6748+ * special nodes: even on read-only mounted filingsystems
6749+ * these are allowed to be written to if permissions allow.
6750+ */
6751+ break;
6752+ default:
6753+ /* no idea what this is */
6754+ return (EINVAL);
6755+ }
6756+
6757+ mode = udf_getaccessmode(udf_node);
6758+ if (vp->v_type == VDIR && ump->flags & UDFMNT_USE_DIRMASK)
6759+ mode = (mode & ~ALLPERMS) | ump->dirmode;
6760+ else if (vp->v_type != VDIR && ump->flags & UDFMNT_USE_MASK)
6761+ mode = (mode & ~ALLPERMS) | ump->mode;
6762+
6763+ if (udf_node->fe != NULL) {
6764+ uid = udf_node->fe->uid;
6765+ gid = udf_node->fe->gid;
6766+ }
6767+ else {
6768+ uid = udf_node->efe->uid;
6769+ gid = udf_node->efe->gid;
6770+ }
6771+
6772+ return (vaccess(vp->v_type, mode, uid, gid, accmode, ap->a_cred, NULL));
6773+}
6774+
6775+int
6776+udf_readlink(struct vop_readlink_args *ap)
6777+{
6778+ struct vnode *vp = ap->a_vp;
6779+ struct uio *uio = ap->a_uio;
6780+ struct pathcomp pathcomp;
6781+ struct udf_node *udf_node;
6782+ int error, filelen, first, len, l_ci, mntonnamelen, namelen, pathlen;
6783+ int targetlen;
6784+ char *mntonname;
6785+ uint8_t *pathbuf, *pathpos, *targetbuf, *targetpos, *tmpname;
6786+
6787+ udf_node = VTOI(vp);
6788+
6789+ if (udf_node->efe != NULL)
6790+ filelen = le64toh(udf_node->efe->inf_len);
6791+ else
6792+ filelen = le64toh(udf_node->fe->inf_len);
6793+
6794+ if (UDF_SYMLINKBUFLEN - 1 < filelen)
6795+ return (EINVAL);
6796+
6797+ /* claim temporary buffers for translation */
6798+ pathbuf = malloc(UDF_SYMLINKBUFLEN, M_UDFTEMP, M_WAITOK);
6799+ targetbuf = malloc(PATH_MAX + 1, M_UDFTEMP, M_WAITOK);
6800+ tmpname = malloc(PATH_MAX + 1, M_UDFTEMP, M_WAITOK);
6801+ memset(pathbuf, 0, UDF_SYMLINKBUFLEN);
6802+ memset(targetbuf, 0, PATH_MAX + 1);
6803+
6804+ /* read contents of file in our temporary buffer */
6805+ error = vn_rdwr(UIO_READ, vp, pathbuf, filelen, 0, UIO_SYSSPACE,
6806+ IO_NODELOCKED, FSCRED, NULL, NULL, curthread);
6807+ if (error != 0) {
6808+ /* failed to read in symlink contents */
6809+ free(pathbuf, M_UDFTEMP);
6810+ free(targetbuf, M_UDFTEMP);
6811+ free(tmpname, M_UDFTEMP);
6812+ return (error);
6813+ }
6814+
6815+ /* convert to a unix path */
6816+ pathpos = pathbuf;
6817+ pathlen = 0;
6818+ targetpos = targetbuf;
6819+ targetlen = PATH_MAX;
6820+ mntonname = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
6821+ mntonnamelen = strlen(mntonname);
6822+
6823+ error = 0;
6824+ first = 1;
6825+ while (filelen - pathlen >= UDF_PATH_COMP_SIZE) {
6826+ len = UDF_PATH_COMP_SIZE;
6827+ memcpy(&pathcomp, pathpos, len);
6828+ l_ci = pathcomp.l_ci;
6829+ switch (pathcomp.type) {
6830+ case UDF_PATH_COMP_ROOT:
6831+ /* XXX should check for l_ci; bugcompatible now */
6832+ if (targetlen < 1 || first == 0) {
6833+ error = EINVAL;
6834+ break;
6835+ }
6836+ *targetpos++ = '/';
6837+ targetlen--;
6838+ break;
6839+ case UDF_PATH_COMP_MOUNTROOT:
6840+ /* XXX what should it be if l_ci > 0 ? [4/48.16.1.2] */
6841+ if (l_ci || targetlen < mntonnamelen + 1 || !first) {
6842+ error = EINVAL;
6843+ break;
6844+ }
6845+ memcpy(targetpos, mntonname, mntonnamelen);
6846+ targetpos += mntonnamelen;
6847+ targetlen -= mntonnamelen;
6848+ if (filelen - pathlen > UDF_PATH_COMP_SIZE + l_ci) {
6849+ /* more follows, so must be directory */
6850+ *targetpos++ = '/';
6851+ targetlen--;
6852+ }
6853+ break;
6854+ case UDF_PATH_COMP_PARENTDIR:
6855+ /* XXX should check for l_ci; bugcompatible now */
6856+ if (targetlen < 3) {
6857+ error = EINVAL;
6858+ break;
6859+ }
6860+ *targetpos++ = '.';
6861+ targetlen--;
6862+ *targetpos++ = '.';
6863+ targetlen--;
6864+ *targetpos++ = '/';
6865+ targetlen--;
6866+ break;
6867+ case UDF_PATH_COMP_CURDIR:
6868+ /* XXX should check for l_ci; bugcompatible now */
6869+ if (targetlen < 2) {
6870+ error = EINVAL;
6871+ break;
6872+ }
6873+ *targetpos++ = '.';
6874+ targetlen--;
6875+ *targetpos++ = '/';
6876+ targetlen--;
6877+ break;
6878+ case UDF_PATH_COMP_NAME:
6879+ if (l_ci == 0) {
6880+ error = EINVAL;
6881+ break;
6882+ }
6883+ memset(tmpname, 0, PATH_MAX);
6884+ memcpy(&pathcomp, pathpos, len + l_ci);
6885+ udf_to_unix_name(udf_node->ump, tmpname, MAXPATHLEN,
6886+ pathcomp.ident, l_ci);
6887+ namelen = strlen(tmpname);
6888+ if (targetlen < namelen + 1) {
6889+ error = EINVAL;
6890+ break;
6891+ }
6892+ memcpy(targetpos, tmpname, namelen);
6893+ targetpos += namelen;
6894+ targetlen -= namelen;
6895+ if (filelen-pathlen > UDF_PATH_COMP_SIZE + l_ci) {
6896+ /* more follows, so must be directory */
6897+ *targetpos++ = '/';
6898+ targetlen--;
6899+ }
6900+ break;
6901+ default:
6902+ error = EINVAL;
6903+ break;
6904+ }
6905+ first = 0;
6906+ if (error != 0)
6907+ break;
6908+ pathpos += UDF_PATH_COMP_SIZE + l_ci;
6909+ pathlen += UDF_PATH_COMP_SIZE + l_ci;
6910+
6911+ }
6912+ /* all processed? */
6913+ if (filelen - pathlen > 0)
6914+ error = EINVAL;
6915+
6916+ /* uiomove() to destination */
6917+ if (error == 0)
6918+ uiomove(targetbuf, PATH_MAX - targetlen, uio);
6919+
6920+ free(pathbuf, M_UDFTEMP);
6921+ free(targetbuf, M_UDFTEMP);
6922+ free(tmpname, M_UDFTEMP);
6923+
6924+ return (error);
6925+}
6926+
6927+static int
6928+udf_ioctl(struct vop_ioctl_args *ap)
6929+{
6930+ return (ENOTTY);
6931+}
6932+
6933+static int
6934+udf_print(struct vop_print_args *ap)
6935+{
6936+ struct vnode *vp = ap->a_vp;
6937+ struct udf_node *udf_node = VTOI(vp);
6938+
6939+ printf(" ino %u, on dev %s", (uint32_t)udf_node->hash_id,
6940+ devtoname(udf_node->ump->devvp->v_rdev));
6941+ if (vp->v_type == VFIFO)
6942+ fifo_printinfo(vp);
6943+ printf("\n");
6944+
6945+ return (0);
6946+}
6947+
6948+static int
6949+udf_vptofh(struct vop_vptofh_args *ap)
6950+{
6951+ struct udf_node *udf_node = VTOI(ap->a_vp);
6952+ struct udf_fid *ufid = (struct udf_fid *)ap->a_fhp;
6953+
6954+ ufid->len = sizeof(struct udf_fid);
6955+ ufid->ino = udf_node->hash_id;
6956+
6957+ return (0);
6958+}
6959+
6960+static int
6961+udf_getpages(struct vop_getpages_args /* {
6962+ struct vnode *a_vp;
6963+ vm_page_t *a_m;
6964+ int a_count;
6965+ int a_reqpage;
6966+ vm_ooffset_t a_offset;
6967+ } */ *ap)
6968+{
6969+ struct buf *bp;
6970+ struct bufobj *bo;
6971+ struct vnode *vp = ap->a_vp;
6972+ vm_page_t *pages;
6973+ daddr_t startreq, lastreq, firstblk, vblock, address;
6974+ off_t filesize, foff, tfoff;
6975+ vm_offset_t kva, curdata;
6976+ int blksperpage, bsize, error, i, numblks, pagecnt, size;
6977+ int curpage, fpage, npage;
6978+
6979+ error = 0;
6980+ bsize = vp->v_mount->mnt_stat.f_iosize;
6981+ filesize = vp->v_object->un_pager.vnp.vnp_size;
6982+ pages = ap->a_m;
6983+ pagecnt = btoc(ap->a_count);
6984+ blksperpage = PAGE_SIZE / bsize;
6985+
6986+ /*
6987+ * Free other pages, if requested page is valid. If only part of a page
6988+ * is marked as valid, we overwrite it below. This approch would not
6989+ * work, if the filesystem implemented write support.
6990+ */
6991+#if __FreeBSD__ < 10
6992+ VM_OBJECT_LOCK(vp->v_object);
6993+#else
6994+ VM_OBJECT_WLOCK(vp->v_object);
6995+#endif
6996+ if (pages[ap->a_reqpage]->valid == VM_PAGE_BITS_ALL) {
6997+ for (i = 0; i < pagecnt; i++)
6998+ if (i != ap->a_reqpage) {
6999+ vm_page_lock(pages[i]);
7000+ vm_page_free(pages[i]);
7001+ vm_page_unlock(pages[i]);
7002+ }
7003+#if __FreeBSD__ < 10
7004+ VM_OBJECT_UNLOCK(vp->v_object);
7005+#else
7006+ VM_OBJECT_WUNLOCK(vp->v_object);
7007+#endif
7008+ return VM_PAGER_OK;
7009+ }
7010+#if __FreeBSD__ < 10
7011+ VM_OBJECT_UNLOCK(vp->v_object);
7012+#else
7013+ VM_OBJECT_WUNLOCK(vp->v_object);
7014+#endif
7015+
7016+ /* Map all memory pages, and then use a single buf object for all
7017+ bstrategy calls. */
7018+ bp = getpbuf(&udf_pbuf_freecnt);
7019+ bp->b_iocmd = BIO_READ;
7020+ bp->b_iodone = bdone;
7021+ bp->b_rcred = crhold(curthread->td_ucred);
7022+ bp->b_wcred = crhold(curthread->td_ucred);
7023+
7024+ curdata = kva = (vm_offset_t)bp->b_data;
7025+ pmap_qenter(kva, pages, pagecnt);
7026+
7027+ firstblk = pages[0]->pindex * blksperpage;
7028+ startreq = pages[ap->a_reqpage]->pindex * blksperpage;
7029+ lastreq = startreq + blksperpage - 1;
7030+ if ((lastreq + 1) * bsize > filesize)
7031+ lastreq = (filesize - 1) / bsize;
7032+ fpage = -1;
7033+
7034+ for (curpage = 0, vblock = firstblk; vblock <= lastreq; ) {
7035+ error = VOP_BMAP(vp, vblock, &bo, &address, &numblks, NULL);
7036+ if (error)
7037+ goto error;
7038+
7039+ numblks++;
7040+ if (vblock + numblks <= startreq) {
7041+ vblock += numblks - 1; /* last block of run */
7042+ npage = (vblock - firstblk) / blksperpage + 1;
7043+ vblock = pages[npage]->pindex * blksperpage;
7044+ curdata = kva + IDX_TO_OFF(pages[npage]->pindex);
7045+ continue;
7046+ }
7047+
7048+ curpage = ((vblock - firstblk) * bsize) / PAGE_SIZE;
7049+
7050+ /* find number of blocks to readahead */
7051+ numblks = MIN(numblks,
7052+ blksperpage * pagecnt - (vblock - firstblk));
7053+ if (vblock + numblks - 1 > lastreq)
7054+ numblks -= (vblock - firstblk + numblks) % blksperpage;
7055+ size = bsize * numblks;
7056+
7057+ /* from initpbuf() */
7058+ bp->b_qindex = 0;
7059+ bp->b_xflags = 0;
7060+ bp->b_flags = 0;
7061+ bp->b_ioflags = 0;
7062+ bp->b_iodone = NULL;
7063+ bp->b_error = 0;
7064+
7065+ /* setup the buffer for this run */
7066+ if (fpage == -1) {
7067+ pbgetbo(bo, bp);
7068+ bp->b_vp = vp;
7069+ fpage = curpage;
7070+ }
7071+
7072+ bp->b_data = (caddr_t)curdata;
7073+ bp->b_blkno = address;
7074+ bp->b_lblkno = vblock;
7075+ bp->b_bcount = size; /* this is the current read size. */
7076+ bp->b_bufsize = size;
7077+ bp->b_runningbufspace = bp->b_bufsize;
7078+ atomic_add_long(&runningbufspace, bp->b_runningbufspace);
7079+
7080+ bp->b_iooffset = dbtob(bp->b_blkno);
7081+ bstrategy(bp);
7082+
7083+ bwait(bp, PVM, "udfvnread");
7084+
7085+ if ((bp->b_ioflags & BIO_ERROR) != 0) {
7086+ error = EIO;
7087+ goto error;
7088+ }
7089+
7090+ vblock = vblock + numblks;
7091+ curdata += size;
7092+ }
7093+
7094+ /* it should error out before here if vblock == firstblk */
7095+ npage = (vblock - 1 - firstblk) / blksperpage + 1;
7096+
7097+ if ((vblock - firstblk) % blksperpage != 0) {
7098+ bzero((caddr_t) curdata,
7099+ ((vblock - firstblk) % blksperpage) * bsize);
7100+ }
7101+
7102+error:
7103+ pmap_qremove(kva, pagecnt);
7104+
7105+ bp->b_vp = NULL;
7106+ pbrelbo(bp);
7107+ relpbuf(bp, &vnode_pbuf_freecnt);
7108+
7109+ if (error != 0) {
7110+#if __FreeBSD__ < 10
7111+ VM_OBJECT_LOCK(vp->v_object);
7112+#else
7113+ VM_OBJECT_WLOCK(vp->v_object);
7114+#endif
7115+ for (i = 0; i < pagecnt; i++)
7116+ if (i != ap->a_reqpage) {
7117+ vm_page_lock(pages[i]);
7118+ vm_page_free(pages[i]);
7119+ vm_page_unlock(pages[i]);
7120+ }
7121+#if __FreeBSD__ < 10
7122+ VM_OBJECT_UNLOCK(vp->v_object);
7123+#else
7124+ VM_OBJECT_WUNLOCK(vp->v_object);
7125+#endif
7126+ return (VM_PAGER_ERROR);
7127+ }
7128+
7129+#if __FreeBSD__ < 10
7130+ VM_OBJECT_LOCK(vp->v_object);
7131+#else
7132+ VM_OBJECT_WLOCK(vp->v_object);
7133+#endif
7134+ /* remove all pages before first loaded page. */
7135+ for (i = 0; i < fpage; i++) {
7136+ vm_page_lock(pages[i]);
7137+ vm_page_free(pages[i]);
7138+ vm_page_unlock(pages[i]);
7139+ }
7140+
7141+ /* mark filled pages. */
7142+ foff = IDX_TO_OFF(pages[fpage]->pindex);
7143+ for (i = fpage, tfoff = foff; i < npage; i++, tfoff += PAGE_SIZE) {
7144+ /* We only read complete pages above. */
7145+ if (tfoff + PAGE_SIZE <= filesize)
7146+ pages[i]->valid = VM_PAGE_BITS_ALL;
7147+ else {
7148+#if __FreeBSD__ < 10
7149+ vm_page_set_valid(pages[i], 0, filesize - tfoff);
7150+#else
7151+ vm_page_set_valid_range(pages[i], 0, filesize - tfoff);
7152+#endif
7153+ }
7154+
7155+ if (i != ap->a_reqpage)
7156+ vm_page_readahead_finish(pages[i]);
7157+ }
7158+
7159+ /* remove all pages after last loaded page. */
7160+ for (i = npage; i < pagecnt; i++) {
7161+ vm_page_lock(pages[i]);
7162+ vm_page_free(pages[i]);
7163+ vm_page_unlock(pages[i]);
7164+ }
7165+#if __FreeBSD__ < 10
7166+ VM_OBJECT_UNLOCK(vp->v_object);
7167+#else
7168+ VM_OBJECT_WUNLOCK(vp->v_object);
7169+#endif
7170+
7171+ return (VM_PAGER_OK);
7172+}
7173+
7174
7175--- sys/kern/kern_sysctl.c 2015-07-04 07:20:46.000000000 -0700
7176+++ updates/sys/kern/kern_sysctl.c 2015-07-04 06:45:19.000000000 -0700
7177@@ -36,7 +36,7 @@
7178 */
7179
7180 #include <sys/cdefs.h>
7181-__FBSDID("$FreeBSD: head/sys/kern/kern_sysctl.c 285131 2015-07-04 14:44:39Z mjg $");
7182+__FBSDID("$FreeBSD: head/sys/kern/kern_sysctl.c 285126 2015-07-04 07:01:43Z mjg $");
7183
7184 #include "opt_capsicum.h"
7185 #include "opt_compat.h"
7186@@ -113,6 +113,26 @@
7187 static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
7188 static int sysctl_new_kernel(struct sysctl_req *, void *, size_t);
7189
7190+static void
7191+sysctl_lock(struct rm_priotracker *tracker)
7192+{
7193+
7194+ if (tracker != NULL)
7195+ SYSCTL_RLOCK(tracker);
7196+ else
7197+ SYSCTL_WLOCK();
7198+}
7199+
7200+static void
7201+sysctl_unlock(struct rm_priotracker *tracker)
7202+{
7203+
7204+ if (tracker != NULL)
7205+ SYSCTL_RUNLOCK(tracker);
7206+ else
7207+ SYSCTL_WUNLOCK();
7208+}
7209+
7210 static struct sysctl_oid *
7211 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
7212 {
7213@@ -154,11 +174,7 @@
7214
7215 if (oid->oid_kind & CTLFLAG_DYN)
7216 atomic_add_int(&oid->oid_running, 1);
7217-
7218- if (tracker != NULL)
7219- SYSCTL_RUNLOCK(tracker);
7220- else
7221- SYSCTL_WUNLOCK();
7222+ sysctl_unlock(tracker);
7223
7224 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
7225 mtx_lock(&Giant);
7226@@ -166,11 +182,7 @@
7227 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
7228 mtx_unlock(&Giant);
7229
7230- if (tracker != NULL)
7231- SYSCTL_RLOCK(tracker);
7232- else
7233- SYSCTL_WLOCK();
7234-
7235+ sysctl_lock(tracker);
7236 if (oid->oid_kind & CTLFLAG_DYN) {
7237 if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
7238 (oid->oid_kind & CTLFLAG_DYING) != 0)
7239
7240--- sys/modules/Makefile 2015-07-04 07:18:25.000000000 -0700
7241+++ updates/sys/modules/Makefile 2015-07-04 07:09:05.000000000 -0700
7242@@ -347,6 +347,8 @@
7243 ubsec \
7244 udf \
7245 udf_iconv \
7246+ udf2 \
7247+ udf2_iconv \
7248 ufs \
7249 unionfs \
7250 usb \
7251
7252--- sys/modules/udf2/Makefile 1969-12-31 16:00:00.000000000 -0800
7253+++ updates/sys/modules/udf2/Makefile 2015-07-04 07:02:31.000000000 -0700
7254@@ -0,0 +1,12 @@
7255+# $FreeBSD: src/sys/modules/udf/Makefile,v 1.5 2004/01/13 11:28:50 ru Exp $
7256+
7257+.PATH: ${.CURDIR}/../../fs/udf2
7258+
7259+KMOD= udf2
7260+
7261+SRCS= udf_readwrite.c udf_subr.c udf_allocation.c \
7262+ udf_osta.c udf_vfsops.c udf_vnops.c udf_filenames.c
7263+SRCS+= vnode_if.h
7264+EXPORT_SYMS= udf_iconv
7265+
7266+.include <bsd.kmod.mk>
7267
7268--- sys/modules/udf2_iconv/Makefile 1969-12-31 16:00:00.000000000 -0800
7269+++ updates/sys/modules/udf2_iconv/Makefile 2015-07-04 07:04:57.000000000 -0700
7270@@ -0,0 +1,9 @@
7271+# $FreeBSD: src/sys/modules/udf_iconv/Makefile,v 1.1 2003/11/07 09:38:05 scottl Exp $
7272+
7273+.PATH: ${.CURDIR}/../../fs/udf2
7274+KMOD= udf2_iconv
7275+SRCS= udf_iconv.c
7276+
7277+CFLAGS+= -I${.CURDIR}/../../
7278+
7279+.include <bsd.kmod.mk>
7280
7281--- sys/sys/udfio.h 1969-12-31 16:00:00.000000000 -0800
7282+++ updates/sys/sys/udfio.h 2014-11-16 17:05:03.000000000 -0800
7283@@ -0,0 +1,29 @@
7284+
7285+
7286+/* Shared between kernel & process */
7287+
7288+#ifndef _SYS_UDFIO_H_
7289+#define _SYS_UDFIO_H_
7290+
7291+#ifndef _KERNEL
7292+#include <sys/types.h>
7293+#endif
7294+#include <sys/ioccom.h>
7295+
7296+struct udf_session_info {
7297+ uint16_t num_sessions;
7298+ uint16_t sector_size;
7299+ uint16_t num_tracks;
7300+ uint8_t first_track;
7301+
7302+ uint32_t session_num;
7303+ uint32_t session_start_addr;
7304+ uint32_t session_end_addr;
7305+ uint32_t session_last_written;
7306+ uint16_t session_first_track;
7307+ uint8_t session_first_track_blank;
7308+ uint16_t session_last_track;
7309+};
7310+#define UDFIOREADSESSIONINFO _IOWR('c',300, struct udf_session_info)
7311+
7312+#endif /* !_SYS_UDFIO_H_ */
7313
7314--- sys/cam/scsi/scsi_cd.c 2015-07-04 07:22:35.000000000 -0700
7315+++ updates/sys/cam/scsi/scsi_cd.c 2015-07-04 06:45:21.000000000 -0700
7316@@ -60,6 +60,7 @@
7317 #include <sys/cdio.h>
7318 #include <sys/cdrio.h>
7319 #include <sys/dvdio.h>
7320+#include <sys/udfio.h>
7321 #include <sys/devicestat.h>
7322 #include <sys/sysctl.h>
7323 #include <sys/taskqueue.h>
7324@@ -264,6 +265,19 @@
7325 struct dvd_struct *dvdstruct);
7326 static timeout_t cdmediapoll;
7327
7328+/* added for UDF */
7329+static int udfreaddiscinfo(struct cam_periph *periph,
7330+ struct udf_session_info *usi);
7331+static int cdgetconf(struct cam_periph *periph, u_int8_t *data,
7332+ u_int32_t len, uint8_t rt,
7333+ uint16_t startfeature, u_int32_t sense_flags);
7334+static int cdreaddiscinfo(struct cam_periph *periph, uint8_t *data,
7335+ uint32_t len, uint32_t sense_flags);
7336+static int cdreadtrackinfo(struct cam_periph *periph,
7337+ uint8_t *data, uint32_t len,
7338+ uint32_t trackno,
7339+ uint32_t sense_flags);
7340+
7341 static struct periph_driver cddriver =
7342 {
7343 cdinit, "cd",
7344@@ -2139,6 +2153,18 @@
7345
7346 break;
7347 }
7348+ case UDFIOREADSESSIONINFO: {
7349+ struct udf_session_info *usi;
7350+
7351+ usi = (struct udf_session_info *)addr;
7352+
7353+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
7354+ ("trying to do UDFIOREADDISCINFO\n"));
7355+
7356+ error = udfreaddiscinfo(periph, usi);
7357+
7358+ break;
7359+ }
7360 default:
7361 cam_periph_lock(periph);
7362 error = cam_periph_ioctl(periph, cmd, addr, cderror);
7363@@ -2158,6 +2184,252 @@
7364 return (error);
7365 }
7366
7367+/* Added for UDF. */
7368+static int
7369+udfreaddiscinfo(struct cam_periph *periph, struct udf_session_info *usi)
7370+{
7371+ struct scsi_read_disc_info_data *rdi;
7372+ struct scsi_read_track_info_data *ti;
7373+ struct scsi_get_conf_header *gch;
7374+ struct scsi_get_conf_feature_inc_stream_write *lf;
7375+ int error, linksize, lra_valid, nwa_valid, diskstate;
7376+ int sessionstatus;
7377+ uint32_t track_start_addr, track_size, free_blocks, nwa, lra;
7378+ uint16_t track, sessret;
7379+ uint8_t lsb, msb;
7380+
7381+ rdi = malloc(sizeof(*rdi), M_SCSICD, M_WAITOK | M_ZERO);
7382+ ti = malloc(sizeof(*ti), M_SCSICD, M_WAITOK | M_ZERO);
7383+ gch = malloc(sizeof(*gch) + sizeof(*lf), M_SCSICD, M_WAITOK | M_ZERO);
7384+
7385+ cam_periph_lock(periph);
7386+
7387+ /* Get link size. */
7388+ linksize = 7; // for CD-Roms
7389+
7390+ error = cdgetconf(periph, (u_int8_t *)gch, sizeof(*gch) + sizeof(*lf),
7391+ GC_RT_ONEFEATURE, GC_FC_INCR_STREAMING_WRITABLE, SF_NO_PRINT);
7392+ lf = (struct scsi_get_conf_feature_inc_stream_write *)(gch + 1);
7393+ if (error)
7394+ goto out;
7395+
7396+ if (lf->byte3 & GC_CURRENT)
7397+ if (lf->num_link_sizes > 0)
7398+ linksize = lf->first_linksize;
7399+
7400+ /* Read get config and header data. */
7401+ error = cdreaddiscinfo(periph, (uint8_t *)rdi, sizeof (*rdi),
7402+ SF_NO_PRINT);
7403+ if (error != 0)
7404+ goto out;
7405+
7406+ usi->num_sessions = rdi->num_sessions_lsb |
7407+ (rdi->num_sessions_msb << 8);
7408+
7409+ if (usi->session_num == 0) {
7410+ diskstate = rdi->byte2 & 0x3;
7411+ sessionstatus = (rdi->byte2 >> 2) & 0x3;
7412+
7413+ // if the session is empty, we don't want to read it.
7414+ if (diskstate < 2 && sessionstatus == 0 &&
7415+ usi->num_sessions > 1)
7416+ usi->session_num = usi->num_sessions - 1;
7417+ else
7418+ usi->session_num = usi->num_sessions;
7419+ }
7420+
7421+ usi->first_track = rdi->num_first_track;
7422+
7423+ lsb = rdi->last_track_last_session_lsb;
7424+ msb = rdi->last_track_last_session_msb;
7425+ usi->num_tracks = ((msb << 8) | lsb) - usi->first_track + 1;
7426+
7427+ usi->session_first_track = 0;
7428+ usi->session_last_track = 0;
7429+ usi->session_start_addr = 0;
7430+ track_start_addr = 0;
7431+ track_size = 0;
7432+ free_blocks = 0;
7433+ nwa = 0;
7434+ lra = 0;
7435+ lra_valid = 0;
7436+ nwa_valid = 0;
7437+ for (track = usi->first_track; track <= usi->num_tracks; track++) {
7438+ error = cdreadtrackinfo(periph, (uint8_t *)ti, sizeof(*ti),
7439+ track, /*sense_flags*/SF_NO_PRINT);
7440+ if (error != 0) {
7441+ goto out;
7442+ }
7443+ sessret = (ti->session_num_msb << 8) | ti->session_num_lsb;
7444+ if (sessret == usi->session_num) {
7445+ if (usi->session_first_track == 0) {
7446+ usi->session_first_track = track;
7447+ usi->session_start_addr =
7448+ scsi_4btoul(ti->track_start_addr);
7449+ usi->session_first_track_blank =
7450+ ti->track_info2 & READ_TRACK_BLANK ? 1 : 0;
7451+ }
7452+ usi->session_last_track = track;
7453+ track_start_addr = scsi_4btoul(ti->track_start_addr);
7454+ track_size = scsi_4btoul(ti->track_size);
7455+ free_blocks = scsi_4btoul(ti->free_blocks);
7456+ lra_valid = ti->valid_data & READ_TRACK_INFO_LRA_V;
7457+ lra = scsi_4btoul(ti->last_recorded_addr);
7458+ nwa_valid = ti->valid_data & READ_TRACK_INFO_NWA_V;
7459+ nwa = scsi_4btoul(ti->next_writable_addr);
7460+ } else if (usi->session_first_track != 0)
7461+ break;
7462+ }
7463+
7464+ if (usi->session_first_track == 0 || usi->session_last_track == 0) {
7465+ error = EINVAL;
7466+ goto out;
7467+ }
7468+
7469+ /* Calculate end address of session. */
7470+ usi->session_end_addr = track_start_addr + track_size - 1;
7471+
7472+ /* Only needed for sequentially written disk, but populate it anyway.*/
7473+ if (lra_valid != 0)
7474+ usi->session_last_written = lra;
7475+ /* else if (nwa_valid != 0)
7476+ usi->session_last_written = nwa - linksize; */
7477+ else {
7478+ usi->session_last_written = usi->session_end_addr;
7479+ if (free_blocks)
7480+ usi->session_last_written -= free_blocks + linksize;
7481+ }
7482+
7483+ usi->sector_size = 2048; /* Almost all CDs have this block size. */
7484+out:
7485+ cam_periph_unlock(periph);
7486+ free(rdi, M_SCSICD);
7487+ free(ti, M_SCSICD);
7488+ free(gch, M_SCSICD);
7489+
7490+ if (error != 0)
7491+ error = ENODEV;
7492+
7493+ return (error);
7494+}
7495+
7496+static int
7497+cdgetconf(struct cam_periph *periph, uint8_t *data, uint32_t len,
7498+ uint8_t rt, uint16_t startfeature, uint32_t sense_flags)
7499+{
7500+ struct scsi_get_conf *scsi_cmd;
7501+ struct ccb_scsiio *csio;
7502+ union ccb *ccb;
7503+ int error;
7504+
7505+ error = 0;
7506+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
7507+ csio = &ccb->csio;
7508+
7509+ cam_fill_csio(csio,
7510+ /* retries */ cd_retry_count,
7511+ /* cbfcnp */ cddone,
7512+ /* flags */ CAM_DIR_IN,
7513+ /* tag_action */ MSG_SIMPLE_Q_TAG,
7514+ /* data_ptr */ data,
7515+ /* dxfer_len */ len,
7516+ /* sense_len */ SSD_FULL_SIZE,
7517+ sizeof(struct scsi_get_conf),
7518+ /* timeout */ 50000);
7519+
7520+ scsi_cmd = (struct scsi_get_conf *)&csio->cdb_io.cdb_bytes;
7521+ bzero (scsi_cmd, sizeof(*scsi_cmd));
7522+ scsi_cmd->op_code = GET_CONFIGURATION;
7523+ scsi_cmd->byte2 = rt;
7524+ scsi_ulto2b(startfeature, scsi_cmd->start_feature);
7525+ scsi_ulto2b(len, scsi_cmd->alloc_len);
7526+
7527+ error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
7528+ /*sense_flags*/SF_RETRY_UA | sense_flags);
7529+
7530+ xpt_release_ccb(ccb);
7531+
7532+ return (error);
7533+}
7534+
7535+static int
7536+cdreaddiscinfo(struct cam_periph *periph, uint8_t *data, uint32_t len,
7537+ uint32_t sense_flags)
7538+{
7539+ struct scsi_read_disc_info *scsi_cmd;
7540+ struct ccb_scsiio *csio;
7541+ union ccb *ccb;
7542+ int error;
7543+
7544+ error = 0;
7545+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
7546+ csio = &ccb->csio;
7547+
7548+ cam_fill_csio(csio,
7549+ /* retries */ cd_retry_count,
7550+ /* cbfcnp */ cddone,
7551+ /* flags */ CAM_DIR_IN,
7552+ /* tag_action */ MSG_SIMPLE_Q_TAG,
7553+ /* data_ptr */ data,
7554+ /* dxfer_len */ len,
7555+ /* sense_len */ SSD_FULL_SIZE,
7556+ sizeof(struct scsi_read_disc_info),
7557+ /* timeout */ 50000);
7558+
7559+ scsi_cmd = (struct scsi_read_disc_info *)&csio->cdb_io.cdb_bytes;
7560+ bzero (scsi_cmd, sizeof(*scsi_cmd));
7561+ scsi_cmd->op_code = READ_DISC_INFO;
7562+ scsi_ulto2b(len, scsi_cmd->alloc_len);
7563+
7564+ error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
7565+ /*sense_flags*/SF_RETRY_UA | sense_flags);
7566+
7567+ xpt_release_ccb(ccb);
7568+
7569+ return (error);
7570+}
7571+
7572+static int
7573+cdreadtrackinfo(struct cam_periph *periph, uint8_t *data, uint32_t len,
7574+ uint32_t trackno, uint32_t sense_flags)
7575+{
7576+ struct scsi_read_track_info *scsi_cmd;
7577+ struct ccb_scsiio *csio;
7578+ union ccb *ccb;
7579+ int error;
7580+
7581+ error = 0;
7582+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
7583+ csio = &ccb->csio;
7584+
7585+ cam_fill_csio(csio,
7586+ /* retries */ cd_retry_count,
7587+ /* cbfcnp */ cddone,
7588+ /* flags */ CAM_DIR_IN,
7589+ /* tag_action */ MSG_SIMPLE_Q_TAG,
7590+ /* data_ptr */ data,
7591+ /* dxfer_len */ len,
7592+ /* sense_len */ SSD_FULL_SIZE,
7593+ sizeof(struct scsi_read_track_info),
7594+ /* timeout */ 50000);
7595+
7596+ scsi_cmd = (struct scsi_read_track_info *)&csio->cdb_io.cdb_bytes;
7597+ bzero (scsi_cmd, sizeof(*scsi_cmd));
7598+ scsi_cmd->op_code = READ_TRACK_INFO;
7599+ scsi_cmd->byte2 = READ_TRACK_INFO_AT_TRACK;
7600+ scsi_ulto4b(trackno, scsi_cmd->address);
7601+ scsi_ulto2b(len, scsi_cmd->alloc_len);
7602+
7603+ error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
7604+ /*sense_flags*/SF_RETRY_UA | sense_flags);
7605+
7606+ xpt_release_ccb(ccb);
7607+
7608+ return (error);
7609+}
7610+/* End of UDF code. */
7611+
7612+
7613 static void
7614 cdprevent(struct cam_periph *periph, int action)
7615 {
7616
7617--- sys/cam/scsi/scsi_cd.h 2015-07-04 07:22:35.000000000 -0700
7618+++ updates/sys/cam/scsi/scsi_cd.h 2014-11-16 17:03:59.000000000 -0800
7619@@ -56,6 +56,109 @@
7620 * SCSI command format
7621 */
7622
7623+
7624+/* Used in UDF */
7625+#define GET_CONFIGURATION 0x46 /* cdrom read TOC */
7626+struct scsi_get_conf
7627+{
7628+ uint8_t op_code;
7629+ uint8_t byte2;
7630+#define GC_RT_ONEFEATURE 0x02 /* Return header and zero or one feature. */
7631+ uint8_t start_feature[2];
7632+#define GC_FC_INCR_STREAMING_WRITABLE 0x0021
7633+ uint8_t reserved[3];
7634+ uint8_t alloc_len[2];
7635+ uint8_t control;
7636+};
7637+
7638+struct scsi_get_conf_header
7639+{
7640+ uint8_t data_len[4];
7641+ uint8_t reserved[2];
7642+ uint8_t cur_profile[2];
7643+};
7644+
7645+struct scsi_get_conf_feature_inc_stream_write
7646+{
7647+ uint8_t feature_code[2];
7648+ uint8_t byte3;
7649+#define GC_CURRENT 0x1
7650+ uint8_t additional_len;
7651+ uint8_t data_block_types_supported[2];
7652+ uint8_t byte7;
7653+ uint8_t num_link_sizes;
7654+ uint8_t first_linksize;
7655+ uint8_t other_linksizes[1]; /* one byte each, most return 1. */
7656+};
7657+
7658+#define READ_DISC_INFO 0x51
7659+struct scsi_read_disc_info
7660+{
7661+ uint8_t op_code;
7662+ uint8_t byte2;
7663+ uint8_t reserved[5];
7664+ uint8_t alloc_len[2];
7665+ uint8_t control;
7666+};
7667+
7668+struct scsi_read_disc_info_data
7669+{
7670+ uint8_t disc_info_len[2];
7671+ uint8_t byte2;
7672+ uint8_t num_first_track;
7673+ uint8_t num_sessions_lsb;
7674+ uint8_t first_track_last_session_lsb;
7675+ uint8_t last_track_last_session_lsb;
7676+ uint8_t byte8;
7677+ uint8_t disc_type;
7678+ uint8_t num_sessions_msb;
7679+ uint8_t first_track_last_session_msb;
7680+ uint8_t last_track_last_session_msb;
7681+ uint8_t disc_id[4];
7682+ uint8_t leadin_start_last_session[4];
7683+ uint8_t last_start_time_leadout[4];
7684+ uint8_t disc_bar_code[8];
7685+ uint8_t reserved;
7686+ uint8_t num_opc_entries;
7687+ uint8_t opc_entries[];
7688+};
7689+
7690+#define READ_TRACK_INFO 0x52
7691+struct scsi_read_track_info
7692+{
7693+ uint8_t op_code;
7694+ uint8_t byte2;
7695+#define READ_TRACK_INFO_AT_TRACK 0x01
7696+ uint8_t address[4];
7697+ uint8_t reserved;
7698+ uint8_t alloc_len[2];
7699+ uint8_t control;
7700+};
7701+
7702+struct scsi_read_track_info_data
7703+{
7704+ uint8_t track_info_len[2];
7705+ uint8_t track_num_lsb;
7706+ uint8_t session_num_lsb;
7707+ uint8_t reserved1;
7708+ uint8_t track_info1;
7709+ uint8_t track_info2;
7710+#define READ_TRACK_BLANK 0x40
7711+ uint8_t valid_data;
7712+#define READ_TRACK_INFO_LRA_V 0x2
7713+#define READ_TRACK_INFO_NWA_V 0x1
7714+ uint8_t track_start_addr[4];
7715+ uint8_t next_writable_addr[4];
7716+ uint8_t free_blocks[4];
7717+ uint8_t packet_size[4];
7718+ uint8_t track_size[4];
7719+ uint8_t last_recorded_addr[4];
7720+ uint8_t track_num_msb;
7721+ uint8_t session_num_msb;
7722+ uint8_t reserved2[2];
7723+};
7724+/* End of UDF */
7725+
7726 struct scsi_pause
7727 {
7728 u_int8_t op_code;