udftools-2.0/0000755000175000017500000000000013221466662010223 500000000000000udftools-2.0/doc/0000755000175000017500000000000013221466662010770 500000000000000udftools-2.0/doc/Makefile.in0000644000175000017500000004251313221466653012762 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_doc_DATA) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)" \ "$(DESTDIR)$(docdir)" man8dir = $(mandir)/man8 NROFF = nroff MANS = $(dist_man_MANS) DATA = $(dist_doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ dist_man_MANS = cdrwtool.1 udfinfo.1 wrudf.1 mkfs.udf.8 mkudffs.8 pktsetup.8 udflabel.8 dist_doc_DATA = HOWTO.udf UDF-Specifications all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man8: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_docDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_docDATA uninstall-man uninstall-man: uninstall-man1 uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_docDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-man8 \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am uninstall-dist_docDATA \ uninstall-man uninstall-man1 uninstall-man8 .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/doc/udflabel.80000644000175000017500000002026013221466537012560 00000000000000'\" t -*- coding: UTF-8 -*- .\" Copyright (C) 2017 Pali Rohár .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License along .\" with this program; if not, write to the Free Software Foundation, Inc., .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. .TH UDFLABEL 8 "udftools" "Commands" .SH NAME udflabel \- show or change UDF filesystem label .SH SYNOPSIS .BI "udflabel [encoding-options] [block-options] [identifier-options] " device " [" new-label "]" .SH DESCRIPTION When \fBudflabel\fP is invoked without \fBidentifier-options\fP and without specifying \fInew-label\fP then it show current label of UDF filesystem on \fIdevice\fP to standard output terminated by new line. Otherwise it update UDF filesystem (up to the revision 2.60) on \fIdevice\fP with new specified identifiers from \fBidentifier-options\fP. Specifying \fInew-label\fP is synonym for both \fI\-\-lvid\fP and \fI\-\-vid\fP, see section \fBUDF LABEL AND UUID\fP. .SH OPTIONS .SS "GENERAL OPTIONS" .TP .B \-h,\-\-help Display the usage and the list of options. .SS "BLOCK OPTIONS" .TP .BI \-b,\-\-blocksize= " block\-size " Specify the size of blocks in bytes. Valid block size for a UDF filesystem is power of two in range from 512 to 32768 and must match a device logical (sector) size. If omitted, \fBudflabel\fP tries to autodetect block size. It tries logical (sector) size and then all valid block sizes. .TP .BI \-\-vatblock= " vat\-block " Specify the block location of the Virtual Allocation Table. Virtual Allocation Table is present only on UDF disks with Virtual Partition Map and must be at the last written/recorded disk block. If omitted, \fBudflabel\fP for optical disc tries to detect the last recorded block with fallback to the last block of block device or disk file image. In most cases this fallback does not have to work and for disk file images with Virtual Allocation Table is necessary to specify correct location. Virtual Allocation Table on disks with UDF revisions higher then 1.50 contains Logical Volume Identifier (UDF Label). .TP .B \-\-force Force updating UDF disks without write support. Some media, like CD-ROM, DVD-ROM or BD-ROM are read-only. Other media, like CD-RW or DVD-RW are write-once. UDF is designed also for such media where updating Label or Identifiers is not possible. But in some rare cases it could make sense to try overwrite existing Label or Identifiers also for UDF filesystem which has Access Type either Read-Only or Recordable (Write-Once). This is possible only if underlaying media supports overwriting. E.g. UDF image of CD-ROM stored on hard disk or Read-Only UDF image burned to DVD-RAM or BD-RE discs. Option \fI\-\-force\fP ignores UDF Access Type and treat it as Overwritable. .TP .B \-n,\-\-no-write Not really, do not write to \fIdevice\fP. Just simulate and display what would happen with \fIdevice\fP. Useful for determining which UDF blocks would be overwritten. .SS "IDENTIFIER OPTIONS" .TP .BI \-u,\-\-uuid= " uuid " Specify the UDF uuid. Must be exactly 16 hexadecimal lowercase digits and is used for first 16 characters of \fB\-\-fullvsid\fP option. Special value \fBrandom\fP generates new uuid from local time and random number. See section \fBUDF LABEL AND UUID\fP. .TP .BI \-\-lvid= " new\-logical\-volume\-identifier " Specify the new Logical Volume Identifier. .TP .BI \-\-vid= " new\-volume\-identifier " Specify the new Volume Identifier. .TP .BI \-\-vsid= " new\-volume\-set\-identifier " Specify the new 17.-127. character of Volume Set Identifier. See section \fBUDF LABEL AND UUID\fP. .TP .BI \-\-fsid= " new\-file\-set\-identifier " Specify the new File Set Identifier. .TP .BI \-\-fullvsid= " new\-full\-volume\-set\-identifier " Specify the new Volume Set identifier. Overwrite previous \fB\-\-uuid\fP and \fB\-\-vsid\fP options. See section \fBUDF LABEL AND UUID\fP. .SS ENCODING OPTIONS .TP .B \-\-locale Treat identifier string options as strings encoded according to current locale settings (default). Must be specified as first argument. .TP .B \-\-u8 Treat identifier string options as strings encoded in 8-bit OSTA Compressed Unicode format, equivalent to Latin1 (ISO-8859-1). Must be specified as first argument. .TP .B \-\-u16 Treat identifier string options as strings encoded in 16-bit OSTA Compressed Unicode format, equivalent to UCS-2BE. Note that it is not possible to include zero byte in command line options, therefore any character which has at least one zero byte cannot be supplied (this applies to all Latin1 characters). Must be specified as first argument. .TP .B \-\-utf8 Treat identifier string options as strings encoded in UTF-8. Must be specified as first argument. .SH "UDF LABEL AND UUID" UDF specification does not say anything about a disk label but describe that UDF Logical Volume Identifier is extremely important field for media identification in a jukebox as that field is displayed to the user. And based on this statement it is a common practice for majority of UDF implementations to use UDF Logical Volume Identifier as a UDF disk label. UDF specification does not have concept of disk UUID like other filesystems. But mandates that the first 16 characters of UDF Volume Set Identifier are unique, a non-fixed and a non-trivial value. Plus first eight characters are hexadecimal digits. Windows application format.exe and Mac OS X application newfs_udf are known to violates this requirement and set only the first 8 characters as unique (others are fixed). Because there are still lot of UDF implementations which use in the first 16 characters only hexadecimal digits and all compliant UDF implementations have hexadecimal digits in the first 8 characters, the following algorithm for generating stable UUID was informally chosen and now is used by udftools, util-linux, grub2 and other projects: .RS 0. If Volume Set Identifier has less then 8 characters then stop with empty UUID .br 1. Take the first 16 bytes from UTF-8 encoded string of Volume Set Identifier .br 2. If all bytes are hexadecimal digits then use their lowercase form as UUID .br 3. If first 8 bytes are not all hexadecimal digits then convert those 8 bytes to their hexadecimal representation (resulting in 16 bytes) and use as UUID .br 4. Otherwise, compose UUID from two 8 byte parts: .RS 1. part: Use lowercase form of the first 8 bytes (which are hexadecimal digits) .br 2. part: Convert next 4 bytes (9.-12. pos.) to their hexadecimal representation .RE .RE Which means that this generated UUID has always 16 hexadecimal lowercase digits. In most cases this UUID matches case-insensitively the first 16 characters of UDF Volume Set Identifier and for all disks compliant to the UDF specification the first 8 bytes of UUID matches case-insensitively the first 8 characters of UDF Volume Set Identifier. In that algorithm was chosen UTF-8 encoding because it is the only commonly used Unicode transformation to bytes with fixed points in all hexadecimal digits. .SH "EXIT STATUS" \fBudflabel\fP returns 0 if successful, non-zero if there are problems like block device does not contain UDF filesystem or updating failed. .SH LIMITATIONS \fBudflabel\fP is not able to set new Label, Logical Volume Identifier and File Set Identifier for disks with Metadata Partition (used by UDF revisions higher then 2.01) or Virtual Allocation Table (used by Write Once media). Also is not able to read Label correctly if disk has Virtual Allocation Table stored outside of Information Control Block. .SH AUTHOR .nf Pali Rohár .fi .SH AVAILABILITY \fBudflabel\fP is part of the udftools package since version 2.0 and is available from https://github.com/pali/udftools/. .SH "SEE ALSO" \fBmkudffs\fP(8), \fBpktsetup\fP(8), \fBcdrwtool\fP(1), \fBudfinfo\fP(1), \fBwrudf\fP(1) udftools-2.0/doc/pktsetup.80000644000175000017500000000500313221466537012657 00000000000000.\" Copyright 2002 Paul Thompson .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .\" References consulted: .\" losetup.8 .\" udftools src .\" .TH PKTSETUP 8 "udftools" "System Management Commands" .SH NAME pktsetup \- set up and tear down packet device associations .SH SYNOPSIS .ad l .B pktsetup .I packet_device block_device .br .B pktsetup .B \-d .I packet_device .br .B pktsetup .B \-s .ad b .SH DESCRIPTION .B Pktsetup is used to associate packet devices with CD or DVD block devices, so that the packet device can then be mounted and potentially used as a read/write filesystem. This requires kernel support for the packet device, and the UDF filesystem. .PP See: HOWTO.udf (in the udftools documents directory) .SH EXIT STATUS .B Pktsetup returns 0 on success, nonzero on failure. .SH OPTIONS .IP "\fB\-d \fIpacket-device\fP" Delete the association between the specified \fIpacket-device\fP and its block device. .IP "\fB\-s\fP" Show the current device mapping, one device per line, in the format \fIname\fP : \fIpktdevid\fP -> \fIblkdevid\fP .br (e.g. "0 : 253:0 -> 22:0") .SH EXAMPLE The following commands provide an example of using the packet device. .nf .IP cdrwtool \-d /dev/sr0 \-q pktsetup 0 /dev/sr0 mount \-t udf /dev/pktcdvd0 /mnt ... umount /dev/pktcdvd0 pktsetup \-d 0 .fi .LP .SH FILES .nf /dev/pktcdvd0,/dev/pktcdvd1,... CD/DVD packet devices .fi .SH AUTHOR .nf Jens Axboe Some additions by Richard Atterer .fi .SH AVAILABILITY .B pktsetup is part of the udftools package and is available from https://github.com/pali/udftools/. .SH "SEE ALSO" .BR cdrwtool (1) udftools-2.0/doc/mkudffs.80000644000175000017500000003655713221466537012461 00000000000000'\" t -*- coding: UTF-8 -*- .\" Copyright 2002 Paul Thompson .\" Copyright 2014-2017 Pali Rohár .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License along .\" with this program; if not, write to the Free Software Foundation, Inc., .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. .TH MKUDFFS 8 "udftools" "System Management Commands" .SH NAME mkudffs \- create an UDF filesystem .SH SYNOPSIS .BI "mkudffs [ options ] " device " [ " blocks\-count " ] " .SH DESCRIPTION \fBmkudffs\fP is used to create a UDF filesystem on a device (usually a disk). \fIdevice\fP is the special file corresponding to the device (e.g. \fI/dev/hdX\fP) or file image. \fIblocks\-count\fP is the number of blocks on the device. If omitted, \fBmkudffs\fP automagically figures the filesystem size. The order of options matters. Encoding option must be first and options to override default settings implied by the media type or UDF revision should be after the option they are overriding. .SH OPTIONS .TP .B \-h,\-\-help Display the usage and list of options. .TP .BI \-l,\-\-label= " label " Specify the UDF label. UDF label is synonym for specifying both \fB\-\-lvid\fP and \fB\-\-vid\fP options. If omitted, \fBmkudffs\fP label is \fILinuxUDF\fP. (Option available since mkudffs 1.1) .TP .BI \-u,\-\-uuid= " uuid " Specify the UDF uuid. Must be exactly 16 hexadecimal lowercase digits and is used for first 16 characters of \fB\-\-fullvsid\fP option. If omitted, \fBmkudffs\fP uuid is generated from local time and random number. (Option available since mkudffs 1.1) .TP .BI \-b,\-\-blocksize= " block\-size " Specify the size of blocks in bytes. Valid block size for a UDF filesystem is power of two in range from 512 to 32768 and must match a device logical (sector) size. If omitted, \fBmkudffs\fP block\-size is set to device logical block (sector) size. If logical block (sector) size is unknown (e.g. when creating disk image) then for \fB\-\-media\-type\fP=\fIhd\fP is used block\-size 512 and for other media types 2048. .TP .BI \-m,\-\-media\-type= " media\-type " Specify the media type. Must be specified before \fB\-\-udfrev\fP. Valid media types are: .RS 1.2i .TP 1.6i hd (default) HD (Hard Disk) .TP worm WORM (Write Once Read Many) .TP mo MO (Magneto Optical) .TP cd CD\-ROM (CD Read\-Only Memory) .TP cdr CD\-R (CD Recordable) .TP cdrw CD\-RW (CD Read\-Write) .TP dvd DVD\-ROM (DVD Read\-Only Memory) .TP dvdr DVD\-R (DVD Recordable) .TP dvdrw DVD\-RW (DVD Read\-Write) .TP dvdram DVD\-RAM (DVD Random Access Memory) .TP bdr BD\-R (Blu\-ray Disc Recordable) .RE .RS (Short option variant \fB\-m\fP and values \fIcd\fP, \fIdvdr\fP, \fIbdr\fP are available since mkudffs 2.0) .RE .TP .BI \-r,\-\-udfrev= " udf\-revision " Specify the UDF revision to use, either in hexadecimal (e.g. 0x0201) or decimal (e.g. 2.01) format. Valid revisions arei 1.02, 1.50, 2.00, 2.01, 2.50 and 2.60. If omitted, \fBmkudffs\fP udf\-revision is \fI2.01\fP, except for Blu-ray Discs which is \fI2.50\fP. UDF revisions higher then 2.01 are experimental. Option must be specified after \fB\-\-media\-type\fP. (Values in decimal format and revisions higher then 2.01 are supported since mkudffs 2.0) .TP .B \-n,\-\-no-write Not really, do not write to \fIdevice\fP. Just simulate and display what would happen with \fIdevice\fP. Useful for determining calculated location of different UDF blocks. (Option available since mkudffs 2.0) .TP .B \-\-new\-file Create a new image file specified by \fIdevice\fP with \fIblocks\-count\fP and fail if file already exists. If omitted, \fBmkudffs\fP creates a new image file only in case it does not exist yet. (Option available since mkudffs 2.0) .TP .BI \-\-lvid= " logical\-volume\-identifier " Specify the \fILogical Volume Identifier\fP. If omitted, \fBmkudffs\fP logical\-volume\-identifier is \fILinuxUDF\fP. Most UDF implementations uses this identifier as a disk label. .TP .BI \-\-vid= " volume\-identifier " Specify the \fIVolume Identifier\fP. If omitted, \fBmkudffs\fP volume\-identifier is \fILinuxUDF\fP. .TP .BI \-\-vsid= " volume\-set\-identifier " Specify the 17.-127. character of \fIVolume Set Identifier\fP. If omitted, \fBmkudffs\fP volume\-set\-identifier is \fILinuxUDF\fP. .TP .BI \-\-fsid= " file\-set\-identifier " Specify the \fIFile Set Identifier\fP. If omitted, \fBmkudffs\fP file\-set\-identifier is \fILinuxUDF\fP. .TP .BI \-\-fullvsid= " full\-volume\-set\-identifier " Specify the full \fIVolume Set Identifier\fP. Overwrite previous \fB\-\-uuid\fP and \fB\-\-vsid\fP options. (Option available since mkudffs 1.1) .TP .BI \-\-uid= " uid " Specify the uid of the root (/) directory. If omitted, \fBmkudffs\fP uid is \fI0\fP. Special value \fI-1\fP means invalid or not specified uid. (Option available since mkudffs 1.1) .TP .BI \-\-gid= " gid " Specify the gid of the root (/) directory. If omitted, \fBmkudffs\fP gid is \fI0\fP. Special value \fI-1\fP means invalid or not specified gid. (Option available since mkudffs 1.1) .TP .BI \-\-mode= " mode " Specify permissions in octal mode bits of the root (/) directory. If omitted, \fBmkudffs\fP mode is \fI0755\fP. (Option available since mkudffs 2.0) .TP .BI \-\-bootarea= " fill " Specify how to fill UDF boot area which is first 32kB of disk and is not used by UDF itself. Option \fImbr\fP make sense only when running mkudffs on whole disk, not on just one partition. Valid options are: .RS 1.2i .TP 1.6i preserve preserve existing UDF boot area, do not touch it (default for media type different from hd) .TP erase erase existing UDF boot area, fill it by zeros (default for hd media type on partitions and on removable disks) .TP mbr put MBR table with one partition which starts at sector 0 (includes MBR itself) and spans whole disk device, needed only for non-removable hard disks used on Microsoft Windows systems (default for hd media type on non-removable hard disk without partitions), see section \fBWHOLE DISK VS PARTITION\fP .RE .RS (Option available since mkudffs 2.0) .RE .TP .BI \-\-strategy= " strategy " Specify the allocation strategy to use. Valid strategies are 4 and 4096. If omitted, \fBmkudffs\fP strategy is based on the \fB\-\-media\-type\fP. .TP .BI \-\-spartable,\ \-\-spartable= " spartable\-number " Enable usage Sparing Table. Optionally specify also the number of sparing tables. Valid numbers are 1-4. When spartable\-number is omitted then two tables are written to disc. If option is omitted then usage of Sparing Table depends on media type. (Option prior to mkudffs 2.0 was available only for cdrw media type) .TP .BI \-\-sparspace= " num\-of\-entires " Specify the number of entries in Sparing Table. If omitted, default number of entries is 1024, but depends on media type. (Option available since mkudffs 2.0) .TP .BI \-\-packetlen= " length " Packet length in number of blocks for Sparing Table. It specify also size of the Sparing Space. If omitted, default value for DVD discs 16 blocks, otherwise 32. .TP .B \-\-vat Enable usage of Virtual Allocation Table (VAT). If omitted, usage depends on media type. (Option available since mkudffs 2.0) .TP .B \-\-closed Close disc with Virtual Allocation Table. AVDP is written also to the end of disc. By default disc with Virtual Allocation Table is not closed. .TP .BI \-\-space= " space " Specify the Space Set. \fIUnallocated\fP Space Set is used for media which blocks may be allocated immediately. \fIFreed\fP Space Set is used for media which blocks needs to be specially prepared/erased before allocation. In Space \fITable\fP is stored list of unallocated extents. In Space \fIBitmap\fP is stored bitmap of unallocated blocks. Not used for VAT. .RS 1.2i .TP 1.6i freedbitmap Freed Bitmap .TP freedtable Freed Table .TP unallocbitmap Unallocated Bitmap (default) .TP unalloctable Unallocated Table .RE .TP .BI \-\-ad= " ad " Specify the Allocation Descriptors of the root (/) directory. .RS 1.2i .TP 1.6i inicb Allocation Descriptors in ICB (default) .TP short Short Allocation Descriptors .TP long Long Allocation Descriptors .RE .TP .B \-\-noefe Don't Use Extended File Entries for the root (/) directory. Affects only UDF 2.00 or higher. Must be specified after \fB\-\-udfrev\fP. .TP .B \-\-locale Treat identifier string options as strings encoded according to current locale settings (default). Must be specified as first argument. (Option available since mkudffs 2.0) .TP .B \-\-u8 Treat identifier string options as strings encoded in 8-bit OSTA Compressed Unicode format, equivalent to Latin1 (ISO-8859-1). Must be specified as first argument. .TP .B \-\-u16 Treat identifier string options as strings encoded in 16-bit OSTA Compressed Unicode format, equivalent to UCS-2BE. Note that it is not possible to include zero byte in command line options, therefore any character which has at least one zero byte cannot be supplied (this applies to all Latin1 characters). Must be specified as first argument. .TP .B \-\-utf8 Treat identifier string options as strings encoded in UTF-8. Must be specified as first argument. .SH COMPATIBILITY .SS "OPERATING SYSTEMS SUPPORT" UDF filesystem is natively supported by large amount of operating systems. See following compatibility table: .TS box; c s|c s c|c|c|c l|l|c|c. Operating system Maximum UDF revision for _ Name Version read write = Linux 2.3.17 - 2.4.5 2.00 2.00 \^ 2.4.6 - 2.6.25 2.01 2.01 \^ 2.6.26 (and new) 2.50 2.01 _ Windows 98/Me 1.02 none \^ 2000 1.50 none \^ XP 2.01 none \^ Vista (and new) 2.60 2.50 _ Mac OS 8.1 - 8.5 1.02 none \^ 8.6 - 9.2 1.50 1.50 _ Mac OS X 10.0 - 10.3 1.50 1.50 \^ 10.4 2.01 2.01 \^ 10.5 (and new) 2.60 2.50 _ FreeBSD 5 (and new) 1.50 none _ NetBSD 4.0 2.60 none \^ 5.0 (and new) 2.60 2.60 _ OpenBSD 3.8 - 3.9 1.02 none \^ 4.0 - 4.6 1.50 \^ \^ 4.7 (and new) 2.60 \^ _ Solaris 7 (and new) 1.50 1.50 _ AIX 5.2 (and new) 2.01 2.01 .TE Note that Windows 98 and Windows Me can read UDF filesystem only from CD and DVD optical discs, not from hard disks. .SS "BLOCK SIZE" In most cases operating systems are unable to mount UDF filesystem if UDF block size differs from logical sector size of device. Typically hard disks have sector size 512 bytes and optical media 2048 bytes. Therefore UDF block size must match logical sector size of device. Linux kernel prior to version 2.6.30 used hardcoded UDF block size of 2048 bytes independently of logical sector size, therefore it was not able to automatically mount UDF filesystem if block size differed from 2048. Since 2.6.30 and prior to 4.11 Linux kernel used logical sector size of device as UDF block size, plus it tried fallback to 2048. Since 4.11 it uses logical sector size and fallbacks to any valid block size between logical sector size and 4096. Therefore since version 2.6.30 Linux kernel can automatically mount UDF filesystems correctly if UDF block size matches device logical sector size and since version 4.11 can automatically also mount devices which sector size does not match UDF block size. In any case and also for Linux kernel prior to version 2.6.30, different UDF block size (which is not autodetected) can be manually specified via \fBbs\fP=\fIblocksize\fP mount parameter. .SS "WHOLE DISK VS PARTITION" UDF filesystem is supposed to be formatted on the whole media and not to the partitioned hard disk. Mac OS X systems enforce this rule and reject to automatically mount UDF filesystem unless it is formatted on the whole unpartitioned hard disk. Possible partition table (e.g. MBR or GPT) on disk with valid UDF filesystem is ignored. On the other hand Microsoft Windows systems are unable to detect non-removable hard disks without MBR or GPT partition table. Removable disks do not have this restriction. Consequence is that non-removable hard disks formatted to UDF by Windows Vista+ are not recognized by Mac OS X systems and vice-versa. Note that manual mount of UDF partition on partitioned hard disk on Mac OS X system is possible and working (e.g. by running commands mkdir /Volumes/DriveName && mount_udf /dev/disk1s1 /Volumes/DriveName). But there is no known way to mount unpartitioned non-removable disk on Windows system. Thanks to reserved and unused UDF boot area (first 32kB of UDF filesystem) it is possible to deal with this problem, by putting MBR on such non-removable hard disk just for compatibility reasons with Windows. Such MBR table would contain one partition which starts at sector 0 (includes MBR itself) and span whole disk device. So the whole disk device and also first partition on disk points to same sectors. Therefore UDF filesystem can be mounted either from whole disk device (needed for Mac OS X systems) or from first partition (needed for Microsoft Windows systems). Linux kernel ignores MBR table if contains partition which starts at sector 0. Normally Linux kernel can detect and mount UDF filesystem either on partition or on whole disk device. It does not have any restrictions. \fBmkudffs\fP option \fB\-\-bootarea\fP=\fImbr\fP put such MBR table for compatibility with Microsoft Windows systems into disk when formatting. .SS "LINUX LABEL BUGS" In most cases \fILogical Volume Identifier\fP is used as UDF label. But Linux libblkid prior to version 2.26 used \fIVolume Identifier\fP. Therefore \fBmkudffs\fP \fB\-\-label\fP for compatibility reasons set both \fILogical Volume Identifier\fP and \fIVolume Identifier\fP. Linux libblkid prior to version 2.30 incorrectly processed non-ASCII identifier strings encoded in 8-bit OSTA Compressed Unicode format. Therefore \fBmkudffs\fP since version 2.0 for compatibility reasons tries to encode non-ASCII identifier strings in 16-bit OSTA Compressed Unicode format and then fallbacks to 8-bit format. For more information about UDF Label and UUID see \fBudflabel\fP(8) section \fBUDF LABEL AND UUID\fP. .SH "EXIT STATUS" \fBmkudffs\fP returns 0 if successful, non-zero if there are problems. .SH LIMITATIONS \fBmkudffs\fP cannot create UDF 2.50 Metadata partition, therefore it does not support UDF revisions higher then 2.01 for non Write Once media yet. So there is no support for Blu\-ray discs which needs UDF 2.50 (except for Blu\-ray Disc Recordable which does not require Metadata partition). .SH BUGS \fBmkudffs\fP prior to version 1.1 was unable to process non-ASCII characters from identifier strings in \fB\-\-utf8\fP mode, \fB\-\-vsid\fP option was completely broken and \fB\-\-blocksize\fP must have been manually specified for hard disks as default value was hardcoded for optical disks. \fBmkudffs\fP prior to version 2.0 generated broken and unreadable cdr disc images. .SH AUTHOR .nf Ben Fennema Pali Rohár .fi .SH AVAILABILITY \fBmkudffs\fP is part of the udftools package and is available from https://github.com/pali/udftools/. .SH SEE ALSO \fBpktsetup\fP(8), \fBudflabel\fP(8), \fBcdrwtool\fP(1), \fBudfinfo\fP(1), \fBwrudf\fP(1) udftools-2.0/doc/mkfs.udf.80000644000175000017500000000001613221466537012514 00000000000000.so mkudffs.8 udftools-2.0/doc/wrudf.10000644000175000017500000000164413221466537012127 00000000000000.\" Text automatically generated by txt2man .TH wrudf 1 "udftools" "Linux Reference Manual" .SH NAME \fBwrudf \fP- Maintain an UDF filesystem. .SH SYNOPSIS .nf .fam C \fBwrudf\fP \fIdevice\fP \fBwrudf\fP \fB--help\fP | \fB-help\fP | \fB-h\fP .fam T .fi .fam T .fi .SH DESCRIPTION \fBwrudf\fP provides an interactive shell with operations on existing UDF filesystem: cp, rm, mkdir, rmdir, ls, cd. .SS COMMANDS .TP .B cp copy .TP .B rm remove .TP .B mkdir make directory .TP .B rmdir remove directory .TP .B lsc list files (Compact disc version) .TP .B lsh list files (Hard disc version) .TP .B cdc change working directory (Compact disc) .TP .B cdh change working directory (Hard disc) .TP .B quit quit \fBwrudf\fP .TP .B exit quit \fBwrudf\fP .SH AVAILABILITY \fBwrudf\fP is part of the udftools package and is available from https://github.com/pali/udftools/. .SH SEE ALSO \fBcdrwtool\fP(1), \fBmkudffs\fP(8), \fBpktsetup\fP(8) udftools-2.0/doc/udfinfo.10000644000175000017500000001552713221466537012437 00000000000000'\" t -*- coding: UTF-8 -*- .\" Copyright (C) 2017 Pali Rohár .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License along .\" with this program; if not, write to the Free Software Foundation, Inc., .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. .TH UDFINFO 1 "udftools" "Commands" .SH NAME udfinfo \- show information about UDF filesystem .SH SYNOPSIS .BI "udfinfo [ options ] " device .SH DESCRIPTION \fBudfinfo\fP shows various information about a UDF filesystem stored either on the block device or in the disk file image. The output from the \fBudfinfo\fP is suitable for parsing by external applications or scripts. .SH OPTIONS .TP .B \-h,\-\-help Display the usage and the list of options. .TP .BI \-b,\-\-blocksize= " block\-size " Specify the size of blocks in bytes. Valid block size for a UDF filesystem is power of two in range from 512 to 32768 and must match a device logical (sector) size. If omitted, \fBudfinfo\fP tries to autodetect block size. It tries logical (sector) size and then all valid block sizes. .TP .BI \-\-vatblock= " vat\-block " Specify the block location of the Virtual Allocation Table. Virtual Allocation Table is present only on UDF disks with Virtual Partition Map and must be at the last written/recorded disk block. If omitted, \fBudfinfo\fP for optical disc tries to detect the last recorded block with fallback to the last block of block device or disk file image. In most cases this fallback does not have to work and for disk file images with Virtual Allocation Table is necessary to specify correct location. Virtual Allocation Table contains locations of UDF disk blocks needed to read data storage, determinate used and free space blocks, read File Set Identifier and calculate Windows specific Volume Serial Number. Also on disks with UDF revisions higher then 1.50 it contains Logical Volume Identifier and overwrite one stored in Logical Volume Descriptor. .TP .B \-\-locale Encode UDF string identifiers on output according to current locale settings (default). .TP .B \-\-u8 Encode UDF string identifiers on output to 8 bit OSTA Compressed Unicode format, equivalent to Latin1 (ISO-8859-1). This will work only for strings which Unicode code points are below U+100. .TP .B \-\-u16 Encode UDF string identifiers on output to 16 bit OSTA Compressed Unicode format, equivalent to UCS-2BE. .TP .B \-\-utf8 Encode UDF string identifiers on output to UTF-8. .SH "EXIT STATUS" \fBudfinfo\fP returns 0 if successful, non-zero if there are problems like block device does not contain UDF filesystem. .SH "OUTPUT FORMAT" First part of the \fBudfinfo\fP standard output contains information in \fIkey\fP=\fIvalue\fP format. List of all keys with their meaning are in the following table: .RS .TP 1.6i filename File name of the selected block device or disk file image .TP label label is an alias for \fIlvid\fP, see \fBudflabel\fP(8) section \fBUDF LABEL AND UUID\fP .TP uuid UUID are first 16 hexadecimal lowercase digits of \fIfullvsid\fP, but see \fBudflabel\fP(8) section \fBUDF LABEL AND UUID\fP .TP lvid UDF Logical Volume Identifier stored in UDF Logical Volume Descriptor .TP vid UDF Volume Identifier stored in UDF Primary Volume Descriptor .TP vsid \fIfullvsid\fP after \fIuuid\fP part, typically 17.-127. character .TP fsid UDF File Set Identifier stored in UDF File Set Descriptor .TP fullvsid UDF Volume Set Identifier stored in UDF Primary Volume Descriptor .TP winserialnum Windows specific Volume Serial Number .TP blocksize UDF block size .TP blocks Number of all blocks on the selected block device or disk file image .TP usedblocks Number of used space blocks on UDF disk for data storage .TP freeblocks Number of free space blocks on UDF disk for data storage .TP behindblocks Number of blocks which are behind the last block used by UDF disk .TP numfiles Number of stored files on UDF disk .TP numdirs Number of stored directories on UDF disk .TP udfrev UDF revision needed for reading UDF disk .TP udfwriterev UDF revision needed for writing or modifying UDF disk .TP vatblock UDF block location of the Virtual Allocation Table (visible only when available) .TP integrity UDF integrity of Logical Volume, one of: \fIopened\fP, \fIclosed\fP, \fIunknown\fP .TP accesstype UDF Access Type, one of: \fIoverwritable\fP, \fIrewritable\fP, \fIwriteonce\fP, \fIreadonly\fP, \fIpseudo\-overwritable\fP, \fIunknown\fP .RE When UDF integrity is not \fIclosed\fP it means that the UDF disk was not properly unmounted, is in inconsistent state and needs repairing. All UDF string identifiers are stored on UDF disk in Unicode, therefore they are locale or code page agnostic. Options \fB\-\-locale\fP, \fB\-\-u8\fP, \fB\-\-u16\fP and \fB\-\-utf8\fP controls how are identifiers encoded on output. All newline characters from the UDF string identifiers are removed, so it is guaranteed that the newline character is present only as a separator. Second part of the \fBudfinfo\fP standard output contains list of UDF block types stored on device, one per line in the following format: .RS start=\fIblock\-num\fP, blocks=\fIblock\-count\fP, type=\fIblock\-type\fP .RE With meaning that \fIblock\-type\fP starts at UDF block \fIblock\-num\fP and span \fIblock\-count\fP blocks on device. Windows specific \fIVolume Serial Number\fP is a non-standard 32 bit checksum, calculated as four separate 8 bit XOR checksums of 512 bytes long UDF File Set Descriptor. Therefore it cannot be set or changed as opposite to UUID which is moreover 64 bit long. This non-standard checksum is used only by Windows systems (since Windows 98 era when it was introduced) and can be displayed on Windows systems by applications like \fBvol\fP, \fBdir\fP or \fBfsutil\fP. .SH LIMITATIONS \fBudfinfo\fP is not able to read Metadata Partition and Virtual Allocation Table stored outside of Information Control Block yet. Therefore determining used and free space blocks, reading File Set Identifier and calculating Windows specific Volume Serial Number may not be available for some Write Once media and disks with UDF revisions higher then 2.01 which have Metadata Partition. .SH AUTHOR .nf Pali Rohár .fi .SH AVAILABILITY \fBudfinfo\fP is part of the udftools package since version 2.0 and is available from https://github.com/pali/udftools/. .SH "SEE ALSO" \fBmkudffs\fP(8), \fBpktsetup\fP(8), \fBudflabel\fP(8), \fBcdrwtool\fP(1), \fBwrudf\fP(1) udftools-2.0/doc/cdrwtool.10000644000175000017500000001044713221466537012636 00000000000000.\" Copyright 2002 Paul Thompson .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, .\" USA. .\" .\" References consulted: .\" udf-0.9.5 source .\" .\" .TH CDRWTOOL 1 "udftools" "Commands" .SH NAME cdrwtool \- perform various actions on a CD-R, CD-RW, and DVD-R .SH SYNOPSIS .BI "cdrwtool \-d " device " \-i | \-g" .PP .BI "cdrwtool \-d " device " \-s [ " write-parameters " ]" .PP .BI "cdrwtool \-d " device " \-q [ " write-parameters " ]" .PP .BI "cdrwtool \-d " device " \-m " offset " [ " write-parameters " ]" .PP .BI "cdwrtool \-d " device " \-u " blocks " [ " write-parameters " ]" .PP .BI "cdrwtool \-d " device " \-b " b_mode " [ " write-parameters " ]" .PP .BI "cdrwtool \-d " device " \-c " blocks " [ " write-parameters " ]" .PP .BI "cdwrtool \-d " device " \-f " filename " [ " write-parameters " ]" .PP .BI "cdwrtool \-d " device " \-r " track " [ " write-parameters " ]" .PP .BI "cdrwtool \-h" .SH DESCRIPTION The \fBcdwrtool\fP command can perform certain actions on a CD-R, CD-RW, or DVD-R device. Mainly these are blanking the media, formatting it for use with the packet-cd device, and applying an UDF filesystem. .PP The most common usage is probably the `quick setup' option: .IP .BI "cdrwtool \-d " device " \-q" .PP which will blank the disc, format it as one large track, and write the UDF filesystem structures. .PP Other options get and set various parameters of how the device is set up, and provide for different offsets, modes and settings from the defaults. .PP The usefulness of most of the options is not explained. .SH OPTIONS Main directives: .IP "\fB\-d \fIdevice\fP" Specify the device to use. eg. \fI/dev/sr0\fP .IP \fB\-i\fP Print disc track info. .IP \fB\-g\fP Print write parameters. .IP "\fB\-u \fIlength\fP" Make a UDF filesystem using \fIlength\fP number of blocks. .IP "\fB\-q\fP" `Quick setup': blank the disc, format it as one large track and write a UDF filesystem. .IP "\fB\-m \fIoffset\fP" Format the disc at \fIoffset\fP number of blocks. .IP "\fB\-b \fImode\fP" Blank the disk using a \fImode\fP of `full' or `fast'. .IP "\fB\-f \fIfilename\fP" Write file. .IP "\fB\-c \fItrack\fP" Close track. .IP "\fB\-r \fItrack\fP" Reserve track. .IP "\fB\-z \fIlength\fP" Fixed packet length. .IP \fB\-s\fP Set write parameters determined by .BR "\-l" , " \-w" ", and" " \-p" options for the disc. .IP "\fB\-v \fIversion\fP" Specify the udf revision to use. Valid revisions are 0x0201, 0x0200, 0x0150, and 0x0102. If omitted, .B mkudffs udf-version is 0x0150. .IP \fB\-h\fP Prints a sparse help message. .PP Write parameters: .IP "\fB\-t \fIspeed\fP" Set write speed. (Defaults to 12x ?) .IP "\fB\-l \fItype\fP" Set multi\-session field. Either `0' (default), `1', or `3', corresponding to `No B0 pointer. Next Session not allowed', `B0 pointer = FF:FF:FF. Next session not allowed', and `Next session allowed. B0 pointer = next possible program area' respectively. .IP "\fB\-w \fImode\fP" Set write mode. Either `mode1' or `mode2' (default). .IP "\fB\-p \fItype\fP" Set packet type. Either `0' or `1' (default), corresponding to variable and fixed packet sizes respectively. .IP "\fB\-o \fIoffset\fP" Set write offset. .SH AUTHORS .nf Jens Axboe Ben Fennema Some additions by Richard Atterer .fi .SH AVAILABILITY .B cdrwtool is part of the udftools package and is available from https://github.com/pali/udftools/. .SH "SEE ALSO" .BR pktsetup (8) udftools-2.0/doc/UDF-Specifications0000644000175000017500000000052513221466537014215 00000000000000The UDF Specifications are available as free PDF files from OSTA at: http://www.osta.org/specs/ Many IEC/ISO standards that they reference are co-published by ECMA. For example, Ecma publication ECMA-167 is also approved as ISO/IEC 13346. They are available as free PDF files from ECMA at: http://www.ecma-international.org/publications/ udftools-2.0/doc/HOWTO.udf0000644000175000017500000001347613221466537012324 00000000000000udftools =================== Kernel support for packet writing --------------------------------- Packet writing is a technique by which a writable medium (typically a CD or DVD) can be used just like a USB stick or a directory on the hard disc: Files and directories can be created/renamed/removed freely, and no separate "burning" step is necessary to write the data to the medium. Packet writing is possible both with write-once media (CD-R, DVD+R, DVD-R) and rewritable media (CD-RW, DVD+RW, DVD-RW). Obviously, with write-once media the free space on the filesystem will not increase if you delete files. In order to do packet writing under Linux, your kernel needs both support for UDF (Universal Disc Format) filesystems and for packet writing. This is the case for kernels later than about 2.6.10. This package tries to support both old-style packet writing (kernel <2.6.8), and the newer variant (>=2.6.10), with and without udev. Use a recent 2.6 kernel for optimum results! Formatting and using a UDF DVD-RW or CD-RW for packet writing ------------------------------------------------------------- The commands differ depending on whether you are using DVD or CD media. 1) Edit /etc/udftools.conf and add your drive for packet writing. For example, if your CD/DVD writer is /dev/hdc and you want it available as the default /dev/pktcdvd/0, then use the setting "DEVICES=/dev/hdc". Execute "/etc/rc.d/rc.udftools start" afterwards to register the device. If the device name /dev/hdc differs on your system, adjust the following commands as appropriate. 2) Prepare the medium in restricted overwrite mode: DVD-RW: dvd+rw-format -force /dev/hdc CD-RW: Do nothing, skip this step! 3) Write an empty session spanning the whole medium. It seems that without this step, any attempt to create the UDF filesystem will fail. DVD-RW: growisofs -Z /dev/hdc=/dev/zero CD-RW: cdrwtool -d /dev/hdc -q 4) Format the packet device in UDF format. DVD-RW: mkudffs --udfrev=0x0150 --spartable=2 --media-type=dvdrw /dev/pktcdvd/0 CD-RW: mkudffs --udfrev=0x0150 --spartable=2 --media-type=cdrw /dev/pktcdvd/0 The parameters require some more explanation: For --udfrev, use either 0x0150 for UDF version 1.50, or 0x0201 for UDF version 2.01. The version decision has mostly to do with compatibility: - Windows 98/ME can read up to v1.02 - Windows 2000, Mac OS 9, Linux 2.4 can read up to v1.50 - Windows 2003/XP can read up to v2.01 - Linux 2.6 can read up to v2.60 For normal data, UDF 1.50 is OK. UDF 2.00 and 2.01 introduce additional functionality for streaming audio/video. Possible values for --media-type are: hd dvdram dvdrw worm mo cdrw cdr. Use the one appropriate for your medium/device. 5) Mount the disc. The "noatime" option is important: It will reduce the amount of writes to the device and thus increase its lifetime. You may first have to create the mount directory using "mkdir /media/dvd0": mount -t udf -o rw,noatime /dev/pktcdvd/0 /media/dvd0 The "sync" mount option might also be useful, but will typically cause an increased number of write accesses to the medium. From now on, the root user can access the filesystem under /media/dvd0 using read and write operations. 6) If regular users should also have write access, modify the permissions as follows _while the filesystem is mounted_: chgrp plugdev /media/dvd0 # Set group ownership to "plugdev" chmod g+rwx /media/dvd0 # Give full read/write access to group Now all users who should have access to the disc need to be added to the "plugdev" group using "adduser plugdev". To also allow these users to mount and unmount/eject the medium, you can use either of these two routes: - Install the "pmount" package and add the device to the list of allowed devices using "echo /dev/pktcdvd/0 >>/etc/pmount.allow". All members of the group "plugdev" will then be able to mount the disc using "pmount /dev/pktcdvd/0 dvd0" and unmount it using "pumount /media/dvd0". - Add a line like the following to /etc/fstab: /dev/pktcdvd/0 /media/dvd0 udf rw,noatime,users,noauto 0 0 This will enable _all_ users to mount the disc using "mount /media/dvd0" and unmount it with "umount /media/dvd0". However, with the permissions from step 5) above, only the members of group "plugdev" ought to be able to write to it. Support for UDF filesystems --------------------------- UDF (not packet writing) support in Linux 2.4 and later kernels is sufficient to read from and write to UDF filesystems. For example, you can create a regular file, "format" it using mkudffs, and then loop-mount it. To do this, execute the following commands as root: (After "count=", supply the required size in MB of the filesystem.) dd if=/dev/zero of=udfimage bs=1M count=10 mkudffs udfimage mkdir udfmnt mount -o loop -t udf udfimage udfmnt You need Linux 2.4+ with UDF read *and* write support enabled. Now you can copy data to the "udfmnt" directory. After an "umount udfmnt", the file "udfimage" could theoretically be written to a CD-R(W) or DVD-R(W). In practice, you will not want to do that, as the whole point of using UDF is to do packet writing. "/dev/pktcdvd0" not present? ---------------------------- The "pktsetup" tool requires a device like /dev/pktcdvd0, /dev/pktcdvd1 etc. If the device is not present on your system, this means one of two things: - You are using devfs (the file /dev/.devfsd is present). In this case, just try to use the device, and the appropriate driver should be loaded automatically. - You are not using devfs now, but it was being used at the time the udftools package was installed. In this case, you need to create the devices as root now, using the command: dpkg-reconfigure udftools - You are using udev, and there is no packet writing support in your kernel. -- Richard Atterer Wed, 22 Nov 2006 23:38:16 +0100 udftools-2.0/doc/Makefile.am0000644000175000017500000000020513221466537012742 00000000000000dist_man_MANS = cdrwtool.1 udfinfo.1 wrudf.1 mkfs.udf.8 mkudffs.8 pktsetup.8 udflabel.8 dist_doc_DATA = HOWTO.udf UDF-Specifications udftools-2.0/wrudf/0000755000175000017500000000000013221466662011352 500000000000000udftools-2.0/wrudf/ide-pc.h0000644000175000017500000002731713221466537012617 00000000000000/* ide-pc.h * * PURPOSE * Header file for programs using ide-pc.c defined routines * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 2001 Enno Fennema * * HISTORY * 16 Aug 01 ef Created. * */ #ifndef _IDE_PC_H #define _IDE_PC_H #include struct cdrom_inquiry { u_char type : 5; /* 0 */ #define INQ_WORM 4 #define INQ_CDROM 5 u_char qualifier : 3; /* 0 */ u_char type_modifier : 7; /* 1 */ u_char removable : 1; /* 1 */ u_char ansi_version : 3; /* 2 */ u_char ecma_version : 3; /* 2 */ u_char iso_version : 2; /* 2 */ u_char data_format : 4; /* 3 */ u_char res3_54 : 2; /* 3 */ u_char termiop : 1; /* 3 */ u_char aenc : 1; /* 3 */ u_char add_len : 8; /* 4 */ u_char sense_len : 8; /* 5 */ /* only Emulex ??? */ u_char res2 : 8; /* 6 */ u_char softreset : 1; /* 7 */ u_char cmdque : 1; u_char res7_2 : 1; u_char linked : 1; u_char sync : 1; u_char wbus16 : 1; u_char wbus32 : 1; u_char reladr : 1; /* 7 */ char vendor_info[8]; /* 8 */ char prod_ident[16]; /* 16 */ char prod_revision[4]; /* 32 */ char vendor_uniq[20]; /* 36 */ char reserved[40]; /* 56 to 96 */ }; struct cdrom_discinfo { u_short data_length; u_char disc_status :2; #define DS_EMPTY 0 /* Empty disk */ #define DS_APPENDABLE 1 /* Incomplete disk (appendable) */ #define DS_COMPLETE 2 /* Complete disk (closed/no B0 pointer) */ u_char session_status :2; #define SS_EMPTY 0 /* Empty session */ #define SS_APPENDABLE 1 /* Incomplete session */ #define SS_COMPLETE 3 /* Complete session (needs DS_COMPLETE) */ u_char erasable:1; u_char _r1 :3; u_char trk0; u_char nsessions; u_char trk0_lastsession; u_char trk1_lastsession; u_char _r4 :5; u_char uru :1; u_char dbc_v :1; u_char did_v :1; u_char disc_type; u_char _r9; u_char _r10; u_char _r11; u_int disc_id; u_char latest_leadin_msf[4]; u_char last_leadout_msf[4]; u_char barcode[8]; u_char _r32; u_char n_opc; }; struct cdrom_trackinfo { u_short data_length; u_char trk; u_char session; u_char _r4; u_char trk_mode :4; u_char copy :1; u_char damage :1; u_char _r5 :2; u_char data_mode :4; u_char fixpkt :1; u_char packet :1; u_char blank :1; u_char rsrvd_trk :1; u_char nwa_v :1; u_char _r7 :7; u_int trk_start; u_int nwa; u_int free_blks; u_int fixpkt_size; u_int trk_size; }; struct cdrom_buffercapacity { u_short dataLength; u_short rsrvd; u_int totalBufferLength; u_int freeBufferLength; }; struct cdrom_reccapacity { u_int lastblock; u_int blocksize; }; struct cdrom_header { u_char datamode; u_char _r234[3]; int lba; }; #define PGCTL_CURRENT_VALUES 0 #define PGCTL_CHANGE_MASK 1 #define PGCTL_DEFAULT_VALUES 2 #define PGCTL_SAVED_VALUES 3 typedef struct mode_header { u_short data_length; // length excl. this field u_char medium_type; u_char dev_specific; u_short r1; u_short block_desc_length; // 0 } mode_hdr;; #define GPMODE_READ_ERROR_RECOV_PAGE 0x01 // Read/Write Error Recov in Mt Fuji version struct read_error_recovery_params { u_char page_code :6; // 07h u_char _r1 :1; u_char ps :1; u_char length; u_char error_recovery_param; u_char retry_count; u_char _r2[4]; }; #define GPMODE_CACHE_PAGE 0x08 // Cache control page struct cdrom_cacheparams { u_char page_code :6; // 08h u_char _r1 :1; u_char ps :1; u_char length; u_char rcd :1; u_char mf :1; u_char wce :1; u_char _r2 :5; u_short dpftl; u_short minpf; u_short maxpf; u_short maxpfceiling; }; struct cdrom_writeparams { u_char page_code :6; u_char _r1 :1; u_char ps :1; u_char page_length; u_char write_type :4; u_char test_write :1; u_char _r2 :3; u_char trk_mode :4; u_char copy :1; u_char fp :1; u_char multi_session :2; #define MS_NONE 0 /* No B0 pointer. Next session not allowed*/ #define MS_FINAL 1 /* B0 = FF:FF:FF. Next session not allowed*/ #define MS_MULTI 3 /* B0 = Next PA. Next session allowed */ u_char data_blk_type :4; #define DB_RAW 0 /* 2352 bytes of raw data */ #define DB_RAW_PQ 1 /* 2368 bytes (raw data + P/Q Subchannel) */ #define DB_RAW_PW 2 /* 2448 bytes (raw data + P-W Subchannel) */ #define DB_RAW_PW_R 3 /* 2448 bytes (raw data + P-W raw Subchannel)*/ #define DB_RES_4 4 /* - Reserved */ #define DB_RES_5 5 /* - Reserved */ #define DB_RES_6 6 /* - Reserved */ #define DB_VU_7 7 /* - Vendor specific */ #define DB_ROM_MODE1 8 /* 2048 bytes Mode 1 (ISO/IEC 10149) */ #define DB_ROM_MODE2 9 /* 2336 bytes Mode 2 (ISO/IEC 10149) */ #define DB_XA_F1 10 /* 2048 bytes Mode 2? (CD-ROM XA form 1) */ #define DB_XA_F1_8H 11 /* 2056 bytes Mode 2 (CD-ROM XA form 1) + 8 header bytes */ #define DB_XA_F2 12 /* 2324 bytes Mode 2 (CD-ROM XA form 2) */ #define DB_XA_MODE2_MIX 13 /* 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr) */ #define DB_RES_14 14 /* - Reserved */ #define DB_VU_15 15 /* - Vendor specific */ u_char _r4 :4; u_char _r5; u_char _r6; u_char host_appl_code :6; u_char _r7 :2; u_char session_format; u_char _r9; u_int pkt_size __attribute__ ((packed)); u_short audio_pause; u_char mcn[16]; u_char isrc[16]; u_char subhdr0; u_char subhdr1; u_char subhdr2; u_char subhdr3; }; struct cdrom_capabilities { /* CD Cap / mech status */ u_char p_code : 6; u_char p_res : 1; u_char parsave : 1; u_char p_len; /* 0x14 = 20 Bytes */ u_char cd_r_read : 1; /* Reads CD-R media */ u_char cd_rw_read : 1; /* Reads CD-RW media */ u_char method2 : 1; /* Reads fixed packet method2 media */ u_char dvd_rom_read : 1; /* Reads DVD ROM media */ u_char dvd_r_read : 1; /* Reads DVD-R media */ u_char dvd_ram_read : 1; /* Reads DVD-RAM media */ u_char res_2_67 : 2; /* Reserved */ u_char cd_r_write : 1; /* Supports writing CD-R media */ u_char cd_rw_write : 1; /* Supports writing CD-RW media */ u_char test_write : 1; /* Supports emulation write */ u_char res_3_3 : 1; /* Reserved */ u_char dvd_r_write : 1; /* Supports writing DVD-R media */ u_char dvd_ram_write : 1; /* Supports writing DVD-RAM media */ u_char res_3_67 : 2; /* Reserved */ u_char audio_play : 1; /* Supports Audio play operation */ u_char composite : 1; /* Deliveres composite A/V stream */ u_char digital_port_2 : 1; /* Supports digital output on port 2 */ u_char digital_port_1 : 1; /* Supports digital output on port 1 */ u_char mode_2_form_1 : 1; /* Reads Mode-2 form 1 media (XA) */ u_char mode_2_form_2 : 1; /* Reads Mode-2 form 2 media */ u_char multi_session : 1; /* Reads multi-session media */ u_char res_4 : 1; /* Reserved */ u_char cd_da_supported : 1; /* Reads audio data with READ CD cmd */ u_char cd_da_accurate : 1; /* READ CD data stream is accurate */ u_char rw_supported : 1; /* Reads R-W sub channel information */ u_char rw_deint_corr : 1; /* Reads de-interleved R-W sub chan */ u_char c2_pointers : 1; /* Supports C2 error pointers */ u_char ISRC : 1; /* Reads ISRC information */ u_char UPC : 1; /* Reads media catalog number (UPC) */ u_char read_bar_code : 1; /* Supports reading bar codes */ u_char lock : 1; /* PREVENT/ALLOW may lock media */ u_char lock_state : 1; /* Lock state 0=unlocked 1=locked */ u_char prevent_jumper : 1; /* State of prev/allow jumper 0=pres */ u_char eject : 1; /* Ejects disc/cartr with STOP LoEj */ u_char res_6_4 : 1; /* Reserved */ u_char loading_type : 3; /* Loading mechanism type */ #define CAPS_LT_CADDY 0 #define CAPS_LT_TRAY 1 u_char sep_chan_vol : 1; /* Vol controls each channel separat */ u_char sep_chan_mute : 1; /* Mute controls each channel separat*/ u_char disk_present_rep: 1; /* Changer supports disk present rep */ u_char sw_slot_sel : 1; /* Load empty slot in changer */ u_char res_7 : 4; /* Reserved */ u_short max_read_speed; /* Max. read speed in KB/s */ u_short num_vol_levels; /* # of supported volume levels */ u_short buffer_size; /* Buffer size for the data in KB */ u_short cur_read_speed; /* Current read speed in KB/s */ u_char res_16; /* Reserved */ u_char res_17_0 : 1; /* Reserved */ u_char BCK : 1; /* Data valid on falling edge of BCK */ u_char RCK : 1; /* Set: HIGH high LRCK=left channel */ u_char LSBF : 1; /* Set: LSB first Clear: MSB first */ u_char length : 2; /* 0=32BCKs 1=16BCKs 2=24BCKs 3=24I2c*/ u_char res_17 : 2; /* Reserved */ u_short max_write_speed; /* Max. write speed n KB/s */ u_short cur_write_speed; /* Current write speed in KB/s */ }; #define BLANK_DISC 0x00 /* Erase the entire disc */ #define BLANK_MINIMAL 0x01 /* Erase the PMA, 1st session TOC, pregap */ #define BLANK_TRACK 0x02 /* Erase an incomplete track */ #define BLANK_UNRESERVE 0x03 /* Unreserve a track */ #define BLANK_TAIL 0x04 /* Erase the tail of a track: input trackno required */ #define BLANK_UNCLOSE 0x05 /* Unclose the last session */ #define BLANK_SESSION 0x06 /* Erase the last session */ // #define PGCTL_CURRENT_VALUES 0 // #define PGCTL_CHANGE_MASK 1 // #define PGCTL_DEFAULT_VALUES 2 // #define PGCTL_SAVED_VALUES 3 void fail(char *fmt, ...); struct request_sense *get_sense_data(); char* get_sense_string(void); int blank(int fd, int type, int track); // see BLANK_xxx above int format(int fd, int session_grow, int size); int close_track_session(int fd, int close_track, int track); // close_track == 0 --> close session int synchronize_cache(int fd); int test_unit_ready(int fd); #define DS_OPERATIONAL 0 #define DS_NO_DISC 1 #define DS_TRAY_OPEN 2 #define DS_NOT_READY 3 int getDriveState(int fd); // returns DS_xxx int inquiry(int fd, struct cdrom_inquiry *inq); int mediumRemoval(int fd, int allow); int read_discinfo(int fd, struct cdrom_discinfo *di); int read_trackinfo(int fd, struct cdrom_trackinfo *ti, int track); int read_buffercapacity(int fd, struct cdrom_buffercapacity *bufcap); int read_reccapacity(int fd, struct cdrom_reccapacity *rc); int read_header(int fd, struct cdrom_header *hd, u_int block); int reserve_track(int fd, int size); #define SSU_STOP 0 #define SSU_STOP_EJECT 1 #define SSU_START 2 #define SSU_LOAD_START 3 int startStopUnit(int fd, int ssu_action); int readCD(int fd, int sectortype, int lba, int nblocks, unsigned char* buf); int writeCD(int fd, int lba, int nblocks, unsigned char* buf); int mode_sense(int fd, u_char **buffer, u_char **mode, u_char pageno, int pgctl); int mode_select(int fd, u_char *buffer); #ifdef MMC2 int verify(int fd, int lba, int nblocks); #else int verify(int fd, int sectortype, int lba, int nblocks, char* buf); #endif int set_cdspeed(int fd, int readspeed, int writespeed); /* get_write_params sets the pointers to the mode header 'buffer' and the mode page 'wp' */ int get_writeparams(int fd, u_char **buffer, struct cdrom_writeparams **wp, int pgctl); /* to set write params leave buffer and wp as returned by get_write_params */ int set_writeparams(int fd, u_char *buffer, struct cdrom_writeparams *wp); int get_capabilities(int fd, u_char **buffer, struct cdrom_capabilities **cap, int pgctl); #endif udftools-2.0/wrudf/wrudf.h0000644000175000017500000001126713221466537012602 00000000000000/* wrudf.h * * PURPOSE * The header file for wrudf.c and related source files. * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 2001 Enno Fennema * * HISTORY * 16 Aug 01 ef created. */ #include #include #include #include #include "ecma_167.h" #include "osta_udf.h" #include "libudffs.h" struct generic_desc { tag descTag; uint32_t volDescSeqNum; }; extern char* hdWorkingDir; extern int ignoreReadError; extern int device; extern int devicetype; #define DISK_IMAGE 0xAA enum MEDIUM { CDR = 1, CDRW }; extern enum MEDIUM medium; // #define CDR 'R' // #define CDRW 'W' extern uint32_t trackSize; #ifdef _GNU_SOURCE /* I appear not to have readline.h */ char* readline(char* prompt); extern char *line; #else extern char line[256]; #endif extern regid entityWRUDF; extern timestamp timeStamp; enum RV { CMND_OK, CMND_FAILED, WRONG_NO_ARGS, CMND_ARG_INVALID, NOT_IN_RW_PARTITION, DIR_INVALID, EXISTING_DIR, EXISTING_FILE, DELETED_DIR, DELETED_FILE, DOES_NOT_EXIST, DIR_NOT_EMPTY, PERMISSION_DENIED, IS_DIRECTORY }; enum CMND { CMND_CP = 50, CMND_RM, CMND_MKDIR, CMND_RMDIR, CMND_LSC, CMND_LSH, CMND_CDC, CMND_CDH, CMND_QUIT }; extern int cmndc; extern char** cmndv; extern uint32_t options; #define OPT_DUMMY 0x01 #define OPT_FORCE 0x02 #define OPT_RECURSIVE 0x04 extern int spaceMapDirty, usdDirty, sparingTableDirty; extern struct logicalVolDesc *lvd; extern struct partitionDesc *pd; /* The (re)writable partition descriptor */ extern uint16_t virtualPartitionNum; extern uint32_t *vat; extern struct unallocSpaceDesc *usd; extern struct spaceBitmapDesc *spaceMap; extern struct logicalVolIntegrityDesc *lvid; extern struct fileSetDesc *fsd; extern unsigned int usedSparingEntries; extern struct sparingTable *st; typedef struct _dir_ { struct _dir_ *parent, *child; uint32_t dataSize; char *data; long_ad icb; /* icb of this directory itself */ char *name; uint32_t dirDirty; struct fileEntry fe; uint8_t spacer[2048-sizeof(struct fileEntry)]; } Directory; extern Directory *rootDir, *curDir; /*wrudf.c */ char* readLine(char *prompt); /* wrudf-cmnd.c */ int updateDirectory(Directory* dir); Directory *readDirectory(Directory *parentDir, long_ad *icb, char* name); int cpCommand(void); int rmCommand(void); int mkdirCommand(void); int rmdirCommand(void); int cdcCommand(void); int cdhCommand(void); int lscCommand(void); int lshCommand(void); /* wrudf-desc.c */ struct fileIdentDesc* makeFileIdentDesc(char* name); struct fileIdentDesc* findFileIdentDesc(Directory *dir, char* name); int deleteFID(Directory *dir, struct fileIdentDesc *fid); int removeFID(Directory *dir, struct fileIdentDesc *fid); int insertFileIdentDesc(Directory *dir, struct fileIdentDesc* fid); struct fileEntry* makeFileEntry(); /* wrudf-cdrw.c */ enum markAction { FREE, ALLOC }; void markBlock(enum markAction action, uint32_t blkno); extern int lastTrack; extern int sectortype; extern struct cdrom_trackinfo ti; int getExtents(uint32_t requestedLength, short_ad *extents); int freeShortExtents(short_ad* extent); int freeLongExtents(long_ad* extent); void getUnallocSpaceExtent(uint32_t requestLength, uint32_t requestAfter, extent_ad *alloc); void setChecksum(void *descriptor); void updateTimestamp(time_t t, uint32_t ut); /* current time if t = 0 */ void setStrictRead(int yes); uint32_t getPhysical(uint32_t lbn, uint16_t part); void updateSparingTable(); #define ABSOLUTE 0xFFFF /* ignore partition, process physical blocknumber */ /* actually 0xFFFF is a perfectly valid partition number * could make part a uint32_t and use 0xFFFFFFFF * or have write absolute block routine */ #define INVALID 0xFFFFFFFF void* readBlock(uint32_t lbn, uint16_t part); void freeBlock(uint32_t lbn, uint16_t part); void dirtyBlock(uint32_t lbn, uint16_t part); void writeBlock(uint32_t lbn, uint16_t part, void* src); void* readSingleBlock(uint32_t pbn); void* readTaggedBlock(uint32_t lbn, uint16_t part); int readExtents(char* dest, int usesShort, void* extents); int writeExtents(char* src, int usesShort, void* extents); int initIO(char *filename); int closeIO(); /* wrudf-cdr.c */ uint32_t newVATentry(); uint32_t getNWA(); uint32_t getMaxVarPktSize(); uint32_t writeCDR(void* src); void syncCDR(); void writeHDlink(); unsigned char* readCDR(uint32_t lbn, uint16_t partition); int verifyCDR(struct fileEntry *fe); void readVATtable(); void writeVATtable(); /* ide-pc.h */ void fail(char* fmt, ...); udftools-2.0/wrudf/ide-pc.c0000644000175000017500000003403413221466537012604 00000000000000/* ide-pc.c * * PURPOSE * Execute most MMC commands on a ATAPI-Packet command CD(re)writer through IOCTL CDROM_SEND_PACKET * Where similar routines and structures are defined in linux/ cdrom.h this program * maintains structures strictly as defined MMC to facilitate the interface with the CDwriter * at the expense of a simple user interface. * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 2001 Enno Fennema * * HISTORY * * 16 Aug 01 ef Created. */ #include "config.h" #include #include #include #include #include #include /* for u_char etc. */ #include #include /* sleep() */ #include #include "bswap.h" #include "ide-pc.h" typedef struct cdrom_generic_command CGC; static int rv; // -1 if ioctl failed, else equal stat static struct request_sense sense_data; void fail(char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); exit(1); } struct request_sense * get_sense_data() { return &sense_data; } char* get_sense_string() { static char str[128]; sprintf(str, "Stat %d Err %02X Key %02Xx; ASC %02Xx; ASCQ %02Xx; Info %02X%02X%02X%02Xx", rv, sense_data.error_code, sense_data.sense_key, sense_data.asc, sense_data.ascq, sense_data.information[0], sense_data.information[1], sense_data.information[2], sense_data.information[3]); return str; } void initpc(CGC *pc) { memset(pc,0,sizeof(*pc)); memset(&sense_data, 0 , sizeof(sense_data)); pc->sense=&sense_data; pc->data_direction = CGC_DATA_NONE; pc->timeout = 2500; } int blank(int fd, int type, int start) { CGC pc; uint32_t start_be32 = cpu_to_be32(start); initpc(&pc); pc.cmd[0]=GPCMD_BLANK; pc.cmd[1]= type & 7; memcpy(&pc.cmd[2], &start_be32, sizeof(start_be32));/* blank track tail : lba to start blanking * blank track : track number to blank */ return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int close_track_session(int fd, int close_track, int track) { CGC pc; initpc(&pc); pc.cmd[0] = GPCMD_CLOSE_TRACK; pc.cmd[2] = close_track ? 0x01 : 0x02; pc.cmd[5] = track; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int format(int fd, int session_grow, int size) { struct { u_char flh_rsrv; u_char flh_imm; u_short flh_fdlen; u_int id; u_char fd_sg; u_char fd_rsrv[3]; u_int fd_size; } f; CGC pc; initpc(&pc); pc.data_direction = CGC_DATA_WRITE; memset(&f, 0, sizeof(f)); pc.buffer= (void*)&f; pc.buflen= sizeof(f); pc.cmd[0] = GPCMD_FORMAT_UNIT; pc.cmd[1] = 0x17; /* Format Parameter List present; format 0x7 */ f.flh_fdlen = cpu_to_be16(8); f.fd_sg = session_grow; f.fd_size = cpu_to_be32(size); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int set_cdspeed(int fd, int readspeed, int writespeed) { CGC pc; uint16_t readspeed_be16 = cpu_to_be16(readspeed); uint16_t writespeed_be16 = cpu_to_be16(writespeed); initpc(&pc); pc.cmd[0]=GPCMD_SET_SPEED; memcpy(&pc.cmd[2], &readspeed_be16, sizeof(readspeed_be16)); memcpy(&pc.cmd[4], &writespeed_be16, sizeof(writespeed_be16)); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int synchronize_cache(int fd) { CGC pc; initpc(&pc); pc.cmd[0] = GPCMD_FLUSH_CACHE; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int test_unit_ready(int fd) { CGC pc; initpc(&pc); /* Test Unit Ready command = 0x00 */ /* kernel returns -1 when CHECK_CONDITION status returned * sense data is valid and gives further info */ return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int getDriveState(int fd ) { int rv; rv = test_unit_ready(fd); if( rv ) sleep(2); /* wait a bit longer */ rv = test_unit_ready(fd); if( rv < 0 ) return DS_NOT_READY; if( rv == 0 ) return DS_OPERATIONAL; if( sense_data.sense_key == 2 && sense_data.asc == 0x04 && sense_data.ascq == 0x04 ) return DS_OPERATIONAL; if( sense_data.sense_key == 2 && sense_data.asc == 0x3A && sense_data.ascq == 2 ) return DS_TRAY_OPEN; return DS_NO_DISC; } int inquiry(int fd, struct cdrom_inquiry *inq) { CGC pc; initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_INQUIRY; pc.cmd[4]=sizeof(struct cdrom_inquiry); pc.buffer= (void*)inq; pc.buflen= sizeof(struct cdrom_inquiry); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int mediumRemoval(int fd, int allow) { CGC pc; initpc(&pc); pc.data_direction = CGC_DATA_NONE; pc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; pc.cmd[4] = allow; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int read_reccapacity(int fd, struct cdrom_reccapacity *reccap) { CGC pc; initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_READ_CDVD_CAPACITY; pc.buffer=(void*)reccap; pc.buflen=sizeof(struct cdrom_reccapacity); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); reccap->lastblock = be32_to_cpu(reccap->lastblock); reccap->blocksize = be32_to_cpu(reccap->blocksize); return rv; } int read_buffercapacity(int fd, struct cdrom_buffercapacity *bufcap) { CGC pc; uint16_t size_be16 = cpu_to_be16(sizeof(struct cdrom_buffercapacity)); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0] = 0x5C; // READ BUFFER CAPACITY memcpy(&pc.cmd[7], &size_be16, sizeof(size_be16)); pc.buffer=(void*)bufcap; pc.buflen=sizeof(struct cdrom_buffercapacity); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); bufcap->totalBufferLength = be32_to_cpu(bufcap->totalBufferLength); bufcap->freeBufferLength = be32_to_cpu(bufcap->freeBufferLength); return rv; } int reserve_track(int fd, int size) { CGC pc; uint32_t size_be32 = cpu_to_be32(size); initpc(&pc); pc.cmd[0]=GPCMD_RESERVE_RZONE_TRACK; /* 0x53 */ memcpy(&pc.cmd[5], &size_be32, sizeof(size_be32)); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int startStopUnit(int fd, int action) { CGC pc; initpc(&pc); pc.cmd[0] = GPCMD_START_STOP_UNIT; pc.cmd[4] = action; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int read_discinfo(int fd, struct cdrom_discinfo *di) { CGC pc; uint16_t size_be16 = cpu_to_be16( sizeof(struct cdrom_discinfo) ); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_READ_DISC_INFO; memcpy(&pc.cmd[7], &size_be16, sizeof(size_be16)); pc.buffer=(void*)di; pc.buflen=sizeof(struct cdrom_discinfo); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); di->data_length = be16_to_cpu(di->data_length); di->disc_id = be32_to_cpu(di->disc_id); return rv; } int read_header(int fd, struct cdrom_header *hd, u_int block) { CGC pc; uint32_t block_be32 = cpu_to_be32( block ); uint16_t size_be16 = cpu_to_be16( sizeof(struct cdrom_header) ); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_READ_HEADER; memcpy(&pc.cmd[2], &block_be32, sizeof(block_be32)); memcpy(&pc.cmd[7], &size_be16, sizeof(size_be16)); pc.buffer=(void*)hd; pc.buflen=sizeof(struct cdrom_header); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); hd->lba = be32_to_cpu(hd->lba); return rv; } int read_trackinfo(int fd, struct cdrom_trackinfo *ti, int trackno) { CGC pc; uint32_t trackno_be32 = cpu_to_be32( trackno ); uint16_t size_be16 = cpu_to_be16( sizeof(struct cdrom_trackinfo) ); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_READ_TRACK_RZONE_INFO; pc.cmd[1]=1; memcpy(&pc.cmd[2], &trackno_be32, sizeof(trackno_be32)); memcpy(&pc.cmd[7], &size_be16, sizeof(size_be16)); /* 28; if higher data underrun error */ pc.buffer=(void*)ti; pc.buflen=sizeof(struct cdrom_trackinfo); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); ti->data_length = be16_to_cpu(ti->data_length); ti->trk_start = be32_to_cpu(ti->trk_start); ti->nwa = be32_to_cpu(ti->nwa); ti->free_blks = be32_to_cpu(ti->free_blks); ti->fixpkt_size = be32_to_cpu(ti->fixpkt_size); ti->trk_size = be32_to_cpu(ti->trk_size); return rv; } int readCD(int fd, int sectortype, int lba, int n, unsigned char* buf) { CGC pc; uint32_t lba_be32 = cpu_to_be32(lba); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0]=GPCMD_READ_CD; pc.cmd[1]=sectortype << 2; /* Sector type per MCC table 31 */ memcpy(&pc.cmd[2], &lba_be32, sizeof(lba_be32)); pc.cmd[8]=n; /* read n blocks */ pc.cmd[9]=0x10; /* user data only */ pc.buffer=buf; pc.buflen=n * 2048; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int writeCD(int fd, int lba, int nblks, unsigned char* buf) { CGC pc; uint32_t lba_be32 = cpu_to_be32(lba); uint16_t nblks_be16 = cpu_to_be16(nblks); initpc(&pc); pc.data_direction = CGC_DATA_WRITE; pc.cmd[0] = GPCMD_WRITE_10; pc.cmd[1] = 0; /* DPO 0x10; FUA 0x08 */ memcpy(&pc.cmd[2], &lba_be32, sizeof(lba_be32)); memcpy(&pc.cmd[7], &nblks_be16, sizeof(nblks_be16)); pc.buffer = buf; pc.buflen = nblks * 2048; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } #ifdef MMC2 // VERIFY and WRITE_AND_VERIFY are new in MMC2 and not supported by my HP8100 int verify(int fd, int lba, int nblocks) { CGC pc; uint32_t lba_be32 = cpu_to_be32(lba); initpc(&pc); pc.cmd[0] = GPCMD_VERIFY_10; pc.cmd[1] = 0; memcpy(&pc.cmd[2], &lba_be32, sizeof(lba_be32)); pc.cmd[8] = (u_char) nblocks; return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } #endif /* * mode_sense * Returns 8 byte header followed by actual mode page. The HP 8100 recognizes: * 1 - Read Error Recovery page * In MtFuji this is called Read/Write Error recovery mode page * The separate Verify Error Recovery Mode page of SCSI-2 draft has gone. * The HP8100 recovers a change mask of 01 06 36 FF 00 00 00 00 * This would mean retry count 0 to 255 acceptable * and TB, RC, PER and DTE bits settable. Not the DCR bit. * Could these also affect a verify operation. MtFuji VERIFY says no. * 5 - Write parameters page * 8 - Media supported mode page * D - CD-ROM page: Inactivity time, seconds/minute, frames/second * E - CD-ROM Audio Control page * 1D - Timeout and protect (MtFuji 12.11.3.5) * 2A - CD Capabilities mode page * 2F - ASCII message ? : '(c) 1997-1998 HP, license available' */ int mode_select(int fd, u_char *buffer) { CGC pc; int len = 2 + be16_to_cpu(((mode_hdr*)buffer)->data_length); uint16_t len_be16 = cpu_to_be16(len); initpc(&pc); pc.data_direction = CGC_DATA_WRITE; pc.cmd[0] = GPCMD_MODE_SELECT_10; pc.cmd[1] = 0x10; // PF bit pc.buffer = buffer; pc.buflen = len; memcpy(&pc.cmd[7], &len_be16, sizeof(len_be16)); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } int mode_sense(int fd, u_char **buffer, u_char **mode, u_char pageno, int pgctl) { CGC pc; mode_hdr h; int len, offset; uint16_t size_be16 = cpu_to_be16(sizeof(mode_hdr)); uint16_t len_be16; memset(&h, 0x00, sizeof(mode_hdr)); initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0] = GPCMD_MODE_SENSE_10; pc.cmd[2] = (pgctl<<6) + (pageno & 0x3F); memcpy(&pc.cmd[7], &size_be16, sizeof(size_be16)); pc.buffer = (void *)&h; pc.buflen = sizeof(mode_hdr); rv = ioctl(fd, CDROM_SEND_PACKET, &pc); if( rv ) { printf("mode_sense(1): stat %d\n", rv); return rv; } len = 2 + be16_to_cpu(h.data_length); offset = 8 + be16_to_cpu(h.block_desc_length); *buffer = (u_char*) calloc(len, sizeof(u_char)); *mode = &(*buffer)[offset]; pc.buffer = *buffer; pc.buflen = len; len_be16 = cpu_to_be16(len); memcpy(&pc.cmd[7], &len_be16, sizeof(len_be16)); return ioctl(fd, CDROM_SEND_PACKET, &pc); } // MMC-2 feature not supported by my HP 8100 CD-Writer #ifdef MMC2 int get_configuration(int fd, u_char* buffer, int size, u_char feature) { int i, realsize; uint16_t tmp_be16; CGC pc; initpc(&pc); pc.data_direction = CGC_DATA_READ; pc.cmd[0] = 0x46; // GET CONFIGURATION tmp_be16 = cpu_to_be16(feature); memcpy(&pc.cmd[2], &tmp_be16, sizeof(tmp_be16)); tmp_be16 = cpu_to_be16(8); memcpy(&pc.cmd[7], &tmp_be16, sizeof(tmp_be16)); // only to see how much will be returned pc.buffer=(void*)buffer; if( size < 8 ) return -EINVAL; pc.buflen = 8; rv = ioctl(fd, CDROM_SEND_PACKET, &pc); if( rv ) return rv; realsize = be32_to_cpu((int)buffer[0]) + 4; if( realsize < size ) { pc.buflen = realsize; tmp_be16 = cpu_to_be16(realsize); } else { pc.buflen = size; tmp_be16 = cpu_to_be16(size); } memcpy(&pc.cmd[7], &tmp_be16, sizeof(tmp_be16)); return rv = ioctl(fd, CDROM_SEND_PACKET, &pc); } #endif // MMC2 int get_writeparams(int fd, u_char **buffer, struct cdrom_writeparams **wp, int pgctl) { rv = mode_sense(fd, buffer, (u_char**) wp, 0x05, pgctl); (*wp)->pkt_size = be32_to_cpu((*wp)->pkt_size); (*wp)->audio_pause = be16_to_cpu((*wp)->audio_pause); return rv; } int set_writeparams(int fd, u_char *buffer, struct cdrom_writeparams *wp) { wp->pkt_size = cpu_to_be32(wp->pkt_size); wp->audio_pause = cpu_to_be16(wp->audio_pause); rv = mode_select(fd, buffer); wp->pkt_size = be32_to_cpu(wp->pkt_size); wp->audio_pause = be16_to_cpu(wp->audio_pause); return rv; } int get_capabilities(int fd, u_char **buffer, struct cdrom_capabilities **cap, int pgctl) { rv = mode_sense(fd, buffer, (u_char**) cap, GPMODE_CAPABILITIES_PAGE, pgctl); (*cap)->max_read_speed = be16_to_cpu((*cap)->max_read_speed); (*cap)->num_vol_levels = be16_to_cpu((*cap)->num_vol_levels); (*cap)->buffer_size = be16_to_cpu((*cap)->buffer_size); (*cap)->cur_read_speed = be16_to_cpu((*cap)->cur_read_speed); (*cap)->max_write_speed = be16_to_cpu((*cap)->max_write_speed); (*cap)->cur_write_speed = be16_to_cpu((*cap)->cur_write_speed); return rv; } udftools-2.0/wrudf/wrudf-cdr.c0000644000175000017500000002404713221466537013343 00000000000000/* wrudf-cdr.c * */ #include "config.h" #include #include #include #include #include "wrudf.h" #include "ide-pc.h" #include "bswap.h" static unsigned char *blockBuffer; static uint32_t newVATindex; static uint32_t sizeVAT; static uint32_t prevVATlbn; uint64_t CDRuniqueID; // from VAT FE uint32_t newVATentry() { if( newVATindex + 10 > (sizeVAT >> 2) ) { // ensure enough spave for regid and prevVATlbn sizeVAT += 2048; vat = realloc(vat, sizeVAT); if( vat == NULL ) printf("VAT reallocation failed\n"); } /* could go through VAT and try to find unused 0xFFFFFFFF entry rather than alloc new one at the end */ vat[newVATindex] = getNWA() - pd->partitionStartingLocation; return newVATindex++; } uint32_t getNWA() { if( devicetype == DISK_IMAGE ) return lseek(device, 0, SEEK_END) >> 11; if( read_trackinfo(device, &ti, lastTrack) ) printf("Get Track Info failed\n"); if( ti.nwa_v ) return ti.nwa; else return INVALID; } uint32_t getMaxVarPktSize() { struct cdrom_buffercapacity bc; if( devicetype == DISK_IMAGE ) return 1024 * 2048; // nonsense value; just for testing read_buffercapacity(device, &bc); return ((bc.freeBufferLength >> 11) - 20) << 11; // - 20 :: keep some spare blocks ??? } unsigned char* readCDR(uint32_t lbn, uint16_t partition) { int stat; uint32_t pbn = getPhysical(lbn, partition); if( devicetype == DISK_IMAGE ) { stat = lseek(device, 2048 * pbn, SEEK_SET); stat = read(device, blockBuffer, 2048); if( stat != 2048 ) fail("readCDR(hd) failed %m\n"); else return blockBuffer; } stat = readCD(device, sectortype, pbn, 1, blockBuffer); if( stat ) { if( ! ignoreReadError ) printf("readCDR: %s\n", get_sense_string()); return NULL; } return blockBuffer; } void writeHD(uint32_t physical, unsigned char* src) { int stat; stat = lseek(device, 2048 * physical, SEEK_SET); stat = write(device, src, 2048); if( stat != 2048 ) { printf("writeHD failed %m\n"); } } void syncCDR() { // uint32_t nwa; if( device == DISK_IMAGE ) return; synchronize_cache(device); // nwa = getNWA(); // printf("Link from %d to %d\n", nwa-7, nwa-1); } void writeHDlink() { uint32_t blk = getNWA(); int i; for(i = 0; i < 7; i++ ) writeHD(blk+i, blockBuffer); } /* writeBlockCDR() * Writes one 2048 byte block */ uint32_t writeCDR(void* src) { uint32_t physical; physical = getNWA(); // printf("Write CDR sector %d\n", physical); if( devicetype == DISK_IMAGE ) writeHD(physical, src); else { writeCD(device, physical, 1, src); } return physical; } /* flagError * split up extent in (1) good, (2) bad and (3) good subextents. * In bad extent (2) set logicalBlockNum to zero * If (1) is empty, maybe (2) can be merged with immediately preceding bad extent */ long_ad * flagError(long_ad *extents, long_ad *ext, uint32_t pbn) { uint32_t lbn = pbn - pd->partitionStartingLocation; int posInExtent = lbn - ext->extLocation.logicalBlockNum + 1; int blksInExtent = (ext->extLength + 2047) >> 11; /* if there is a preceding extent which is bad and * the current bad block is the first in this extent, * then add this bad to the preceding extent */ if( ext > extents && lbn == ext->extLocation.logicalBlockNum && !ext[-1].extLocation.logicalBlockNum ) { if( ext[0].extLength < 2048 ) { ext[-1].extLength += ext[0].extLength; ext[0].extLength = 0; } else { ext[-1].extLength += 2048; ext[0].extLength -= 2048; ext[0].extLocation.logicalBlockNum++; } return ext - 1; } /* watch one block extents */ if( blksInExtent == 1 ) { ext[0].extLocation.logicalBlockNum = 0; return ext; } /* 1st block of extent is bad */ if( posInExtent == 1 ) { memmove(ext+1, ext, extents - ext + 62); ext[0].extLength = 2048; ext[0].extLocation.logicalBlockNum = 0; ext[1].extLength -= 2048; ext[1].extLocation.logicalBlockNum = lbn + 1; return ext; } /* last block of extent is bad - watch partial block */ if( posInExtent == blksInExtent ) { memmove(ext+1, ext, extents - ext + 62); ext[1].extLength = ext->extLength - 2048; ext[1].extLocation.logicalBlockNum = 0; ext[0].extLength -= ext[1].extLength; return ext; } /* middle block in extent is bad */ memmove(ext+2, ext, extents - ext + 61); memcpy(ext+1, ext, sizeof(long_ad)); ext[0].extLength = 2048 * posInExtent; ext[1].extLength = 2048; ext[1].extLocation.logicalBlockNum = 0; ext[2].extLength -= ext[0].extLength + 2048; ext[2].extLocation.logicalBlockNum = lbn + 1; return ext+1; } int verifyCDR(struct fileEntry *fe) { long_ad *ext, *extents; uint32_t processed; int stat, rv = 0; uint32_t pbn, pbnFE, rewriteBlkno; setStrictRead(1); extents = ext = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr); processed = 0; pbnFE = vat[fe->descTag.tagLocation] + pd->partitionStartingLocation; pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation; if( (fe->icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB ) goto FileEntryOnly; do { if( pbn > pbnFE ) { if( devicetype == DISK_IMAGE ) { printf("Verify %d\n", pbn); stat = 0; // if( (pbn == 557) || pbn == 565 ) stat = 1; /* for testing only */ } else stat = readCD(device, sectortype, pbn, 1, blockBuffer); if( stat ) { printf("readError %d : %s\n", pbn, get_sense_string()); rv++; ext = flagError(extents, ext, pbn); processed = ext->extLength - 2048; } } processed += 2048; pbn++; if( processed == ext->extLength ) { ext++; pbn = ext->extLocation.logicalBlockNum + pd->partitionStartingLocation; processed = 0; } } while (processed < ext->extLength); FileEntryOnly: if( rv == 0 ) { /* no errors in data, now verify FileEntry */ int retries; for( retries = 0; retries < 3; retries++ ) { if( devicetype == DISK_IMAGE ) { printf("Verify %d\n", pbnFE); stat = 0; // if( pbnFE == 552 || pbnFE == 553 ) stat = 1; /* testing only */ } else stat = readCD(device, sectortype, pbnFE, 1, blockBuffer); if( stat == 0 ) { setStrictRead(0); return 0; } printf("readError %d : %s\n", pbnFE, get_sense_string()); pbnFE = getNWA(); vat[fe->descTag.tagLocation] = pbnFE - pd->partitionStartingLocation; writeCDR(fe); } printf("verifyCDR: verify FE failed 3 times\n"); } setStrictRead(0); rewriteBlkno = getNWA() + 1 - pd->partitionStartingLocation; // NWA itself for revised FileEntry fe->lengthAllocDescs = 0; for( ext = extents; ext->extLength; ext++ ) { fe->lengthAllocDescs += sizeof(long_ad); if( ext->extLocation.logicalBlockNum != 0 ) continue; ext->extLocation.logicalBlockNum = rewriteBlkno; rewriteBlkno += ext->extLength >> 11; if( ext->extLength & 2047 ) break; } fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthExtendedAttr + fe->lengthAllocDescs - 16; return rv; } void readVATtable() { uint32_t blkno; struct fileEntry *fe; blkno = getNWA() - (devicetype == DISK_IMAGE ? 1 : 8); prevVATlbn = blkno; fe = (struct fileEntry*)readTaggedBlock(blkno, ABSOLUTE); if( fe->descTag.tagIdent != TAG_IDENT_FE || fe->icbTag.fileType != 0 ) fail("VAT ICB not found\n"); CDRuniqueID = fe->uniqueID; sizeVAT = ((fe->informationLength + 4095) & ~2047); vat = malloc(sizeVAT); memset(vat, 0xFF, sizeVAT); // later or not at all newVATindex = (fe->informationLength - 36) >> 2; if( sizeof(*fe) + fe->lengthExtendedAttr + fe->informationLength <= 2048 ) { memcpy(vat, fe->allocDescs + fe->lengthExtendedAttr, fe->informationLength - 36); } else { readExtents((char*)vat, 1, fe->allocDescs + fe->lengthExtendedAttr); } } void writeVATtable() { regid *id; struct fileEntry *fe; uint64_t i; int stat, retries, size; uint32_t startBlk; short_ad *ext; uint16_t udf_rev_le16; retries = 0; id = (regid*)(&vat[newVATindex]); memset(id, 0, sizeof(regid)); strcpy((char *)id->ident, UDF_ID_ALLOC); udf_rev_le16 = cpu_to_le16(0x150); memcpy(id->identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); id->identSuffix[2] = UDF_OS_CLASS_UNIX; id->identSuffix[3] = UDF_OS_ID_LINUX; *(uint32_t*)(id+1) = prevVATlbn; fe = makeFileEntry(); size = (newVATindex + 9) << 2; fe->informationLength = cpu_to_le64(size); fe->descTag.tagSerialNum = lvid->descTag.tagSerialNum; fe->icbTag.fileType = ICBTAG_FILE_TYPE_UNDEF; fe->fileLinkCount = 0; for( retries = 0; retries < 8; retries++ ) { startBlk = getNWA(); if( sizeof(*fe) + size < 2048 ) { fe->icbTag.flags = ICBTAG_FLAG_AD_IN_ICB; memcpy(fe->allocDescs, vat, size); fe->lengthAllocDescs = cpu_to_le32(size); } else { fe->logicalBlocksRecorded = (size + 2047) >> 11; fe->icbTag.flags = ICBTAG_FLAG_AD_SHORT; ext = (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr); ext->extLength = size; ext->extPosition = startBlk - pd->partitionStartingLocation; fe->lengthAllocDescs = cpu_to_le32(16); } fe->descTag.tagLocation = startBlk - pd->partitionStartingLocation + fe->logicalBlocksRecorded; fe->descTag.descCRCLength = sizeof(*fe) + fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag); setChecksum(&fe->descTag); for( i = 0; i < fe->logicalBlocksRecorded; i++ ) writeCDR(vat + (i<<9)); writeCDR(fe); setStrictRead(1); for( i = 0; i <= fe->logicalBlocksRecorded; i++ ) { // "<=" so including FileEntry if( devicetype == DISK_IMAGE ) { printf("Verify %llu\n", (unsigned long long int)(startBlk+i)); stat = 0; } else stat = readCD(device, sectortype, startBlk + i, 1, blockBuffer); if( stat != 0 ) { printf("writeVATtable verifyError %llu : %s\n", (unsigned long long int)(startBlk + i), get_sense_string()); break; } } if( stat == 0 ) break; } if( retries == 8 ) printf("*** writeVATtable rewrite FAILED\nLast VAT was at LBN %d\n", prevVATlbn); setStrictRead(0); } udftools-2.0/wrudf/wrudf-cdrw.c0000644000175000017500000005547413221466537013542 00000000000000/* wrufd-cdrw.c * * PURPOSE * Lowlevel IO routines. * To minimise reading and writing packets wrudf uses a few 64kb packetbuffers. * Blocks to be read are preferentially taken from those buffers and updates written * to the buffers. Buffers that are in-use will not be discarded. * When a new buffer is required preferentially an unused not-dirty buffer gets overwritten. * If not available, then a unused dirty buffer gets written and is then reused. * If no such buffer can be found the system panics. * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * * (C) 2001 Enno Fennema * * HISTORY * 16 Aug 01 ef Created. */ #include "config.h" #include #include #include #include #include #include #include #include #include /* for CDROM_DRIVE_STATUS */ #include "wrudf.h" #include "ide-pc.h" #include "bswap.h" #define MAXPKTBUFS 4 struct packetbuf { uint32_t inuse; uint32_t dirty; uint32_t bufNum; uint32_t start; unsigned char *pkt; }; int lastTrack; struct cdrom_trackinfo ti; struct read_error_recovery_params *rerp; u_char *rerp_buffer; struct cdrom_cacheparams *cp; u_char *cp_buffer; struct packetbuf pktbuf[MAXPKTBUFS+1]; /* last one special use */ static unsigned char *verifyBuffer; /* for verify only */ static unsigned char *blockBuffer; uint32_t trackStart; uint32_t trackSize; int sectortype; /* from track info for readCD() */ /* declarations */ struct packetbuf* findBuf(uint32_t blkno); int readPacket(struct packetbuf* pb); int writePacket(struct packetbuf* pb); /* markBlock() * FREE or ALLOC block in spacemap */ void markBlock(enum markAction action, uint32_t blkno) { uint8_t *bm; uint8_t mask; spaceMapDirty = 1; bm = spaceMap->bitmap + (blkno >> 3); mask = 1 << (blkno & 7); if( action == FREE ) { *bm |= mask; lvid->freeSpaceTable[pd->partitionNumber]++; } else { *bm &= ~mask; lvid->freeSpaceTable[pd->partitionNumber]--; } } /* GetExtents() * Try to find unallocated blocks for 'requestedLength' bytes in the rewritable partition * Return short_ad's of lbns in the physical partition together satisfying that request * Last extent has length < n * 2048; if exact multiple of 2048 the a final length 0 short_ad * * Return value: lenAllocDescs if extents found, 0 if not. */ int getExtents(uint32_t requestedLength, short_ad *extents) { uint32_t blkno, lengthFound = 0; short_ad *ext; uint32_t mask, *bm; if( medium == CDR ) { /* check space availability */ extents->extLength = requestedLength; extents->extPosition = getNWA() - pd->partitionStartingLocation; if( (requestedLength & 2047) == 0 ) { extents[1].extPosition = 0; extents[1].extLength = 0; return 16; } else return 8; } // clear extents ext = extents; ext->extLength = 0; bm = ((uint32_t*)spaceMap->bitmap) - 1; mask = 0; blkno = 0xFFFFFFFF; while( lengthFound < requestedLength ) { blkno++; mask <<= 1; if( mask == 0 ) { bm++; mask = 1; // check bm within limits } if( (*bm & mask) == 0 ) { // if allocated if( ext->extLength != 0 ) { ext++; if( ext - extents > 31 ) { printf("GetExtents: Too many extents\n"); return 0; } ext->extLength = 0; } continue; } if( ext->extLength == 0 ) ext->extPosition = blkno; lengthFound += 2048; ext->extLength += 2048; } if( requestedLength != lengthFound ) { ext->extLength = ((ext->extLength & ~2047) | (requestedLength & 2047)) - 2048; } else { ext++; ext->extLength = 0; ext->extPosition = 0; } return (uint8_t*)ext - (uint8_t*)extents + sizeof(short_ad); } int freeShortExtents(short_ad* extents) { uint32_t blkno, lengthFreed; short_ad* ext; for( ext = extents; extents->extLength != 0; ext++ ) { blkno = ext->extPosition; for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) { markBlock(FREE, blkno); blkno++; } if( ext->extLength & 2047 || (ext+1)->extLength == 0 ) break; } return CMND_OK; } int freeLongExtents(long_ad* extents) { uint32_t blkno, lengthFreed; long_ad* ext; for( ext = extents; extents->extLength != 0; ext++ ) { if( ext->extLocation.partitionReferenceNum != pd->partitionNumber ) fail("freeLongExtents: Not RW partition\n"); blkno = ext->extLocation.logicalBlockNum; for( lengthFreed = 0 ; lengthFreed < ext->extLength; lengthFreed += 2048 ) { markBlock(FREE, blkno); blkno++; } if( ext->extLength & 2047 || (ext+1)->extLength == 0 ) break; } return CMND_OK; } /* getUnallocSpaceExtent() * Only used to get new extent for LVID sequence * (Could use to extend sparing blocks as well) */ void getUnallocSpaceExtent(uint32_t requestLength, uint32_t requestAfter, extent_ad *alloc) { uint32_t i, n; alloc->extLength = alloc->extLocation = 0; n = (requestLength + 2047) & ~2047; for( i = 0; i < usd->numAllocDescs; i++ ) { if( usd->allocDescs[i].extLocation > requestAfter ) { if( usd->allocDescs[i].extLength >= requestLength ) { alloc->extLocation = usd->allocDescs[i].extLocation; alloc->extLength = n; usd->allocDescs[i].extLocation += n >> 11; usd->allocDescs[i].extLength -= n; usdDirty = 1; return; } else { alloc->extLocation = usd->allocDescs[i].extLocation; alloc->extLength = usd->allocDescs[i].extLength; usd->numAllocDescs--; for ( ; i < usd->numAllocDescs; i++ ) usd->allocDescs[i] = usd->allocDescs[i+1]; usdDirty = 1; return; } } } if( requestAfter > 0 ) getUnallocSpaceExtent( requestLength, 0, alloc); } void setChecksum(void *descriptor) { uint32_t sum; int i; tag *descTag = (tag*) descriptor; descTag->descCRC = udf_crc((uint8_t*)descTag + sizeof(tag), descTag->descCRCLength, 0); descTag->tagChecksum = sum = 0; for( i = 0; i < 16; i++ ) sum += *((uint8_t*)descTag + i); descTag->tagChecksum = (uint8_t) sum; } void updateTimestamp(time_t t, uint32_t ut) { struct timeval timev; struct tm time; int offset; if( t == 0 ) { gettimeofday(&timev, NULL); } else { timev.tv_sec = t; timev.tv_usec = ut; } localtime_r( &timev.tv_sec, &time); offset = time.tm_gmtoff / 60; timeStamp.typeAndTimezone = 0x1000 + (offset & 0x0FFF); /* 1/3.7.1 */ timeStamp.year = time.tm_year + 1900; timeStamp.month = time.tm_mon + 1;; timeStamp.day = time.tm_mday; timeStamp.hour = time.tm_hour; timeStamp.minute = time.tm_min; timeStamp.second = time.tm_sec; timeStamp.centiseconds = timev.tv_usec / 10000; timeStamp.hundredsOfMicroseconds = (timev.tv_usec / 100) % 100; timeStamp.microseconds = timev.tv_usec % 100 ; } void setStrictRead(int yes) { if( device == DISK_IMAGE ) return; synchronize_cache(device); if( yes ) { rerp->error_recovery_param = 0x04; rerp->retry_count = 2; cp->rcd = 1; } else { rerp->error_recovery_param = 0x00; // back to default rerp->retry_count = 5; cp->rcd = 0; } mode_select(device, rerp_buffer); mode_select(device, cp_buffer); } uint32_t getPhysical(uint32_t lbn, uint16_t part) { if( part == 0xFFFF ) return lbn; if( part == virtualPartitionNum ) lbn = vat[lbn]; return lbn + pd->partitionStartingLocation; } int cmpBlk(const void* a, const void* b) { /* compare routine for sparing table lookup */ if( *(uint32_t*)a < ((struct sparingEntry*)b)->origLocation ) return -1; if( *(uint32_t*)a > ((struct sparingEntry*)b)->origLocation ) return 1; return 0; } /* If the original packet occurs in the Sparing Table return the mappedLocation * else return the original packet address unchanged. */ uint32_t lookupSparingTable(uint32_t original) { struct sparingEntry* se; if( !st ) // no sparing table found return original; se = bsearch(&original, st->mapEntry, usedSparingEntries, sizeof(struct sparingEntry), cmpBlk); if( se ) return se->mappedLocation; else return original; } /* Make an entry in the Sparing Table for packet 'original' and * return the mappedLocation */ uint32_t newSparingTableEntry(uint32_t original) { struct sparingEntry *se, newEntry, swapEntry; uint32_t mapped; unsigned int i; if( !st ) { printf("No sparing table provided\n"); return INVALID; } if( usedSparingEntries == st->reallocationTableLen ) { fail("SparingTable full\n"); } se = bsearch(&original, &st->mapEntry[0], usedSparingEntries, sizeof(struct sparingEntry), cmpBlk); if( se ) { /* sparing a sparing packet */ se->origLocation = 0xFFFFFFF0; } newEntry.origLocation = original; newEntry.mappedLocation = mapped = st->mapEntry[usedSparingEntries].mappedLocation; for( i = 0; i < usedSparingEntries; i++ ) { if( st->mapEntry[i].origLocation < original ) continue; } for( ; i <= usedSparingEntries; i++ ) { swapEntry = st->mapEntry[i]; st->mapEntry[i] = newEntry; newEntry = swapEntry; } usedSparingEntries++; st->sequenceNum++; sparingTableDirty = 1; #ifdef DEBUG printf("Sparing %d to %d\n", original, mapped); #endif return mapped; } /* updateSparingTable() * Only done when quitting. * Do not verify writing as that would change the table again. */ void updateSparingTable() { size_t i; int pbn, ret; off_t off; ssize_t len; struct generic_desc *p; struct packetbuf *pb; struct sparablePartitionMap *spm = (struct sparablePartitionMap*)lvd->partitionMaps; for( i = 0; i < sizeof(spm->locSparingTable)/sizeof(spm->locSparingTable[0]); i++ ) { pbn = spm->locSparingTable[i]; if( pbn == 0 ) return; p = readBlock(pbn, ABSOLUTE); pb = findBuf(pbn); memcpy(p, st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry)); p->descTag.tagLocation = pbn; p->descTag.descCRCLength = sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry) - sizeof(tag); setChecksum(p); if( devicetype != DISK_IMAGE ) { ret = writeCD(device, pbn, 32, pb->pkt); if( ret ) printf("Write SparingTable at %d: %s\n", pbn, get_sense_string()); } else { // DISK_IMAGE off = lseek(device, 2048 * pbn, SEEK_SET); if( off == (off_t)-1 ) fail("writeSparingTable at %d: %m\n", pbn); len = write(device, pb->pkt, 32 * 2048); if( len < 0 ) fail("writeSparingTable at %d: %m\n", pbn); if( len != 32 * 2048 ) fail("writeSparingTable at %d: %s\n", pbn, strerror(EIO)); } } } int readPacket(struct packetbuf* pb) { int ret; off_t off; ssize_t len; uint32_t physical; physical = lookupSparingTable(pb->start); if( devicetype != DISK_IMAGE ) { ret = readCD(device, sectortype, physical, 32, pb->pkt); if( ret ) printf("readPacket: readCD %s\n", get_sense_string()); } else { off = lseek(device, 2048 * physical, SEEK_SET); if( off == (off_t)-1 ) fail("readPacket: lseek failed %m\n"); len = read(device, pb->pkt, 32 * 2048); if( len < 0 ) fail("readPacket: read failed %m\n"); if( len != 32 * 2048 ) fail("readPacket: read failed %s\n", strerror(EIO)); ret = 0; } return ret; } int writePacket(struct packetbuf* pb) { int ret, retry; off_t off; ssize_t len; uint32_t physical; pb->dirty = 0; physical = lookupSparingTable(pb->start); if( devicetype != DISK_IMAGE ) { for(retry = 0; retry < 2; retry++ ) { if( retry != 0 ) physical = newSparingTableEntry(pb->start); ret = writeCD(device, physical, 32, pb->pkt); if( ret ) fail("writePacket: writeCD %s\n", get_sense_string()); // must now verify write operation and spare if necessary // My HP8100 does not support Verify or WriteAndVerify // Use ReadCD with strict Read Error Recovery Parameters setStrictRead(1); ret = readCD(device, sectortype, physical, 32, verifyBuffer); if( ret == 0 ) { setStrictRead(0); return 0; } printf("writePacket: verify %s\n", get_sense_string()); } setStrictRead(0); } else { // DISK_IMAGE #ifdef DEBUG_SPARING // force sparing on packets of disk image if( st ) { if( physical == 0x820 || physical == 0x880 ) // arbitrary 'bad' blocks physical = newSparingTableEntry(pb->start); } #endif off = lseek(device, 2048 * physical, SEEK_SET); if( off == (off_t)-1 ) fail("writePacket: writeHD failed %m\n"); len = write(device, pb->pkt, 32 * 2048); if( len < 0 ) fail("writePacket: writeHD failed %m\n"); if( len != 32 * 2048 ) fail("writePacket: writeHD failed %s\n", strerror(EIO)); ret = 0; } return ret; } struct packetbuf* findBuf(uint32_t blkno) { struct packetbuf *b; blkno &= ~31; for(b = &pktbuf[0]; b < &pktbuf[MAXPKTBUFS]; b++ ) { if( blkno == b->start ) return b; } return NULL; } struct packetbuf* getFreePacketBuffer(uint32_t lbn, uint16_t part) { struct packetbuf *b, *bFree, *bMustWrite; uint32_t blkno; blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation ); bFree = bMustWrite = NULL; for( b = &pktbuf[0]; b < &pktbuf[MAXPKTBUFS]; b++ ) { if( (b->inuse | b->dirty) == 0 ) { bFree = b; break; } else if( b->inuse == 0 ) bMustWrite = b; } if( !bFree && !bMustWrite ) { printf("readBlock: Permission to panic, Sir!!!\n"); return NULL; } if( !bFree ) { writePacket(bMustWrite); bMustWrite->inuse = 0; bMustWrite->dirty = 0; bFree = bMustWrite; } bFree->start = blkno & ~31; return bFree; } void* readBlock(uint32_t lbn, uint16_t part) { struct packetbuf *b; uint32_t physical = getPhysical(lbn, part); if( medium == CDR ) return readCDR(physical, ABSOLUTE); b = findBuf(physical); if( !b ) { b = getFreePacketBuffer(lbn, part); readPacket(b); } b->inuse |= 0x80000000 >> (lbn & 31); return b->pkt + ((lbn & 31) << 11); } void* readSingleBlock(uint32_t pbn) { int ret; off_t off; ssize_t len; if( devicetype != DISK_IMAGE ) { ret = readCD(device, sectortype, pbn, 1, blockBuffer); if( ret ) { if( ! ignoreReadError ) printf("readSingleBlock: %s\n", get_sense_string()); return NULL; } else return blockBuffer; } else { off = lseek(device, 2048 * pbn, SEEK_SET); if( off != (off_t)-1 ) return NULL; len = read(device, blockBuffer, 2048); if( len != 2048 ) return NULL; else return blockBuffer; } } void freeBlock(uint32_t lbn, uint16_t part) { struct packetbuf *b; uint32_t blkno; if( medium == CDR ) return; blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation ); b = findBuf(blkno); if( !b ) fail("freeBlock failed on block %d\n", blkno); b->inuse &= ~(0x80000000 >> (blkno & 31)); /* turn off INUSE bit */ } void dirtyBlock(uint32_t lbn, uint16_t part) { struct packetbuf *pb; uint32_t blkno; blkno = lbn + ( part == 0xFFFF ? 0 : pd->partitionStartingLocation ); pb = findBuf(blkno); if( !pb ) fail("dirtyBlock failed on block %d\n", blkno); pb->dirty |= 0x80000000 >> (blkno & 31); /* turn on DIRTY bit */ } void writeBlock(uint32_t lbn, uint16_t part, void* src) { char *p; p = readBlock(lbn, part); memcpy(p, src, 2048); if( part != ABSOLUTE ) markBlock(ALLOC, lbn); dirtyBlock(lbn, part); freeBlock(lbn, part); } void* readTaggedBlock(uint32_t lbn, uint16_t partition) { int i; uint8_t sum, *p; struct generic_desc *block; if( medium == CDR ) block = (struct generic_desc*) readCDR(lbn, partition); else { block = (struct generic_desc*) readBlock(lbn, partition); freeBlock(lbn,partition); if( !block ) return block; } if( block->descTag.tagIdent == 0x0000 ) { /* ignore not ISO 13346 defined descriptors with 0 tags */ if( strncmp((char *)((struct sparingTable*)block)->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)) != 0 ) { for( i = 0; i < 2048; i++ ) { if( ((uint8_t*)block)[i] != 0 ) { printf("readTaggedBlock: Empty block %d not all zeroes\n", lbn); break; } } return block; } } for( i = 0, sum = 0, p = (uint8_t*)block; i< 16; i++ ) if( i != 4 ) sum += *(p + i); if( block->descTag.tagChecksum != sum ) fail("readTagged: Checksum error in block %d\n", lbn); if( block->descTag.descCRC != udf_crc((uint8_t*)block + sizeof(tag), ((tag*)block)->descCRCLength, 0) ) fail("readTagged: CRC error in block %d\n", lbn); return block; } int readExtents(char* dest, int usesShort, void* extents) { uint len, blkno, partitionNumber; char *p; long_ad *lo; short_ad *sh; if( usesShort ) { sh = (short_ad*) extents; len = sh->extLength; blkno = sh->extPosition; partitionNumber = pd->partitionNumber; } else { lo = (long_ad*) extents; len = lo->extLength; blkno = lo->extLocation.logicalBlockNum; partitionNumber = lo->extLocation.partitionReferenceNum; } for(;;) { p = readBlock(blkno, partitionNumber); memcpy(dest, p, 2048); freeBlock(blkno, partitionNumber); dest += 2048; if( len < 2048 ) break; if( len == 0 ) { if( usesShort ) { sh++; len = sh->extLength; blkno = sh->extPosition; } else { lo++; len = lo->extLength; blkno = lo->extLocation.logicalBlockNum; partitionNumber = lo->extLocation.partitionReferenceNum; } if( len == 0 ) break; continue; } len -= 2048; blkno++; } return CMND_OK; } int writeExtents(char* src, int usesShort, void* extents) { uint len, blkno, partitionNumber; long_ad *lo=NULL; short_ad *sh=NULL; if( usesShort ) { sh = (short_ad*) extents; len = sh->extLength; blkno = sh->extPosition; partitionNumber = pd->partitionNumber; } else { lo = (long_ad*) extents; len = lo->extLength; blkno = lo->extLocation.logicalBlockNum; partitionNumber = lo->extLocation.partitionReferenceNum; } for(;;) { writeBlock(blkno, partitionNumber, src); src += 2048; if( len < 2048) break; if( len == 2048 ) { if( usesShort ) { sh++; len = sh->extLength; blkno = sh->extPosition; } else { lo++; len = lo->extLength; blkno = lo->extLocation.logicalBlockNum; partitionNumber = lo->extLocation.partitionReferenceNum; } if( len == 0 ) break; continue; } len -= 2048; blkno++; } return CMND_OK; } int initIO(char *filename) { struct packetbuf *pb; int rv; off_t off; ssize_t len; struct stat filestat; struct cdrom_discinfo di; u_char *buffer; struct cdrom_writeparams *wp; uint16_t ident; if( (rv = stat(filename, &filestat)) < 0 ) fail("initIO: stat on %s failed\n", filename); if( S_ISREG(filestat.st_mode) ) { /* disk image of a UDF volume */ devicetype = DISK_IMAGE; if( (device = open(filename, O_RDWR)) < 0 ) { fail("initIO: open %s failed\n", filename); return 0; } /* heuristically determine medium imitated on disk image based on VAT FileEntry in block 512 */ off = lseek(device, 2048 * 512, SEEK_SET); if( off == (off_t)-1 ) fail("initIO: lseek %s failed: %m\n", filename); len = read(device, &ident, 2); if( len < 0 ) fail("initIO: read %s failed: %m\n", filename); if( len != 2 ) fail("initIO: read %s failed: %s\n", filename, strerror(EIO)); medium = ident == TAG_IDENT_VDP ? CDR : CDRW; if( medium == CDRW ) { for( pb = pktbuf, rv = 1; pb <= pktbuf + MAXPKTBUFS; pb++ ) { pb->start = 0xFFFFFFFF; pb->pkt = malloc(32*2048); pb->bufNum = rv++; if( pb->pkt == NULL ) fail("malloc packetBuffer failed\n"); } } } if( (blockBuffer = malloc(2048)) == NULL ) fail("malloc blockBuffer failed\n"); if( devicetype == DISK_IMAGE ) return 0; if( (device = open(filename, O_RDONLY | O_NONBLOCK )) < 0 ) fail("initIO: open %s failed\n", filename); rv = ioctl(device, CDROM_DRIVE_STATUS); if( (rv != CDS_DISC_OK) && (rv != CDS_NO_INFO) ) fail("No disc or not ready\n"); if( read_discinfo(device, &di) ) fail("Read discinfo failed\n"); if( di.erasable == 0 ) { medium = CDR; printf("CDR disc\n"); } else { medium = CDRW; printf("CDRW disc\n"); } lastTrack = di.trk1_lastsession; if( read_trackinfo(device, &ti, lastTrack) ) /* last track 1 in last session writable for UDF */ fail("Read discinfo failed\n"); if( medium == CDRW ) { if( !ti.fixpkt ) { printf("Assume CDRW disc used as CDR\n"); medium = CDR; } else if ( ti.fixpkt_size != 32 ) fail("CDRW not fixed 32 sector packets\n"); } if( medium == CDRW ) { for( pb = pktbuf, rv = 1; pb <= pktbuf + MAXPKTBUFS; pb++ ) { pb->start = 0xFFFFFFFF; pb->pkt = malloc(32*2048); pb->bufNum = rv++; if( pb->pkt == NULL ) fail("malloc packetBuffer failed\n"); } if( (verifyBuffer = malloc(32 * 2048)) == NULL ) fail("malloc verifyBuffer failed\n"); } if( medium == CDR ) { if( ti.rsrvd_trk || ! ti.packet || ti.fixpkt ) fail("CDR disc last track reserved or not variable packet\n"); if( !ti.nwa_v ) fail("Next writable address invalid in track %d\n", ti.trk); } trackStart = ti.trk_start; trackSize = ti.trk_size; if( ti.data_mode == 1 ) sectortype = 2; /* for readCD() */ else if( ti.data_mode == 2 ) sectortype = 4; else fail("Neither Data Mode1 nor Mode2 on disc\n"); /* get read error recovery parameters page */ rv = mode_sense(device, &rerp_buffer, (void *)&rerp, GPMODE_R_W_ERROR_PAGE, PGCTL_CURRENT_VALUES); /* get cache parameters page */ rv = mode_sense(device, &cp_buffer, (void *)&cp, GPMODE_CACHE_PAGE, PGCTL_CURRENT_VALUES); /* setup write params */ get_writeparams(device, &buffer, &wp, PGCTL_CURRENT_VALUES); wp->write_type = 0; // wp->trk_mode = 7; wp->copy = 0; wp->fp = medium == CDRW ? 1 : 0; wp->test_write = 0; wp->data_blk_type = ( ti.data_mode == 2 ? DB_XA_F1 : DB_ROM_MODE1); wp->host_appl_code = 0; wp->session_format = (ti.data_mode == 2 ? 0x20 : 0x00); wp->pkt_size = medium == CDRW ? 32 : 0; wp->subhdr0 = 0x00; wp->subhdr1 = 0x00; wp->subhdr2 = 0x08; wp->subhdr3 = 0x00; if( (rv = set_writeparams(device, buffer, wp)) ) { free(buffer); fail("Set write parameters failed\n"); } else free(buffer); return 0; } int closeIO(void) { struct packetbuf *pb; if( medium == CDRW ) { for( pb = pktbuf; pb < pktbuf + MAXPKTBUFS; pb++ ) { if( pb->dirty && !pb->inuse ) writePacket(pb); if( pb->inuse || pb->dirty) printf("PacketBuffet[%d] at %d inuse %08X dirty %08X\n", pb->bufNum, pb->start, pb->inuse, pb->dirty); free(pb->pkt); } } if( blockBuffer ) free(blockBuffer); if( verifyBuffer ) free(verifyBuffer); if( devicetype != DISK_IMAGE ) synchronize_cache(device); close(device); return 1; } udftools-2.0/wrudf/wrudf-desc.c0000644000175000017500000001505713221466537013512 00000000000000/* wrudf-desc.c * * PURPOSE * Routines to create/find/insert/delete FileIdentDesc's and FileEntries. * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * * (C) 2001 Enno Fennema * * HISTORY * 16 Aug 01 ef Created. */ #include "config.h" #include #include #include #include #include "wrudf.h" /* removeFID() * * Physically remove a FileIdentDesc from the directory */ int removeFID(Directory *dir, struct fileIdentDesc *fid) { uint32_t lenFID = (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3; uint32_t lenMove; dir->fe.informationLength -= lenFID; lenMove = dir->fe.informationLength - ((char *)fid - dir->data); memcpy(fid, (char *)fid + lenFID, lenMove); dir->dirDirty = 1; return 0; } /* deleteFID() * * Remove an FID from the directory * If fileLinkCount now zero, deallocate FileEntry and any data extents */ int deleteFID(Directory * dir, struct fileIdentDesc * fid) { int rv; struct fileEntry *fe; struct logicalVolIntegrityDescImpUse *lvidiu; rv = CMND_OK; // if( fid->icb.extLocation.partitionReferenceNum != pd->partitionNumber ) // return NOT_IN_RW_PARTITION; fe = readTaggedBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum); /* check permission */ freeBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum); if( fe->fileLinkCount > 1 ) { fe->fileLinkCount--; setChecksum(fe); if( medium == CDRW ) dirtyBlock(fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum); else vat[fid->icb.extLocation.logicalBlockNum] = writeCDR(fe); } else { if( medium == CDR ) { if( fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY ) dir->fe.fileLinkCount--; vat[fid->icb.extLocation.logicalBlockNum] = 0xFFFFFFFF; } else { if( fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY ) { dir->fe.fileLinkCount--; lvidiu = (struct logicalVolIntegrityDescImpUse*) (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions); lvidiu->numDirs--; } else { lvidiu = (struct logicalVolIntegrityDescImpUse*) (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions); lvidiu->numFiles--; } /* free file data */ switch( fe->icbTag.flags & ICBTAG_FLAG_AD_MASK ) { case ICBTAG_FLAG_AD_IN_ICB: break; case ICBTAG_FLAG_AD_SHORT: freeShortExtents((short_ad*)(fe->allocDescs + fe->lengthExtendedAttr)); break; case ICBTAG_FLAG_AD_LONG: freeLongExtents((long_ad*)(fe->allocDescs + fe->lengthExtendedAttr)); break; default: printf("UDF does not use Extended Alloc Descs\n"); rv = CMND_FAILED; } /* free the File Entry itself */ markBlock(FREE, fid->icb.extLocation.logicalBlockNum); } } removeFID(dir, fid); dir->dirDirty = 1; return rv; } struct fileIdentDesc* findFileIdentDesc(Directory *dir, char* name) { uint64_t i; char *data; struct fileIdentDesc *fid; dchars uName[256]; size_t uLen; uLen = encode_locale(uName, name, 256); if (uLen == (size_t)-1) return NULL; data = dir->data; for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*)(data + i); if( fid->descTag.tagIdent == TAG_IDENT_TE ) return NULL; if( fid->descTag.tagIdent == TAG_IDENT_IE ) { printf("Indirect Entry not yet implemented\n"); continue; } if( fid->descTag.tagIdent != TAG_IDENT_FID ) fail("Unknown tag id %08X in directory\n", fid->descTag.tagIdent); // check CRC if( fid->fileCharacteristics == FID_FILE_CHAR_PARENT) continue; if( fid->lengthFileIdent == uLen && memcmp( fid->fileIdent, uName, fid->lengthFileIdent) == 0 ) return fid; } return NULL; } /* * Return pointer to new FileEntry in a 2k allocated block to be free'd when no longer required. * Only basic data is filled in. */ struct fileEntry* makeFileEntry() { struct fileEntry *fe = (struct fileEntry*) calloc(2048, 1); struct logicalVolHeaderDesc* lvhd = (struct logicalVolHeaderDesc*)lvid->logicalVolContentsUse; updateTimestamp(0,0); fe->descTag.tagIdent = TAG_IDENT_FE; fe->descTag.descVersion = 2; fe->descTag.tagSerialNum = lvd->descTag.tagSerialNum; fe->icbTag.strategyType = 4; fe->icbTag.numEntries = 1; fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR; /* User has all permission; Group/Others Read/Exec */ fe->permissions = FE_PERM_U_READ | FE_PERM_U_WRITE | FE_PERM_U_DELETE | FE_PERM_U_CHATTR | FE_PERM_U_EXEC | FE_PERM_G_READ | FE_PERM_G_EXEC | FE_PERM_O_READ | FE_PERM_O_EXEC; fe->fileLinkCount = 1; fe->accessTime = timeStamp; fe->modificationTime = timeStamp; fe->attrTime = timeStamp; fe->impIdent = entityWRUDF; fe->uniqueID = lvhd->uniqueID++; return fe; } /* * Return pointer to new FileIdentDesc in an allocated block to be free'd when no longer required. * Does NOT fill: descTag.checksum, descTag.tagLocation, icbTag.characteristics, icb */ struct fileIdentDesc* makeFileIdentDesc(char* name) { dchars uName[256]; size_t uLen; struct fileIdentDesc *fid; fid = (struct fileIdentDesc*) calloc(512,1); fid->descTag.tagIdent = TAG_IDENT_FID; fid->descTag.descVersion = 2; fid->descTag.tagSerialNum = lvd->descTag.tagSerialNum; fid->fileVersionNum = 1; fid->icb.extLength = 2048; if( name[0] != 0 ) { /* FID to parent directory has no name */ uLen = encode_locale(uName, name, 256); if (uLen == (size_t)-1) { uLen = 1; uName[0] = 0x8; } fid->lengthFileIdent = uLen; memcpy(fid->fileIdent + fid->lengthOfImpUse, uName, fid->lengthFileIdent); } return fid; } int insertFileIdentDesc(Directory *dir, struct fileIdentDesc* fid) { uint32_t lenFid; lenFid = (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3; fid->descTag.descCRCLength = lenFid - sizeof(tag); setChecksum(fid); if( dir->fe.informationLength + lenFid > dir->dataSize ) { if( !(dir->data = realloc(dir->data, dir->dataSize + 2048)) ) { fail("Realloc directory data failed\n"); } dir->dataSize += 2048; } memcpy(dir->data + dir->fe.informationLength, fid, lenFid); dir->fe.informationLength += lenFid; dir->dirDirty = 1; return CMND_OK; } udftools-2.0/wrudf/wrudf-cmnd.c0000644000175000017500000007615613221466537013524 00000000000000/* wrudf-cmnd.c * * PURPOSE * High level wrudf command functions * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * * (C) 2001 Enno Fennema * * HISTORY * 16 Aug 01 ef Created. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "wrudf.h" int deleteDirectory(Directory *dir, struct fileIdentDesc *fid); Directory *makeDir(Directory *dir, char* name); int questionOverwrite(Directory *dir, struct fileIdentDesc *fid, char* name); int directoryIsEmpty(Directory *dir); char *hdWorkingDir; /* copyFile() * Write File Entry immediately followed by data * A verify error on CDR causes a further packet with * the new FE followed by copies of the defective blocks only */ int copyFile(Directory *dir, char* inName, char*newName, struct stat *fileStat) { uint32_t i=0; int fd, blkno; uint32_t nBytes, blkInPkt; uint32_t maxVarPktSize; // in bytes struct fileIdentDesc *fid; struct fileEntry *fe; struct allocDescImpUse *adiu; struct logicalVolIntegrityDescImpUse *lvidiu; uint8_t p[2048]; fd = open(inName, O_RDONLY); if( fd == 0 ) { printf("'%s' does not exist\n", inName); return CMND_FAILED; } printf("Copy file %s\n", inName); fid = findFileIdentDesc(dir, newName); if( fid && questionOverwrite(dir, fid, newName) ) { close(fd); return CMND_OK; } fid = makeFileIdentDesc(newName); // could reuse FID if overwrite allowed fe = makeFileEntry(); fe->uid = fileStat->st_uid; fe->gid = fileStat->st_gid; if( fileStat->st_mode & S_IRUSR ) fe->permissions |= FE_PERM_U_READ; if( fileStat->st_mode & S_IWUSR ) fe->permissions |= FE_PERM_U_WRITE | FE_PERM_U_DELETE | FE_PERM_U_CHATTR;; if( fileStat->st_mode & S_IXUSR ) fe->permissions |= FE_PERM_U_EXEC; if( fileStat->st_mode & S_IRGRP ) fe->permissions |= FE_PERM_G_READ; if( fileStat->st_mode & S_IWGRP ) fe->permissions |= FE_PERM_G_WRITE | FE_PERM_G_DELETE | FE_PERM_G_CHATTR; if( fileStat->st_mode & S_IXGRP ) fe->permissions |= FE_PERM_G_EXEC; if( fileStat->st_mode & S_IROTH ) fe->permissions |= FE_PERM_O_READ; if( fileStat->st_mode & S_IWOTH ) fe->permissions |= FE_PERM_O_WRITE | FE_PERM_O_DELETE | FE_PERM_O_CHATTR;; if( fileStat->st_mode & S_IXOTH ) fe->permissions |= FE_PERM_O_EXEC; if( fileStat->st_mode & S_ISUID ) fe->icbTag.flags |= ICBTAG_FLAG_SETUID; if( fileStat->st_mode & S_ISGID ) fe->icbTag.flags |= ICBTAG_FLAG_SETGID; fe->informationLength = fileStat->st_size; updateTimestamp(fileStat->st_atime, 0); fe->accessTime = timeStamp; updateTimestamp(fileStat->st_mtime, 0); fe->modificationTime = timeStamp; updateTimestamp(fileStat->st_ctime, 0); fe->attrTime = timeStamp; /* check whether embedding of data is possible */ fe->logicalBlocksRecorded = ((fileStat->st_size + 2047) & ~2047) >> 11; if( medium == CDR ) { /* File data written in physical space but fileEntry in virtual space * so must use long allocation descriptors * * Variable packet length restricted by drive buffer size. * Must break up long file over several var packets. * Only 116 long_ad's fit in fileEntry without going to extended alloc descs */ long_ad *ad; uint32_t loc; maxVarPktSize = getMaxVarPktSize(); if( fe->informationLength / maxVarPktSize > 116 ) { printf("Cannot handle files longer than %d\n", 116 * maxVarPktSize); close(fd); free(fe); free(fid); return CMND_FAILED; } fe->icbTag.flags |= ICBTAG_FLAG_AD_LONG; /* +1 as the fileEntry itself occupies block NWA */ loc = getNWA() + 1 - pd->partitionStartingLocation; nBytes = (uint32_t) fe->informationLength ; for( ad = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr); nBytes > 0; ad++ ) { if( nBytes > maxVarPktSize ) { ad->extLength = maxVarPktSize; nBytes -= maxVarPktSize; } else { ad->extLength = nBytes; nBytes = 0; } ad->extLocation.logicalBlockNum = loc; ad->extLocation.partitionReferenceNum = pd->partitionNumber; adiu = (struct allocDescImpUse*)(ad->impUse); memcpy(&adiu->impUse, &fe->uniqueID, sizeof(uint32_t)); loc += ((ad->extLength + 2047) >> 11) + 7; } if( ((ad-1)->extLength & 2047) == 0 ) { memset(ad, 0, sizeof(long_ad)); adiu = (struct allocDescImpUse*)(ad->impUse); memcpy(&adiu->impUse, &fe->uniqueID, sizeof(uint32_t)); ad++; } fe->lengthAllocDescs = (uint8_t*)ad - (fe->allocDescs + fe->lengthExtendedAttr); fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag); fe->descTag.tagLocation = newVATentry(); for( ;; ) { /* retry loop for verify failure */ int blknoFE, skipped, retries; long_ad *extent; setChecksum(fe); skipped = 0; retries = 0; lseek(fd, 0, SEEK_SET); /* write FE */ blknoFE = vat[fe->descTag.tagLocation] = writeCDR(fe) - pd->partitionStartingLocation; fid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation; fid->icb.extLocation.partitionReferenceNum = virtualPartitionNum; /* write file data */ extent = (long_ad*)(fe->allocDescs + fe->lengthExtendedAttr); for( blkInPkt = nBytes = 0; nBytes < fe->informationLength; extent++ ) { blkno = extent->extLocation.logicalBlockNum; if( blkno < blknoFE ) { nBytes += extent->extLength; skipped = 1; continue; } for( i = 0; i < extent->extLength; blkno++, i += 2048 ) { memset(p, 0, 2048); if( skipped ) { lseek(fd, nBytes, SEEK_SET); skipped = 0; } nBytes += read(fd, p, 2048); writeCDR(p); if( ++blkInPkt == (maxVarPktSize >> 11) ) { syncCDR(); blkInPkt = 0; } } } syncCDR(); if( verifyCDR(fe) == 0 ) // verify the file data break; if( retries++ > 3 ) { printf("Retry count 3 exceeded\n"); break; } } } else { short_ad *extent, extentFE[2]; if( getExtents(2048, extentFE ) != 16 ) { /* extent for File Entry */ printf("No space for File Entry\n"); close(fd); free(fe); free(fid); return CMND_FAILED; } fe->descTag.tagLocation = extentFE[0].extPosition; // must mark allocated; otherwise allocated for a second time before being written markBlock(ALLOC, fe->descTag.tagLocation); fe->lengthAllocDescs = /* extents for the file data */ getExtents(fe->informationLength, (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr)); if( !fe->lengthAllocDescs ) { printf("No space for file\n"); close(fd); free(fe); free(fid); return CMND_FAILED; } /* write FE */ fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthExtendedAttr + fe->lengthAllocDescs - sizeof(tag); setChecksum(fe); writeBlock(fe->descTag.tagLocation, pd->partitionNumber, fe); fid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation; fid->icb.extLocation.partitionReferenceNum = pd->partitionNumber; /* write file data */ extent = (short_ad*)(fe->allocDescs + fe->lengthExtendedAttr); for( nBytes = 0; nBytes < fe->informationLength; extent++ ) { blkno = extent->extPosition; for( i = 0; i < extent->extLength; blkno++, i += 2048 ) { memset(p, 0, 2048); nBytes += read(fd, p, 2048); writeBlock(blkno, pd->partitionNumber, p); } } } if( devicetype == DISK_IMAGE && medium == CDR ) writeHDlink(); adiu = (struct allocDescImpUse*)(fid->icb.impUse); memcpy(&adiu->impUse, &fe->uniqueID, sizeof(uint32_t)); insertFileIdentDesc(dir, fid); lvidiu = (struct logicalVolIntegrityDescImpUse*) (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions); lvidiu->numFiles++; close(fd); free(fe); free(fid); return CMND_OK; } int copyDirectory(Directory *dir, char* name) { DIR *srcDir; Directory *workDir; struct dirent *dirEnt; struct stat dirEntStat; struct fileIdentDesc *fid; if( !(srcDir = opendir(name)) ) { printf("Open dir '%s': %m\n", name); return CMND_FAILED; } if( chdir(name) != 0 ) { printf("Change dir '%s': %m\n", name); closedir(srcDir); return CMND_FAILED; } printf("Now in %s\n", getcwd(NULL, 0)); workDir = dir; while( (dirEnt = readdir(srcDir)) ) { if( !strcmp(dirEnt->d_name, ".") || !strcmp(dirEnt->d_name, "..") ) continue; if( lstat(dirEnt->d_name, &dirEntStat) != 0 ) { // do not follow links printf("Stat dirEnt '%s' failed: %s\n", dirEnt->d_name, strerror(errno)); continue; } if( S_ISDIR(dirEntStat.st_mode) ) { if( !(options & OPT_RECURSIVE) ) { printf("Not recursive. Ignoring '%s' directory\n", dirEnt->d_name); continue; } fid = findFileIdentDesc(dir, dirEnt->d_name); if( fid && !(fid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY ) ) { printf("'%s' exists but is not a directory\n", dirEnt->d_name); continue; } if( fid && (fid->fileCharacteristics & FID_FILE_CHAR_DELETED) ) { removeFID(dir, fid); fid = NULL; } if( !fid ) workDir = makeDir(dir, dirEnt->d_name); else workDir = readDirectory(dir, &fid->icb, dirEnt->d_name); copyDirectory(workDir, dirEnt->d_name); } else { if( S_ISREG(dirEntStat.st_mode) ) copyFile(workDir, dirEnt->d_name, dirEnt->d_name, &dirEntStat); } } if( chdir("..") != 0 ) printf("Change dir '..': %m\n"); closedir(srcDir); return CMND_OK; } /* deleteDirectory() * * Recursing into subdirectories. * If anywhere no permission, query deletion but proceed if 'yes' * Returns 0 if fid freed, 1 if fid not empty */ int deleteDirectory(Directory *dir, struct fileIdentDesc* fid) { uint64_t i; int rv, notEmpty; char *name; struct fileIdentDesc *childFid; Directory *childDir; rv = 0; if( fid->fileCharacteristics & FID_FILE_CHAR_DELETED ) return CMND_OK; if( (fid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY) == 0 ) return deleteFID(dir, fid); /* delete regular files */ name = malloc(fid->lengthFileIdent + 1); strncpy(name, (char *)(fid->fileIdent + fid->lengthOfImpUse), fid->lengthFileIdent); name[fid->lengthFileIdent] = 0; readDirectory(dir, &fid->icb, name); childDir = dir->child; /* check permission */ notEmpty = 0; for( i = 0; i < childDir->fe.informationLength; i += ((sizeof(struct fileIdentDesc) + childFid->lengthOfImpUse + childFid->lengthFileIdent + 3) & ~3) ) { childFid = (struct fileIdentDesc*)(childDir->data + i); if( childFid->fileCharacteristics & (FID_FILE_CHAR_DELETED | FID_FILE_CHAR_PARENT) ) continue; if( childFid->fileCharacteristics & FID_FILE_CHAR_DIRECTORY ) deleteDirectory( childDir, childFid); else deleteFID(childDir, childFid); } if( directoryIsEmpty(childDir) ) { rv |= deleteFID(dir, fid); } else { childDir->dirDirty = 1; updateDirectory(childDir); rv = notEmpty; } free(name); return rv; } /* readDirectory() * All fileIdentDesc's are put into the data area of the Directory structure. * irrespective whether they were embedded or separately in allocated extents. * updateDirectory() will embed or write in separate extents as appropriate. */ Directory * readDirectory(Directory *parentDir, long_ad* icb, char *name) { char *p; uint32_t len; Directory *dir; if( parentDir == NULL ) dir = rootDir; else { dir = parentDir->child; if( dir == NULL ) { parentDir->child = dir = (Directory*)malloc(sizeof(Directory)); memset(dir, 0, sizeof(Directory)); dir->parent = parentDir; dir->dataSize = 4096; dir->data = malloc(4096); if( dir->name ) free(dir->name); dir->name = malloc(strlen(name) + 1); strcpy(dir->name, name); } else if( dir->icb.extLocation.logicalBlockNum == icb->extLocation.logicalBlockNum && dir->icb.extLocation.partitionReferenceNum == icb->extLocation.partitionReferenceNum ) return dir; // already the one requested } if( dir->dirDirty ) updateDirectory(dir); dir->icb = *icb; if( name[0] ) { if( dir->name ) free(dir->name); dir->name = malloc(strlen(name) + 1); strcpy(dir->name, name); } p = readTaggedBlock(icb->extLocation.logicalBlockNum, icb->extLocation.partitionReferenceNum); memcpy(&dir->fe, p, 2048); if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB ) { memcpy(dir->data, dir->fe.allocDescs + dir->fe.lengthExtendedAttr, dir->fe.lengthAllocDescs); memset(dir->fe.allocDescs + dir->fe.lengthExtendedAttr, 0, dir->fe.lengthAllocDescs); } else { if( dir->fe.informationLength > dir->dataSize ) { len = (dir->fe.informationLength + 2047) & ~2047; dir->data = realloc(dir->data, len); if( !dir->data ) { printf("Realloc directory data failed\n"); return NULL; } dir->dataSize = len; } readExtents(dir->data, (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT, dir->fe.allocDescs + dir->fe.lengthExtendedAttr); if( medium == CDRW ) { if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT ) freeShortExtents((short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); else if( (dir->fe.icbTag.flags & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG ) freeLongExtents((long_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); } } printf("Read dir %s\n", dir->name); return dir; } /* updateDirectory() * Extents and ICB AllocMask are unchanged since reading the directory from CD. * Based on current informationLength will have to decide embedding or on output extents required * and free any superfluous extents */ int updateDirectory(Directory* dir) { uint64_t i; struct fileIdentDesc *fid; if( dir->child ) updateDirectory(dir->child); if( !dir->dirDirty ) return CMND_OK; if( sizeof(struct fileEntry) + dir->fe.lengthExtendedAttr + dir->fe.informationLength <= 2048 ) { /* fileIdentDescs embedded in directory ICB */ dir->fe.logicalBlocksRecorded = 0; dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_IN_ICB; dir->fe.lengthAllocDescs = dir->fe.informationLength; memcpy(dir->fe.allocDescs + dir->fe.lengthExtendedAttr, dir->data, dir->fe.lengthAllocDescs); /* UDF2.00 2.2.1.3 - For a structure in virtual space, tagLocation is the virtual location */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->fe.allocDescs + i); fid->descTag.tagLocation = dir->icb.extLocation.logicalBlockNum; setChecksum(&fid->descTag); } } else { /* get new extents for the directory data */ dir->fe.logicalBlocksRecorded = ((dir->fe.informationLength + 2047) & ~2047) >> 11; if( medium == CDR ) { long_ad *ad; struct allocDescImpUse *adiu; uint32_t blkno; dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_LONG; ad = (long_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr); ad->extLength = dir->fe.informationLength; ad->extLocation.logicalBlockNum = blkno = getNWA() + 1 - pd->partitionStartingLocation; ad->extLocation.partitionReferenceNum = pd->partitionNumber; adiu = (struct allocDescImpUse*)(ad->impUse); memcpy(&adiu->impUse, &dir->fe.uniqueID, sizeof(uint32_t)); memset(ad + 1, 0, sizeof(long_ad)); /* necessary only if infolength multiple of 2048 */ dir->fe.lengthAllocDescs = 2 * sizeof(long_ad); /* set tagLocation in all FIDs */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->data + i); fid->descTag.tagLocation = blkno + (i >> 11); fid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) - sizeof(tag); setChecksum(fid); } } else { uint32_t *blocks, blkno, len; short_ad *extent; extent =(short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr); dir->fe.lengthAllocDescs = getExtents(dir->fe.informationLength, extent); dir->fe.icbTag.flags = (dir->fe.icbTag.flags & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_SHORT; /* find which blocks are to going be used to set tagLocations */ blocks = (uint32_t*)malloc(dir->fe.logicalBlocksRecorded * sizeof(uint32_t)); blkno = extent->extPosition; len = extent->extLength; for( i = 0; i < dir->fe.logicalBlocksRecorded; i++ ) { blocks[i] = blkno; if( len <= 2048 ) { extent++; blkno = extent->extPosition; len = extent->extLength; } else { len -= 2048; blkno++; } } /* set tagLocation */ for( i = 0; i < dir->fe.informationLength; i += (sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3 ) { fid = (struct fileIdentDesc*) (dir->data + i); fid->descTag.tagLocation = blocks[i >> 11]; fid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) - sizeof(tag); setChecksum(fid); } free(blocks); } } dir->fe.descTag.descCRCLength = sizeof(struct fileEntry) + dir->fe.lengthExtendedAttr + dir->fe.lengthAllocDescs - sizeof(tag); setChecksum(&dir->fe); if( medium == CDRW ) { /* write the directory fileEntry */ writeBlock(dir->icb.extLocation.logicalBlockNum, dir->icb.extLocation.partitionReferenceNum, &dir->fe); if( dir->fe.logicalBlocksRecorded ) { /* write any directory data */ writeExtents(dir->data, 1, (short_ad*)(dir->fe.allocDescs + dir->fe.lengthExtendedAttr)); } } else { /* medium == CDR */ int retries; retries = 0; for( ;; ) { /* loop only when verify failed */ uint32_t pbn; /* write the directory fileEntry */ pbn = writeCDR(&dir->fe); vat[((long_ad*)&dir->icb)->extLocation.logicalBlockNum] = pbn - pd->partitionStartingLocation; if( dir->fe.logicalBlocksRecorded ) for( i = 0; i < dir->fe.informationLength; i += 2048 ) writeCDR(dir->data + i); if( verifyCDR(&dir->fe) == 0 ) break; if( ++retries > 3 ) { printf("updateDirectory: '%s' failed\n", dir->name); return CMND_FAILED; } } } dir->dirDirty = 0; printf("Wrote dir %s\n", dir->name); return CMND_OK; } /* Create subdirectory called 'name' in 'dir' */ Directory * makeDir(Directory *dir, char* name ) { Directory *newDir; struct fileEntry *fe; struct fileIdentDesc *backFid, *forwFid; struct allocDescImpUse *adiu; struct logicalVolIntegrityDescImpUse *lvidiu; short_ad allocDescs[2]; /* back reference to parent in new directory */ backFid = makeFileIdentDesc(""); backFid->icb = dir->icb; backFid->fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; backFid->descTag.descCRCLength = ((sizeof(struct fileIdentDesc) + 3) & ~3) - sizeof(tag); fe = makeFileEntry(); fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY; fe->icbTag.flags = ICBTAG_FLAG_AD_IN_ICB; fe->informationLength = (sizeof(struct fileIdentDesc) + 3) & ~3; /* forward reference to new directory in parent directory */ forwFid = makeFileIdentDesc(name); forwFid->fileCharacteristics = FID_FILE_CHAR_DIRECTORY; adiu = (struct allocDescImpUse*)forwFid->icb.impUse; memcpy(&adiu->impUse, &fe->uniqueID, sizeof(uint32_t)); if( medium == CDR ) { fe->descTag.tagLocation = newVATentry(); forwFid->icb.extLocation.logicalBlockNum = fe->descTag.tagLocation; forwFid->icb.extLocation.partitionReferenceNum = virtualPartitionNum; } else { if( getExtents( 2048, allocDescs) != 16 ) fail("makeDir: Could not get File Entry extent\n"); markBlock(ALLOC, allocDescs[0].extPosition); fe->descTag.tagLocation = allocDescs[0].extPosition; backFid->descTag.tagLocation = allocDescs[0].extPosition; forwFid->icb.extLocation.logicalBlockNum = allocDescs[0].extPosition; forwFid->icb.extLocation.partitionReferenceNum = pd->partitionNumber; setChecksum(&backFid->descTag); fe->descTag.descCRCLength = sizeof(struct fileEntry) + fe->lengthAllocDescs - sizeof(tag); setChecksum(fe); } insertFileIdentDesc(dir, forwFid); dir->fe.fileLinkCount++; dir->dirDirty = 1; /* setup directory structure for new directory */ newDir = dir->child; if( newDir != NULL ) updateDirectory(newDir); else { newDir = (Directory*)malloc(sizeof(Directory)); memset(newDir, 0, sizeof(Directory)); newDir->parent = dir; newDir->dataSize = 4096; newDir->data = malloc(4096); dir->child = newDir; } memset(newDir->data, 0, newDir->dataSize); newDir->name = malloc(strlen(name)+1); strcpy(newDir->name, name); newDir->icb = forwFid->icb; memcpy(&newDir->fe, fe, 2048); memcpy(newDir->data, backFid, fe->informationLength); newDir->dirDirty = 1; lvidiu = (struct logicalVolIntegrityDescImpUse*) (lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions); lvidiu->numDirs++; free(backFid); free(forwFid); free(fe); return newDir; } /* analyzeDest() * * The last argument in a command is the destination for copying or the object * to act on. The argument consists of / separated components * eg. /src/test/udf/wrudf.h or /src/test/iso/ * or just a single component eg. . or / or wrudf.c * * All but the last component must be existing directories and curDir points to * the last directopry in that chain, eg. udf, otherwise result DIR_INVALID. * * When the last component does not exist, return result DOES_NOT_EXIST. * name --> last component eg. wrudf.h or iso * * If the last component identifies a directory return EXISTING_DIR or DELETED_DIR, * *fid = NULL, *name = last component name eg. iso. * * If the last component is a file return EXISTING_FILE or DELETED_FILE. * *fid points to FID entry in curDir with name equal the last component. * *name --> last component name eg. wrudf.h */ enum RV analyzeDest(char* arg, struct fileIdentDesc** fid, char** name) { int len; char *comp, *endComp; if( arg[0] == '/' ) { curDir = rootDir; comp = arg + 1; } else { comp = arg; } len = strlen(comp); if( len > 1 && comp[len-1] == '/' ) comp[len-1] = 0; /* remove any trailing slash */ for( ; ( endComp = strchr(comp, '/') ) != NULL; comp = ++endComp ) { *endComp = 0; if( strcmp(comp, ".") == 0 ) continue; if( strcmp(comp, "..") == 0 ) { if( !curDir->parent ) return DIR_INVALID; curDir = curDir->parent; continue; } *fid = findFileIdentDesc(curDir, comp); if( *fid == NULL ) return DIR_INVALID; if( ! ((*fid)->fileCharacteristics & FID_FILE_CHAR_DIRECTORY )) return DIR_INVALID; if( (*fid)->fileCharacteristics & FID_FILE_CHAR_DELETED ) return DIR_INVALID; // curDir = readDirectory(curDir->child, &(*fid)->icb, comp); curDir = readDirectory(curDir, &(*fid)->icb, comp); } // final component *name = comp; if( comp[0] == 0 || strcmp(comp, ".") == 0 ) return EXISTING_DIR; if( strcmp(comp, "..") == 0 ) { if( !curDir->parent ) return DIR_INVALID; curDir = curDir->parent; return EXISTING_DIR; } *fid = findFileIdentDesc(curDir, comp); if( *fid == NULL ) return DOES_NOT_EXIST; if( (*fid)->fileCharacteristics & FID_FILE_CHAR_DIRECTORY ) { if( (*fid)->fileCharacteristics & FID_FILE_CHAR_DELETED ) return DELETED_DIR; else { curDir = readDirectory(curDir, &(*fid)->icb, comp); return EXISTING_DIR; } } else { if( (*fid)->fileCharacteristics & FID_FILE_CHAR_DELETED ) return DELETED_FILE; } return EXISTING_FILE; } int cpCommand(void) { int i, rv; enum RV state; char *srcname, *name, *p; Directory *cpyDir; struct fileIdentDesc *fid, *newFid; struct stat fileStat; if( cmndc < 2 ) return WRONG_NO_ARGS; name = NULL; state = analyzeDest(cmndv[cmndc-1], &fid, &name); if( state == DIR_INVALID ) return DIR_INVALID; if( state == DELETED_DIR ) { printf("Cannot reuse deleted directory name yet\n"); return CMND_FAILED; } if( state == DELETED_FILE ) { removeFID(curDir, fid); state = DOES_NOT_EXIST; } if( state == EXISTING_FILE ) { if( questionOverwrite(curDir, fid, name) ) return CMND_FAILED; state = DOES_NOT_EXIST; } /* do I have write permission for the destination directory ? */ /* process source arguments */ for( i = 0; i < cmndc - 1; i++ ) { p = strrchr(cmndv[i], '/'); if( p && p > cmndv[i] && *(p+1) == 0 ) *p = 0; // remove any trailing slash (except in "/") p = strrchr(cmndv[i], '/'); if( p ) { srcname = p+1; } else srcname = cmndv[i]; if( (rv = lstat(cmndv[i], &fileStat)) < 0 ) { // do not follow soft links printf("stat failed on %s\n", cmndv[i]); continue; } if( S_ISDIR(fileStat.st_mode) ) { if( state == EXISTING_DIR ) { newFid = findFileIdentDesc(curDir, srcname); if( newFid == NULL ) { cpyDir = makeDir(curDir, srcname); newFid = findFileIdentDesc(curDir, srcname); } else { if( newFid->fileCharacteristics != FID_FILE_CHAR_DIRECTORY ) { printf("Destination is not a directory\n"); return CMND_FAILED; } cpyDir = readDirectory(curDir, &newFid->icb, srcname); } if( chdir(cmndv[i]) != 0 ) printf("Change dir '%s': %m\n", cmndv[i]); else copyDirectory(cpyDir, "."); } else printf("Destination is not a directory\n"); if( chdir(hdWorkingDir) != 0 ) { printf("Change dir '%s': %m\n", hdWorkingDir); return CMND_FAILED; } continue; } if( !S_ISREG(fileStat.st_mode) ) { printf("Can only copy regular files or directories\n"); return CMND_FAILED; } if( state == DOES_NOT_EXIST || state == EXISTING_DIR ) name = srcname; copyFile(curDir, cmndv[i], name, &fileStat); } return CMND_OK; } int rmCommand(void) { enum RV state; int i; struct fileIdentDesc *fid; char* name; if( cmndc < 1 ) return CMND_ARG_INVALID; for( i = 0; i < cmndc; i++ ) { state = analyzeDest(cmndv[i], &fid, &name); if( state == EXISTING_FILE ) { deleteFID(curDir, fid); continue; } if( state != EXISTING_DIR ) return state; if( options & OPT_RECURSIVE ) { deleteDirectory(curDir, fid); continue; } else printf("Cannot delete directory '%s' without -r option\n", cmndv[i]); } return CMND_OK; } int mkdirCommand(void) { int rv; char *name; struct fileIdentDesc *fid; Directory *newDir; if( cmndc != 1 ) return WRONG_NO_ARGS; rv = analyzeDest(cmndv[0], &fid, &name); if( rv == DIR_INVALID ) return DIR_INVALID; if( rv == EXISTING_FILE || rv == EXISTING_DIR ) { if( fid->fileCharacteristics & FID_FILE_CHAR_DELETED ) { removeFID(curDir, fid); } else return rv; } newDir = makeDir(curDir, name); if( !newDir ) return CMND_FAILED; curDir = newDir; return CMND_OK; } int rmdirCommand(void) { int state; struct fileIdentDesc *fid; char* name; if( cmndc != 1 ) return WRONG_NO_ARGS; state = analyzeDest(cmndv[0], &fid, &name); if( state != EXISTING_DIR ) return state; if( !directoryIsEmpty(curDir) ) return DIR_NOT_EMPTY; if( !curDir->parent ) { printf("Cannot remove root directory\n"); return CMND_FAILED; } return deleteFID(curDir, fid); } int cdcCommand() { int state; struct fileIdentDesc *fid; char* name; if( cmndc != 1 ) return WRONG_NO_ARGS; state = analyzeDest(cmndv[0], &fid, &name); if( state != EXISTING_DIR ) return state; return CMND_OK; } int lscCommand(void) { struct fileIdentDesc *fid; struct fileEntry *fe; char *name, filename[512]; uint64_t i; int state; if( cmndc > 1 ) return WRONG_NO_ARGS; if( cmndc == 1 ) { state = analyzeDest(cmndv[0], &fid, &name); if( state != EXISTING_DIR ) return state; } for( i = 0; i < curDir->fe.informationLength; i += ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) ) { fid = (struct fileIdentDesc*)(curDir->data + i); if( fid->fileCharacteristics & FID_FILE_CHAR_DELETED ) continue; if( fid->fileCharacteristics & FID_FILE_CHAR_PARENT ) strcpy(filename, ".."); else decode_locale((dchars *)(fid->fileIdent + fid->lengthOfImpUse), filename, fid->lengthFileIdent, sizeof(filename)); fe = readTaggedBlock( fid->icb.extLocation.logicalBlockNum, fid->icb.extLocation.partitionReferenceNum); printf("%s %6d:%c%c%c%c%c %6d:%c%c%c%c%c other:%c%c%c%c%c links:%2d info:%12d %s\n", fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY ? "DIR" : " ", fe->uid, fe->permissions & FE_PERM_U_READ ? 'r' : '-', fe->permissions & FE_PERM_U_WRITE ? 'w' : '-', fe->permissions & FE_PERM_U_EXEC ? 'x' : '-', fe->permissions & FE_PERM_U_CHATTR ? 'a' : '-', fe->permissions & FE_PERM_U_DELETE ? 'd' : '-', fe->gid, fe->permissions & FE_PERM_G_READ ? 'r' : '-', fe->permissions & FE_PERM_G_WRITE ? 'w' : '-', fe->permissions & FE_PERM_G_EXEC ? 'x' : '-', fe->permissions & FE_PERM_G_CHATTR ? 'a' : '-', fe->permissions & FE_PERM_G_DELETE ? 'd' : '-', fe->permissions & FE_PERM_O_READ ? 'r' : '-', fe->permissions & FE_PERM_O_WRITE ? 'w' : '-', fe->permissions & FE_PERM_O_EXEC ? 'x' : '-', fe->permissions & FE_PERM_O_CHATTR ? 'a' : '-', fe->permissions & FE_PERM_O_DELETE ? 'd' : '-', fe->fileLinkCount, (uint32_t)fe->informationLength, filename); } return CMND_OK; } int cdhCommand() { if( cmndc > 1 ) return WRONG_NO_ARGS; if( chdir(cmndv[0]) != 0 ) { printf("Change dir '%s': %m\n", cmndv[0]); return CMND_FAILED; } if( hdWorkingDir ) free(hdWorkingDir); hdWorkingDir = getcwd(NULL, 0); printf("Harddisk working directory set to %s\n", cmndv[0]); return CMND_OK; } int lshCommand() { char cmnd[128]; if( cmndc > 1 ) return WRONG_NO_ARGS; strcpy(cmnd, "ls -l "); if( cmndc == 1 ) strncat(cmnd, cmndv[0], sizeof(cmnd)-strlen("ls -l ")-1); if( system(cmnd) != 0 ) return CMND_FAILED; return CMND_OK; } /* directoryIsEmpty() * Return 1 if a directory contains only a parent dir entry and, possibly 0, deleted entries; * Otherwise return 0; */ int directoryIsEmpty(Directory *dir) { uint64_t i; struct fileIdentDesc *fid; for( i = 0; i < dir->fe.informationLength; i += ((sizeof(struct fileIdentDesc) + fid->lengthOfImpUse + fid->lengthFileIdent + 3) & ~3) ) { fid = (struct fileIdentDesc*)(dir->data + i); if( fid->fileCharacteristics & (FID_FILE_CHAR_DELETED | FID_FILE_CHAR_PARENT) ) continue; return 0; } return 1; } /* questionOverwrite() * Query whether to overwrite existing file. * Remove the FID entry from the directory if reply was 'y' and return 0. * Return 1 if don't overwrite. */ int questionOverwrite(Directory *dir, struct fileIdentDesc *fid, char* name) { printf("File %s already exists. Overwrite ? (y/N) : ", name); #ifdef _GNU_SOURCE readLine(NULL); #else fgets(line, 256, stdin); #endif if( !line || line[0] != 'y' ) return 1; deleteFID(dir, fid); return 0; } udftools-2.0/wrudf/wrudf.c0000644000175000017500000005007113221466537012571 00000000000000/* wrudf.c * * Maintains a UDF filing system * */ #include "config.h" #include #include #include #include #include #include #include "wrudf.h" char *devicename; /* "/dev/cdrom" or disk image filename */ int device; /* the file descriptor */ int devicetype; enum MEDIUM medium; int ignoreReadError; /* used while reading VRS which may be absent on open CDR */ #ifdef _GNU_SOURCE char *line; #define GETLINE(prompt) readLine(prompt); #else char line[256]; #define GETLINE(prompt) printf(prompt); fgets(line, 256, stdin); *strchr(line, '\n') = 0; #endif int cmndc; int cmndvSize; char** cmndv; #define FOUND_BEA01 1 #define FOUND_NSR02 1<<1 #define FOUND_TEA01 1<<2 #define FOUND_PVD 1<<8 #define FOUND_LVD 1<<9 #define FOUND_PD 1<<10 #define FOUND_USD 1<<11 uint32_t found; uint32_t options; Directory *rootDir, *curDir; timestamp timeStamp; regid entityWRUDF = { 0, "-wrudf (" PACKAGE_VERSION ")", "\x04\x05"}; extent_ad extentMainVolDescSeq; extent_ad extentRsrvVolDescSeq; extent_ad extentNextVolDescSeq; extent_ad extentLogVolIntegritySeq; uint32_t integrityDescBlocknumber; /* where to write LVID when finished */ extent_ad extentLogVolIntegrityDesc; /* (continuation) extent for current LVIDs */ extern uint64_t CDRuniqueID; /* in wrudf-cdr.c ex VAT FE */ struct partitionDesc *pd; /* for the writable partition */ uint16_t virtualPartitionNum = 0xFFFF; uint32_t *vat; struct logicalVolDesc *lvd; struct unallocSpaceDesc *usd; struct spaceBitmapDesc *spaceMap; struct logicalVolIntegrityDesc *lvid; struct fileSetDesc *fsd; unsigned int usedSparingEntries; struct sparingTable *st; int spaceMapDirty, usdDirty, sparingTableDirty; char* readLine(char* prompt) { if( line ) { free(line); } return line = readline(prompt); } void initialise(char *devicename) { uint32_t i, len, blkno, lastblk, size; long_ad *fsdAd; short_ad *adSpaceMap; struct sparablePartitionMap *spm; char zeroes[5]; char fsdOut[91]; struct generic_desc *p; struct volStructDesc *vsd; struct partitionHeaderDesc *phd; struct logicalVolHeaderDesc *lvhd; initIO(devicename); memset(zeroes, 0, 5); /* read Volume Recognition Sequence */ ignoreReadError = 1; for( blkno = 16; blkno < 256; blkno++ ) { vsd = readSingleBlock(blkno); if( vsd == NULL || memcmp(vsd->stdIdent, zeroes, 5) == 0 ) break; if( strncmp((char *)vsd->stdIdent, "BEA01", VSD_STD_ID_LEN) == 0 ) { found |= FOUND_BEA01; continue; } if( strncmp((char *)vsd->stdIdent, "NSR02", VSD_STD_ID_LEN) == 0 ) { found |= FOUND_NSR02; continue; } if( strncmp((char *)vsd->stdIdent, "TEA01", 5) == 0 ) { found |= FOUND_TEA01; continue; } } ignoreReadError = 0; if( !(found & FOUND_BEA01) || !(found & FOUND_NSR02) || !(found & FOUND_TEA01) ) printf("No UDF VRS\n"); p = NULL; if( medium == CDR ) { p = readSingleBlock(512); if( p == NULL || p->descTag.tagIdent != TAG_IDENT_AVDP ) fail("No AVDP at block 512 on CDR disc\n"); } if( !p ) { p = readTaggedBlock(256, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) { p = readTaggedBlock(trackSize - 1, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) { p = readTaggedBlock(trackSize - 256, ABSOLUTE); if( p->descTag.tagIdent != TAG_IDENT_AVDP ) fail("No AVDP at block 256, N-256 or N-1 \n"); } } } extentMainVolDescSeq = ((struct anchorVolDescPtr*)p)->mainVolDescSeqExt; extentRsrvVolDescSeq = ((struct anchorVolDescPtr*)p)->reserveVolDescSeqExt; /* read Volume Descriptor Sequence */ blkno = extentMainVolDescSeq.extLocation; len = extentMainVolDescSeq.extLength; for( i = 0; i < len; blkno++, i += 2048 ) { int inMainSeq = 1; if( (p = readTaggedBlock(blkno, ABSOLUTE)) == NULL ) { if( !inMainSeq ) fail("Volume Descriptor Sequences read failure\n"); blkno = extentRsrvVolDescSeq.extLocation; len = extentRsrvVolDescSeq.extLength; inMainSeq = 0; i = 0; } switch( p->descTag.tagIdent ) { case TAG_IDENT_PVD: found |= FOUND_PVD; break; case TAG_IDENT_VDP: blkno = ((struct volDescPtr*)p)->nextVolDescSeqExt.extLocation - 1; len = ((struct volDescPtr*)p)->nextVolDescSeqExt.extLength; i = (uint32_t) -2048; break; case TAG_IDENT_IUVD: break; case TAG_IDENT_PD: /* must have one (re)writable partition */ /* may have at most one RDONLY partition */ switch( ((struct partitionDesc *)p)->accessType ) { case PD_ACCESS_TYPE_READ_ONLY: break; case PD_ACCESS_TYPE_REWRITABLE: case PD_ACCESS_TYPE_WRITE_ONCE: found |= FOUND_PD; if( !pd ) pd = (struct partitionDesc*) calloc(512, 1); if( p->volDescSeqNum > pd->volDescSeqNum ) memcpy(pd, p, 512); break; case PD_ACCESS_TYPE_OVERWRITABLE: printf("Partition with overwritable accesstype is not supported\n"); break; default: printf("What to do with an accesstype %d partition?\n", ((struct partitionDesc*)p)->accessType); break; } break; case TAG_IDENT_LVD: found |= FOUND_LVD; if( !lvd ) lvd = (struct logicalVolDesc*) calloc(512, 1); if( p->volDescSeqNum > lvd->volDescSeqNum ) memcpy(lvd, p, 512); break; case TAG_IDENT_USD: found |= FOUND_USD; if( !usd ) usd = (struct unallocSpaceDesc*) calloc(512, 1); if( p->volDescSeqNum > usd->volDescSeqNum ) memcpy(usd, p, 512); break; case TAG_IDENT_TD: i = len; break; default: printf("Unexpected tag ID %04X\n in Volume Descriptor Sequence block %d", p->descTag.tagIdent, blkno); } } if( (found & FOUND_LVD) == 0 ) fail("No LVD found \n"); if( (found & FOUND_PD) == 0 ) fail("No PD found\n"); if( lvd->logicalBlockSize != 2048 ) fail("Blocksize not 2048\n"); spm = (struct sparablePartitionMap*)lvd->partitionMaps; for( i = 0; i < lvd->numPartitionMaps; i++ ) { if( spm->partitionMapType == 2 ) { if( strncmp((char *)spm->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)) == 0 ) { unsigned int j; if( spm->sizeSparingTable > 2048 ) fail("Cannot handle SparingTable > 2048 bytes"); st = (struct sparingTable*)malloc(2048); p = readTaggedBlock(spm->locSparingTable[0], ABSOLUTE); memcpy(st, p, spm->sizeSparingTable); /* if #1 fails, try #2; should pick copy with highest sequenceNum */ for( j = usedSparingEntries = 0; j < (spm->sizeSparingTable >> 3); j++ ) { if( st->mapEntry[j].origLocation < 0xFFFFFFF0 ) usedSparingEntries++; } } else if( strncmp((char *)spm->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)) == 0 ) virtualPartitionNum = i; } spm = (struct sparablePartitionMap*)((char*)spm + spm->partitionMapLength); } if( medium == CDR ) { if( virtualPartitionNum != 0xFFFF ) readVATtable(); else fail("No Virtual Partition Map on CDR\n"); } if( medium != CDR && (found & FOUND_USD) == 0 ) fail("Did not find Unallocated Space Descriptor\n"); /* Read Fileset Descriptor Sequence */ fsdAd = (long_ad*) lvd->logicalVolContentsUse; for( i = 0; i < (fsdAd->extLength >> 11); i++ ) { blkno = pd->partitionStartingLocation + fsdAd->extLocation.logicalBlockNum + i; if( !(p = readTaggedBlock(blkno, ABSOLUTE)) ) exit(1); switch( p->descTag.tagIdent ) { case TAG_IDENT_TD: i = fsdAd->extLength; break; case TAG_IDENT_FSD: if( fsd && (lvd->volDescSeqNum > p->volDescSeqNum) ) break; fsd = (struct fileSetDesc*)malloc(512); memcpy(fsd, p, 512); break; default: printf("Unxpected tag id %d, where File Set Desc(256) expected\n", p->descTag.tagIdent); } } if( !fsd ) fail("No File Set Descriptor\n"); /* load Spacemap extent */ phd = (struct partitionHeaderDesc*)pd->partitionContentsUse; adSpaceMap = &phd->unallocSpaceBitmap; if( adSpaceMap->extLength != 0 ) { blkno = adSpaceMap->extPosition; len = adSpaceMap->extLength; spaceMap = (struct spaceBitmapDesc*) malloc((len + 2047) & ~2047); for( i = 0; i < len; i += 2048 ) { p = readBlock(blkno, 0); memcpy( (uint8_t*)spaceMap + i, (uint8_t*) p, 2048); freeBlock(blkno++, 0); } if( spaceMap->descTag.tagIdent != TAG_IDENT_SBD ) fail("SpaceBitmap not found\n"); } if (decode_string(NULL, fsd->fileSetIdent, fsdOut, sizeof(fsd->fileSetIdent), sizeof(fsdOut)) == (size_t)-1) fsdOut[0] = 0; printf("You are going to update fileset '%s'\nProceed (y/N) : ", fsdOut); readLine(NULL); if( !line || line[0] != 'y' ) fail("wrudf terminated\n"); /* Read Logical Volume Integrity sequence */ blkno = lvd->integritySeqExt.extLocation; lastblk = blkno + (lvd->integritySeqExt.extLength >> 11); extentLogVolIntegrityDesc = lvd->integritySeqExt; for( ; blkno < lastblk; blkno++ ) { if( !(p = readTaggedBlock(blkno, ABSOLUTE)) ) fail("Read failure in Integrity Sequence, blk %d\n", blkno); switch( p->descTag.tagIdent ) { case TAG_IDENT_TD: blkno = lastblk; break; case TAG_IDENT_LVID: size = sizeof(struct logicalVolIntegrityDesc) + sizeof(struct logicalVolIntegrityDescImpUse) + 2 * sizeof(uint32_t) * ((struct logicalVolIntegrityDesc*)p)->numOfPartitions; if( !lvid ) lvid = (struct logicalVolIntegrityDesc*) malloc(size); integrityDescBlocknumber = blkno; memcpy(lvid, p, size); if( lvid->nextIntegrityExt.extLocation ) { extentLogVolIntegrityDesc = lvid->nextIntegrityExt; blkno = lvid->nextIntegrityExt.extLocation; lastblk = blkno + (lvid->nextIntegrityExt.extLength >> 11); blkno--; /* incremented again in for statement */ } break; default: printf("Unxpected tag %X in Integrity Sequence; blk %d\n", p->descTag.tagIdent, blkno); blkno = lastblk; break; } } if( !lvid || lvid->descTag.tagIdent != TAG_IDENT_LVID ) fail("No Logical Volume Integrity Descriptor\n"); if( medium == CDR && lvid->integrityType == LVID_INTEGRITY_TYPE_CLOSE ) fail("CDR volume has been closed\n"); if( medium == CDR ) { // take from VAT FileEntry lvhd = (struct logicalVolHeaderDesc*)lvid->logicalVolContentsUse; lvhd->uniqueID = CDRuniqueID; } curDir = rootDir = (Directory*)malloc(sizeof(Directory)); memset(rootDir, 0, sizeof(Directory)); rootDir->dataSize = 4096; rootDir->data = malloc(4096); rootDir->name = ""; readDirectory( NULL, &fsd->rootDirectoryICB, ""); if( medium == CDR ) return; if( lvid->integrityType == LVID_INTEGRITY_TYPE_OPEN ) { GETLINE("** Volume was not closed; do you wish to proceed (y/N) : "); if( (line[0] | 0x20) != 'y' ) exit(0); } /* If prevailing LVID is in one before last block of extent * then next LVID will be in last and must contain continuation extent */ if( integrityDescBlocknumber + 2 == extentLogVolIntegrityDesc.extLocation + (extentLogVolIntegrityDesc.extLength >> 11) ) { getUnallocSpaceExtent( 32 * 2048, extentLogVolIntegrityDesc.extLocation, &lvid->nextIntegrityExt); if( lvid->nextIntegrityExt.extLength == 0 ) { printf("No more unallocated space for Integrity Sequence\n"); } } else { lvid->nextIntegrityExt.extLength = 0; lvid->nextIntegrityExt.extLocation = 0; } integrityDescBlocknumber++; updateTimestamp(0,0); memcpy(lvid->impUse + 2 * sizeof(uint32_t) * lvid->numOfPartitions, &entityWRUDF, sizeof(regid)); lvid->recordingDateAndTime = timeStamp; lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; lvid->descTag.tagLocation = integrityDescBlocknumber; size = sizeof(struct logicalVolIntegrityDesc) + sizeof(struct logicalVolIntegrityDescImpUse) + 2 * sizeof(uint32_t) * lvid->numOfPartitions; lvid->descTag.descCRCLength = size - sizeof(tag); setChecksum(lvid); p = readTaggedBlock(integrityDescBlocknumber, ABSOLUTE); memcpy( p, lvid, size); dirtyBlock(integrityDescBlocknumber, ABSOLUTE); /* not written because of buffering : Force unit access? */ } int finalise(void) { int i, lbn, len, size, blkno ; struct generic_desc *p; short_ad *adSpaceMap; struct partitionHeaderDesc *phd; updateDirectory(rootDir); /* and any dirty children */ if( medium == CDR ) { writeVATtable(); } else { /* rewrite Space Bitmap */ if( spaceMapDirty) { phd = (struct partitionHeaderDesc*)pd->partitionContentsUse; adSpaceMap = &phd->unallocSpaceBitmap; lbn = adSpaceMap->extPosition; len = adSpaceMap->extLength; for( i = 0; i < len; i += 2048 ) { p = readBlock(lbn, 0); memcpy( p, (uint8_t*)spaceMap + i, 2048); dirtyBlock(lbn, 0); freeBlock(lbn++, 0); } } if( sparingTableDirty ) updateSparingTable(); /* write closed Logical Volume Integrity Descriptor */ lvid->integrityType = LVID_INTEGRITY_TYPE_CLOSE; updateTimestamp(0,0); lvid->recordingDateAndTime = timeStamp; lvid->descTag.tagLocation = integrityDescBlocknumber; size = sizeof(struct logicalVolIntegrityDesc) + sizeof(struct logicalVolIntegrityDescImpUse) + 2 * sizeof(uint32_t) * lvid->numOfPartitions; lvid->descTag.descCRCLength = size - sizeof(tag); setChecksum(lvid); p = readBlock(integrityDescBlocknumber, ABSOLUTE); memcpy(p, lvid, size); dirtyBlock(integrityDescBlocknumber, ABSOLUTE); freeBlock(integrityDescBlocknumber, ABSOLUTE); /* terminating descriptor */ blkno = lvid->nextIntegrityExt.extLocation; if( !blkno ) blkno = integrityDescBlocknumber + 1; p = readBlock(blkno, ABSOLUTE); memset(p, 0, 2048); p->descTag.tagLocation = blkno; p->descTag.tagSerialNum = lvid->descTag.tagSerialNum; p->descTag.tagIdent = TAG_IDENT_TD; p->descTag.descCRCLength = 512 - sizeof(tag); setChecksum(p); dirtyBlock(blkno, ABSOLUTE); freeBlock(blkno, ABSOLUTE); if( usdDirty ) { size = sizeof(struct unallocSpaceDesc) + usd->numAllocDescs * sizeof(extent_ad); usd->descTag.descCRCLength = size - sizeof(tag); setChecksum(usd); p = readBlock(usd->descTag.tagLocation, ABSOLUTE); memcpy(p, usd, size); dirtyBlock(usd->descTag.tagLocation, ABSOLUTE); freeBlock(usd->descTag.tagLocation, ABSOLUTE); /* now rewrite in Reserve Sequence which must be exact copy of Main Sequence */ usd->descTag.tagLocation += extentRsrvVolDescSeq.extLocation - extentMainVolDescSeq.extLocation; setChecksum(usd); p = readBlock(usd->descTag.tagLocation, ABSOLUTE); memcpy(p, usd, size); dirtyBlock(usd->descTag.tagLocation, ABSOLUTE); freeBlock(usd->descTag.tagLocation, ABSOLUTE); } } // end not CDR closeIO(); /* clears packet buffers; closes device */ /* free allocated space */ if(pd) free(pd); if(lvd) free(lvd); if(fsd) free(fsd); if(usd) free (usd); if(spaceMap) free(spaceMap); if(lvid) free(lvid); if(st) free(st); if(vat) free(vat); return 0; } int parseCmnd(char* line) { char *p, *q, next, term; int i, j; int cmnd; if( !cmndvSize ) { cmndvSize = 64; cmndv = malloc(cmndvSize * sizeof(char*)); } if( !line || line[0] == 0 ) return CMND_FAILED; cmndc = 0; for( p = line; *p == ' '; p++ ) ; for( q = p; *q && (*q != ' '); q++ ) ; next = *q; *q = 0; if( !strcmp(p, "cd") || !strcmp(p, "ls") ) { printf("Specify cdh/lsh or cdc/lsc for Harddisk or CompactDisc\n"); return CMND_FAILED; } if( !strcmp(p, "cp") ) cmnd = CMND_CP; else if( !strcmp(p, "rm") ) cmnd = CMND_RM; else if( !strcmp(p, "mkdir") ) cmnd = CMND_MKDIR; else if( !strcmp(p, "rmdir") ) cmnd = CMND_RMDIR; else if( !strcmp(p, "lsc") ) cmnd = CMND_LSC; else if( !strcmp(p, "lsh") ) cmnd = CMND_LSH; else if( !strcmp(p, "cdc") ) cmnd = CMND_CDC; else if( !strcmp(p, "cdh") ) cmnd = CMND_CDH; else if( !strcmp(p, "quit") ) cmnd = CMND_QUIT; else if( !strcmp(p, "exit") ) cmnd = CMND_QUIT; else if( !strcmp(p, "help") ) { printf( "Available commands:\n" "\tcp\n" "\trm\n" "\tmkdir\n" "\trmdir\n" "\tlsc\n" "\tlsh\n" "\tcdc\n" "\tcdh\n" "Specify cdh/lsh or cdc/lsc to do cd or ls for Harddisk or CompactDisc.\n" "\tquit\n" "\texit\n" ); return CMND_FAILED; } else { printf("Invalid command\n"); return CMND_FAILED; } while( next != 0 ) { if( cmndc == cmndvSize ) { cmndvSize += 32; cmndv = realloc(cmndv, cmndvSize); if( !cmndv ) fail("cmndv reallocation failed\n"); } p = q + 1; while( *p == ' ') p++; if( *p == 0 ) break; if( *p == '"' ) { term = '"'; q = p+1; } else { term = ' '; q = p; } while( *q && *q != term ) q++; next = *q; if( *p == '"' ) { if( *q == 0 ) return CMND_ARG_INVALID; cmndv[cmndc++] = p+1; *(q-1) = 0; } else { cmndv[cmndc++] = p; *q = 0; } } options = 0; for( i = 0; i < cmndc; i ++ ) { if( cmndv[i][0] == '-' ) { for( j = 1; cmndv[i][j]; j++ ) { switch( cmndv[i][j] ) { case 'f': options |= OPT_FORCE; break; case 'r': options |= OPT_RECURSIVE; break; default: return CMND_ARG_INVALID; } } cmndv[i] = NULL; } } for( i = j = 0; i < cmndc; i++ ) { if( i != j ) cmndv[j] = cmndv[i]; if( cmndv[j] != NULL ) j++; } cmndc = j; /* could check whether options valid for command */ return cmnd; } int show_help() { char *msg = "Interactive tool to maintain an UDF filesystem.\n" "Usage:\n" "\twrudf [device]\n" "Available commands:\n" "\tcp\n" "\trm\n" "\tmkdir\n" "\trmdir\n" "\tlsc\n" "\tlsh\n" "\tcdc\n" "\tcdh\n" "Specify cdh/lsh or cdc/lsc to do cd or ls for Harddisk or CompactDisc.\n" "\tquit\n" "\texit\n"; printf("%s", msg); return 0; } int main(int argc, char** argv) { int rv=0; int cmnd; char prompt[256]; char *ptr; size_t len; Directory *d; setlocale(LC_CTYPE, ""); printf("wrudf from " PACKAGE_NAME " " PACKAGE_VERSION "\n"); devicename= "/dev/cdrom"; if( argc > 2 || (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--help"))) ) return show_help(); else if( argc == 2 ) devicename = argv[1]; /* can specify disk image filename */ if( setpriority(PRIO_PROCESS, 0, -10) ) { printf("setpriority(): %m\n"); } hdWorkingDir = getcwd(NULL, 0); initialise(devicename); for(;;) { d = rootDir; prompt[0] = 0; ptr = prompt; while( curDir != d ) { len = strlen(d->name); if( ptr + len + 1 >= prompt + sizeof(prompt) - 7 ) break; memcpy(ptr, d->name, len); ptr[len] = '/'; ptr += len + 1; d = d->child; } len = strlen(d->name); if( ptr + len + 1 >= prompt + sizeof(prompt) - 7 ) { memcpy(ptr, "...", 3); ptr += 3; } else if( d->name[0] == 0 ) { *(ptr++) = '/'; } else { memcpy(ptr, d->name, len); ptr += len; } memcpy(ptr, " > ", 4); GETLINE(prompt); cmnd = parseCmnd(line); if( cmnd == CMND_FAILED ) continue; if( cmnd == CMND_QUIT ) break; switch( cmnd ) { case CMND_CP: rv = cpCommand(); break; case CMND_RM: rv = rmCommand(); break; case CMND_MKDIR: rv = mkdirCommand(); break; case CMND_RMDIR: rv = rmdirCommand(); break; case CMND_LSC: rv = lscCommand(); break; case CMND_LSH: rv = lshCommand(); break; case CMND_CDC: rv = cdcCommand(); break; case CMND_CDH: rv = cdhCommand(); break; } switch( rv ) { case CMND_OK: break; case CMND_FAILED: printf("Failed\n"); break; case WRONG_NO_ARGS: printf("Incorrect number of arguments\n"); break; case CMND_ARG_INVALID: printf("Invalid argument\n"); break; case NOT_IN_RW_PARTITION: printf("Not in RW partition\n"); break; case DIR_INVALID: printf("Invalid directory\n"); break; case DIR_NOT_EMPTY: printf("Directory not empty\n"); break; case EXISTING_DIR: printf("Dir already exists\n"); break; case DOES_NOT_EXIST: printf("File/directory does not exist\n"); break; case PERMISSION_DENIED: printf("Permission denied\n"); break; case IS_DIRECTORY: printf("Is a directory\n"); break; default: printf("Unknown return value %d\n", rv); } } free(hdWorkingDir); return finalise(); } udftools-2.0/wrudf/Makefile.in0000644000175000017500000004652613221466653013354 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = wrudf$(EXEEXT) subdir = wrudf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_wrudf_OBJECTS = wrudf.$(OBJEXT) wrudf-cmnd.$(OBJEXT) \ wrudf-desc.$(OBJEXT) wrudf-cdrw.$(OBJEXT) wrudf-cdr.$(OBJEXT) \ ide-pc.$(OBJEXT) wrudf_OBJECTS = $(am_wrudf_OBJECTS) wrudf_DEPENDENCIES = $(top_builddir)/libudffs/libudffs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(wrudf_SOURCES) DIST_SOURCES = $(wrudf_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ wrudf_LDADD = $(top_builddir)/libudffs/libudffs.la -lreadline wrudf_SOURCES = wrudf.c wrudf-cmnd.c wrudf-desc.c wrudf-cdrw.c wrudf-cdr.c ide-pc.c wrudf.h ide-pc.h ../include/ecma_167.h ../include/osta_udf.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include -D_GNU_SOURCE -DDEBUG all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu wrudf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu wrudf/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list wrudf$(EXEEXT): $(wrudf_OBJECTS) $(wrudf_DEPENDENCIES) $(EXTRA_wrudf_DEPENDENCIES) @rm -f wrudf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wrudf_OBJECTS) $(wrudf_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ide-pc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrudf-cdr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrudf-cdrw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrudf-cmnd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrudf-desc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrudf.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/wrudf/Makefile.am0000644000175000017500000000046413221466537013333 00000000000000bin_PROGRAMS = wrudf wrudf_LDADD = $(top_builddir)/libudffs/libudffs.la -lreadline wrudf_SOURCES = wrudf.c wrudf-cmnd.c wrudf-desc.c wrudf-cdrw.c wrudf-cdr.c ide-pc.c wrudf.h ide-pc.h ../include/ecma_167.h ../include/osta_udf.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include -D_GNU_SOURCE -DDEBUG udftools-2.0/udflabel/0000755000175000017500000000000013221466662012001 500000000000000udftools-2.0/udflabel/options.h0000644000175000017500000000304513221466537013570 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef OPTIONS_H #define OPTIONS_H struct udf_disc; void parse_args(int, char *[], struct udf_disc *, char **, int *, dstring *, dstring *, dstring *, dstring *, char *, dstring *); /* * Command line option token values. * 0x0000-0x00ff Single characters * 0x1000-0x1fff Long switches (no arg) * 0x2000-0x2fff Long settings (arg required) */ #define OPT_HELP 0x1000 #define OPT_LOCALE 0x1001 #define OPT_UNICODE8 0x1002 #define OPT_UNICODE16 0x1003 #define OPT_UTF8 0x1004 #define OPT_FORCE 0x1005 #define OPT_NO_WRITE 0x1006 #define OPT_BLK_SIZE 0x2000 #define OPT_VAT_BLOCK 0x2001 #define OPT_UUID 0x2002 #define OPT_LVID 0x2003 #define OPT_VID 0x2004 #define OPT_VSID 0x2005 #define OPT_FSID 0x2006 #define OPT_FULLVSID 0x2007 #endif /* OPTIONS_H */ udftools-2.0/udflabel/options.c0000644000175000017500000002133113221466537013561 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "libudffs.h" #include "options.h" static struct option long_options[] = { { "help", no_argument, NULL, OPT_HELP }, { "blocksize", required_argument, NULL, OPT_BLK_SIZE }, { "vatblock", required_argument, NULL, OPT_VAT_BLOCK }, { "force", no_argument, NULL, OPT_FORCE }, { "no-write", no_argument, NULL, OPT_NO_WRITE }, { "uuid", required_argument, NULL, OPT_UUID }, { "lvid", required_argument, NULL, OPT_LVID }, { "vid", required_argument, NULL, OPT_VID }, { "vsid", required_argument, NULL, OPT_VSID }, { "fsid", required_argument, NULL, OPT_FSID }, { "fullvsid", required_argument, NULL, OPT_FULLVSID }, { "locale", no_argument, NULL, OPT_LOCALE }, { "u8", no_argument, NULL, OPT_UNICODE8 }, { "u16", no_argument, NULL, OPT_UNICODE16 }, { "utf8", no_argument, NULL, OPT_UTF8 }, { 0, 0, NULL, 0 }, }; static void usage(void) { fprintf(stderr, "udflabel from " PACKAGE_NAME " " PACKAGE_VERSION "\n" "Usage:\n" "\tudflabel [encoding-options] [block-options] [identifier-options] device [new-label]\n" "\n" "When all Identifier Options and new UDF Label are omitted then show current UDF Label.\n" "Otherwise set new Identifier Options. New UDF Label is synonym for both --lvid and --vid.\n" "\n" "Options:\n" "\t--help, -h Display this help\n" "\n" "Block Options:\n" "\t--blocksize=, -b Size of blocks in bytes (512, 1024, 2048, 4096, 8192, 16384, 32768; default: detect)\n" "\t--vatblock= Block location of the Virtual Allocation Table (default: detect)\n" "\t--force Force updating UDF disks without write support (useful only for disk images)\n" "\t--no-write, -n Not really, do not write to device, just simulate\n" "\n" "Identifier Options:\n" "\t--uuid=, -u New UDF UUID, first 16 characters of Volume Set Identifier\n" "\t--lvid= New Logical Volume Identifier\n" "\t--vid= New Volume Identifier\n" "\t--vsid= New 17.-127. character of Volume Set Identifier\n" "\t--fsid= New File Set Identifier\n" "\t--fullvsid= New full Volume Set Identifier, overwrite --uuid and --vsid\n" "\n" "Encoding Options:\n" "\t--locale Identifier options are encoded according to current locale (default)\n" "\t--u8 Identifier options are encoded in 8-bit OSTA Compressed Unicode format\n" "\t--u16 Identifier options are encoded in 16-bit OSTA Compressed Unicode format\n" "\t--utf8 Identifier options are encoded in UTF-8\n" ); exit(1); } static unsigned long int strtoul_safe(const char *str, int base, int *failed) { char *endptr = NULL; unsigned long int ret; errno = 0; ret = strtoul(str, &endptr, base); *failed = (!*str || *endptr || errno) ? 1 : 0; return ret; } static void get_random_bytes(void *buffer, size_t count) { int fd; size_t i; fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { if (read(fd, buffer, count) == (ssize_t)count) { close(fd); return; } close(fd); } for (i = 0; i < count; ++i) ((uint8_t *)buffer)[i] = rand() % 0xFF; } static void process_uuid_arg(const char *arg, char *new_uuid) { unsigned long int rnd; int i; if (strcmp(arg, "random") == 0) { get_random_bytes(&rnd, sizeof(rnd)); snprintf(new_uuid, 17, "%08lx%08lx", ((unsigned long int)time(NULL)) % 0xFFFFFFFF, rnd % 0xFFFFFFFF); return; } if (strlen(arg) != 16) { fprintf(stderr, "%s: Error: Option --uuid is not 16 bytes long\n", appname); exit(1); } for (i = 0; i < 16; ++i) { if (!isxdigit(arg[i]) || (!isdigit(arg[i]) && !islower(arg[i]))) { fprintf(stderr, "%s: Error: Option --uuid is not in lowercase hexadecimal digit format\n", appname); exit(1); } } memcpy(new_uuid, arg, 17); } static void process_vid_lvid_arg(struct udf_disc *disc, int option, const char *arg, dstring *new_lvid, dstring *new_vid) { if (option != OPT_VID) { if (encode_string(disc, new_lvid, arg, 128) == (size_t)-1) { if (option == OPT_LVID) fprintf(stderr, "%s: Error: Option --lvid is too long\n", appname); else fprintf(stderr, "%s: Error: Label is too long\n", appname); exit(1); } } if (option != OPT_LVID) { if (encode_string(disc, new_vid, arg, 32) == (size_t)-1) { if (option == OPT_VID) { fprintf(stderr, "%s: Error: Option --vid is too long\n", appname); exit(1); } /* This code was not triggered by --vid option, do not throw error but rather store truncated --lvid */ memcpy(new_vid, new_lvid, 32); new_vid[31] = 31; } } } void parse_args(int argc, char *argv[], struct udf_disc *disc, char **filename, int *force, dstring *new_lvid, dstring *new_vid, dstring *new_fsid, dstring *new_fullvsid, char *new_uuid, dstring *new_vsid) { unsigned long int value; int failed; int ret; size_t len; while ((ret = getopt_long(argc, argv, "b:nu:h", long_options, NULL)) != EOF) { switch (ret) { case OPT_HELP: case 'h': usage(); break; case OPT_BLK_SIZE: case 'b': value = strtoul_safe(optarg, 0, &failed); if (failed || value < 512 || value > 32768 || (value & (value - 1))) { fprintf(stderr, "%s: Error: Invalid value for option --blocksize\n", appname); exit(1); } disc->blocksize = value; break; case OPT_VAT_BLOCK: value = strtoul_safe(optarg, 0, &failed); if (failed || value > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --vatblock\n", appname); exit(1); } disc->vat_block = value; break; case OPT_FORCE: *force = 1; break; case OPT_NO_WRITE: case 'n': disc->flags |= FLAG_NO_WRITE; break; case OPT_UUID: case 'u': process_uuid_arg(optarg, new_uuid); new_fullvsid[0] = 0xFF; break; case OPT_VID: case OPT_LVID: process_vid_lvid_arg(disc, ret, optarg, new_lvid, new_vid); break; case OPT_VSID: len = encode_string(disc, new_vsid, optarg, 128); if (len == (size_t)-1 || len > 127-16 || (new_vsid[0] == 16 && len > 127-16*2)) { fprintf(stderr, "%s: Error: Option --vsid is too long\n", appname); exit(1); } new_fullvsid[0] = 0xFF; break; case OPT_FULLVSID: if (encode_string(disc, new_fullvsid, optarg, 128) == (size_t)-1) { fprintf(stderr, "%s: Error: Option --fullvsid is too long\n", appname); exit(1); } new_uuid[0] = 0; new_vsid[0] = 0xFF; break; case OPT_FSID: if (encode_string(disc, new_fsid, optarg, 32) == (size_t)-1) { fprintf(stderr, "%s: Error: Option --fsid is too long\n", appname); exit(1); } break; case OPT_UNICODE8: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE8; if (strcmp(argv[1], "--u8") != 0) { fprintf(stderr, "%s: Error: Option --u8 must be specified as first argument\n", appname); exit(1); } break; case OPT_UNICODE16: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE16; if (strcmp(argv[1], "--u16") != 0) { fprintf(stderr, "%s: Error: Option --u16 must be specified as first argument\n", appname); exit(1); } break; case OPT_UTF8: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UTF8; if (strcmp(argv[1], "--utf8") != 0) { fprintf(stderr, "%s: Error: Option --utf8 must be specified as first argument\n", appname); exit(1); } break; case OPT_LOCALE: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_LOCALE; if (strcmp(argv[1], "--locale") != 0) { fprintf(stderr, "%s: Error: Option --locale must be specified as first argument\n", appname); exit(1); } break; default: usage(); break; } } if (optind+1 != argc && optind+2 != argc) usage(); *filename = argv[optind]; if (optind+2 == argc) process_vid_lvid_arg(disc, -1, argv[optind+1], new_lvid, new_vid); } udftools-2.0/udflabel/main.c0000644000175000017500000004324413221466537013021 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "libudffs.h" #include "options.h" #include "../udfinfo/readdisc.h" static uint64_t get_size(int fd) { struct stat st; uint64_t size; off_t offset; if (fstat(fd, &st) == 0) { if (S_ISBLK(st.st_mode) && ioctl(fd, BLKGETSIZE64, &size) == 0) return size; else if (S_ISREG(st.st_mode)) return st.st_size; } offset = lseek(fd, 0, SEEK_END); if (offset == (off_t)-1) { fprintf(stderr, "%s: Error: Cannot detect size of disk: %s\n", appname, strerror(errno)); exit(1); } if (lseek(fd, 0, SEEK_SET) != 0) { fprintf(stderr, "%s: Error: Cannot seek to start of disk: %s\n", appname, strerror(errno)); exit(1); } return offset; } static int get_sector_size(int fd) { int size; if (ioctl(fd, BLKSSZGET, &size) != 0) return 0; if (size < 512 || size > 32768 || (size & (size - 1))) { fprintf(stderr, "%s: Warning: Disk logical sector size (%d) is not suitable for UDF\n", appname, size); return 0; } return size; } static uint16_t compute_crc(void *desc, size_t length) { return cpu_to_le16(udf_crc((uint8_t *)desc + sizeof(tag), length - sizeof(tag), 0)); } static uint8_t compute_checksum(tag *tag) { uint8_t i, checksum = 0; for (i = 0; i < 16; i++) { if (i == 4) continue; checksum += ((uint8_t *)tag)[i]; } return checksum; } static int check_desc(void *desc, size_t length) { tag *tag = desc; uint16_t crc_length = le16_to_cpu(tag->descCRCLength); if (crc_length > length - sizeof(*tag)) return 0; if (compute_checksum(tag) != tag->tagChecksum) return 0; if (compute_crc(desc, sizeof(*tag) + crc_length) != le16_to_cpu(tag->descCRC)) return 0; return 1; } static void update_desc(void *desc, size_t length) { tag *tag = desc; if (length > le16_to_cpu(tag->descCRCLength) + sizeof(*tag)) length = le16_to_cpu(tag->descCRCLength) + sizeof(*tag); tag->descCRC = cpu_to_le16(compute_crc(desc, length)); tag->tagChecksum = compute_checksum(tag); } static void write_desc(int fd, struct udf_disc *disc, enum udf_space_type type, uint16_t ident, void *buffer) { struct udf_extent *ext; struct udf_desc *desc; off_t off; size_t offset; ssize_t ret; ext = disc->head; while ((ext = next_extent(ext, type))) { desc = ext->head; while ((desc = next_desc(desc, ident))) { if (!desc->data || desc->data->buffer != buffer) continue; printf(" ... at block %lu\n", (unsigned long int)(ext->start + desc->offset)); offset = (size_t)disc->blocksize * (ext->start + desc->offset); off = lseek(fd, offset, SEEK_SET); if (off != (off_t)-1 && (size_t)off != offset) { errno = EIO; off = (off_t)-1; } if (off == (off_t)-1) { fprintf(stderr, "%s: Error: lseek failed: %s\n", appname, strerror(errno)); return; } if (!(disc->flags & FLAG_NO_WRITE)) { ret = write(fd, desc->data->buffer, desc->data->length); if (ret >= 0 && (size_t)ret != desc->data->length) { errno = EIO; ret = -1; } if (ret < 0) { fprintf(stderr, "%s: Error: write failed: %s\n", appname, strerror(errno)); return; } } return; } } fprintf(stderr, "%s: Error: Cannot find needed block for write\n", appname); return; } int main(int argc, char *argv[]) { struct udf_disc disc; struct stat stat; char *filename; struct partitionDesc *pd; struct logicalVolDesc *lvd; struct impUseVolDescImpUse *iuvdiu; size_t len; int fd; int i; char buf[256]; dstring new_lvid[128]; dstring new_vid[32]; dstring new_fsid[32]; dstring new_fullvsid[128]; char new_uuid[17]; dstring new_vsid[128]; int force = 0; int update = 0; int update_pvd = 0; int update_lvd = 0; int update_iuvd = 0; int update_fsd = 0; if (fcntl(0, F_GETFL) < 0 && open("/dev/null", O_RDONLY) < 0) _exit(1); if (fcntl(1, F_GETFL) < 0 && open("/dev/null", O_WRONLY) < 0) _exit(1); if (fcntl(2, F_GETFL) < 0 && open("/dev/null", O_WRONLY) < 0) _exit(1); setlocale(LC_CTYPE, ""); appname = "udflabel"; memset(&disc, 0, sizeof(disc)); disc.flags = FLAG_LOCALE; disc.head = calloc(1, sizeof(struct udf_extent)); disc.tail = disc.head; disc.head->space_type = USPACE; memset(new_lvid, 0, sizeof(new_lvid)); memset(new_vid, 0, sizeof(new_vid)); memset(new_fsid, 0, sizeof(new_fsid)); memset(new_fullvsid, 0, sizeof(new_fullvsid)); memset(new_vsid, 0, sizeof(new_vsid)); new_lvid[0] = 0xFF; new_vid[0] = 0xFF; new_fsid[0] = 0xFF; new_fullvsid[0] = 0xFF; new_uuid[0] = 0; new_vsid[0] = 0xFF; parse_args(argc, argv, &disc, &filename, &force, new_lvid, new_vid, new_fsid, new_fullvsid, new_uuid, new_vsid); if (disc.flags & FLAG_NO_WRITE) printf("Note: Not writing to device, just simulating\n"); if (new_lvid[0] != 0xFF) { update_lvd = 1; update_iuvd = 1; update_fsd = 1; } if (new_vid[0] != 0xFF) update_pvd = 1; if (new_fsid[0] != 0xFF) update_fsd = 1; if (new_uuid[0] || new_vsid[0] != 0xFF || new_fullvsid[0] != 0xFF) update_pvd = 1; if (update_pvd || update_lvd || update_iuvd || update_fsd) update = 1; fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, strerror(errno)); exit(1); } if (update) { int fd2; int flags2; char filename2[64]; const char *error; if (fstat(fd, &stat) != 0) { fprintf(stderr, "%s: Error: Cannot stat device '%s': %s\n", appname, filename, strerror(errno)); exit(1); } if (!(disc.flags & FLAG_NO_WRITE)) flags2 = O_RDWR; else flags2 = O_RDONLY; if (snprintf(filename2, sizeof(filename2), "/proc/self/fd/%d", fd) >= (int)sizeof(filename2)) { fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, strerror(ENAMETOOLONG)); exit(1); } // Re-open block device with O_EXCL mode which fails when device is already mounted if (S_ISBLK(stat.st_mode)) flags2 |= O_EXCL; fd2 = open(filename2, flags2); if (fd2 < 0) { if (errno != ENOENT) { error = (errno != EBUSY) ? strerror(errno) : "Device is busy, maybe mounted?"; fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, error); exit(1); } // Fallback to orignal filename when /proc is not available, but this introduce race condition between stat and open fd2 = open(filename, flags2); if (fd2 < 0) { error = (errno != EBUSY) ? strerror(errno) : "Device is busy, maybe mounted?"; fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, error); exit(1); } } close(fd); fd = fd2; } disc.blksize = get_size(fd); disc.blkssz = get_sector_size(fd); if (read_disc(fd, &disc) < 0) { fprintf(stderr, "%s: Error: Cannot process device '%s' as UDF disk\n", appname, filename); exit(1); } if (!update) { close(fd); if (disc.udf_lvd[0]) lvd = disc.udf_lvd[0]; else if (disc.udf_lvd[1]) lvd = disc.udf_lvd[1]; else { fprintf(stderr, "%s: Error: Logical Volume Descriptor is needed for label\n", appname); exit(1); } len = decode_string(&disc, lvd->logicalVolIdent, buf, sizeof(lvd->logicalVolIdent), sizeof(buf)); if (len == (size_t)-1) { fprintf(stderr, "%s: Error: Cannot decode label from OSTA Unicode dstring\n", appname); exit(1); } fwrite(buf, len, 1, stdout); putchar('\n'); return 0; } printf("Updating device: %s\n", filename); if (!disc.udf_lvid || le32_to_cpu(disc.udf_lvid->integrityType) != LVID_INTEGRITY_TYPE_CLOSE) { fprintf(stderr, "%s: Error: Logical Volume is in inconsistent state\n", appname); exit(1); } if (disc.udf_write_rev > 0x0260) { fprintf(stderr, "%s: Error: Minimal UDF Write Revision is %x.%02x, but udflabel supports only 2.60\n", appname, (unsigned int)(disc.udf_write_rev >> 8), (unsigned int)(disc.udf_write_rev & 0xFF)); exit(1); } if (disc.udf_pd[0]) pd = disc.udf_pd[0]; else if (disc.udf_pd[1]) pd = disc.udf_pd[1]; else { fprintf(stderr, "%s: Error: Both Main and Reserve Partition Descriptor are damaged\n", appname); exit(1); } switch (le32_to_cpu(pd->accessType)) { case PD_ACCESS_TYPE_OVERWRITABLE: case PD_ACCESS_TYPE_REWRITABLE: case PD_ACCESS_TYPE_NONE: /* Pseudo OverWrite */ break; case PD_ACCESS_TYPE_WRITE_ONCE: if (!force && disc.udf_rev < 0x0200) { fprintf(stderr, "%s: Error: Cannot update writeonce partition of UDF revision prior to 2.00\n", appname); exit(1); } if (!force && (new_fullvsid[0] != 0xFF || new_vid[0] != 0xFF)) { fprintf(stderr, "%s: Error: Cannot update --vid, --vsid, --uuid or --fullvid on writeonce partition\n", appname); exit(1); } else if (!force && !disc.vat_block) { fprintf(stderr, "%s: Error: Cannot update writeonce partition without Virtual Allocation Table\n", appname); exit(1); } else if (force) { fprintf(stderr, "%s: Warning: Trying to overwrite writeonce partition\n", appname); } break; case PD_ACCESS_TYPE_READ_ONLY: if (!force) { fprintf(stderr, "%s: Error: Cannot overwrite readonly partition\n", appname); exit(1); } else { fprintf(stderr, "%s: Warning: Trying to overwrite readonly partition\n", appname); } break; default: if (!force) { fprintf(stderr, "%s: Error: Partition Access Type is unknown\n", appname); exit(1); } else { fprintf(stderr, "%s: Warning: Trying to overwrite partition with unknown access type\n", appname); } break; } /* TODO: VAT mode */ if ((le32_to_cpu(pd->accessType) == PD_ACCESS_TYPE_WRITE_ONCE && !force) || (disc.vat && (new_lvid[0] != 0xFF || new_fsid[0] != 0xFF))) { fprintf(stderr, "%s: Error: Updating Virtual Allocation Table is not supported yet\n", appname); exit(1); } if (update_pvd) { if (!disc.udf_pvd[0] || !check_desc(disc.udf_pvd[0], sizeof(*disc.udf_pvd[0]))) { fprintf(stderr, "%s: Error: Main Primary Volume Descriptor is damaged\n", appname); exit(1); } if (!disc.udf_pvd[1] || !check_desc(disc.udf_pvd[1], sizeof(*disc.udf_pvd[1]))) { fprintf(stderr, "%s: Error: Reserve Primary Volume Descriptor is damaged\n", appname); exit(1); } } if ((new_uuid[0] || new_vsid[0] != 0xFF) && new_fullvsid[0] == 0xFF) { if (!new_uuid[0] || new_vsid[0] == 0xFF) { memset(buf, 0, sizeof(buf)); len = gen_uuid_from_vol_set_ident(buf, disc.udf_pvd[0]->volSetIdent, sizeof(disc.udf_pvd[0]->volSetIdent)); if (len < 16) { fprintf(stderr, "%s: Error: First 16 characters of Volume Set Identifier are not hexadecimal lowercase digits\n", appname); fprintf(stderr, "%s: Error: In this case it is needed to specify both --vsid and --uuid\n", appname); exit(1); } if (!new_uuid[0]) memcpy(new_uuid, buf, sizeof(new_uuid)); else if (disc.udf_pvd[0]->volSetIdent[0] == 16) { new_vsid[0] = 16; new_vsid[127] = disc.udf_pvd[0]->volSetIdent[127]-32; memcpy(new_vsid+1, disc.udf_pvd[0]->volSetIdent+1+32, 127-1-32); } else { new_vsid[0] = 8; new_vsid[127] = disc.udf_pvd[0]->volSetIdent[127]-16; memcpy(new_vsid+1, disc.udf_pvd[0]->volSetIdent+1+16, 127-1-16); } } new_fullvsid[0] = new_vsid[0]; if (new_vsid[0] != 16) { new_fullvsid[127] = 16+1; memcpy(new_fullvsid+1, new_uuid, 16); if (new_vsid[127]) { memcpy(new_fullvsid+1+16, new_vsid+1, 127-1-16); new_fullvsid[127] += new_vsid[127]-1; } } else { new_fullvsid[127] = 32+1; for (i = 0; i < 16; ++i) { new_fullvsid[2*i+1] = 0; new_fullvsid[2*i+2] = new_uuid[i]; } if (new_vsid[127]) { memcpy(new_fullvsid+1+32, new_vsid+1, 127-1-32); new_fullvsid[127] += new_vsid[127]-1; } } } if (update_lvd) { if (!disc.udf_lvd[0] || !check_desc(disc.udf_lvd[0], sizeof(*disc.udf_lvd[0]) + le32_to_cpu(disc.udf_lvd[0]->mapTableLength))) { fprintf(stderr, "%s: Error: Main Logical Volume Descriptor is damaged\n", appname); exit(1); } if (!disc.udf_lvd[1] || !check_desc(disc.udf_lvd[1], sizeof(*disc.udf_lvd[1]) + le32_to_cpu(disc.udf_lvd[1]->mapTableLength))) { fprintf(stderr, "%s: Error: Reserve Logical Volume Descriptor is damaged\n", appname); exit(1); } } if (update_iuvd) { if (!disc.udf_iuvd[0] || !check_desc(disc.udf_iuvd[0], sizeof(*disc.udf_iuvd[0]))) { fprintf(stderr, "%s: Error: Main Implementation Use Volume Descriptor is damaged\n", appname); exit(1); } if (!disc.udf_iuvd[1] || !check_desc(disc.udf_iuvd[1], sizeof(*disc.udf_iuvd[1]))) { fprintf(stderr, "%s: Error: Reserve Implementation Use Volume Descriptor is damaged\n", appname); exit(1); } } if (update_fsd) { if (!disc.udf_fsd || !check_desc(disc.udf_fsd, sizeof(*disc.udf_fsd))) { fprintf(stderr, "%s: Error: Main File Set Descriptor is damaged\n", appname); exit(1); } } if (new_lvid[0] != 0xFF) { memset(buf, 0, sizeof(buf)); decode_string(&disc, new_lvid, buf, sizeof(new_lvid), sizeof(buf)); printf("Using new Logical Volume Identifier: %s\n", buf); memcpy(disc.udf_lvd[0]->logicalVolIdent, new_lvid, sizeof(new_lvid)); memcpy(disc.udf_lvd[1]->logicalVolIdent, new_lvid, sizeof(new_lvid)); iuvdiu = (struct impUseVolDescImpUse *)disc.udf_iuvd[0]->impUse; memcpy(iuvdiu->logicalVolIdent, new_lvid, sizeof(new_lvid)); iuvdiu = (struct impUseVolDescImpUse *)disc.udf_iuvd[1]->impUse; memcpy(iuvdiu->logicalVolIdent, new_lvid, sizeof(new_lvid)); memcpy(disc.udf_fsd->logicalVolIdent, new_lvid, sizeof(new_lvid)); } if (new_vid[0] != 0xFF) { memset(buf, 0, sizeof(buf)); decode_string(&disc, new_vid, buf, sizeof(new_vid), sizeof(buf)); printf("Using new Volume Identifier: %s\n", buf); memcpy(disc.udf_pvd[0]->volIdent, new_vid, sizeof(new_vid)); memcpy(disc.udf_pvd[1]->volIdent, new_vid, sizeof(new_vid)); } if (new_fsid[0] != 0xFF) { memset(buf, 0, sizeof(buf)); decode_string(&disc, new_fsid, buf, sizeof(new_fsid), sizeof(buf)); printf("Using new File Set Identifier: %s\n", buf); memcpy(disc.udf_fsd->fileSetIdent, new_fsid, sizeof(new_fsid)); } if (new_fullvsid[0] != 0xFF) { memset(buf, 0, sizeof(buf)); len = gen_uuid_from_vol_set_ident(buf, new_fullvsid, sizeof(new_fullvsid)); printf("Using new UUID: %s\n", buf); memcpy(new_vsid, new_fullvsid, sizeof(new_vsid)); if (len >= 8) { if (len < 16) len = 1; else len = 2; if (new_vsid[127] > new_vsid[0]*len) { new_vsid[127] -= new_vsid[0]*len; memmove(new_vsid + 1, new_vsid + new_vsid[0]*len + 1, new_vsid[127] - 1); } else { new_vsid[0] = 0; } } memset(buf, 0, sizeof(buf)); decode_string(&disc, new_vsid, buf, sizeof(new_vsid), sizeof(buf)); printf("Using new Volume Set Identifier: %s\n", buf); memset(buf, 0, sizeof(buf)); decode_string(&disc, new_fullvsid, buf, sizeof(new_fullvsid), sizeof(buf)); printf("Using new full Volume Set Identifier: %s\n", buf); memcpy(disc.udf_pvd[0]->volSetIdent, new_fullvsid, sizeof(new_fullvsid)); memcpy(disc.udf_pvd[1]->volSetIdent, new_fullvsid, sizeof(new_fullvsid)); } if (update_pvd) { printf("Updating Main Primary Volume Descriptor...\n"); update_desc(disc.udf_pvd[0], sizeof(*disc.udf_pvd[0])); write_desc(fd, &disc, MVDS, TAG_IDENT_PVD, disc.udf_pvd[0]); } if (update_lvd) { printf("Updating Main Logical Volume Descriptor...\n"); update_desc(disc.udf_lvd[0], sizeof(*disc.udf_lvd[0]) + le32_to_cpu(disc.udf_lvd[0]->mapTableLength)); write_desc(fd, &disc, MVDS, TAG_IDENT_LVD, disc.udf_lvd[0]); } if (update_iuvd) { printf("Updating Main Implementation Use Volume Descriptor...\n"); update_desc(disc.udf_iuvd[0], sizeof(*disc.udf_iuvd[0])); write_desc(fd, &disc, MVDS, TAG_IDENT_IUVD, disc.udf_iuvd[0]); } if (update_pvd || update_lvd || update_iuvd) { printf("Synchronizing...\n"); if (!(disc.flags & FLAG_NO_WRITE)) { if (fdatasync(fd) != 0) { fprintf(stderr, "%s: Synchronization failed: %s\n", appname, strerror(errno)); exit(1); } } } if (update_fsd) { printf("Updating File Set Descriptor...\n"); update_desc(disc.udf_fsd, sizeof(*disc.udf_fsd)); write_desc(fd, &disc, PSPACE, TAG_IDENT_FSD, disc.udf_fsd); } if (update_pvd) { printf("Updating Reserve Primary Volume Descriptor...\n"); update_desc(disc.udf_pvd[1], sizeof(*disc.udf_pvd[1])); write_desc(fd, &disc, RVDS, TAG_IDENT_PVD, disc.udf_pvd[1]); } if (update_lvd) { printf("Updating Reserve Logical Volume Descriptor...\n"); update_desc(disc.udf_lvd[1], sizeof(*disc.udf_lvd[1]) + le32_to_cpu(disc.udf_lvd[1]->mapTableLength)); write_desc(fd, &disc, RVDS, TAG_IDENT_LVD, disc.udf_lvd[1]); } if (update_iuvd) { printf("Updating Reserve Implementation Use Volume Descriptor...\n"); update_desc(disc.udf_iuvd[1], sizeof(*disc.udf_iuvd[1])); write_desc(fd, &disc, RVDS, TAG_IDENT_IUVD, disc.udf_iuvd[1]); } printf("Synchronizing...\n"); if (!(disc.flags & FLAG_NO_WRITE)) { if (fdatasync(fd) != 0) { fprintf(stderr, "%s: Synchronization failed: %s\n", appname, strerror(errno)); exit(1); } } printf("Done\n"); return 0; } udftools-2.0/udflabel/Makefile.in0000644000175000017500000005163013221466653013773 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = udflabel$(EXEEXT) subdir = udflabel ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_udflabel_OBJECTS = main.$(OBJEXT) options.$(OBJEXT) \ readdisc.$(OBJEXT) udflabel_OBJECTS = $(am_udflabel_OBJECTS) udflabel_DEPENDENCIES = $(top_builddir)/libudffs/libudffs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(udflabel_SOURCES) DIST_SOURCES = $(udflabel_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udflabel_LDADD = $(top_builddir)/libudffs/libudffs.la udflabel_SOURCES = main.c options.c ../udfinfo/readdisc.c options.h ../udfinfo/readdisc.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu udflabel/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu udflabel/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list udflabel$(EXEEXT): $(udflabel_OBJECTS) $(udflabel_DEPENDENCIES) $(EXTRA_udflabel_DEPENDENCIES) @rm -f udflabel$(EXEEXT) $(AM_V_CCLD)$(LINK) $(udflabel_OBJECTS) $(udflabel_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdisc.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< readdisc.o: ../udfinfo/readdisc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readdisc.o -MD -MP -MF $(DEPDIR)/readdisc.Tpo -c -o readdisc.o `test -f '../udfinfo/readdisc.c' || echo '$(srcdir)/'`../udfinfo/readdisc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readdisc.Tpo $(DEPDIR)/readdisc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../udfinfo/readdisc.c' object='readdisc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readdisc.o `test -f '../udfinfo/readdisc.c' || echo '$(srcdir)/'`../udfinfo/readdisc.c readdisc.obj: ../udfinfo/readdisc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readdisc.obj -MD -MP -MF $(DEPDIR)/readdisc.Tpo -c -o readdisc.obj `if test -f '../udfinfo/readdisc.c'; then $(CYGPATH_W) '../udfinfo/readdisc.c'; else $(CYGPATH_W) '$(srcdir)/../udfinfo/readdisc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readdisc.Tpo $(DEPDIR)/readdisc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../udfinfo/readdisc.c' object='readdisc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readdisc.obj `if test -f '../udfinfo/readdisc.c'; then $(CYGPATH_W) '../udfinfo/readdisc.c'; else $(CYGPATH_W) '$(srcdir)/../udfinfo/readdisc.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/udflabel/Makefile.am0000644000175000017500000000047413221466537013763 00000000000000sbin_PROGRAMS = udflabel udflabel_LDADD = $(top_builddir)/libudffs/libudffs.la udflabel_SOURCES = main.c options.c ../udfinfo/readdisc.c options.h ../udfinfo/readdisc.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include udftools-2.0/udfinfo/0000755000175000017500000000000013221466662011655 500000000000000udftools-2.0/udfinfo/options.h0000644000175000017500000000242613221466537013446 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef OPTIONS_H #define OPTIONS_H struct udf_disc; void parse_args(int, char *[], struct udf_disc *, char **); /* * Command line option token values. * 0x0000-0x00ff Single characters * 0x1000-0x1fff Long switches (no arg) * 0x2000-0x2fff Long settings (arg required) */ #define OPT_HELP 0x1000 #define OPT_LOCALE 0x1001 #define OPT_UNICODE8 0x1002 #define OPT_UNICODE16 0x1003 #define OPT_UTF8 0x1004 #define OPT_BLK_SIZE 0x2000 #define OPT_VAT_BLOCK 0x2001 #endif /* OPTIONS_H */ udftools-2.0/udfinfo/readdisc.h0000644000175000017500000000161313221466537013526 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef READDISC_H #define READDISC_H struct udf_disc; int read_disc(int, struct udf_disc *); #endif /* READDISC_H */ udftools-2.0/udfinfo/options.c0000644000175000017500000000612713221466537013443 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include "libudffs.h" #include "options.h" static struct option long_options[] = { { "help", no_argument, NULL, OPT_HELP }, { "blocksize", required_argument, NULL, OPT_BLK_SIZE }, { "vatblock", required_argument, NULL, OPT_VAT_BLOCK }, { "locale", no_argument, NULL, OPT_LOCALE }, { "u8", no_argument, NULL, OPT_UNICODE8 }, { "u16", no_argument, NULL, OPT_UNICODE16 }, { "utf8", no_argument, NULL, OPT_UTF8 }, { 0, 0, NULL, 0 }, }; static void usage(void) { fprintf(stderr, "udfinfo from " PACKAGE_NAME " " PACKAGE_VERSION "\n" "Usage:\n" "\tudfinfo [--locale|--u8|--u16|--utf8] [-b|--blocksize=block-size] [--vatblock=block] device\n" ); exit(1); } static unsigned long int strtoul_safe(const char *str, int base, int *failed) { char *endptr = NULL; unsigned long int ret; errno = 0; ret = strtoul(str, &endptr, base); *failed = (!*str || *endptr || errno) ? 1 : 0; return ret; } void parse_args(int argc, char *argv[], struct udf_disc *disc, char **filename) { unsigned long int value; int failed; int ret; while ((ret = getopt_long(argc, argv, "b:h", long_options, NULL)) != EOF) { switch (ret) { case OPT_HELP: case 'h': usage(); break; case OPT_BLK_SIZE: case 'b': value = strtoul_safe(optarg, 0, &failed); if (failed || value < 512 || value > 32768 || (value & (value - 1))) { fprintf(stderr, "%s: Error: Invalid value for option --blocksize\n", appname); exit(1); } disc->blocksize = value; break; case OPT_VAT_BLOCK: value = strtoul_safe(optarg, 0, &failed); if (failed || value > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --vatblock\n", appname); exit(1); } disc->vat_block = value; break; case OPT_UNICODE8: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE8; break; case OPT_UNICODE16: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE16; break; case OPT_UTF8: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UTF8; break; case OPT_LOCALE: disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_LOCALE; break; default: usage(); break; } } if (optind+1 != argc) usage(); *filename = argv[optind]; } udftools-2.0/udfinfo/readdisc.c0000644000175000017500000014067713221466537013537 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "libudffs.h" #include "readdisc.h" static int read_offset(int fd, struct udf_disc *disc, void *buf, size_t offset, size_t count, int warn_beyond) { off_t off; ssize_t ret; if (offset + count > (size_t)disc->blocks * disc->blocksize) { if (warn_beyond) fprintf(stderr, "%s: Warning: Trying to read beyond end of disk\n", appname); return -1; } off = lseek(fd, offset, SEEK_SET); if (off != (off_t)-1 && (size_t)off != offset) { errno = EIO; off = (off_t)-1; } if (off == (off_t)-1) { fprintf(stderr, "%s: Warning: lseek failed: %s\n", appname, strerror(errno)); return -1; } ret = read(fd, buf, count); if (ret >= 0 && (size_t)ret != count) { errno = EIO; ret = -1; } if (ret < 0) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno)); return -1; } return 0; } static int read_vrs(int fd, struct udf_disc *disc, int *bea, int *nsr, int *tea) { struct volStructDesc vsd; uint32_t vsd_len; int i; vsd_len = disc->blocksize > 2048 ? disc->blocksize : 2048; *nsr = -1; *bea = -1; *tea = -1; for (i = 0; i < 64; ++i) { if (32768 + i*vsd_len >= 256*disc->blocksize) break; if (read_offset(fd, disc, &vsd, 32768 + i*vsd_len, sizeof(vsd), 0) < 0) break; if (!vsd.stdIdent[0]) break; else if (memcmp(vsd.stdIdent, VSD_STD_ID_BEA01, VSD_STD_ID_LEN) == 0) { if (*bea == -1) { *bea = i; disc->udf_vrs[0] = malloc(sizeof(vsd)); if (!disc->udf_vrs[0]) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } memcpy(disc->udf_vrs[0], &vsd, sizeof(vsd)); } } else if (memcmp(vsd.stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN) == 0 || memcmp(vsd.stdIdent, VSD_STD_ID_NSR03, VSD_STD_ID_LEN) == 0) { if (*nsr == -1) { *nsr = i; disc->udf_vrs[1] = malloc(sizeof(vsd)); if (!disc->udf_vrs[1]) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } memcpy(disc->udf_vrs[1], &vsd, sizeof(vsd)); } } else if (memcmp(vsd.stdIdent, VSD_STD_ID_TEA01, VSD_STD_ID_LEN) == 0) { if (*tea == -1) { *tea = i; disc->udf_vrs[2] = malloc(sizeof(vsd)); if (!disc->udf_vrs[2]) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } memcpy(disc->udf_vrs[2], &vsd, sizeof(vsd)); } } else if (memcmp(vsd.stdIdent, VSD_STD_ID_BOOT2, VSD_STD_ID_LEN) != 0 && memcmp(vsd.stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN) != 0 && memcmp(vsd.stdIdent, VSD_STD_ID_CDW02, VSD_STD_ID_LEN) != 0) break; } if (i == 64) fprintf(stderr, "%s: Warning: Too many Volume Sequence Descriptors in Volume Recognition Sequence, stopping scanning\n", appname); if (*nsr == -1) return -2; return 0; } static void setup_blocks(struct udf_disc *disc) { uint64_t blocks = disc->blksize / disc->blocksize; if (blocks > UINT32_MAX) disc->blocks = UINT32_MAX; else disc->blocks = (uint32_t)blocks; disc->head->blocks = disc->blocks; } static void setup_vrs(struct udf_disc *disc, int bea, int nsr, int tea) { int max; struct udf_extent *ext; max = tea; if (max < nsr) max = nsr; if (max < bea) max = bea; if (disc->blocksize >= 2048) ext = set_extent(disc, VRS, 32768 / disc->blocksize, max+1); else ext = set_extent(disc, VRS, 32768 / disc->blocksize, ((2048 * (max+1)) + disc->blocksize - 1) / disc->blocksize); if (disc->blocksize >= 2048) { set_desc(ext, 0x00, nsr, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[1], sizeof(struct volStructDesc))); if (bea != -1) set_desc(ext, 0x00, bea, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[0], sizeof(struct volStructDesc))); if (tea != -1) set_desc(ext, 0x00, tea, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[2], sizeof(struct volStructDesc))); } else { set_desc(ext, 0x00, nsr * 2048 / disc->blocksize, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[1], sizeof(struct volStructDesc))); if (bea != -1) set_desc(ext, 0x00, bea * 2048 / disc->blocksize, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[0], sizeof(struct volStructDesc))); if (tea != -1) set_desc(ext, 0x00, tea * 2048 / disc->blocksize, sizeof(struct volStructDesc), alloc_data(disc->udf_vrs[2], sizeof(struct volStructDesc))); } } static int read_anchor_i(int fd, struct udf_disc *disc, int i, uint32_t location) { struct anchorVolDescPtr avdp; struct udf_extent *ext; if (read_offset(fd, disc, &avdp, (size_t)location * disc->blocksize, sizeof(avdp), 1) < 0) return -2; if (le32_to_cpu(avdp.descTag.tagLocation) != location) return -2; if (le16_to_cpu(avdp.descTag.tagIdent) != TAG_IDENT_AVDP) return -2; disc->udf_anchor[i] = malloc(sizeof(avdp)); if (!disc->udf_anchor[i]) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } memcpy(disc->udf_anchor[i], &avdp, sizeof(avdp)); ext = set_extent(disc, ANCHOR, location, 1); set_desc(ext, TAG_IDENT_AVDP, 0, sizeof(avdp), alloc_data(disc->udf_anchor[i], sizeof(avdp))); return 0; } static int read_anchor_first(int fd, struct udf_disc *disc) { return read_anchor_i(fd, disc, 0, 256); } static int read_anchor_second(int fd, struct udf_disc *disc) { int ret1, ret2; if (disc->blocks > 257 && (size_t)(disc->blocks - 257) * disc->blocksize > (size_t)32768 + disc->blocksize && disc->blocks - 257 != 256) ret1 = read_anchor_i(fd, disc, 1, disc->blocks - 257); else ret1 = -2; if (ret1 == -1) return -1; if ((size_t)(disc->blocks - 1) * disc->blocksize > (size_t)32768 + disc->blocksize && disc->blocks - 1 != 256) ret2 = read_anchor_i(fd, disc, 2, disc->blocks - 1); else ret2 = -2; if (ret2 == -1) return -1; if (disc->udf_anchor[0]) return 0; if (ret1 < 0 && ret2 < 0) return -2; if (ret2 < 0) fprintf(stderr, "%s: Warning: First and third Anchor Volume Descriptor Pointer not found, using second\n", appname); else if (ret1 < 0) fprintf(stderr, "%s: Warning: First and second Anchor Volume Descriptor Pointer not found, using third\n", appname); else fprintf(stderr, "%s: Warning: First Anchor Volume Descriptor Pointer not found, using second\n", appname); return 0; } static int read_anchor_512(int fd, struct udf_disc *disc) { int ret; ret = read_anchor_i(fd, disc, 0, 512); if (ret == 0) fprintf(stderr, "%s: Warning: First, second and third Anchor Volume Descriptor Pointer not found, but found on sector 512, using it\n", appname); return ret; } static int detect_vrs_and_anchor(int fd, struct udf_disc *disc, int id, int *found_vrs, int *vsd_2048_valid, int *bea, int *nsr, int *tea) { int ret; if (disc->blocksize <= 2048 && *vsd_2048_valid == 0) return -2; setup_blocks(disc); if (disc->blocksize > 2048 || *vsd_2048_valid == -1) { free(disc->udf_vrs[0]); free(disc->udf_vrs[1]); free(disc->udf_vrs[2]); disc->udf_vrs[0] = NULL; disc->udf_vrs[1] = NULL; disc->udf_vrs[2] = NULL; ret = read_vrs(fd, disc, bea, nsr, tea); if (ret == -2) { if (disc->blocksize <= 2048) *vsd_2048_valid = 0; return -3; } else if (ret < 0) return ret; if (disc->blocksize <= 2048) *vsd_2048_valid = 1; *found_vrs = 1; } if (id == 0) return read_anchor_first(fd, disc); else if (id == 1) return read_anchor_second(fd, disc); else if (id == 2) return read_anchor_512(fd, disc); { fprintf(stderr, "%s: Error: Wrong Anchor type\n", appname); exit(1); } } static int detect_udf(int fd, struct udf_disc *disc) { int ret, ret2; int bea, nsr, tea; int bea_2048 = -1, nsr_2048 = -1, tea_2048 = -1; int vsd_2048_valid = -1; int found_vrs = 0; if (disc->blocksize) { if (disc->blksize / disc->blocksize > UINT32_MAX) fprintf(stderr, "%s: Warning: Disk is too big (%llu), using only %lu blocks\n", appname, (unsigned long long int)(disc->blksize / disc->blocksize), (unsigned long int)UINT32_MAX); setup_blocks(disc); ret = read_vrs(fd, disc, &bea, &nsr, &tea); if (ret < 0) { if (ret == -2) fprintf(stderr, "%s: Error: UDF Volume Recognition Sequence not found\n", appname); return -1; } ret = read_anchor_first(fd, disc); ret2 = read_anchor_second(fd, disc); if (ret < 0 && ret2 < 0) { if (ret == -2 || ret2 == -2) { ret = read_anchor_512(fd, disc); if (ret < 0) { fprintf(stderr, "%s: Error: UDF Volume Recognition Sequence found but not Anchor Volume Descriptor Pointer, maybe wrong --blocksize?\n", appname); return -1; } } else return -1; } setup_vrs(disc, bea, nsr, tea); return 0; } else if (disc->blkssz) { disc->blocksize = disc->blkssz; setup_blocks(disc); ret = read_vrs(fd, disc, &bea, &nsr, &tea); if (ret != -2) { if (ret != 0) return -1; ret = read_anchor_first(fd, disc); ret2 = read_anchor_second(fd, disc); if (ret == 0 || ret2 == 0) { setup_vrs(disc, bea, nsr, tea); return 0; } else if (ret == -2 || ret2 == -2) { ret = read_anchor_512(fd, disc); if (ret < 0 && ret != -2) return -1; else if (ret == 0) return 0; } else return -1; } } for (disc->blocksize = 512; disc->blocksize <= 32768; disc->blocksize *= 2) { if (disc->blocksize <= 2048 && vsd_2048_valid) { bea = bea_2048; nsr = nsr_2048; tea = tea_2048; } ret = detect_vrs_and_anchor(fd, disc, 0, &found_vrs, &vsd_2048_valid, &bea, &nsr, &tea); if (disc->blocksize <= 2048 && vsd_2048_valid) { bea_2048 = bea; nsr_2048 = nsr; tea_2048 = tea; } if (ret == -3 || ret == -2) continue; else if (ret < 0) return ret; ret = read_anchor_second(fd, disc); if (ret == -1) return -1; break; } if (disc->blocksize > 32768) { for (disc->blocksize = 512; disc->blocksize <= 32768; disc->blocksize *= 2) { ret = detect_vrs_and_anchor(fd, disc, 1, &found_vrs, &vsd_2048_valid, &bea, &nsr, &tea); if (ret == -3 || ret == -2) continue; else if (ret < 0) return ret; break; } if (disc->blocksize > 32768) { for (disc->blocksize = 512; disc->blocksize <= 32768; disc->blocksize *= 2) { ret = detect_vrs_and_anchor(fd, disc, 2, &found_vrs, &vsd_2048_valid, &bea, &nsr, &tea); if (ret == -3 || ret == -2) continue; else if (ret < 0) return ret; break; } if (disc->blocksize > 32768) { if (found_vrs) fprintf(stderr, "%s: Error: UDF Volume Recognition Sequence found but not Anchor Volume Descriptor Pointer, maybe wrong --blocksize?\n", appname); else fprintf(stderr, "%s: Error: UDF Volume Recognition Sequence not found\n", appname); return -1; } } } if (disc->blksize / disc->blocksize > UINT32_MAX) fprintf(stderr, "%s: Warning: Disk is too big (%llu), using only %lu blocks\n", appname, (unsigned long long int)(disc->blksize / disc->blocksize), (unsigned long int)UINT32_MAX); if (disc->blkssz && disc->blkssz != disc->blocksize) fprintf(stderr, "%s: Warning: Disk logical sector size (%d) does not match UDF block size (%u)\n", appname, disc->blkssz, (unsigned int)disc->blocksize); if (disc->blocksize <= 2048) { bea = bea_2048; nsr = nsr_2048; tea = tea_2048; } setup_vrs(disc, bea, nsr, tea); return 0; } static void read_mbr(int fd, struct udf_disc *disc) { struct mbr mbr; if (read_offset(fd, disc, &mbr, 0, sizeof(mbr), 1) < 0) return; if (le16_to_cpu(mbr.boot_signature) != MBR_BOOT_SIGNATURE) return; set_extent(disc, MBR, 0, 1); } static int choose_anchor(struct udf_disc *disc) { if (disc->udf_anchor[0]) return 0; else if (disc->udf_anchor[1]) return 1; else if (disc->udf_anchor[2]) return 2; else return -1; } static int scan_vds(int fd, struct udf_disc *disc, enum udf_space_type vds_type) { uint32_t location, length, count, i; uint32_t next_vdp_num, next_location, next_length, next_count; uint16_t type, udf_rev_le16; size_t gd_length; struct genericDesc *gd_ptr; struct udf_extent *ext; struct volDescPtr *vdp; struct logicalVolDesc *lvd; struct unallocSpaceDesc *usd; unsigned char buffer[512]; int id, anchor; int nested; anchor = choose_anchor(disc); if (anchor == -1) return -2; if (vds_type == MVDS) { next_location = le32_to_cpu(disc->udf_anchor[anchor]->mainVolDescSeqExt.extLocation); next_length = le32_to_cpu(disc->udf_anchor[anchor]->mainVolDescSeqExt.extLength) & EXT_LENGTH_MASK; id = 0; } else if (vds_type == RVDS) { next_location = le32_to_cpu(disc->udf_anchor[anchor]->reserveVolDescSeqExt.extLocation); next_length = le32_to_cpu(disc->udf_anchor[anchor]->reserveVolDescSeqExt.extLength) & EXT_LENGTH_MASK; id = 1; } else { fprintf(stderr, "%s: Error: Wrong Volume Descriptor Sequence type\n", appname); exit(1); } next_count = next_length / disc->blocksize; if (!next_location || !next_count) return -2; nested = 0; next_vdp_num = 0; while (next_location && next_count) { if (++nested > 64) { fprintf(stderr, "%s: Warning: Too many nested Volume Descriptor Sequences, stopping scanning\n", appname); break; } location = next_location; length = next_length; count = next_count; next_location = 0; next_length = 0; next_count = 0; ext = set_extent(disc, vds_type, location, count); if (count > 256) length = 256 * disc->blocksize; for (i = 0; i < count; ++i) { if (count >= 256) { fprintf(stderr, "%s: Warning: Too many descriptors (%lu) in Volume Descriptor Sequence, stopping scanning\n", appname, (long unsigned int)count); break; } if (read_offset(fd, disc, &buffer, ((size_t)location+i) * disc->blocksize, sizeof(buffer), 1) < 0) return -3; gd_ptr = (struct genericDesc *)&buffer; type = le16_to_cpu(gd_ptr->descTag.tagIdent); if (type == 0) break; if (le32_to_cpu(gd_ptr->descTag.tagLocation) != location+i) { fprintf(stderr, "%s: Warning: Incorrect Volume Descriptor\n", appname); return -3; } switch (type) { case TAG_IDENT_PVD: case TAG_IDENT_PD: case TAG_IDENT_IUVD: case TAG_IDENT_TD: case TAG_IDENT_VDP: default: gd_ptr = malloc(sizeof(buffer)); if (!gd_ptr) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } memcpy(gd_ptr, &buffer, sizeof(buffer)); set_desc(ext, type, i, sizeof(buffer), alloc_data(gd_ptr, sizeof(buffer))); if (type == TAG_IDENT_PVD && (!disc->udf_pvd[id] || le32_to_cpu(disc->udf_pvd[id]->volDescSeqNum) < le32_to_cpu(gd_ptr->volDescSeqNum))) disc->udf_pvd[id] = (struct primaryVolDesc *)gd_ptr; else if (type == TAG_IDENT_PD && (!disc->udf_pd[id] || le32_to_cpu(disc->udf_pd[id]->volDescSeqNum) < le32_to_cpu(gd_ptr->volDescSeqNum))) disc->udf_pd[id] = (struct partitionDesc *)gd_ptr; else if (type == TAG_IDENT_IUVD && (!disc->udf_iuvd[id] || le32_to_cpu(disc->udf_iuvd[id]->volDescSeqNum) < le32_to_cpu(gd_ptr->volDescSeqNum))) disc->udf_iuvd[id] = (struct impUseVolDesc *)gd_ptr; else if (type == TAG_IDENT_TD && !disc->udf_td[id]) disc->udf_td[id] = (struct terminatingDesc *)gd_ptr; else if (type == TAG_IDENT_VDP) { vdp = (struct volDescPtr *)gd_ptr; if (next_vdp_num < le32_to_cpu(vdp->volDescSeqNum)) { next_location = le32_to_cpu(vdp->nextVolDescSeqExt.extLocation); if (next_location <= location) { fprintf(stderr, "%s: Warning: Next descriptor in Volume Descriptor Sequence is not on higher block number, ignoring it\n", appname); next_location = 0; } else { next_vdp_num = le32_to_cpu(vdp->volDescSeqNum); next_length = le32_to_cpu(vdp->nextVolDescSeqExt.extLength) & EXT_LENGTH_MASK; next_count = next_length / disc->blocksize; } } } else fprintf(stderr, "%s: Warning: Unknown descriptor in Volume Descriptor Sequence\n", appname); break; case TAG_IDENT_LVD: lvd = (struct logicalVolDesc *)gd_ptr; gd_length = sizeof(*lvd) + le32_to_cpu(lvd->mapTableLength); if (i*disc->blocksize + gd_length > length || gd_length > 256*disc->blocksize) { fprintf(stderr, "%s: Warning: Logical Volume Descriptor is too big (%llu)\n", appname, (unsigned long long int)(i*disc->blocksize + gd_length)); i = count-1; break; } lvd = malloc(gd_length); if (!lvd) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } if (gd_length <= sizeof(buffer)) memcpy(lvd, &buffer, gd_length); else { memcpy(lvd, &buffer, sizeof(buffer)); errno = 0; if (read(fd, (void *)lvd + sizeof(buffer), gd_length - sizeof(buffer)) != (ssize_t)(gd_length - sizeof(buffer))) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); free(lvd); return -3; } } set_desc(ext, TAG_IDENT_LVD, i, gd_length, alloc_data(lvd, gd_length)); if (gd_length > disc->blocksize) i += (gd_length + (disc->blocksize-1)) / disc->blocksize - 1; if (!disc->udf_lvd[id] || le32_to_cpu(disc->udf_lvd[id]->volDescSeqNum) < le32_to_cpu(lvd->volDescSeqNum)) { disc->udf_lvd[id] = lvd; if (strncmp((char *)disc->udf_lvd[id]->domainIdent.ident, UDF_ID_COMPLIANT, sizeof(disc->udf_lvd[id]->domainIdent.ident)) == 0) { memcpy(&udf_rev_le16, disc->udf_lvd[id]->domainIdent.identSuffix, sizeof(udf_rev_le16)); disc->udf_rev = le16_to_cpu(udf_rev_le16); disc->udf_write_rev = disc->udf_rev; } } if (le32_to_cpu(lvd->logicalBlockSize) != disc->blocksize) fprintf(stderr, "%s: Warning: blocksize in Logical Volume Descriptor is different as expected\n", appname); break; case TAG_IDENT_USD: usd = (struct unallocSpaceDesc *)&buffer; gd_length = sizeof(*usd) + le32_to_cpu(usd->numAllocDescs) * sizeof(*usd->allocDescs); if (i*disc->blocksize + gd_length > length || gd_length > 256*disc->blocksize) { fprintf(stderr, "%s: Warning: Unallocated Space Descriptor is too big (%llu)\n", appname, (unsigned long long int)(i*disc->blocksize + gd_length)); i = count-1; break; } usd = malloc(gd_length); if (!usd) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return -1; } if (gd_length <= sizeof(buffer)) memcpy(usd, &buffer, gd_length); else { memcpy(usd, &buffer, sizeof(buffer)); errno = 0; if (read(fd, (void *)usd + sizeof(buffer), gd_length - sizeof(buffer)) != (ssize_t)(gd_length - sizeof(buffer))) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); free(usd); return -3; } } set_desc(ext, TAG_IDENT_USD, i, gd_length, alloc_data(usd, gd_length)); if (gd_length > disc->blocksize) i += (gd_length + (disc->blocksize-1)) / disc->blocksize - 1; if (!disc->udf_usd[id] || le32_to_cpu(disc->udf_usd[id]->volDescSeqNum) < le32_to_cpu(usd->volDescSeqNum)) disc->udf_usd[id] = usd; break; } if (type == TAG_IDENT_TD) break; } } return 0; } static void scan_mvds(int fd, struct udf_disc *disc) { int ret; ret = scan_vds(fd, disc, MVDS); if (ret == -2) fprintf(stderr, "%s: Warning: Main Volume Descriptor Sequence not found\n", appname); else if (ret == -3) fprintf(stderr, "%s: Warning: Main Volume Descriptor Sequence is damaged\n", appname); } static void scan_rvds(int fd, struct udf_disc *disc) { int ret; ret = scan_vds(fd, disc, RVDS); if (ret == -2) fprintf(stderr, "%s: Warning: Reserve Volume Descriptor Sequence not found\n", appname); else if (ret == -3) fprintf(stderr, "%s: Warning: Reserve Volume Descriptor Sequence is damaged\n", appname); } static void scan_lvis(int fd, struct udf_disc *disc) { uint32_t location, length; uint32_t next_location, next_length; uint16_t type; size_t lvid_length; unsigned char buffer[512]; struct udf_extent *ext; struct logicalVolIntegrityDesc *lvid; tag *descTag; int id; int scanned; if (disc->udf_lvd[0]) id = 0; else if (disc->udf_lvd[1]) id = 1; else return; location = le32_to_cpu(disc->udf_lvd[id]->integritySeqExt.extLocation); length = le32_to_cpu(disc->udf_lvd[id]->integritySeqExt.extLength) & EXT_LENGTH_MASK; scanned = 0; while (location && length) { if (length > 256*disc->blocksize) { fprintf(stderr, "%s: Warning: Logical Volume Integrity Descriptor Sequence is too big (%lu)\n", appname, (unsigned long int)length); break; } if (read_offset(fd, disc, &buffer, (size_t)location * disc->blocksize, sizeof(buffer), 1) < 0) return; descTag = (tag *)&buffer; type = le16_to_cpu(descTag->tagIdent); if (type == 0) break; if (le32_to_cpu(descTag->tagLocation) != location) { fprintf(stderr, "%s: Warning: Incorrect Logical Volume Integrity Descriptor\n", appname); break; } if (type == TAG_IDENT_TD) break; if (type != TAG_IDENT_LVID) { fprintf(stderr, "%s: Warning: Incorrect Logical Volume Integrity Descriptor\n", appname); break; } lvid = (struct logicalVolIntegrityDesc *)buffer; if (le32_to_cpu(lvid->numOfPartitions) > 32) { fprintf(stderr, "%s: Warning: Too many partitions (%lu) in Logical Volume Integrity Descriptor, stopping scanning\n", appname, (unsigned long int)le32_to_cpu(lvid->numOfPartitions)); break; } if (le32_to_cpu(lvid->lengthOfImpUse) > 32*disc->blocksize) { fprintf(stderr, "%s: Warning: Logical Volume Integrity Descriptor Implementation Use is too big (%lu), stopping scanning\n", appname, (unsigned long int)le32_to_cpu(lvid->lengthOfImpUse)); break; } lvid_length = sizeof(*lvid) + le32_to_cpu(lvid->numOfPartitions) * 2 * sizeof(uint32_t) + le32_to_cpu(lvid->lengthOfImpUse); if (lvid_length > length) { fprintf(stderr, "%s: Warning: Incorrect Logical Volume Integrity Descriptor\n", appname); break; } lvid = malloc(lvid_length); if (!lvid) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); break; } if (lvid_length <= sizeof(buffer)) memcpy(lvid, &buffer, lvid_length); else { memcpy(lvid, &buffer, sizeof(buffer)); errno = 0; if (read(fd, (void *)lvid + sizeof(buffer), lvid_length - sizeof(buffer)) != (ssize_t)(lvid_length - sizeof(buffer))) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); free(lvid); break; } } ext = set_extent(disc, LVID, location, (lvid_length + disc->blocksize-1) / disc->blocksize); set_desc(ext, TAG_IDENT_LVID, 0, lvid_length, alloc_data(lvid, lvid_length)); disc->udf_lvid = lvid; next_location = le32_to_cpu(lvid->nextIntegrityExt.extLocation); next_length = le32_to_cpu(lvid->nextIntegrityExt.extLength) & EXT_LENGTH_MASK; if (next_length && next_location <= location) { fprintf(stderr, "%s: Warning: Next Logical Volume Integrity is not on higher block number, ignoring it\n", appname); next_length = 0; } if (next_location && next_length) { location = next_location; length = next_length; } else if (length > disc->blocksize) { ++location; length -= disc->blocksize; } else { length = 0; } if (length > 0 && ++scanned >= 1000) { fprintf(stderr, "%s: Warning: Too many Logical Volume Integrity Descriptors, stopping scanning\n", appname); break; } } } static void parse_lvidiu(struct udf_disc *disc) { struct logicalVolIntegrityDescImpUse *lvidiu; if (!disc->udf_lvid || disc->udf_lvid->lengthOfImpUse < sizeof(*lvidiu)) { fprintf(stderr, "%s: Warning: Logical Volume Integrity Descriptor Implementation Use not found\n", appname); return; } lvidiu = (struct logicalVolIntegrityDescImpUse *)&(disc->udf_lvid->impUse[le32_to_cpu(disc->udf_lvid->numOfPartitions) * 2 * sizeof(uint32_t)]); disc->udf_rev = le16_to_cpu(lvidiu->minUDFReadRev); disc->udf_write_rev = le16_to_cpu(lvidiu->minUDFWriteRev); disc->num_files = le32_to_cpu(lvidiu->numFiles); disc->num_dirs = le32_to_cpu(lvidiu->numDirs); } static struct genericPartitionMap *find_partition(struct udf_disc *disc, uint8_t type, const char *ident) { uint32_t i, offset; struct genericPartitionMap *pmap; struct udfPartitionMap2 *upm2; int id; if (disc->udf_lvd[0]) id = 0; else if (disc->udf_lvd[1]) id = 1; else return NULL; offset = 0; for (i = 0; i < le32_to_cpu(disc->udf_lvd[id]->numPartitionMaps); ++i) { if (offset >= le32_to_cpu(disc->udf_lvd[id]->mapTableLength)) return NULL; pmap = (struct genericPartitionMap *)&disc->udf_lvd[id]->partitionMaps[offset]; if (pmap->partitionMapType == type) { if (!ident) return pmap; upm2 = (struct udfPartitionMap2 *)pmap; if (strncmp((char *)upm2->partIdent.ident, ident, sizeof(upm2->partIdent.ident)) == 0) return pmap; } offset += pmap->partitionMapLength; } return NULL; } static struct genericPartitionMap *get_partition(struct udf_disc *disc, int id, uint16_t partition) { uint16_t i; uint32_t offset; struct genericPartitionMap *pmap; if (partition >= le32_to_cpu(disc->udf_lvd[id]->numPartitionMaps)) return NULL; offset = 0; for (i = 0; i <= partition; ++i) { if (offset >= le32_to_cpu(disc->udf_lvd[id]->mapTableLength)) return NULL; pmap = (struct genericPartitionMap *)&disc->udf_lvd[id]->partitionMaps[offset]; offset += pmap->partitionMapLength; } if (offset > le32_to_cpu(disc->udf_lvd[id]->mapTableLength)) return NULL; return pmap; } static uint32_t find_block_position(struct udf_disc *disc, struct genericPartitionMap *pmap, uint32_t block) { struct udfPartitionMap2 *upm2; struct sparablePartitionMap *spm; uint8_t count, i; uint16_t packet_len, num, j; uint32_t location, packet, offset; if (pmap->partitionMapType == GP_PARTITION_MAP_TYPE_1) return block; else if (pmap->partitionMapType == GP_PARTITION_MAP_TYPE_2) { upm2 = (struct udfPartitionMap2 *)pmap; if (strncmp((char *)upm2->partIdent.ident, UDF_ID_VIRTUAL, sizeof(upm2->partIdent.ident)) == 0) { if (!disc->vat) return UINT32_MAX; else if (block < disc->vat_entries) return disc->vat[block]; else return block; } else if (strncmp((char *)upm2->partIdent.ident, UDF_ID_SPARABLE, sizeof(upm2->partIdent.ident)) == 0) { spm = (struct sparablePartitionMap *)upm2; count = spm->numSparingTables; packet_len = le16_to_cpu(spm->packetLength); packet = block & ~(packet_len-1); offset = block & (packet_len-1); for (i = 0; i < count; ++i) { if (!disc->udf_stable[i]) continue; num = le16_to_cpu(disc->udf_stable[i]->reallocationTableLen); for (j = 0; j < num; ++j) { location = le32_to_cpu(disc->udf_stable[i]->mapEntry[j].origLocation); if (location >= 0xFFFFFFF0) break; else if (location == packet) return le32_to_cpu(disc->udf_stable[i]->mapEntry[j].mappedLocation) + offset; else if (location > packet) break; } } return block; } else if (strncmp((char *)upm2->partIdent.ident, UDF_ID_METADATA, sizeof(upm2->partIdent.ident)) == 0) { /* TODO: Add support for Metadata */ fprintf(stderr, "%s: Warning: Metadata Partition Map is not supported\n", appname); return UINT32_MAX; } else { fprintf(stderr, "%s: Warning: Unknown Type 2 Partition Map\n", appname); return UINT32_MAX; } } else { fprintf(stderr, "%s: Warning: Unknown Partition Map\n", appname); return UINT32_MAX; } } static void read_stable(int fd, struct udf_disc *disc) { size_t st_len; uint8_t count, i; uint16_t packet_len, num, j; uint32_t location, length; unsigned char buffer[512]; struct sparablePartitionMap *spm; struct sparingTable *st; struct udf_extent *ext; spm = (struct sparablePartitionMap *)find_partition(disc, GP_PARTITION_MAP_TYPE_2, UDF_ID_SPARABLE); if (!spm) return; count = spm->numSparingTables; if (count > 4) { fprintf(stderr, "%s: Warning: Too many Sparing Tables\n", appname); return; } length = le32_to_cpu(spm->sizeSparingTable); packet_len = le16_to_cpu(spm->packetLength); for (i = 0; i < count; ++i) { location = le32_to_cpu(spm->locSparingTable[i]); if (read_offset(fd, disc, &buffer, (size_t)location * disc->blocksize, sizeof(buffer), 1) < 0) return; st = (struct sparingTable *)&buffer; if (le16_to_cpu(st->descTag.tagIdent) != 0 || le32_to_cpu(st->descTag.tagLocation) != location) { fprintf(stderr, "%s: Warning: Invalid Sparing Table\n", appname); return; } if (st->sparingIdent.flags != 0 || strncmp((char *)st->sparingIdent.ident, UDF_ID_SPARING, sizeof(st->sparingIdent.ident)) != 0) continue; num = le16_to_cpu(st->reallocationTableLen); st_len = sizeof(*st) + num * sizeof(struct sparingEntry); if (st_len > length) { fprintf(stderr, "%s: Warning: Sparing Table is too big (%llu)\n", appname, (unsigned long long int)st_len); return; } disc->udf_stable[i] = malloc(st_len); if (!disc->udf_stable[i]) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return; } if (st_len <= sizeof(buffer)) memcpy(disc->udf_stable[i], &buffer, st_len); else { memcpy(disc->udf_stable[i], &buffer, sizeof(buffer)); errno = 0; if (read(fd, (void *)disc->udf_stable[i] + sizeof(buffer), st_len - sizeof(buffer)) != (ssize_t)(st_len - sizeof(buffer))) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); free(disc->udf_stable[i]); disc->udf_stable[i] = NULL; return; } } set_extent(disc, STABLE, location, (length + disc->blocksize-1) / disc->blocksize); for (j = 0; j < num; ++j) { location = le32_to_cpu(disc->udf_stable[i]->mapEntry[j].mappedLocation); ext = set_extent(disc, SSPACE, location, packet_len); if (ext->prev && ext->prev->space_type == SSPACE) { ext->prev->blocks = packet_len + location - ext->prev->start; ext->prev->next = ext->next; if (ext->next) ext->next->prev = ext->prev; free(ext); } } } } static void read_vat(int fd, struct udf_disc *disc) { long last; uint32_t i, vat_block; uint32_t length, offset, location; struct stat st; struct fileEntry *fe; struct extendedFileEntry *efe; struct virtualAllocationTable15 *vat15; struct virtualAllocationTable20 *vat20; unsigned char *vat; unsigned char buffer[512]; int id; if (disc->udf_pd[0]) id = 0; else if (disc->udf_pd[1]) id = 1; else return; location = le32_to_cpu(disc->udf_pd[id]->partitionStartingLocation); if (!find_partition(disc, GP_PARTITION_MAP_TYPE_2, UDF_ID_VIRTUAL)) return; if (disc->vat_block) vat_block = disc->vat_block; else if (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, CDROM_LAST_WRITTEN, &last) == 0) vat_block = last; else vat_block = disc->blocks - 1; for (i = vat_block + 3; i > 0 && i > vat_block - 32; --i) { if (read_offset(fd, disc, &buffer, (size_t)i * disc->blocksize, sizeof(buffer), 0) < 0) continue; fe = (struct fileEntry *)&buffer; if (le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_FE && le16_to_cpu(fe->descTag.tagIdent) != TAG_IDENT_EFE) continue; if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_UNDEF && fe->icbTag.fileType != ICBTAG_FILE_TYPE_VAT20) continue; if (location + le32_to_cpu(fe->descTag.tagLocation) != i) { fprintf(stderr, "%s: Warning: Found Virtual Allocation Table at partition offset %u (block %u), but expected at offset %u, ignoring it\n", appname, (unsigned int)(i-location), (unsigned int)i, (unsigned int)(le32_to_cpu(fe->descTag.tagLocation))); continue; } if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) != ICBTAG_FLAG_AD_IN_ICB) { fprintf(stderr, "%s: Warning: Reading Virtual Allocation Table outside of Information Control Block is not supported yet\n", appname); break; } if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) { offset = sizeof(*fe) + le32_to_cpu(fe->lengthExtendedAttr); length = le32_to_cpu(fe->lengthAllocDescs); } else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE) { efe = (struct extendedFileEntry *)&buffer; offset = sizeof(*efe) + le32_to_cpu(efe->lengthExtendedAttr); length = le32_to_cpu(efe->lengthAllocDescs); } else continue; if (le64_to_cpu(fe->informationLength) > length) { fprintf(stderr, "%s: Warning: Virtual Allocation Table inside of Information Control Block is larger then allocated block\n", appname); break; } length = le64_to_cpu(fe->informationLength); if (length < 36) { fprintf(stderr, "%s: Warning: Virtual Allocation Table is too small\n", appname); break; } if (offset+length > disc->blocksize) { fprintf(stderr, "%s: Warning: Virtual Allocation Table inside of Information Control Block is larger then block size\n", appname); break; } vat = malloc(length); if (!vat) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); break; } if (read_offset(fd, disc, vat, (size_t)i * disc->blocksize + offset, length, 1) < 0) { free(vat); break; } if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_UNDEF) { vat15 = (struct virtualAllocationTable15 *)(vat + ((length - 36) / 4) * 4); if (strncmp((const char *)vat15->vatIdent.ident, UDF_ID_ALLOC, sizeof(vat15->vatIdent.ident)) != 0) { fprintf(stderr, "%s: Warning: Virtual Allocation Table is damaged\n", appname); free(vat); break; } disc->vat = (uint32_t *)vat; disc->vat_entries = (length - 36) / 4; } else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_VAT20) { vat20 = (struct virtualAllocationTable20 *)vat; if (vat20->lengthHeader < sizeof(*vat20) || vat20->lengthHeader != sizeof(*vat20) + vat20->lengthImpUse || vat20->lengthHeader > length) { fprintf(stderr, "%s: Warning: Virtual Allocation Table is damaged\n", appname); free(vat); break; } if (disc->udf_lvd[0]) memcpy(disc->udf_lvd[0]->logicalVolIdent, vat20->logicalVolIdent, sizeof(vat20->logicalVolIdent)); if (disc->udf_lvd[1]) memcpy(disc->udf_lvd[1]->logicalVolIdent, vat20->logicalVolIdent, sizeof(vat20->logicalVolIdent)); if (disc->udf_lvid) { disc->udf_rev = le16_to_cpu(vat20->minUDFReadRev); disc->udf_write_rev = le16_to_cpu(vat20->minUDFWriteRev); disc->num_files = le32_to_cpu(vat20->numFiles); disc->num_dirs = le32_to_cpu(vat20->numDirs); } disc->vat = (uint32_t *)(vat + vat20->lengthHeader); disc->vat_entries = (length - vat20->lengthHeader) / 4; } else { free(vat); continue; } disc->vat_block = i; if (disc->udf_lvid) disc->udf_lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); if (i != vat_block) fprintf(stderr, "%s: Note: Found Virtual Allocation Table at block %u (expected at block %u)\n", appname, (unsigned int)i, (unsigned int)vat_block); return; } fprintf(stderr, "%s: Error: Virtual Allocation Table not found, maybe wrong --vatblock?\n", appname); } static void setup_pspace(struct udf_disc *disc) { struct udf_extent *ext, *new_ext; uint32_t location, blocks; int id; if (disc->udf_pd[0]) id = 0; else if (disc->udf_pd[1]) id = 1; else { fprintf(stderr, "%s: Warning: Partition Space not found\n", appname); return; } location = le32_to_cpu(disc->udf_pd[id]->partitionStartingLocation); blocks = le32_to_cpu(disc->udf_pd[id]->partitionLength); if (!location || !blocks) { fprintf(stderr, "%s: Warning: Partition Space not found\n", appname); return; } if (location + blocks > disc->blocks && !find_partition(disc, GP_PARTITION_MAP_TYPE_2, UDF_ID_VIRTUAL)) fprintf(stderr, "%s: Warning: Partition Space is beyond end of disk\n", appname); ext = find_extent(disc, location); if (ext->space_type != USPACE) { fprintf(stderr, "%s: Warning: Partition Space overlaps with other blocks\n", appname); ext = ext->next; if (ext->space_type == USPACE) { if (blocks > ext->start - location && blocks - (ext->start - location) < ext->blocks) ext = set_extent(disc, PSPACE, ext->start, blocks - (ext->start - location)); else ext = set_extent(disc, PSPACE, ext->start, ext->blocks); ext->start = location; ext->blocks = blocks; } else { new_ext = malloc(sizeof(struct udf_extent)); new_ext->space_type = PSPACE; new_ext->start = location; new_ext->blocks = blocks; new_ext->head = new_ext->tail = NULL; new_ext->prev = ext->prev; new_ext->next = ext; new_ext->prev->next = new_ext; new_ext->next->prev = new_ext; } } else { if ((location == ext->start || (location > ext->start && location + blocks > ext->start + ext->blocks)) && blocks > ext->blocks) { if (ext != disc->tail) fprintf(stderr, "%s: Warning: Partition Space overlaps with other blocks\n", appname); ext = set_extent(disc, PSPACE, location, ext->blocks); ext->blocks = blocks; } else set_extent(disc, PSPACE, location, blocks); } } static void read_fsd(int fd, struct udf_disc *disc) { long_ad *ad; uint16_t partition; uint32_t block_num, location, position, length; struct genericPartitionMap *pmap; struct udf_extent *ext; int id; if (disc->udf_lvd[0] && disc->udf_pd[0]) id = 0; else if (disc->udf_lvd[1] && disc->udf_pd[1]) id = 1; else if (disc->udf_lvd[0] && disc->udf_pd[1]) id = 0; else if (disc->udf_lvd[1] && disc->udf_pd[0]) id = 1; else return; ad = (long_ad *)disc->udf_lvd[id]->logicalVolContentsUse; block_num = le32_to_cpu(ad->extLocation.logicalBlockNum); partition = le16_to_cpu(ad->extLocation.partitionReferenceNum); length = le32_to_cpu(ad->extLength) & EXT_LENGTH_MASK; pmap = get_partition(disc, id, partition); if (!pmap) { fprintf(stderr, "%s: Warning: Incorrect Logical Volume Descriptor\n", appname); return; } position = find_block_position(disc, pmap, block_num); if (position == UINT32_MAX) { fprintf(stderr, "%s: Warning: File Set Descriptor cannot be read\n", appname); return; } if (id == 0 && !disc->udf_pd[0]) id = 1; else if (id == 1 && !disc->udf_pd[1]) id = 0; location = le32_to_cpu(disc->udf_pd[id]->partitionStartingLocation) + position; if (sizeof(*disc->udf_fsd) > length) { fprintf(stderr, "%s: Warning: Incorrect File Set Descriptor\n", appname); return; } disc->udf_fsd = malloc(length); if (!disc->udf_fsd) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return; } if (read_offset(fd, disc, disc->udf_fsd, (size_t)location * disc->blocksize, length, 1) < 0) { free(disc->udf_fsd); disc->udf_fsd = NULL; return; } if (le32_to_cpu(disc->udf_fsd->descTag.tagLocation) != position) { fprintf(stderr, "%s: Warning: Incorrect Logical Volume Integrity Descriptor\n", appname); free(disc->udf_fsd); disc->udf_fsd = NULL; return; } if (le16_to_cpu(disc->udf_fsd->descTag.tagIdent) != TAG_IDENT_FSD) { fprintf(stderr, "%s: Warning: Incorrect File Set Descriptor\n", appname); free(disc->udf_fsd); disc->udf_fsd = NULL; return; } ext = next_extent(disc->head, PSPACE); if (ext) set_desc(ext, TAG_IDENT_FSD, location - ext->start, length, alloc_data(disc->udf_fsd, length)); } static void setup_total_space_blocks(struct udf_disc *disc) { int id; if (disc->udf_pd[0]) id = 0; else if (disc->udf_pd[1]) id = 1; else { fprintf(stderr, "%s: Warning: Determining total space blocks is not possible\n", appname); return; } disc->total_space_blocks = le32_to_cpu(disc->udf_pd[id]->partitionLength); if (disc->total_space_blocks + le32_to_cpu(disc->udf_pd[id]->partitionStartingLocation) > disc->blocks && !find_partition(disc, GP_PARTITION_MAP_TYPE_2, UDF_ID_VIRTUAL)) fprintf(stderr, "%s: Warning: Some space blocks are beyond end of disk\n", appname); } static uint32_t count_bitmap_blocks(int fd, struct udf_disc *disc, uint32_t location, uint32_t length) { unsigned long int buffer[512/sizeof(unsigned long int)]; unsigned long int val; struct spaceBitmapDesc sbd; uint32_t bits; uint32_t bytes; uint32_t blocks; size_t i; if (sizeof(sbd) > length) { fprintf(stderr, "%s: Warning: Invalid Space Bitmap Descriptor\n", appname); return 0; } if (read_offset(fd, disc, &sbd, (size_t)location * disc->blocksize, sizeof(sbd), 1) < 0) return 0; bits = le32_to_cpu(sbd.numOfBits); bytes = le32_to_cpu(sbd.numOfBytes); if (bytes > length - sizeof(sbd) || bytes < (bits+7) / 8) { fprintf(stderr, "%s: Warning: Invalid Space Bitmap Descriptor\n", appname); return 0; } bytes = (bits+7) / 8; blocks = 0; for (bytes = (bits+7) / 8; bytes > sizeof(buffer); bytes -= sizeof(buffer)) { if (read(fd, &buffer, sizeof(buffer)) != (ssize_t)sizeof(buffer)) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); return 0; } for (i = 0; i < sizeof(buffer)/sizeof(*buffer); ++i) { val = buffer[i]; while (val) { val &= val - 1; ++blocks; } } } if (bytes) { memset(&buffer, 0, sizeof(buffer)); if (read(fd, &buffer, bytes) != (ssize_t)bytes) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); return 0; } if (bits % 8) ((unsigned char *)buffer)[bytes-1] &= (1 << bits) - 1; for (i = 0; i < (bytes+sizeof(*buffer)) / sizeof(*buffer); ++i) { val = buffer[i]; while (val) { val &= val - 1; ++blocks; } } } return blocks; } static uint32_t count_table_blocks(int fd, struct udf_disc *disc, uint32_t location, uint32_t length) { unsigned char buffer[512]; struct unallocSpaceEntry *use; size_t use_len; uint64_t space, blocks; size_t i, count; short_ad *sad; long_ad *lad; if (sizeof(*use) > length) { fprintf(stderr, "%s: Warning: Invalid Space Entry\n", appname); return 0; } if (read_offset(fd, disc, &buffer, (size_t)location * disc->blocksize, sizeof(buffer), 1) < 0) return 0; use = (struct unallocSpaceEntry *)&buffer; use_len = sizeof(*use) + le32_to_cpu(use->lengthAllocDescs); if (use_len > length) { fprintf(stderr, "%s: Warning: Invalid Space Entry\n", appname); return 0; } use = malloc(use_len); if (!use) { fprintf(stderr, "%s: Error: malloc failed: %s\n", appname, strerror(errno)); return 0; } if (use_len <= sizeof(buffer)) memcpy(use, &buffer, use_len); else { memcpy(use, &buffer, sizeof(buffer)); errno = 0; if (read(fd, (void *)use + sizeof(buffer), use_len - sizeof(buffer)) != (ssize_t)(use_len - sizeof(buffer))) { fprintf(stderr, "%s: Warning: read failed: %s\n", appname, strerror(errno ? errno : EIO)); free(use); return 0; } } space = 0; switch (le16_to_cpu(use->icbTag.flags) & ICBTAG_FLAG_AD_MASK) { case ICBTAG_FLAG_AD_SHORT: sad = (short_ad *)&use->allocDescs[0]; count = (use_len-sizeof(*use)) / sizeof(*sad); for (i = 0; i < count; ++i) { blocks = le32_to_cpu(sad[i].extLength) & EXT_LENGTH_MASK; if (blocks <= UINT64_MAX - space) space += blocks; else space = UINT64_MAX; } break; case ICBTAG_FLAG_AD_LONG: lad = (long_ad *)&use->allocDescs[0]; count = (use_len-sizeof(*use)) / sizeof(*lad); for (i = 0; i < count; ++i) { blocks = le32_to_cpu(lad[i].extLength) & EXT_LENGTH_MASK; if (blocks <= UINT64_MAX - space) space += blocks; else space = UINT64_MAX; } break; default: fprintf(stderr, "%s: Warning: Invalid Information Control Block in Space Entry\n", appname); break; } free(use); if (space > UINT64_MAX - (disc->blocksize-1)) return UINT32_MAX; blocks = (space + disc->blocksize-1) / disc->blocksize; if (blocks > UINT32_MAX) return UINT32_MAX; return blocks; } static void scan_free_space_blocks(int fd, struct udf_disc *disc) { long_ad *ad; uint16_t partition; uint32_t blocks, position, location, length; struct genericPartitionMap *pmap; struct partitionHeaderDesc *phd; char *ident; int id; if (!disc->udf_lvid) return; if (disc->udf_lvd[0]) id = 0; else if (disc->udf_lvd[1]) id = 1; else return; ad = (long_ad *)disc->udf_lvd[id]->logicalVolContentsUse; partition = le16_to_cpu(ad->extLocation.partitionReferenceNum); if (partition < le32_to_cpu(disc->udf_lvid->numOfPartitions)) { blocks = le32_to_cpu(disc->udf_lvid->freeSpaceTable[partition]); if (blocks != 0xFFFFFFFF) { disc->free_space_blocks = blocks; return; } } pmap = get_partition(disc, id, partition); if (!pmap) return; if (find_block_position(disc, pmap, 0) == UINT32_MAX) { fprintf(stderr, "%s: Warning: Determining free space blocks is not possible\n", appname); return; } if (disc->udf_pd[0]) id = 0; else if (disc->udf_pd[1]) id = 1; else return; ident = (char *)disc->udf_pd[id]->partitionContents.ident; length = sizeof(disc->udf_pd[id]->partitionContents.ident); if (strncmp(ident, PD_PARTITION_CONTENTS_NSR02, length) != 0 && strncmp(ident, PD_PARTITION_CONTENTS_NSR03, length) != 0) { fprintf(stderr, "%s: Warning: Unknown Partition Descriptor Content, determining free space blocks is not possible\n", appname); return; } location = le32_to_cpu(disc->udf_pd[id]->partitionStartingLocation); phd = (struct partitionHeaderDesc *)disc->udf_pd[id]->partitionContentsUse; if (disc->vat) { disc->free_space_blocks = location + disc->total_space_blocks - (disc->vat_block+1); return; } length = le32_to_cpu(phd->unallocSpaceBitmap.extLength) & EXT_LENGTH_MASK; if (length) { position = find_block_position(disc, pmap, le32_to_cpu(phd->unallocSpaceBitmap.extPosition)); blocks = count_bitmap_blocks(fd, disc, location + position, length); if (blocks) { disc->free_space_blocks = blocks; return; } } length = le32_to_cpu(phd->freedSpaceBitmap.extLength) & EXT_LENGTH_MASK; if (length) { position = find_block_position(disc, pmap, le32_to_cpu(phd->freedSpaceBitmap.extPosition)); blocks = count_bitmap_blocks(fd, disc, location + position, length); if (blocks) { disc->free_space_blocks = blocks; return; } } length = le32_to_cpu(phd->unallocSpaceTable.extLength) & EXT_LENGTH_MASK; if (length) { position = find_block_position(disc, pmap, le32_to_cpu(phd->unallocSpaceTable.extPosition)); blocks = count_table_blocks(fd, disc, location + position, length); if (blocks) { disc->free_space_blocks = blocks; return; } } length = le32_to_cpu(phd->freedSpaceTable.extLength) & EXT_LENGTH_MASK; if (length) { position = find_block_position(disc, pmap, le32_to_cpu(phd->freedSpaceTable.extPosition)); blocks = count_table_blocks(fd, disc, location + position, length); if (blocks) { disc->free_space_blocks = blocks; return; } } disc->free_space_blocks = 0; } int read_disc(int fd, struct udf_disc *disc) { if (detect_udf(fd, disc) < 0) return -1; read_mbr(fd, disc); scan_mvds(fd, disc); scan_rvds(fd, disc); if (!disc->udf_anchor[1] && !disc->udf_anchor[2] && !find_partition(disc, GP_PARTITION_MAP_TYPE_2, UDF_ID_VIRTUAL)) fprintf(stderr, "%s: Warning: Second and third Anchor Volume Descriptor Pointer not found\n", appname); if (!disc->udf_pvd[0] && !disc->udf_pvd[1]) fprintf(stderr, "%s: Warning: Primary Volume Descriptor not found\n", appname); if (!disc->udf_pd[0] && !disc->udf_pd[1]) fprintf(stderr, "%s: Warning: Partition Descriptor not found\n", appname); if (!disc->udf_lvd[0] && !disc->udf_lvd[1]) fprintf(stderr, "%s: Warning: Logical Volume Descriptor not found\n", appname); if (!disc->udf_usd[0] && !disc->udf_usd[1]) fprintf(stderr, "%s: Warning: Unallocated Space Descriptor not found\n", appname); if (!disc->udf_iuvd[0] && !disc->udf_iuvd[1]) fprintf(stderr, "%s: Warning: Implementation Use Volume Descriptor not found\n", appname); if (!disc->udf_td[0] && !disc->udf_td[1]) fprintf(stderr, "%s: Warning: Terminating Descriptor not found\n", appname); scan_lvis(fd, disc); if (!disc->udf_lvid) fprintf(stderr, "%s: Warning: Logical Volume Integrity Descriptor not found\n", appname); parse_lvidiu(disc); read_stable(fd, disc); read_vat(fd, disc); setup_pspace(disc); /* TODO: setup USPACE extents */ read_fsd(fd, disc); if (!disc->udf_fsd) fprintf(stderr, "%s: Warning: File Set Descriptor not found\n", appname); setup_total_space_blocks(disc); scan_free_space_blocks(fd, disc); return 0; } udftools-2.0/udfinfo/main.c0000644000175000017500000002051313221466537012667 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "libudffs.h" #include "options.h" #include "readdisc.h" static uint64_t get_size(int fd) { struct stat st; uint64_t size; off_t offset; if (fstat(fd, &st) == 0) { if (S_ISBLK(st.st_mode) && ioctl(fd, BLKGETSIZE64, &size) == 0) return size; else if (S_ISREG(st.st_mode)) return st.st_size; } offset = lseek(fd, 0, SEEK_END); if (offset == (off_t)-1) { fprintf(stderr, "%s: Error: Cannot detect size of disk: %s\n", appname, strerror(errno)); exit(1); } if (lseek(fd, 0, SEEK_SET) != 0) { fprintf(stderr, "%s: Error: Cannot seek to start of disk: %s\n", appname, strerror(errno)); exit(1); } return offset; } static int get_sector_size(int fd) { int size; if (ioctl(fd, BLKSSZGET, &size) != 0) return 0; if (size < 512 || size > 32768 || (size & (size - 1))) { fprintf(stderr, "%s: Warning: Disk logical sector size (%d) is not suitable for UDF\n", appname, size); return 0; } return size; } static uint32_t compute_windows_serial_num(struct udf_disc *disc) { uint8_t *buffer = (uint8_t *)disc->udf_fsd; size_t len = sizeof(*disc->udf_fsd); uint8_t checksum[4] = { 0, 0, 0, 0 }; if (!buffer) return 0; while (len--) checksum[len & 0x3] += *buffer++; return (checksum[0] << 24) | (checksum[1] << 16) | (checksum[2] << 8) | checksum[3]; } static uint32_t compute_behind_blocks(struct udf_disc *disc) { struct udf_extent *start_ext; uint32_t last_block = 0; for (start_ext = disc->head; start_ext != NULL; start_ext = start_ext->next) { if (start_ext->space_type & USPACE) continue; if (last_block < start_ext->start + start_ext->blocks) last_block = start_ext->start + start_ext->blocks; } if (disc->blocks > last_block) return disc->blocks - last_block; else return 0; } static void print_dstring(struct udf_disc *disc, const char *name, const dstring *string, size_t len) { char buf[256]; size_t i; fputs(name, stdout); putchar('='); if (string) { len = decode_string(disc, string, buf, len, sizeof(buf)); if (len != (size_t)-1) { for (i = 0; i < len; ++i) { if (buf[i] == '\n') buf[i] = ' '; } fwrite(buf, len, 1, stdout); } } putchar('\n'); } static const char *udf_space_type_str[UDF_SPACE_TYPE_SIZE] = { "RESERVED", "VRS", "ANCHOR", "MVDS", "RVDS", "LVID", "STABLE", "SSPACE", "PSPACE", "USPACE", "BAD", "MBR" }; static void dump_space(struct udf_disc *disc) { struct udf_extent *start_ext; int i; for (start_ext = disc->head; start_ext != NULL; start_ext = start_ext->next) { for (i = 0; i < UDF_SPACE_TYPE_SIZE; ++i) { if (!(start_ext->space_type & (1<space_type & (USPACE|RESERVED)) continue; printf("start=%lu, blocks=%lu, type=%s\n", (unsigned long int)start_ext->start, (unsigned long int)start_ext->blocks, udf_space_type_str[i]); } } } int main(int argc, char *argv[]) { struct udf_disc disc; dstring vsid[128]; char uuid[17]; char *filename; struct logicalVolDesc *lvd; struct primaryVolDesc *pvd; struct partitionDesc *pd; uint32_t serial_num; uint32_t used_blocks; uint32_t behind_blocks; size_t ret; int fd; setlocale(LC_CTYPE, ""); appname = "udfinfo"; memset(&disc, 0, sizeof(disc)); disc.flags = FLAG_LOCALE; disc.head = calloc(1, sizeof(struct udf_extent)); disc.tail = disc.head; disc.head->space_type = USPACE; parse_args(argc, argv, &disc, &filename); fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, strerror(errno)); exit(1); } disc.blksize = get_size(fd); disc.blkssz = get_sector_size(fd); if (read_disc(fd, &disc) < 0) { fprintf(stderr, "%s: Error: Cannot process device '%s' as UDF disk\n", appname, filename); exit(1); } close(fd); if (disc.udf_lvd[0]) lvd = disc.udf_lvd[0]; else if (disc.udf_lvd[1]) lvd = disc.udf_lvd[1]; else lvd = NULL; if (disc.udf_pvd[0]) pvd = disc.udf_pvd[0]; else if (disc.udf_pvd[1]) pvd = disc.udf_pvd[1]; else pvd = NULL; if (disc.udf_pd[0]) pd = disc.udf_pd[0]; else if (disc.udf_pd[1]) pd = disc.udf_pd[1]; else pd = NULL; if (disc.total_space_blocks < disc.free_space_blocks) used_blocks = disc.total_space_blocks; else used_blocks = disc.total_space_blocks - disc.free_space_blocks; behind_blocks = compute_behind_blocks(&disc); serial_num = compute_windows_serial_num(&disc); if (pvd) { ret = gen_uuid_from_vol_set_ident(uuid, pvd->volSetIdent, sizeof(pvd->volSetIdent)); if (ret < 8) { memcpy(vsid, pvd->volSetIdent, 128); } else { vsid[0] = pvd->volSetIdent[0]; vsid[127] = 0; if (ret < 16) ret = 1; else ret = 2; if (pvd->volSetIdent[127] > vsid[0]*ret) { vsid[127] = pvd->volSetIdent[127] - vsid[0]*ret; memcpy(vsid + 1, pvd->volSetIdent + vsid[0]*ret + 1, vsid[127] - 1); } } } else { uuid[0] = 0; vsid[0] = 0; vsid[127] = 0; } if (!disc.udf_lvid || le32_to_cpu(disc.udf_lvid->integrityType) != LVID_INTEGRITY_TYPE_CLOSE) fprintf(stderr, "%s: Warning: Logical Volume is in inconsistent state\n", appname); printf("filename=%s\n", filename); print_dstring(&disc, "label", lvd ? lvd->logicalVolIdent : NULL, sizeof(lvd->logicalVolIdent)); printf("uuid=%s\n", uuid); print_dstring(&disc, "lvid", lvd ? lvd->logicalVolIdent : NULL, sizeof(lvd->logicalVolIdent)); print_dstring(&disc, "vid", pvd ? pvd->volIdent : NULL, sizeof(pvd->volIdent)); print_dstring(&disc, "vsid", vsid, sizeof(vsid)); print_dstring(&disc, "fsid", disc.udf_fsd ? disc.udf_fsd->fileSetIdent : NULL, sizeof(disc.udf_fsd->fileSetIdent)); print_dstring(&disc, "fullvsid", pvd ? pvd->volSetIdent : NULL, sizeof(pvd->volSetIdent)); printf("winserialnum=0x%08lx\n", (unsigned long int)serial_num); printf("blocksize=%d\n", disc.blocksize); printf("blocks=%lu\n", (unsigned long int)disc.blocks); printf("usedblocks=%lu\n", (unsigned long int)used_blocks); printf("freeblocks=%lu\n", (unsigned long int)disc.free_space_blocks); printf("behindblocks=%lu\n", (unsigned long int)behind_blocks); printf("numfiles=%lu\n", (unsigned long int)disc.num_files); printf("numdirs=%lu\n", (unsigned long int)disc.num_dirs); printf("udfrev=%x.%02x\n", (unsigned int)(disc.udf_rev >> 8), (unsigned int)(disc.udf_rev & 0xFF)); printf("udfwriterev=%x.%02x\n", (unsigned int)(disc.udf_write_rev >> 8), (unsigned int)(disc.udf_write_rev & 0xFF)); if (disc.vat_block) printf("vatblock=%lu\n", (unsigned long int)disc.vat_block); if (disc.udf_lvid) { switch (le32_to_cpu(disc.udf_lvid->integrityType)) { case LVID_INTEGRITY_TYPE_OPEN: printf("integrity=opened\n"); break; case LVID_INTEGRITY_TYPE_CLOSE: printf("integrity=closed\n"); break; default: printf("integrity=unknown\n"); break; } } else printf("integrity=unknown\n"); if (pd) { switch (le32_to_cpu(pd->accessType)) { case PD_ACCESS_TYPE_OVERWRITABLE: printf("accesstype=overwritable\n"); break; case PD_ACCESS_TYPE_REWRITABLE: printf("accesstype=rewritable\n"); break; case PD_ACCESS_TYPE_WRITE_ONCE: printf("accesstype=writeonce\n"); break; case PD_ACCESS_TYPE_READ_ONLY: printf("accesstype=readonly\n"); break; case PD_ACCESS_TYPE_NONE: printf("accesstype=pseudo-overwritable\n"); break; default: printf("accesstype=unknown\n"); break; } } else printf("accesstype=unknown\n"); dump_space(&disc); return 0; } udftools-2.0/udfinfo/Makefile.in0000644000175000017500000004610313221466653013646 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = udfinfo$(EXEEXT) subdir = udfinfo ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_udfinfo_OBJECTS = main.$(OBJEXT) readdisc.$(OBJEXT) \ options.$(OBJEXT) udfinfo_OBJECTS = $(am_udfinfo_OBJECTS) udfinfo_DEPENDENCIES = $(top_builddir)/libudffs/libudffs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(udfinfo_SOURCES) DIST_SOURCES = $(udfinfo_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udfinfo_LDADD = $(top_builddir)/libudffs/libudffs.la udfinfo_SOURCES = main.c readdisc.c options.c readdisc.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu udfinfo/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu udfinfo/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list udfinfo$(EXEEXT): $(udfinfo_OBJECTS) $(udfinfo_DEPENDENCIES) $(EXTRA_udfinfo_DEPENDENCIES) @rm -f udfinfo$(EXEEXT) $(AM_V_CCLD)$(LINK) $(udfinfo_OBJECTS) $(udfinfo_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdisc.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/udfinfo/Makefile.am0000644000175000017500000000044213221466537013632 00000000000000bin_PROGRAMS = udfinfo udfinfo_LDADD = $(top_builddir)/libudffs/libudffs.la udfinfo_SOURCES = main.c readdisc.c options.c readdisc.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include udftools-2.0/udffsck/0000755000175000017500000000000013221466662011650 500000000000000udftools-2.0/udffsck/main.c0000644000175000017500000000152013221466537012657 00000000000000/* * main.c * * Copyright (c) 2001-2002 Ben Fennema * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ int main() { return 0; } udftools-2.0/udffsck/Makefile.in0000644000175000017500000004151713221466653013645 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = udffsck$(EXEEXT) subdir = udffsck ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_udffsck_OBJECTS = main.$(OBJEXT) udffsck_OBJECTS = $(am_udffsck_OBJECTS) udffsck_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(udffsck_SOURCES) DIST_SOURCES = $(udffsck_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udffsck_SOURCES = main.c AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu udffsck/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu udffsck/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list udffsck$(EXEEXT): $(udffsck_OBJECTS) $(udffsck_DEPENDENCIES) $(EXTRA_udffsck_DEPENDENCIES) @rm -f udffsck$(EXEEXT) $(AM_V_CCLD)$(LINK) $(udffsck_OBJECTS) $(udffsck_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/udffsck/Makefile.am0000644000175000017500000000013213221466537013621 00000000000000noinst_PROGRAMS = udffsck udffsck_SOURCES = main.c AM_CPPFLAGS = -I$(top_srcdir)/include udftools-2.0/pktsetup/0000755000175000017500000000000013221466662012102 500000000000000udftools-2.0/pktsetup/pktsetup.rules0000644000175000017500000000043013221466537014753 00000000000000# Create and remove packet writing device for each optical block device ACTION=="add", SUBSYSTEM=="block", ENV{ID_CDROM}=="1", RUN+="/usr/sbin/pktsetup %E{MAJOR}:%E{MINOR}" ACTION=="remove", SUBSYSTEM=="block", ENV{ID_CDROM}=="1", RUN+="/usr/sbin/pktsetup -d %E{MAJOR}:%E{MINOR}" udftools-2.0/pktsetup/pktsetup.c0000644000175000017500000002717213221466537014057 00000000000000/* * Copyright (c) 1999,2000 Jens Axboe * Copyright (c) 2004 Peter Osterlund * Copyright (c) 2014-2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* * if we don't have one, we probably have neither */ #ifndef PACKET_SETUP_DEV #define PACKET_SETUP_DEV _IOW('X', 1, unsigned int) #define PACKET_TEARDOWN_DEV _IOW('X', 2, unsigned int) #endif #ifndef PACKET_CTRL_CMD #define PACKET_CTRL_CMD _IOWR('X', 1, struct pkt_ctrl_command) #endif #define MAJOR(dev) ((dev & 0xfff00) >> 8) #define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00)) #define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12)) #define MISC_MAJOR 10 #define CTL_DIR "/dev/pktcdvd" #define CTL_DEV "control" #define PKT_CTRL_CMD_SETUP 0 #define PKT_CTRL_CMD_TEARDOWN 1 #define PKT_CTRL_CMD_STATUS 2 struct pkt_ctrl_command { __u32 command; /* in: Setup, teardown, status */ __u32 dev_index; /* in/out: Device index */ __u32 dev; /* in/out: Device nr for cdrw device */ __u32 pkt_dev; /* out: Device nr for packet device */ __u32 num_devices; /* out: Largest device index + 1 */ __u32 padding; }; static int init_cdrom(int fd) { if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) < 0) { fprintf(stderr, "pktsetup: Error: Drive is not ready\n"); return 1; } if (ioctl(fd, CDROM_DISC_STATUS, CDSL_CURRENT) < 0) { fprintf(stderr, "pktsetup: Error: No disc inserted\n"); return 1; } /* * we don't care what disc type the uniform layer thinks it * is, since it may get it wrong. what matters is that the above * will force a TOC read. */ return 0; } static int setup_dev(char *pkt_device, char *device, int rem) { int pkt_fd, dev_fd, cmd, arg, ret; if ((pkt_fd = open(pkt_device, O_RDONLY)) == -1) { fprintf(stderr, "pktsetup: Error: Can't open packet device '%s': %s\n", pkt_device, strerror(errno)); return 1; } if (!rem) { cmd = PACKET_SETUP_DEV; if ((dev_fd = open(device, O_RDONLY | O_NONBLOCK)) == -1) { fprintf(stderr, "pktsetup: Error: Can't open cd-rom device '%s': %s\n", device, strerror(errno)); close(pkt_fd); return 1; } if (init_cdrom(dev_fd)) { close(pkt_fd); close(dev_fd); return 1; } arg = dev_fd; } else { cmd = PACKET_TEARDOWN_DEV; dev_fd = -1; arg = 0; } ret = ioctl(pkt_fd, cmd, arg); if (ret == -1) { if (rem) fprintf(stderr, "pktsetup: Error: Can't tear down packet device '%s': %s\n", pkt_device, strerror(errno)); else fprintf(stderr, "pktsetup: Error: Can't setup packet device '%s' for cd-rom device '%s': %s\n", pkt_device, device, strerror(errno)); } if (dev_fd >= 0) close(dev_fd); close(pkt_fd); if (ret == -1) return 1; return 0; } static int usage(void) { printf("pktsetup from " PACKAGE_NAME " " PACKAGE_VERSION "\n"); printf("Set up and tear down packet device associations\n"); #if 0 /* pktcdvd >= 0.2.0 is in linux kernel since 2.6.10, so hide help for old interface */ printf("For pktcdvd < 0.2.0:\n"); printf(" pktsetup /dev/pktcdvd0 /dev/cdrom setup device\n"); printf(" pktsetup -d /dev/pktcdvd0 tear down device\n"); printf("For pktcdvd >= 0.2.0:\n"); #endif printf(" pktsetup [dev_name] /dev/cdrom setup device\n"); printf(" pktsetup [dev_name] major:minor setup device\n"); printf(" pktsetup -d dev_name tear down device\n"); printf(" pktsetup -d major:minor tear down device\n"); printf(" pktsetup -s show device mappings\n"); return 1; } /* * Find the minor device number for the pktcdvd control device. */ static int get_misc_minor(void) { int minor; char name[64]; FILE *f; if ((f = fopen("/proc/misc", "r")) == NULL) return -1; while (fscanf(f, " %d %63s", &minor, name) == 2) { if (strcmp(name, "pktcdvd") == 0) { fclose(f); return minor; } } fclose(f); return -1; } static const char *pkt_dev_name(const char *dev) { static char buf[512]; if (snprintf(buf, sizeof(buf), "%s/%s", CTL_DIR, dev) >= (int)sizeof(buf)) { fprintf(stderr, "pktsetup: Error: Can't process device '%s': %s\n", dev, strerror(ENAMETOOLONG)); exit(1); } return buf; } static int create_ctl_dev(void) { int misc_minor; struct stat stat_buf; dev_t dev; if ((misc_minor = get_misc_minor()) < 0) { if (system("/sbin/modprobe pktcdvd") != 0) { fprintf(stderr, "pktsetup: Error: Can't load pktcdvd kernel module\n"); } misc_minor = get_misc_minor(); } if (misc_minor < 0) { fprintf(stderr, "pktsetup: Error: Can't find pktcdvd character device number\n"); return -1; } dev = MKDEV(MISC_MAJOR, misc_minor); if ((stat(pkt_dev_name(CTL_DEV), &stat_buf) >= 0) && S_ISCHR(stat_buf.st_mode) && (stat_buf.st_rdev == dev)) return 0; /* Already set up */ mkdir(CTL_DIR, 0755); unlink(pkt_dev_name(CTL_DEV)); if (mknod(pkt_dev_name(CTL_DEV), S_IFCHR | 0644, dev) < 0) { perror("pktsetup: Error: Can't create pktcdvd control device"); return -1; } return 0; } static int remove_stale_dev_node(int ctl_fd, char *devname) { struct stat stat_buf; unsigned int i; dev_t dev; struct pkt_ctrl_command c; if (stat(pkt_dev_name(devname), &stat_buf) < 0) return 0; if (!S_ISBLK(stat_buf.st_mode)) return 1; dev = stat_buf.st_rdev; memset(&c, 0, sizeof(struct pkt_ctrl_command)); for (i = 0; ; i++) { c.command = PKT_CTRL_CMD_STATUS; c.dev_index = i; if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { perror("pktsetup: Error: Can't check status of device"); return 1; } if (i >= c.num_devices) break; if (c.pkt_dev == dev) return 1; /* busy */ } unlink(pkt_dev_name(devname)); return 0; } static dev_t find_pkdev_for_dev(int ctl_fd, dev_t blk_dev) { struct pkt_ctrl_command c; unsigned int i; memset(&c, 0, sizeof(struct pkt_ctrl_command)); for (i = 0; ; i++) { c.command = PKT_CTRL_CMD_STATUS; c.dev_index = i; if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { perror("pktsetup: Error: Can't get device mapping"); return 0; } if (i >= c.num_devices) return 0; if (c.dev == blk_dev) return c.pkt_dev; } return 0; } static int setup_dev_chardev(char *pkt_device, char *device, int rem) { struct pkt_ctrl_command c; struct stat stat_buf; int ctl_fd, dev_fd; int ret = 1; memset(&c, 0, sizeof(struct pkt_ctrl_command)); if (create_ctl_dev() < 0) return 1; if ((ctl_fd = open(pkt_dev_name(CTL_DEV), O_RDONLY)) < 0) { perror("pktsetup: Error: Can't open pktcdvd control device"); return 1; } if (!rem) { if ((dev_fd = open(device, O_RDONLY | O_NONBLOCK)) == -1) { int major, minor, old_errno; old_errno = errno; if (sscanf(device, "%d:%d", &major, &minor) != 2) { fprintf(stderr, "pktsetup: Error: Can't open cd-rom device '%s': %s\n", device, strerror(old_errno)); goto out_close; } c.dev = MKDEV(major, minor); } else { if (fstat(dev_fd, &stat_buf) < 0) { fprintf(stderr, "pktsetup: Error: Can't stat cd-rom device '%s': %s\n", device, strerror(errno)); close(dev_fd); goto out_close; } if (!S_ISBLK(stat_buf.st_mode)) { fprintf(stderr, "pktsetup: Error: Node '%s' is not a block device\n", device); close(dev_fd); goto out_close; } if (init_cdrom(dev_fd)) { close(dev_fd); goto out_close; } close(dev_fd); c.dev = stat_buf.st_rdev; } c.command = PKT_CTRL_CMD_SETUP; if (pkt_device && remove_stale_dev_node(ctl_fd, pkt_device) != 0) { fprintf(stderr, "pktsetup: Error: Device node '%s' already in use\n", pkt_device); goto out_close; } if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { fprintf(stderr, "pktsetup: Error: Can't setup packet device for cd-rom device '%s': %s\n", device, strerror(errno)); goto out_close; } if (pkt_device && mknod(pkt_dev_name(pkt_device), S_IFBLK | 0640, c.pkt_dev) < 0 && errno != EEXIST) { fprintf(stderr, "pktsetup: Error: Can't create device node '%s': %s\n", pkt_device, strerror(errno)); goto out_close; } ret = 0; } else { int major, minor, remove_node; if ((stat(pkt_dev_name(pkt_device), &stat_buf) >= 0) && S_ISBLK(stat_buf.st_mode)) { major = MAJOR(stat_buf.st_rdev); minor = MINOR(stat_buf.st_rdev); if (strncmp(pkt_device, "pktcdvd", sizeof("pktcdvd")-1) == 0) remove_node = 0; else remove_node = 1; } else if (sscanf(pkt_device, "%d:%d", &major, &minor) == 2) { remove_node = 0; } else { fprintf(stderr, "pktsetup: Error: Can't find major/minor numbers for packet device '%s'\n", pkt_device); goto out_close; } c.command = PKT_CTRL_CMD_TEARDOWN; c.pkt_dev = MKDEV(major, minor); if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { int cur_errno = errno; if (cur_errno != ENXIO) goto out_error; remove_node = 0; c.pkt_dev = find_pkdev_for_dev(ctl_fd, MKDEV(major, minor)); if (!c.pkt_dev) goto out_error; if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { cur_errno = errno; out_error: fprintf(stderr, "pktsetup: Error: Can't tear down packet device '%s': %s\n", pkt_device, strerror(cur_errno)); goto out_close; } } if (remove_node) { if (unlink(pkt_dev_name(pkt_device)) != 0) fprintf(stderr, "pktsetup: Error: Can't unlink device node '%s': %s\n", pkt_device, strerror(errno)); else ret = 0; } else { ret = 0; } } out_close: close(ctl_fd); return ret; } static int show_mappings(void) { struct pkt_ctrl_command c; unsigned int i; int ctl_fd; int ret; ret = 0; memset(&c, 0, sizeof(struct pkt_ctrl_command)); if (create_ctl_dev() < 0) return 1; if ((ctl_fd = open(pkt_dev_name(CTL_DEV), O_RDONLY)) < 0) { perror("pktsetup: Error: Can't open pktcdvd control device"); return 1; } for (i = 0; ; i++) { c.command = PKT_CTRL_CMD_STATUS; c.dev_index = i; if (ioctl(ctl_fd, PACKET_CTRL_CMD, &c) < 0) { perror("pktsetup: Error: Can't show device mapping"); ret = 1; goto out_close; } if (i >= c.num_devices) break; if (c.dev) { printf("%2d : %d:%d -> %d:%d\n", i, MAJOR(c.pkt_dev), MINOR(c.pkt_dev), MAJOR(c.dev), MINOR(c.dev)); } } out_close: close(ctl_fd); return ret; } int main(int argc, char **argv) { int rem = 0, c, old_api; char *pkt_device; char *device; if (argc == 1) return usage(); while ((c = getopt(argc, argv, "ds?")) != EOF) { switch (c) { case 'd': rem = 1; break; case 's': return show_mappings(); default: return usage(); } } if (optind == argc || (!rem && optind+2 < argc) || (rem && optind+1 < argc)) return usage(); if (!rem && optind+1 == argc) { device = argv[optind]; pkt_device = NULL; old_api = 0; } else { pkt_device = argv[optind]; device = rem ? NULL : argv[optind + 1]; old_api = (strchr(pkt_device, '/') != NULL); } if (old_api) return setup_dev(pkt_device, device, rem); else return setup_dev_chardev(pkt_device, device, rem); } udftools-2.0/pktsetup/Makefile.in0000644000175000017500000004577013221466653014104 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = pktsetup$(EXEEXT) subdir = pktsetup ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_pktsetup_OBJECTS = pktsetup.$(OBJEXT) pktsetup_OBJECTS = $(am_pktsetup_OBJECTS) pktsetup_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pktsetup_SOURCES) DIST_SOURCES = $(pktsetup_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pktsetup_SOURCES = pktsetup.c EXTRA_DIST = pktsetup.rules all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pktsetup/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu pktsetup/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list pktsetup$(EXEEXT): $(pktsetup_OBJECTS) $(pktsetup_DEPENDENCIES) $(EXTRA_pktsetup_DEPENDENCIES) @rm -f pktsetup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pktsetup_OBJECTS) $(pktsetup_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pktsetup.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-local uninstall-sbinPROGRAMS .PRECIOUS: Makefile install-data-local: mkdir -p "$(DESTDIR)/lib/udev/rules.d" $(INSTALL_DATA) "$(srcdir)/pktsetup.rules" "$(DESTDIR)/lib/udev/rules.d/80-pktsetup.rules" uninstall-local: rm -f "$(DESTDIR)/lib/udev/rules.d/80-pktsetup.rules" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/pktsetup/Makefile.am0000644000175000017500000000046513221466537014064 00000000000000sbin_PROGRAMS = pktsetup pktsetup_SOURCES = pktsetup.c EXTRA_DIST = pktsetup.rules install-data-local: mkdir -p "$(DESTDIR)/lib/udev/rules.d" $(INSTALL_DATA) "$(srcdir)/pktsetup.rules" "$(DESTDIR)/lib/udev/rules.d/80-pktsetup.rules" uninstall-local: rm -f "$(DESTDIR)/lib/udev/rules.d/80-pktsetup.rules" udftools-2.0/cdrwtool/0000755000175000017500000000000013221466662012060 500000000000000udftools-2.0/cdrwtool/cdrwtool.h0000644000175000017500000001462213221466537014014 00000000000000/* * Perform all sort of actions on a CD-R, CD-RW, and DVD-R drive. * * Copyright Jens Axboe, 1999, 2000 * * Released under the GPL licences. * */ #ifndef _CDRWTOOL_H #define _CDRWTOOL_H 1 #include #include #include "../include/libudffs.h" /* * define this to be the default cdrom device */ #define CDROM_DEVICE "/dev/scd1" #ifndef HZ #define HZ sysconf(_SC_CLK_TCK) #endif /* * adjust these values if commands are timing out before completion */ #define WAIT_PC (5 * HZ) #define WAIT_SYNC (25 * HZ) #define WAIT_BLANK (60 * 60 * HZ) /* * define this to 0 to make format and blank block until the entire * operation has succeeded. otherwise control is returned as soon as * the drive has verified the command -- this can be used for polling * the device for completion. */ #define USE_IMMED 0 #define PAGE_CURRENT 0 #define PAGE_CHANGE 1 #define PAGE_DEFAULT 2 #define PAGE_SAVE 3 #define BLANK_FULL 1 #define BLANK_FAST 2 #define WRITE_MODE1 1 #define WRITE_MODE2 2 /* mode2, form 1 */ #define CDROM_BLOCK 2048 #define PACKET_BLOCK 32 #define PACKET_SIZE CDROM_BLOCK*PACKET_BLOCK #define DEFAULT_SPEED 12 typedef struct { unsigned char ls_v; /* link_size valid */ unsigned char border; /* or session */ unsigned char fpacket; /* fixed, variable */ unsigned char track_mode; /* control nibbler, sub q */ unsigned char data_block; /* write type */ unsigned char link_size; /* links loss size */ unsigned char session_format; /* session closure settings */ unsigned long packet_size; /* fixed packet size */ } write_params_t; struct cdrw_disc { const char * filename; /* file to write */ unsigned long offset; /* write file / format */ unsigned char get_settings; /* just print settings */ unsigned char set_settings; /* save settings */ unsigned char blank; /* blank cdrw disc */ unsigned char fpacket; /* fixed/variable packets */ unsigned char packet_size; /* fixed packet size */ unsigned char link_size; /* link loss size */ unsigned char write_type; /* mode1 or mode2 */ unsigned char disc_track_info; /* list disc/track info */ unsigned char format; /* format disc */ unsigned char border; /* border/session */ unsigned char speed; /* writing speed */ unsigned int buffer; /* buffer size */ unsigned int reserve_track; /* reserve a track */ unsigned char quick_setup; unsigned char mkudf; unsigned int close_track; unsigned int close_session; struct udf_disc udf_disc; }; #ifndef be16_to_cpu #define be16_to_cpu(x) \ ((uint16_t)( \ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8) )) #endif #ifndef be32_to_cpu #define be32_to_cpu(x) \ ((uint32_t)( \ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24) )) #endif typedef struct disc_info { uint16_t length; #if __BYTE_ORDER == __BIG_ENDIAN unsigned char reserved1 : 3; unsigned char erasable : 1; unsigned char border : 2; unsigned char status : 2; #elif __BYTE_ORDER == __LITTLE_ENDIAN unsigned char status : 2; unsigned char border : 2; unsigned char erasable : 1; unsigned char reserved1 : 3; #else #error " is wack" #endif uint8_t n_first_track; uint8_t n_sessions_l; uint8_t first_track_l; uint8_t last_track_l; #if __BYTE_ORDER == __BIG_ENDIAN unsigned char did_v : 1; unsigned char dbc_v : 1; unsigned char uru : 1; unsigned char reserved2 : 5; #elif __BYTE_ORDER == __LITTLE_ENDIAN unsigned char reserved2 : 5; unsigned char uru : 1; unsigned char dbc_v : 1; unsigned char did_v : 1; #endif uint8_t disc_type; uint8_t n_sessions_m; uint8_t first_track_m; uint8_t last_track_m; uint32_t disc_id; uint8_t lead_in_r; uint8_t lead_in_m; uint8_t lead_in_s; uint8_t lead_in_f; uint8_t lead_out_r; uint8_t lead_out_m; uint8_t lead_out_s; uint8_t lead_out_f; uint8_t disc_bar_code[8]; uint8_t reserved3; uint8_t opc_entries; } disc_info_t; typedef struct track_info { uint16_t info_length; uint8_t track_number_l; uint8_t session_number_l; uint8_t reserved1; #if __BYTE_ORDER == __BIG_ENDIAN uint8_t reserved2 : 2; uint8_t damage : 1; uint8_t copy : 1; uint8_t track_mode : 4; uint8_t rt : 1; uint8_t blank : 1; uint8_t packet : 1; uint8_t fp : 1; uint8_t data_mode : 4; uint8_t reserved3 : 6; uint8_t lra_v : 1; uint8_t nwa_v : 1; #elif __BYTE_ORDER == __LITTLE_ENDIAN uint8_t track_mode : 4; uint8_t copy : 1; uint8_t damage : 1; uint8_t reserved2 : 2; uint8_t data_mode : 4; uint8_t fp : 1; uint8_t packet : 1; uint8_t blank : 1; uint8_t rt : 1; uint8_t nwa_v : 1; uint8_t lra_v : 1; uint8_t reserved3 : 6; #endif uint32_t track_start; uint32_t next_writable; uint32_t free_blocks; uint32_t packet_size; uint32_t track_size; uint32_t last_recorded; uint8_t track_number_m; uint8_t session_number_m; uint8_t reserved4; uint8_t reserved5; } track_info_t; typedef struct opc_table { uint16_t speed; uint8_t opc_value[6]; } opc_table_t; typedef struct disc_capacity { uint32_t lba; uint32_t block_length; } disc_capacity_t; int msf_to_lba(int, int, int); void hexdump(const void *, int); void dump_sense(unsigned char *, struct request_sense *); int wait_cmd(int, struct cdrom_generic_command *, unsigned char *, int, int); int mode_select(int, unsigned char *, int); int mode_sense(int, unsigned char *, int, char, int); int set_write_mode(int, write_params_t *); int get_write_mode(int, write_params_t *); int sync_cache(int); int write_blocks(int, unsigned char *, int, int); int write_file(int, struct cdrw_disc *); int blank_disc(int, int); int format_disc(int, struct cdrw_disc *); int read_disc_info(int, disc_info_t *); int read_track_info(int, track_info_t *, int); int reserve_track(int, struct cdrw_disc *); int close_track(int, unsigned int); int close_session(int, unsigned int); int read_buffer_cap(int, struct cdrw_disc *); int set_cd_speed(int, int); void cdrom_close(int); int cdrom_open_check(int); void print_disc_info(disc_info_t *); void print_track_info(track_info_t *); int print_disc_track_info(int); void make_write_page(write_params_t *, struct cdrw_disc *); void print_params(write_params_t *); void cdrw_init_disc(struct cdrw_disc *); int udf_set_version(struct udf_disc *, int); #endif /* _CDRWTOOL_H */ udftools-2.0/cdrwtool/options.h0000644000175000017500000000230013221466537013640 00000000000000/* * options.h * * Copyright (c) 2002 Ben Fennema * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef _OPTIONS_H #define _OPTIONS_H 1 #include void usage(void); void parse_args(int, char *[], struct cdrw_disc *, const char **); /* * Command line option token values. * 0x0000-0x00ff Single characters * 0x1000-0x1fff Long switches (no arg) * 0x2000-0x2fff Long settings (arg required) */ #define OPT_HELP 0x1000 #endif /* _OPTIONS_H */ udftools-2.0/cdrwtool/cdrwtool.c0000644000175000017500000004376513221466537014021 00000000000000/* * cdrwtool - perform all sort of actions on a CD-R, CD-RW, and DVD-R drive. * * Copyright (c) 1999,2000 Jens Axboe * Copyright (c) 2002 Ben Fennema * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "cdrwtool.h" #include "../mkudffs/mkudffs.h" static int progress; int msf_to_lba(int m, int s, int f) { return (((m * 60) + s) * 75) + f; } void hexdump(const void *buffer, int size) { unsigned char *ptr = (unsigned char *) buffer; int i; for (i = 0; i < size; i++) printf("%02x ", ptr[i]); printf("\n"); } void dump_sense(unsigned char *cdb, struct request_sense *sense) { int i; printf("Command failed: "); for (i=0; i<12; i++) printf("%02x ", cdb[i]); if (sense) { printf("- sense %02x.%02x.%02x\n", sense->sense_key, sense->asc, sense->ascq); } else { printf(", no sense\n"); } } int wait_cmd(int fd, struct cdrom_generic_command *cgc, unsigned char *buf, int dir, int timeout) { struct request_sense sense; int ret; if (cgc->timeout <= 0) cgc->timeout = 500; memset(&sense, 0, sizeof(sense)); cgc->buffer = buf; cgc->data_direction = dir; cgc->sense = &sense; cgc->timeout = timeout; ret = ioctl(fd, CDROM_SEND_PACKET, cgc); if (ret) { perror("wait_cmd"); dump_sense(cgc->cmd, cgc->sense); } return ret; } int sigfd; void sig_progress(int sig) { struct cdrom_generic_command cgc; struct request_sense sense; static int did = 0; int ret; if (sig != SIGALRM) return; memset(&cgc, 0, sizeof(cgc)); memset(&sense, 0, sizeof(sense)); cgc.sense = &sense; ret = wait_cmd(sigfd, &cgc, NULL, CGC_DATA_NONE, WAIT_PC); if ((ret || !(sense.sks[0] & 0x80)) && !did) { printf("Progress indicator not implemented on this drive\n"); printf("Don't access drive until operation has completed\n"); progress = 101; return; } progress = ((sense.sks[1] << 8 | sense.sks[2]) * 100) / 0xffff; did = 1; printf("%02d%% complete\n", progress); if (progress == 99) { progress = 101; return; } alarm(2); } void print_completion_info(int fd) { sigfd = fd; /* we can only poll sense for non-blocking commands */ #if USE_IMMED == 0 return; #else progress = 0; signal(SIGALRM, sig_progress); alarm(5); while (progress < 100) sleep(1); #endif } /* buffer must already have been filled by mode_sense */ int mode_select(int fd, unsigned char *buffer, int len) { struct cdrom_generic_command cgc; memset(&cgc, 0, sizeof(cgc)); memset(buffer, 0, 3); cgc.cmd[0] = GPCMD_MODE_SELECT_10; cgc.cmd[1] = 1 << 4; cgc.cmd[8] = cgc.buflen = len; return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_PC); } int mode_sense(int fd, unsigned char *buffer, int page, char pc, int size) { struct cdrom_generic_command cgc; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_MODE_SENSE_10; // cgc.cmd[1] = 1 << 4; cgc.cmd[2] = page | pc << 6; cgc.cmd[8] = cgc.buflen = size; return wait_cmd(fd, &cgc, buffer, CGC_DATA_READ, WAIT_PC); } int set_write_mode(int fd, write_params_t *w) { unsigned char header[0x10]; unsigned char *buffer; int ret, len, offset; memset(header, 0x00, sizeof(header)); len = 0x10; if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE, PAGE_DEFAULT, len)) < 0) { perror("mode_sense_write"); return ret; } len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff)); offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff)); buffer = calloc(len, sizeof(unsigned char)); if ((len <= offset+13) || (w->data_block == 10 && len <= offset+51)) { perror("mode_sense_write"); free(buffer); return ret; } if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE, PAGE_DEFAULT, len)) < 0) { perror("mode_sense_write"); free(buffer); return ret; } buffer[offset+2] = w->ls_v << 5; buffer[offset+3] = w->track_mode | w->fpacket << 5 | w->border << 6; buffer[offset+4] = w->data_block & 0xf; buffer[offset+5] = w->link_size; buffer[offset+8] = w->session_format & 0xff; buffer[offset+10] = (w->packet_size >> 24) & 0xff; buffer[offset+11] = (w->packet_size >> 16) & 0xff; buffer[offset+12] = (w->packet_size >> 8) & 0xff; buffer[offset+13] = w->packet_size & 0xff; /* sub-header is only a mode-2 thing */ if (w->data_block == 10) { buffer[offset+48] = 0x00; buffer[offset+49] = 0x00; buffer[offset+50] = 0x08; buffer[offset+51] = 0x00; } if ((ret = mode_select(fd, buffer, len)) < 0) { hexdump(buffer, len); free(buffer); perror("mode_select"); return ret; } free(buffer); return 0; } int get_write_mode(int fd, write_params_t *w) { unsigned char header[0x10]; unsigned char *buffer; int ret, len, offset; memset(header, 0x00, sizeof(header)); len = 0x10; if ((ret = mode_sense(fd, header, GPMODE_WRITE_PARMS_PAGE, PAGE_CURRENT, len)) < 0) { perror("mode_sense_write"); return ret; } len = 2 + (((header[0] & 0xff) << 8) | (header[1] & 0xff)); offset = 8 + (((header[6] & 0xff) << 8) | (header[7] & 0xff)); buffer = calloc(len, sizeof(unsigned char)); if (len <= offset+13) { perror("mode_sense_write"); free(buffer); return ret; } if ((ret = mode_sense(fd, buffer, GPMODE_WRITE_PARMS_PAGE, PAGE_CURRENT, len)) < 0) { perror("mode_sense_write"); free(buffer); return ret; } w->ls_v = (buffer[offset+2] >> 5) & 1; w->border = (buffer[offset+3] >> 6) & 3; w->fpacket = (buffer[offset+3] >> 5) & 1; w->track_mode = buffer[offset+3] & 0xf; w->data_block = buffer[offset+4] & 0xf; w->link_size = buffer[offset+5]; w->session_format = buffer[offset+8]; w->packet_size = buffer[offset+13]; free(buffer); return 0; } int sync_cache(int fd) { struct cdrom_generic_command cgc; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = 0x35; cgc.cmd[1] = 2; return wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_SYNC); } int write_blocks(int fd, unsigned char *buffer, int lba, int blocks) { struct cdrom_generic_command cgc; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_WRITE_10; #if 0 cgc.cmd[1] = 1 << 3; #endif cgc.cmd[2] = (lba >> 24) & 0xff; cgc.cmd[3] = (lba >> 16) & 0xff; cgc.cmd[4] = (lba >> 8) & 0xff; cgc.cmd[5] = lba & 0xff; cgc.cmd[7] = (blocks >> 8) & 0xff; cgc.cmd[8] = blocks & 0xff; cgc.buflen = blocks * CDROM_BLOCK; return wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_SYNC); } int write_file(int fd, struct cdrw_disc *disc) { int file, lba, size, blocks; unsigned char *buf = NULL; int ret = 0, go_on = 1; if ((file = open(disc->filename, O_RDONLY)) < 0) { fprintf(stderr, "can't open %s\n", disc->filename); return 1; } /* for fixed packets, the write size is set. variable packets, * we write a little less than the buffer capacity. the drive * probably uses some of this for internal housekeeping, and * we want to completely eliminate buffer underruns. */ size = disc->fpacket ? disc->packet_size * CDROM_BLOCK : 63 * CDROM_BLOCK; lba = disc->offset; buf = (unsigned char *) malloc(size+1); if (buf == NULL) { perror("malloc"); close(file); return 1; } while (!ret && go_on) { blocks = disc->fpacket ? disc->packet_size : size / CDROM_BLOCK; ret = read(file, buf, size); if (ret == -1) { perror("read from file"); break; } else if (ret < size) { /* not enough data to complete the packet. fill * the rest of the data block with zeros. we must * write out complete packets every time with * fixed packets. for variable packets we just * write what we have left. */ if (disc->fpacket) { memset(&buf[ret], 0, size - ret - 1); } else { blocks = (ret + CDROM_BLOCK - 1) / CDROM_BLOCK; } /* regardless of type, this is the last write */ go_on = 0; } fprintf(stdout, "writing at lba = %d, blocks = %d\n", lba, blocks); if ((ret = write_blocks(fd, buf, lba, blocks))) break; /* sync to indicate that one packet has been sent */ // sync_cache(fd); /* for fixed packets, the run-in/run-out blocks are * contained within the packet size. variable packets * don't count them as part of the written size. */ lba += blocks; // lba += disc->fpacket ? 0 : 7; } sync_cache(fd); close(file); free(buf); return ret; } int blank_disc(int fd, int type) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_BLANK; cgc.cmd[1] = (type == BLANK_FULL ? 0 : 1); cgc.cmd[1] |= (USE_IMMED << 4); if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0) { perror("blank disc"); return ret; } print_completion_info(fd); return 0; } int format_disc(int fd, struct cdrw_disc *disc) { struct cdrom_generic_command cgc; unsigned char buffer[16]; int ret; memset(&cgc, 0, sizeof(cgc)); memset(buffer, 0, sizeof(buffer)); cgc.cmd[0] = GPCMD_FORMAT_UNIT; cgc.cmd[1] = 1 << 4 | 7; cgc.buflen = 16; /* format list header */ buffer[0] = 0; buffer[1] = 0; /* FOV: 0 (use defaults) */ buffer[1] |= (USE_IMMED << 1); buffer[2] = 0; buffer[3] = 8; /* bytes 4 through 7 are the initialization pattern, which * we just ignore. no use for CD-RW drives. */ /* format descriptor */ buffer[8] = 0x00; /* session and grow bits (7 and 6) */ buffer[9] = 0; buffer[10] = 0; buffer[11] = 0; buffer[12] = (disc->offset >> 24) & 0xff; buffer[13] = (disc->offset >> 16) & 0xff; buffer[14] = (disc->offset >> 8) & 0xff; buffer[15] = disc->offset & 0xff; if ((ret = wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_BLANK)) < 0) { perror("format disc"); return ret; } print_completion_info(fd); return 0; } int read_disc_info(int fd, disc_info_t *di) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); memset(di, 0, sizeof(disc_info_t)); cgc.cmd[0] = GPCMD_READ_DISC_INFO; cgc.cmd[8] = cgc.buflen = 2; if ((ret = wait_cmd(fd, &cgc, (unsigned char *)di, CGC_DATA_READ, WAIT_PC)) < 0) { perror("read disc info"); return ret; } cgc.buflen = be16_to_cpu(di->length) + sizeof(di->length); if (cgc.buflen > sizeof(disc_info_t)) cgc.buflen = sizeof(disc_info_t); cgc.cmd[8] = cgc.buflen; if ((ret = wait_cmd(fd, &cgc, (unsigned char *)di, CGC_DATA_READ, WAIT_PC)) < 0) { perror("read disc info"); return ret; } return 0; } int read_track_info(int fd, track_info_t *ti, int trackno) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); memset(ti, 0, sizeof(track_info_t)); cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO; cgc.cmd[1] = 1; cgc.cmd[5] = trackno; cgc.cmd[8] = cgc.buflen = 28; if ((ret = wait_cmd(fd, &cgc, (unsigned char *) ti, CGC_DATA_READ, WAIT_PC)) < 0) { perror("read track info"); return ret; } return 0; } int reserve_track(int fd, struct cdrw_disc *disc) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_RESERVE_RZONE_TRACK; cgc.cmd[5] = (disc->reserve_track >> 24) & 0xff; cgc.cmd[6] = (disc->reserve_track >> 16) & 0xff; cgc.cmd[7] = (disc->reserve_track >> 8) & 0xff; cgc.cmd[8] = disc->reserve_track & 0xff; if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0) { perror("reserve track"); return ret; } return 0; } int close_track(int fd, unsigned int track) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_CLOSE_TRACK; cgc.cmd[1] = USE_IMMED; cgc.cmd[2] = 1; /* bit 2 is close session/border */ cgc.cmd[4] = (track >> 8) & 0xff; cgc.cmd[5] = track & 0xff; if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0) { perror("close track"); return ret; } print_completion_info(fd); return 0; } int close_session(int fd, unsigned int track) { struct cdrom_generic_command cgc; int ret; memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = GPCMD_CLOSE_TRACK; cgc.cmd[1] = USE_IMMED; cgc.cmd[2] = 2; /* bit 2 is close session/border */ cgc.cmd[4] = (track >> 8) & 0xff; cgc.cmd[5] = track & 0xff; if ((ret = wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_BLANK)) < 0) { perror("close session"); return ret; } print_completion_info(fd); return 0; } int read_buffer_cap(int fd, struct cdrw_disc *disc) { struct cdrom_generic_command cgc; struct { unsigned int pad; unsigned int buffer_size; unsigned int buffer_free; } __attribute((packed)) buf; int ret; memset(&cgc, 0, sizeof(cgc)); memset(&buf, 0, sizeof(buf)); cgc.cmd[0] = 0x5c; cgc.cmd[8] = cgc.buflen = 12; if ((ret = wait_cmd(fd, &cgc, (unsigned char *)&buf, CGC_DATA_READ, WAIT_PC))) return ret; disc->buffer = be32_to_cpu(buf.buffer_size); printf("%uKB internal buffer\n", disc->buffer >> 10); return 0; } int set_cd_speed(int fd, int speed) { struct cdrom_generic_command cgc; printf("setting write speed to %ux\n", speed); memset(&cgc, 0, sizeof(cgc)); cgc.cmd[0] = 0xbb; /* read speed */ cgc.cmd[2] = 0xff; cgc.cmd[3] = 0xff; /* write speed */ cgc.cmd[4] = ((0xb0 * speed) >> 8) & 0xff; cgc.cmd[5] = (0xb0 * speed) & 0xff; return wait_cmd(fd, &cgc, NULL, CGC_DATA_NONE, WAIT_PC); } void cdrom_close(int fd) { /* enable locking */ if (ioctl(fd, CDROM_LOCKDOOR, 0) < 0) printf("can't unlock door\n"); ioctl(fd, CDROM_SET_OPTIONS, CDO_LOCK); } int cdrom_open_check(int fd) { int ret, attempts = 3; while (--attempts) { ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); if (ret < 0) return ret; if (ret == CDS_DISC_OK) break; } if (attempts == 0) return 1; /* drive should now be ready. check media */ ret = ioctl(fd, CDROM_DISC_STATUS); if (ret == CDS_AUDIO || ret < 0) return 1; /* disable locking */ if ((ret = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_LOCK)) < 0) return ret; if ((ret = ioctl(fd, CDROM_LOCKDOOR, 1)) < 0) { fprintf(stderr, "CD-ROM appears to already be opened\n"); return 1; } return 0; } void print_disc_info(disc_info_t *di) { printf("\terasable : %s\n", di->erasable ? "Yes" : "No"); printf("\tborder = %d\n", di->border); printf("\tDisc status = %d\n", di->status); printf("\tnumber of first track = %d\n", di->n_first_track); printf("\tnumber of sessions = %d\n", (di->n_sessions_m << 8) | di->n_sessions_l); printf("\tnumber of tracks = %d\n", (di->first_track_m << 8) | di->first_track_l); printf("\tstatus of last track = %d\n", (di->last_track_m << 8) | di->last_track_l); printf("\turu = %d\n", di->uru); printf("\tdid_v = %d\n", di->did_v); printf("\tdbc_v = %d\n", di->dbc_v); printf("\tdisc type = %d\n", di->disc_type); printf("\tdisc_id = %u\n", be32_to_cpu(di->disc_id)); printf("\tlead_in = %02d:%02d:%02d (%u)\n", di->lead_in_m, di->lead_in_s, di->lead_in_f, msf_to_lba(di->lead_in_m, di->lead_in_s, di->lead_in_f)); printf("\tlead_out = %02d:%02d:%02d (%u)\n", di->lead_out_m, di->lead_out_s, di->lead_out_f, msf_to_lba(di->lead_out_m, di->lead_out_s, di->lead_out_f)); printf("\tOPC entries = %u\n", di->opc_entries); printf("\n"); } void print_track_info(track_info_t *ti) { printf("\ttrack_number = %d\n", (ti->track_number_m << 8) | ti->track_number_l); printf("\tsession_number = %d\n", (ti->session_number_m << 8) | ti->session_number_l); printf("\tdamage = %d\n", ti->damage); printf("\tcopy = %d\n", ti->copy); printf("\ttrack_mode = %d\n", ti->track_mode); printf("\tRt = %d\n", ti->rt); printf("\tblank = %d\n", ti->blank); printf("\tpacket = %d\n", ti->packet); printf("\tfp = %d\n", ti->fp); printf("\tdata_mode = %d\n", ti->data_mode); printf("\tlra_v = %d\n", ti->lra_v); printf("\tnwa_v = %d\n", ti->nwa_v); printf("\ttrack_start = %u\n", be32_to_cpu(ti->track_start)); printf("\tnext_writable = %u\n", be32_to_cpu(ti->next_writable)); printf("\tlast_recorded = %u\n", be32_to_cpu(ti->last_recorded)); printf("\tfree_blocks = %u\n", be32_to_cpu(ti->free_blocks)); printf("\tpacket_size = %u\n", be32_to_cpu(ti->packet_size)); printf("\ttrack_size = %u (%uKB)\n", be32_to_cpu(ti->track_size), be32_to_cpu(ti->track_size) * 2); } int print_disc_track_info(int fd) { int ret, i; track_info_t ti; disc_info_t di; memset(&di, 0, sizeof(disc_info_t)); memset(&ti, 0, sizeof(track_info_t)); if ((ret = read_disc_info(fd, &di)) < 0) return ret; printf("\nDISC INFO:\n"); print_disc_info(&di); /* Assumes no more than 256 tracks ;) */ printf("TRACK INFO:\n"); for (i = di.n_first_track; i <= di.last_track_l; i++) { if ((ret = read_track_info(fd, &ti, i)) < 0) return ret; printf("\nTrack %d\n", i); print_track_info(&ti); } return 0; } void make_write_page(write_params_t *w, struct cdrw_disc *disc) { switch (disc->write_type) { case WRITE_MODE1: { w->data_block = 0x8; w->session_format = 0x00; break; } case WRITE_MODE2: { w->data_block = 0xa; w->session_format = 0x20; break; } } w->packet_size = disc->packet_size; w->fpacket = disc->fpacket; w->link_size = disc->link_size; w->border = disc->border; w->track_mode = w->track_mode | 0x3; } void print_params(write_params_t *wp) { fprintf(stdout, "writing %s packets\n", wp->fpacket ? "fixed" : "variable"); fprintf(stdout, "border type\t: %d\n", wp->border); fprintf(stdout, "track mode\t: %d\n", wp->track_mode); fprintf(stdout, "data block type\t: %d\n", wp->data_block); fprintf(stdout, "session format\t: %d\n", wp->session_format); fprintf(stdout, "packet size\t: %lu\n", wp->packet_size); } void cdrw_init_disc(struct cdrw_disc *disc) { disc->fpacket = 1; disc->packet_size = PACKET_BLOCK; disc->write_type = WRITE_MODE2; disc->speed = DEFAULT_SPEED; } udftools-2.0/cdrwtool/options.c0000644000175000017500000001222313221466537013640 00000000000000/* * options.c * * Copyright (c) 2002 Ben Fennema * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "config.h" #include #include #include "cdrwtool.h" #include "libudffs.h" #include "options.h" struct option long_options[] = { { "help", no_argument, NULL, OPT_HELP }, { "device", 1, NULL, 'd' }, { "set write parameters", no_argument, NULL, 's' }, { "get write parameters", no_argument, NULL, 'g' }, { "blank cdrw disc", 1, NULL, 'b' }, { "format cdrw disc", 1,NULL, 'm' }, { "run mkudffs on track", 1, NULL, 'u' }, { "set mkudffs version", 1, NULL, 'v' }, { "set cd writing speed", 1, NULL, 't' }, { "write fixed packets", 1, NULL, 'p' }, { "perform quick setup", optional_argument, NULL, 'q' }, { "reserve track", 1, NULL, 'r' }, { "close track", 1, NULL, 'c' }, { "fixed packet size", 1, NULL, 'z' }, { "border/session setting", 1, NULL, 'l' }, { "write type", 1, NULL, 'w' }, { "file to write", 1, NULL, 'f' }, { "start at this lba for file write", 1, NULL,'o' }, { "print detailed disc info", no_argument, NULL, 'i' }, { 0, 0, NULL, 0 }, }; void usage(void) { int i; printf("cdrwtool from " PACKAGE_NAME " " PACKAGE_VERSION "\nUsage:\n\tcdrwtool [options]\nOptions:\n"); for (i = 0; long_options[i].name != NULL; i++) if (long_options[i].val >= 0xFF) printf("\t--%s\t%s\n", long_options[i].name, long_options[i].name); else printf("\t-%c\t%s\n", long_options[i].val, long_options[i].name); exit(1); } void parse_args(int argc, char *argv[], struct cdrw_disc *disc, const char **device) { int retval; while ((retval = getopt_long(argc, argv, "r:t:im:u:v:d:sgq::c:C:b:p:z:l:w:f:o:h", long_options, NULL)) != EOF) { switch (retval) { case OPT_HELP: case 'h': usage(); break; case 'c': { disc->close_track = strtol(optarg, NULL, 10); break; } case 'C': { disc->close_session = strtol(optarg, NULL, 10); break; } case 'q': { disc->quick_setup = 1; if (optarg) disc->offset = strtol(optarg, NULL, 10); else disc->offset = 0; break; } case 'u': { disc->mkudf = 1; disc->offset = strtol(optarg, NULL, 10); printf("mkudffs %lu blocks\n", disc->offset); break; } case 'v': { if (udf_set_version(&disc->udf_disc, strtol(optarg, NULL, 16))) exit(1); printf("udf version set to 0x%04x\n", disc->udf_disc.udf_rev); break; } case 'r': { disc->reserve_track = strtol(optarg, NULL, 10); printf("reserving track %u\n", disc->reserve_track); break; } case 't': { disc->speed = strtol(optarg, NULL, 10); printf("setting speed to %d\n", disc->speed); break; } case 'm': { disc->format = 1; disc->offset = strtol(optarg, NULL, 10); printf("formatting %lu blocks\n", disc->offset); break; } case 'i': { disc->disc_track_info = 1; break; } case 'd': { *device = optarg; printf("using device %s\n", *device); break; } case 'g': { printf("ok, want to get\n"); disc->get_settings = 1; break; } case 's': { printf("ok, want to set\n"); disc->set_settings = 1; break; } case 'b': { if (!strcmp("full", optarg)) { printf("full blank\n"); disc->blank = BLANK_FULL; } else if (!strcmp("fast", optarg)) { printf("fast blank\n"); disc->blank = BLANK_FAST; } else { printf("full or fast blanking only\n"); exit(1); } break; } case 'p': { disc->fpacket = !!strtol(optarg, NULL, 10); printf("%s packets\n", disc->fpacket?"fixed":"variable"); break; } case 'z': { disc->packet_size = strtol(optarg, NULL, 10); printf("packet size: %d\n", disc->packet_size); break; } case 'l': { disc->border = strtol(optarg, NULL, 10); printf("border type: %d\n", disc->border); break; } case 'w': { if (!strcmp("mode1", optarg)) { printf("mode1\n"); disc->write_type = 1; } else if (!strcmp("mode2", optarg)) { printf("mode2\n"); disc->write_type = 2; } else { fprintf(stderr, "mode1 or mode2 writing only\n"); exit(1); } break; } case 'f': { disc->filename = optarg; printf("write file %s\n", disc->filename); break; } case 'o': { disc->offset = strtoul(optarg, NULL, 10); printf("write offset %lu\n", disc->offset); break; } } } if (optind < argc) usage(); } udftools-2.0/cdrwtool/main.c0000644000175000017500000002032513221466537013073 00000000000000/* * main.c * * Copyright (c) 2002 Ben Fennema * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "cdrwtool.h" #include "options.h" #include "../mkudffs/defaults.h" #include "../mkudffs/mkudffs.h" int write_func(struct udf_disc *disc, struct udf_extent *ext) { static unsigned char *buffer = NULL; static size_t bufferlen = 0; static int lastpacket = -1; int fd = *(int *)disc->write_data; size_t offset; int packet; struct udf_desc *desc; struct udf_data *data; if (buffer == NULL) { bufferlen = disc->blocksize * 32; buffer = calloc(bufferlen, 1); } if (ext == NULL) { if (lastpacket != -1) { if (write_blocks(fd, buffer, lastpacket * 32, 32) < 0) return -1; } } else if (!(ext->space_type & (USPACE|RESERVED))) { desc = ext->head; while (desc != NULL) { packet = (uint64_t)(ext->start + desc->offset) / 32; if (lastpacket != -1 && packet != lastpacket) { if (write_blocks(fd, buffer, lastpacket * 32, 32) < 0) return -1; memset(buffer, 0x00, bufferlen); } data = desc->data; offset = ((uint64_t)(ext->start + desc->offset) - (packet * 32)) * disc->blocksize; while (data != NULL) { if (data->length + offset > bufferlen) { memcpy(buffer + offset, data->buffer, bufferlen - offset); if (write_blocks(fd, buffer, packet * 32, 32) < 0) return -1; memset(buffer, 0x00, bufferlen); lastpacket = ++ packet; memcpy(buffer, data->buffer + (bufferlen - offset), data->length - (bufferlen - offset)); offset = data->length - (bufferlen - offset); } else { lastpacket = packet; memcpy(buffer + offset, data->buffer, data->length); offset += data->length; } if (offset == disc->blocksize * 32) { if (write_blocks(fd, buffer, packet * 32, 32) < 0) return -1; memset(buffer, 0x00, bufferlen); lastpacket = -1; offset = 0; packet ++; } data = data->next; } desc = desc->next; } } return 0; } int quick_setup(int fd, struct cdrw_disc *disc, const char *device) { disc_info_t di; track_info_t ti; int ret, i; unsigned blocks; printf("Settings for %s:\n", device); printf("\t%s packets, size %u\n", disc->fpacket ? "Fixed" : "Variable", disc->packet_size); printf("\tMode-%d disc\n", disc->write_type); printf( "\nI'm going to do a quick setup of %s. The disc is going to " "be blanked and formatted with one big track. All data on " "the device will be lost!! Press CTRL-C to cancel now.\n" "ENTER to continue.\n", device); getchar(); printf("Initiating quick disc blank\n"); if ((ret = blank_disc(fd, BLANK_FAST))) return ret; if ((ret = read_disc_info(fd, &di)) < 0) return ret; if ((ret = read_track_info(fd, &ti, 1)) < 0) return ret; blocks = msf_to_lba(di.lead_out_m, di.lead_out_s, di.lead_out_f) - 152; if (disc->fpacket) { /* fixed packets format usable blocks */ blocks = ((blocks + 7) / (disc->packet_size + 7)) * disc->packet_size; } printf("Disc capacity is %u blocks (%uKB/%uMB)\n", blocks, blocks * 2, blocks / 512); if (!disc->offset) disc->udf_disc.head->blocks = blocks; else disc->udf_disc.head->blocks = disc->offset; disc->udf_disc.blocks = disc->udf_disc.head->blocks; if (disc->fpacket) { if (!disc->offset) disc->offset = blocks; printf("Formatting track\n"); if ((ret = format_disc(fd, disc))) return ret; add_type2_sparable_partition(&disc->udf_disc, 0, 2, 0); disc->udf_disc.udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE); } else { disc->reserve_track = blocks; printf("Reserving track\n"); if ((ret = reserve_track(fd, disc))) return ret; } disc->udf_disc.flags |= FLAG_UNALLOC_BITMAP; for (i=0; iudf_disc.sizing[i].denomSize == 0) memcpy(&disc->udf_disc.sizing[i], &default_sizing[DEFAULT_CDRW][i], sizeof(default_sizing[DEFAULT_CDRW][i])); } split_space(&disc->udf_disc); setup_vrs(&disc->udf_disc); setup_anchor(&disc->udf_disc); setup_partition(&disc->udf_disc); setup_vds(&disc->udf_disc); dump_space(&disc->udf_disc); printf("Writing UDF structures to disc\n"); write_disc(&disc->udf_disc); disc->udf_disc.write(&disc->udf_disc, NULL); sync_cache(fd); printf("Quick setup complete!\n"); return 0; } int mkudf_session(int fd, struct cdrw_disc *disc) { int i; disc->udf_disc.head->blocks = disc->offset; disc->udf_disc.blocks = disc->udf_disc.head->blocks; add_type2_sparable_partition(&disc->udf_disc, 0, 2, 0); disc->udf_disc.udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE); disc->udf_disc.flags |= FLAG_UNALLOC_BITMAP; for (i=0; iudf_disc.sizing[i].denomSize == 0) memcpy(&disc->udf_disc.sizing[i], &default_sizing[DEFAULT_CDRW][i], sizeof(default_sizing[DEFAULT_CDRW][i])); } split_space(&disc->udf_disc); setup_vrs(&disc->udf_disc); setup_anchor(&disc->udf_disc); setup_partition(&disc->udf_disc); setup_vds(&disc->udf_disc); dump_space(&disc->udf_disc); printf("Writing UDF structures to disc\n"); write_disc(&disc->udf_disc); disc->udf_disc.write(&disc->udf_disc, NULL); sync_cache(fd); return 0; } int main(int argc, char *argv[]) { struct cdrw_disc disc; write_params_t w; const char *filename; int fd, ret; appname = "cdrwtool"; memset(&disc, 0x00, sizeof(disc)); cdrw_init_disc(&disc); udf_init_disc(&disc.udf_disc); udf_set_version(&disc.udf_disc, 0x150); disc.udf_disc.flags |= FLAG_BOOTAREA_PRESERVE; filename = CDROM_DEVICE; parse_args(argc, argv, &disc, &filename); if (((fd = open(filename, O_RDWR | O_NONBLOCK)) < 0) && ((errno != EROFS) || ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0))) { perror("open cdrom device"); return fd; } disc.udf_disc.write = write_func; disc.udf_disc.write_data = &fd; if ((ret = cdrom_open_check(fd))) { fprintf(stderr, "set_options\n"); cdrom_close(fd); return ret; } if ((ret = read_buffer_cap(fd, &disc))) { cdrom_close(fd); return ret; } if ((ret = get_write_mode(fd, &w))) { fprintf(stderr, "get_write\n"); cdrom_close(fd); return ret; } if ((ret = set_cd_speed(fd, disc.speed))) { fprintf(stderr, "set speed\n"); cdrom_close(fd); return ret; } if (disc.get_settings || disc.disc_track_info) { if (disc.get_settings) print_params(&w); if (disc.disc_track_info) print_disc_track_info(fd); cdrom_close(fd); return ret; } /* define write parameters based on command line options */ make_write_page(&w, &disc); if ((ret = set_write_mode(fd, &w))) { printf("set_write\n"); cdrom_close(fd); return ret; } if (disc.close_track) { ret = close_track(fd, disc.close_track); cdrom_close(fd); return ret; } if (disc.close_session) { ret = close_session(fd, disc.close_session); cdrom_close(fd); return ret; } if (disc.quick_setup) { ret = quick_setup(fd, &disc, filename); cdrom_close(fd); return ret; } if (disc.blank) { ret = blank_disc(fd, disc.blank); cdrom_close(fd); return ret; } if (disc.format) { ret = format_disc(fd, &disc); cdrom_close(fd); return ret; } if (disc.mkudf) { ret = mkudf_session(fd, &disc); cdrom_close(fd); return ret; } if (disc.filename) { ret = write_file(fd, &disc); cdrom_close(fd); return ret; } if (disc.reserve_track) { ret = reserve_track(fd, &disc); cdrom_close(fd); return ret; } cdrom_close(fd); return 0; } udftools-2.0/cdrwtool/Makefile.in0000644000175000017500000006114113221466653014050 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = cdrwtool$(EXEEXT) subdir = cdrwtool ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_cdrwtool_OBJECTS = main.$(OBJEXT) options.$(OBJEXT) \ cdrwtool.$(OBJEXT) mkudffs.$(OBJEXT) defaults.$(OBJEXT) \ file.$(OBJEXT) cdrwtool_OBJECTS = $(am_cdrwtool_OBJECTS) cdrwtool_DEPENDENCIES = $(top_builddir)/libudffs/libudffs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(cdrwtool_SOURCES) DIST_SOURCES = $(cdrwtool_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ cdrwtool_LDADD = $(top_builddir)/libudffs/libudffs.la cdrwtool_SOURCES = main.c options.c cdrwtool.c ../mkudffs/mkudffs.c ../mkudffs/defaults.c ../mkudffs/file.c options.h cdrwtool.h ../include/ecma_167.h ../include/osta_udf.h ../mkudffs/mkudffs.h ../mkudffs/defaults.h ../mkudffs/file.h ../include/libudffs.h ../include/udf_endian.h AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cdrwtool/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu cdrwtool/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cdrwtool$(EXEEXT): $(cdrwtool_OBJECTS) $(cdrwtool_DEPENDENCIES) $(EXTRA_cdrwtool_DEPENDENCIES) @rm -f cdrwtool$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cdrwtool_OBJECTS) $(cdrwtool_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrwtool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaults.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkudffs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mkudffs.o: ../mkudffs/mkudffs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkudffs.o -MD -MP -MF $(DEPDIR)/mkudffs.Tpo -c -o mkudffs.o `test -f '../mkudffs/mkudffs.c' || echo '$(srcdir)/'`../mkudffs/mkudffs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mkudffs.Tpo $(DEPDIR)/mkudffs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/mkudffs.c' object='mkudffs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkudffs.o `test -f '../mkudffs/mkudffs.c' || echo '$(srcdir)/'`../mkudffs/mkudffs.c mkudffs.obj: ../mkudffs/mkudffs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mkudffs.obj -MD -MP -MF $(DEPDIR)/mkudffs.Tpo -c -o mkudffs.obj `if test -f '../mkudffs/mkudffs.c'; then $(CYGPATH_W) '../mkudffs/mkudffs.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/mkudffs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mkudffs.Tpo $(DEPDIR)/mkudffs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/mkudffs.c' object='mkudffs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mkudffs.obj `if test -f '../mkudffs/mkudffs.c'; then $(CYGPATH_W) '../mkudffs/mkudffs.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/mkudffs.c'; fi` defaults.o: ../mkudffs/defaults.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT defaults.o -MD -MP -MF $(DEPDIR)/defaults.Tpo -c -o defaults.o `test -f '../mkudffs/defaults.c' || echo '$(srcdir)/'`../mkudffs/defaults.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/defaults.Tpo $(DEPDIR)/defaults.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/defaults.c' object='defaults.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o defaults.o `test -f '../mkudffs/defaults.c' || echo '$(srcdir)/'`../mkudffs/defaults.c defaults.obj: ../mkudffs/defaults.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT defaults.obj -MD -MP -MF $(DEPDIR)/defaults.Tpo -c -o defaults.obj `if test -f '../mkudffs/defaults.c'; then $(CYGPATH_W) '../mkudffs/defaults.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/defaults.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/defaults.Tpo $(DEPDIR)/defaults.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/defaults.c' object='defaults.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o defaults.obj `if test -f '../mkudffs/defaults.c'; then $(CYGPATH_W) '../mkudffs/defaults.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/defaults.c'; fi` file.o: ../mkudffs/file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.o -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.o `test -f '../mkudffs/file.c' || echo '$(srcdir)/'`../mkudffs/file.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/file.c' object='file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.o `test -f '../mkudffs/file.c' || echo '$(srcdir)/'`../mkudffs/file.c file.obj: ../mkudffs/file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.obj -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.obj `if test -f '../mkudffs/file.c'; then $(CYGPATH_W) '../mkudffs/file.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/file.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../mkudffs/file.c' object='file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.obj `if test -f '../mkudffs/file.c'; then $(CYGPATH_W) '../mkudffs/file.c'; else $(CYGPATH_W) '$(srcdir)/../mkudffs/file.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/cdrwtool/Makefile.am0000644000175000017500000000061513221466537014037 00000000000000bin_PROGRAMS = cdrwtool cdrwtool_LDADD = $(top_builddir)/libudffs/libudffs.la cdrwtool_SOURCES = main.c options.c cdrwtool.c ../mkudffs/mkudffs.c ../mkudffs/defaults.c ../mkudffs/file.c options.h cdrwtool.h ../include/ecma_167.h ../include/osta_udf.h ../mkudffs/mkudffs.h ../mkudffs/defaults.h ../mkudffs/file.h ../include/libudffs.h ../include/udf_endian.h AM_CPPFLAGS = -I$(top_srcdir)/include udftools-2.0/mkudffs/0000755000175000017500000000000013221466662011662 500000000000000udftools-2.0/mkudffs/options.h0000644000175000017500000000375213221466537013456 00000000000000/* * options.h * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef _OPTIONS_H #define _OPTIONS_H 1 void usage(void); void parse_args(int, char *[], struct udf_disc *, char **, int *, int *, int *); /* * Command line option token values. * 0x0000-0x00ff Single characters * 0x1000-0x1fff Long switches (no arg) * 0x2000-0x2fff Long settings (arg required) */ #define OPT_HELP 0x1000 #define OPT_NO_EFE 0x1001 #define OPT_LOCALE 0x1002 #define OPT_UNICODE8 0x1003 #define OPT_UNICODE16 0x1004 #define OPT_UTF8 0x1005 #define OPT_MEDIA_TYPE 0x1006 #define OPT_CLOSED 0x1007 #define OPT_VAT 0x1008 #define OPT_NEW_FILE 0x1009 #define OPT_NO_WRITE 0x1010 #define OPT_BLK_SIZE 0x2000 #define OPT_UDF_REV 0x2001 #define OPT_LVID 0x2002 #define OPT_VID 0x2003 #define OPT_VSID 0x2004 #define OPT_FSID 0x2005 #define OPT_STRATEGY 0x2006 #define OPT_SPARTABLE 0x2007 #define OPT_PACKETLEN 0x2008 #define OPT_SPARSPACE 0x2009 #define OPT_SPACE 0x200A #define OPT_AD 0x200B #define OPT_LABEL 0x200C #define OPT_UUID 0x200D #define OPT_FULLVSID 0x200E #define OPT_UID 0x200F #define OPT_GID 0x2010 #define OPT_MODE 0x2011 #define OPT_BOOTAREA 0x2012 #endif /* _OPTIONS_H */ udftools-2.0/mkudffs/file.h0000644000175000017500000000447113221466537012701 00000000000000/* * libudffs.h * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2016-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef __FILE_H #define __FILE_H #include "libudffs.h" tag query_tag(struct udf_disc *, struct udf_extent *, struct udf_desc *, uint16_t); extern tag udf_query_tag(struct udf_disc *, uint16_t, uint16_t, uint32_t, struct udf_data *, uint16_t); extern struct udf_desc *udf_create(struct udf_disc *, struct udf_extent *, const dchars *, uint8_t, uint32_t, struct udf_desc *, uint8_t, uint8_t, uint16_t); extern struct udf_desc *udf_mkdir(struct udf_disc *, struct udf_extent *, const dchars *, uint8_t, uint32_t, struct udf_desc *); extern void insert_data(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_data *data); extern void insert_fid(struct udf_disc *, struct udf_extent *, struct udf_desc *, struct udf_desc *, const dchars *, uint8_t, uint8_t); extern int udf_alloc_blocks(struct udf_disc *, struct udf_extent *, uint32_t, uint32_t); static inline void clear_bits(uint8_t *bitmap, uint32_t offset, uint64_t length) { for (;length>0;length--) { bitmap[(length+offset-1)/8] &= ~(1 << ((offset+length-1)%8)); } } static inline struct impUseVolDescImpUse *query_iuvdiu(struct udf_disc *disc) { return (struct impUseVolDescImpUse *)disc->udf_iuvd[0]->impUse; } static inline struct logicalVolIntegrityDescImpUse *query_lvidiu(struct udf_disc *disc) { return (struct logicalVolIntegrityDescImpUse *)&(disc->udf_lvid->impUse[le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps) * 2 * sizeof(uint32_t)]); } #endif /* __FILE_H */ udftools-2.0/mkudffs/defaults.h0000644000175000017500000000356513221466537013574 00000000000000/* * defaults.h * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2016-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef _DEFAULTS_H #define _DEFAULTS_H 1 extern int default_media[]; extern struct udf_sizing default_sizing[][UDF_ALLOC_TYPE_SIZE]; extern struct primaryVolDesc default_pvd; extern struct logicalVolDesc default_lvd; extern struct volDescPtr default_vdp; extern struct impUseVolDescImpUse default_iuvdiu; extern struct impUseVolDesc default_iuvd; extern struct partitionDesc default_pd; extern struct unallocSpaceDesc default_usd; extern struct terminatingDesc default_td; extern struct logicalVolIntegrityDesc default_lvid; extern struct logicalVolIntegrityDescImpUse default_lvidiu; extern struct sparingTable default_stable; extern struct sparablePartitionMap default_sparmap; extern struct virtualAllocationTable15 default_vat15; extern struct virtualAllocationTable20 default_vat20; extern struct virtualPartitionMap default_virtmap; extern struct fileSetDesc default_fsd; extern struct fileEntry default_fe; extern struct extendedFileEntry default_efe; extern struct mbr default_mbr; #endif /* _DEFAULTS_H */ udftools-2.0/mkudffs/mkudffs.h0000644000175000017500000000640713221466537013422 00000000000000/* * mkudffs.h * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2016-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef __MKUDFFS_H #define __MKUDFFS_H #include "ecma_167.h" #include "osta_udf.h" #include "udf_endian.h" #include "libudffs.h" #define CS0 0x00000001 #define UDF_ID_APPLICATION "*Linux mkudffs" #define DEFAULT_HD 0 #define DEFAULT_CD 0 #define DEFAULT_DVD 0 #define DEFAULT_DVDRAM 0 #define DEFAULT_WORM 1 #define DEFAULT_MO 1 #define DEFAULT_CDRW 2 #define DEFAULT_CDR 3 #define DEFAULT_BDR 3 #define DEFAULT_DVDRW 4 #define DEFAULT_DVDR 5 enum media_type { MEDIA_TYPE_NONE, MEDIA_TYPE_HD, MEDIA_TYPE_DVD, MEDIA_TYPE_DVDRAM, MEDIA_TYPE_DVDRW, MEDIA_TYPE_DVDR, MEDIA_TYPE_WORM, MEDIA_TYPE_MO, MEDIA_TYPE_CDRW, MEDIA_TYPE_CDR, MEDIA_TYPE_CD, MEDIA_TYPE_BDR, }; extern char *udf_space_type_str[UDF_SPACE_TYPE_SIZE]; void udf_init_disc(struct udf_disc *); int udf_set_version(struct udf_disc *, int); void get_random_bytes(void *, size_t); void split_space(struct udf_disc *); void dump_space(struct udf_disc *); int write_disc(struct udf_disc *); void setup_mbr(struct udf_disc *); void setup_vrs(struct udf_disc *); void setup_anchor(struct udf_disc *); void setup_partition(struct udf_disc *); int setup_space(struct udf_disc *, struct udf_extent *, uint32_t); int setup_fileset(struct udf_disc *, struct udf_extent *); int setup_root(struct udf_disc *, struct udf_extent *); void calc_space(struct udf_disc *, struct udf_extent *); void setup_vds(struct udf_disc *); void setup_pvd(struct udf_disc *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_lvd(struct udf_disc *, struct udf_extent *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_pd(struct udf_disc *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_usd(struct udf_disc *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_iuvd(struct udf_disc *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_td(struct udf_disc *, struct udf_extent *, struct udf_extent *, uint32_t); void setup_lvid(struct udf_disc *, struct udf_extent *); void setup_stable(struct udf_disc *, struct udf_extent *[4], struct udf_extent *); void setup_vat(struct udf_disc *, struct udf_extent *); void add_type1_partition(struct udf_disc *, uint16_t); void add_type2_sparable_partition(struct udf_disc *, uint16_t, uint8_t, uint16_t); void add_type2_virtual_partition(struct udf_disc *, uint16_t); struct sparablePartitionMap *find_type2_sparable_partition(struct udf_disc *, uint16_t); #endif /* __MKUDFFS_H */ udftools-2.0/mkudffs/options.c0000644000175000017500000005667013221466537013460 00000000000000/* * options.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * mkudffs option handling functions */ #include "config.h" #include #include #include #include #include #include #include #include "mkudffs.h" #include "defaults.h" #include "options.h" static struct option long_options[] = { { "help", no_argument, NULL, OPT_HELP }, { "label", required_argument, NULL, OPT_LABEL }, { "uuid", required_argument, NULL, OPT_UUID }, { "blocksize", required_argument, NULL, OPT_BLK_SIZE }, { "udfrev", required_argument, NULL, OPT_UDF_REV }, { "lvid", required_argument, NULL, OPT_LVID }, { "vid", required_argument, NULL, OPT_VID }, { "vsid", required_argument, NULL, OPT_VSID }, { "fsid", required_argument, NULL, OPT_FSID }, { "fullvsid", required_argument, NULL, OPT_FULLVSID }, { "uid", required_argument, NULL, OPT_UID }, { "gid", required_argument, NULL, OPT_GID }, { "mode", required_argument, NULL, OPT_MODE }, { "bootarea", required_argument, NULL, OPT_BOOTAREA }, { "strategy", required_argument, NULL, OPT_STRATEGY }, { "spartable", optional_argument, NULL, OPT_SPARTABLE }, { "sparspace", required_argument, NULL, OPT_SPARSPACE }, { "packetlen", required_argument, NULL, OPT_PACKETLEN }, { "media-type", required_argument, NULL, OPT_MEDIA_TYPE }, { "space", required_argument, NULL, OPT_SPACE }, { "ad", required_argument, NULL, OPT_AD }, { "vat", no_argument, NULL, OPT_VAT }, { "noefe", no_argument, NULL, OPT_NO_EFE }, { "locale", no_argument, NULL, OPT_LOCALE }, { "u8", no_argument, NULL, OPT_UNICODE8 }, { "u16", no_argument, NULL, OPT_UNICODE16 }, { "utf8", no_argument, NULL, OPT_UTF8 }, { "closed", no_argument, NULL, OPT_CLOSED }, { "new-file", no_argument, NULL, OPT_NEW_FILE }, { "no-write", no_argument, NULL, OPT_NO_WRITE }, { 0, 0, NULL, 0 }, }; void usage(void) { fprintf(stderr, "mkudffs from " PACKAGE_NAME " " PACKAGE_VERSION "\n" "Usage:\n" "\tmkudffs [options] device [blocks-count]\n" "Options:\n" "\t--help, -h Display this help\n" "\t--label=, -l UDF label, synonym for both --lvid and --vid (default: LinuxUDF)\n" "\t--uuid=, -u UDF uuid, first 16 characters of Volume set identifier (default: random)\n" "\t--blocksize=, -b Size of blocks in bytes (512, 1024, 2048, 4096, 8192, 16384, 32768; default: detect)\n" "\t--media-type=, -m Media type (hd, dvd, dvdram, dvdrw, dvdr, worm, mo, cdrw, cdr, cd, bdr; default: hd)\n" "\t--udfrev=, -r UDF revision (1.02, 1.50, 2.00, 2.01, 2.50, 2.60; default: 2.01)\n" "\t--no-write, -n Not really, do not write to device, just simulate\n" "\t--new-file Create new image file, fail if already exists\n" "\t--lvid= Logical Volume Identifier (default: LinuxUDF)\n" "\t--vid= Volume Identifier (default: LinuxUDF)\n" "\t--vsid= 17.-127. character of Volume Set Identifier (default: LinuxUDF)\n" "\t--fsid= File Set Identifier (default: LinuxUDF)\n" "\t--fullvsid= Full Volume Set Identifier, overwrite --uuid and --vsid\n" "\t--uid= Uid of the root directory (default: 0)\n" "\t--gid= Gid of the root directory (default: 0)\n" "\t--mode= Permissions (octal mode bits) of the root directory (default: 0755)\n" "\t--bootarea= UDF boot area (preserve, erase, mbr; default: based on media type)\n" "\t--strategy= Allocation strategy to use (4, 4096; default: based on media type)\n" "\t--spartable Use Sparing Table (default: based on media type) and set its count (1 - 4; default: 2)\n" "\t--sparspace= Number of entries in Sparing Table (default: 1024, but based on media type)\n" "\t--packetlen= Packet length in number of blocks for Sparing Table (default: based on media type)\n" "\t--vat Use Virtual Allocation Table (default: based on media type)\n" "\t--closed Close disc with Virtual Allocation Table (default: do not close)\n" "\t--space= Space (freedbitmap, freedtable, unallocbitmap, unalloctable; default: unallocbitmap)\n" "\t--ad= Allocation descriptor (inicb, short, long; default: inicb)\n" "\t--noefe Don't Use Extended File Entries (default: use for UDF revision >= 2.00)\n" "\t--locale String options are encoded according to current locale (default)\n" "\t--u8 String options are encoded in 8-bit OSTA Compressed Unicode format\n" "\t--u16 String options are encoded in 16-bit OSTA Compressed Unicode format\n" "\t--utf8 String options are encoded in UTF-8\n" ); exit(1); } static unsigned long int strtoul_safe(const char *str, int base, int *failed) { char *endptr = NULL; unsigned long int ret; errno = 0; ret = strtoul(str, &endptr, base); *failed = (!*str || *endptr || errno) ? 1 : 0; return ret; } void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, int *create_new_file, int *blocksize, int *media_ptr) { int retval; int i; int media = MEDIA_TYPE_NONE; uint16_t packetlen = 0; unsigned long int blocks = 0; int rev = 0; int use_sparable = 0; unsigned long int sparspace = 0; int failed; while ((retval = getopt_long(argc, argv, "l:u:b:m:r:nh", long_options, NULL)) != EOF) { switch (retval) { case OPT_HELP: case 'h': usage(); break; case OPT_BLK_SIZE: case 'b': disc->blocksize = strtoul_safe(optarg, 0, &failed); if (failed || disc->blocksize < 512 || disc->blocksize > 32768 || (disc->blocksize & (disc->blocksize - 1))) { fprintf(stderr, "%s: Error: Invalid value for option --blocksize\n", appname); exit(1); } disc->udf_lvd[0]->logicalBlockSize = cpu_to_le32(disc->blocksize); *blocksize = disc->blocksize; break; case OPT_UDF_REV: case 'r': { unsigned char maj = 0; unsigned char min = 0; int len = 0; if (sscanf(optarg, "%hhx.%hhx%n", &maj, &min, &len) >= 2 && !optarg[len]) { rev = (maj << 8) | min; } else { unsigned long int rev_opt = strtoul_safe(optarg, 16, &failed); if (!failed && rev_opt < INT_MAX) rev = rev_opt; else rev = 0; } if (!rev || udf_set_version(disc, rev)) { fprintf(stderr, "%s: Error: Invalid value for option --udfrev\n", appname); exit(1); } if (rev < 0x0150 && (media == MEDIA_TYPE_DVDRW || media == MEDIA_TYPE_DVDR || media == MEDIA_TYPE_CDRW || media == MEDIA_TYPE_CDR)) { fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for CD-R/CD-RW/DVD-R/DVD-RW discs\n", appname); exit(1); } if (rev < 0x0250 && media == MEDIA_TYPE_BDR) { fprintf(stderr, "%s: Error: At least UDF revision 2.50 is needed for BD-R discs\n", appname); exit(1); } if (rev < 0x0150 && use_sparable) { fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for Sparing Table\n", appname); exit(1); } break; } case OPT_NO_WRITE: case 'n': { disc->flags |= FLAG_NO_WRITE; break; } case OPT_NO_EFE: { disc->flags &= ~FLAG_EFE; break; } case OPT_NEW_FILE: { *create_new_file = 1; break; } case OPT_UNICODE8: { disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE8; if (strcmp(argv[1], "--u8") != 0) { fprintf(stderr, "%s: Error: Option --u8 must be specified as first argument\n", appname); exit(1); } break; } case OPT_UNICODE16: { disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UNICODE16; if (strcmp(argv[1], "--u16") != 0) { fprintf(stderr, "%s: Error: Option --u16 must be specified as first argument\n", appname); exit(1); } break; } case OPT_UTF8: { disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_UTF8; if (strcmp(argv[1], "--utf8") != 0) { fprintf(stderr, "%s: Error: Option --utf8 must be specified as first argument\n", appname); exit(1); } break; } case OPT_LOCALE: { disc->flags &= ~FLAG_CHARSET; disc->flags |= FLAG_LOCALE; if (strcmp(argv[1], "--locale") != 0) { fprintf(stderr, "%s: Error: Option --locale must be specified as first argument\n", appname); exit(1); } break; } case OPT_CLOSED: { if (!(disc->flags & FLAG_VAT)) { fprintf(stderr, "%s: Error: Option --vat must be specified before option --closed\n", appname); exit(1); } disc->flags |= FLAG_CLOSED; break; } case OPT_VAT: { disc->flags |= FLAG_VAT; disc->flags &= ~FLAG_CLOSED; break; } case OPT_LVID: case OPT_VID: case OPT_LABEL: case 'l': { if (retval != OPT_VID) { struct impUseVolDescImpUse *iuvdiu; if (encode_string(disc, disc->udf_lvd[0]->logicalVolIdent, optarg, 128) == (size_t)-1) { fprintf(stderr, "%s: Error: Option %s is too long\n", appname, (retval == OPT_LVID) ? "--lvid" : "--label"); exit(1); } iuvdiu = (struct impUseVolDescImpUse *)disc->udf_iuvd[0]->impUse; memcpy(iuvdiu->logicalVolIdent, disc->udf_lvd[0]->logicalVolIdent, 128); memcpy(disc->udf_fsd->logicalVolIdent, disc->udf_lvd[0]->logicalVolIdent, 128); } if (retval != OPT_LVID) { if (encode_string(disc, disc->udf_pvd[0]->volIdent, optarg, 32) == (size_t)-1) { if (retval == OPT_VID) { fprintf(stderr, "%s: Error: Option --vid is too long\n", appname); exit(1); } /* This code was not triggered by --vid option, do not throw error but rather store truncated --lvid */ memcpy(disc->udf_pvd[0]->volIdent, disc->udf_lvd[0]->logicalVolIdent, 32); disc->udf_pvd[0]->volIdent[31] = 31; } } break; } case OPT_VSID: { dstring ts[128]; size_t len = encode_string(disc, ts, optarg, 128); if (len == (size_t)-1 || len > 127-16 || (ts[0] == 16 && len > 127-16*2) || (ts[0] == 8 && disc->udf_pvd[0]->volSetIdent[0] == 16 && len > (127-16*2-1)/2+1)) // 2*(len-1)+1 > 127-16*2 { fprintf(stderr, "%s: Error: Option --vsid is too long\n", appname); exit(1); } if (ts[0] == disc->udf_pvd[0]->volSetIdent[0]) { for (i = 0; i < 16; ++i) { if (ts[0] == 8) { if (!disc->udf_pvd[0]->volSetIdent[i+1]) disc->udf_pvd[0]->volSetIdent[i+1] = '0'; } else if (ts[0] == 16) { if (!disc->udf_pvd[0]->volSetIdent[(2*i)+1] && !disc->udf_pvd[0]->volSetIdent[(2*i)+2]) disc->udf_pvd[0]->volSetIdent[(2*i)+2] = '0'; } } } else if(ts[0] == 16) { disc->udf_pvd[0]->volSetIdent[0] = 16; for (i = 17; i > 0; --i) { disc->udf_pvd[0]->volSetIdent[(2*(i-1))+1] = 0; disc->udf_pvd[0]->volSetIdent[(2*(i-1))+2] = disc->udf_pvd[0]->volSetIdent[i]; if (!disc->udf_pvd[0]->volSetIdent[(2*(i-1))+2]) disc->udf_pvd[0]->volSetIdent[(2*(i-1))+2] = '0'; } } else if(ts[0] == 8 && disc->udf_pvd[0]->volSetIdent[0] == 16) { ts[0] = 16; for (i = len; i > 0; --i) { ts[(2*(i-1))+2] = ts[i]; ts[(2*(i-1))+1] = 0; } len = (len-1)*2+1; } if (len) memcpy(&disc->udf_pvd[0]->volSetIdent[1+16*(ts[0]/8)], &ts[1], len-1+(ts[0]/8)); disc->udf_pvd[0]->volSetIdent[127] = 16*(ts[0]/8)+len; for (i = disc->udf_pvd[0]->volSetIdent[127]; i < 127; ++i) disc->udf_pvd[0]->volSetIdent[i] = 0; break; } case OPT_UUID: case 'u': { if (strlen(optarg) != 16) { fprintf(stderr, "%s: Error: Option --uuid is not 16 bytes long\n", appname); exit(1); } for (i = 0; i < 16; ++i) { if (!isxdigit(optarg[i]) || (!isdigit(optarg[i]) && !islower(optarg[i]))) { fprintf(stderr, "%s: Error: Option --uuid is not in lowercase hexadecimal digit format\n", appname); exit(1); } } if (disc->udf_pvd[0]->volSetIdent[0] == 8) { memcpy(&disc->udf_pvd[0]->volSetIdent[1], optarg, 16); if (disc->udf_pvd[0]->volSetIdent[127] < 17) { disc->udf_pvd[0]->volSetIdent[17] = 0; disc->udf_pvd[0]->volSetIdent[127] = 17; } } else if (disc->udf_pvd[0]->volSetIdent[0] == 16) { for (i = 0; i < 16; ++i) { disc->udf_pvd[0]->volSetIdent[2*i+1] = 0; disc->udf_pvd[0]->volSetIdent[2*i+2] = optarg[i]; } if (disc->udf_pvd[0]->volSetIdent[127] < 2*16+1) { disc->udf_pvd[0]->volSetIdent[2*16+1] = 0; disc->udf_pvd[0]->volSetIdent[2*16+2] = 0; disc->udf_pvd[0]->volSetIdent[127] = 2*16+1; } } break; } case OPT_FULLVSID: { if (encode_string(disc, disc->udf_pvd[0]->volSetIdent, optarg, 128) == (size_t)-1) { fprintf(stderr, "%s: Error: Option --fullvsid is too long\n", appname); exit(1); } break; } case OPT_FSID: { if (encode_string(disc, disc->udf_fsd->fileSetIdent, optarg, 32) == (size_t)-1) { fprintf(stderr, "%s: Error: Option --fsid is too long\n", appname); exit(1); } break; } case OPT_UID: { unsigned long int uid = strtoul_safe(optarg, 0, &failed); if (strcmp(optarg, "-1") == 0) { uid = UINT32_MAX; failed = 0; } if (failed || uid > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --uid\n", appname); exit(1); } disc->uid = uid; break; } case OPT_GID: { unsigned long int gid = strtoul_safe(optarg, 0, &failed); if (strcmp(optarg, "-1") == 0) { gid = UINT32_MAX; failed = 0; } if (failed || gid > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --gid\n", appname); exit(1); } disc->gid = gid; break; } case OPT_MODE: { unsigned long int mode = strtoul_safe(optarg, 8, &failed); if (failed || mode > UINT16_MAX || (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO))) { fprintf(stderr, "%s: Error: Invalid value for option --mode\n", appname); exit(1); } disc->mode = mode; break; } case OPT_BOOTAREA: { disc->flags &= ~FLAG_BOOTAREA_MASK; if (!strcmp(optarg, "preserve")) disc->flags |= FLAG_BOOTAREA_PRESERVE; else if (!strcmp(optarg, "erase")) disc->flags |= FLAG_BOOTAREA_ERASE; else if (!strcmp(optarg, "mbr")) disc->flags |= FLAG_BOOTAREA_MBR; else { fprintf(stderr, "%s: Error: Invalid value for option --bootarea\n", appname); exit(1); } break; } case OPT_STRATEGY: { unsigned long int strategy = strtoul_safe(optarg, 0, &failed); if (failed || (strategy != 4 && strategy != 4096)) { fprintf(stderr, "%s: Error: Invalid value for option --strategy\n", appname); exit(1); } if (strategy == 4096) disc->flags |= FLAG_STRATEGY4096; else disc->flags &= ~FLAG_STRATEGY4096; break; } case OPT_SPARTABLE: { unsigned long int spartable = 2; if (optarg) { spartable = strtoul_safe(optarg, 0, &failed); if (failed || spartable > 4) { fprintf(stderr, "%s: Error: Invalid value for option --spartable\n", appname); exit(1); } } if (disc->flags & FLAG_VAT) { fprintf(stderr, "%s: Error: Cannot use Sparing Table when VAT is enabled\n", appname); exit(1); } add_type2_sparable_partition(disc, 0, spartable, packetlen); use_sparable = 1; break; } case OPT_SPARSPACE: { if (!use_sparable) { fprintf(stderr, "%s: Error: Option --spartable must be specified before option --sparspace\n", appname); exit(1); } sparspace = strtoul_safe(optarg, 0, &failed); if (failed || sparspace > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --sparspace\n", appname); exit(1); } break; } case OPT_PACKETLEN: { struct sparablePartitionMap *spm; unsigned long int packetlen_opt = strtoul_safe(optarg, 0, &failed); if (failed || packetlen_opt > UINT16_MAX) { fprintf(stderr, "%s: Error: Invalid value for option --packetlen\n", appname); exit(1); } packetlen = packetlen_opt; if ((spm = find_type2_sparable_partition(disc, 0))) spm->packetLength = cpu_to_le16(packetlen); break; } case OPT_MEDIA_TYPE: case 'm': { if (rev) { fprintf(stderr, "%s: Error: Option --media-type must be specified before option --udfrev\n", appname); exit(1); } if (packetlen) { fprintf(stderr, "%s: Error: Option --media-type must be specified before option --packetlen\n", appname); exit(1); } if (media != MEDIA_TYPE_NONE) { fprintf(stderr, "%s: Error: Option --media-type was specified more times\n", appname); exit(1); } if (!strcmp(optarg, "hd")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE); media = MEDIA_TYPE_HD; } else if (!strcmp(optarg, "dvd")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY); media = MEDIA_TYPE_DVD; } else if (!strcmp(optarg, "dvdram")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE); media = MEDIA_TYPE_DVDRAM; } else if (!strcmp(optarg, "dvdrw")) { struct sparablePartitionMap *spm; disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE); media = MEDIA_TYPE_DVDRW; use_sparable = 1; packetlen = 16; if ((spm = find_type2_sparable_partition(disc, 0))) spm->packetLength = cpu_to_le16(packetlen); } else if (!strcmp(optarg, "dvdr")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE); media = MEDIA_TYPE_DVDR; disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS; disc->flags &= ~FLAG_CLOSED; } else if (!strcmp(optarg, "worm")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE); media = MEDIA_TYPE_WORM; disc->flags |= (FLAG_STRATEGY4096 | FLAG_BLANK_TERMINAL); } else if (!strcmp(optarg, "mo")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE); media = MEDIA_TYPE_MO; disc->flags |= (FLAG_STRATEGY4096 | FLAG_BLANK_TERMINAL); } else if (!strcmp(optarg, "cdrw")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE); media = MEDIA_TYPE_CDRW; use_sparable = 1; } else if (!strcmp(optarg, "cdr")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE); media = MEDIA_TYPE_CDR; disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS; disc->flags &= ~FLAG_CLOSED; } else if (!strcmp(optarg, "cd")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY); media = MEDIA_TYPE_CD; } else if (!strcmp(optarg, "bdr")) { disc->udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE); media = MEDIA_TYPE_BDR; disc->flags |= FLAG_VAT | FLAG_MIN_300_BLOCKS; disc->flags &= ~FLAG_CLOSED; udf_set_version(disc, 0x0250); } else { fprintf(stderr, "%s: Error: Invalid value for option --media-type\n", appname); exit(1); } break; } case OPT_SPACE: { if (!strncmp(optarg, "freedbitmap", 11)) disc->flags |= FLAG_FREED_BITMAP; else if (!strncmp(optarg, "freedtable", 10)) disc->flags |= FLAG_FREED_TABLE; else if (!strncmp(optarg, "unallocbitmap", 13)) disc->flags |= FLAG_UNALLOC_BITMAP; else if (!strncmp(optarg, "unalloctable", 12)) disc->flags |= FLAG_UNALLOC_TABLE; else { fprintf(stderr, "%s: Error: Invalid value for option --space\n", appname); exit(1); } break; } case OPT_AD: { if (!strncmp(optarg, "inicb", 5)) { default_fe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_IN_ICB); default_efe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_IN_ICB); } else if (!strncmp(optarg, "short", 5)) { default_fe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_SHORT); default_efe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_SHORT); } else if (!strncmp(optarg, "long", 4)) { default_fe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_LONG); default_efe.icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_LONG); } else { fprintf(stderr, "%s: Error: Invalid value for option --ad\n", appname); exit(1); } break; } default: exit(1); } } if (optind == argc) usage(); *device = argv[optind]; optind ++; if (optind < argc) { blocks = strtoul_safe(argv[optind++], 0, &failed); if (failed || blocks > UINT32_MAX) { fprintf(stderr, "%s: Error: Invalid value for block-count\n", appname); exit(1); } disc->blocks = blocks; } if (optind < argc) usage(); if (packetlen && !use_sparable) { fprintf(stderr, "%s: Error: Option --packetlen cannot be used without Sparing Table\n", appname); exit(1); } if (le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps) == 0) { if (disc->flags & FLAG_VAT) { if (disc->udf_rev < 0x0150) { fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for VAT\n", appname); exit(1); } add_type1_partition(disc, 0); add_type2_virtual_partition(disc, 0); } else if (use_sparable) { if (disc->udf_rev < 0x0150) { fprintf(stderr, "%s: Error: At least UDF revision 1.50 is needed for Sparing Table\n", appname); exit(1); } add_type2_sparable_partition(disc, 0, 2, packetlen); } else add_type1_partition(disc, 0); } /* TODO: UDF 2.50+ require for non-VAT disks Metadata partition which mkudffs cannot create yet */ if (rev > 0x0201 && !(disc->flags & FLAG_VAT)) { fprintf(stderr, "%s: Error: UDF revision above 2.01 is not currently supported for specified media type\n", appname); exit(1); } if ((disc->flags & FLAG_VAT) && (disc->flags & FLAG_SPACE)) { fprintf(stderr, "%s: Error: Option --space cannot be used for VAT\n", appname); exit(1); } if (!(disc->flags & FLAG_VAT) && !(disc->flags & FLAG_SPACE)) disc->flags |= FLAG_UNALLOC_BITMAP; if ((disc->flags & FLAG_STRATEGY4096) && (disc->flags & FLAG_VAT)) { fprintf(stderr, "%s: Error: Cannot use strategy type 4096 for VAT\n", appname); exit(1); } /* TODO: autodetection */ if (media == MEDIA_TYPE_NONE) media = MEDIA_TYPE_HD; for (i=0; isizing[i].denomSize == 0) disc->sizing[i] = default_sizing[default_media[media]][i]; } if (use_sparable) { if (sparspace) { disc->sizing[SSPACE_SIZE].minSize = sparspace; disc->sizing[STABLE_SIZE].minSize = 0; // recalculation is implemented in split_space() } if (!packetlen) packetlen = le16_to_cpu(default_sparmap.packetLength); disc->sizing[PSPACE_SIZE].align = packetlen; disc->sizing[SSPACE_SIZE].align = packetlen; disc->sizing[STABLE_SIZE].align = packetlen; if (disc->sizing[SSPACE_SIZE].minSize == 0) disc->sizing[SSPACE_SIZE].minSize = 1024; } *media_ptr = media; } udftools-2.0/mkudffs/file.c0000644000175000017500000010237213221466537012673 00000000000000/* * file.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2016-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * libudffs file and directory handling functions */ #include "config.h" #include #include #include #include "libudffs.h" #include "file.h" #include "defaults.h" /** * For a more detailed discussion of partition and extends see the comments * at the top of extent.c in this directory. * * An information control block (ICB) is an on-disc structure used to * store information about files such as allocation descriptors. The * structure of the ICB hierarchy can be quite complex for write-once * media which use various strategies of linked lists to preserve multiple * historial file versions. Strategy type 4 is normally used on rewritable * media where an ICB containing 'direct entries' can be updated as needed. * * Every file has a file entry/extended file entry (tag:FE/EFE) udf_descriptor * which is in the root of the ICB hierarchy for the file. For normal files the * FE/EFE can be thought of as the 'inode' for the file as it contains the * location of the on-disc extents of the file. Small amounts of data can be * recorded directly in the allocation descriptor area of the FE/EFE ICB if it * is deemed useful. This 'INICB' feature is used for directories with strategy * type 4. * * A file identifier descriptor (tag:FID) udf_descriptor is a 40+ byte structure * recorded in a directory file to describe the parent directory and any files * or subdirectories. The unnamed parent entry is always recorded first and the * parent of the root directory is the root directory, generally referred to * as ''. All other files/directories must have a non-zero length name. * Along with the name and attributes of the file a FID contains the location * of the file FE/EFE 'inode' ICB. While not required, this may be recorded * adjacent to the file data on-disc for convenience. * * The notation tag:FE/EFE means a udf_descriptor with an ident of either * TAG_IDENT_FE or TAG_IDENT_EFE with the on-disc format FE/EFE structure * stored in the first udf_data item on the udf_data list of that udf_descriptor. * The 16-byte on-disc format tag will be at the beginning of that structure. * Additional information such as the FID structure for directory entries will * be stored in subsequent entries on the list. */ /** * @brief create an on-disc format tag for a udf_descriptor of a * udf_extent with any space_type. For type:PSPACE the block * number will be relative to to the first block of the partition, * otherwise it will be relative to the first block of the media * @param disc the udf_disc * @param ext the udf_extent containing the udf_descriptor * @param desc the udf_descriptor * @param SerialNum the serial number to assign * @return the tag */ tag query_tag(struct udf_disc *disc, struct udf_extent *ext, struct udf_desc *desc, uint16_t SerialNum) { tag ret; int i; struct udf_data *data; uint16_t crc = 0; int offset = sizeof(tag); ret.tagIdent = cpu_to_le16(desc->ident); if (disc->udf_rev >= 0x0200) ret.descVersion = cpu_to_le16(3); else ret.descVersion = cpu_to_le16(2); ret.tagChecksum = 0; ret.reserved = 0; ret.tagSerialNum = cpu_to_le16(SerialNum); ret.descCRCLength = cpu_to_le16(desc->length - sizeof(tag)); data = desc->data; while (data != NULL) { crc = udf_crc(data->buffer + offset, data->length - offset, crc); offset = 0; data = data->next; } ret.descCRC = cpu_to_le16(crc); if (ext->space_type & PSPACE) ret.tagLocation = cpu_to_le32(desc->offset); else ret.tagLocation = cpu_to_le32(ext->start + desc->offset); for (i=0; i<16; i++) if (i != 4) ret.tagChecksum += (uint8_t)(((char *)&ret)[i]); return ret; } /** * @brief create an on-disc format tag from udf_descriptor components * @param disc the udf_disc * @param Ident the tag:Ident to assign * @param SerialNum the serial number to assign * @param Location the block number of the on-disc tag:Ident udf_descriptor * @param data the udf_data list head * @param length the summed data length * @return the tag */ tag udf_query_tag(struct udf_disc *disc, uint16_t Ident, uint16_t SerialNum, uint32_t Location, struct udf_data *data, uint16_t length) { tag ret; int i; uint16_t crc = 0; int offset = sizeof(tag); int clength; ret.tagIdent = cpu_to_le16(Ident); if (disc->udf_rev >= 0x0200) ret.descVersion = cpu_to_le16(3); else ret.descVersion = cpu_to_le16(2); ret.tagChecksum = 0; ret.reserved = 0; ret.tagSerialNum = cpu_to_le16(SerialNum); ret.descCRCLength = cpu_to_le16(length - sizeof(tag)); while (data != NULL && length) { if ((clength = data->length) > length) clength = length; crc = udf_crc(data->buffer + offset, clength - offset, crc); length -= clength; offset = 0; data = data->next; } ret.descCRC = cpu_to_le16(crc); ret.tagLocation = cpu_to_le32(Location); for (i=0; i<16; i++) if (i != 4) ret.tagChecksum += (uint8_t)(((char *)&ret)[i]); return ret; } /** * @brief append a udf_data item containing a FID in the payload to the * udf_data list for a directory tag:FE/EFE udf_descriptor * @param disc the udf_disc * @param pspace the type:PSPACE udf_extent for on-disc allocations * @param desc the file tag:FE/EFE udf_descriptor (for offset) * @param parent the directory tag:FE/EFE udf_descriptor * @param data the udf_data item containing the FID * @return the block number of the on-disc tag:FID udf_desciptor */ int insert_desc(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_desc *parent, struct udf_data *data) { uint32_t block = 0; if (disc->flags & FLAG_EFE) { struct extendedFileEntry *efe = (struct extendedFileEntry *)parent->data->buffer; if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB) { block = parent->offset; append_data(parent, data); efe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(efe->lengthAllocDescs) + data->length); } else { struct udf_desc *fiddesc = NULL; if (le32_to_cpu(efe->lengthAllocDescs) == 0) { block = udf_alloc_blocks(disc, pspace, desc->offset, 1); fiddesc = set_desc(pspace, TAG_IDENT_FID, block, data->length, data); if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT) { short_ad *sad; parent->length += sizeof(short_ad); parent->data->length += sizeof(short_ad); parent->data->buffer = realloc(parent->data->buffer, parent->length); efe = (struct extendedFileEntry *)parent->data->buffer; sad = (short_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs)]; sad->extPosition = cpu_to_le32(block); sad->extLength = cpu_to_le32(data->length); efe->lengthAllocDescs = cpu_to_le32(sizeof(short_ad)); } else if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG) { long_ad *lad; parent->length += sizeof(long_ad); parent->data->length += sizeof(long_ad); parent->data->buffer = realloc(parent->data->buffer, parent->length); efe = (struct extendedFileEntry *)parent->data->buffer; lad = (long_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs)]; lad->extLocation.logicalBlockNum = cpu_to_le32(block); lad->extLocation.partitionReferenceNum = cpu_to_le16(0); lad->extLength = cpu_to_le32(data->length); efe->lengthAllocDescs = cpu_to_le32(sizeof(long_ad)); } efe->logicalBlocksRecorded = cpu_to_le32(1); } else { if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT) { short_ad *sad; sad = (short_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs) - sizeof(short_ad)]; fiddesc = find_desc(pspace, le32_to_cpu(sad->extPosition)); block = fiddesc->offset; append_data(fiddesc, data); sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) + data->length); } else if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG) { long_ad *lad; lad = (long_ad *)&efe->allocDescs[le32_to_cpu(efe->lengthExtendedAttr) + le32_to_cpu(efe->lengthAllocDescs) - sizeof(long_ad)]; fiddesc = find_desc(pspace, le32_to_cpu(lad->extLocation.logicalBlockNum)); block = fiddesc->offset; append_data(fiddesc, data); lad->extLength = cpu_to_le32(le32_to_cpu(lad->extLength) + data->length); } } } } else { struct fileEntry *fe = (struct fileEntry *)parent->data->buffer; if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB) { block = parent->offset; append_data(parent, data); fe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(fe->lengthAllocDescs) + data->length); } else { struct udf_desc *fiddesc = NULL; if (le32_to_cpu(fe->lengthAllocDescs) == 0) { block = udf_alloc_blocks(disc, pspace, desc->offset, 1); fiddesc = set_desc(pspace, TAG_IDENT_FID, block, data->length, data); if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT) { short_ad *sad; parent->length += sizeof(short_ad); parent->data->length += sizeof(short_ad); parent->data->buffer = realloc(parent->data->buffer, parent->length); fe = (struct fileEntry *)parent->data->buffer; sad = (short_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs)]; sad->extPosition = cpu_to_le32(block); sad->extLength = cpu_to_le32(data->length); fe->lengthAllocDescs = cpu_to_le32(sizeof(short_ad)); } else if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG) { long_ad *lad; parent->length += sizeof(long_ad); parent->data->length += sizeof(long_ad); parent->data->buffer = realloc(parent->data->buffer, parent->length); fe = (struct fileEntry *)parent->data->buffer; lad = (long_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs)]; lad->extLocation.logicalBlockNum = cpu_to_le32(block); lad->extLocation.partitionReferenceNum = cpu_to_le16(0); lad->extLength = cpu_to_le32(data->length); fe->lengthAllocDescs = cpu_to_le32(sizeof(long_ad)); } fe->logicalBlocksRecorded = cpu_to_le32(1); } else { if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_SHORT) { short_ad *sad; sad = (short_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs) - sizeof(short_ad)]; fiddesc = find_desc(pspace, le32_to_cpu(sad->extPosition)); block = fiddesc->offset; append_data(fiddesc, data); sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) + data->length); } else if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_LONG) { long_ad *lad; lad = (long_ad *)&fe->allocDescs[le32_to_cpu(fe->lengthExtendedAttr) + le32_to_cpu(fe->lengthAllocDescs) - sizeof(long_ad)]; fiddesc = find_desc(pspace, le32_to_cpu(lad->extLocation.logicalBlockNum)); block = fiddesc->offset; append_data(fiddesc, data); lad->extLength = cpu_to_le32(le32_to_cpu(lad->extLength) + data->length); } } } } return block; } /** * @brief append a udf_data list to a (hidden) VAT file ??? * @param disc the udf_disc * @param pspace the type:PSPACE udf_extent for on-disc allocations * @param desc the file tag:FE/EFE udf_descriptor of a VAT file * @param data the udf_data list head * @return void */ void insert_data(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_data *data) { if (disc->flags & FLAG_EFE) { struct extendedFileEntry *efe = (struct extendedFileEntry *)desc->data->buffer; if ((le16_to_cpu(efe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB) { append_data(desc, data); efe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(efe->lengthAllocDescs) + data->length); efe->informationLength = cpu_to_le64(le64_to_cpu(efe->informationLength) + data->length); efe->objectSize = cpu_to_le64(le64_to_cpu(efe->objectSize) + data->length); } else { fprintf(stderr, "%s: Error: Cannot insert data when inicb is not used\n", appname); exit(1); } } else { struct fileEntry *fe = (struct fileEntry *)desc->data->buffer; if ((le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK) == ICBTAG_FLAG_AD_IN_ICB) { append_data(desc, data); fe->lengthAllocDescs = cpu_to_le32(le32_to_cpu(fe->lengthAllocDescs) + data->length); fe->informationLength = cpu_to_le64(le64_to_cpu(fe->informationLength) + data->length); } else { fprintf(stderr, "%s: Error: Cannot insert data when inicb is not used\n", appname); exit(1); } } *(tag *)desc->data->buffer = query_tag(disc, pspace, desc, 1); } /** * @brief helper function to compute tag:FID udf_descriptor size and padding * to a multiple of 4 bytes * @param length the length of the file name in bytes * @return the length of the required memory allocation */ uint32_t compute_ident_length(uint32_t length) { return length + (4 - (length % 4)) %4; } /** * @brief create a FID and add it to a directory then increment the file * link count * @param disc the udf_disc * @param pspace the type:PSPACE udf_extent for on-disc allocations * @param desc the file tag:FE/EFE udf_descriptor * @param parent the directory tag:FE/EFE udf_descriptor * @param name the file name in OSTA Compressed Unicode format (d-characters) * @param length the length of the file name in bytes * @param filechar the file characteristics * @return void */ void insert_fid(struct udf_disc *disc, struct udf_extent *pspace, struct udf_desc *desc, struct udf_desc *parent, const dchars *name, uint8_t length, uint8_t filechar) { struct udf_data *data; struct fileIdentDesc *fid; struct allocDescImpUse *adiu; int ilength = compute_ident_length(sizeof(struct fileIdentDesc) + length); int offset; uint64_t uniqueID; uint32_t uniqueID_le32; data = alloc_data(NULL, ilength); fid = data->buffer; offset = insert_desc(disc, pspace, desc, parent, data); fid->descTag.tagLocation = cpu_to_le32(offset); if (disc->flags & FLAG_EFE) { struct extendedFileEntry *efe = (struct extendedFileEntry *)desc->data->buffer; efe->fileLinkCount = cpu_to_le16(le16_to_cpu(efe->fileLinkCount) + 1); uniqueID = le64_to_cpu(efe->uniqueID); efe = (struct extendedFileEntry *)parent->data->buffer; if (disc->flags & FLAG_STRATEGY4096) fid->icb.extLength = cpu_to_le32(disc->blocksize * 2); else fid->icb.extLength = cpu_to_le32(disc->blocksize); fid->icb.extLocation.logicalBlockNum = cpu_to_le32(desc->offset); if (disc->flags & FLAG_VAT) fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(1); else fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(0); uniqueID_le32 = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); adiu = (struct allocDescImpUse *)fid->icb.impUse; memcpy(adiu->impUse, &uniqueID_le32, sizeof(uniqueID_le32)); fid->fileVersionNum = cpu_to_le16(1); fid->fileCharacteristics = filechar; fid->lengthFileIdent = length; fid->lengthOfImpUse = cpu_to_le16(0); memcpy(fid->fileIdent, name, length); fid->descTag = udf_query_tag(disc, TAG_IDENT_FID, 1, le32_to_cpu(fid->descTag.tagLocation), data, ilength); efe->informationLength = cpu_to_le64(le64_to_cpu(efe->informationLength) + ilength); efe->objectSize = cpu_to_le64(le64_to_cpu(efe->objectSize) + ilength); } else { struct fileEntry *fe = (struct fileEntry *)desc->data->buffer; fe->fileLinkCount = cpu_to_le16(le16_to_cpu(fe->fileLinkCount) + 1); uniqueID = le64_to_cpu(fe->uniqueID); fe = (struct fileEntry *)parent->data->buffer; if (disc->flags & FLAG_STRATEGY4096) fid->icb.extLength = cpu_to_le32(disc->blocksize * 2); else fid->icb.extLength = cpu_to_le32(disc->blocksize); fid->icb.extLocation.logicalBlockNum = cpu_to_le32(desc->offset); if (disc->flags & FLAG_VAT) fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(1); else fid->icb.extLocation.partitionReferenceNum = cpu_to_le16(0); uniqueID_le32 = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); adiu = (struct allocDescImpUse *)fid->icb.impUse; memcpy(adiu->impUse, &uniqueID_le32, sizeof(uniqueID_le32)); fid->fileVersionNum = cpu_to_le16(1); fid->fileCharacteristics = filechar; fid->lengthFileIdent = length; fid->lengthOfImpUse = cpu_to_le16(0); memcpy(fid->fileIdent, name, length); fid->descTag = udf_query_tag(disc, TAG_IDENT_FID, 1, le32_to_cpu(fid->descTag.tagLocation), data, ilength); fe->informationLength = cpu_to_le64(le64_to_cpu(fe->informationLength) + ilength); } *(tag *)desc->data->buffer = query_tag(disc, pspace, desc, 1); *(tag *)parent->data->buffer = query_tag(disc, pspace, parent, 1); } /** * @brief create a file tag:FE/EFE udf_descriptor and add the file to a directory * @param disc the udf_disc * @param pspace the type:PSPACE udf_extent for on-disc allocations * @param name the file name in OSTA Compressed Unicode format (d-characters) * @param length the length of the file name in bytes * @param offset the starting block number to search for on-disc allocations * @param parent the directory tag:FE/EFE udf_descriptor * @param filechar file characteristics * @param filetype the file type * @param flags the file flags * @return the in-memory address of file tag:FE/EFE udf_descriptor */ struct udf_desc *udf_create(struct udf_disc *disc, struct udf_extent *pspace, const dchars *name, uint8_t length, uint32_t offset, struct udf_desc *parent, uint8_t filechar, uint8_t filetype, uint16_t flags) { struct udf_desc *desc; if (disc->flags & FLAG_STRATEGY4096) offset = udf_alloc_blocks(disc, pspace, offset, 2); else offset = udf_alloc_blocks(disc, pspace, offset, 1); if (disc->flags & FLAG_EFE) { struct extendedFileEntry *efe; uint64_t uniqueID_le64; desc = set_desc(pspace, TAG_IDENT_EFE, offset, sizeof(struct extendedFileEntry), NULL); efe = (struct extendedFileEntry *)desc->data->buffer; memcpy(efe, &default_efe, sizeof(struct extendedFileEntry)); memcpy(&efe->accessTime, &disc->udf_pvd[0]->recordingDateAndTime, sizeof(timestamp)); memcpy(&efe->modificationTime, &efe->accessTime, sizeof(timestamp)); memcpy(&efe->attrTime, &efe->accessTime, sizeof(timestamp)); memcpy(&efe->createTime, &efe->accessTime, sizeof(timestamp)); if (filetype == ICBTAG_FILE_TYPE_STREAMDIR || flags & ICBTAG_FLAG_STREAM) efe->uniqueID = cpu_to_le64(0); else { memcpy(&efe->uniqueID, disc->udf_lvid->logicalVolContentsUse, sizeof(efe->uniqueID)); if (!(le64_to_cpu(efe->uniqueID) & 0x00000000FFFFFFFFUL)) uniqueID_le64 = cpu_to_le64(le64_to_cpu(efe->uniqueID) + 16); else uniqueID_le64 = cpu_to_le64(le64_to_cpu(efe->uniqueID) + 1); memcpy(disc->udf_lvid->logicalVolContentsUse, &uniqueID_le64, sizeof(uniqueID_le64)); } if (disc->flags & FLAG_STRATEGY4096) { efe->icbTag.strategyType = cpu_to_le16(4096); efe->icbTag.strategyParameter = cpu_to_le16(1); efe->icbTag.numEntries = cpu_to_le16(2); } efe->icbTag.fileType = filetype; efe->icbTag.flags = cpu_to_le16(le16_to_cpu(efe->icbTag.flags) | flags); if (parent) { // efe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(parent->offset); // for strategy type != 4 efe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(0); efe->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); insert_fid(disc, pspace, desc, parent, name, length, filechar); } else { efe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(0); efe->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); if (filetype == ICBTAG_FILE_TYPE_DIRECTORY) // root directory { efe->uid = cpu_to_le32(disc->uid); efe->gid = cpu_to_le32(disc->gid); efe->permissions = cpu_to_le32( ((disc->mode & S_IRWXU) << 4) | ((disc->mode & S_IRWXG) << 2) | ((disc->mode & S_IRWXO) << 0) | ((disc->mode & S_IWUSR) ? FE_PERM_U_CHATTR : 0) | ((disc->mode & S_IWGRP) ? FE_PERM_G_CHATTR : 0) | ((disc->mode & S_IWOTH) ? FE_PERM_O_CHATTR : 0) | 0 // Do not allow deleting root directory ); } } if (filetype == ICBTAG_FILE_TYPE_DIRECTORY) query_lvidiu(disc)->numDirs = cpu_to_le32(le32_to_cpu(query_lvidiu(disc)->numDirs)+1); else if (filetype != ICBTAG_FILE_TYPE_STREAMDIR && filetype != ICBTAG_FILE_TYPE_VAT20 && filetype != ICBTAG_FILE_TYPE_UNDEF && !(flags & ICBTAG_FLAG_STREAM)) query_lvidiu(disc)->numFiles = cpu_to_le32(le32_to_cpu(query_lvidiu(disc)->numFiles)+1); } else { struct fileEntry *fe; uint64_t uniqueID_le64; desc = set_desc(pspace, TAG_IDENT_FE, offset, sizeof(struct fileEntry), NULL); fe = (struct fileEntry *)desc->data->buffer; memcpy(fe, &default_fe, sizeof(struct fileEntry)); memcpy(&fe->accessTime, &disc->udf_pvd[0]->recordingDateAndTime, sizeof(timestamp)); memcpy(&fe->modificationTime, &fe->accessTime, sizeof(timestamp)); memcpy(&fe->attrTime, &fe->accessTime, sizeof(timestamp)); if (filetype == ICBTAG_FILE_TYPE_STREAMDIR || flags & ICBTAG_FLAG_STREAM) fe->uniqueID = cpu_to_le64(0); else { memcpy(&fe->uniqueID, disc->udf_lvid->logicalVolContentsUse, sizeof(fe->uniqueID)); if (!(le64_to_cpu(fe->uniqueID) & 0x00000000FFFFFFFFUL)) uniqueID_le64 = cpu_to_le64(le64_to_cpu(fe->uniqueID) + 16); else uniqueID_le64 = cpu_to_le64(le64_to_cpu(fe->uniqueID) + 1); memcpy(disc->udf_lvid->logicalVolContentsUse, &uniqueID_le64, sizeof(uniqueID_le64)); } if (disc->flags & FLAG_STRATEGY4096) { fe->icbTag.strategyType = cpu_to_le16(4096); fe->icbTag.strategyParameter = cpu_to_le16(1); fe->icbTag.numEntries = cpu_to_le16(2); } fe->icbTag.fileType = filetype; fe->icbTag.flags = cpu_to_le16(le16_to_cpu(fe->icbTag.flags) | flags); if (parent) { // fe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(parent->offset); // for strategy type != 4 fe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(0); fe->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); insert_fid(disc, pspace, desc, parent, name, length, filechar); } else { fe->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(0); fe->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); if (filetype == ICBTAG_FILE_TYPE_DIRECTORY) // root directory { fe->uid = cpu_to_le32(disc->uid); fe->gid = cpu_to_le32(disc->gid); fe->permissions = cpu_to_le32( ((disc->mode & S_IRWXU) << 4) | ((disc->mode & S_IRWXG) << 2) | ((disc->mode & S_IRWXO) << 0) | ((disc->mode & S_IWUSR) ? FE_PERM_U_CHATTR : 0) | ((disc->mode & S_IWGRP) ? FE_PERM_G_CHATTR : 0) | ((disc->mode & S_IWOTH) ? FE_PERM_O_CHATTR : 0) | 0 // Do not allow deleting root directory ); } } if (filetype == ICBTAG_FILE_TYPE_DIRECTORY) query_lvidiu(disc)->numDirs = cpu_to_le32(le32_to_cpu(query_lvidiu(disc)->numDirs)+1); else if (filetype != ICBTAG_FILE_TYPE_STREAMDIR && filetype != ICBTAG_FILE_TYPE_VAT20 && filetype != ICBTAG_FILE_TYPE_UNDEF && !(flags & ICBTAG_FLAG_STREAM)) query_lvidiu(disc)->numFiles = cpu_to_le32(le32_to_cpu(query_lvidiu(disc)->numFiles)+1); } return desc; } /** * @brief create a directory tag:FE/EFE udf_descriptor and add the directory to * a parent directory * @param disc the udf_disc * @param pspace the type:PSPACE udf_extent for on-disc allocations * @param name the file name in OSTA Compressed Unicode format (d-characters) * @param length the length of the file name in bytes * @param offset the starting block number to search for on-disc allocations * @param parent the parent directory tag:FE/EFE udf_descriptor * @return the in-memory address of the directory tag:FE/EFE udf_descriptor */ struct udf_desc *udf_mkdir(struct udf_disc *disc, struct udf_extent *pspace, const dchars *name, uint8_t length, uint32_t offset, struct udf_desc *parent) { struct udf_desc *desc = udf_create(disc, pspace, name, length, offset, parent, FID_FILE_CHAR_DIRECTORY, ICBTAG_FILE_TYPE_DIRECTORY, 0); if (!parent) parent = desc; // the root directory is it's own parent insert_fid(disc, pspace, parent, desc, NULL, 0, FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT); // directory parent back links are unnamed return desc; } #define BITS_PER_LONG 32 #define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x) #define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y) #define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y)) #define uintBPL uint(BITS_PER_LONG) #define uint(x) xuint(x) #define xuint(x) uint ## x ## _t /** * @brief utility function to find the first zero bit in an unsigned long * @param word the unsigned long to search * @return the 0 based bit position from the lsb or BITS_PER_LONG */ static inline unsigned long ffz(unsigned long word) { unsigned long result; result = 0; while (word & 1) { result ++; word >>= 1; } return result; } /** * @brief find the first one bit in a space bitmap * @param addr the in-memory address of the space bitmap * @param size the size of the space bitmap in bits * @param offset the starting bit position for the search * @return the 0 based bit position or size */ static inline unsigned long udf_find_next_one_bit (void * addr, unsigned long size, unsigned long offset) { uintBPL * p = ((uintBPL *) addr) + (offset / BITS_PER_LONG); uintBPL result = offset & ~(BITS_PER_LONG-1); uintBPL tmp; if (offset >= size) return size; size -= result; offset &= (BITS_PER_LONG-1); if (offset) { tmp = leBPL_to_cpup(p++); tmp &= ~0UL << offset; if (size < BITS_PER_LONG) goto found_first; if (tmp) goto found_middle; size -= BITS_PER_LONG; result += BITS_PER_LONG; } while (size & ~(BITS_PER_LONG-1)) { if ((tmp = leBPL_to_cpup(p++))) goto found_middle; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = 0; memcpy(&tmp, p, (size+7)/8); tmp = leBPL_to_cpup(&tmp); found_first: tmp &= ~0UL >> (BITS_PER_LONG-size); found_middle: return result + ffz(~tmp); } /** * @brief find the first zero bit in a space bitmap * @param addr the in-memory address of the space bitmap * @param size the size of the space bitmap in bits * @param offset the starting bit position for the search * @return the 0 based bit position or size */ static inline unsigned long udf_find_next_zero_bit(void * addr, unsigned long size, unsigned long offset) { uintBPL * p = ((uintBPL *) addr) + (offset / BITS_PER_LONG); uintBPL result = offset & ~(BITS_PER_LONG-1); uintBPL tmp; if (offset >= size) return size; size -= result; offset &= (BITS_PER_LONG-1); if (offset) { tmp = leBPL_to_cpup(p++); tmp |= (~0UL >> (BITS_PER_LONG-offset)); if (size < BITS_PER_LONG) goto found_first; if (~tmp) goto found_middle; size -= BITS_PER_LONG; result += BITS_PER_LONG; } while (size & ~(BITS_PER_LONG-1)) { if (~(tmp = leBPL_to_cpup(p++))) goto found_middle; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = 0; memcpy(&tmp, p, (size+7)/8); tmp = leBPL_to_cpup(&tmp); found_first: tmp |= (~0UL << size); if (tmp == (uintBPL)~0UL) /* Are any bits zero? */ return result + size; /* Nope. */ found_middle: return result + ffz(tmp); } /** * @brief allocate an aligned space bitmap on-disc * @param disc the udf disc * @param bitmap the space bitmap tag:USB/FSB udf_descriptor * @param start the starting block number to search for on-disc allocations * @param blocks the number of blocks in the space bitmap * @return the starting block number of the on-disc aligned space bitmap */ int udf_alloc_bitmap_blocks(struct udf_disc *disc, struct udf_desc *bitmap, uint32_t start, uint32_t blocks) { uint32_t alignment = disc->sizing[PSPACE_SIZE].align; struct spaceBitmapDesc *sbd = (struct spaceBitmapDesc *)bitmap->data->buffer; uint32_t end; do { start = ((start + alignment - 1) / alignment) * alignment; if (start + blocks >= sbd->numOfBits) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } if (sbd->bitmap[start/8] & (1 << (start%8))) { end = udf_find_next_zero_bit(sbd->bitmap, sbd->numOfBits, start); } else start = end = udf_find_next_one_bit(sbd->bitmap, sbd->numOfBits, start); } while ((end - start) <= blocks); clear_bits(sbd->bitmap, start, blocks); return start; } /** * @brief allocate a space table on-disc * @param disc the udf_disc * @param table the space table tag:USE/FSE udf_descriptor * @param start the starting block offset for the allocation search * @param blocks the number of blocks in the space table * @return the starting block number of the on-disc space table */ int udf_alloc_table_blocks(struct udf_disc *disc, struct udf_desc *table, uint32_t start, uint32_t blocks) { uint32_t alignment = disc->sizing[PSPACE_SIZE].align; struct unallocSpaceEntry *use = (struct unallocSpaceEntry *)table->data->buffer; uint32_t end, offset = 0; short_ad *sad; do { if (offset >= use->lengthAllocDescs) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } sad = (short_ad *)&use->allocDescs[offset]; if (start < le32_to_cpu(sad->extPosition)) start = le32_to_cpu(sad->extPosition); start = ((start + alignment - 1) / alignment) * alignment; end = le32_to_cpu(sad->extPosition) + ((le32_to_cpu(sad->extLength) & EXT_LENGTH_MASK) / disc->blocksize); if (start > end) start = end; offset += sizeof(short_ad); } while ((end - start) < blocks); if (start == le32_to_cpu(sad->extPosition) && start + blocks == end) { /* deleted extent */ memmove(&use->allocDescs[offset-sizeof(short_ad)], &use->allocDescs[offset], le32_to_cpu(use->lengthAllocDescs) - offset); use->lengthAllocDescs = cpu_to_le32(le32_to_cpu(use->lengthAllocDescs) - sizeof(short_ad)); memset(&use->allocDescs[le32_to_cpu(use->lengthAllocDescs)], 0x00, sizeof(short_ad)); } else if (start == le32_to_cpu(sad->extPosition)) { sad->extPosition = cpu_to_le32(start + blocks); sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) - blocks * disc->blocksize); } else if (start + blocks == end) { sad->extLength = cpu_to_le32(le32_to_cpu(sad->extLength) - blocks * disc->blocksize); } else { memmove(&use->allocDescs[offset+sizeof(short_ad)], &use->allocDescs[offset], le32_to_cpu(use->lengthAllocDescs) - offset); sad->extLength = cpu_to_le32(EXT_NOT_RECORDED_ALLOCATED | (start - le32_to_cpu(sad->extPosition)) * disc->blocksize); sad = (short_ad *)&use->allocDescs[offset]; sad->extPosition = cpu_to_le32(start+blocks); sad->extLength = cpu_to_le32(EXT_NOT_RECORDED_ALLOCATED | (end - start - blocks) * disc->blocksize); use->lengthAllocDescs = cpu_to_le32(le32_to_cpu(use->lengthAllocDescs) + sizeof(short_ad)); } use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, table->offset, table->data, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs)); return start; } /** * @brief allocate blocks on-disc * @param disc the udf_disc * @param start the starting block offset for the allocation search * @param blocks the number of blocks to allocate * @return the starting block number of the on-disc allocation */ int udf_alloc_blocks(struct udf_disc *disc, struct udf_extent *pspace, uint32_t start, uint32_t blocks) { struct udf_desc *desc; struct partitionHeaderDesc *phd = (struct partitionHeaderDesc *)disc->udf_pd[0]->partitionContentsUse; disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - blocks); if (disc->flags & FLAG_FREED_BITMAP) { desc = find_desc(pspace, le32_to_cpu(phd->freedSpaceBitmap.extPosition)); return udf_alloc_bitmap_blocks(disc, desc, start, blocks); } else if (disc->flags & FLAG_FREED_TABLE) { desc = find_desc(pspace, le32_to_cpu(phd->freedSpaceTable.extPosition)); return udf_alloc_table_blocks(disc, desc, start, blocks); } else if (disc->flags & FLAG_UNALLOC_BITMAP) { desc = find_desc(pspace, le32_to_cpu(phd->unallocSpaceBitmap.extPosition)); return udf_alloc_bitmap_blocks(disc, desc, start, blocks); } else if (disc->flags & FLAG_UNALLOC_TABLE) { desc = find_desc(pspace, le32_to_cpu(phd->unallocSpaceTable.extPosition)); return udf_alloc_table_blocks(disc, desc, start, blocks); } else if (disc->flags & FLAG_VAT) { uint32_t offset = 0, length = 0, i = 0; if (pspace->tail) { offset = pspace->tail->offset; length = (pspace->tail->length + disc->blocksize - 1) / disc->blocksize; } if (offset + length > start) start = offset + length; if (start >= pspace->blocks) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } for (i = 0; i < blocks; ++i) disc->vat[disc->vat_entries++] = start+i; return start; } else return 0; } udftools-2.0/mkudffs/defaults.c0000644000175000017500000003115213221466537013560 00000000000000/* * defaults.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * mkudffs default structure initializers */ #include "config.h" #include "mkudffs.h" int default_media[] = { [MEDIA_TYPE_HD] = DEFAULT_HD, [MEDIA_TYPE_DVD] = DEFAULT_DVD, [MEDIA_TYPE_DVDRAM] = DEFAULT_DVDRAM, [MEDIA_TYPE_DVDRW] = DEFAULT_DVDRW, [MEDIA_TYPE_DVDR] = DEFAULT_DVDR, [MEDIA_TYPE_WORM] = DEFAULT_WORM, [MEDIA_TYPE_MO] = DEFAULT_MO, [MEDIA_TYPE_CDRW] = DEFAULT_CDRW, [MEDIA_TYPE_CDR] = DEFAULT_CDR, [MEDIA_TYPE_CD] = DEFAULT_CD, [MEDIA_TYPE_BDR] = DEFAULT_BDR, }; struct udf_sizing default_sizing[][UDF_ALLOC_TYPE_SIZE] = { // align, numSize,denomSize,minSize { // Media 0 = HD, CDROM, DVDROM, DVDRAM { 1, 0, 1, 16 }, // VDS_SIZE Volume Descriptor Set { 1, 0, 1, 1 }, // LVID_SIZE Logical Volume Integrity Descriptor { 1, 0, 1, 0 }, // STABLE_SIZE Sparing Table { 1, 0, 1, 0 }, // SSPACE_SIZE Sparing Space { 1, 0, 1, 0 }, // PSPACE_SIZE Partition Space }, { // Media 1 = WORM, MO { 1, 0, 1, 255 }, { 1, 1, 50, 10 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, { 1, 0, 1, 0 }, }, { // Media 2 = CDRW { 32, 0, 1, 32 }, { 32, 0, 1, 32 }, { 32, 0, 1, 5 }, // 56+8*1024 bytes ~~ 5 blocks { 32, 0, 1, 1024 }, { 32, 0, 1, 0 }, }, { // Media 3 = CDR, BD-R { 32, 0, 1, 16 }, { 32, 0, 1, 1 }, { 32, 0, 1, 0 }, { 32, 0, 1, 0 }, { 32, 0, 1, 0 }, }, { // Media 4 = DVDRW { 16, 0, 1, 16 }, { 16, 0, 1, 16 }, { 16, 0, 1, 5 }, // 56+8*1024 bytes ~~ 5 blocks { 16, 0, 1, 1024 }, { 16, 0, 1, 0 }, }, { // Media 5 = DVDR { 16, 0, 1, 16 }, { 16, 0, 1, 1 }, { 16, 0, 1, 0 }, { 16, 0, 1, 0 }, { 16, 0, 1, 0 }, } }; struct primaryVolDesc default_pvd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_PVD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct primaryVolDesc) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(1), .primaryVolDescNum = constant_cpu_to_le32(0), .volIdent = "\x08" "LinuxUDF", .volSeqNum = constant_cpu_to_le16(1), .maxVolSeqNum = constant_cpu_to_le16(1), .interchangeLvl = constant_cpu_to_le16(3), .maxInterchangeLvl = constant_cpu_to_le16(3), .charSetList = constant_cpu_to_le32(CS0), .maxCharSetList = constant_cpu_to_le32(CS0), .volSetIdent = "\x08" "0000000000000000LinuxUDF", .descCharSet = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO, }, .explanatoryCharSet = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO, }, .appIdent = { .ident = UDF_ID_APPLICATION, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .flags = constant_cpu_to_le16(PVD_FLAGS_VSID_COMMON), }; struct logicalVolDesc default_lvd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_LVD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct logicalVolDesc) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(2), .descCharSet = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO, }, .logicalVolIdent = "\x08" "LinuxUDF", .logicalBlockSize = constant_cpu_to_le32(2048), .domainIdent = { .ident = UDF_ID_COMPLIANT, .identSuffix = { 0x01, 0x02, 0x00, } }, .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, } }; struct volDescPtr default_vdp = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_VDP), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct volDescPtr) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(3), }; struct impUseVolDescImpUse default_iuvdiu = { .LVICharset = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO }, .logicalVolIdent = "\x08" "LinuxUDF", .LVInfo1 = "\x08" "Linux mkudffs " PACKAGE_VERSION, .LVInfo2 = "\x08" "Linux udftools " PACKAGE_VERSION, .LVInfo3 = "\x08" PACKAGE_URL, .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, }; struct impUseVolDesc default_iuvd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_IUVD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct impUseVolDesc) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(4), .impIdent = { .ident = UDF_ID_LV_INFO, .identSuffix = { 0x01, 0x02, UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, }; struct partitionDesc default_pd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_PD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct partitionDesc) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(5), .partitionFlags = constant_cpu_to_le16(0x0001), .partitionContents = { .ident = PD_PARTITION_CONTENTS_NSR03, }, .accessType = constant_cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE), .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, }; struct unallocSpaceDesc default_usd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_USD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct unallocSpaceDesc) - sizeof(tag)), }, .volDescSeqNum = constant_cpu_to_le32(6), }; struct terminatingDesc default_td = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_TD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct terminatingDesc) - sizeof(tag)), }, }; struct logicalVolIntegrityDesc default_lvid = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_LVID), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct logicalVolIntegrityDesc) - sizeof(tag)), }, .integrityType = constant_cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE), .lengthOfImpUse = constant_cpu_to_le32(sizeof(struct logicalVolIntegrityDescImpUse)), }; struct logicalVolIntegrityDescImpUse default_lvidiu = { .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .minUDFReadRev = constant_cpu_to_le16(0x0201), .minUDFWriteRev = constant_cpu_to_le16(0x0201), .maxUDFWriteRev = constant_cpu_to_le16(0x0201), }; struct sparingTable default_stable = { .descTag = { .tagIdent = constant_cpu_to_le16(0), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct sparingTable) - sizeof(tag)), }, .sparingIdent = { .flags = 0, .ident = UDF_ID_SPARING, .identSuffix = { 0x01, 0x02, UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .reallocationTableLen = constant_cpu_to_le16(0), .sequenceNum = constant_cpu_to_le32(0) }; struct sparablePartitionMap default_sparmap = { .partitionMapType = 2, .partitionMapLength = sizeof(struct sparablePartitionMap), .partIdent = { .flags = 0, .ident = UDF_ID_SPARABLE, .identSuffix = { 0x01, 0x02, UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .volSeqNum = constant_cpu_to_le16(1), .packetLength = constant_cpu_to_le16(32) }; struct virtualAllocationTable15 default_vat15 = { .vatIdent = { .flags = 0, .ident = UDF_ID_ALLOC, .identSuffix = { 0x01, 0x02, UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .previousVATICBLoc = constant_cpu_to_le32(0xFFFFFFFF) }; struct virtualAllocationTable20 default_vat20 = { .lengthHeader = constant_cpu_to_le16(152), .lengthImpUse = constant_cpu_to_le16(0), .logicalVolIdent = "\x08" "LinuxUDF", .previousVATICBLoc = constant_cpu_to_le32(0xFFFFFFFF), .minUDFReadRev = constant_cpu_to_le16(0x0201), .minUDFWriteRev = constant_cpu_to_le16(0x0201), .maxUDFWriteRev = constant_cpu_to_le16(0x0201) }; struct virtualPartitionMap default_virtmap = { .partitionMapType = 2, .partitionMapLength = sizeof(struct virtualPartitionMap), .partIdent = { .flags = 0, .ident = UDF_ID_VIRTUAL, .identSuffix = { 0x01, 0x02, UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX }, }, .volSeqNum = constant_cpu_to_le16(1) }; struct fileSetDesc default_fsd = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_FSD), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct fileSetDesc) - sizeof(tag)), }, .interchangeLvl = constant_cpu_to_le16(3), .maxInterchangeLvl = constant_cpu_to_le16(3), .charSetList = constant_cpu_to_le32(CS0), .maxCharSetList = constant_cpu_to_le32(CS0), .logicalVolIdentCharSet = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO, }, .logicalVolIdent = "\x08" "LinuxUDF", .fileSetCharSet = { .charSetType = UDF_CHAR_SET_TYPE, .charSetInfo = UDF_CHAR_SET_INFO, }, .fileSetIdent = "\x08" "LinuxUDF", .copyrightFileIdent = "\x08" "Copyright", .abstractFileIdent = "\x08" "Abstract", .domainIdent = { .ident = UDF_ID_COMPLIANT, .identSuffix = { 0x01, 0x02, 0x00, }, } }; struct fileEntry default_fe = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_FE), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct fileEntry) - sizeof(tag)), }, .icbTag = { .strategyType = constant_cpu_to_le16(4), .strategyParameter = constant_cpu_to_le16(0), .numEntries = constant_cpu_to_le16(1), .fileType = 0, .flags = constant_cpu_to_le16(ICBTAG_FLAG_AD_IN_ICB), }, .permissions = constant_cpu_to_le32(FE_PERM_U_DELETE|FE_PERM_U_CHATTR|FE_PERM_U_READ|FE_PERM_U_WRITE|FE_PERM_U_EXEC|FE_PERM_G_READ|FE_PERM_G_EXEC|FE_PERM_O_READ|FE_PERM_O_EXEC), .fileLinkCount = constant_cpu_to_le16(0), .informationLength = constant_cpu_to_le64(0), .logicalBlocksRecorded = constant_cpu_to_le64(0), .checkpoint = constant_cpu_to_le32(1), .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, }; struct extendedFileEntry default_efe = { .descTag = { .tagIdent = constant_cpu_to_le16(TAG_IDENT_EFE), .descVersion = constant_cpu_to_le16(3), .tagSerialNum = constant_cpu_to_le16(1), .descCRC = constant_cpu_to_le16(sizeof(struct extendedFileEntry) - sizeof(tag)), }, .icbTag = { .strategyType = constant_cpu_to_le16(4), .strategyParameter = constant_cpu_to_le16(0), .numEntries = constant_cpu_to_le16(1), .fileType = 0, .flags = constant_cpu_to_le16(ICBTAG_FLAG_AD_IN_ICB), }, .permissions = constant_cpu_to_le32(FE_PERM_U_DELETE|FE_PERM_U_CHATTR|FE_PERM_U_READ|FE_PERM_U_WRITE|FE_PERM_U_EXEC|FE_PERM_G_READ|FE_PERM_G_EXEC|FE_PERM_O_READ|FE_PERM_O_EXEC), .fileLinkCount = constant_cpu_to_le16(0), .informationLength = constant_cpu_to_le64(0), .objectSize = constant_cpu_to_le64(0), .logicalBlocksRecorded = constant_cpu_to_le64(0), .checkpoint = constant_cpu_to_le32(1), .impIdent = { .ident = UDF_ID_DEVELOPER, .identSuffix = { UDF_OS_CLASS_UNIX, UDF_OS_ID_LINUX, }, }, }; struct mbr default_mbr = { .boot_code = "", .disk_signature = constant_cpu_to_le32(0x0), .unknown = 0x0, .partitions = { { .boot_indicator = MBR_PARTITION_NOT_BOOTABLE, .starting_chs = { 0, 0, 0 }, .partition_type = MBR_PARTITION_TYPE_IFS, .ending_chs = { 0, 0, 0 }, .starting_lba = constant_cpu_to_le32(0), .size_in_lba = constant_cpu_to_le32(0), }, }, .boot_signature = constant_cpu_to_le16(MBR_BOOT_SIGNATURE), }; udftools-2.0/mkudffs/mkudffs.c0000644000175000017500000013673213221466537013422 00000000000000/* * mkudffs.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * mkudffs support functions */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "mkudffs.h" #include "file.h" #include "defaults.h" void udf_init_disc(struct udf_disc *disc) { timestamp ts; struct timeval tv; struct tm *tm; int altzone; unsigned long int rnd; srand(time(NULL)); memset(disc, 0x00, sizeof(*disc)); disc->blocksize = 2048; disc->udf_rev = le16_to_cpu(default_lvidiu.minUDFReadRev); disc->flags = FLAG_LOCALE | FLAG_CLOSED | FLAG_EFE; disc->blkssz = 512; disc->mode = 0755; gettimeofday(&tv, NULL); tm = localtime(&tv.tv_sec); altzone = timezone - 3600; if (daylight) ts.typeAndTimezone = cpu_to_le16(((-altzone/60) & 0x0FFF) | 0x1000); else ts.typeAndTimezone = cpu_to_le16(((-timezone/60) & 0x0FFF) | 0x1000); ts.year = cpu_to_le16(1900 + tm->tm_year); ts.month = 1 + tm->tm_mon; ts.day = tm->tm_mday; ts.hour = tm->tm_hour; ts.minute = tm->tm_min; ts.second = tm->tm_sec; ts.centiseconds = tv.tv_usec / 10000; ts.hundredsOfMicroseconds = (tv.tv_usec - ts.centiseconds * 10000) / 100; ts.microseconds = tv.tv_usec - ts.centiseconds * 10000 - ts.hundredsOfMicroseconds * 100; get_random_bytes(&rnd, sizeof(rnd)); /* Allocate/Initialize Descriptors */ disc->udf_pvd[0] = malloc(sizeof(struct primaryVolDesc)); memcpy(disc->udf_pvd[0], &default_pvd, sizeof(struct primaryVolDesc)); memcpy(&disc->udf_pvd[0]->recordingDateAndTime, &ts, sizeof(timestamp)); sprintf((char *)&disc->udf_pvd[0]->volSetIdent[1], "%08lx%08lx%s", ((unsigned long int)mktime(tm))%0xFFFFFFFF, rnd%0xFFFFFFFF, &disc->udf_pvd[0]->volSetIdent[17]); disc->udf_pvd[0]->volIdent[31] = strlen((char *)disc->udf_pvd[0]->volIdent); disc->udf_pvd[0]->volSetIdent[127] = strlen((char *)disc->udf_pvd[0]->volSetIdent); disc->udf_lvd[0] = malloc(sizeof(struct logicalVolDesc)); memcpy(disc->udf_lvd[0], &default_lvd, sizeof(struct logicalVolDesc)); disc->udf_lvd[0]->logicalVolIdent[127] = strlen((char *)disc->udf_lvd[0]->logicalVolIdent); disc->udf_pd[0] = malloc(sizeof(struct partitionDesc)); memcpy(disc->udf_pd[0], &default_pd, sizeof(struct partitionDesc)); disc->udf_usd[0] = malloc(sizeof(struct unallocSpaceDesc)); memcpy(disc->udf_usd[0], &default_usd, sizeof(struct unallocSpaceDesc)); disc->udf_iuvd[0] = malloc(sizeof(struct impUseVolDesc) + sizeof(struct impUseVolDescImpUse)); memcpy(disc->udf_iuvd[0], &default_iuvd, sizeof(struct impUseVolDesc)); memcpy(query_iuvdiu(disc), &default_iuvdiu, sizeof(struct impUseVolDescImpUse)); query_iuvdiu(disc)->logicalVolIdent[127] = strlen((char *)query_iuvdiu(disc)->logicalVolIdent); query_iuvdiu(disc)->LVInfo1[35] = strlen((char *)query_iuvdiu(disc)->LVInfo1); query_iuvdiu(disc)->LVInfo2[35] = strlen((char *)query_iuvdiu(disc)->LVInfo2); query_iuvdiu(disc)->LVInfo3[35] = strlen((char *)query_iuvdiu(disc)->LVInfo3); disc->udf_td[0] = malloc(sizeof(struct terminatingDesc)); memcpy(disc->udf_td[0], &default_td, sizeof(struct terminatingDesc)); disc->udf_lvid = malloc(sizeof(struct logicalVolIntegrityDesc) + sizeof(struct logicalVolIntegrityDescImpUse)); memcpy(disc->udf_lvid, &default_lvid, sizeof(struct logicalVolIntegrityDesc)); memcpy(&disc->udf_lvid->recordingDateAndTime, &ts, sizeof(timestamp)); memcpy(query_lvidiu(disc), &default_lvidiu, sizeof(struct logicalVolIntegrityDescImpUse)); disc->udf_stable[0] = malloc(sizeof(struct sparingTable)); memcpy(disc->udf_stable[0], &default_stable, sizeof(struct sparingTable)); disc->vat = calloc(1, disc->blocksize); disc->vat_entries = 0; disc->udf_fsd = malloc(sizeof(struct fileSetDesc)); memcpy(disc->udf_fsd, &default_fsd, sizeof(struct fileSetDesc)); memcpy(&disc->udf_fsd->recordingDateAndTime, &ts, sizeof(timestamp)); disc->udf_fsd->logicalVolIdent[127] = strlen((char *)disc->udf_fsd->logicalVolIdent); disc->udf_fsd->fileSetIdent[31] = strlen((char *)disc->udf_fsd->fileSetIdent); disc->udf_fsd->copyrightFileIdent[31] = strlen((char *)disc->udf_fsd->copyrightFileIdent); disc->udf_fsd->abstractFileIdent[31] = strlen((char *)disc->udf_fsd->abstractFileIdent); disc->head = malloc(sizeof(struct udf_extent)); disc->tail = disc->head; disc->head->space_type = USPACE; disc->head->start = 0; disc->head->blocks = 0; disc->head->next = NULL; disc->head->prev = NULL; disc->head->head = NULL; disc->head->tail = NULL; } int udf_set_version(struct udf_disc *disc, int udf_rev) { struct logicalVolIntegrityDescImpUse *lvidiu; uint16_t udf_rev_le16; if (disc->udf_rev == udf_rev) return 0; else if (udf_rev != 0x0102 && udf_rev != 0x0150 && udf_rev != 0x0200 && udf_rev != 0x0201 && udf_rev != 0x0250 && udf_rev != 0x0260) { return 1; } else disc->udf_rev = udf_rev; if (disc->udf_rev >= 0x0200) { disc->flags |= FLAG_EFE; strcpy((char *)disc->udf_pd[0]->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03); } else if (disc->udf_rev == 0x0150) { disc->flags &= ~FLAG_EFE; strcpy((char *)disc->udf_pd[0]->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02); } else // 0x0102 { disc->flags &= ~FLAG_VAT; disc->flags &= ~FLAG_EFE; strcpy((char *)disc->udf_pd[0]->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02); } udf_rev_le16 = cpu_to_le16(udf_rev); memcpy(disc->udf_fsd->domainIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); memcpy(disc->udf_lvd[0]->domainIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); memcpy(disc->udf_iuvd[0]->impIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); memcpy(disc->udf_stable[0]->sparingIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); lvidiu = query_lvidiu(disc); if (udf_rev == 0x0260) lvidiu->minUDFReadRev = cpu_to_le16(0x0250); else lvidiu->minUDFReadRev = cpu_to_le16(udf_rev); lvidiu->minUDFWriteRev = cpu_to_le16(udf_rev); lvidiu->maxUDFWriteRev = cpu_to_le16(udf_rev); return 0; } void get_random_bytes(void *buffer, size_t count) { int fd; size_t i; fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { if (read(fd, buffer, count) == (ssize_t)count) { close(fd); return; } close(fd); } for (i = 0; i < count; ++i) ((uint8_t *)buffer)[i] = rand() % 0xFF; } void split_space(struct udf_disc *disc) { uint32_t sizes[UDF_ALLOC_TYPE_SIZE]; uint32_t offsets[UDF_ALLOC_TYPE_SIZE]; uint32_t blocks = disc->blocks; uint32_t start, size, start2, size2; struct sparablePartitionMap *spm; struct udf_extent *ext; uint32_t accessType; uint32_t i, j; // OS boot area if (disc->flags & FLAG_BOOTAREA_MBR) set_extent(disc, MBR, 0, 1); else set_extent(disc, RESERVED, 0, 32768 / disc->blocksize); // Volume Recognition Sequence if (disc->blocksize >= 2048) set_extent(disc, VRS, (2048 * 16) / disc->blocksize, 4); // 3 sectors for VSD + one empty sector else set_extent(disc, VRS, (2048 * 16) / disc->blocksize, ((2048 * 3) + disc->blocksize) / disc->blocksize); // 3 VSD in more sectors + one empty sector // First Anchor Point at sector 256 if (blocks > 257) set_extent(disc, ANCHOR, 256, 1); // Second anchor point at sector (End-Of-Volume - 256) if (disc->flags & FLAG_CLOSED) { if (disc->flags & FLAG_VAT) { if (blocks <= 257 || blocks-257 <= 256) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, ANCHOR, 257, 1); } else if (blocks >= 3072) { set_extent(disc, ANCHOR, blocks-257, 1); } } // Final anchor point at sector End-Of-Volume/Session for sequentially writable media if (!(disc->flags & FLAG_VAT)) set_extent(disc, ANCHOR, blocks-1, 1); // Calculate minimal size for Sparing Table needed for Sparing Space if ((spm = find_type2_sparable_partition(disc, 0)) && disc->sizing[STABLE_SIZE].minSize == 0) disc->sizing[STABLE_SIZE].minSize = (sizeof(struct sparingTable) + disc->sizing[SSPACE_SIZE].minSize / le16_to_cpu(spm->packetLength) * sizeof(struct sparingEntry) + disc->blocksize-1) / disc->blocksize; for (i=0; isizing[i].numSize * blocks / disc->sizing[i].denomSize; if (disc->sizing[i].minSize > sizes[i]) sizes[i] = disc->sizing[i].minSize; offsets[i] = disc->sizing[i].align; } accessType = le32_to_cpu(disc->udf_pd[0]->accessType); if ((accessType == PD_ACCESS_TYPE_OVERWRITABLE || accessType == PD_ACCESS_TYPE_REWRITABLE) && sizes[LVID_SIZE] * (size_t)disc->blocksize < 8192) sizes[LVID_SIZE] = (8192 + disc->blocksize-1) / disc->blocksize; if (!(disc->flags & FLAG_VAT) && blocks < 770) start = 0; else start = 96; start = find_next_extent_size(disc, start, USPACE, sizes[VDS_SIZE], offsets[VDS_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, MVDS, start, sizes[VDS_SIZE]); if (disc->flags & FLAG_VAT) { start = find_next_extent_size(disc, (256-sizes[VDS_SIZE])/offsets[VDS_SIZE]*offsets[VDS_SIZE], USPACE, sizes[VDS_SIZE], offsets[VDS_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, RVDS, start, sizes[VDS_SIZE]); } else { if (blocks >= 3072) start = find_next_extent_size(disc, (blocks-257+97)/32*32, USPACE, sizes[VDS_SIZE], offsets[VDS_SIZE]); else start = prev_extent_size(disc->tail, USPACE, sizes[VDS_SIZE], offsets[VDS_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, RVDS, start, sizes[VDS_SIZE]); } start = prev_extent_size(disc->tail, USPACE, sizes[LVID_SIZE], offsets[LVID_SIZE]); if (start < 256 || blocks >= 770) { if (!(disc->flags & FLAG_VAT) && blocks < 770) start = 0; else start = 128; start = find_next_extent_size(disc, start, USPACE, sizes[LVID_SIZE], offsets[LVID_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, LVID, start, sizes[LVID_SIZE]); } if ((spm = find_type2_sparable_partition(disc, 0))) { for (i=0; inumSparingTables; i++) { if (i == 0) start = find_next_extent_size(disc, next_extent(disc->head, MVDS)->start, USPACE, sizes[STABLE_SIZE], offsets[STABLE_SIZE]); else if (i == 1) start = prev_extent_size(disc->tail, USPACE, sizes[STABLE_SIZE], offsets[STABLE_SIZE]); else if (i == 2) start = prev_extent_size(next_extent(disc->head, ANCHOR), USPACE, sizes[STABLE_SIZE], offsets[STABLE_SIZE]); else start = find_next_extent_size(disc, prev_extent(disc->tail->prev, ANCHOR)->start, USPACE, sizes[STABLE_SIZE], offsets[STABLE_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, STABLE, start, sizes[STABLE_SIZE]); } start = find_next_extent_size(disc, next_extent(disc->head, MVDS)->start, USPACE, sizes[SSPACE_SIZE], offsets[SSPACE_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, SSPACE, start, sizes[SSPACE_SIZE]); } start2 = 0; size2 = 0; for (i = 0; i < 3; ++i) { if (i != 0 && ((disc->flags & FLAG_VAT) || blocks >= 770)) break; if (i == 0) ext = next_extent(find_extent(disc, 256), USPACE); else if (i == 1) ext = prev_extent(disc->tail, USPACE); else ext = next_extent(disc->head, USPACE); for (; ext; ext = next_extent(ext->next, USPACE)) { // round start up to a multiple of alignment/packet_size if (ext->start % offsets[PSPACE_SIZE]) { if (offsets[PSPACE_SIZE] >= ext->blocks + (ext->start % offsets[PSPACE_SIZE])) continue; start = ext->start + offsets[PSPACE_SIZE] - (ext->start % offsets[PSPACE_SIZE]); size = ext->blocks - offsets[PSPACE_SIZE] + (ext->start % offsets[PSPACE_SIZE]); } else { start = ext->start; size = ext->blocks; } // round size down to a multiple of alignment/packet_size if (size % offsets[PSPACE_SIZE]) size -= (size % offsets[PSPACE_SIZE]); if (size == 0) continue; if (size2 < size) { start2 = start; size2 = size; } } } start = start2; size = size2; if (size == 0) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, PSPACE, start, size); for (i=0; iudf_lvd[0]->numPartitionMaps); i++) { if (i == 1) disc->udf_lvid->freeSpaceTable[i] = cpu_to_le32(0xFFFFFFFF); else disc->udf_lvid->freeSpaceTable[i] = cpu_to_le32(size); } for (j=0; judf_lvd[0]->numPartitionMaps); j++) { if (j == 1) disc->udf_lvid->sizeTable[i+j] = cpu_to_le32(0xFFFFFFFF); else disc->udf_lvid->sizeTable[i+j] = cpu_to_le32(size); } if (!next_extent(disc->head, LVID)) { start = find_next_extent_size(disc, 0, USPACE, sizes[LVID_SIZE], offsets[LVID_SIZE]); if (!start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } set_extent(disc, LVID, start, sizes[LVID_SIZE]); } } void dump_space(struct udf_disc *disc) { struct udf_extent *start_ext; int i; start_ext = disc->head; while (start_ext != NULL) { printf("start=%lu, blocks=%lu, type=", (unsigned long int)start_ext->start, (unsigned long int)start_ext->blocks); for (i=0; ispace_type & (1<space_type & (USPACE|RESERVED)) && !(disc->flags & FLAG_BOOTAREA_PRESERVE)) printf("ERASE "); else printf("%s ", udf_space_type_str[i]); } printf("\n"); start_ext = start_ext->next; } } int write_disc(struct udf_disc *disc) { struct udf_extent *start_ext; int ret=0; start_ext = disc->head; while (start_ext != NULL) { if ((ret = disc->write(disc, start_ext)) < 0) return ret; start_ext = start_ext->next; } return ret; } static void fill_mbr(struct udf_disc *disc, struct mbr *mbr, uint32_t start) { struct mbr old_mbr; uint64_t lba_blocks; struct stat st; struct hd_geometry geometry; unsigned int heads, sectors; struct mbr_partition *mbr_partition; int fd = disc->write_data ? (*(int *)disc->write_data) : -1; memcpy(mbr, &default_mbr, sizeof(struct mbr)); mbr_partition = &mbr->partitions[0]; if (fd >= 0 && lseek(fd, ((off_t)start) * disc->blocksize, SEEK_SET) >= 0) { if (read(fd, &old_mbr, sizeof(struct mbr)) == sizeof(struct mbr)) { if (old_mbr.boot_signature == constant_cpu_to_le16(MBR_BOOT_SIGNATURE)) mbr->disk_signature = le32_to_cpu(old_mbr.disk_signature); } } if (!mbr->disk_signature) get_random_bytes(&mbr->disk_signature, sizeof(mbr->disk_signature)); lba_blocks = ((uint64_t)disc->blocks * disc->blocksize + disc->blkssz - 1) / disc->blkssz; if (fd >= 0 && fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, HDIO_GETGEO, &geometry) == 0) { heads = geometry.heads; sectors = geometry.sectors; } else { /* Use LBA-Assist Translation for calculating CHS when disk geometry is not available */ sectors = 63; if (lba_blocks < 16*63*1024) heads = 16; else if (lba_blocks < 32*63*1024) heads = 32; else if (lba_blocks < 64*63*1024) heads = 64; else if (lba_blocks < 128*63*1024) heads = 128; else heads = 255; } if (heads > 255 || sectors > 63 || lba_blocks >= heads*sectors*1024) { /* If CHS address is too large use tuple (1023, 254, 63) */ mbr_partition->ending_chs[0] = 254; mbr_partition->ending_chs[1] = 255; mbr_partition->ending_chs[2] = 255; } else { mbr_partition->ending_chs[0] = (lba_blocks / sectors) % heads; mbr_partition->ending_chs[1] = ((1 + lba_blocks % sectors) & 63) | (((lba_blocks / (heads*sectors)) >> 8) * 64); mbr_partition->ending_chs[2] = (lba_blocks / (heads*sectors)) & 255; } mbr_partition->size_in_lba = cpu_to_le32(lba_blocks); } void setup_mbr(struct udf_disc *disc) { struct udf_extent *ext; struct udf_desc *desc; struct mbr *mbr; if (!(ext = next_extent(disc->head, MBR))) return; desc = set_desc(ext, 0x00, 0, ext->blocks * disc->blocksize, NULL); mbr = (struct mbr *)desc->data->buffer; fill_mbr(disc, mbr, ext->start); } void setup_vrs(struct udf_disc *disc) { struct udf_extent *ext; struct udf_desc *desc; if (!(ext = next_extent(disc->head, VRS))) return; desc = set_desc(ext, 0x00, 0, sizeof(struct volStructDesc), NULL); disc->udf_vrs[0] = (struct volStructDesc *)desc->data->buffer; disc->udf_vrs[0]->structType = 0x00; disc->udf_vrs[0]->structVersion = 0x01; memcpy(disc->udf_vrs[0]->stdIdent, VSD_STD_ID_BEA01, VSD_STD_ID_LEN); if (disc->blocksize >= 2048) desc = set_desc(ext, 0x00, 1, sizeof(struct volStructDesc), NULL); else desc = set_desc(ext, 0x00, 2048 / disc->blocksize, sizeof(struct volStructDesc), NULL); disc->udf_vrs[1] = (struct volStructDesc *)desc->data->buffer; disc->udf_vrs[1]->structType = 0x00; disc->udf_vrs[1]->structVersion = 0x01; if (disc->udf_rev >= 0x0200) memcpy(disc->udf_vrs[1]->stdIdent, VSD_STD_ID_NSR03, VSD_STD_ID_LEN); else memcpy(disc->udf_vrs[1]->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN); if (disc->blocksize >= 2048) desc = set_desc(ext, 0x00, 2, sizeof(struct volStructDesc), NULL); else desc = set_desc(ext, 0x00, 4096 / disc->blocksize, sizeof(struct volStructDesc), NULL); disc->udf_vrs[2] = (struct volStructDesc *)desc->data->buffer; disc->udf_vrs[2]->structType = 0x00; disc->udf_vrs[2]->structVersion = 0x01; memcpy(disc->udf_vrs[2]->stdIdent, VSD_STD_ID_TEA01, VSD_STD_ID_LEN); } void setup_anchor(struct udf_disc *disc) { struct udf_extent *ext; uint32_t mloc, rloc, mlen, rlen; int i = 0; ext = next_extent(disc->head, MVDS); if (!ext) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } mloc = ext->start; mlen = ext->blocks * disc->blocksize; ext = next_extent(disc->head, RVDS); if (!ext) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } rloc = ext->start; rlen = ext->blocks * disc->blocksize; ext = next_extent(disc->head, ANCHOR); if (!ext) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } do { ext->head = ext->tail = malloc(sizeof(struct udf_desc) + sizeof(struct udf_data)); ext->head->data = (struct udf_data *)&(ext->head)[1]; ext->head->data->next = ext->head->data->prev = NULL; ext->head->ident = TAG_IDENT_AVDP; ext->head->offset = 0; ext->head->length = ext->head->data->length = sizeof(struct anchorVolDescPtr); disc->udf_anchor[i] = ext->head->data->buffer = malloc(sizeof(struct anchorVolDescPtr)); ext->head->next = ext->head->prev = NULL; disc->udf_anchor[i]->mainVolDescSeqExt.extLocation = cpu_to_le32(mloc); disc->udf_anchor[i]->mainVolDescSeqExt.extLength = cpu_to_le32(mlen); disc->udf_anchor[i]->reserveVolDescSeqExt.extLocation = cpu_to_le32(rloc); disc->udf_anchor[i]->reserveVolDescSeqExt.extLength = cpu_to_le32(rlen); memset(disc->udf_anchor[i]->reserved, 0, sizeof(disc->udf_anchor[i]->reserved)); disc->udf_anchor[i]->descTag = query_tag(disc, ext, ext->head, 1); ext = next_extent(ext->next, ANCHOR); } while (i++, ext != NULL); } void setup_partition(struct udf_disc *disc) { struct udf_extent *pspace; pspace = next_extent(disc->head, PSPACE); if (!pspace) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } setup_space(disc, pspace, 0); setup_fileset(disc, pspace); setup_root(disc, pspace); if (disc->flags & FLAG_VAT) setup_vat(disc, pspace); } int setup_space(struct udf_disc *disc, struct udf_extent *pspace, uint32_t offset) { struct udf_desc *desc; struct partitionHeaderDesc *phd = (struct partitionHeaderDesc *)disc->udf_pd[0]->partitionContentsUse; uint32_t length = (sizeof(struct spaceBitmapDesc) + (pspace->blocks+7)/8 + disc->blocksize-1) / disc->blocksize * disc->blocksize; if (disc->flags & FLAG_FREED_BITMAP) { phd->freedSpaceBitmap.extPosition = cpu_to_le32(offset); phd->freedSpaceBitmap.extLength = cpu_to_le32(length); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - (length / disc->blocksize)); } else if (disc->flags & FLAG_FREED_TABLE) { phd->freedSpaceTable.extPosition = cpu_to_le32(offset); if (disc->flags & FLAG_STRATEGY4096) { phd->freedSpaceTable.extLength = cpu_to_le32(disc->blocksize * 2); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - 2); } else { phd->freedSpaceTable.extLength = cpu_to_le32(disc->blocksize); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - 1); } } else if (disc->flags & FLAG_UNALLOC_BITMAP) { phd->unallocSpaceBitmap.extPosition = cpu_to_le32(offset); phd->unallocSpaceBitmap.extLength = cpu_to_le32(length); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - (length / disc->blocksize)); } else if (disc->flags & FLAG_UNALLOC_TABLE) { phd->unallocSpaceTable.extPosition = cpu_to_le32(offset); if (disc->flags & FLAG_STRATEGY4096) { phd->unallocSpaceTable.extLength = cpu_to_le32(disc->blocksize * 2); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - 2); } else { phd->unallocSpaceTable.extLength = cpu_to_le32(disc->blocksize); disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(le32_to_cpu(disc->udf_lvid->freeSpaceTable[0]) - 1); } } if (disc->flags & FLAG_SPACE_BITMAP) { struct spaceBitmapDesc *sbd; int nBytes = (pspace->blocks+7)/8; length = sizeof(struct spaceBitmapDesc) + nBytes; desc = set_desc(pspace, TAG_IDENT_SBD, offset, length, NULL); sbd = (struct spaceBitmapDesc *)desc->data->buffer; sbd->numOfBits = cpu_to_le32(pspace->blocks); sbd->numOfBytes = cpu_to_le32(nBytes); memset(sbd->bitmap, 0xFF, sizeof(uint8_t) * nBytes); if (pspace->blocks%8) sbd->bitmap[nBytes-1] = 0xFF >> (8-(pspace->blocks%8)); clear_bits(sbd->bitmap, offset, (length + disc->blocksize - 1) / disc->blocksize); sbd->descTag = udf_query_tag(disc, TAG_IDENT_SBD, 1, desc->offset, desc->data, sizeof(struct spaceBitmapDesc)); } else if (disc->flags & FLAG_SPACE_TABLE) { struct unallocSpaceEntry *use; short_ad *sad; uint32_t max_value = (UINT32_MAX & EXT_LENGTH_MASK); uint32_t max = (max_value / disc->blocksize) * disc->blocksize; uint32_t pos=0; uint64_t rem; if (disc->flags & FLAG_STRATEGY4096) length = disc->blocksize * 2; else length = disc->blocksize; desc = set_desc(pspace, TAG_IDENT_USE, offset, disc->blocksize, NULL); use = (struct unallocSpaceEntry *)desc->data->buffer; use->lengthAllocDescs = cpu_to_le32(sizeof(short_ad)); sad = (short_ad *)&use->allocDescs[0]; rem = (uint64_t)pspace->blocks * disc->blocksize - length; if (disc->blocksize - sizeof(struct unallocSpaceEntry) < (rem / max) * sizeof(short_ad)) { fprintf(stderr, "%s: Error: Creation of so large filesystems with unalloc table not supported.\n", appname); exit(1); } pos = offset + (length/disc->blocksize); if (rem > max_value) { while (rem > max) { sad->extLength = cpu_to_le32(EXT_NOT_RECORDED_ALLOCATED | max); sad->extPosition = cpu_to_le32(pos); pos += max / disc->blocksize; sad ++; rem -= max; use->lengthAllocDescs = cpu_to_le32(le32_to_cpu(use->lengthAllocDescs) + sizeof(short_ad)); } } sad->extLength = cpu_to_le32(EXT_NOT_RECORDED_ALLOCATED | rem); sad->extPosition = cpu_to_le32(pos); if (disc->flags & FLAG_STRATEGY4096) { use->icbTag.strategyType = cpu_to_le16(4096); use->icbTag.strategyParameter = cpu_to_le16(1); use->icbTag.numEntries = cpu_to_le16(2); } else { use->icbTag.strategyType = cpu_to_le16(4); use->icbTag.numEntries = cpu_to_le16(1); } use->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(0); use->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); use->icbTag.fileType = ICBTAG_FILE_TYPE_USE; use->icbTag.flags = cpu_to_le16(ICBTAG_FLAG_AD_SHORT); use->descTag = udf_query_tag(disc, TAG_IDENT_USE, 1, desc->offset, desc->data, sizeof(struct unallocSpaceEntry) + le32_to_cpu(use->lengthAllocDescs)); if (disc->flags & FLAG_STRATEGY4096) { struct udf_desc *tdesc; struct terminalEntry *te; if (disc->flags & FLAG_BLANK_TERMINAL) { // tdesc = set_desc(pspace, TAG_IDENT_IE, offset+1, sizeof(struct indirectEntry), NULL); } else { tdesc = set_desc(pspace, TAG_IDENT_TE, offset+1, sizeof(struct terminalEntry), NULL); te = (struct terminalEntry *)tdesc->data->buffer; te->icbTag.priorRecordedNumDirectEntries = cpu_to_le32(1); te->icbTag.strategyType = cpu_to_le16(4096); te->icbTag.strategyParameter = cpu_to_le16(1); te->icbTag.numEntries = cpu_to_le16(2); te->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(desc->offset); te->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); te->icbTag.fileType = ICBTAG_FILE_TYPE_TE; te->descTag = query_tag(disc, pspace, tdesc, 1); } } } return (length + disc->blocksize - 1) / disc->blocksize; } int setup_fileset(struct udf_disc *disc, struct udf_extent *pspace) { uint32_t offset = 0; struct udf_desc *desc; int length = sizeof(struct fileSetDesc); long_ad ad; offset = udf_alloc_blocks(disc, pspace, offset, 1); memset(&ad, 0, sizeof(ad)); ad.extLength = cpu_to_le32(disc->blocksize); ad.extLocation.logicalBlockNum = cpu_to_le32(offset); if (disc->flags & FLAG_VAT) ad.extLocation.partitionReferenceNum = cpu_to_le16(1); else ad.extLocation.partitionReferenceNum = cpu_to_le16(0); memcpy(disc->udf_lvd[0]->logicalVolContentsUse, &ad, sizeof(ad)); desc = set_desc(pspace, TAG_IDENT_FSD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_fsd; if (!(disc->flags & FLAG_VAT) && disc->udf_rev >= 0x0200) { struct udf_desc *ss; ss = udf_create(disc, pspace, NULL, 0, offset+1, NULL, FID_FILE_CHAR_DIRECTORY, ICBTAG_FILE_TYPE_STREAMDIR, 0); insert_fid(disc, pspace, ss, ss, NULL, 0, FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT); offset = ss->offset; disc->udf_fsd->streamDirectoryICB.extLength = cpu_to_le32(disc->blocksize); disc->udf_fsd->streamDirectoryICB.extLocation.logicalBlockNum = cpu_to_le32(offset); disc->udf_fsd->streamDirectoryICB.extLocation.partitionReferenceNum = cpu_to_le16(0); } disc->udf_fsd->descTag = query_tag(disc, pspace, desc, 1); return (length + disc->blocksize - 1) / disc->blocksize; } int setup_root(struct udf_disc *disc, struct udf_extent *pspace) { uint32_t offset = 0; struct udf_desc *desc, *fsd_desc, *tdesc; struct terminalEntry *te; desc = udf_mkdir(disc, pspace, NULL, 0, offset, NULL); // the root directory does not have a name offset = desc->offset; if (disc->flags & FLAG_STRATEGY4096) disc->udf_fsd->rootDirectoryICB.extLength = cpu_to_le32(disc->blocksize * 2); else disc->udf_fsd->rootDirectoryICB.extLength = cpu_to_le32(disc->blocksize); disc->udf_fsd->rootDirectoryICB.extLocation.logicalBlockNum = cpu_to_le32(offset); if (disc->flags & FLAG_VAT) disc->udf_fsd->rootDirectoryICB.extLocation.partitionReferenceNum = cpu_to_le16(1); else disc->udf_fsd->rootDirectoryICB.extLocation.partitionReferenceNum = cpu_to_le16(0); fsd_desc = next_desc(pspace->head, TAG_IDENT_FSD); disc->udf_fsd->descTag = query_tag(disc, pspace, fsd_desc, 1); if (disc->flags & FLAG_STRATEGY4096) { if (disc->flags & FLAG_BLANK_TERMINAL) { // tdesc = set_desc(pspace, TAG_IDENT_IE, offset+1, sizeof(struct indirectEntry), NULL); offset ++; } else { tdesc = set_desc(pspace, TAG_IDENT_TE, offset+1, sizeof(struct terminalEntry), NULL); te = (struct terminalEntry *)tdesc->data->buffer; te->icbTag.priorRecordedNumDirectEntries = cpu_to_le32(1); te->icbTag.strategyType = cpu_to_le16(4096); te->icbTag.strategyParameter = cpu_to_le16(1); te->icbTag.numEntries = cpu_to_le16(2); te->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(desc->offset); te->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); te->icbTag.fileType = ICBTAG_FILE_TYPE_TE; te->descTag = query_tag(disc, pspace, tdesc, 1); offset = tdesc->offset; } } if (next_extent(disc->head, STABLE) && next_extent(disc->head, SSPACE)) { struct udf_desc *nat; if (disc->flags & FLAG_EFE) { struct extendedFileEntry *efe; struct udf_desc *ss; ss = find_desc(pspace, le32_to_cpu(disc->udf_fsd->streamDirectoryICB.extLocation.logicalBlockNum)); #if 0 nat = udf_create(disc, pspace, NULL, 0, offset+1, NULL, FID_FILE_CHAR_DIRECTORY, ICBTAG_FILE_TYPE_STREAMDIR, 0); insert_fid(disc, pspace, nat, nat, NULL, 0, FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT); offset = nat->offset; disc->udf_fsd->streamDirectoryICB.extLength = cpu_to_le32(disc->blocksize); disc->udf_fsd->streamDirectoryICB.extLocation.logicalBlockNum = cpu_to_le32(offset); disc->udf_fsd->streamDirectoryICB.extLocation.partitionReferenceNum = cpu_to_le16(0); #endif nat = udf_create(disc, pspace, (const dchars *)"\x08" "*UDF Non-Allocatable Space", 27, offset+1, ss, FID_FILE_CHAR_METADATA, ICBTAG_FILE_TYPE_REGULAR, ICBTAG_FLAG_STREAM | ICBTAG_FLAG_SYSTEM); efe = (struct extendedFileEntry *)nat->data->buffer; efe->icbTag.flags = cpu_to_le16((le16_to_cpu(efe->icbTag.flags) & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_SHORT); efe->descTag = query_tag(disc, pspace, nat, 1); offset = nat->offset; } else { struct fileEntry *fe; nat = udf_create(disc, pspace, (const dchars *)"\x08" "Non-Allocatable Space", 22, offset+1, desc, FID_FILE_CHAR_HIDDEN, ICBTAG_FILE_TYPE_REGULAR, ICBTAG_FLAG_SYSTEM); fe = (struct fileEntry *)nat->data->buffer; fe->icbTag.flags = cpu_to_le16((le16_to_cpu(fe->icbTag.flags) & ~ICBTAG_FLAG_AD_MASK) | ICBTAG_FLAG_AD_SHORT); fe->descTag = query_tag(disc, pspace, nat, 1); offset = nat->offset; } } #if 0 // this works fine if you really want a lost+find directory on disc desc = udf_mkdir(disc, pspace, (const dchars *)"\x08" "lost+found", 11, offset+1, desc); offset = desc->offset; if (disc->flags & FLAG_STRATEGY4096) { if (disc->flags & FLAG_BLANK_TERMINAL) { // tdesc = set_desc(pspace, TAG_IDENT_IE, offset+1, sizeof(struct indirectEntry), NULL); offset ++; } else { tdesc = set_desc(pspace, TAG_IDENT_TE, offset+1, sizeof(struct terminalEntry), NULL); te = (struct terminalEntry *)tdesc->data->buffer; te->icbTag.priorRecordedNumDirectEntries = cpu_to_le32(1); te->icbTag.strategyType = cpu_to_le16(4096); te->icbTag.strategyParameter = cpu_to_le16(1); te->icbTag.numEntries = cpu_to_le16(2); te->icbTag.parentICBLocation.logicalBlockNum = cpu_to_le32(desc->offset); te->icbTag.parentICBLocation.partitionReferenceNum = cpu_to_le16(0); te->icbTag.fileType = ICBTAG_FILE_TYPE_TE; te->descTag = query_tag(disc, pspace, tdesc, 1); offset = tdesc->offset; } } #endif if (disc->flags & FLAG_STRATEGY4096) return 4; else return 2; } void setup_vds(struct udf_disc *disc) { struct udf_extent *mvds, *rvds, *lvid, *stable[4], *sspace; mvds = next_extent(disc->head, MVDS); rvds = next_extent(disc->head, RVDS); lvid = next_extent(disc->head, LVID); stable[0] = next_extent(disc->head, STABLE); sspace = next_extent(disc->head, SSPACE); if (!mvds || !rvds || !lvid) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } setup_pvd(disc, mvds, rvds, 0); setup_lvid(disc, lvid); if (stable[0] && sspace) { int i; for (i=1; i<4 && stable[i-1]; i++) { stable[i] = next_extent(stable[i-1]->next, STABLE); } setup_stable(disc, stable, sspace); } setup_lvd(disc, mvds, rvds, lvid, 1); setup_pd(disc, mvds, rvds, 2); setup_usd(disc, mvds, rvds, 3); setup_iuvd(disc, mvds, rvds, 4); if (mvds->blocks > 5) setup_td(disc, mvds, rvds, 5); } void setup_pvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset) { struct udf_desc *desc; int length = sizeof(struct primaryVolDesc); desc = set_desc(mvds, TAG_IDENT_PVD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_pvd[0]; disc->udf_pvd[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_PVD, offset, length, NULL); memcpy(disc->udf_pvd[1] = desc->data->buffer, disc->udf_pvd[0], length); disc->udf_pvd[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_lvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, struct udf_extent *lvid, uint32_t offset) { struct udf_desc *desc; int length = sizeof(struct logicalVolDesc) + le32_to_cpu(disc->udf_lvd[0]->mapTableLength); disc->udf_lvd[0]->integritySeqExt.extLength = cpu_to_le32(lvid->blocks * disc->blocksize); disc->udf_lvd[0]->integritySeqExt.extLocation = cpu_to_le32(lvid->start); // ((uint16_t *)disc->udf_lvd[0]->domainIdent.identSuffix)[0] = cpu_to_le16(disc->udf_rev); desc = set_desc(mvds, TAG_IDENT_LVD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_lvd[0]; disc->udf_lvd[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_LVD, offset, length, NULL); memcpy(disc->udf_lvd[1] = desc->data->buffer, disc->udf_lvd[0], length); disc->udf_lvd[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_pd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset) { struct udf_desc *desc; struct udf_extent *ext; int length = sizeof(struct partitionDesc); ext = next_extent(disc->head, PSPACE); if (!ext) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } disc->udf_pd[0]->partitionStartingLocation = cpu_to_le32(ext->start); disc->udf_pd[0]->partitionLength = cpu_to_le32(ext->blocks); #if 0 if (disc->udf_rev >= 0x0200) strcpy(disc->udf_pd[0]->partitionContents.ident, PARTITION_CONTENTS_NSR03); else strcpy(disc->udf_pd[0]->partitionContents.ident, PARTITION_CONTENTS_NSR02); #endif desc = set_desc(mvds, TAG_IDENT_PD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_pd[0]; disc->udf_pd[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_PD, offset, length, NULL); memcpy(disc->udf_pd[1] = desc->data->buffer, disc->udf_pd[0], length); disc->udf_pd[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_usd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset) { struct udf_desc *desc; struct udf_extent *ext; int count = 0; int length = sizeof(struct unallocSpaceDesc); ext = next_extent(disc->head, USPACE); while (ext) { length += sizeof(extent_ad); disc->udf_usd[0] = realloc(disc->udf_usd[0], length); disc->udf_usd[0]->numAllocDescs = cpu_to_le32(le32_to_cpu(disc->udf_usd[0]->numAllocDescs)+1); disc->udf_usd[0]->allocDescs[count].extLength = cpu_to_le32(ext->blocks * disc->blocksize); disc->udf_usd[0]->allocDescs[count].extLocation = cpu_to_le32(ext->start); count ++; ext = next_extent(ext->next, USPACE); } desc = set_desc(mvds, TAG_IDENT_USD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_usd[0]; disc->udf_usd[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_USD, offset, length, NULL); memcpy(disc->udf_usd[1] = desc->data->buffer, disc->udf_usd[0], length); disc->udf_usd[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_iuvd(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset) { struct udf_desc *desc; int length = sizeof(struct impUseVolDesc); // ((uint16_t *)disc->udf_iuvd[0]->impIdent.identSuffix)[0] = cpu_to_le16(disc->udf_rev); desc = set_desc(mvds, TAG_IDENT_IUVD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_iuvd[0]; disc->udf_iuvd[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_IUVD, offset, length, NULL); memcpy(disc->udf_iuvd[1] = desc->data->buffer, disc->udf_iuvd[0], length); disc->udf_iuvd[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_td(struct udf_disc *disc, struct udf_extent *mvds, struct udf_extent *rvds, uint32_t offset) { struct udf_desc *desc; int length = sizeof(struct terminatingDesc); desc = set_desc(mvds, TAG_IDENT_TD, offset, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_td[0]; disc->udf_td[0]->descTag = query_tag(disc, mvds, desc, 1); desc = set_desc(rvds, TAG_IDENT_TD, offset, length, NULL); memcpy(disc->udf_td[1] = desc->data->buffer, disc->udf_td[0], length); disc->udf_td[1]->descTag = query_tag(disc, rvds, desc, 1); } void setup_lvid(struct udf_disc *disc, struct udf_extent *lvid) { struct udf_desc *desc; // struct udf_extent *ext; int length = sizeof(struct logicalVolIntegrityDesc) + le32_to_cpu(disc->udf_lvid->numOfPartitions) * sizeof(uint32_t) * 2 + le32_to_cpu(disc->udf_lvid->lengthOfImpUse); // ext = next_extent(disc->head, PSPACE); // disc->udf_lvid->freeSpaceTable[0] = cpu_to_le32(ext->blocks); // disc->udf_lvid->sizeTable[1] = cpu_to_le32(ext->blocks); if (disc->flags & FLAG_VAT) disc->udf_lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); desc = set_desc(lvid, TAG_IDENT_LVID, 0, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_lvid; disc->udf_lvid->descTag = query_tag(disc, lvid, desc, 1); if (!(disc->flags & FLAG_BLANK_TERMINAL) && lvid->blocks > 1) { desc = set_desc(lvid, TAG_IDENT_TD, 1, sizeof(struct terminatingDesc), NULL); ((struct terminatingDesc *)desc->data->buffer)->descTag = query_tag(disc, lvid, desc, 1); } } void setup_stable(struct udf_disc *disc, struct udf_extent *stable[4], struct udf_extent *sspace) { struct udf_desc *desc; uint32_t i, num, length; uint16_t packetlen; struct sparablePartitionMap *spm; spm = find_type2_sparable_partition(disc, 0); if (!spm) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } packetlen = le16_to_cpu(spm->packetLength); num = sspace->blocks / packetlen; if (num > UINT16_MAX) num = UINT16_MAX; length = sizeof(struct sparingTable) + num * sizeof(struct sparingEntry); if (length > stable[0]->blocks * disc->blocksize) { length = stable[0]->blocks * disc->blocksize; if (length < sizeof(struct sparingTable)) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } num = (length - sizeof(struct sparingTable)) / sizeof(struct sparingEntry); if (num > UINT16_MAX) num = UINT16_MAX; if (num == 0) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } length = sizeof(struct sparingTable) + num * sizeof(struct sparingEntry); } spm->sizeSparingTable = cpu_to_le32(length); for (i=0; inumSparingTables; i++) spm->locSparingTable[i] = cpu_to_le32(stable[i]->start); disc->udf_stable[0] = realloc(disc->udf_stable[0], length); disc->udf_stable[0]->reallocationTableLen = cpu_to_le16(num); for (i=0; iudf_stable[0]->mapEntry[i].origLocation = cpu_to_le32(0xFFFFFFFF); disc->udf_stable[0]->mapEntry[i].mappedLocation = cpu_to_le32(sspace->start + (i * packetlen)); } desc = set_desc(stable[0], 0, 0, 0, NULL); desc->length = desc->data->length = length; desc->data->buffer = disc->udf_stable[0]; disc->udf_stable[0]->descTag = query_tag(disc, stable[0], desc, 1); for (i=1; i<4 && stable[i]; i++) { desc = set_desc(stable[i], 0, 0, length, NULL); memcpy(disc->udf_stable[i] = desc->data->buffer, disc->udf_stable[0], length); disc->udf_stable[i]->descTag = query_tag(disc, stable[i], desc, 1); } } void setup_vat(struct udf_disc *disc, struct udf_extent *pspace) { uint32_t offset = 0; struct udf_extent *anchor; struct udf_desc *vtable; struct udf_data *data; uint32_t len; struct virtualAllocationTable15 *vat15; struct virtualAllocationTable20 *vat20; uint16_t udf_rev_le16; if (disc->flags & FLAG_MIN_300_BLOCKS) { // On optical discs one track has minimal size of 300 sectors, so put VAT to the last sector offset = pspace->tail->offset + (pspace->tail->length + disc->blocksize-1) / disc->blocksize; if (pspace->start + offset < 299) offset = 299 - pspace->start; } if (disc->flags & FLAG_CLOSED) { anchor = prev_extent(disc->tail, ANCHOR); if (pspace->start - anchor->start > 256) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } offset = 256 - (pspace->start - anchor->start); } if (disc->udf_rev >= 0x0200) { vtable = udf_create(disc, pspace, (const dchars *)"\x08" UDF_ID_ALLOC, strlen(UDF_ID_ALLOC)+1, offset, NULL, FID_FILE_CHAR_HIDDEN, ICBTAG_FILE_TYPE_VAT20, 0); disc->vat_entries--; // Remove VAT file itself from VAT table len = sizeof(struct virtualAllocationTable20); data = alloc_data(&default_vat20, len); vat20 = data->buffer; vat20->numFiles = query_lvidiu(disc)->numFiles; vat20->numDirs = query_lvidiu(disc)->numDirs; vat20->minUDFReadRev = query_lvidiu(disc)->minUDFReadRev; vat20->minUDFWriteRev = query_lvidiu(disc)->minUDFWriteRev; vat20->maxUDFWriteRev = query_lvidiu(disc)->maxUDFWriteRev; memcpy(vat20->logicalVolIdent, disc->udf_lvd[0]->logicalVolIdent, 128); insert_data(disc, pspace, vtable, data); data = alloc_data(disc->vat, disc->vat_entries * sizeof(uint32_t)); insert_data(disc, pspace, vtable, data); } else { vtable = udf_create(disc, pspace, (const dchars *)"\x08" UDF_ID_ALLOC, strlen(UDF_ID_ALLOC)+1, offset, NULL, FID_FILE_CHAR_HIDDEN, ICBTAG_FILE_TYPE_UNDEF, 0); disc->vat_entries--; // Remove VAT file itself from VAT table len = sizeof(struct virtualAllocationTable15); data = alloc_data(disc->vat, disc->vat_entries * sizeof(uint32_t)); insert_data(disc, pspace, vtable, data); data = alloc_data(&default_vat15, len); vat15 = data->buffer; udf_rev_le16 = cpu_to_le16(disc->udf_rev); memcpy(vat15->vatIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); insert_data(disc, pspace, vtable, data); } disc->vat_block = pspace->start + vtable->offset; } void add_type1_partition(struct udf_disc *disc, uint16_t partitionNum) { struct genericPartitionMap1 *pm; int mtl = le32_to_cpu(disc->udf_lvd[0]->mapTableLength); int npm = le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps); disc->udf_lvd[0] = realloc(disc->udf_lvd[0], sizeof(struct logicalVolDesc) + mtl + sizeof(struct genericPartitionMap1)); pm = (struct genericPartitionMap1 *)&disc->udf_lvd[0]->partitionMaps[mtl]; mtl += sizeof(struct genericPartitionMap1); disc->udf_lvd[0]->mapTableLength = cpu_to_le32(mtl); disc->udf_lvd[0]->numPartitionMaps = cpu_to_le32(npm + 1); pm->partitionMapType = 1; pm->partitionMapLength = sizeof(struct genericPartitionMap1); pm->volSeqNum = cpu_to_le16(1); pm->partitionNum = cpu_to_le16(partitionNum); disc->udf_lvid->numOfPartitions = cpu_to_le32(npm + 1); disc->udf_lvid = realloc(disc->udf_lvid, sizeof(struct logicalVolIntegrityDesc) + sizeof(uint32_t) * 2 * (npm + 1) + sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * npm], sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * npm], sizeof(uint32_t)); } void add_type2_sparable_partition(struct udf_disc *disc, uint16_t partitionNum, uint8_t spartable, uint16_t packetlen) { struct sparablePartitionMap *pm; int mtl = le32_to_cpu(disc->udf_lvd[0]->mapTableLength); int npm = le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps); uint16_t udf_rev_le16 = cpu_to_le16(disc->udf_rev); disc->udf_lvd[0] = realloc(disc->udf_lvd[0], sizeof(struct logicalVolDesc) + mtl + sizeof(struct sparablePartitionMap)); pm = (struct sparablePartitionMap *)&disc->udf_lvd[0]->partitionMaps[mtl]; mtl += sizeof(struct sparablePartitionMap); disc->udf_lvd[0]->mapTableLength = cpu_to_le32(mtl); disc->udf_lvd[0]->numPartitionMaps = cpu_to_le32(npm + 1); memcpy(pm, &default_sparmap, sizeof(struct sparablePartitionMap)); pm->partitionNum = cpu_to_le16(partitionNum); memcpy(pm->partIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); if (packetlen) pm->packetLength = cpu_to_le16(packetlen); pm->numSparingTables = spartable; pm->sizeSparingTable = cpu_to_le32(sizeof(struct sparingTable)); disc->udf_lvid->numOfPartitions = cpu_to_le32(npm + 1); disc->udf_lvid = realloc(disc->udf_lvid, sizeof(struct logicalVolIntegrityDesc) + sizeof(uint32_t) * 2 * (npm + 1) + sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * npm], sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * npm], sizeof(uint32_t)); } struct sparablePartitionMap *find_type2_sparable_partition(struct udf_disc *disc, uint16_t partitionNum) { int i, npm, mtl = 0; struct genericPartitionMap *pm; struct udfPartitionMap2 *pm2; struct sparablePartitionMap *spm; npm = le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps); for (i=0; iudf_lvd[0]->partitionMaps[mtl]; if (pm->partitionMapType == 2) { pm2 = (struct udfPartitionMap2 *)&disc->udf_lvd[0]->partitionMaps[mtl]; if (!strncmp((char *)pm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { spm = (struct sparablePartitionMap *)&disc->udf_lvd[0]->partitionMaps[mtl]; if (le16_to_cpu(spm->partitionNum) == partitionNum) return spm; } } mtl += pm->partitionMapLength; } return NULL; } void add_type2_virtual_partition(struct udf_disc *disc, uint16_t partitionNum) { struct virtualPartitionMap *pm; int mtl = le32_to_cpu(disc->udf_lvd[0]->mapTableLength); int npm = le32_to_cpu(disc->udf_lvd[0]->numPartitionMaps); uint16_t udf_rev_le16 = cpu_to_le16(disc->udf_rev); disc->udf_lvd[0] = realloc(disc->udf_lvd[0], sizeof(struct logicalVolDesc) + mtl + sizeof(struct virtualPartitionMap)); pm = (struct virtualPartitionMap *)&disc->udf_lvd[0]->partitionMaps[mtl]; mtl += sizeof(struct virtualPartitionMap); disc->udf_lvd[0]->mapTableLength = cpu_to_le32(mtl); disc->udf_lvd[0]->numPartitionMaps = cpu_to_le32(npm + 1); memcpy(pm, &default_virtmap, sizeof(struct virtualPartitionMap)); pm->partitionNum = cpu_to_le16(partitionNum); memcpy(pm->partIdent.identSuffix, &udf_rev_le16, sizeof(udf_rev_le16)); disc->udf_lvid->numOfPartitions = cpu_to_le32(npm + 1); disc->udf_lvid = realloc(disc->udf_lvid, sizeof(struct logicalVolIntegrityDesc) + sizeof(uint32_t) * 2 * (npm + 1) + sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * 2 * npm], sizeof(struct logicalVolIntegrityDescImpUse)); memmove(&disc->udf_lvid->impUse[sizeof(uint32_t) * (npm + 1)], &disc->udf_lvid->impUse[sizeof(uint32_t) * npm], sizeof(uint32_t)); } char *udf_space_type_str[UDF_SPACE_TYPE_SIZE] = { "RESERVED", "VRS", "ANCHOR", "MVDS", "RVDS", "LVID", "STABLE", "SSPACE", "PSPACE", "USPACE", "BAD", "MBR" }; udftools-2.0/mkudffs/main.c0000644000175000017500000002657313221466537012710 00000000000000/* * main.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * mkudffs main program and I/O functions */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mkudffs.h" #include "defaults.h" #include "options.h" static int valid_offset(int fd, off_t offset) { char ch; if (lseek(fd, offset, SEEK_SET) < 0) return 0; if (read(fd, &ch, 1) < 1) return 0; return 1; } static uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks) { uint64_t blocks; #ifdef BLKGETSIZE64 uint64_t size64; #endif #ifdef BLKGETSIZE long size; #endif #ifdef FDGETPRM struct floppy_struct this_floppy; #endif struct stat buf; if (opt_blocks) return opt_blocks; if (fd <= 0) return 0; #ifdef BLKGETSIZE64 if (ioctl(fd, BLKGETSIZE64, &size64) >= 0) blocks = size64 / blocksize; else #endif #ifdef BLKGETSIZE if (ioctl(fd, BLKGETSIZE, &size) >= 0) blocks = size / (blocksize / 512); else #endif #ifdef FDGETPRM if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) blocks = this_floppy.size / (blocksize / 512); else #endif if (fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode)) blocks = buf.st_size / blocksize; else { off_t high, low; for (low=0, high = 1024; valid_offset(fd, high); high *= 2) low = high; while (low < high - 1) { const off_t mid = (low + high) / 2; if (valid_offset(fd, mid)) low = mid; else high = mid; } valid_offset(fd, 0); blocks = (low + 1) / blocksize; } if (blocks > UINT32_MAX) { fprintf(stderr, "%s: Warning: Disk is too big, using only %lu blocks\n", appname, (unsigned long int)UINT32_MAX); return UINT32_MAX; } return blocks; } static void detect_blocksize(int fd, struct udf_disc *disc, int *blocksize) { #ifdef BLKSSZGET int size; if (ioctl(fd, BLKSSZGET, &size) != 0 || size <= 0) return; disc->blkssz = size; if (*blocksize != -1) return; if (size < 512 || size > 32768 || (size & (size - 1))) { fprintf(stderr, "%s: Warning: Disk logical sector size (%d) is not suitable for UDF\n", appname, size); return; } disc->blocksize = size; *blocksize = disc->blocksize; disc->udf_lvd[0]->logicalBlockSize = cpu_to_le32(disc->blocksize); #endif } static int is_whole_disk(int fd) { struct stat st; char buf[512]; DIR *dir; struct dirent *d; int maj; int min; int has_slave; int slave_errno; if (fstat(fd, &st) != 0) return -1; if (!S_ISBLK(st.st_mode)) return 1; maj = major(st.st_rdev); min = minor(st.st_rdev); if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/partition", maj, min) >= (int)sizeof(buf)) return -1; if (stat(buf, &st) == 0) return 0; else if (errno != ENOENT) return -1; if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/slaves/", maj, min) >= (int)sizeof(buf)) return -1; dir = opendir(buf); if (!dir && errno != ENOENT) return -1; if (dir) { errno = 0; has_slave = 0; while ((d = readdir(dir))) { if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) continue; has_slave = 1; break; } slave_errno = errno; closedir(dir); if (slave_errno) return -1; if (has_slave) return 0; } if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/", maj, min) >= (int)sizeof(buf)) return -1; if (stat(buf, &st) != 0) return -1; return 1; } static int is_removable_disk(int fd) { struct stat st; char buf[512]; ssize_t ret; if (fstat(fd, &st) != 0) return -1; if (!S_ISBLK(st.st_mode)) return -1; if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/removable", major(st.st_rdev), minor(st.st_rdev)) >= (int)sizeof(buf)) return -1; int rem_fd = open(buf, O_RDONLY); if (rem_fd < 0) return -1; ret = read(rem_fd, buf, sizeof(buf)-1); close(rem_fd); if (ret < 0) return -1; buf[ret] = 0; if (strcmp(buf, "1\n") == 0) return 1; else if (strcmp(buf, "0\n") == 0) return 0; return -1; } static int write_func(struct udf_disc *disc, struct udf_extent *ext) { static char *buffer = NULL; static size_t bufferlen = 0; int fd = *(int *)disc->write_data; ssize_t length, offset; uint32_t blocks; struct udf_desc *desc; struct udf_data *data; if (buffer == NULL) { bufferlen = disc->blocksize; buffer = calloc(bufferlen, 1); } if (!(ext->space_type & (USPACE|RESERVED))) { desc = ext->head; while (desc != NULL) { if (!(disc->flags & FLAG_NO_WRITE) || fd >= 0) { if (lseek(fd, (off_t)(ext->start + desc->offset) * disc->blocksize, SEEK_SET) < 0) return -1; } data = desc->data; offset = 0; while (data != NULL) { if (data->length + offset > bufferlen) { bufferlen = (data->length + offset + disc->blocksize - 1) & ~(disc->blocksize - 1); buffer = realloc(buffer, bufferlen); } memcpy(buffer + offset, data->buffer, data->length); offset += data->length; data = data->next; } length = (offset + disc->blocksize - 1) & ~(disc->blocksize - 1); if (offset != length) memset(buffer + offset, 0x00, length - offset); if (!(disc->flags & FLAG_NO_WRITE)) { if (write(fd, buffer, length) != length) return -1; } desc = desc->next; } } else if (!(disc->flags & FLAG_BOOTAREA_PRESERVE)) { length = disc->blocksize; blocks = ext->blocks; memset(buffer, 0, length); if (!(disc->flags & FLAG_NO_WRITE) || fd >= 0) { if (lseek(fd, (off_t)(ext->start) * disc->blocksize, SEEK_SET) < 0) return -1; } while (blocks-- > 0) { if (!(disc->flags & FLAG_NO_WRITE)) { if (write(fd, buffer, length) != length) return -1; } } } return 0; } int main(int argc, char *argv[]) { struct udf_disc disc; struct stat stat; char *filename; char buf[128*3]; int fd; int create_new_file = 0; int blocksize = -1; int media; size_t len; if (fcntl(0, F_GETFL) < 0 && open("/dev/null", O_RDONLY) < 0) _exit(1); if (fcntl(1, F_GETFL) < 0 && open("/dev/null", O_WRONLY) < 0) _exit(1); if (fcntl(2, F_GETFL) < 0 && open("/dev/null", O_WRONLY) < 0) _exit(1); setlocale(LC_CTYPE, ""); appname = "mkudffs"; udf_init_disc(&disc); parse_args(argc, argv, &disc, &filename, &create_new_file, &blocksize, &media); if (disc.flags & FLAG_NO_WRITE) printf("Note: Not writing to device, just simulating\n"); fd = open(filename, O_RDONLY); if (fd < 0) { if (errno != ENOENT) { fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, strerror(errno)); exit(1); } if (!disc.blocks) { fprintf(stderr, "%s: Error: Cannot create new image file '%s': block-count was not specified\n", appname, filename); exit(1); } } else { int fd2; int flags2; char filename2[64]; const char *error; if (create_new_file) { fprintf(stderr, "%s: Error: Cannot create new image file '%s': %s\n", appname, filename, strerror(EEXIST)); exit(1); } if (fstat(fd, &stat) != 0) { fprintf(stderr, "%s: Error: Cannot stat device '%s': %s\n", appname, filename, strerror(errno)); exit(1); } if (!(disc.flags & FLAG_NO_WRITE)) flags2 = O_RDWR; else flags2 = O_RDONLY; if (snprintf(filename2, sizeof(filename2), "/proc/self/fd/%d", fd) >= (int)sizeof(filename2)) { fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, strerror(ENAMETOOLONG)); exit(1); } // Re-open block device with O_EXCL mode which fails when device is already mounted if (S_ISBLK(stat.st_mode)) flags2 |= O_EXCL; fd2 = open(filename2, flags2); if (fd2 < 0) { if (errno != ENOENT) { error = (errno != EBUSY) ? strerror(errno) : "Device is mounted or mkudffs is already running"; fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, error); exit(1); } // Fallback to orignal filename when /proc is not available, but this introduce race condition between stat and open fd2 = open(filename, flags2); if (fd2 < 0) { error = (errno != EBUSY) ? strerror(errno) : "Device is mounted or mkudffs is already running"; fprintf(stderr, "%s: Error: Cannot open device '%s': %s\n", appname, filename, error); exit(1); } } close(fd); fd = fd2; } if (fd >= 0) detect_blocksize(fd, &disc, &blocksize); if (blocksize == -1 && media == MEDIA_TYPE_HD) { disc.blocksize = 512; disc.udf_lvd[0]->logicalBlockSize = cpu_to_le32(disc.blocksize); } disc.blocks = get_blocks(fd, disc.blocksize, disc.blocks); disc.head->blocks = disc.blocks; disc.write = write_func; disc.write_data = &fd; if (!(disc.flags & FLAG_BOOTAREA_MASK)) { if (media != MEDIA_TYPE_HD) disc.flags |= FLAG_BOOTAREA_PRESERVE; else if (fd >= 0 && is_removable_disk(fd) == 0 && is_whole_disk(fd) == 1) disc.flags |= FLAG_BOOTAREA_MBR; else disc.flags |= FLAG_BOOTAREA_ERASE; } printf("filename=%s\n", filename); memset(buf, 0, sizeof(buf)); len = decode_string(&disc, disc.udf_lvd[0]->logicalVolIdent, buf, 128, sizeof(buf)); printf("label=%s\n", buf); memset(buf, 0, sizeof(buf)); len = gen_uuid_from_vol_set_ident(buf, disc.udf_pvd[0]->volSetIdent, 128); printf("uuid=%s\n", buf); printf("blocksize=%u\n", (unsigned int)disc.blocksize); printf("blocks=%lu\n", (unsigned long int)disc.blocks); printf("udfrev=%x.%02x\n", (unsigned int)(disc.udf_rev >> 8), (unsigned int)(disc.udf_rev & 0xFF)); split_space(&disc); setup_mbr(&disc); setup_vrs(&disc); setup_anchor(&disc); setup_partition(&disc); setup_vds(&disc); if (disc.vat_block) printf("vatblock=%lu\n", (unsigned long int)disc.vat_block); dump_space(&disc); if (len == (size_t)-1) fprintf(stderr, "%s: Warning: Volume Set Identifier must be at least 8 characters long\n", appname); else if (len < 16) fprintf(stderr, "%s: Warning: First 16 characters of Volume Set Identifier are not hexadecimal lowercase digits\n%s: Warning: This would cause problems for UDF uuid\n", appname, appname); if (fd >= 0 && is_whole_disk(fd) == 0) fprintf(stderr, "%s: Warning: Creating new UDF filesystem on partition, and not on whole disk device\n%s: Warning: UDF filesystem on partition cannot be read on Apple systems\n", appname, appname); if (fd < 0 && !(disc.flags & FLAG_NO_WRITE)) { // Create new file disk image fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0660); if (fd < 0) { fprintf(stderr, "%s: Error: Cannot create new image file '%s': %s\n", appname, filename, strerror(errno)); exit(1); } } if (write_disc(&disc) < 0) { fprintf(stderr, "%s: Error: Cannot write to device '%s': %s\n", appname, filename, strerror(errno)); return 1; } return 0; } udftools-2.0/mkudffs/Makefile.in0000644000175000017500000004721213221466653013655 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = mkudffs$(EXEEXT) subdir = mkudffs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_mkudffs_OBJECTS = main.$(OBJEXT) mkudffs.$(OBJEXT) \ defaults.$(OBJEXT) file.$(OBJEXT) options.$(OBJEXT) mkudffs_OBJECTS = $(am_mkudffs_OBJECTS) mkudffs_DEPENDENCIES = $(top_builddir)/libudffs/libudffs.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mkudffs_SOURCES) DIST_SOURCES = $(mkudffs_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ mkudffs_LDADD = $(top_builddir)/libudffs/libudffs.la mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mkudffs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu mkudffs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mkudffs$(EXEEXT): $(mkudffs_OBJECTS) $(mkudffs_DEPENDENCIES) $(EXTRA_mkudffs_DEPENDENCIES) @rm -f mkudffs$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mkudffs_OBJECTS) $(mkudffs_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaults.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkudffs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-exec-am install-strip uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-exec-hook install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-hook uninstall-sbinPROGRAMS .PRECIOUS: Makefile install-exec-hook: cd "$(DESTDIR)$(sbindir)" && ln -sf mkudffs$(EXEEXT) mkfs.udf$(EXEEXT) uninstall-hook: cd "$(DESTDIR)$(sbindir)" && rm -f mkfs.udf$(EXEEXT) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/mkudffs/Makefile.am0000644000175000017500000000075113221466537013642 00000000000000sbin_PROGRAMS = mkudffs mkudffs_LDADD = $(top_builddir)/libudffs/libudffs.la mkudffs_SOURCES = main.c mkudffs.c defaults.c file.c options.c mkudffs.h defaults.h file.h options.h ../include/ecma_167.h ../include/osta_udf.h ../include/libudffs.h ../include/udf_endian.h ../include/bswap.h AM_CPPFLAGS = -I$(top_srcdir)/include install-exec-hook: cd "$(DESTDIR)$(sbindir)" && ln -sf mkudffs$(EXEEXT) mkfs.udf$(EXEEXT) uninstall-hook: cd "$(DESTDIR)$(sbindir)" && rm -f mkfs.udf$(EXEEXT) udftools-2.0/libudffs/0000755000175000017500000000000013221466662012021 500000000000000udftools-2.0/libudffs/unicode.c0000644000175000017500000002045413221466537013541 00000000000000/* * unicode.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * libudffs unicode handling functions */ #include "config.h" #include "libudffs.h" #include #include #include #include #include #include size_t decode_utf8(const dchars *in, char *out, size_t inlen, size_t outlen) { size_t len = 0, i; unsigned int c; if (outlen == 0) return (size_t)-1; if (in[0] != 8 && in[0] != 16) return (size_t)-1; if (in[0] == 16 && (inlen-1) % 2 != 0) return (size_t)-1; for (i=1; i= outlen) return (size_t)-1; out[len++] = (uint8_t)c; } else if (c < 0x800U) { if (len+2 >= outlen) return (size_t)-1; out[len++] = (uint8_t)(0xc0 | (c >> 6)); out[len++] = (uint8_t)(0x80 | (c & 0x3f)); } else { if (len+3 >= outlen) return (size_t)-1; out[len++] = (uint8_t)(0xe0 | (c >> 12)); out[len++] = (uint8_t)(0x80 | ((c >> 6) & 0x3f)); out[len++] = (uint8_t)(0x80 | (c & 0x3f)); } } out[len] = 0; return len; } size_t encode_utf8(dchars *out, const char *in, size_t outlen) { size_t inlen = strlen(in); size_t len, i; int utf_cnt; uint32_t utf_char, max_val; unsigned int c; len = 1; out[0] = 8; max_val = 0x7F; try_again: utf_cnt = 0; utf_char = 0; for (i=0; i max_val) { if (max_val == 0x7F) { len = 1; max_val = 0xFFFF; out[0] = 0x10; goto try_again; } return (size_t)-1; } if (max_val == 0xFFFF) { if (len + 2 > outlen) { len = 1; max_val = 0xFF; out[0] = 0x8; goto try_again; } out[len++] = utf_char >> 8; } if (len + 1 > outlen) return (size_t)-1; out[len++] = utf_char & 0xFF; } if (utf_cnt) { error_invalid: fprintf(stderr, "%s: Error: Cannot convert input string from UTF-8 encoding: Invalid or incomplete UTF-8 sequence\n", appname); exit(1); } return len; } size_t decode_locale(const dchars *in, char *out, size_t inlen, size_t outlen) { size_t len = 0, i; size_t wcslen, clen; wchar_t *wcs; mbstate_t ps; char cbuf[MB_CUR_MAX]; if (outlen == 0) return (size_t)-1; if (in[0] == 16 && (inlen-1) % 2 != 0) return (size_t)-1; if (in[0] == 8) wcslen = (inlen-1); else if (in[0] == 16) wcslen = (inlen-1)/2; else return (size_t)-1; wcs = calloc(wcslen+1, sizeof(wchar_t)); if (!wcs) return (size_t)-1; for (i=1; i outlen) { free(wcs); return (size_t)-1; } memcpy(out+len, cbuf, clen); len += clen; } out[len] = 0; free(wcs); return len; } size_t encode_locale(dchars *out, const char *in, size_t outlen) { size_t i; size_t mbslen; size_t len; wchar_t max_val; wchar_t *wcs; mbslen = mbstowcs(NULL, in, 0); if (mbslen == (size_t)-1) { fprintf(stderr, "%s: Error: Cannot convert input string from current locale encoding: %s\n", appname, strerror(errno)); exit(1); } wcs = calloc(mbslen+1, sizeof(wchar_t)); if (!wcs) goto error_out; if (mbstowcs(wcs, in, mbslen+1) == (size_t)-1) goto error_out; len = 1; out[0] = 8; max_val = 0x7F; try_again: for (i=0; i max_val) { if (max_val == 0x7F) { len = 1; out[0] = 16; max_val = 0xFFFF; goto try_again; } goto error_out; } if (max_val == 0xFFFF) { if (len+2 > outlen) { len = 1; out[0] = 8; max_val = 0xFF; goto try_again; } out[len++] = (wcs[i] >> 8) & 0xFF; } if (len+1 > outlen) goto error_out; out[len++] = wcs[i] & 0xFF; } free(wcs); return len; error_out: free(wcs); return (size_t)-1; } size_t decode_string(struct udf_disc *disc, const dstring *in, char *out, size_t inlen, size_t outlen) { uint32_t flags = disc ? disc->flags : FLAG_LOCALE; if (in[0] == 0 && outlen) { out[0] = 0; return 0; } if (in[inlen-1] == 0 || in[inlen-1] >= inlen) return (size_t)-1; inlen = in[inlen-1]; if (flags & FLAG_UTF8) return decode_utf8((dchars *)in, out, inlen, outlen); else if (flags & FLAG_LOCALE) return decode_locale((dchars *)in, out, inlen, outlen); else if (flags & (FLAG_UNICODE8 | FLAG_UNICODE16)) { size_t i; if (in[0] != 8 && in[0] != 16) return (size_t)-1; if (in[0] == 16 && (inlen-1) % 2 != 0) return (size_t)-1; if ((in[0] == 8 && (flags & FLAG_UNICODE8)) || (in[0] == 16 && (flags & FLAG_UNICODE16))) { if (inlen > outlen) return (size_t)-1; memcpy(out, &in[1], inlen); if (in[0] == 0x10 && (flags & FLAG_UNICODE16)) { if (inlen+1 > outlen) return (size_t)-1; out[inlen] = 0; return inlen+1; } return inlen; } else if (flags & FLAG_UNICODE16) { if (2*(inlen-1)+2 > outlen) return (size_t)-1; for (i=1; i outlen) return (size_t)-1; for (i=1; iflags : FLAG_LOCALE; size_t ret = (size_t)-1; if (outlen == 0) return (size_t)-1; if (in[0] == 0) { memset(out, 0, outlen); return 0; } if (flags & FLAG_UTF8) ret = encode_utf8((dchars *)out, in, outlen-1); else if (flags & FLAG_LOCALE) ret = encode_locale((dchars *)out, in, outlen-1); else if (flags & (FLAG_UNICODE8|FLAG_UNICODE16)) { size_t inlen = strlen(in); memset(out, 0, outlen); if (inlen >= outlen - 2) return (size_t)-1; memcpy(&out[1], in, inlen); if (flags & FLAG_UNICODE8) out[0] = 0x08; else out[0] = 0x10; ret = inlen + 1; } if (ret != (size_t)-1 && ret > 1 && ret < 256) { memset(out+ret, 0, outlen-ret-1); out[outlen-1] = ret; } else { memset(out, 0, outlen); ret = (size_t)-1; } return ret; } udftools-2.0/libudffs/misc.c0000644000175000017500000000364113221466537013045 00000000000000/* * Copyright (C) 2017 Pali Rohár * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include "libudffs.h" const char *appname; size_t gen_uuid_from_vol_set_ident(char uuid[17], const dstring *vol_set_ident, size_t size) { size_t i; size_t len; size_t nonhexpos; unsigned char buf[127*4+1]; memset(buf, 0, sizeof(buf)); if (size > 0 && vol_set_ident[size-1] > 0 && vol_set_ident[size-1] < size) len = decode_utf8((dchars *)vol_set_ident, (char *)buf, vol_set_ident[size-1], sizeof(buf)); else len = 0; if (len < 8) { uuid[0] = 0; return (size_t)-1; } nonhexpos = 16; for (i = 0; i < 16; ++i) { if (!isxdigit(buf[i])) { nonhexpos = i; break; } } if (nonhexpos < 8) { snprintf(uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); } else if (nonhexpos < 16) { for (i = 0; i < 8; ++i) uuid[i] = tolower(buf[i]); snprintf(uuid + 8, 9, "%02x%02x%02x%02x", buf[8], buf[9], buf[10], buf[11]); } else { for (i = 0; i < 16; ++i) uuid[i] = tolower(buf[i]); uuid[16] = 0; } if (nonhexpos < 16) return nonhexpos; return 16; } udftools-2.0/libudffs/extent.c0000644000175000017500000004113013221466537013414 00000000000000/* * extent.c * * Copyright (c) 2001-2002 Ben Fennema * Copyright (c) 2014-2017 Pali Rohár * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /** * @file * libudffs extend handling functions */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "libudffs.h" /** * This code was very sparsely commented and essentially undocumented as written. * Comments and doxygen documentation were generated by code inspection more than * a decade after the fact. If you find errors please feel free to correct them. * * For a more detailed discussion about descriptors the comments at the top * of file.c in this directory. * * Volume space is the set of all blocks on a particular physical disc volume. * Blocks in volume space are described using an 32-bit short_ad. * A volume-set is multiple related physical volumes, usually with a robotic * media changer. Blocks anywhere in a volume set are described by an 48-bit * long_ad which contains a volume identifier as well as a location * in the volume space of the identifed volume. Block numbers in volume space * start at zero and are relative to the first block of the media. * * Partition space is the set of all blocks contained in a logical partition. * Block numbers in partition space start at zero and are relative to the first * block of the partition, *NOT* the first block of of the media * * An 'extent' is a contiguous set of data and a descriptor is a structure * containing descriptive information, but these names are used in two very * different ways when creating a UDF filesystem on a disc volume/volume-set. * * An ECMA-167 extent is a region in the volume space of a single physical * disc volume described by type extent_ad having a 32-bit starting block * and a 32-bit length <2^30 *BYTES* which is normally a multiple of blocksize. * The two high order bits define the allocated/written status of the extent. * These extents are used in on-disc descriptors at the physical volume level * for structures such as the primary volume descriptor and anchor points that * operate above the filesystem level. * * The on-disc descriptors are little-endian and require the use of various * le*_to_cpu() and cpu_to_le*() functions when reading and writing them. * Descriptors like the primary volume descriptor which are shared with other * standards such as ECMA-119/ISO-9660 begin with a one byte type identifier. * Other descriptors which are specific to ECMA-167 and UDF begin with a 16-byte * tag which starts with a two byte tag identifer and contains additional * information such as a CRC field which is pertinent to udf_extents. * * A udf_extent is an in-memory structure used to organize UDF filesystem level * structures such as directories and files and is described using a struct * udf_extent having a 32-bit starting block and a 32-bit length *IN BLOCKS* * as well as a space type such as unallocated or partition space and various * linked lists in cpu byte order. A udf_disc starts with a single extent of * unallocated space which becomes a list as that extent is split and the new * smaller extents are used for various things. A udf_extent has a udf_descriptor * list which is kept sorted by the location within the extent of the described * blocks. A udf_descriptor can have a number of different tag identifiers such * as file-entry/extended-file-entry descriptor or allocation descriptor. * A udf_descriptor has a udf_data list. A udf_data item carries a payload of * arbitrary data dependent on the descriptor type. The udf_descriptor can be * thought of as the in-memory version of the descriptor tag since it contains * the tag ident. The on-disc format structure corresponding to that tag is * stored in the first udf_data item on the udf_data list of that descriptor. * The 16-byte on-disc format tag will be at the beginning of that structure. * * Once the UDF volume structure has been constructed in memory, writing it to * disc is just a matter of iterating through the extents and their descriptors * and data in order and writing them sequentially onto the media while also * converting to the on-disc little-endian format as needed. */ /** * @brief find the next udf_extent of a given space_type on a udf_extent list * @param start_ext the starting udf_extent for the search * @param type the space_type of the udf_extent to search for * @return the in-memory address of udf_extent or NULL */ struct udf_extent *next_extent(struct udf_extent *start_ext, enum udf_space_type type) { while (start_ext != NULL && !(start_ext->space_type & type)) start_ext = start_ext->next; return start_ext; } /** * @brief find the next udf_extent of a given space_type on a udf_extent list * that satisfies the necessary size and alignment * @param disc the udf_disc containing the blocks * @param start_ext the starting udf_extent for the search * @param type the space_type of the udf_extent to search for * @param blocks the minimum size of the udf_extent in blocks * @param offset the required alignment for the start block * @return the start block of the aligned udf_extent or zero */ uint32_t next_extent_size(struct udf_disc *disc, struct udf_extent *start_ext, enum udf_space_type type, uint32_t blocks, uint32_t offset) { return find_next_extent_size(disc, start_ext->start, type, blocks, offset); } /** * @brief find the next udf_extent of a given space_type on a udf_extent list * that satisfies the necessary size and alignment * @param disc the udf_disc containing the blocks * @param start the block to search for * @param type the space_type of the udf_extent to search for * @param blocks the minimum size of the udf_extent in blocks * @param offset the required alignment for the start block * @return the start block of the aligned udf_extent or zero */ uint32_t find_next_extent_size(struct udf_disc *disc, uint32_t start, enum udf_space_type type, uint32_t blocks, uint32_t offset) { uint32_t inc; struct udf_extent *start_ext; start_ext = next_extent(find_extent(disc, start), type); cont: while (start_ext != NULL && start_ext->blocks < blocks) start_ext = next_extent(start_ext->next, type); if (start_ext != NULL && (start_ext->start % offset || start_ext->start < start)) { if (start_ext->start < start) inc = start - start_ext->start; else inc = offset - (start_ext->start % offset); if (start_ext->blocks - inc < blocks) { start_ext = next_extent(start_ext->next, type); goto cont; } } else inc = 0; return start_ext ? start_ext->start + inc : 0; } /** * @brief find the previous udf_extent of a given space_type on a udf_extent list * @param start_ext the starting udf_extent for the search * @param type the space_type of the udf_extent to search for * @return the in-memory address of the udf_extent or NULL */ struct udf_extent *prev_extent(struct udf_extent *start_ext, enum udf_space_type type) { while (start_ext != NULL && !(start_ext->space_type & type)) start_ext = start_ext->prev; return start_ext; } /** * @brief find the previous udf_extent of a given space_type on a udf_extent * list that satisfies the necessary size and alignment * @param start_ext the starting udf_extent for the search * @param type the space_type of the udf_extent to search for * @param blocks the minimum size of the udf_extent in blocks * @param offset the required alignment for the start block * @return the start block of the aligned udf_extent or zero */ uint32_t prev_extent_size(struct udf_extent *start_ext, enum udf_space_type type, uint32_t blocks, uint32_t offset) { uint32_t inc; start_ext = prev_extent(start_ext, type); cont: while (start_ext != NULL && start_ext->blocks < blocks) start_ext = prev_extent(start_ext->prev, type); if (start_ext != NULL && (start_ext->start % offset)) { inc = offset - (start_ext->start % offset); if (start_ext->blocks - inc < blocks) { start_ext = prev_extent(start_ext->prev, type); goto cont; } } else inc = 0; return start_ext ? start_ext->start + inc + ((start_ext->blocks - inc - blocks)/offset)*offset : 0; } /** * @brief find the udf_extent on a udf_disc's udf_extent list which contains * a particular block * @param disc the udf_disc containing the udf_extent list head * @param start the block to search for * @return the in-memory address of the udf_extent or NULL */ struct udf_extent *find_extent(struct udf_disc *disc, uint32_t start) { struct udf_extent *start_ext = disc->head; while (start_ext->next != NULL) { if (start_ext->start + start_ext->blocks > start) break; start_ext = start_ext->next; } return start_ext; } /** * @brief set the space_type, location and size of a udf_extent on a * udf_disc's udf_extent list, splitting the udf_extent if required * to have the returned udf_extent only contain the requested blocks * @param disc the udf_disc containing the blocks * @param type the space_type of the udf_extent * @param start the start block of the udf_extent * @param blocks the size of the udf_extent in blocks * @return the in-memory address of the udf_extent */ struct udf_extent *set_extent(struct udf_disc *disc, enum udf_space_type type, uint32_t start, uint32_t blocks) { struct udf_extent *new_ext, *start_ext = find_extent(disc, start); if (start < start_ext->start) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } if (start == start_ext->start) { if (blocks == start_ext->blocks) { start_ext->space_type = type; return start_ext; } else if (blocks < start_ext->blocks) { new_ext = malloc(sizeof(struct udf_extent)); new_ext->space_type = type; new_ext->start = start; new_ext->blocks = blocks; new_ext->head = new_ext->tail = NULL; new_ext->prev = start_ext->prev; if (new_ext->prev) new_ext->prev->next = new_ext; new_ext->next = start_ext; if (disc->head == start_ext) disc->head = new_ext; start_ext->start += blocks; start_ext->blocks -= blocks; start_ext->prev = new_ext; return new_ext; } else /* blocks > start_ext->blocks */ { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } } else /* start > start_ext->start */ { if (start + blocks == start_ext->start + start_ext->blocks) { new_ext = malloc(sizeof(struct udf_extent)); new_ext->space_type = type; new_ext->start = start; new_ext->blocks = blocks; new_ext->head = new_ext->tail = NULL; new_ext->prev = start_ext; new_ext->next = start_ext->next; if (new_ext->next) new_ext->next->prev = new_ext; if (disc->tail == start_ext) disc->tail = new_ext; start_ext->blocks -= blocks; start_ext->next = new_ext; return new_ext; } else if (start + blocks < start_ext->start + start_ext->blocks) { new_ext = malloc(sizeof(struct udf_extent)); new_ext->space_type = type; new_ext->start = start; new_ext->blocks = blocks; new_ext->head = new_ext->tail = NULL; new_ext->prev = start_ext; new_ext->next = malloc(sizeof(struct udf_extent)); new_ext->next->prev = new_ext; new_ext->next->space_type = start_ext->space_type; new_ext->next->start = start + blocks; new_ext->next->blocks = start_ext->blocks - blocks - start + start_ext->start; new_ext->next->head = new_ext->next->tail = NULL; new_ext->next->next = start_ext->next; if (new_ext->next->next) new_ext->next->next->prev = new_ext->next; if (disc->tail == start_ext) disc->tail = new_ext->next; start_ext->blocks = start - start_ext->start; start_ext->next = new_ext; return new_ext; } else /* start + blocks > start_ext->start + start_ext->blocks */ { if (start_ext->blocks < blocks) { fprintf(stderr, "%s: Error: Not enough blocks on device\n", appname); exit(1); } new_ext = malloc(sizeof(struct udf_extent)); new_ext->space_type = type; new_ext->start = start; new_ext->blocks = blocks; new_ext->head = new_ext->tail = NULL; new_ext->prev = start_ext; new_ext->next = start_ext->next; if (new_ext->next) new_ext->next->prev = new_ext; if (disc->tail == start_ext) disc->tail = new_ext; start_ext->blocks -= blocks; start_ext->next = new_ext; return new_ext; } } } /** * @brief find the next udf_descriptor of a given tag ident on a udf_descriptor list * @param start_desc the starting udf_descriptor for the search * @param ident the tag ident of udf_descriptor to search for * @return the in-memory address of the udf_descriptor or NULL */ struct udf_desc *next_desc(struct udf_desc *start_desc, uint16_t ident) { while (start_desc != NULL && start_desc->ident != ident) start_desc = start_desc->next; return start_desc; } /** * @brief search the udf_descriptor list of a udf_extent to find the udf_descriptor * that describes a particular block * @param ext the udf_extent containing the udf_descriptor list head * @param offset the block to search for * @return the in-memory address of the udf_descriptor or NULL */ struct udf_desc *find_desc(struct udf_extent *ext, uint32_t offset) { struct udf_desc *start_desc = ext->head; while (start_desc->next != NULL) { if (start_desc->offset == offset) return start_desc; else if (start_desc->offset > offset) return start_desc->prev; else start_desc = start_desc->next; } return start_desc; } /** * @brief allocate a new udf_descriptor having a udf_data item and insert it * into the udf_descriptor list of a udf_extent ordered by block number * @oaram ext the udf_extent containing the udf_descriptor list head * @param ident the tag ident of the new udf_descriptor * @param offset the first block the new descriptor describes * @param length the length of the udf_data item payload in bytes * @param data the udf_data item, if NULL allocate memory for the udf_data item * @return the in-memory address of the new udf_descriptor */ struct udf_desc *set_desc(struct udf_extent *ext, uint16_t ident, uint32_t offset, uint32_t length, struct udf_data *data) { struct udf_desc *start_desc, *new_desc = calloc(1, sizeof(struct udf_desc)); new_desc->ident = ident; new_desc->offset = offset; new_desc->length = length; if (data == NULL) new_desc->data = alloc_data(NULL, length); else new_desc->data = data; if (ext->head == NULL) { ext->head = ext->tail = new_desc; new_desc->next = new_desc->prev = NULL; } else { start_desc = find_desc(ext, offset); if (start_desc == NULL) { new_desc->next = ext->head; new_desc->prev = NULL; new_desc->next->prev = new_desc; ext->head = new_desc; } else { new_desc->next = start_desc->next; new_desc->prev = start_desc; if (start_desc->next) start_desc->next->prev = new_desc; else ext->tail = new_desc; start_desc->next = new_desc; } } return new_desc; } /** * @brief append a udf_data list to the end of the udf_data list of a * udf_descriptor and update the udf_descriptor summed data length * @param desc the udf_descriptor containing the target udf_data list head * @param data the source udf_data list head * @return void */ void append_data(struct udf_desc *desc, struct udf_data *data) { struct udf_data *ndata = desc->data; desc->length += data->length; while (ndata->next != NULL) ndata = ndata->next; ndata->next = data; data->prev = ndata; } /** * @brief allocate a new udf_data item and initialize it with either * allocated zeros or the supplied payload * @param buffer the supplied payload, if NULL allocate memory for the payload * @param length the length of the udf_data item payload in bytes * @return the in-memory address of the new udf_data item */ struct udf_data *alloc_data(void *buffer, int length) { struct udf_data *data = calloc(1, sizeof(struct udf_data)); if (buffer) data->buffer = buffer; else if (length) data->buffer = calloc(1, length); data->length = length; return data; } udftools-2.0/libudffs/crc.c0000644000175000017500000001236413221466537012663 00000000000000/* * crc.c * * PURPOSE * Routines to generate, calculate, and test a 16-bit CRC. * * DESCRIPTION * The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories * and Ned W. Rhodes of Software Systems Group. It has been published in * "Design and Validation of Computer Protocols", Prentice Hall, * Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4. * * Copyright is held by AT&T. * * AT&T gives permission for the free use of the CRC source code. * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. */ /** * @file * libudffs CRC functions */ #include "ecma_167.h" static uint16_t crc_table[256] = { 0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U, 0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU, 0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U, 0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU, 0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U, 0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU, 0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U, 0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU, 0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U, 0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU, 0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U, 0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU, 0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U, 0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U, 0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U, 0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U, 0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU, 0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U, 0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU, 0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U, 0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU, 0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U, 0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU, 0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U, 0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU, 0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U, 0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU, 0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U, 0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U, 0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U, 0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U, 0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U }; /* * udf_crc * * PURPOSE * Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial. * * DESCRIPTION * The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory. * The polynomial used is: x^16 + x^12 + x^15 + 1 * * PRE-CONDITIONS * data Pointer to the data block. * size Size of the data block. * * POST-CONDITIONS * CRC of the data block. * * HISTORY * July 21, 1997 - Andrew E. Mileski * Adapted from OSTA-UDF(tm) 1.50 standard. */ extern uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc) { while (size--) crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8); return crc; } /****************************************************************************/ #if defined(TEST) /* * PURPOSE * Test udf_crc() * * HISTORY * July 21, 1997 - Andrew E. Mileski * Adapted from OSTA-UDF(tm) 1.50 standard. */ unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U }; int main(void) { unsigned short x; x = udf_crc16(bytes, sizeof bytes); printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U); return 0; } #endif /* defined(TEST) */ /****************************************************************************/ #if defined(GENERATE) /* * PURPOSE * Generate a table for fast 16-bit CRC calculations (any polynomial). * * DESCRIPTION * The ITU-T V.41 polynomial is 010041. * * HISTORY * July 21, 1997 - Andrew E. Mileski * Adapted from OSTA-UDF(tm) 1.50 standard. */ #include int main(int argc, char **argv) { unsigned long crc, poly; int n, i; /* Get the polynomial */ sscanf(argv[1], "%lo", &poly); if (poly & 0xffff0000U){ fprintf(stderr, "polynomial is too large\en"); exit(1); } printf("/* CRC 0%o */\n", poly); /* Create a table */ printf("static unsigned short crc_table[256] = {\n"); for (n = 0; n < 256; n++){ if (n % 8 == 0) printf("\t"); crc = n << 8; for (i = 0; i < 8; i++){ if(crc & 0x8000U) crc = (crc << 1) ^ poly; else crc <<= 1; crc &= 0xFFFFU; } if (n == 255) printf("0x%04xU ", crc); else printf("0x%04xU, ", crc); if(n % 8 == 7) printf("\n"); } printf("};\n"); return 0; } #endif /* defined(GENERATE) */ udftools-2.0/libudffs/Makefile.in0000644000175000017500000004247713221466653014024 00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = libudffs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libudffs_la_DEPENDENCIES = @LTLIBOBJS@ am_libudffs_la_OBJECTS = crc.lo extent.lo misc.lo unicode.lo libudffs_la_OBJECTS = $(am_libudffs_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libudffs_la_SOURCES) DIST_SOURCES = $(libudffs_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libudffs.la libudffs_la_SOURCES = crc.c extent.c misc.c unicode.c ../include/libudffs.h ../include/ecma_167.h ../include/osta_udf.h ../include/udf_endian.h ../include/bswap.h libudffs_la_LIBADD = @LTLIBOBJS@ AM_CPPFLAGS = -I$(top_srcdir)/include all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libudffs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libudffs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libudffs.la: $(libudffs_la_OBJECTS) $(libudffs_la_DEPENDENCIES) $(EXTRA_libudffs_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libudffs_la_OBJECTS) $(libudffs_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unicode.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: udftools-2.0/libudffs/Makefile.am0000644000175000017500000000042013221466537013772 00000000000000noinst_LTLIBRARIES = libudffs.la libudffs_la_SOURCES = crc.c extent.c misc.c unicode.c ../include/libudffs.h ../include/ecma_167.h ../include/osta_udf.h ../include/udf_endian.h ../include/bswap.h libudffs_la_LIBADD = @LTLIBOBJS@ AM_CPPFLAGS = -I$(top_srcdir)/include udftools-2.0/Doxyfile0000644000175000017500000030360313221466537011657 00000000000000# Doxyfile 1.8.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "udftools" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /