From c292f6440603e28462ce7670bd89584d601d2b71 Mon Sep 17 00:00:00 2001 From: Fedor Date: Wed, 18 Nov 2009 00:43:09 -0500 Subject: [PATCH] ntfs-3g ver. 2009.11.14 --- release/src/router/ntfs-3g/AUTHORS | 1 + release/src/router/ntfs-3g/CREDITS | 5 +- release/src/router/ntfs-3g/INSTALL | 53 +- release/src/router/ntfs-3g/Makefile.in | 163 +- release/src/router/ntfs-3g/README | 41 +- release/src/router/ntfs-3g/aclocal.m4 | 1006 ++- release/src/router/ntfs-3g/config.guess | 147 +- release/src/router/ntfs-3g/config.h.in | 6 + release/src/router/ntfs-3g/config.sub | 120 +- release/src/router/ntfs-3g/configure | 2384 ++++--- release/src/router/ntfs-3g/configure.ac | 48 +- release/src/router/ntfs-3g/depcomp | 93 +- release/src/router/ntfs-3g/include/Makefile.in | 142 +- .../router/ntfs-3g/include/fuse-lite/Makefile.am | 2 +- .../router/ntfs-3g/include/fuse-lite/Makefile.in | 112 +- .../src/router/ntfs-3g/include/fuse-lite/fuse.h | 5 + .../router/ntfs-3g/include/fuse-lite/fuse_common.h | 21 + .../router/ntfs-3g/include/fuse-lite/fuse_kernel.h | 44 +- .../ntfs-3g/include/fuse-lite/fuse_lowlevel.h | 20 + .../src/router/ntfs-3g/include/ntfs-3g/Makefile.am | 3 + .../src/router/ntfs-3g/include/ntfs-3g/Makefile.in | 134 +- release/src/router/ntfs-3g/include/ntfs-3g/acls.h | 201 + .../src/router/ntfs-3g/include/ntfs-3g/attrib.h | 13 +- .../src/router/ntfs-3g/include/ntfs-3g/compress.h | 6 + release/src/router/ntfs-3g/include/ntfs-3g/dir.h | 21 +- .../ntfs-3g/include/ntfs-3g/{compress.h => efs.h} | 22 +- release/src/router/ntfs-3g/include/ntfs-3g/index.h | 38 +- release/src/router/ntfs-3g/include/ntfs-3g/inode.h | 13 + release/src/router/ntfs-3g/include/ntfs-3g/misc.h | 66 + .../src/router/ntfs-3g/include/ntfs-3g/reparse.h | 39 + .../src/router/ntfs-3g/include/ntfs-3g/runlist.h | 8 +- .../src/router/ntfs-3g/include/ntfs-3g/security.h | 295 +- .../src/router/ntfs-3g/include/ntfs-3g/unistr.h | 47 + .../src/router/ntfs-3g/include/ntfs-3g/volume.h | 27 + release/src/router/ntfs-3g/install-sh | 514 +- .../src/router/ntfs-3g/libfuse-lite/Makefile.in | 206 +- release/src/router/ntfs-3g/libfuse-lite/fuse.c | 3 + .../router/ntfs-3g/libfuse-lite/fuse_lowlevel.c | 200 +- release/src/router/ntfs-3g/libntfs-3g/Makefile.am | 3 + release/src/router/ntfs-3g/libntfs-3g/Makefile.in | 382 +- release/src/router/ntfs-3g/libntfs-3g/acls.c | 4283 ++++++++++++ release/src/router/ntfs-3g/libntfs-3g/attrib.c | 823 ++- release/src/router/ntfs-3g/libntfs-3g/collate.c | 123 +- release/src/router/ntfs-3g/libntfs-3g/compat.c | 4 +- release/src/router/ntfs-3g/libntfs-3g/compress.c | 902 ++- release/src/router/ntfs-3g/libntfs-3g/dir.c | 722 +- release/src/router/ntfs-3g/libntfs-3g/efs.c | 339 + release/src/router/ntfs-3g/libntfs-3g/index.c | 187 +- release/src/router/ntfs-3g/libntfs-3g/inode.c | 223 +- release/src/router/ntfs-3g/libntfs-3g/lcnalloc.c | 135 +- release/src/router/ntfs-3g/libntfs-3g/mft.c | 38 +- release/src/router/ntfs-3g/libntfs-3g/misc.c | 328 + release/src/router/ntfs-3g/libntfs-3g/reparse.c | 1296 ++++ release/src/router/ntfs-3g/libntfs-3g/runlist.c | 76 +- release/src/router/ntfs-3g/libntfs-3g/security.c | 4762 ++++++++++++- release/src/router/ntfs-3g/libntfs-3g/unistr.c | 279 +- release/src/router/ntfs-3g/libntfs-3g/unix_io.c | 38 +- release/src/router/ntfs-3g/libntfs-3g/volume.c | 32 +- release/src/router/ntfs-3g/ltmain.sh | 213 +- release/src/router/ntfs-3g/missing | 61 +- release/src/router/ntfs-3g/src/Makefile.am | 16 +- release/src/router/ntfs-3g/src/Makefile.in | 265 +- release/src/router/ntfs-3g/src/ntfs-3g.8.in | 184 +- release/src/router/ntfs-3g/src/ntfs-3g.c | 1977 +++++- release/src/router/ntfs-3g/src/ntfs-3g.probe.8.in | 15 +- .../src/router/ntfs-3g/src/ntfs-3g.secaudit.8.in | 171 + .../src/router/ntfs-3g/src/ntfs-3g.usermap.8.in | 96 + release/src/router/ntfs-3g/src/secaudit.c | 7113 ++++++++++++++++++++ release/src/router/ntfs-3g/src/secaudit.h | 731 ++ release/src/router/ntfs-3g/src/usermap.c | 1333 ++++ 70 files changed, 30389 insertions(+), 3030 deletions(-) create mode 100644 release/src/router/ntfs-3g/include/ntfs-3g/acls.h copy release/src/router/ntfs-3g/include/ntfs-3g/{compress.h => efs.h} (69%) create mode 100644 release/src/router/ntfs-3g/include/ntfs-3g/reparse.h create mode 100644 release/src/router/ntfs-3g/libntfs-3g/acls.c create mode 100644 release/src/router/ntfs-3g/libntfs-3g/efs.c create mode 100644 release/src/router/ntfs-3g/libntfs-3g/reparse.c create mode 100644 release/src/router/ntfs-3g/src/ntfs-3g.secaudit.8.in create mode 100644 release/src/router/ntfs-3g/src/ntfs-3g.usermap.8.in create mode 100644 release/src/router/ntfs-3g/src/secaudit.c create mode 100644 release/src/router/ntfs-3g/src/secaudit.h create mode 100644 release/src/router/ntfs-3g/src/usermap.c diff --git a/release/src/router/ntfs-3g/AUTHORS b/release/src/router/ntfs-3g/AUTHORS index a56a1ef4f7..f9299b4171 100644 --- a/release/src/router/ntfs-3g/AUTHORS +++ b/release/src/router/ntfs-3g/AUTHORS @@ -3,6 +3,7 @@ Present authors of ntfs-3g in alphabetical order: Jean-Pierre Andre Alon Bar-Lev +Martin Bene Dominique L Bouix Csaba Henk Bernhard Kaindl diff --git a/release/src/router/ntfs-3g/CREDITS b/release/src/router/ntfs-3g/CREDITS index 12fc207f89..844a147e36 100644 --- a/release/src/router/ntfs-3g/CREDITS +++ b/release/src/router/ntfs-3g/CREDITS @@ -38,7 +38,4 @@ Ismail Donmez Laszlo Dvornik Pallaghy Ajtony Szabolcs Szakacsits -Jean-Pierre Andre -Alejandro Pulver -Erik Larsson -Alon Bar-Lev + diff --git a/release/src/router/ntfs-3g/INSTALL b/release/src/router/ntfs-3g/INSTALL index 23e5f25d0e..d3c5b40a94 100644 --- a/release/src/router/ntfs-3g/INSTALL +++ b/release/src/router/ntfs-3g/INSTALL @@ -1,8 +1,8 @@ Installation Instructions ************************* -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it. Basic Installation ================== -These are generic installation instructions. +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -23,9 +26,9 @@ debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is +the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale -cache files.) +cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail @@ -35,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + `./configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. 2. Type `make' to compile the package. @@ -67,6 +67,9 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. + 6. Often, you can also type `make uninstall' to remove the installed + files again. + Compilers and Options ===================== @@ -78,7 +81,7 @@ details on some of the pertinent environment variables. by setting variables in the command line or in the environment. Here is an example: - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. @@ -87,17 +90,15 @@ Compiling For Multiple Architectures You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. Installation Names ================== @@ -190,12 +191,12 @@ them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: +overridden in the site shell script). - /bin/bash ./configure CONFIG_SHELL=/bin/bash +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== diff --git a/release/src/router/ntfs-3g/Makefile.in b/release/src/router/ntfs-3g/Makefile.in index b29e854b7d..9793774c53 100644 --- a/release/src/router/ntfs-3g/Makefile.in +++ b/release/src/router/ntfs-3g/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -14,15 +14,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -37,18 +33,18 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ +subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure AUTHORS COPYING COPYING.LIB ChangeLog \ INSTALL NEWS compile config.guess config.sub depcomp \ install-sh ltmain.sh missing -subdir = . 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) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno configure.status.lineno + configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = @@ -56,10 +52,11 @@ SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ - install-exec-recursive install-info-recursive \ - install-recursive installcheck-recursive installdirs-recursive \ - pdf-recursive ps-recursive uninstall-info-recursive \ - uninstall-recursive + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -69,6 +66,8 @@ am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(docdir)" docDATA_INSTALL = $(INSTALL_DATA) DATA = $(doc_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) @@ -84,8 +83,6 @@ GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -104,26 +101,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -137,13 +128,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -155,25 +143,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -185,6 +167,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -217,12 +200,15 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = gnu ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = AUTHORS CREDITS COPYING NEWS autogen.sh @@ -289,7 +275,7 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ - $(MAKE) stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @@ -311,10 +297,9 @@ clean-libtool: distclean-libtool: -rm -f libtool -uninstall-info-am: install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) - test -z "$(docdir)" || $(mkdir_p) "$(DESTDIR)$(docdir)" + test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" @list='$(doc_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ @@ -361,8 +346,7 @@ $(RECURSIVE_TARGETS): $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" -mostlyclean-recursive clean-recursive distclean-recursive \ -maintainer-clean-recursive: +$(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ @@ -406,8 +390,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -432,8 +416,8 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -443,13 +427,12 @@ ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -464,24 +447,22 @@ distclean-tags: distdir: $(DISTFILES) $(am__remove_distdir) - mkdir $(distdir) - $(mkdir_p) $(distdir)/libntfs-3g $(distdir)/src - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + test -d $(distdir) || mkdir $(distdir) + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -495,7 +476,7 @@ distdir: $(DISTFILES) list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ - || $(mkdir_p) "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ @@ -503,6 +484,8 @@ distdir: $(DISTFILES) $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ @@ -513,7 +496,7 @@ distdir: $(DISTFILES) -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz @@ -523,6 +506,10 @@ dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) @@ -549,6 +536,8 @@ distcheck: dist GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ @@ -588,7 +577,7 @@ distcheck: dist $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ @@ -613,7 +602,7 @@ all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docdir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive @@ -662,12 +651,20 @@ info-am: install-data-am: install-docDATA +install-dvi: install-dvi-recursive + install-exec-am: +install-html: install-html-recursive + install-info: install-info-recursive install-man: +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + installcheck-am: maintainer-clean: maintainer-clean-recursive @@ -688,25 +685,27 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-docDATA uninstall-info-am +uninstall-am: uninstall-docDATA -uninstall-info: uninstall-info-recursive +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip -.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ - check-am clean clean-generic clean-libtool clean-recursive \ - ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ - dist-hook dist-shar dist-tarZ dist-zip distcheck distclean \ - distclean-generic distclean-hdr distclean-libtool \ - distclean-recursive distclean-tags distcleancheck distdir \ +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ + dist-gzip dist-hook dist-lzma dist-shar dist-tarZ dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ - install-docDATA install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ + install-docDATA 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 installdirs-am maintainer-clean \ - maintainer-clean-generic maintainer-clean-recursive \ - mostlyclean mostlyclean-generic mostlyclean-libtool \ - mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ - uninstall uninstall-am uninstall-docDATA uninstall-info-am + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-docDATA dist-hook: diff --git a/release/src/router/ntfs-3g/README b/release/src/router/ntfs-3g/README index ecc1943b28..12328b3ce2 100644 --- a/release/src/router/ntfs-3g/README +++ b/release/src/router/ntfs-3g/README @@ -3,43 +3,48 @@ INTRODUCTION ============ The NTFS-3G driver is an open source, freely available read/write NTFS driver -for Linux, FreeBSD, Mac OS X, NetBSD, Solaris and Haiku. It provides safe and -fast handling of the Windows XP, Windows Server 2003, Windows 2000, Windows -Vista, and Windows Server 2008 file systems. +for Linux, FreeBSD, Mac OS X, NetBSD, OpenSolaris, QNX and Haiku. It provides +safe and fast handling of the Windows XP, Windows Server 2003, Windows 2000, +Windows Vista, Windows Server 2008 and Windows 7 file systems. -The purpose of the project is to develop, continuously quality test and -support a trustable, featureful and high performance solution for hardware -platforms and operating systems whose users need to reliably interoperate -with NTFS. Besides this practical goal, the project also aims to explore -the limits of the hybrid, kernel/user space filesystem driver approach, -performance, reliability and feature richness per invested effort wise. +The purpose of the project is to develop, quality assurance and support a +trustable, featureful and high performance solution for hardware platforms +and operating systems whose users need to reliably interoperate with NTFS. +Besides this practical goal, the project also aims to explore the limits +of the hybrid, kernel/user space filesystem driver approach, performance, +reliability and feature richness per invested effort wise. -The driver is in STABLE status. The test methods, the test suites used -can be found at +Besides the common file system features, NTFS-3G has support for file +ownership and permissions, POSIX ACLs, junction points, extended attributes +and creating compressed files. Parameter files in the directory .NTFS-3G may +be required to enable them, please get the instructions from - http://ntfs-3g.org/quality.html + http://www.tuxera.com/community/ntfs-3g-advanced/ News, support answers, problem submission instructions, support and discussion forums, performance numbers and other information are available on the project web site at - http://ntfs-3g.org + http://www.tuxera.com/community/ QUICK INSTALLATION ================== Linux: Make sure you have the basic development tools and the kernel includes -the FUSE kernel module. Then type: +the FUSE kernel module. Then unpack the source tarball and type: ./configure make make install # or 'sudo make install' if you aren't root. -Please note that NTFS-3G doesn't require the FUSE user space package anymore. +Please note that NTFS-3G doesn't require the FUSE user space package. -Non-Linux: Please see the NTFS-3G web page for OS specific installation and -source packages. +Non-Linux: Please see + + http://www.tuxera.com/community/ntfs-3g-download/ + +for OS specific installation and source packages. USAGE @@ -57,7 +62,7 @@ or Please see the ntfs-3g manual page for more options and examples. You can also make NTFS to be mounted during boot by putting the below -line at the __END__ of the /etc/fstab file: +line at the END(!) of the /etc/fstab file: /dev/sda1 /mnt/windows ntfs-3g defaults 0 0 diff --git a/release/src/router/ntfs-3g/aclocal.m4 b/release/src/router/ntfs-3g/aclocal.m4 index a2dcb64bec..1379c104c4 100644 --- a/release/src/router/ntfs-3g/aclocal.m4 +++ b/release/src/router/ntfs-3g/aclocal.m4 @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.9.6 -*- Autoconf -*- +# generated automatically by aclocal 1.10.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This file 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. @@ -11,9 +11,17 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(AC_AUTOCONF_VERSION, [2.61],, +[m4_warning([this file was generated for autoconf 2.61. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# serial 48 AC_PROG_LIBTOOL +# serial 52 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) @@ -101,7 +109,6 @@ AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl - AC_LIBTOOL_SYS_MAX_CMD_LEN AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE AC_LIBTOOL_OBJDIR @@ -176,7 +183,7 @@ test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= @@ -203,6 +210,8 @@ file_magic*) ;; esac +_LT_REQUIRED_DARWIN_CHECKS + AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) @@ -263,8 +272,9 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Check for compiler boilerplate output or warnings with # the simple compiler test code. AC_DEFUN([_LT_COMPILER_BOILERPLATE], -[ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* @@ -276,13 +286,85 @@ $rm conftest* # Check for linker boilerplate output or warnings with # the simple link test code. AC_DEFUN([_LT_LINKER_BOILERPLATE], -[ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +[AC_REQUIRE([LT_AC_PROG_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* ])# _LT_LINKER_BOILERPLATE +# _LT_REQUIRED_DARWIN_CHECKS +# -------------------------- +# Check for some things on darwin +AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + echo "int foo(void){return 1;}" > conftest.c + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib ${wl}-single_module conftest.c + if test -f libconftest.dylib; then + lt_cv_apple_cc_single_mod=yes + rm -rf libconftest.dylib* + fi + rm conftest.c + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + case $host_os in + rhapsody* | darwin1.[[0123]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil="~$DSYMUTIL \$lib || :" + else + _lt_dsymutil= + fi + ;; + esac +]) # _LT_AC_SYS_LIBPATH_AIX # ---------------------- @@ -293,12 +375,20 @@ $rm conftest* # If we don't find anything, use the default library path according # to the aix ld manual. AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], -[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi],[]) +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_AC_SYS_LIBPATH_AIX @@ -529,13 +619,17 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; @@ -552,6 +646,9 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) ;; *64-bit*) case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; @@ -592,7 +689,11 @@ sparc*-*solaris*) *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) LD="${LD-ld} -64" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; esac ;; esac @@ -623,7 +724,7 @@ AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], AC_CACHE_CHECK([$1], [$2], [$2=no ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -664,11 +765,12 @@ fi # ------------------------------------------------------------ # Check whether the given compiler option works AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], -[AC_CACHE_CHECK([$1], [$2], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" - printf "$lt_simple_link_test_code" > conftest.$ac_ext + echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings @@ -684,7 +786,7 @@ AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], $2=yes fi fi - $rm conftest* + $rm -r conftest* LDFLAGS="$save_LDFLAGS" ]) @@ -782,24 +884,27 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl fi ;; *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi ;; esac ]) @@ -952,7 +1057,7 @@ else AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], @@ -960,7 +1065,7 @@ else [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) @@ -1026,7 +1131,8 @@ fi # --------------------------------- # Check to see if options -c and -o are simultaneously supported by compiler AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], -[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no @@ -1034,7 +1140,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], mkdir conftest cd conftest mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or @@ -1174,6 +1280,7 @@ else darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" + old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) @@ -1191,7 +1298,8 @@ fi # ----------------------------- # PORTME Fill in your ld.so characteristics AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], -[AC_MSG_CHECKING([dynamic linker characteristics]) +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= @@ -1205,20 +1313,58 @@ shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" +m4_if($1,[],[ if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`echo $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi +fi]) need_lib_prefix=unknown hardcode_into_libs=no @@ -1236,7 +1382,7 @@ aix3*) soname_spec='${libname}${release}${shared_ext}$major' ;; -aix4* | aix5*) +aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no @@ -1375,12 +1521,8 @@ darwin* | rhapsody*) shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi + m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; @@ -1397,18 +1539,6 @@ freebsd1*) dynamic_linker=no ;; -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -1446,7 +1576,7 @@ freebsd* | dragonfly*) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; - freebsd*) # from 4.6 on + *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; @@ -1509,7 +1639,7 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; -interix3*) +interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no @@ -1564,7 +1694,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -1578,27 +1708,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -1610,18 +1723,6 @@ linux*) dynamic_linker='GNU/Linux ld.so' ;; -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -1703,6 +1804,10 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; +rdos*) + dynamic_linker=no + ;; + solaris*) version_type=linux need_lib_prefix=no @@ -1798,6 +1903,13 @@ esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no +AC_CACHE_VAL([lt_cv_sys_lib_search_path_spec], +[lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec"]) +sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +AC_CACHE_VAL([lt_cv_sys_lib_dlsearch_path_spec], +[lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec"]) +sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" @@ -1808,7 +1920,8 @@ fi # _LT_AC_TAGCONFIG # ---------------- AC_DEFUN([_LT_AC_TAGCONFIG], -[AC_ARG_WITH([tags], +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_ARG_WITH([tags], [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], [include additional configurations @<:@automatic@:>@])], [tagnames="$withval"]) @@ -2069,7 +2182,7 @@ m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], # AC_PATH_TOOL_PREFIX # ------------------- -# find a file program which can recognise shared library +# find a file program which can recognize shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_MSG_CHECKING([for $1]) @@ -2132,7 +2245,7 @@ fi # AC_PATH_MAGIC # ------------- -# find a file program which can recognise a shared library +# find a file program which can recognize a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then @@ -2279,7 +2392,7 @@ esac # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], -[AC_CACHE_CHECK([how to recognise dependent libraries], +[AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= @@ -2296,7 +2409,7 @@ lt_cv_deplibs_check_method='unknown' # whether `pass_all' will *always* work, you probably want this one. case $host_os in -aix4* | aix5*) +aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; @@ -2318,16 +2431,22 @@ cygwin*) mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump'. - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | kfreebsd*-gnu | dragonfly*) +freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) @@ -2365,7 +2484,7 @@ hpux10.20* | hpux11*) esac ;; -interix3*) +interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; @@ -2381,7 +2500,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; @@ -2415,6 +2534,10 @@ osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + solaris*) lt_cv_deplibs_check_method=pass_all ;; @@ -2467,7 +2590,7 @@ AC_DEFUN([AC_PROG_NM], lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do @@ -2683,10 +2806,10 @@ objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" +lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' +lt_simple_link_test_code='int main(){return(0);}' _LT_AC_SYS_COMPILER @@ -2722,7 +2845,7 @@ aix3*) fi ;; -aix4* | aix5*) +aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi @@ -2779,6 +2902,7 @@ _LT_AC_TAGVAR(postdep_objects, $1)= _LT_AC_TAGVAR(predeps, $1)= _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= +_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)= # Source file extension for C++ test sources. ac_ext=cpp @@ -2788,10 +2912,10 @@ objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" +lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER @@ -2888,7 +3012,7 @@ case $host_os in # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - aix4* | aix5*) + aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -2901,7 +3025,7 @@ case $host_os in # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) @@ -2937,7 +3061,7 @@ case $host_os in strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes + : else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported @@ -3047,59 +3171,31 @@ case $host_os in fi ;; darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - - if test "$GXX" = yes ; then - lt_int_apple_cc_single_mod=no + _LT_AC_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + if test "$GXX" = yes ; then output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes + _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -3133,7 +3229,7 @@ case $host_os in freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes @@ -3182,9 +3278,7 @@ case $host_os in _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in - hppa*64*|ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - ;; + hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; @@ -3252,7 +3346,7 @@ case $host_os in ;; esac ;; - interix3*) + interix[[3-9]]*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' @@ -3292,7 +3386,7 @@ case $host_os in _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -3344,7 +3438,7 @@ case $host_os in _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; - pgCC*) + pgCC* | pgcpp*) # Portland Group C++ compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' @@ -3372,6 +3466,29 @@ case $host_os in # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; esac ;; lynxos*) @@ -3410,16 +3527,20 @@ case $host_os in _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no fi - output_verbose_link_cmd='echo' ;; osf3*) case $cc_basename in @@ -3581,15 +3702,10 @@ case $host_os in case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. We must also pass each convience library through - # to the system linker between allextract/defaultextract. - # The C++ compiler will combine linker options so we - # cannot just pass the convience library names through - # without $wl. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes @@ -3636,6 +3752,12 @@ case $host_os in fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac fi ;; esac @@ -3751,7 +3873,8 @@ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. -AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP], +[AC_REQUIRE([LT_AC_PROG_SED])dnl dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each @@ -3876,10 +3999,15 @@ fi $rm -f confest.$objext +_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_AC_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_AC_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi + # PORTME: override above test on systems where it is broken ifelse([$1],[CXX], [case $host_os in -interix3*) +interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_AC_TAGVAR(predep_objects,$1)= @@ -3887,19 +4015,51 @@ interix3*) _LT_AC_TAGVAR(postdeps,$1)= ;; +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + # + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + solaris*) case $cc_basename in CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. - _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun' + if test "$solaris_use_stlport4" != yes; then + _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi ;; esac ;; esac ]) - case " $_LT_AC_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac @@ -3942,10 +4102,17 @@ objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code=" subroutine t\n return\n end\n" +lt_simple_compile_test_code="\ + subroutine t + return + end +" # Code to be used in simple link tests -lt_simple_link_test_code=" program t\n end\n" +lt_simple_link_test_code="\ + program t + end +" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER @@ -3977,7 +4144,7 @@ aix3*) postinstall_cmds='$RANLIB $lib' fi ;; -aix4* | aix5*) +aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi @@ -4024,10 +4191,10 @@ objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}\n" +lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n' +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER @@ -4042,7 +4209,6 @@ CC=${GCJ-"gcj"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) -_LT_AC_TAGVAR(LD, $1)="$LD" # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no @@ -4081,7 +4247,7 @@ objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" @@ -4155,6 +4321,7 @@ if test -f "$ltmain"; then _LT_AC_TAGVAR(predeps, $1) \ _LT_AC_TAGVAR(postdeps, $1) \ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_dirs, $1) \ _LT_AC_TAGVAR(archive_cmds, $1) \ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ _LT_AC_TAGVAR(postinstall_cmds, $1) \ @@ -4170,6 +4337,7 @@ if test -f "$ltmain"; then _LT_AC_TAGVAR(module_cmds, $1) \ _LT_AC_TAGVAR(module_expsym_cmds, $1) \ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(fix_srcfile_path, $1) \ _LT_AC_TAGVAR(exclude_expsyms, $1) \ _LT_AC_TAGVAR(include_expsyms, $1); do @@ -4216,7 +4384,7 @@ ifelse([$1], [], # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: @@ -4306,9 +4474,6 @@ CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) # Is the compiler the GNU C compiler? with_gcc=$_LT_AC_TAGVAR(GCC, $1) -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -4442,11 +4607,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_[]_LT_AC_TAGVAR(predep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_[]_LT_AC_TAGVAR(postdep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) # Dependencies to place before the objects being linked to create a # shared library. @@ -4456,9 +4621,13 @@ predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) # shared library. postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_dirs, $1) + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -4538,13 +4707,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) @@ -4627,6 +4796,7 @@ fi # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([LT_AC_PROG_SED]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. @@ -4663,7 +4833,7 @@ hpux*) # Its linker distinguishes data from code symbols lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; -linux*) +linux* | k*bsd*-gnu) if test "$host_cpu" = ia64; then symcode='[[ABCDGIRSTW]]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" @@ -4804,7 +4974,7 @@ EOF echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi - rm -f conftest* conftst* + rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then @@ -4853,13 +5023,16 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | os2* | pw32*) + mingw* | cygwin* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -4870,7 +5043,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; - interix3*) + interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -4896,7 +5069,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) esac else case $host_os in - aix4* | aix5*) + aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor @@ -4936,7 +5109,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; esac ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) @@ -4979,7 +5152,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; esac ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4992,7 +5165,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; - pgCC*) + pgCC* | pgcpp*) # Portland Group C++ compiler. _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' @@ -5006,6 +5179,14 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac ;; esac ;; @@ -5126,14 +5307,17 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) @@ -5142,7 +5326,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; - interix3*) + interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -5200,10 +5384,11 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) esac ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + m4_if([$1], [GCJ], [], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) @@ -5233,7 +5418,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' @@ -5252,6 +5437,22 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) # All Alpha code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + esac + ;; esac ;; @@ -5261,6 +5462,10 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; + rdos*) + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + solaris*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' @@ -5320,7 +5525,7 @@ AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) # if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + _LT_AC_TAGVAR(lt_cv_prog_compiler_pic_works, $1), [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; @@ -5344,7 +5549,7 @@ esac # wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + _LT_AC_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) @@ -5355,11 +5560,12 @@ AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], # ------------------------------------ # See if the linker supports building shared libraries. AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], -[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +[AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in - aix4* | aix5*) + aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then @@ -5372,12 +5578,13 @@ ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac + _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ],[ runpath_var= _LT_AC_TAGVAR(allow_undefined_flag, $1)= @@ -5408,12 +5615,14 @@ ifelse([$1],[CXX],[ # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. - _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. _LT_CC_BASENAME([$compiler]) @@ -5463,7 +5672,7 @@ ifelse([$1],[CXX],[ # See if GNU ld supports shared libraries. case $host_os in - aix3* | aix4* | aix5*) + aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(ld_shlibs, $1)=no @@ -5511,7 +5720,7 @@ EOF _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -5529,7 +5738,7 @@ EOF fi ;; - interix3*) + interix[[3-9]]*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' @@ -5544,7 +5753,7 @@ EOF _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - linux*) + gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in @@ -5562,13 +5771,22 @@ EOF ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else _LT_AC_TAGVAR(ld_shlibs, $1)=no @@ -5608,7 +5826,7 @@ EOF sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 @@ -5673,7 +5891,7 @@ _LT_EOF fi ;; - aix4* | aix5*) + aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -5693,7 +5911,7 @@ _LT_EOF # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -5727,7 +5945,7 @@ _LT_EOF strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - _LT_AC_TAGVAR(hardcode_direct, $1)=yes + : else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported @@ -5820,7 +6038,7 @@ _LT_EOF # The linker will automatically build a .lib file if we build a DLL. _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. - _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; @@ -5853,19 +6071,18 @@ _LT_EOF _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -5905,7 +6122,7 @@ _LT_EOF ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes @@ -6027,24 +6244,28 @@ _LT_EOF ;; openbsd*) - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + if test -f /usr/libexec/ld.so; then + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac + _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; @@ -6103,17 +6324,16 @@ _LT_EOF case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; - *) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; + if test "$GCC" = yes; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; @@ -6170,7 +6390,7 @@ _LT_EOF fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -6245,7 +6465,7 @@ x|xyes) # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest @@ -6348,6 +6568,30 @@ AC_DEFUN([LT_AC_PROG_RC], [AC_CHECK_TOOL(RC, windres, no) ]) + +# Cheap backport of AS_EXECUTABLE_P and required macros +# from Autoconf 2.59; we should not use $as_executable_p directly. + +# _AS_TEST_PREPARE +# ---------------- +m4_ifndef([_AS_TEST_PREPARE], +[m4_defun([_AS_TEST_PREPARE], +[if test -x / >/dev/null 2>&1; then + as_executable_p='test -x' +else + as_executable_p='test -f' +fi +])])# _AS_TEST_PREPARE + +# AS_EXECUTABLE_P +# --------------- +# Check whether a file is executable. +m4_ifndef([AS_EXECUTABLE_P], +[m4_defun([AS_EXECUTABLE_P], +[AS_REQUIRE([_AS_TEST_PREPARE])dnl +$as_executable_p $1[]dnl +])])# AS_EXECUTABLE_P + # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # @@ -6368,12 +6612,13 @@ do test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done +IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris @@ -6406,6 +6651,7 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do done ]) SED=$lt_cv_path_SED +AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ]) @@ -6477,16 +6723,14 @@ fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], -[if test -n "$PKG_CONFIG"; then - if test -n "$$1"; then - pkg_cv_[]$1="$$1" - else - PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], - [pkg_failed=yes]) - fi -else - pkg_failed=untried +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + else + pkg_failed=untried fi[]dnl ])# _PKG_CONFIG @@ -6530,9 +6774,9 @@ See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` else - $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD @@ -6557,7 +6801,7 @@ path to pkg-config. _PKG_TEXT -To get pkg-config, see .])], +To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS @@ -6567,7 +6811,7 @@ else fi[]dnl ])# PKG_CHECK_MODULES -# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -6577,14 +6821,31 @@ fi[]dnl # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.10' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.10.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.9.6])]) +[AM_AUTOMAKE_VERSION([1.10.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- @@ -6641,14 +6902,14 @@ am_aux_dir=`cd $ac_aux_dir && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file 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. -# serial 7 +# serial 8 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- @@ -6657,8 +6918,10 @@ AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE]) -AC_SUBST([$1_FALSE]) +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl if $2; then $1_TRUE= $1_FALSE='#' @@ -6672,15 +6935,14 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file 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. -# serial 8 +# serial 9 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, @@ -6708,6 +6970,7 @@ AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) @@ -6773,6 +7036,7 @@ AC_CACHE_CHECK([dependency style of $depcc], depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then @@ -6825,7 +7089,8 @@ if test "x$enable_dependency_tracking" != xno; then AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- @@ -6850,8 +7115,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue @@ -6898,14 +7164,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008 Free Software Foundation, Inc. # # This file 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. -# serial 12 +# serial 13 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. @@ -6922,16 +7188,20 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.58])dnl +[AC_PREREQ([2.60])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi fi # test whether we have cygpath @@ -6951,6 +7221,9 @@ m4_ifval([$2], AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl @@ -6986,6 +7259,10 @@ AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) ]) @@ -6999,16 +7276,17 @@ AC_PROVIDE_IFELSE([AC_PROG_CXX], # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. +_am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $1 | $1:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # @@ -7021,7 +7299,7 @@ echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"$am_aux_dir/install-sh"} +install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. @@ -7126,13 +7404,14 @@ AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) -# Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. # # This file 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. -# serial 3 +# serial 5 # AM_PROG_CC_C_O # -------------- @@ -7140,6 +7419,7 @@ rm -f confinc confmf AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC @@ -7152,18 +7432,22 @@ if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file 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. -# serial 4 +# serial 5 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ @@ -7179,6 +7463,7 @@ AC_SUBST($1)]) # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then @@ -7189,7 +7474,7 @@ else fi ]) -# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -7197,60 +7482,23 @@ fi # AM_PROG_MKDIR_P # --------------- -# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. -# -# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories -# created by `make install' are always world readable, even if the -# installer happens to have an overly restrictive umask (e.g. 077). -# This was a mistake. There are at least two reasons why we must not -# use `-m 0755': -# - it causes special bits like SGID to be ignored, -# - it may be too restrictive (some setups expect 775 directories). -# -# Do not use -m 0755 and let people choose whatever they expect by -# setting umask. -# -# We cannot accept any implementation of `mkdir' that recognizes `-p'. -# Some implementations (such as Solaris 8's) are not thread-safe: if a -# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' -# concurrently, both version can detect that a/ is missing, but only -# one can create it and the other will error out. Consequently we -# restrict ourselves to GNU make (using the --version option ensures -# this.) +# Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], -[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi -AC_SUBST([mkdir_p])]) +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) # Helper functions for option handling. -*- Autoconf -*- @@ -7362,9 +7610,21 @@ dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) +# Copyright (C) 2006 Free Software Foundation, Inc. +# +# This file 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. diff --git a/release/src/router/ntfs-3g/config.guess b/release/src/router/ntfs-3g/config.guess index e3ef63f6cb..e6b5d5b86f 100755 --- a/release/src/router/ntfs-3g/config.guess +++ b/release/src/router/ntfs-3g/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. -timestamp='2005-12-13' +timestamp='2008-01-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -55,8 +56,8 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -106,7 +107,7 @@ set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; @@ -138,6 +139,16 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "${UNAME_MACHINE}" in + i?86) + test -z "$VENDOR" && VENDOR=pc + ;; + *) + test -z "$VENDOR" && VENDOR=unknown + ;; +esac +test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse + # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in @@ -160,6 +171,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched @@ -206,8 +218,11 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; macppc:MirBSD:*:*) - echo powerppc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} @@ -325,7 +340,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; - i86pc:SunOS:5.*:*) + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) @@ -527,7 +542,7 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -764,12 +779,19 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; - i*:MINGW*:*) + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) @@ -779,9 +801,18 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[345]*) - echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' - exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; @@ -815,7 +846,17 @@ EOF echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + else + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu @@ -824,16 +865,16 @@ EOF echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) - echo frv-unknown-linux-gnu + echo frv-${VENDOR}-linux-gnu exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build @@ -851,8 +892,12 @@ EOF #endif #endif EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build @@ -870,17 +915,21 @@ EOF #endif #endif EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; } ;; or32:Linux:*:*) - echo or32-unknown-linux-gnu + echo or32-${VENDOR}-linux-gnu exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo powerpc-${VENDOR}-linux-gnu exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + echo powerpc64-${VENDOR}-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -894,36 +943,39 @@ EOF esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-${VENDOR}-linux-gnu ;; + PA8*) echo hppa2.0-${VENDOR}-linux-gnu ;; + *) echo hppa-${VENDOR}-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + echo hppa64-${VENDOR}-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo x86_64-${VENDOR}-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so @@ -938,18 +990,18 @@ EOF p'` case "$ld_supported_targets" in elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux-gnu" ;; a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" + echo "${UNAME_MACHINE}-${VENDOR}-linux-gnuaout" exit ;; coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" + echo "${UNAME_MACHINE}-${VENDOR}-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + echo "${UNAME_MACHINE}-${VENDOR}-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf @@ -967,7 +1019,7 @@ EOF LIBC=gnulibc1 # endif #else - #if defined(__INTEL_COMPILER) || defined(__PGI) + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout @@ -977,9 +1029,13 @@ EOF LIBC=dietlibc #endif EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^LIBC/{s: ::g;p;}'`" + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } @@ -1179,6 +1235,15 @@ EOF SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; diff --git a/release/src/router/ntfs-3g/config.h.in b/release/src/router/ntfs-3g/config.h.in index 559729b521..a47f7651bc 100644 --- a/release/src/router/ntfs-3g/config.h.in +++ b/release/src/router/ntfs-3g/config.h.in @@ -3,6 +3,9 @@ /* Define to 1 if debug should be enabled */ #undef ENABLE_DEBUG +/* Define to 1 if the nfconv patch should be enabled */ +#undef ENABLE_NFCONV + /* Define to 1 if using internal fuse */ #undef FUSE_INTERNAL @@ -288,6 +291,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* POSIX ACL support */ +#undef POSIXACLS + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/release/src/router/ntfs-3g/config.sub b/release/src/router/ntfs-3g/config.sub index c0ada46fa7..6759825a5b 100755 --- a/release/src/router/ntfs-3g/config.sub +++ b/release/src/router/ntfs-3g/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. -timestamp='2005-12-11' +timestamp='2008-01-16' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -71,8 +72,8 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -240,15 +241,16 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -268,26 +270,25 @@ case $basic_machine in | mn10200 | mn10300 \ | mt \ | msp430 \ + | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ - | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; - m32c) - basic_machine=$basic_machine-unknown - ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown @@ -317,18 +318,18 @@ case $basic_machine in | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ + | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* | m32rle-* \ + | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ @@ -350,28 +351,31 @@ case $basic_machine in | mmix-* \ | mt-* \ | msp430-* \ + | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-*) ;; - m32c-*) + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -443,6 +447,14 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; c90) basic_machine=c90-cray os=-unicos @@ -475,8 +487,8 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16c) - basic_machine=cr16c-unknown + cr16) + basic_machine=cr16-unknown os=-elf ;; crds | unos) @@ -668,6 +680,14 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -683,6 +703,10 @@ case $basic_machine in basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -809,6 +833,14 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -818,6 +850,12 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; @@ -904,6 +942,10 @@ case $basic_machine in sb1el) basic_machine=mipsisa64sb1el-unknown ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; sei) basic_machine=mips-sei os=-seiux @@ -915,6 +957,9 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh5el) + basic_machine=sh5le-unknown + ;; sh64) basic_machine=sh64-unknown ;; @@ -1004,6 +1049,10 @@ case $basic_machine in basic_machine=tic6x-unknown os=-coff ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; tx39) basic_machine=mipstx39-unknown ;; @@ -1120,7 +1169,7 @@ case $basic_machine in sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) @@ -1193,7 +1242,8 @@ case $os in | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ @@ -1208,7 +1258,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1360,7 +1410,10 @@ else # system, and we'll never get to this point. case $basic_machine in - spu-*) + score-*) + os=-elf + ;; + spu-*) os=-elf ;; *-acorn) @@ -1372,9 +1425,9 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff - ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 @@ -1400,6 +1453,9 @@ case $basic_machine in m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; diff --git a/release/src/router/ntfs-3g/configure b/release/src/router/ntfs-3g/configure index f5646968e8..8e2fe9d1d8 100755 --- a/release/src/router/ntfs-3g/configure +++ b/release/src/router/ntfs-3g/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for ntfs-3g 2009.4.4. +# Generated by GNU Autoconf 2.61 for ntfs-3g 2009.11.14. # # Report bugs to . # @@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='ntfs-3g' PACKAGE_TARNAME='ntfs-3g' -PACKAGE_VERSION='2009.4.4' -PACKAGE_STRING='ntfs-3g 2009.4.4' +PACKAGE_VERSION='2009.11.14' +PACKAGE_STRING='ntfs-3g 2009.11.14' PACKAGE_BUGREPORT='ntfs-3g-devel@lists.sf.net' ac_unique_file="src/ntfs-3g.c" @@ -822,6 +822,7 @@ target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA +am__isrc CYGPATH_W PACKAGE VERSION @@ -860,11 +861,14 @@ CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE LN_S +SED GREP EGREP ECHO AR RANLIB +DSYMUTIL +NMEDIT CPP CXX CXXFLAGS @@ -879,7 +883,6 @@ ac_ct_F77 LIBTOOL MV RM -SED LDCONFIG PKG_CONFIG FUSE_MODULE_CFLAGS @@ -1433,7 +1436,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ntfs-3g 2009.4.4 to adapt to many kinds of systems. +\`configure' configures ntfs-3g 2009.11.14 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1504,7 +1507,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ntfs-3g 2009.4.4:";; + short | recursive ) echo "Configuration of ntfs-3g 2009.11.14:";; esac cat <<\_ACEOF @@ -1522,8 +1525,12 @@ Optional Features: --disable-ldconfig do not update dynamic linker cache using ldconfig --disable-library do not install libntfs-3g but link it into ntfs-3g --disable-mtab disable and ignore usage of /etc/mtab + --enable-posix-acls enable POSIX ACL support --disable-device-default-io-ops install default IO ops + --disable-nfconv disable the 'nfconv' patch, which adds support for + Unicode normalization form conversion when built on + Mac OS X [default=enabled for Mac OS X] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=yes] @@ -1629,7 +1636,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ntfs-3g configure 2009.4.4 +ntfs-3g configure 2009.11.14 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1643,7 +1650,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ntfs-3g $as_me 2009.4.4, which was +It was created by ntfs-3g $as_me 2009.11.14, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -1997,7 +2004,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -LIBNTFS_3G_VERSION="54" +LIBNTFS_3G_VERSION="71" # Environment @@ -2160,7 +2167,8 @@ test -n "$target_alias" && program_prefix=${target_alias}- # Automake -am__api_version="1.9" +am__api_version='1.10' + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -2312,38 +2320,53 @@ else echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi -if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' +{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 +echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done +done +IFS=$as_save_IFS + +fi + + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" else - mkdir_p='$(install_sh) -d' + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + test -d ./--version && rmdir ./--version + MKDIR_P="$ac_install_sh -d" fi fi +{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5 +echo "${ECHO_T}$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac for ac_prog in gawk mawk nawk awk do @@ -2426,12 +2449,16 @@ else fi rmdir .tst 2>/dev/null -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } + fi fi # test whether we have cygpath @@ -2474,7 +2501,7 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -install_sh=${install_sh-"$am_aux_dir/install-sh"} +install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right @@ -2578,7 +2605,7 @@ else fi fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. @@ -2606,9 +2633,7 @@ fi { echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6; } - - -if test $USE_MAINTAINER_MODE = yes; then + if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else @@ -2707,6 +2732,15 @@ else fi +# Check whether --enable-posix-acls was given. +if test "${enable_posix_acls+set}" = set; then + enableval=$enable_posix_acls; +else + enable_posix_acls="no" + +fi + + # Check whether --enable-device-default-io-ops was given. if test "${enable_device_default_io_ops+set}" = set; then enableval=$enable_device_default_io_ops; @@ -2716,6 +2750,20 @@ else fi +# Check whether --enable-nfconv was given. +if test "${enable_nfconv+set}" = set; then + enableval=$enable_nfconv; enable_nfconv="no" +else + + case "${target_os}" in + darwin*) enable_nfconv="yes" ;; + *) enable_nfconv="no" ;; + esac + + +fi + + # pthread_rwlock_t requires _GNU_SOURCE cat >>confdefs.h <<\_ACEOF @@ -3500,9 +3548,7 @@ if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi - - -if test "x$enable_dependency_tracking" != xno; then + if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else @@ -3512,7 +3558,6 @@ fi - depcc="$CC" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 @@ -3580,6 +3625,7 @@ else depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then @@ -3609,9 +3655,7 @@ fi echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - -if + if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= @@ -3759,6 +3803,7 @@ if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then fi + # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} @@ -3845,12 +3890,13 @@ do test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done +IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris @@ -3885,6 +3931,7 @@ done fi SED=$lt_cv_path_SED + { echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6; } @@ -4235,8 +4282,8 @@ fi echo "${ECHO_T}$lt_cv_path_NM" >&6; } NM="$lt_cv_path_NM" -{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 -echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 +echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else @@ -4255,7 +4302,7 @@ lt_cv_deplibs_check_method='unknown' # whether `pass_all' will *always* work, you probably want this one. case $host_os in -aix4* | aix5*) +aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; @@ -4277,16 +4324,22 @@ cygwin*) mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump'. - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | kfreebsd*-gnu | dragonfly*) +freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) @@ -4324,7 +4377,7 @@ hpux10.20* | hpux11*) esac ;; -interix3*) +interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; @@ -4340,7 +4393,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; @@ -4374,6 +4427,10 @@ osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + solaris*) lt_cv_deplibs_check_method=pass_all ;; @@ -4461,7 +4518,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 4464 "configure"' > conftest.$ac_ext + echo '#line 4521 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -4496,7 +4553,8 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 @@ -4507,6 +4565,9 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) case `/usr/bin/file conftest.o` in *32-bit*) case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; @@ -4523,6 +4584,9 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) ;; *64-bit*) case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; @@ -4626,7 +4690,11 @@ sparc*-*solaris*) *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) LD="${LD-ld} -64" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; esac ;; esac @@ -5690,6 +5758,7 @@ else depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then @@ -5719,9 +5788,7 @@ fi echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - -if + if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= @@ -6229,7 +6296,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! - # find the maximum length of command line arguments { echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } @@ -6316,24 +6382,27 @@ else fi ;; *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi ;; esac @@ -6350,6 +6419,7 @@ fi + # Check for command to grab the raw symbol name followed by C symbol from nm. { echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } @@ -6387,7 +6457,7 @@ hpux*) # Its linker distinguishes data from code symbols lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; -linux*) +linux* | k*bsd*-gnu) if test "$host_cpu" = ia64; then symcode='[ABCDGIRSTW]' lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" @@ -6540,7 +6610,7 @@ EOF echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi - rm -f conftest* conftst* + rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then @@ -6938,7 +7008,7 @@ test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= @@ -7100,6 +7170,318 @@ fi ;; esac + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_DSYMUTIL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { echo "$as_me:$LINENO: result: $DSYMUTIL" >&5 +echo "${ECHO_T}$DSYMUTIL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5 +echo "${ECHO_T}$ac_ct_DSYMUTIL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_NMEDIT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { echo "$as_me:$LINENO: result: $NMEDIT" >&5 +echo "${ECHO_T}$NMEDIT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5 +echo "${ECHO_T}$ac_ct_NMEDIT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + + { echo "$as_me:$LINENO: checking for -single_module linker flag" >&5 +echo $ECHO_N "checking for -single_module linker flag... $ECHO_C" >&6; } +if test "${lt_cv_apple_cc_single_mod+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + echo "int foo(void){return 1;}" > conftest.c + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib ${wl}-single_module conftest.c + if test -f libconftest.dylib; then + lt_cv_apple_cc_single_mod=yes + rm -rf libconftest.dylib* + fi + rm conftest.c + fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5 +echo "${ECHO_T}$lt_cv_apple_cc_single_mod" >&6; } + { echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5 +echo $ECHO_N "checking for -exported_symbols_list linker flag... $ECHO_C" >&6; } +if test "${lt_cv_ld_exported_symbols_list+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + lt_cv_ld_exported_symbols_list=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_ld_exported_symbols_list=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5 +echo "${ECHO_T}$lt_cv_ld_exported_symbols_list" >&6; } + case $host_os in + rhapsody* | darwin1.[0123]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil="~$DSYMUTIL \$lib || :" + else + _lt_dsymutil= + fi + ;; + esac + + enable_dlopen=no enable_win32_dll=no @@ -7138,10 +7520,10 @@ objext=o objext=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" +lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' +lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. @@ -7156,16 +7538,16 @@ compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* @@ -7182,7 +7564,7 @@ if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -7193,11 +7575,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7196: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7578: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7200: \$? = $ac_status" >&5 + echo "$as_me:7582: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7248,13 +7630,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; @@ -7264,7 +7648,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic='-fno-common' ;; - interix3*) + interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -7322,7 +7706,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } esac ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' @@ -7355,7 +7739,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static='-Bstatic' ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl='-Wl,' @@ -7374,6 +7758,22 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + esac + ;; esac ;; @@ -7383,6 +7783,10 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static='-non_shared' ;; + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' @@ -7445,12 +7849,12 @@ if test -n "$lt_prog_compiler_pic"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works+set}" = set; then +if test "${lt_cv_prog_compiler_pic_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_pic_works=no + lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -7461,27 +7865,27 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7464: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7868: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7468: \$? = $ac_status" >&5 + echo "$as_me:7872: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works=yes + lt_cv_prog_compiler_pic_works=yes fi fi $rm conftest* fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_pic_works" >&6; } -if test x"$lt_prog_compiler_pic_works" = xyes; then +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -7508,13 +7912,13 @@ esac wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works+set}" = set; then +if test "${lt_cv_prog_compiler_static_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_static_works=no + lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext + echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings @@ -7524,20 +7928,20 @@ else $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works=yes + lt_cv_prog_compiler_static_works=yes fi else - lt_prog_compiler_static_works=yes + lt_cv_prog_compiler_static_works=yes fi fi - $rm conftest* + $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_static_works" >&6; } -if test x"$lt_prog_compiler_static_works" = xyes; then +if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= @@ -7554,7 +7958,7 @@ else mkdir conftest cd conftest mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or @@ -7565,11 +7969,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7568: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7972: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7572: \$? = $ac_status" >&5 + echo "$as_me:7976: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7649,12 +8053,13 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. - exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do @@ -7713,7 +8118,7 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # See if GNU ld supports shared libraries. case $host_os in - aix3* | aix4* | aix5*) + aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no @@ -7761,7 +8166,7 @@ EOF allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -7779,7 +8184,7 @@ EOF fi ;; - interix3*) + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' @@ -7794,7 +8199,7 @@ EOF archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - linux*) + gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in @@ -7812,13 +8217,22 @@ EOF ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac - archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs=no @@ -7923,7 +8337,7 @@ _LT_EOF fi ;; - aix4* | aix5*) + aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -7943,7 +8357,7 @@ _LT_EOF # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -7977,7 +8391,7 @@ _LT_EOF strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - hardcode_direct=yes + : else # We have old collect2 hardcode_direct=unsupported @@ -8051,11 +8465,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -8110,11 +8531,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -8168,7 +8596,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; @@ -8201,19 +8629,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi link_all_deplibs=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' - archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -8253,7 +8680,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -8375,24 +8802,28 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; openbsd*) - hardcode_direct=yes - hardcode_shlibpath_var=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + ld_shlibs=no fi ;; @@ -8451,17 +8882,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; esac link_all_deplibs=yes ;; @@ -8518,7 +8948,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no @@ -8595,7 +9025,7 @@ x|xyes) { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 @@ -8653,17 +9083,55 @@ shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" + if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`echo $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi @@ -8684,7 +9152,7 @@ aix3*) soname_spec='${libname}${release}${shared_ext}$major' ;; -aix4* | aix5*) +aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -8823,12 +9291,8 @@ darwin* | rhapsody*) shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; @@ -8845,18 +9309,6 @@ freebsd1*) dynamic_linker=no ;; -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -8894,7 +9346,7 @@ freebsd* | dragonfly*) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; - freebsd*) # from 4.6 on + *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; @@ -8957,7 +9409,7 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; -interix3*) +interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -9012,45 +9464,24 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 9033 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -9062,18 +9493,6 @@ linux*) dynamic_linker='GNU/Linux ld.so' ;; -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -9155,6 +9574,10 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; +rdos*) + dynamic_linker=no + ;; + solaris*) version_type=linux need_lib_prefix=no @@ -9251,6 +9674,21 @@ esac echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" +fi + +sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" +fi + +sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" @@ -9308,6 +9746,7 @@ else darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" + old_striplib="$STRIP -S" { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else @@ -9569,7 +10008,7 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else { echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } @@ -9845,7 +10284,7 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi @@ -9894,7 +10333,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&6;} # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: @@ -10325,9 +10766,6 @@ CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -10461,11 +10899,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_predep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_predep_objects # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_postdep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_postdep_objects # Dependencies to place before the objects being linked to create a # shared library. @@ -10475,9 +10913,13 @@ predeps=$lt_predeps # shared library. postdeps=$lt_postdeps +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_compiler_lib_search_path | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -10557,13 +10999,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols @@ -10723,6 +11165,7 @@ postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= +compiler_lib_search_dirs_CXX= # Source file extension for C++ test sources. ac_ext=cpp @@ -10732,10 +11175,10 @@ objext=o objext_CXX=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" +lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' +lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. @@ -10751,16 +11194,16 @@ compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* # Allow CC to be a program name with arguments. @@ -10967,7 +11410,7 @@ case $host_os in # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - aix4* | aix5*) + aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -10980,7 +11423,7 @@ case $host_os in # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) @@ -11016,7 +11459,7 @@ case $host_os in strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - hardcode_direct_CXX=yes + : else # We have old collect2 hardcode_direct_CXX=unsupported @@ -11090,11 +11533,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -11150,11 +11600,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -11224,59 +11681,31 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='' link_all_deplibs_CXX=yes - - if test "$GXX" = yes ; then - lt_int_apple_cc_single_mod=no + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" + if test "$GXX" = yes ; then output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -11310,7 +11739,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi freebsd-elf*) archive_cmds_need_lc_CXX=no ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes @@ -11359,9 +11788,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_separator_CXX=: case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_CXX='+b $libdir' - ;; + hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; @@ -11429,7 +11856,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; esac ;; - interix3*) + interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' @@ -11469,7 +11896,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -11521,7 +11948,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; - pgCC*) + pgCC* | pgcpp*) # Portland Group C++ compiler archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' @@ -11549,6 +11976,29 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; esac ;; lynxos*) @@ -11587,16 +12037,20 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ld_shlibs_CXX=no ;; openbsd*) - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='${wl}-E' - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + else + ld_shlibs_CXX=no fi - output_verbose_link_cmd='echo' ;; osf3*) case $cc_basename in @@ -11758,15 +12212,10 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. We must also pass each convience library through - # to the system linker between allextract/defaultextract. - # The C++ compiler will combine linker options so we - # cannot just pass the convience library names through - # without $wl. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes @@ -11813,6 +12262,12 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac fi ;; esac @@ -11900,7 +12355,6 @@ test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" - cat > conftest.$ac_ext <&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + # + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + solaris*) case $cc_basename in CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. - postdeps_CXX='-lCstd -lCrun' + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi ;; esac ;; esac - case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac @@ -12055,12 +12546,14 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | os2* | pw32*) + mingw* | cygwin* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) @@ -12072,7 +12565,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; - interix3*) + interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -12098,7 +12591,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } esac else case $host_os in - aix4* | aix5*) + aix[4-9]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor @@ -12138,7 +12631,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } ;; esac ;; - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) @@ -12181,7 +12674,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } ;; esac ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler @@ -12194,7 +12687,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; - pgCC*) + pgCC* | pgcpp*) # Portland Group C++ compiler. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' @@ -12208,6 +12701,14 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static_CXX='-non_shared' ;; *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac ;; esac ;; @@ -12317,12 +12818,12 @@ if test -n "$lt_prog_compiler_pic_CXX"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then +if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_pic_works_CXX=no + lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -12333,27 +12834,27 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12336: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12837: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12340: \$? = $ac_status" >&5 + echo "$as_me:12841: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_CXX=yes + lt_cv_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_CXX" >&6; } -if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; @@ -12380,13 +12881,13 @@ esac wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_CXX+set}" = set; then +if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_static_works_CXX=no + lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext + echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings @@ -12396,20 +12897,20 @@ else $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_CXX=yes + lt_cv_prog_compiler_static_works_CXX=yes fi else - lt_prog_compiler_static_works_CXX=yes + lt_cv_prog_compiler_static_works_CXX=yes fi fi - $rm conftest* + $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_static_works_CXX" >&6; } -if test x"$lt_prog_compiler_static_works_CXX" = xyes; then +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= @@ -12426,7 +12927,7 @@ else mkdir conftest cd conftest mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or @@ -12437,11 +12938,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12440: $lt_compile\"" >&5) + (eval echo "\"\$as_me:12941: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12444: \$? = $ac_status" >&5 + echo "$as_me:12945: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12494,7 +12995,7 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in - aix4* | aix5*) + aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then @@ -12507,12 +13008,13 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' { echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6; } @@ -12538,7 +13040,7 @@ x|xyes) { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 @@ -12596,20 +13098,7 @@ shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi + need_lib_prefix=unknown hardcode_into_libs=no @@ -12627,7 +13116,7 @@ aix3*) soname_spec='${libname}${release}${shared_ext}$major' ;; -aix4* | aix5*) +aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -12766,12 +13255,7 @@ darwin* | rhapsody*) shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; @@ -12788,18 +13272,6 @@ freebsd1*) dynamic_linker=no ;; -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -12837,7 +13309,7 @@ freebsd* | dragonfly*) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; - freebsd*) # from 4.6 on + *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; @@ -12900,7 +13372,7 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; -interix3*) +interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -12955,7 +13427,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -12969,31 +13441,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 12976 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -13005,18 +13456,6 @@ linux*) dynamic_linker='GNU/Linux ld.so' ;; -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -13098,6 +13537,10 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; +rdos*) + dynamic_linker=no + ;; + solaris*) version_type=linux need_lib_prefix=no @@ -13194,6 +13637,21 @@ esac echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" +fi + +sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" +fi + +sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" @@ -13277,6 +13735,7 @@ if test -f "$ltmain"; then predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ + compiler_lib_search_dirs_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ @@ -13292,6 +13751,7 @@ if test -f "$ltmain"; then module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ + fix_srcfile_path_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do @@ -13377,9 +13837,6 @@ CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -13513,11 +13970,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_predep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_predep_objects_CXX # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_postdep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_postdep_objects_CXX # Dependencies to place before the objects being linked to create a # shared library. @@ -13527,9 +13984,13 @@ predeps=$lt_predeps_CXX # shared library. postdeps=$lt_postdeps_CXX +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -13609,13 +14070,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_CXX" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX @@ -13706,10 +14167,17 @@ objext=o objext_F77=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code=" subroutine t\n return\n end\n" +lt_simple_compile_test_code="\ + subroutine t + return + end +" # Code to be used in simple link tests -lt_simple_link_test_code=" program t\n end\n" +lt_simple_link_test_code="\ + program t + end +" # ltmain only uses $CC for tagged configurations so make sure $CC is set. @@ -13725,16 +14193,16 @@ compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* # Allow CC to be a program name with arguments. @@ -13772,7 +14240,7 @@ aix3*) postinstall_cmds='$RANLIB $lib' fi ;; -aix4* | aix5*) +aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi @@ -13818,13 +14286,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; @@ -13834,7 +14304,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic_F77='-fno-common' ;; - interix3*) + interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -13892,7 +14362,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } esac ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' @@ -13925,7 +14395,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static_F77='-Bstatic' ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' @@ -13944,6 +14414,22 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + lt_prog_compiler_wl_F77='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + lt_prog_compiler_wl_F77='' + ;; + esac + ;; esac ;; @@ -13953,6 +14439,10 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static_F77='-non_shared' ;; + rdos*) + lt_prog_compiler_static_F77='-non_shared' + ;; + solaris*) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' @@ -14015,12 +14505,12 @@ if test -n "$lt_prog_compiler_pic_F77"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_F77+set}" = set; then +if test "${lt_cv_prog_compiler_pic_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_pic_works_F77=no + lt_cv_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -14031,27 +14521,27 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14034: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14524: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14038: \$? = $ac_status" >&5 + echo "$as_me:14528: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_F77=yes + lt_cv_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_F77" >&6; } -if test x"$lt_prog_compiler_pic_works_F77" = xyes; then +if test x"$lt_cv_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; @@ -14078,13 +14568,13 @@ esac wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_F77+set}" = set; then +if test "${lt_cv_prog_compiler_static_works_F77+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_static_works_F77=no + lt_cv_prog_compiler_static_works_F77=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext + echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings @@ -14094,20 +14584,20 @@ else $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_F77=yes + lt_cv_prog_compiler_static_works_F77=yes fi else - lt_prog_compiler_static_works_F77=yes + lt_cv_prog_compiler_static_works_F77=yes fi fi - $rm conftest* + $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_static_works_F77" >&6; } -if test x"$lt_prog_compiler_static_works_F77" = xyes; then +if test x"$lt_cv_prog_compiler_static_works_F77" = xyes; then : else lt_prog_compiler_static_F77= @@ -14124,7 +14614,7 @@ else mkdir conftest cd conftest mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or @@ -14135,11 +14625,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14138: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14628: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14142: \$? = $ac_status" >&5 + echo "$as_me:14632: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -14219,12 +14709,13 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. - exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + exclude_expsyms_F77='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do @@ -14283,7 +14774,7 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # See if GNU ld supports shared libraries. case $host_os in - aix3* | aix4* | aix5*) + aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no @@ -14331,7 +14822,7 @@ EOF allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -14349,7 +14840,7 @@ EOF fi ;; - interix3*) + interix[3-9]*) hardcode_direct_F77=no hardcode_shlibpath_var_F77=no hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' @@ -14364,7 +14855,7 @@ EOF archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - linux*) + gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in @@ -14382,13 +14873,22 @@ EOF ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac - archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_F77=no @@ -14493,7 +14993,7 @@ _LT_EOF fi ;; - aix4* | aix5*) + aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -14513,7 +15013,7 @@ _LT_EOF # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -14547,7 +15047,7 @@ _LT_EOF strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - hardcode_direct_F77=yes + : else # We have old collect2 hardcode_direct_F77=unsupported @@ -14611,11 +15111,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -14660,11 +15167,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -14718,7 +15232,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. - old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; @@ -14751,19 +15265,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi link_all_deplibs_F77=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds_F77="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_F77="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_F77="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_F77="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -14803,7 +15316,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes @@ -14925,24 +15438,28 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; openbsd*) - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' + if test -f /usr/libexec/ld.so; then + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - ;; - *) - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - ;; - esac + ld_shlibs_F77=no fi ;; @@ -15001,17 +15518,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; + if test "$GCC" = yes; then + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' + fi + ;; esac link_all_deplibs_F77=yes ;; @@ -15068,7 +15584,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_F77='${wl}-z,text' archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no @@ -15145,7 +15661,7 @@ x|xyes) { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 @@ -15203,20 +15719,7 @@ shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi + need_lib_prefix=unknown hardcode_into_libs=no @@ -15234,7 +15737,7 @@ aix3*) soname_spec='${libname}${release}${shared_ext}$major' ;; -aix4* | aix5*) +aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -15373,12 +15876,7 @@ darwin* | rhapsody*) shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; @@ -15395,18 +15893,6 @@ freebsd1*) dynamic_linker=no ;; -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -15444,7 +15930,7 @@ freebsd* | dragonfly*) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; - freebsd*) # from 4.6 on + *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; @@ -15507,7 +15993,7 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; -interix3*) +interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -15562,7 +16048,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -15576,31 +16062,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 15583 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -15612,18 +16077,6 @@ linux*) dynamic_linker='GNU/Linux ld.so' ;; -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -15705,6 +16158,10 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; +rdos*) + dynamic_linker=no + ;; + solaris*) version_type=linux need_lib_prefix=no @@ -15793,13 +16250,28 @@ uts4*) shlibpath_var=LD_LIBRARY_PATH ;; -*) - dynamic_linker=no - ;; -esac -{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" +fi + +sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" +fi + +sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then @@ -15884,6 +16356,7 @@ if test -f "$ltmain"; then predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ + compiler_lib_search_dirs_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ @@ -15899,6 +16372,7 @@ if test -f "$ltmain"; then module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ + fix_srcfile_path_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do @@ -15984,9 +16458,6 @@ CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -16120,11 +16591,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_predep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_predep_objects_F77 # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_postdep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_postdep_objects_F77 # Dependencies to place before the objects being linked to create a # shared library. @@ -16134,9 +16605,13 @@ predeps=$lt_predeps_F77 # shared library. postdeps=$lt_postdeps_F77 +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_F77 + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -16216,13 +16691,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_F77" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 @@ -16280,10 +16755,10 @@ objext=o objext_GCJ=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}\n" +lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. @@ -16299,16 +16774,16 @@ compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* # Allow CC to be a program name with arguments. @@ -16326,7 +16801,6 @@ for cc_temp in $compiler""; do done cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` -LD_GCJ="$LD" # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no @@ -16347,7 +16821,7 @@ if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -16358,11 +16832,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16361: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16835: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16365: \$? = $ac_status" >&5 + echo "$as_me:16839: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -16413,14 +16887,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + ;; darwin* | rhapsody*) @@ -16429,7 +16905,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_pic_GCJ='-fno-common' ;; - interix3*) + interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; @@ -16487,10 +16963,10 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } esac ;; - mingw* | pw32* | os2*) + mingw* | cygwin* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; hpux9* | hpux10* | hpux11*) @@ -16520,7 +16996,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static_GCJ='-Bstatic' ;; - linux*) + linux* | k*bsd*-gnu) case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' @@ -16539,6 +17015,22 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + lt_prog_compiler_wl_GCJ='' + ;; + esac + ;; esac ;; @@ -16548,6 +17040,10 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } lt_prog_compiler_static_GCJ='-non_shared' ;; + rdos*) + lt_prog_compiler_static_GCJ='-non_shared' + ;; + solaris*) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' @@ -16610,12 +17106,12 @@ if test -n "$lt_prog_compiler_pic_GCJ"; then { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then +if test "${lt_cv_prog_compiler_pic_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_pic_works_GCJ=no + lt_cv_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. @@ -16626,27 +17122,27 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16629: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17125: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16633: \$? = $ac_status" >&5 + echo "$as_me:17129: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_GCJ=yes + lt_cv_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_GCJ" >&6; } -if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then +if test x"$lt_cv_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; @@ -16673,13 +17169,13 @@ esac wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } -if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then +if test "${lt_cv_prog_compiler_static_works_GCJ+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - lt_prog_compiler_static_works_GCJ=no + lt_cv_prog_compiler_static_works_GCJ=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext + echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16689,20 +17185,20 @@ else $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_GCJ=yes + lt_cv_prog_compiler_static_works_GCJ=yes fi else - lt_prog_compiler_static_works_GCJ=yes + lt_cv_prog_compiler_static_works_GCJ=yes fi fi - $rm conftest* + $rm -r conftest* LDFLAGS="$save_LDFLAGS" fi -{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_static_works_GCJ" >&6; } -if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then +if test x"$lt_cv_prog_compiler_static_works_GCJ" = xyes; then : else lt_prog_compiler_static_GCJ= @@ -16719,7 +17215,7 @@ else mkdir conftest cd conftest mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or @@ -16730,11 +17226,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16733: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17229: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16737: \$? = $ac_status" >&5 + echo "$as_me:17233: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16814,12 +17310,13 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. - exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + exclude_expsyms_GCJ='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= # Just being paranoid about ensuring that cc_basename is set. for cc_temp in $compiler""; do @@ -16878,7 +17375,7 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # See if GNU ld supports shared libraries. case $host_os in - aix3* | aix4* | aix5*) + aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no @@ -16926,7 +17423,7 @@ EOF allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' @@ -16944,7 +17441,7 @@ EOF fi ;; - interix3*) + interix[3-9]*) hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' @@ -16959,7 +17456,7 @@ EOF archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - linux*) + gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then tmp_addflag= case $cc_basename,$host_cpu in @@ -16977,13 +17474,22 @@ EOF ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; esac - archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + *) + tmp_sharedflag='-shared' ;; + esac + archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test $supports_anon_versioning = yes; then archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi else ld_shlibs_GCJ=no @@ -17088,7 +17594,7 @@ _LT_EOF fi ;; - aix4* | aix5*) + aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. @@ -17108,7 +17614,7 @@ _LT_EOF # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes @@ -17142,7 +17648,7 @@ _LT_EOF strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 - hardcode_direct_GCJ=yes + : else # We have old collect2 hardcode_direct_GCJ=unsupported @@ -17216,11 +17722,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -17275,11 +17788,18 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -17333,7 +17853,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. - old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; @@ -17366,19 +17886,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi link_all_deplibs_GCJ=yes if test "$GCC" = yes ; then output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds_GCJ="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_GCJ="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_GCJ="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_GCJ="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else case $cc_basename in xlc*) output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ;; *) @@ -17418,7 +17937,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) + freebsd* | dragonfly*) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes @@ -17540,24 +18059,28 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; openbsd*) - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' + if test -f /usr/libexec/ld.so; then + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - ;; - *) - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - ;; - esac + ld_shlibs_GCJ=no fi ;; @@ -17616,17 +18139,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; + if test "$GCC" = yes; then + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' + fi + ;; esac link_all_deplibs_GCJ=yes ;; @@ -17683,7 +18205,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_GCJ='${wl}-z,text' archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no @@ -17760,7 +18282,7 @@ x|xyes) { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 @@ -17818,20 +18340,7 @@ shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi + need_lib_prefix=unknown hardcode_into_libs=no @@ -17849,7 +18358,7 @@ aix3*) soname_spec='${libname}${release}${shared_ext}$major' ;; -aix4* | aix5*) +aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -17988,12 +18497,7 @@ darwin* | rhapsody*) shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; @@ -18010,18 +18514,6 @@ freebsd1*) dynamic_linker=no ;; -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -18059,7 +18551,7 @@ freebsd* | dragonfly*) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; - freebsd*) # from 4.6 on + *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; @@ -18122,7 +18614,7 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; -interix3*) +interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no @@ -18177,7 +18669,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux*) +linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -18191,31 +18683,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 18198 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -18227,18 +18698,6 @@ linux*) dynamic_linker='GNU/Linux ld.so' ;; -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -18320,6 +18779,10 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; +rdos*) + dynamic_linker=no + ;; + solaris*) version_type=linux need_lib_prefix=no @@ -18416,6 +18879,21 @@ esac echo "${ECHO_T}$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" +fi + +sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" +fi + +sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" @@ -18499,6 +18977,7 @@ if test -f "$ltmain"; then predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ + compiler_lib_search_dirs_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ @@ -18514,6 +18993,7 @@ if test -f "$ltmain"; then module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ + fix_srcfile_path_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do @@ -18599,9 +19079,6 @@ CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -18735,11 +19212,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_predep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_predep_objects_GCJ # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_postdep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_postdep_objects_GCJ # Dependencies to place before the objects being linked to create a # shared library. @@ -18749,9 +19226,13 @@ predeps=$lt_predeps_GCJ # shared library. postdeps=$lt_postdeps_GCJ +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_GCJ + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -18831,13 +19312,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_GCJ" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ @@ -18894,7 +19375,7 @@ objext=o objext_RC=$objext # Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" @@ -18913,16 +19394,16 @@ compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $rm conftest* ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext +echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` -$rm conftest* +$rm -r conftest* # Allow CC to be a program name with arguments. @@ -18982,6 +19463,7 @@ if test -f "$ltmain"; then predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ + compiler_lib_search_dirs_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ @@ -18997,6 +19479,7 @@ if test -f "$ltmain"; then module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ + fix_srcfile_path_RC \ exclude_expsyms_RC \ include_expsyms_RC; do @@ -19082,9 +19565,6 @@ CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC -gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\` -gcc_ver=\`gcc -dumpversion\` - # An ERE matcher. EGREP=$lt_EGREP @@ -19218,11 +19698,11 @@ striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. -predep_objects=\`echo $lt_predep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +predep_objects=$lt_predep_objects_RC # Dependencies to place after the objects being linked to create a # shared library. -postdep_objects=\`echo $lt_postdep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +postdep_objects=$lt_postdep_objects_RC # Dependencies to place before the objects being linked to create a # shared library. @@ -19232,9 +19712,13 @@ predeps=$lt_predeps_RC # shared library. postdeps=$lt_postdeps_RC +# The directories searched by this compiler when creating a shared +# library +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_RC + # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +compiler_lib_search_path=$lt_compiler_lib_search_path_RC # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method @@ -19314,13 +19798,13 @@ variables_saved_for_relink="$variables_saved_for_relink" link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries -sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\` +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_RC" +fix_srcfile_path=$lt_fix_srcfile_path # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC @@ -19918,11 +20402,10 @@ pkg_failed=no { echo "$as_me:$LINENO: checking for FUSE_MODULE" >&5 echo $ECHO_N "checking for FUSE_MODULE... $ECHO_C" >&6; } -if test -n "$PKG_CONFIG"; then - if test -n "$FUSE_MODULE_CFLAGS"; then - pkg_cv_FUSE_MODULE_CFLAGS="$FUSE_MODULE_CFLAGS" - else - if test -n "$PKG_CONFIG" && \ +if test -n "$FUSE_MODULE_CFLAGS"; then + pkg_cv_FUSE_MODULE_CFLAGS="$FUSE_MODULE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"fuse >= 2.6.0\"") >&5 ($PKG_CONFIG --exists --print-errors "fuse >= 2.6.0") 2>&5 ac_status=$? @@ -19932,15 +20415,13 @@ if test -n "$PKG_CONFIG"; then else pkg_failed=yes fi - fi -else - pkg_failed=untried + else + pkg_failed=untried fi -if test -n "$PKG_CONFIG"; then - if test -n "$FUSE_MODULE_LIBS"; then - pkg_cv_FUSE_MODULE_LIBS="$FUSE_MODULE_LIBS" - else - if test -n "$PKG_CONFIG" && \ +if test -n "$FUSE_MODULE_LIBS"; then + pkg_cv_FUSE_MODULE_LIBS="$FUSE_MODULE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"fuse >= 2.6.0\"") >&5 ($PKG_CONFIG --exists --print-errors "fuse >= 2.6.0") 2>&5 ac_status=$? @@ -19950,9 +20431,8 @@ if test -n "$PKG_CONFIG"; then else pkg_failed=yes fi - fi -else - pkg_failed=untried + else + pkg_failed=untried fi @@ -19965,9 +20445,9 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "fuse >= 2.6.0"` + FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "fuse >= 2.6.0" 2>&1` else - FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "fuse >= 2.6.0"` + FUSE_MODULE_PKG_ERRORS=`$PKG_CONFIG --print-errors "fuse >= 2.6.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$FUSE_MODULE_PKG_ERRORS" >&5 @@ -21515,6 +21995,161 @@ _ACEOF fi +# For the 'nfconv' patch (Mac OS X only): +case "${target_os}" in +darwin*) + if test "${enable_nfconv}" = "yes"; then + if test "${ac_cv_header_CoreFoundation_CoreFoundation_h+set}" = set; then + { echo "$as_me:$LINENO: checking for CoreFoundation/CoreFoundation.h" >&5 +echo $ECHO_N "checking for CoreFoundation/CoreFoundation.h... $ECHO_C" >&6; } +if test "${ac_cv_header_CoreFoundation_CoreFoundation_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_CoreFoundation_CoreFoundation_h" >&5 +echo "${ECHO_T}$ac_cv_header_CoreFoundation_CoreFoundation_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking CoreFoundation/CoreFoundation.h usability" >&5 +echo $ECHO_N "checking CoreFoundation/CoreFoundation.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking CoreFoundation/CoreFoundation.h presence" >&5 +echo $ECHO_N "checking CoreFoundation/CoreFoundation.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: CoreFoundation/CoreFoundation.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: CoreFoundation/CoreFoundation.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------------- ## +## Report this to ntfs-3g-devel@lists.sf.net ## +## ----------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for CoreFoundation/CoreFoundation.h" >&5 +echo $ECHO_N "checking for CoreFoundation/CoreFoundation.h... $ECHO_C" >&6; } +if test "${ac_cv_header_CoreFoundation_CoreFoundation_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_CoreFoundation_CoreFoundation_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_CoreFoundation_CoreFoundation_h" >&5 +echo "${ECHO_T}$ac_cv_header_CoreFoundation_CoreFoundation_h" >&6; } + +fi +if test $ac_cv_header_CoreFoundation_CoreFoundation_h = yes; then + + LDFLAGS="${LDFLAGS} -framework CoreFoundation" + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_NFCONV 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Cannot find CoreFoundation required for 'nfconv' functionality Mac OS X. You may use the --disable-nfconv 'configure' option to avoid this error." >&5 +echo "$as_me: error: Cannot find CoreFoundation required for 'nfconv' functionality Mac OS X. You may use the --disable-nfconv 'configure' option to avoid this error." >&2;} + { (exit 1); exit 1; }; } + +fi + + + fi + ;; +esac + # Checks for library functions. # getmntent is in the standard C library on UNICOS, in -lsun on Irix 4, # -lseq on Dynix/PTX, -lgen on Unixware. @@ -23019,6 +23654,11 @@ cat >>confdefs.h <<\_ACEOF #define IGNORE_MTAB 1 _ACEOF +test "${enable_posix_acls}" != "no" && +cat >>confdefs.h <<\_ACEOF +#define POSIXACLS 1 +_ACEOF + test "${enable_really_static}" = "yes" && enable_library="no" test "${enable_library}" = "no" && enable_ldconfig="no" @@ -23052,9 +23692,7 @@ fi - - -if test "${with_fuse}" = "internal"; then + if test "${with_fuse}" = "internal"; then FUSE_INTERNAL_TRUE= FUSE_INTERNAL_FALSE='#' else @@ -23062,9 +23700,7 @@ else FUSE_INTERNAL_FALSE= fi - - -if test "${enable_ldscript}" = "yes"; then + if test "${enable_ldscript}" = "yes"; then GENERATE_LDSCRIPT_TRUE= GENERATE_LDSCRIPT_FALSE='#' else @@ -23072,9 +23708,7 @@ else GENERATE_LDSCRIPT_FALSE= fi - - -if test "${WINDOWS}" = "yes"; then + if test "${WINDOWS}" = "yes"; then WINDOWS_TRUE= WINDOWS_FALSE='#' else @@ -23082,9 +23716,7 @@ else WINDOWS_FALSE= fi - - -if test "${enable_device_default_io_ops}" = "yes"; then + if test "${enable_device_default_io_ops}" = "yes"; then NTFS_DEVICE_DEFAULT_IO_OPS_TRUE= NTFS_DEVICE_DEFAULT_IO_OPS_FALSE='#' else @@ -23092,9 +23724,7 @@ else NTFS_DEVICE_DEFAULT_IO_OPS_FALSE= fi - - -if test "${enable_ldconfig}" = "yes"; then + if test "${enable_ldconfig}" = "yes"; then RUN_LDCONFIG_TRUE= RUN_LDCONFIG_FALSE='#' else @@ -23102,9 +23732,7 @@ else RUN_LDCONFIG_FALSE= fi - - -if test "${enable_really_static}" = "yes"; then + if test "${enable_really_static}" = "yes"; then REALLYSTATIC_TRUE= REALLYSTATIC_FALSE='#' else @@ -23112,9 +23740,7 @@ else REALLYSTATIC_FALSE= fi - - -if test "${enable_library}" = "yes"; then + if test "${enable_library}" = "yes"; then INSTALL_LIBRARY_TRUE= INSTALL_LIBRARY_FALSE='#' else @@ -23122,9 +23748,7 @@ else INSTALL_LIBRARY_FALSE= fi - - -if test "${enable_mount_helper}" = "yes"; then + if test "${enable_mount_helper}" = "yes"; then ENABLE_MOUNT_HELPER_TRUE= ENABLE_MOUNT_HELPER_FALSE='#' else @@ -23145,7 +23769,7 @@ if test -z "${MKDIR_P}"; then fi # generate files -ac_config_files="$ac_config_files Makefile include/Makefile include/fuse-lite/Makefile include/ntfs-3g/Makefile libfuse-lite/Makefile libntfs-3g/Makefile libntfs-3g/libntfs-3g.pc libntfs-3g/libntfs-3g.script.so src/Makefile src/ntfs-3g.8 src/ntfs-3g.probe.8" +ac_config_files="$ac_config_files Makefile include/Makefile include/fuse-lite/Makefile include/ntfs-3g/Makefile libfuse-lite/Makefile libntfs-3g/Makefile libntfs-3g/libntfs-3g.pc libntfs-3g/libntfs-3g.script.so src/Makefile src/ntfs-3g.8 src/ntfs-3g.probe.8 src/ntfs-3g.usermap.8 src/ntfs-3g.secaudit.8" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -23627,7 +24251,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ntfs-3g $as_me 2009.4.4, which was +This file was extended by ntfs-3g $as_me 2009.11.14, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23680,7 +24304,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -ntfs-3g config.status 2009.4.4 +ntfs-3g config.status 2009.11.14 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -23691,6 +24315,7 @@ gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF @@ -23806,6 +24431,8 @@ do "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/ntfs-3g.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.8" ;; "src/ntfs-3g.probe.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.probe.8" ;; + "src/ntfs-3g.usermap.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.usermap.8" ;; + "src/ntfs-3g.secaudit.8") CONFIG_FILES="$CONFIG_FILES src/ntfs-3g.secaudit.8" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -23920,6 +24547,7 @@ target_os!$target_os$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim +am__isrc!$am__isrc$ac_delim CYGPATH_W!$CYGPATH_W$ac_delim PACKAGE!$PACKAGE$ac_delim VERSION!$VERSION$ac_delim @@ -23958,13 +24586,12 @@ CCDEPMODE!$CCDEPMODE$ac_delim am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim LN_S!$LN_S$ac_delim +SED!$SED$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim ECHO!$ECHO$ac_delim AR!$AR$ac_delim RANLIB!$RANLIB$ac_delim -CPP!$CPP$ac_delim -CXX!$CXX$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -24006,6 +24633,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +DSYMUTIL!$DSYMUTIL$ac_delim +NMEDIT!$NMEDIT$ac_delim +CPP!$CPP$ac_delim +CXX!$CXX$ac_delim CXXFLAGS!$CXXFLAGS$ac_delim ac_ct_CXX!$ac_ct_CXX$ac_delim CXXDEPMODE!$CXXDEPMODE$ac_delim @@ -24018,7 +24649,6 @@ ac_ct_F77!$ac_ct_F77$ac_delim LIBTOOL!$LIBTOOL$ac_delim MV!$MV$ac_delim RM!$RM$ac_delim -SED!$SED$ac_delim LDCONFIG!$LDCONFIG$ac_delim PKG_CONFIG!$PKG_CONFIG$ac_delim FUSE_MODULE_CFLAGS!$FUSE_MODULE_CFLAGS$ac_delim @@ -24052,7 +24682,7 @@ MKDIR_P!$MKDIR_P$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 44; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 47; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -24279,6 +24909,11 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF @@ -24332,6 +24967,7 @@ s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out @@ -24447,21 +25083,22 @@ echo "$as_me: $ac_file is unchanged" >&6;} fi rm -f "$tmp/out12" # Compute $ac_file's index in $config_headers. +_am_arg=$ac_file _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $ac_file | $ac_file:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || -$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| . 2>/dev/null || -echo X$ac_file | +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -24496,8 +25133,9 @@ echo "$as_me: executing $ac_file commands" >&6;} # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ diff --git a/release/src/router/ntfs-3g/configure.ac b/release/src/router/ntfs-3g/configure.ac index 8e86c9509d..095da99bd7 100644 --- a/release/src/router/ntfs-3g/configure.ac +++ b/release/src/router/ntfs-3g/configure.ac @@ -3,7 +3,7 @@ # compilation. # # Copyright (c) 2000-2006 Anton Altaparmakov -# Copyright (c) 2005-2008 Szabolcs Szakacsits +# Copyright (c) 2005-2009 Szabolcs Szakacsits # Copyright (C) 2007-2008 Alon Bar-Lev # # This program/include file is free software; you can redistribute it and/or @@ -23,8 +23,8 @@ # Autoconf AC_PREREQ(2.59) -AC_INIT([ntfs-3g],[2009.4.4],[ntfs-3g-devel@lists.sf.net]) -LIBNTFS_3G_VERSION="54" +AC_INIT([ntfs-3g],[2009.11.14],[ntfs-3g-devel@lists.sf.net]) +LIBNTFS_3G_VERSION="71" AC_CONFIG_SRCDIR([src/ntfs-3g.c]) # Environment @@ -107,12 +107,31 @@ AC_ARG_ENABLE( ) AC_ARG_ENABLE( + [posix-acls], + [AS_HELP_STRING([--enable-posix-acls],[enable POSIX ACL support])], + , + [enable_posix_acls="no"] +) + +AC_ARG_ENABLE( [device-default-io-ops], [AS_HELP_STRING([--disable-device-default-io-ops],[install default IO ops])], , [enable_device_default_io_ops="yes"] ) +AC_ARG_ENABLE( + [nfconv], + [AS_HELP_STRING([--disable-nfconv],[disable the 'nfconv' patch, which adds support for Unicode normalization form conversion when built on Mac OS X @<:@default=enabled for Mac OS X@:>@])], + [enable_nfconv="no"], + [ + case "${target_os}" in + darwin*) enable_nfconv="yes" ;; + *) enable_nfconv="no" ;; + esac + ] +) + # pthread_rwlock_t requires _GNU_SOURCE AC_GNU_SOURCE @@ -263,6 +282,26 @@ AC_CHECK_MEMBERS([struct stat.st_rdev]) AC_CHECK_MEMBERS([struct stat.st_atim]) AC_CHECK_MEMBERS([struct stat.st_atimespec]) +# For the 'nfconv' patch (Mac OS X only): +case "${target_os}" in +darwin*) + if test "${enable_nfconv}" = "yes"; then + AC_CHECK_HEADER( + [CoreFoundation/CoreFoundation.h], + [ + LDFLAGS="${LDFLAGS} -framework CoreFoundation" + AC_DEFINE( + [ENABLE_NFCONV], + [1], + [Define to 1 if the nfconv patch should be enabled] + ) + ], + AC_MSG_ERROR([[Cannot find CoreFoundation required for 'nfconv' functionality Mac OS X. You may use the --disable-nfconv 'configure' option to avoid this error.]]) + ) + fi + ;; +esac + # Checks for library functions. AC_FUNC_GETMNTENT AC_FUNC_MBRTOWC @@ -309,6 +348,7 @@ test "${enable_device_default_io_ops}" = "no" && AC_DEFINE( ) test "${enable_mtab}" = "no" && AC_DEFINE([IGNORE_MTAB], [1], [Don't update /etc/mtab]) +test "${enable_posix_acls}" != "no" && AC_DEFINE([POSIXACLS], [1], [POSIX ACL support]) test "${enable_really_static}" = "yes" && enable_library="no" test "${enable_library}" = "no" && enable_ldconfig="no" @@ -375,6 +415,8 @@ AC_CONFIG_FILES([ src/Makefile src/ntfs-3g.8 src/ntfs-3g.probe.8 + src/ntfs-3g.usermap.8 + src/ntfs-3g.secaudit.8 ]) AC_OUTPUT diff --git a/release/src/router/ntfs-3g/depcomp b/release/src/router/ntfs-3g/depcomp index 04701da536..e5f9736c72 100755 --- a/release/src/router/ntfs-3g/depcomp +++ b/release/src/router/ntfs-3g/depcomp @@ -1,9 +1,10 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2005-07-09.11 +scriptversion=2007-03-29.01 -# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software +# Foundation, Inc. # 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 @@ -91,7 +92,20 @@ gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. - "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" stat=$? if test $stat -eq 0; then : else @@ -201,34 +215,39 @@ aix) # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. - stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u "$@" -M fi stat=$? - if test -f "$tmpdepfile"; then : - else - stripped=`echo "$stripped" | sed 's,^.*/,,'` - tmpdepfile="$stripped.u" - fi - if test $stat -eq 0; then : else - rm -f "$tmpdepfile" + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done if test -f "$tmpdepfile"; then - outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile @@ -276,6 +295,46 @@ icc) rm -f "$tmpdepfile" ;; +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. @@ -288,13 +347,13 @@ tru64) if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a - # static library. This mecanism is used in libtool 1.4 series to + # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in in $dir.libs/$base.o.d and + # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is diff --git a/release/src/router/ntfs-3g/include/Makefile.in b/release/src/router/ntfs-3g/include/Makefile.in index 838f43e74c..afadcc53a1 100644 --- a/release/src/router/ntfs-3g/include/Makefile.in +++ b/release/src/router/ntfs-3g/include/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -13,15 +13,11 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -49,17 +45,18 @@ SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ - install-exec-recursive install-info-recursive \ - install-recursive installcheck-recursive installdirs-recursive \ - pdf-recursive ps-recursive uninstall-info-recursive \ - uninstall-recursive + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -78,26 +75,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -111,13 +102,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -129,25 +117,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -159,6 +141,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -191,12 +174,15 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in SUBDIRS = ntfs-3g fuse-lite all: all-recursive @@ -238,10 +224,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -distclean-libtool: - -rm -f libtool -uninstall-info-am: - # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, @@ -273,8 +255,7 @@ $(RECURSIVE_TARGETS): $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" -mostlyclean-recursive clean-recursive distclean-recursive \ -maintainer-clean-recursive: +$(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ @@ -318,8 +299,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -344,8 +325,8 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -355,13 +336,12 @@ ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -375,22 +355,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -404,7 +383,7 @@ distdir: $(DISTFILES) list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ - || $(mkdir_p) "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ @@ -412,6 +391,8 @@ distdir: $(DISTFILES) $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ @@ -452,8 +433,7 @@ clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool \ - distclean-tags +distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive @@ -467,12 +447,20 @@ info-am: install-data-am: +install-dvi: install-dvi-recursive + install-exec-am: +install-html: install-html-recursive + install-info: install-info-recursive install-man: +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + installcheck-am: maintainer-clean: maintainer-clean-recursive @@ -491,22 +479,24 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-info-am +uninstall-am: -uninstall-info: uninstall-info-recursive +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip -.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ - clean clean-generic clean-libtool clean-recursive ctags \ - ctags-recursive distclean distclean-generic distclean-libtool \ - distclean-recursive distclean-tags distdir dvi dvi-am html \ +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + ctags ctags-recursive distclean 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-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ + 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 installdirs-am maintainer-clean \ - maintainer-clean-generic maintainer-clean-recursive \ - mostlyclean mostlyclean-generic mostlyclean-libtool \ - mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ - uninstall uninstall-am uninstall-info-am + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am # 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. diff --git a/release/src/router/ntfs-3g/include/fuse-lite/Makefile.am b/release/src/router/ntfs-3g/include/fuse-lite/Makefile.am index 7c18dea460..15a84bbf5d 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/Makefile.am +++ b/release/src/router/ntfs-3g/include/fuse-lite/Makefile.am @@ -1,5 +1,5 @@ -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +MAINTAINERCLEANFILES = Makefile.in noinst_HEADERS = \ fuse.h \ diff --git a/release/src/router/ntfs-3g/include/fuse-lite/Makefile.in b/release/src/router/ntfs-3g/include/fuse-lite/Makefile.in index 87c89991d6..e9fece0212 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/Makefile.in +++ b/release/src/router/ntfs-3g/include/fuse-lite/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -14,15 +14,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -54,8 +50,6 @@ ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -74,26 +68,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -107,13 +95,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -125,25 +110,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -155,6 +134,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -187,13 +167,16 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in noinst_HEADERS = \ fuse.h \ fuse_common.h \ @@ -241,17 +224,13 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -distclean-libtool: - -rm -f libtool -uninstall-info-am: - ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -263,8 +242,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -274,13 +253,12 @@ ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -294,22 +272,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -355,8 +332,7 @@ clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool \ - distclean-tags +distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am @@ -370,12 +346,20 @@ info-am: install-data-am: +install-dvi: install-dvi-am + 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 + installcheck-am: maintainer-clean: maintainer-clean-am @@ -394,18 +378,22 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am +uninstall-am: + +.MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool ctags distclean 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-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ + 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-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-info-am + uninstall-am # 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. diff --git a/release/src/router/ntfs-3g/include/fuse-lite/fuse.h b/release/src/router/ntfs-3g/include/fuse-lite/fuse.h index 05c1d7afa6..8cc9f2c110 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/fuse.h +++ b/release/src/router/ntfs-3g/include/fuse-lite/fuse.h @@ -441,6 +441,11 @@ struct fuse_context { /** Private filesystem data */ void *private_data; + +#ifdef POSIXACLS + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +#endif }; /* ----------------------------------------------------------- * diff --git a/release/src/router/ntfs-3g/include/fuse-lite/fuse_common.h b/release/src/router/ntfs-3g/include/fuse-lite/fuse_common.h index 6ddcf99e2e..819bb8d75f 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/fuse_common.h +++ b/release/src/router/ntfs-3g/include/fuse-lite/fuse_common.h @@ -16,13 +16,18 @@ #define _FUSE_COMMON_H_ #include "fuse_opt.h" +#include /* temporary */ #include /** Major version of FUSE library interface */ #define FUSE_MAJOR_VERSION 2 /** Minor version of FUSE library interface */ +#ifdef POSIXACLS +#define FUSE_MINOR_VERSION 8 +#else #define FUSE_MINOR_VERSION 7 +#endif #define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) @@ -31,6 +36,13 @@ extern "C" { #endif +#ifdef POSIXACLS +/* + * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations + */ +#define FUSE_CAP_DONT_MASK (1 << 6) +#endif + /** * Information about open files * @@ -104,10 +116,19 @@ struct fuse_conn_info { */ unsigned max_readahead; +#ifdef POSIXACLS + unsigned capable; + unsigned want; + /** + * For future use. + */ + unsigned reserved[25]; +#else /** * For future use. */ unsigned reserved[27]; +#endif }; struct fuse_session; diff --git a/release/src/router/ntfs-3g/include/fuse-lite/fuse_kernel.h b/release/src/router/ntfs-3g/include/fuse-lite/fuse_kernel.h index be124ee944..59c72b8d18 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/fuse_kernel.h +++ b/release/src/router/ntfs-3g/include/fuse-lite/fuse_kernel.h @@ -30,6 +30,9 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir */ #ifndef linux @@ -46,7 +49,12 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ +#ifdef POSIXACLS +#define FUSE_KERNEL_MINOR_VERSION 12 +#define FUSE_KERNEL_MINOR_FALLBACK 8 +#else #define FUSE_KERNEL_MINOR_VERSION 8 +#endif /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -75,6 +83,9 @@ struct fuse_attr { __u32 uid; __u32 gid; __u32 rdev; +#ifdef POSIXACLS + __u64 filling; /* JPA needed for minor >= 12, but meaning unknown */ +#endif }; struct fuse_kstatfs { @@ -119,9 +130,11 @@ struct fuse_file_lock { /** * INIT request/reply flags + * FUSE_DONT_MASK: don't apply umask to file mode on create operations */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) +#define FUSE_DONT_MASK (1 << 6) /** * Release flags @@ -169,6 +182,7 @@ enum fuse_opcode { /* The read buffer is required to be at least 8k, but may be much larger */ #define FUSE_MIN_READ_BUFFER 8192 +#define FUSE_COMPAT_ENTRY_OUT_SIZE 120 /* JPA */ struct fuse_entry_out { __u64 nodeid; /* Inode ID */ @@ -185,6 +199,8 @@ struct fuse_forget_in { __u64 nlookup; }; +#define FUSE_COMPAT_FUSE_ATTR_OUT_SIZE 96 /* JPA */ + struct fuse_attr_out { __u64 attr_valid; /* Cache timeout for the attributes */ __u32 attr_valid_nsec; @@ -192,14 +208,20 @@ struct fuse_attr_out { struct fuse_attr attr; }; +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + struct fuse_mknod_in { __u32 mode; __u32 rdev; +#ifdef POSIXACLS + __u32 umask; + __u32 padding; +#endif }; struct fuse_mkdir_in { __u32 mode; - __u32 padding; + __u32 umask; }; struct fuse_rename_in { @@ -231,7 +253,20 @@ struct fuse_setattr_in { struct fuse_open_in { __u32 flags; +#ifdef POSIXACLS + __u32 unused; +#else + __u32 mode; +#endif +}; + +struct fuse_create_in { + __u32 flags; __u32 mode; +#ifdef POSIXACLS + __u32 umask; + __u32 padding; +#endif }; struct fuse_open_out { @@ -261,11 +296,18 @@ struct fuse_read_in { __u32 padding; }; +#define FUSE_COMPAT_WRITE_IN_SIZE 24 /* JPA */ + struct fuse_write_in { __u64 fh; __u64 offset; __u32 size; __u32 write_flags; +#ifdef POSIXACLS + __u64 lock_owner; /* JPA */ + __u32 flags; /* JPA */ + __u32 padding; /* JPA */ +#endif }; struct fuse_write_out { diff --git a/release/src/router/ntfs-3g/include/fuse-lite/fuse_lowlevel.h b/release/src/router/ntfs-3g/include/fuse-lite/fuse_lowlevel.h index 9dd9ccd414..7125bf0bed 100644 --- a/release/src/router/ntfs-3g/include/fuse-lite/fuse_lowlevel.h +++ b/release/src/router/ntfs-3g/include/fuse-lite/fuse_lowlevel.h @@ -100,6 +100,11 @@ struct fuse_ctx { /** Thread ID of the calling process */ pid_t pid; + +#ifdef POSIXACLS + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +#endif }; /* 'to_set' flags in setattr */ @@ -920,6 +925,21 @@ int fuse_reply_write(fuse_req_t req, size_t count); */ int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); +#ifdef POSIXACLS +/** + * Reply with data vector + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param iov the vector containing the data + * @param count the size of vector + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count); +#endif + /** * Reply with filesystem statistics * diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.am b/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.am index 3f085486af..e431df29d8 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.am +++ b/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.am @@ -2,6 +2,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in headers = \ + acls.h \ attrib.h \ attrlist.h \ bitmap.h \ @@ -13,6 +14,7 @@ headers = \ device.h \ device_io.h \ dir.h \ + efs.h \ endians.h \ index.h \ inode.h \ @@ -24,6 +26,7 @@ headers = \ misc.h \ mst.h \ ntfstime.h \ + reparse.h \ runlist.h \ security.h \ support.h \ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.in b/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.in index f648d3aa96..23eabc6193 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.in +++ b/release/src/router/ntfs-3g/include/ntfs-3g/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -14,15 +14,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -50,16 +46,18 @@ CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = -am__noinst_HEADERS_DIST = attrib.h attrlist.h bitmap.h bootsect.h \ - collate.h compat.h compress.h debug.h device.h device_io.h \ - dir.h endians.h index.h inode.h layout.h lcnalloc.h logfile.h \ - logging.h mft.h misc.h mst.h ntfstime.h runlist.h security.h \ - support.h types.h unistr.h volume.h -am__ntfs3ginclude_HEADERS_DIST = attrib.h attrlist.h bitmap.h \ +am__noinst_HEADERS_DIST = acls.h attrib.h attrlist.h bitmap.h \ + bootsect.h collate.h compat.h compress.h debug.h device.h \ + device_io.h dir.h efs.h endians.h index.h inode.h layout.h \ + lcnalloc.h logfile.h logging.h mft.h misc.h mst.h ntfstime.h \ + reparse.h runlist.h security.h support.h types.h unistr.h \ + volume.h +am__ntfs3ginclude_HEADERS_DIST = acls.h attrib.h attrlist.h bitmap.h \ bootsect.h collate.h compat.h compress.h debug.h device.h \ - device_io.h dir.h endians.h index.h inode.h layout.h \ + device_io.h dir.h efs.h endians.h index.h inode.h layout.h \ lcnalloc.h logfile.h logging.h mft.h misc.h mst.h ntfstime.h \ - runlist.h security.h support.h types.h unistr.h volume.h + reparse.h runlist.h security.h support.h types.h unistr.h \ + volume.h am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -73,8 +71,6 @@ ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -93,26 +89,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -126,13 +116,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -144,25 +131,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -174,6 +155,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -206,14 +188,18 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in headers = \ + acls.h \ attrib.h \ attrlist.h \ bitmap.h \ @@ -225,6 +211,7 @@ headers = \ device.h \ device_io.h \ dir.h \ + efs.h \ endians.h \ index.h \ inode.h \ @@ -236,6 +223,7 @@ headers = \ misc.h \ mst.h \ ntfstime.h \ + reparse.h \ runlist.h \ security.h \ support.h \ @@ -283,13 +271,9 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: install-ntfs3gincludeHEADERS: $(ntfs3ginclude_HEADERS) @$(NORMAL_INSTALL) - test -z "$(ntfs3gincludedir)" || $(mkdir_p) "$(DESTDIR)$(ntfs3gincludedir)" + test -z "$(ntfs3gincludedir)" || $(MKDIR_P) "$(DESTDIR)$(ntfs3gincludedir)" @list='$(ntfs3ginclude_HEADERS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ @@ -310,8 +294,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -323,8 +307,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -334,13 +318,12 @@ ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -354,22 +337,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -385,7 +367,7 @@ check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(ntfs3gincludedir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am @@ -418,8 +400,7 @@ clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile -distclean-am: clean-am distclean-generic distclean-libtool \ - distclean-tags +distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am @@ -433,12 +414,20 @@ info-am: install-data-am: install-ntfs3gincludeHEADERS +install-dvi: install-dvi-am + 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 + installcheck-am: maintainer-clean: maintainer-clean-am @@ -457,19 +446,22 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am uninstall-ntfs3gincludeHEADERS +uninstall-am: uninstall-ntfs3gincludeHEADERS + +.MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool ctags distclean 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-exec install-exec-am install-info \ + 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-ntfs3gincludeHEADERS \ + 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 uninstall uninstall-am uninstall-info-am \ - uninstall-ntfs3gincludeHEADERS + tags uninstall uninstall-am uninstall-ntfs3gincludeHEADERS # 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. diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/acls.h b/release/src/router/ntfs-3g/include/ntfs-3g/acls.h new file mode 100644 index 0000000000..13e5dbd10f --- /dev/null +++ b/release/src/router/ntfs-3g/include/ntfs-3g/acls.h @@ -0,0 +1,201 @@ +/* + * + * Copyright (c) 2007-2008 Jean-Pierre Andre + * + */ + +/* + * 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ACLS_H +#define ACLS_H + +/* + * JPA configuration modes for security.c / acls.c + * should be moved to some config file + */ + +#define FORCE_FORMAT_v1x 0 /* Insert security data as in NTFS v1.x */ +#define OWNERFROMACL 1 /* Get the owner from ACL (not Windows owner) */ +#define BUFSZ 1024 /* buffer size to read mapping file */ +#define MAPPINGFILE ".NTFS-3G/UserMapping" /* default mapping file */ +#define LINESZ 120 /* maximum useful size of a mapping line */ +#define CACHE_PERMISSIONS_BITS 6 /* log2 of unitary allocation of permissions */ +#define CACHE_PERMISSIONS_SIZE 262144 /* max cacheable permissions */ + +/* + * JPA The following must be in some library... + * but did not found out where + */ + +#define endian_rev16(x) (((x >> 8) & 255) | ((x & 255) << 8)) +#define endian_rev32(x) (((x >> 24) & 255) | ((x >> 8) & 0xff00) \ + | ((x & 0xff00) << 8) | ((x & 255) << 24)) + +#define cpu_to_be16(x) endian_rev16(cpu_to_le16(x)) +#define cpu_to_be32(x) endian_rev32(cpu_to_le32(x)) + +/* + * Macro definitions needed to share code with secaudit + */ + +#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf) +#define NTFS_FIND_GSID(map,gid,buf) ntfs_find_gsid(map,gid,buf) +#define NTFS_FIND_USER(map,usid) ntfs_find_user(map,usid) +#define NTFS_FIND_GROUP(map,gsid) ntfs_find_group(map,gsid) + + +/* + * Matching of ntfs permissions to Linux permissions + * these constants are adapted to endianness + * when setting, set them all + * when checking, check one is present + */ + + /* flags which are set to mean exec, write or read */ + +#define FILE_READ (FILE_READ_DATA) +#define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \ + | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) +#define FILE_EXEC (FILE_EXECUTE) +#define DIR_READ FILE_LIST_DIRECTORY +#define DIR_WRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD \ + | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) +#define DIR_EXEC (FILE_TRAVERSE) + + /* flags tested for meaning exec, write or read */ + /* tests for write allow for interpretation of a sticky bit */ + +#define FILE_GREAD (FILE_READ_DATA | GENERIC_READ) +#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE) +#define FILE_GEXEC (FILE_EXECUTE | GENERIC_EXECUTE) +#define DIR_GREAD (FILE_LIST_DIRECTORY | GENERIC_READ) +#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE) +#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE) + + /* standard owner (and administrator) rights */ + +#define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \ + | SYNCHRONIZE \ + | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \ + | FILE_READ_EA | FILE_WRITE_EA) + + /* standard world rights */ + +#define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \ + | SYNCHRONIZE) + + /* inheritance flags for files and directories */ + +#define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE +#define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE) + +/* + * To identify NTFS ACL meaning Posix ACL granted to root + * we use rights always granted to anybody, so they have no impact + * either on Windows or on Linux. + */ + +#define ROOT_OWNER_UNMARK SYNCHRONIZE /* ACL granted to root as owner */ +#define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */ + +/* + * A type large enough to hold any SID + */ + +typedef char BIGSID[40]; + +/* + * Struct to hold the input mapping file + * (private to this module) + */ + +struct MAPLIST { + struct MAPLIST *next; + char *uidstr; /* uid text from the same record */ + char *gidstr; /* gid text from the same record */ + char *sidstr; /* sid text from the same record */ + char maptext[LINESZ + 1]; +}; + +typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos); + +/* + * Constants defined in acls.c + */ + +extern const SID *adminsid; +extern const SID *worldsid; + +/* + * Functions defined in acls.c + */ + +BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz); +BOOL ntfs_valid_pattern(const SID *sid); +BOOL ntfs_valid_sid(const SID *sid); +BOOL ntfs_same_sid(const SID *first, const SID *second); + +BOOL ntfs_is_user_sid(const SID *usid); + + +int ntfs_sid_size(const SID * sid); +unsigned int ntfs_attr_size(const char *attr); + +const SID *ntfs_find_usid(const struct MAPPING *usermapping, + uid_t uid, SID *pdefsid); +const SID *ntfs_find_gsid(const struct MAPPING *groupmapping, + gid_t gid, SID *pdefsid); +uid_t ntfs_find_user(const struct MAPPING *usermapping, const SID *usid); +gid_t ntfs_find_group(const struct MAPPING *groupmapping, const SID * gsid); +const SID *ntfs_acl_owner(const char *secattr); + +#if POSIXACLS + +BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc); +void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc); +int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode); +struct POSIX_SECURITY *ntfs_build_inherited_posix( + const struct POSIX_SECURITY *pxdesc, mode_t mode, + mode_t umask, BOOL isdir); +struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc, + const struct POSIX_ACL *newacl, int count, BOOL deflt); +struct POSIX_SECURITY *ntfs_build_permissions_posix( + struct MAPPING* const mapping[], + const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir); +struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first, + const struct POSIX_SECURITY *second); +char *ntfs_build_descr_posix(struct MAPPING* const mapping[], + struct POSIX_SECURITY *pxdesc, + int isdir, const SID *usid, const SID *gsid); + +#endif /* POSIXACLS */ + +int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, + const SID *usid, const SID *gsid, BOOL fordir); +int ntfs_build_permissions(const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir); +char *ntfs_build_descr(mode_t mode, + int isdir, const SID * usid, const SID * gsid); +struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid); +struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem); +struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem); +void ntfs_free_mapping(struct MAPPING *mapping[]); + +#endif /* ACLS_H */ + diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/attrib.h b/release/src/router/ntfs-3g/include/ntfs-3g/attrib.h index 360962392e..a11f7b6bb8 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/attrib.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/attrib.h @@ -37,6 +37,7 @@ typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx; #include "logging.h" extern ntfschar AT_UNNAMED[]; +extern ntfschar STREAM_SDS[]; /** * enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn() @@ -174,6 +175,7 @@ struct _ntfs_attr { runlist_element *rl; ntfs_inode *ni; ATTR_TYPES type; + ATTR_FLAGS data_flags; ntfschar *name; u32 name_len; unsigned long state; @@ -245,11 +247,14 @@ typedef union { } attr_val; extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, - const BOOL compressed, const BOOL encrypted, const BOOL sparse, + const ATTR_FLAGS data_flags, const BOOL encrypted, + const BOOL sparse, const s64 allocated_size, const s64 data_size, const s64 initialized_size, const s64 compressed_size, const u8 compression_unit); + /* warning : in the following "name" has to be freeable */ + /* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */ extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, u32 name_len); extern void ntfs_attr_close(ntfs_attr *na); @@ -258,6 +263,7 @@ extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b); extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b); +extern int ntfs_attr_pclose(ntfs_attr *na); extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, u32 name_len, s64 *data_size); @@ -279,7 +285,8 @@ extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type); extern int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type); - +int ntfs_attr_make_non_resident(ntfs_attr *na, + ntfs_attr_search_ctx *ctx); extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size); extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, @@ -292,6 +299,8 @@ extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx); extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, ntfschar *name, u8 name_len, u8 *val, s64 size); +extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, + ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask); extern int ntfs_attr_rm(ntfs_attr *na); extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/compress.h b/release/src/router/ntfs-3g/include/ntfs-3g/compress.h index 83eb490da2..809c3c93b4 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/compress.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/compress.h @@ -29,5 +29,11 @@ extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b); +extern s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *brl, s64 wpos, + s64 offs, s64 to_write, s64 rounded, + const void *b, int compressed_part); + +extern int ntfs_compressed_close(ntfs_attr *na, runlist_element *brl, s64 offs); + #endif /* defined _NTFS_COMPRESS_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/dir.h b/release/src/router/ntfs-3g/include/ntfs-3g/dir.h index 2f5f76e636..49f706fb9c 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/dir.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/dir.h @@ -64,15 +64,15 @@ extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, const char *pathname); - -extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type); -extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, - ntfschar *name, u8 name_len, dev_t type, dev_t dev); -extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, +extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, + ntfschar *name, u8 name_len, mode_t type); +extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, + ntfschar *name, u8 name_len, mode_t type, dev_t dev); +extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, ntfschar *name, u8 name_len, ntfschar *target, int target_len); extern int ntfs_check_empty_dir(ntfs_inode *ni); -extern int ntfs_delete(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, +extern int ntfs_delete(ntfs_volume *vol, const char *path, + ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len); extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, @@ -104,5 +104,12 @@ typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name, extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, void *dirent, ntfs_filldir_t filldir); +int ntfs_get_ntfs_dos_name(const char *path, + char *value, size_t size, ntfs_inode *ni); +int ntfs_set_ntfs_dos_name(const char *path, + const char *value, size_t size, int flags, + ntfs_inode *ni); +int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni); + #endif /* defined _NTFS_DIR_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/compress.h b/release/src/router/ntfs-3g/include/ntfs-3g/efs.h similarity index 69% copy from release/src/router/ntfs-3g/include/ntfs-3g/compress.h copy to release/src/router/ntfs-3g/include/ntfs-3g/efs.h index 83eb490da2..bb28e3c747 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/compress.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/efs.h @@ -1,8 +1,6 @@ /* - * compress.h - Exports for compressed attribute handling. - * Originated from the Linux-NTFS project. * - * Copyright (c) 2004 Anton Altaparmakov + * Copyright (c) 2009 Martin Bene * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -20,14 +18,14 @@ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _NTFS_COMPRESS_H -#define _NTFS_COMPRESS_H +#ifndef EFS_H +#define EFS_H -#include "types.h" -#include "attrib.h" - -extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, - void *b); - -#endif /* defined _NTFS_COMPRESS_H */ +int ntfs_get_efs_info(const char *path, + char *value, size_t size, ntfs_inode *ni); +int ntfs_set_efs_info(const char *path, + const char *value, size_t size, int flags, + ntfs_inode *ni); +int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na); +#endif /* EFS_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/index.h b/release/src/router/ntfs-3g/include/ntfs-3g/index.h index d4c4055bdd..75e7b1066c 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/index.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/index.h @@ -25,6 +25,34 @@ #ifndef _NTFS_INDEX_H #define _NTFS_INDEX_H +/* Convenience macros to test the versions of gcc. + * Use them like this: + * #if __GNUC_PREREQ (2,8) + * ... code requiring gcc 2.8 or later ... + * #endif + * Note - they won't work for gcc1 or glibc1, since the _MINOR macros + * were not defined then. + */ + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +/* allows us to warn about unused results of certain function calls */ +#ifndef __attribute_warn_unused_result__ +# if __GNUC_PREREQ (3,4) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# else +# define __attribute_warn_unused_result__ /* empty */ +# endif +#endif + #include "attrib.h" #include "types.h" #include "layout.h" @@ -108,11 +136,15 @@ extern void ntfs_index_ctx_put(ntfs_index_context *ictx); extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx); extern int ntfs_index_lookup(const void *key, const int key_len, + ntfs_index_context *ictx) __attribute_warn_unused_result__; + +extern INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie, ntfs_index_context *ictx); extern int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref); -extern int ntfs_index_remove(ntfs_inode *ni, const void *key, const int keylen); +extern int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni, + const void *key, const int keylen); extern INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr); @@ -124,5 +156,9 @@ extern char *ntfs_ie_filename_get(INDEX_ENTRY *ie); extern void ntfs_ie_filename_dump(INDEX_ENTRY *ie); extern void ntfs_ih_filename_dump(INDEX_HEADER *ih); +/* the following was added by JPA for use in security.c */ +extern int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie); +extern int ntfs_index_rm(ntfs_index_context *icx); + #endif /* _NTFS_INDEX_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/inode.h b/release/src/router/ntfs-3g/include/ntfs-3g/inode.h index c7f1186e20..3abc878c9e 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/inode.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/inode.h @@ -48,6 +48,8 @@ typedef enum { mft record and then to disk. */ NI_FileNameDirty, /* 1: FILE_NAME attributes need to be updated in the index. */ + NI_v3_Extensions, /* 1: JPA v3.x extensions present. */ + NI_TimesDirty, /* 1: Times need to be updated */ } ntfs_inode_state_bits; #define test_nino_flag(ni, flag) test_bit(NI_##flag, (ni)->state) @@ -151,6 +153,12 @@ struct _ntfs_inode { time_t last_data_change_time; time_t last_mft_change_time; time_t last_access_time; + /* NTFS 3.x extensions added by JPA */ + /* only if NI_v3_Extensions is set in state */ + le32 owner_id; + le32 security_id; + le64 quota_charged; + le64 usn; }; typedef enum { @@ -187,4 +195,9 @@ extern int ntfs_inode_free_space(ntfs_inode *ni, int size); extern int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *a); +extern int ntfs_inode_get_times(const char *path, char *value, + size_t size, ntfs_inode *ni); +extern int ntfs_inode_set_times(const char *path, const char *value, + size_t size, int flags, ntfs_inode *ni); + #endif /* defined _NTFS_INODE_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/misc.h b/release/src/router/ntfs-3g/include/ntfs-3g/misc.h index 67cc1eb670..dbdee9a9ee 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/misc.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/misc.h @@ -1,6 +1,72 @@ +/* + * misc.h : miscellaneous exports + * - memory allocation + * - LRU caches + * + * Copyright (c) 2008 Jean-Pierre Andre + * + * This program/include file 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/include file 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifndef _NTFS_MISC_H_ #define _NTFS_MISC_H_ +#include "volume.h" + +struct CACHED_GENERIC { + struct CACHED_GENERIC *next; + void *variable; + size_t varsize; + void *fixed[0]; +} ; + +struct CACHED_INODE { + struct CACHED_INODE *next; + const char *pathname; + size_t varsize; + /* above fields must match "struct CACHED_GENERIC" */ + u64 inum; +} ; + +typedef int (*cache_compare)(const struct CACHED_GENERIC *cached, + const struct CACHED_GENERIC *item); + +struct CACHE_HEADER { + const char *name; + struct CACHED_GENERIC *most_recent_entry; + struct CACHED_GENERIC *free_entry; + unsigned long reads; + unsigned long writes; + unsigned long hits; + int fixed_size; + struct CACHED_GENERIC entry[0]; +} ; + + /* cast to generic, avoiding gcc warnings */ +#define GENERIC(pstr) ((const struct CACHED_GENERIC*)(const void*)(pstr)) + +struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *wanted, cache_compare compare); +struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *item, cache_compare compare); +int ntfs_invalidate_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *item, cache_compare compare); +void ntfs_create_lru_caches(ntfs_volume *vol); +void ntfs_free_lru_caches(ntfs_volume *vol); + void *ntfs_calloc(size_t size); void *ntfs_malloc(size_t size); diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/reparse.h b/release/src/router/ntfs-3g/include/ntfs-3g/reparse.h new file mode 100644 index 0000000000..91ede03ef2 --- /dev/null +++ b/release/src/router/ntfs-3g/include/ntfs-3g/reparse.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 2008 Jean-Pierre Andre + * + */ + +/* + * 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef REPARSE_H +#define REPARSE_H + +char *ntfs_make_symlink(const char *org_path, + ntfs_inode *ni, int *pattr_size); +BOOL ntfs_possible_symlink(ntfs_inode *ni); + +int ntfs_get_ntfs_reparse_data(const char *path, + char *value, size_t size, ntfs_inode *ni); +int ntfs_set_ntfs_reparse_data(const char *path, const char *value, + size_t size, int flags, ntfs_inode *ni); +int ntfs_remove_ntfs_reparse_data(const char *path, ntfs_inode *ni); + +int ntfs_delete_reparse_index(ntfs_inode *ni); + +#endif /* REPARSE_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/runlist.h b/release/src/router/ntfs-3g/include/ntfs-3g/runlist.h index 11950e1927..43de53cc8d 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/runlist.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/runlist.h @@ -49,12 +49,14 @@ struct _runlist_element {/* In memory vcn to lcn mapping structure element. */ s64 length; /* Run length in clusters. */ }; +extern runlist_element *ntfs_rl_extend(runlist_element *rl, int more_entries); + extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn); extern s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl, const s64 pos, s64 count, void *b); extern s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b); + s64 ofs, const s64 pos, s64 count, void *b); extern runlist_element *ntfs_runlists_merge(runlist_element *drl, runlist_element *srl); @@ -65,14 +67,14 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, extern int ntfs_get_nr_significant_bytes(const s64 n); extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, - const runlist_element *rl, const VCN start_vcn); + const runlist_element *rl, const VCN start_vcn, int max_size); extern int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, const s64 n); extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, const int dst_len, const runlist_element *rl, - const VCN start_vcn, VCN *const stop_vcn); + const VCN start_vcn, runlist_element const **stop_rl); extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn); diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/security.h b/release/src/router/ntfs-3g/include/ntfs-3g/security.h index 04cc30a9d2..eaa67b4153 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/security.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/security.h @@ -4,6 +4,7 @@ * * Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2005-2006 Szabolcs Szakacsits + * Copyright (c) 2007-2008 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -27,8 +28,187 @@ #include "types.h" #include "layout.h" #include "inode.h" +#include "dir.h" -extern const GUID *const zero_guid; +#ifndef POSIXACLS +#define POSIXACLS 0 +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define const_cpu_to_be16(x) ((((x) & 255L) << 8) + (((x) >> 8) & 255L)) +#define const_cpu_to_be32(x) ((((x) & 255L) << 24) + (((x) & 0xff00L) << 8) \ + + (((x) >> 8) & 0xff00L) + (((x) >> 24) & 255L)) +#else +#define const_cpu_to_be16(x) (x) +#define const_cpu_to_be32(x) (x) +#endif + +/* + * item in the mapping list + */ + +struct MAPPING { + struct MAPPING *next; + int xid; /* linux id : uid or gid */ + SID *sid; /* Windows id : usid or gsid */ + int grcnt; /* group count (for users only) */ + gid_t *groups; /* groups which the user is member of */ +}; + +/* + * Entry in the permissions cache + * Note : this cache is not organized as a generic cache + */ + +struct CACHED_PERMISSIONS { + uid_t uid; + gid_t gid; + le32 inh_fileid; + le32 inh_dirid; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; + unsigned int pxdescsize:16; +#endif + unsigned int mode:12; + unsigned int valid:1; +} ; + +/* + * Entry in the permissions cache for directories with no security_id + */ + +struct CACHED_PERMISSIONS_LEGACY { + struct CACHED_PERMISSIONS_LEGACY *next; + void *variable; + size_t varsize; + /* above fields must match "struct CACHED_GENERIC" */ + u64 mft_no; + struct CACHED_PERMISSIONS perm; +} ; + +/* + * Entry in the securid cache + */ + +struct CACHED_SECURID { + struct CACHED_SECURID *next; + void *variable; + size_t varsize; + /* above fields must match "struct CACHED_GENERIC" */ + uid_t uid; + gid_t gid; + unsigned int dmode; + le32 securid; +} ; + +/* + * Header of the security cache + * (has no cache structure by itself) + */ + +struct CACHED_PERMISSIONS_HEADER { + unsigned int last; + /* statistics for permissions */ + unsigned long p_writes; + unsigned long p_reads; + unsigned long p_hits; +} ; + +/* + * The whole permissions cache + */ + +struct PERMISSIONS_CACHE { + struct CACHED_PERMISSIONS_HEADER head; + struct CACHED_PERMISSIONS *cachetable[1]; /* array of variable size */ +} ; + +/* + * Security flags values + */ + +enum { + SECURITY_DEFAULT, /* rely on fuse for permissions checking */ + SECURITY_RAW, /* force same ownership/permissions on files */ + SECURITY_ADDSECURIDS, /* upgrade old security descriptors */ + SECURITY_STATICGRPS, /* use static groups for access control */ + SECURITY_WANTED /* a security related option was present */ +} ; + +/* + * Security context, needed by most security functions + */ + +enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ; + +struct SECURITY_CONTEXT { + ntfs_volume *vol; + struct MAPPING *mapping[MAPCOUNT]; + struct PERMISSIONS_CACHE **pseccache; + uid_t uid; /* uid of user requesting (not the mounter) */ + gid_t gid; /* gid of user requesting (not the mounter) */ + pid_t tid; /* thread id of thread requesting */ + mode_t umask; /* umask of requesting thread */ + } ; + +#if POSIXACLS + +/* + * Posix ACL structures + */ + +struct POSIX_ACE { + u16 tag; + u16 perms; + s32 id; +} ; + +struct POSIX_ACL { + u8 version; + u8 flags; + u16 filler; + struct POSIX_ACE ace[0]; +} ; + +struct POSIX_SECURITY { + mode_t mode; + int acccnt; + int defcnt; + int firstdef; + u16 tagsset; + struct POSIX_ACL acl; +} ; + +/* + * Posix tags, cpu-endian 16 bits + */ + +enum { + POSIX_ACL_USER_OBJ = 1, + POSIX_ACL_USER = 2, + POSIX_ACL_GROUP_OBJ = 4, + POSIX_ACL_GROUP = 8, + POSIX_ACL_MASK = 16, + POSIX_ACL_OTHER = 32, + POSIX_ACL_SPECIAL = 64 /* internal use only */ +} ; + +#define POSIX_ACL_EXTENSIONS (POSIX_ACL_USER | POSIX_ACL_GROUP | POSIX_ACL_MASK) + +/* + * Posix permissions, cpu-endian 16 bits + */ + +enum { + POSIX_PERM_X = 1, + POSIX_PERM_W = 2, + POSIX_PERM_R = 4, + POSIX_PERM_DENIAL = 64 /* internal use only */ +} ; + +#define POSIX_VERSION 2 + +#endif extern BOOL ntfs_guid_is_zero(const GUID *guid); extern char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str); @@ -58,4 +238,117 @@ extern int ntfs_sd_add_everyone(ntfs_inode *ni); extern le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len); +int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path); +int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, struct stat*); +int ntfs_set_mode(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, mode_t mode); +BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni); +int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, const char *path, + ntfs_inode *ni, int accesstype); +BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, + const char *path, int accesstype); + +#if POSIXACLS +le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, + uid_t uid, gid_t gid, const char *dir_path, + ntfs_inode *dir_ni, mode_t mode, BOOL isdir); +#else +le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, + uid_t uid, gid_t gid, mode_t mode, BOOL isdir); +#endif +int ntfs_set_owner(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, uid_t uid, gid_t gid); +#if POSIXACLS +int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, + mode_t mode, struct POSIX_SECURITY *pxdesc); +#else +int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode); +#endif +le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, + const char *dir_path, ntfs_inode *dir_ni, BOOL fordir); +int ntfs_open_secure(ntfs_volume *vol); +void ntfs_close_secure(struct SECURITY_CONTEXT *scx); + +#if POSIXACLS + +int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, + const char *dir_path, ntfs_inode *dir_ni, mode_t mode); +int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, char *value, size_t size, + ntfs_inode *ni); +int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, const char *value, size_t size, + int flags, ntfs_inode *ni); +int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, ntfs_inode *ni); +#endif + +int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, char *value, size_t size, + ntfs_inode *ni); +int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, const char *value, size_t size, + int flags, ntfs_inode *ni); +int ntfs_get_ntfs_attrib(const char *path, + char *value, size_t size, ntfs_inode *ni); +int ntfs_set_ntfs_attrib(const char *path, + const char *value, size_t size, int flags, + ntfs_inode *ni); + +/* + * Security API for direct access to security descriptors + * based on Win32 API + */ + +#define MAGIC_API 0x09042009 + +struct SECURITY_API { + u32 magic; + struct SECURITY_CONTEXT security; + struct PERMISSIONS_CACHE *seccache; +} ; + +/* + * The following constants are used in interfacing external programs. + * They are not to be stored on disk and must be defined in their + * native cpu representation. + * When disk representation (le) is needed, use SE_DACL_PRESENT, etc. + */ +enum { OWNER_SECURITY_INFORMATION = 1, + GROUP_SECURITY_INFORMATION = 2, + DACL_SECURITY_INFORMATION = 4, + SACL_SECURITY_INFORMATION = 8 +} ; + +int ntfs_get_file_security(struct SECURITY_API *scapi, + const char *path, u32 selection, + char *buf, u32 buflen, u32 *psize); +int ntfs_set_file_security(struct SECURITY_API *scapi, + const char *path, u32 selection, const char *attr); +int ntfs_get_file_attributes(struct SECURITY_API *scapi, + const char *path); +BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi, + const char *path, s32 attrib); +BOOL ntfs_read_directory(struct SECURITY_API *scapi, + const char *path, ntfs_filldir_t callback, void *context); +int ntfs_read_sds(struct SECURITY_API *scapi, + char *buf, u32 size, u32 offset); +INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi, + INDEX_ENTRY *entry); +INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi, + INDEX_ENTRY *entry); +struct SECURITY_API *ntfs_initialize_file_security(const char *device, + int flags); +BOOL ntfs_leave_file_security(struct SECURITY_API *scx); + +int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf); +int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf); +int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid); +int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid); + #endif /* defined _NTFS_SECURITY_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/unistr.h b/release/src/router/ntfs-3g/include/ntfs-3g/unistr.h index 6de4bacc52..115a8650fb 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/unistr.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/unistr.h @@ -65,5 +65,52 @@ extern ntfschar *ntfs_str2ucs(const char *s, int *len); extern void ntfs_ucsfree(ntfschar *ucs); +extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len); +extern BOOL ntfs_collapsible_chars(ntfs_volume *vol, + const ntfschar *shortname, int shortlen, + const ntfschar *longname, int longlen); + +extern int ntfs_set_char_encoding(const char *locale); + +#if defined(__APPLE__) || defined(__DARWIN__) +/** + * Mac OS X only. + * + * Sets file name Unicode normalization form conversion on or off. + * normalize=0 : Off + * normalize=1 : On + * If set to on, all filenames returned by ntfs-3g will be converted to the NFD + * normalization form, while all filenames recieved by ntfs-3g will be converted to the NFC + * normalization form. Since Windows and most other OS:es use the NFC form while Mac OS X + * mostly uses NFD, this conversion increases compatibility between Mac applications and + * NTFS-3G. + * + * @param normalize decides whether or not the string functions will do automatic filename + * normalization when converting to and from UTF-8. 0 means normalization is disabled, + * 1 means it is enabled. + * @return -1 if the argument was invalid or an error occurred, 0 if all went well. + */ +extern int ntfs_macosx_normalize_filenames(int normalize); + +/** + * Mac OS X only. + * + * Normalizes the input string "utf8_string" to one of the normalization forms NFD or NFC. + * The parameter "composed" decides whether output should be in composed, NFC, form + * (composed == 1) or decomposed, NFD, form (composed == 0). + * Input is assumed to be properly UTF-8 encoded and null-terminated. Output will be a newly + * ntfs_calloc'ed string encoded in UTF-8. It is the callers responsibility to free(...) the + * allocated string when it's no longer needed. + * + * @param utf8_string the input string, which may be in any normalization form. + * @param target a pointer where the resulting string will be stored. + * @param composed decides which composition form to normalize the input string to. 0 means + * composed form (NFC), 1 means decomposed form (NFD). + * @return -1 if the normalization failed for some reason, otherwise the length of the + * normalized string stored in target. + */ +extern int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, int composed); +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + #endif /* defined _NTFS_UNISTR_H */ diff --git a/release/src/router/ntfs-3g/include/ntfs-3g/volume.h b/release/src/router/ntfs-3g/include/ntfs-3g/volume.h index 8ebef49fa1..a0c71bdf7e 100644 --- a/release/src/router/ntfs-3g/include/ntfs-3g/volume.h +++ b/release/src/router/ntfs-3g/include/ntfs-3g/volume.h @@ -42,6 +42,10 @@ #include #endif +#define CACHE_INODE_SIZE 32 /* inode cache, zero or >= 3 and not too big */ +#define CACHE_SECURID_SIZE 16 /* securid cache, zero or >= 3 and not too big */ +#define CACHE_LEGACY_SIZE 8 /* legacy cache size, zero or >= 3 and not too big */ + /* * Under Cygwin, DJGPP and FreeBSD we do not have MS_RDONLY, * so we define them ourselves. @@ -66,6 +70,7 @@ typedef struct _ntfs_volume ntfs_volume; #include "device.h" #include "inode.h" #include "attrib.h" +#include "index.h" /** * enum ntfs_mount_flags - @@ -167,6 +172,7 @@ struct _ntfs_volume { /* Variables used by the cluster and mft allocators. */ u8 mft_zone_multiplier; /* Initial mft zone multiplier. */ + u8 full_zones; /* cluster zones which are full */ s64 mft_data_pos; /* Mft record number at which to allocate the next mft record. */ LCN mft_zone_start; /* First cluster of the mft zone. */ @@ -196,6 +202,12 @@ struct _ntfs_volume { bit means that the mft record is in use and vice versa. */ + ntfs_inode *secure_ni; /* ntfs_inode structure for FILE $Secure */ + ntfs_index_context *secure_xsii; /* index for using $Secure:$SII */ + ntfs_index_context *secure_xsdh; /* index for using $Secure:$SDH */ + int secure_reentry; /* check for non-rentries */ + unsigned int secure_flags; /* flags, see security.h for values */ + int mftmirr_size; /* Size of the FILE_MFTMirr in mft records. */ LCN mftmirr_lcn; /* Logical cluster number of the data attribute for FILE_MFTMirr. */ @@ -217,6 +229,19 @@ struct _ntfs_volume { s64 free_clusters; /* Track the number of free clusters which greatly improves statfs() performance */ s64 free_mft_records; /* Same for free mft records (see above) */ + BOOL efs_raw; /* volume is mounted for raw access to + efs-encrypted files */ + +#if CACHE_INODE_SIZE + struct CACHE_HEADER *xinode_cache; +#endif +#if CACHE_SECURID_SIZE + struct CACHE_HEADER *securid_cache; +#endif +#if CACHE_LEGACY_SIZE + struct CACHE_HEADER *legacy_cache; +#endif + }; extern const char *ntfs_home; @@ -241,6 +266,8 @@ extern int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags); extern int ntfs_volume_error(int err); extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err); +extern int ntfs_volume_get_free_space(ntfs_volume *vol); + extern int ntfs_set_locale(void); #endif /* defined _NTFS_VOLUME_H */ diff --git a/release/src/router/ntfs-3g/install-sh b/release/src/router/ntfs-3g/install-sh index 4d4a9519ea..a5897de6ea 100755 --- a/release/src/router/ntfs-3g/install-sh +++ b/release/src/router/ntfs-3g/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2005-05-14.22 +scriptversion=2006-12-25.00 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -39,38 +39,68 @@ scriptversion=2005-05-14.22 # when there is no Makefile. # # This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. +# from scratch. + +nl=' +' +IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi -# put in absolute paths if you don't have them in your path; or use env. vars. +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" +posix_mkdir= + +# Desired mode of installed file. +mode=0755 -chmodcmd="$chmodprog 0755" -chowncmd= chgrpcmd= -stripcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog rmcmd="$rmprog -f" -mvcmd="$mvprog" +stripcmd= + src= dst= dir_arg= -dstarg= +dst_arg= + +copy_on_change=false no_target_directory= -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... @@ -80,81 +110,86 @@ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG " -while test -n "$1"; do +while test $# -ne 0; do case $1 in - -c) shift - continue;; + -c) ;; + + -C) copy_on_change=true;; - -d) dir_arg=true - shift - continue;; + -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; + shift;; --help) echo "$usage"; exit $?;; - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift - shift - continue;; + shift;; - -s) stripcmd=$stripprog - shift - continue;; + -s) stripcmd=$stripprog;; - -t) dstarg=$2 - shift - shift - continue;; + -t) dst_arg=$2 + shift;; - -T) no_target_directory=true - shift - continue;; + -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done + --) shift break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; esac + shift done -if test -z "$1"; then +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 @@ -164,24 +199,47 @@ if test -z "$1"; then exit 0 fi +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + for src do # Protect names starting with `-'. case $src in - -*) src=./$src ;; + -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. @@ -190,71 +248,199 @@ do exit 1 fi - if test -z "$dstarg"; then + if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi - dst=$dstarg + dst=$dst_arg # Protect names starting with `-'. case $dst in - -*) dst=./$dst ;; + -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 + echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi - dst=$dst/`basename "$src"` + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? fi fi - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac - # Make sure that the destination directory exists. + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - shift - IFS=$oIFS + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac - pathcomp= + eval "$initialize_posix_glob" - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi - pathcomp=$pathcomp/ - done + fi fi if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else - dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ @@ -262,10 +448,9 @@ do # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -273,48 +458,59 @@ do # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit 1 - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit 1; } + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi done -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit 0 -} - # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" diff --git a/release/src/router/ntfs-3g/libfuse-lite/Makefile.in b/release/src/router/ntfs-3g/libfuse-lite/Makefile.in index 8543c57799..155b477c69 100644 --- a/release/src/router/ntfs-3g/libfuse-lite/Makefile.in +++ b/release/src/router/ntfs-3g/libfuse-lite/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -14,15 +14,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -57,26 +53,28 @@ am_libfuse_lite_la_OBJECTS = libfuse_lite_la-fuse.lo \ libfuse_lite_la-helper.lo libfuse_lite_la-mount.lo \ libfuse_lite_la-mount_util.lo libfuse_lite_la_OBJECTS = $(am_libfuse_lite_la_OBJECTS) +libfuse_lite_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libfuse_lite_la_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ @FUSE_INTERNAL_TRUE@am_libfuse_lite_la_rpath = -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ SOURCES = $(libfuse_lite_la_SOURCES) DIST_SOURCES = $(libfuse_lite_la_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -95,26 +93,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -128,13 +120,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -146,25 +135,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -176,6 +159,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -208,12 +192,15 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in @FUSE_INTERNAL_TRUE@noinst_LTLIBRARIES = libfuse-lite.la libfuse_lite_la_CFLAGS = \ @@ -280,7 +267,7 @@ clean-noinstLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libfuse-lite.la: $(libfuse_lite_la_OBJECTS) $(libfuse_lite_la_DEPENDENCIES) - $(LINK) $(am_libfuse_lite_la_rpath) $(libfuse_lite_la_LDFLAGS) $(libfuse_lite_la_OBJECTS) $(libfuse_lite_la_LIBADD) $(LIBS) + $(libfuse_lite_la_LINK) $(am_libfuse_lite_la_rpath) $(libfuse_lite_la_OBJECTS) $(libfuse_lite_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -301,102 +288,102 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfuse_lite_la-mount_util.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libfuse_lite_la-fuse.lo: fuse.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse.Tpo" -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse.Tpo -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse.Tpo $(DEPDIR)/libfuse_lite_la-fuse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse.c' object='libfuse_lite_la-fuse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse.lo `test -f 'fuse.c' || echo '$(srcdir)/'`fuse.c libfuse_lite_la-fuse_kern_chan.lo: fuse_kern_chan.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_kern_chan.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo" -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_kern_chan.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Tpo $(DEPDIR)/libfuse_lite_la-fuse_kern_chan.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_kern_chan.c' object='libfuse_lite_la-fuse_kern_chan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_kern_chan.lo `test -f 'fuse_kern_chan.c' || echo '$(srcdir)/'`fuse_kern_chan.c libfuse_lite_la-fuse_loop.lo: fuse_loop.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_loop.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo" -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_loop.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_loop.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_loop.Tpo $(DEPDIR)/libfuse_lite_la-fuse_loop.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_loop.c' object='libfuse_lite_la-fuse_loop.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_loop.lo `test -f 'fuse_loop.c' || echo '$(srcdir)/'`fuse_loop.c libfuse_lite_la-fuse_lowlevel.lo: fuse_lowlevel.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_lowlevel.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo" -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_lowlevel.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Tpo $(DEPDIR)/libfuse_lite_la-fuse_lowlevel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_lowlevel.c' object='libfuse_lite_la-fuse_lowlevel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_lowlevel.lo `test -f 'fuse_lowlevel.c' || echo '$(srcdir)/'`fuse_lowlevel.c libfuse_lite_la-fuse_opt.lo: fuse_opt.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_opt.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo" -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_opt.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_opt.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_opt.Tpo $(DEPDIR)/libfuse_lite_la-fuse_opt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_opt.c' object='libfuse_lite_la-fuse_opt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_opt.lo `test -f 'fuse_opt.c' || echo '$(srcdir)/'`fuse_opt.c libfuse_lite_la-fuse_session.lo: fuse_session.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_session.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_session.Tpo" -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_session.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_session.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_session.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_session.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_session.Tpo -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_session.Tpo $(DEPDIR)/libfuse_lite_la-fuse_session.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_session.c' object='libfuse_lite_la-fuse_session.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_session.lo `test -f 'fuse_session.c' || echo '$(srcdir)/'`fuse_session.c libfuse_lite_la-fuse_signals.lo: fuse_signals.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_signals.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo" -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo" "$(DEPDIR)/libfuse_lite_la-fuse_signals.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fuse_signals.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fuse_signals.Tpo $(DEPDIR)/libfuse_lite_la-fuse_signals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fuse_signals.c' object='libfuse_lite_la-fuse_signals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fuse_signals.lo `test -f 'fuse_signals.c' || echo '$(srcdir)/'`fuse_signals.c libfuse_lite_la-fusermount.lo: fusermount.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fusermount.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-fusermount.Tpo" -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-fusermount.Tpo" "$(DEPDIR)/libfuse_lite_la-fusermount.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-fusermount.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-fusermount.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-fusermount.Tpo -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-fusermount.Tpo $(DEPDIR)/libfuse_lite_la-fusermount.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fusermount.c' object='libfuse_lite_la-fusermount.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-fusermount.lo `test -f 'fusermount.c' || echo '$(srcdir)/'`fusermount.c libfuse_lite_la-helper.lo: helper.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-helper.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-helper.Tpo" -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-helper.Tpo" "$(DEPDIR)/libfuse_lite_la-helper.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-helper.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-helper.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-helper.Tpo -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-helper.Tpo $(DEPDIR)/libfuse_lite_la-helper.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='helper.c' object='libfuse_lite_la-helper.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-helper.lo `test -f 'helper.c' || echo '$(srcdir)/'`helper.c libfuse_lite_la-mount.lo: mount.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-mount.Tpo" -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-mount.Tpo" "$(DEPDIR)/libfuse_lite_la-mount.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-mount.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-mount.Tpo -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-mount.Tpo $(DEPDIR)/libfuse_lite_la-mount.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mount.c' object='libfuse_lite_la-mount.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c libfuse_lite_la-mount_util.lo: mount_util.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount_util.lo -MD -MP -MF "$(DEPDIR)/libfuse_lite_la-mount_util.Tpo" -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libfuse_lite_la-mount_util.Tpo" "$(DEPDIR)/libfuse_lite_la-mount_util.Plo"; else rm -f "$(DEPDIR)/libfuse_lite_la-mount_util.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -MT libfuse_lite_la-mount_util.lo -MD -MP -MF $(DEPDIR)/libfuse_lite_la-mount_util.Tpo -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libfuse_lite_la-mount_util.Tpo $(DEPDIR)/libfuse_lite_la-mount_util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mount_util.c' object='libfuse_lite_la-mount_util.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfuse_lite_la_CFLAGS) $(CFLAGS) -c -o libfuse_lite_la-mount_util.lo `test -f 'mount_util.c' || echo '$(srcdir)/'`mount_util.c mostlyclean-libtool: -rm -f *.lo @@ -404,17 +391,13 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -distclean-libtool: - -rm -f libtool -uninstall-info-am: - ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -426,8 +409,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -437,13 +420,12 @@ ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -457,22 +439,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -521,7 +502,7 @@ distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags + distclean-tags dvi: dvi-am @@ -535,12 +516,20 @@ info-am: install-data-am: +install-dvi: install-dvi-am + 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 + installcheck-am: maintainer-clean: maintainer-clean-am @@ -561,19 +550,22 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am +uninstall-am: + +.MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES ctags 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-exec \ - install-exec-am install-info install-info-am install-man \ + 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 uninstall uninstall-am \ - uninstall-info-am + pdf pdf-am ps ps-am tags uninstall uninstall-am # 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. diff --git a/release/src/router/ntfs-3g/libfuse-lite/fuse.c b/release/src/router/ntfs-3g/libfuse-lite/fuse.c index 11be5b1bab..f41e8a6b69 100644 --- a/release/src/router/ntfs-3g/libfuse-lite/fuse.c +++ b/release/src/router/ntfs-3g/libfuse-lite/fuse.c @@ -1021,6 +1021,9 @@ static struct fuse *req_fuse_prepare(fuse_req_t req) c->ctx.uid = ctx->uid; c->ctx.gid = ctx->gid; c->ctx.pid = ctx->pid; +#ifdef POSIXACLS + c->ctx.umask = ctx->umask; +#endif return c->ctx.fuse; } diff --git a/release/src/router/ntfs-3g/libfuse-lite/fuse_lowlevel.c b/release/src/router/ntfs-3g/libfuse-lite/fuse_lowlevel.c index 7295832b76..fdd18152f2 100644 --- a/release/src/router/ntfs-3g/libfuse-lite/fuse_lowlevel.c +++ b/release/src/router/ntfs-3g/libfuse-lite/fuse_lowlevel.c @@ -22,7 +22,7 @@ #include #include -#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) +#define PARAM(inarg) (((const char *)(inarg)) + sizeof(*(inarg))) #define OFFSET_MAX 0x7fffffffffffffffLL struct fuse_ll; @@ -78,6 +78,9 @@ static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) attr->atimensec = ST_ATIM_NSEC(stbuf); attr->mtimensec = ST_MTIM_NSEC(stbuf); attr->ctimensec = ST_CTIM_NSEC(stbuf); +#ifdef POSIXACLS + attr->filling = 0; /* JPA trying to be safe */ +#endif } static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) @@ -189,6 +192,24 @@ static int send_reply(fuse_req_t req, int error, const void *arg, return send_reply_iov(req, error, iov, count); } +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) +{ + int res; + struct iovec *padded_iov; + + padded_iov = malloc((count + 1) * sizeof(struct iovec)); + if (padded_iov == NULL) + return fuse_reply_err(req, -ENOMEM); + + memcpy(padded_iov + 1, iov, count * sizeof(struct iovec)); + count++; + + res = send_reply_iov(req, 0, padded_iov, count); + free(padded_iov); + + return res; +} + size_t fuse_dirent_size(size_t namelen) { return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen); @@ -267,7 +288,8 @@ static unsigned long calc_timeout_sec(double t) static unsigned int calc_timeout_nsec(double t) { - double f = t - (double) calc_timeout_sec(t); + unsigned long secs = calc_timeout_sec(t); + double f = t - (double)secs; if (f < 0.0) return 0; else if (f >= 0.999999999) @@ -309,7 +331,12 @@ int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e) memset(&arg, 0, sizeof(arg)); fill_entry(&arg, e); +#ifdef POSIXACLS + return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 + ? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE)); +#else return send_reply_ok(req, &arg, sizeof(arg)); +#endif } int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, @@ -322,8 +349,20 @@ int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, memset(&arg, 0, sizeof(arg)); fill_entry(&arg.e, e); +#ifdef POSIXACLS + if (req->f->conn.proto_minor < 12) { + fill_open((struct fuse_open_out*) + ((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f); + return send_reply_ok(req, &arg, + FUSE_COMPAT_ENTRY_OUT_SIZE + sizeof(struct fuse_open_out)); + } else { + fill_open(&arg.o, f); + return send_reply_ok(req, &arg, sizeof(arg)); + } +#else fill_open(&arg.o, f); return send_reply_ok(req, &arg, sizeof(arg)); +#endif } int fuse_reply_attr(fuse_req_t req, const struct stat *attr, @@ -336,7 +375,12 @@ int fuse_reply_attr(fuse_req_t req, const struct stat *attr, arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); convert_stat(attr, &arg.attr); +#ifdef POSIXACLS + return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 + ? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE)); +#else return send_reply_ok(req, &arg, sizeof(arg)); +#endif } int fuse_reply_readlink(fuse_req_t req, const char *linkname) @@ -418,7 +462,7 @@ int fuse_reply_bmap(fuse_req_t req, uint64_t idx) static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - char *name = (char *) inarg; + const char *name = (const char *) inarg; if (req->f->op.lookup) req->f->op.lookup(req, nodeid, name); @@ -428,7 +472,7 @@ static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg; + const struct fuse_forget_in *arg = (const struct fuse_forget_in *) inarg; if (req->f->op.forget) req->f->op.forget(req, nodeid, arg->nlookup); @@ -448,7 +492,7 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg; + const struct fuse_setattr_in *arg = (const struct fuse_setattr_in *) inarg; if (req->f->op.setattr) { struct fuse_file_info *fi = NULL; @@ -457,20 +501,19 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&stbuf, 0, sizeof(stbuf)); convert_attr(arg, &stbuf); if (arg->valid & FATTR_FH) { - arg->valid &= ~FATTR_FH; memset(&fi_store, 0, sizeof(fi_store)); fi = &fi_store; fi->fh = arg->fh; fi->fh_old = fi->fh; } - req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi); + req->f->op.setattr(req, nodeid, &stbuf, arg->valid & ~FATTR_FH, fi); } else fuse_reply_err(req, ENOSYS); } static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_access_in *arg = (struct fuse_access_in *) inarg; + const struct fuse_access_in *arg = (const struct fuse_access_in *) inarg; if (req->f->op.access) req->f->op.access(req, nodeid, arg->mask); @@ -490,17 +533,30 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg; + const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg; + const char *name = PARAM(arg); + +#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else +#endif + name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; if (req->f->op.mknod) - req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev); + req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev); else fuse_reply_err(req, ENOSYS); } static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg; + const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg; + +#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; +#endif if (req->f->op.mkdir) req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); @@ -510,7 +566,7 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - char *name = (char *) inarg; + const char *name = (const char *) inarg; if (req->f->op.unlink) req->f->op.unlink(req, nodeid, name); @@ -520,7 +576,7 @@ static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - char *name = (char *) inarg; + const char *name = (const char *) inarg; if (req->f->op.rmdir) req->f->op.rmdir(req, nodeid, name); @@ -530,8 +586,8 @@ static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - char *name = (char *) inarg; - char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1; + const char *name = (const char *) inarg; + const char *linkname = ((const char *) inarg) + strlen((const char *) inarg) + 1; if (req->f->op.symlink) req->f->op.symlink(req, linkname, nodeid, name); @@ -541,9 +597,9 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg; - char *oldname = PARAM(arg); - char *newname = oldname + strlen(oldname) + 1; + const struct fuse_rename_in *arg = (const struct fuse_rename_in *) inarg; + const char *oldname = PARAM(arg); + const char *newname = oldname + strlen(oldname) + 1; if (req->f->op.rename) req->f->op.rename(req, nodeid, oldname, arg->newdir, newname); @@ -553,7 +609,7 @@ static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_link_in *arg = (struct fuse_link_in *) inarg; + const struct fuse_link_in *arg = (const struct fuse_link_in *) inarg; if (req->f->op.link) req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg)); @@ -563,22 +619,30 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + const struct fuse_create_in *arg = (const struct fuse_create_in *) inarg; if (req->f->op.create) { struct fuse_file_info fi; + const char *name = PARAM(arg); memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; - req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi); +#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else +#endif + name = (const char *) inarg + sizeof(struct fuse_open_in); + + req->f->op.create(req, nodeid, name, arg->mode, &fi); } else fuse_reply_err(req, ENOSYS); } static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + const struct fuse_open_in *arg = (const struct fuse_open_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -592,7 +656,7 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + const struct fuse_read_in *arg = (const struct fuse_read_in *) inarg; if (req->f->op.read) { struct fuse_file_info fi; @@ -607,7 +671,7 @@ static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_write_in *arg = (struct fuse_write_in *) inarg; + const struct fuse_write_in *arg = (const struct fuse_write_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -615,15 +679,25 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fi.fh_old = fi.fh; fi.writepage = arg->write_flags & 1; - if (req->f->op.write) + if (req->f->op.write) { +#ifdef POSIXACLS + const char *buf; + + if (req->f->conn.proto_minor >= 12) + buf = PARAM(arg); + else + buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE; + req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi); +#else req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi); - else +#endif + } else fuse_reply_err(req, ENOSYS); } static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg; + const struct fuse_flush_in *arg = (const struct fuse_flush_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -641,7 +715,7 @@ static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_release_in *arg = (struct fuse_release_in *) inarg; + const struct fuse_release_in *arg = (const struct fuse_release_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -661,7 +735,7 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; + const struct fuse_fsync_in *arg = (const struct fuse_fsync_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -676,7 +750,7 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + const struct fuse_open_in *arg = (const struct fuse_open_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -690,7 +764,7 @@ static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + const struct fuse_read_in *arg = (const struct fuse_read_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -705,7 +779,7 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_release_in *arg = (struct fuse_release_in *) inarg; + const struct fuse_release_in *arg = (const struct fuse_release_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -721,7 +795,7 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; + const struct fuse_fsync_in *arg = (const struct fuse_fsync_in *) inarg; struct fuse_file_info fi; memset(&fi, 0, sizeof(fi)); @@ -752,9 +826,9 @@ static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg; - char *name = PARAM(arg); - char *value = name + strlen(name) + 1; + const struct fuse_setxattr_in *arg = (const struct fuse_setxattr_in *) inarg; + const char *name = PARAM(arg); + const char *value = name + strlen(name) + 1; if (req->f->op.setxattr) req->f->op.setxattr(req, nodeid, name, value, arg->size, arg->flags); @@ -764,7 +838,7 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; + const struct fuse_getxattr_in *arg = (const struct fuse_getxattr_in *) inarg; if (req->f->op.getxattr) req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size); @@ -774,7 +848,7 @@ static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; + const struct fuse_getxattr_in *arg = (const struct fuse_getxattr_in *) inarg; if (req->f->op.listxattr) req->f->op.listxattr(req, nodeid, arg->size); @@ -784,7 +858,7 @@ static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - char *name = (char *) inarg; + const char *name = (const char *) inarg; if (req->f->op.removexattr) req->f->op.removexattr(req, nodeid, name); @@ -792,7 +866,7 @@ static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } -static void convert_fuse_file_lock(struct fuse_file_lock *fl, +static void convert_fuse_file_lock(const struct fuse_file_lock *fl, struct flock *flock) { memset(flock, 0, sizeof(struct flock)); @@ -808,7 +882,7 @@ static void convert_fuse_file_lock(struct fuse_file_lock *fl, static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; + const struct fuse_lk_in *arg = (const struct fuse_lk_in *) inarg; struct fuse_file_info fi; struct flock flock; @@ -826,7 +900,7 @@ static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, const void *inarg, int should_sleep) { - struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; + const struct fuse_lk_in *arg = (const struct fuse_lk_in *) inarg; struct fuse_file_info fi; struct flock flock; @@ -887,7 +961,7 @@ static int find_interrupted(struct fuse_ll *f, struct fuse_req *req) static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg; + const struct fuse_interrupt_in *arg = (const struct fuse_interrupt_in *) inarg; struct fuse_ll *f = req->f; (void) nodeid; @@ -927,7 +1001,7 @@ static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req) static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg; + const struct fuse_bmap_in *arg = (const struct fuse_bmap_in *) inarg; if (req->f->op.bmap) req->f->op.bmap(req, nodeid, arg->blocksize, arg->block); @@ -937,7 +1011,7 @@ static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { - struct fuse_init_in *arg = (struct fuse_init_in *) inarg; + const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg; struct fuse_init_out outarg; struct fuse_ll *f = req->f; size_t bufsize = fuse_chan_bufsize(req->ch); @@ -965,6 +1039,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.async_read = arg->flags & FUSE_ASYNC_READ; if (arg->max_readahead < f->conn.max_readahead) f->conn.max_readahead = arg->max_readahead; +#ifdef POSIXACLS + if (arg->flags & FUSE_DONT_MASK) + f->conn.capable |= FUSE_CAP_DONT_MASK; +#endif } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -986,11 +1064,29 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) memset(&outarg, 0, sizeof(outarg)); outarg.major = FUSE_KERNEL_VERSION; + /* + * if POSIXACLS is not set, protocol 7.8 provides a good + * compatibility with older kernel modules. + * if POSIXACLS is set, we try to use protocol 7.12 supposed + * to have the ability to process the umask conditionnally, + * but, when using an older kernel module, we fallback to 7.8 + */ +#ifdef POSIXACLS + if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12)) + outarg.minor = FUSE_KERNEL_MINOR_VERSION; + else + outarg.minor = FUSE_KERNEL_MINOR_FALLBACK; +#else outarg.minor = FUSE_KERNEL_MINOR_VERSION; +#endif if (f->conn.async_read) outarg.flags |= FUSE_ASYNC_READ; if (f->op.getlk && f->op.setlk) outarg.flags |= FUSE_POSIX_LOCKS; +#ifdef POSIXACLS + if (f->conn.want & FUSE_CAP_DONT_MASK) + outarg.flags |= FUSE_DONT_MASK; +#endif outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; @@ -1028,6 +1124,18 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) return &req->ctx; } +/* + * The size of fuse_ctx got extended, so need to be careful about + * incompatibility (i.e. a new binary cannot work with an old + * library). + */ +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req); +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req) +{ + return fuse_req_ctx(req); +} +//FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4"); + void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, void *data) { @@ -1106,7 +1214,7 @@ static void fuse_ll_process(void *data, const char *buf, size_t len, struct fuse_chan *ch) { struct fuse_ll *f = (struct fuse_ll *) data; - struct fuse_in_header *in = (struct fuse_in_header *) buf; + const struct fuse_in_header *in = (const struct fuse_in_header *) buf; const void *inarg = buf + sizeof(struct fuse_in_header); struct fuse_req *req; diff --git a/release/src/router/ntfs-3g/libntfs-3g/Makefile.am b/release/src/router/ntfs-3g/libntfs-3g/Makefile.am index 325d2f689b..bf1e7248db 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/Makefile.am +++ b/release/src/router/ntfs-3g/libntfs-3g/Makefile.am @@ -18,6 +18,7 @@ libntfs_3g_la_LIBADD = $(top_builddir)/libfuse-lite/libfuse-lite.la endif libntfs_3g_la_SOURCES = \ + acls.c \ attrib.c \ attrlist.c \ bitmap.c \ @@ -28,6 +29,7 @@ libntfs_3g_la_SOURCES = \ debug.c \ device.c \ dir.c \ + efs.c \ index.c \ inode.c \ lcnalloc.c \ @@ -36,6 +38,7 @@ libntfs_3g_la_SOURCES = \ mft.c \ misc.c \ mst.c \ + reparse.c \ runlist.c \ security.c \ unistr.c \ diff --git a/release/src/router/ntfs-3g/libntfs-3g/Makefile.in b/release/src/router/ntfs-3g/libntfs-3g/Makefile.in index 009d4b8753..637f1d79b9 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/Makefile.in +++ b/release/src/router/ntfs-3g/libntfs-3g/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -15,15 +15,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -63,39 +59,45 @@ rootlibLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \ $(rootlib_LTLIBRARIES) @FUSE_INTERNAL_TRUE@libntfs_3g_la_DEPENDENCIES = $(top_builddir)/libfuse-lite/libfuse-lite.la -am__libntfs_3g_la_SOURCES_DIST = attrib.c attrlist.c bitmap.c \ +am__libntfs_3g_la_SOURCES_DIST = acls.c attrib.c attrlist.c bitmap.c \ bootsect.c collate.c compat.c compress.c debug.c device.c \ - dir.c index.c inode.c lcnalloc.c logfile.c logging.c mft.c \ - misc.c mst.c runlist.c security.c unistr.c volume.c win32_io.c \ - unix_io.c + dir.c efs.c index.c inode.c lcnalloc.c logfile.c logging.c \ + mft.c misc.c mst.c reparse.c runlist.c security.c unistr.c \ + volume.c win32_io.c unix_io.c @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_TRUE@am__objects_1 = libntfs_3g_la-win32_io.lo @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@@WINDOWS_FALSE@am__objects_2 = libntfs_3g_la-unix_io.lo -am_libntfs_3g_la_OBJECTS = libntfs_3g_la-attrib.lo \ - libntfs_3g_la-attrlist.lo libntfs_3g_la-bitmap.lo \ - libntfs_3g_la-bootsect.lo libntfs_3g_la-collate.lo \ - libntfs_3g_la-compat.lo libntfs_3g_la-compress.lo \ - libntfs_3g_la-debug.lo libntfs_3g_la-device.lo \ - libntfs_3g_la-dir.lo libntfs_3g_la-index.lo \ +am_libntfs_3g_la_OBJECTS = libntfs_3g_la-acls.lo \ + libntfs_3g_la-attrib.lo libntfs_3g_la-attrlist.lo \ + libntfs_3g_la-bitmap.lo libntfs_3g_la-bootsect.lo \ + libntfs_3g_la-collate.lo libntfs_3g_la-compat.lo \ + libntfs_3g_la-compress.lo libntfs_3g_la-debug.lo \ + libntfs_3g_la-device.lo libntfs_3g_la-dir.lo \ + libntfs_3g_la-efs.lo libntfs_3g_la-index.lo \ libntfs_3g_la-inode.lo libntfs_3g_la-lcnalloc.lo \ libntfs_3g_la-logfile.lo libntfs_3g_la-logging.lo \ libntfs_3g_la-mft.lo libntfs_3g_la-misc.lo \ - libntfs_3g_la-mst.lo libntfs_3g_la-runlist.lo \ - libntfs_3g_la-security.lo libntfs_3g_la-unistr.lo \ - libntfs_3g_la-volume.lo $(am__objects_1) $(am__objects_2) + libntfs_3g_la-mst.lo libntfs_3g_la-reparse.lo \ + libntfs_3g_la-runlist.lo libntfs_3g_la-security.lo \ + libntfs_3g_la-unistr.lo libntfs_3g_la-volume.lo \ + $(am__objects_1) $(am__objects_2) libntfs_3g_la_OBJECTS = $(am_libntfs_3g_la_OBJECTS) +libntfs_3g_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libntfs_3g_la_CFLAGS) \ + $(CFLAGS) $(libntfs_3g_la_LDFLAGS) $(LDFLAGS) -o $@ @INSTALL_LIBRARY_FALSE@am_libntfs_3g_la_rpath = @INSTALL_LIBRARY_TRUE@am_libntfs_3g_la_rpath = -rpath $(libdir) -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ SOURCES = $(libntfs_3g_la_SOURCES) DIST_SOURCES = $(am__libntfs_3g_la_SOURCES_DIST) pkgconfigDATA_INSTALL = $(INSTALL_DATA) @@ -104,8 +106,6 @@ ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -124,26 +124,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -157,13 +151,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -175,25 +166,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -205,6 +190,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -237,12 +223,15 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in @INSTALL_LIBRARY_TRUE@rootlib_LTLIBRARIES = #Create directory @INSTALL_LIBRARY_TRUE@lib_LTLIBRARIES = libntfs-3g.la @@ -251,11 +240,11 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in libntfs_3g_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g libntfs_3g_la_LDFLAGS = -version-info $(LIBNTFS_3G_VERSION) -no-undefined @FUSE_INTERNAL_TRUE@libntfs_3g_la_LIBADD = $(top_builddir)/libfuse-lite/libfuse-lite.la -libntfs_3g_la_SOURCES = attrib.c attrlist.c bitmap.c bootsect.c \ - collate.c compat.c compress.c debug.c device.c dir.c index.c \ - inode.c lcnalloc.c logfile.c logging.c mft.c misc.c mst.c \ - runlist.c security.c unistr.c volume.c $(am__append_1) \ - $(am__append_2) +libntfs_3g_la_SOURCES = acls.c attrib.c attrlist.c bitmap.c bootsect.c \ + collate.c compat.c compress.c debug.c device.c dir.c efs.c \ + index.c inode.c lcnalloc.c logfile.c logging.c mft.c misc.c \ + mst.c reparse.c runlist.c security.c unistr.c volume.c \ + $(am__append_1) $(am__append_2) all: all-am .SUFFIXES: @@ -295,21 +284,21 @@ libntfs-3g.script.so: $(top_builddir)/config.status $(srcdir)/libntfs-3g.script. cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) - @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: @@ -331,21 +320,21 @@ clean-noinstLTLIBRARIES: done install-rootlibLTLIBRARIES: $(rootlib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(rootlibdir)" || $(mkdir_p) "$(DESTDIR)$(rootlibdir)" + test -z "$(rootlibdir)" || $(MKDIR_P) "$(DESTDIR)$(rootlibdir)" @list='$(rootlib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(rootlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(rootlibdir)/$$f'"; \ - $(LIBTOOL) --mode=install $(rootlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(rootlibdir)/$$f"; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(rootlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(rootlibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(rootlibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(rootlibdir)/$$f"; \ else :; fi; \ done uninstall-rootlibLTLIBRARIES: @$(NORMAL_UNINSTALL) - @set -x; list='$(rootlib_LTLIBRARIES)'; for p in $$list; do \ + @list='$(rootlib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(rootlibdir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(rootlibdir)/$$p"; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(rootlibdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(rootlibdir)/$$p"; \ done clean-rootlibLTLIBRARIES: @@ -357,7 +346,7 @@ clean-rootlibLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libntfs-3g.la: $(libntfs_3g_la_OBJECTS) $(libntfs_3g_la_DEPENDENCIES) - $(LINK) $(am_libntfs_3g_la_rpath) $(libntfs_3g_la_LDFLAGS) $(libntfs_3g_la_OBJECTS) $(libntfs_3g_la_LIBADD) $(LIBS) + $(libntfs_3g_la_LINK) $(am_libntfs_3g_la_rpath) $(libntfs_3g_la_OBJECTS) $(libntfs_3g_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -365,6 +354,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-acls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-attrib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-attrlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-bitmap.Plo@am__quote@ @@ -375,6 +365,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-dir.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-efs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-index.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-inode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-lcnalloc.Plo@am__quote@ @@ -383,6 +374,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-mft.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-mst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-reparse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-runlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-security.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-unistr.Plo@am__quote@ @@ -391,206 +383,223 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libntfs_3g_la-win32_io.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +libntfs_3g_la-acls.lo: acls.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-acls.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-acls.Tpo -c -o libntfs_3g_la-acls.lo `test -f 'acls.c' || echo '$(srcdir)/'`acls.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-acls.Tpo $(DEPDIR)/libntfs_3g_la-acls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='acls.c' object='libntfs_3g_la-acls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-acls.lo `test -f 'acls.c' || echo '$(srcdir)/'`acls.c + libntfs_3g_la-attrib.lo: attrib.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrib.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-attrib.Tpo" -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-attrib.Tpo" "$(DEPDIR)/libntfs_3g_la-attrib.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-attrib.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrib.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-attrib.Tpo -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-attrib.Tpo $(DEPDIR)/libntfs_3g_la-attrib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attrib.c' object='libntfs_3g_la-attrib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrib.lo `test -f 'attrib.c' || echo '$(srcdir)/'`attrib.c libntfs_3g_la-attrlist.lo: attrlist.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrlist.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-attrlist.Tpo" -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-attrlist.Tpo" "$(DEPDIR)/libntfs_3g_la-attrlist.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-attrlist.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-attrlist.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-attrlist.Tpo -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-attrlist.Tpo $(DEPDIR)/libntfs_3g_la-attrlist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='attrlist.c' object='libntfs_3g_la-attrlist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-attrlist.lo `test -f 'attrlist.c' || echo '$(srcdir)/'`attrlist.c libntfs_3g_la-bitmap.lo: bitmap.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bitmap.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-bitmap.Tpo" -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-bitmap.Tpo" "$(DEPDIR)/libntfs_3g_la-bitmap.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-bitmap.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bitmap.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-bitmap.Tpo -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-bitmap.Tpo $(DEPDIR)/libntfs_3g_la-bitmap.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bitmap.c' object='libntfs_3g_la-bitmap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bitmap.lo `test -f 'bitmap.c' || echo '$(srcdir)/'`bitmap.c libntfs_3g_la-bootsect.lo: bootsect.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bootsect.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-bootsect.Tpo" -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-bootsect.Tpo" "$(DEPDIR)/libntfs_3g_la-bootsect.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-bootsect.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-bootsect.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-bootsect.Tpo -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-bootsect.Tpo $(DEPDIR)/libntfs_3g_la-bootsect.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bootsect.c' object='libntfs_3g_la-bootsect.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-bootsect.lo `test -f 'bootsect.c' || echo '$(srcdir)/'`bootsect.c libntfs_3g_la-collate.lo: collate.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-collate.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-collate.Tpo" -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-collate.Tpo" "$(DEPDIR)/libntfs_3g_la-collate.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-collate.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-collate.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-collate.Tpo -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-collate.Tpo $(DEPDIR)/libntfs_3g_la-collate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='collate.c' object='libntfs_3g_la-collate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-collate.lo `test -f 'collate.c' || echo '$(srcdir)/'`collate.c libntfs_3g_la-compat.lo: compat.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compat.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-compat.Tpo" -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-compat.Tpo" "$(DEPDIR)/libntfs_3g_la-compat.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-compat.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compat.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-compat.Tpo -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-compat.Tpo $(DEPDIR)/libntfs_3g_la-compat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='compat.c' object='libntfs_3g_la-compat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compat.lo `test -f 'compat.c' || echo '$(srcdir)/'`compat.c libntfs_3g_la-compress.lo: compress.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compress.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-compress.Tpo" -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-compress.Tpo" "$(DEPDIR)/libntfs_3g_la-compress.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-compress.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-compress.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-compress.Tpo -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-compress.Tpo $(DEPDIR)/libntfs_3g_la-compress.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='compress.c' object='libntfs_3g_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-compress.lo `test -f 'compress.c' || echo '$(srcdir)/'`compress.c libntfs_3g_la-debug.lo: debug.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-debug.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-debug.Tpo" -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-debug.Tpo" "$(DEPDIR)/libntfs_3g_la-debug.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-debug.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-debug.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-debug.Tpo -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-debug.Tpo $(DEPDIR)/libntfs_3g_la-debug.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='debug.c' object='libntfs_3g_la-debug.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c libntfs_3g_la-device.lo: device.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-device.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-device.Tpo" -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-device.Tpo" "$(DEPDIR)/libntfs_3g_la-device.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-device.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-device.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-device.Tpo -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-device.Tpo $(DEPDIR)/libntfs_3g_la-device.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='device.c' object='libntfs_3g_la-device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-device.lo `test -f 'device.c' || echo '$(srcdir)/'`device.c libntfs_3g_la-dir.lo: dir.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-dir.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-dir.Tpo" -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-dir.Tpo" "$(DEPDIR)/libntfs_3g_la-dir.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-dir.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-dir.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-dir.Tpo -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-dir.Tpo $(DEPDIR)/libntfs_3g_la-dir.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dir.c' object='libntfs_3g_la-dir.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-dir.lo `test -f 'dir.c' || echo '$(srcdir)/'`dir.c + +libntfs_3g_la-efs.lo: efs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-efs.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-efs.Tpo -c -o libntfs_3g_la-efs.lo `test -f 'efs.c' || echo '$(srcdir)/'`efs.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-efs.Tpo $(DEPDIR)/libntfs_3g_la-efs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='efs.c' object='libntfs_3g_la-efs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-efs.lo `test -f 'efs.c' || echo '$(srcdir)/'`efs.c libntfs_3g_la-index.lo: index.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-index.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-index.Tpo" -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-index.Tpo" "$(DEPDIR)/libntfs_3g_la-index.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-index.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-index.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-index.Tpo -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-index.Tpo $(DEPDIR)/libntfs_3g_la-index.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='index.c' object='libntfs_3g_la-index.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-index.lo `test -f 'index.c' || echo '$(srcdir)/'`index.c libntfs_3g_la-inode.lo: inode.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-inode.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-inode.Tpo" -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-inode.Tpo" "$(DEPDIR)/libntfs_3g_la-inode.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-inode.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-inode.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-inode.Tpo -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-inode.Tpo $(DEPDIR)/libntfs_3g_la-inode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='inode.c' object='libntfs_3g_la-inode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-inode.lo `test -f 'inode.c' || echo '$(srcdir)/'`inode.c libntfs_3g_la-lcnalloc.lo: lcnalloc.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-lcnalloc.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo" -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo" "$(DEPDIR)/libntfs_3g_la-lcnalloc.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-lcnalloc.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-lcnalloc.Tpo $(DEPDIR)/libntfs_3g_la-lcnalloc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lcnalloc.c' object='libntfs_3g_la-lcnalloc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-lcnalloc.lo `test -f 'lcnalloc.c' || echo '$(srcdir)/'`lcnalloc.c libntfs_3g_la-logfile.lo: logfile.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logfile.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-logfile.Tpo" -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-logfile.Tpo" "$(DEPDIR)/libntfs_3g_la-logfile.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-logfile.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logfile.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-logfile.Tpo -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-logfile.Tpo $(DEPDIR)/libntfs_3g_la-logfile.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='logfile.c' object='libntfs_3g_la-logfile.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logfile.lo `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c libntfs_3g_la-logging.lo: logging.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logging.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-logging.Tpo" -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-logging.Tpo" "$(DEPDIR)/libntfs_3g_la-logging.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-logging.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-logging.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-logging.Tpo -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-logging.Tpo $(DEPDIR)/libntfs_3g_la-logging.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='logging.c' object='libntfs_3g_la-logging.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-logging.lo `test -f 'logging.c' || echo '$(srcdir)/'`logging.c libntfs_3g_la-mft.lo: mft.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mft.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-mft.Tpo" -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-mft.Tpo" "$(DEPDIR)/libntfs_3g_la-mft.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-mft.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mft.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-mft.Tpo -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-mft.Tpo $(DEPDIR)/libntfs_3g_la-mft.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mft.c' object='libntfs_3g_la-mft.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mft.lo `test -f 'mft.c' || echo '$(srcdir)/'`mft.c libntfs_3g_la-misc.lo: misc.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-misc.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-misc.Tpo" -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-misc.Tpo" "$(DEPDIR)/libntfs_3g_la-misc.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-misc.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-misc.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-misc.Tpo -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-misc.Tpo $(DEPDIR)/libntfs_3g_la-misc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc.c' object='libntfs_3g_la-misc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c libntfs_3g_la-mst.lo: mst.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mst.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-mst.Tpo" -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-mst.Tpo" "$(DEPDIR)/libntfs_3g_la-mst.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-mst.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-mst.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-mst.Tpo -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-mst.Tpo $(DEPDIR)/libntfs_3g_la-mst.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mst.c' object='libntfs_3g_la-mst.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-mst.lo `test -f 'mst.c' || echo '$(srcdir)/'`mst.c + +libntfs_3g_la-reparse.lo: reparse.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-reparse.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-reparse.Tpo -c -o libntfs_3g_la-reparse.lo `test -f 'reparse.c' || echo '$(srcdir)/'`reparse.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-reparse.Tpo $(DEPDIR)/libntfs_3g_la-reparse.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='reparse.c' object='libntfs_3g_la-reparse.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-reparse.lo `test -f 'reparse.c' || echo '$(srcdir)/'`reparse.c libntfs_3g_la-runlist.lo: runlist.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-runlist.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-runlist.Tpo" -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-runlist.Tpo" "$(DEPDIR)/libntfs_3g_la-runlist.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-runlist.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-runlist.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-runlist.Tpo -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-runlist.Tpo $(DEPDIR)/libntfs_3g_la-runlist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runlist.c' object='libntfs_3g_la-runlist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-runlist.lo `test -f 'runlist.c' || echo '$(srcdir)/'`runlist.c libntfs_3g_la-security.lo: security.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-security.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-security.Tpo" -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-security.Tpo" "$(DEPDIR)/libntfs_3g_la-security.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-security.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-security.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-security.Tpo -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-security.Tpo $(DEPDIR)/libntfs_3g_la-security.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='security.c' object='libntfs_3g_la-security.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-security.lo `test -f 'security.c' || echo '$(srcdir)/'`security.c libntfs_3g_la-unistr.lo: unistr.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unistr.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-unistr.Tpo" -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-unistr.Tpo" "$(DEPDIR)/libntfs_3g_la-unistr.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-unistr.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unistr.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-unistr.Tpo -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-unistr.Tpo $(DEPDIR)/libntfs_3g_la-unistr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='unistr.c' object='libntfs_3g_la-unistr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unistr.lo `test -f 'unistr.c' || echo '$(srcdir)/'`unistr.c libntfs_3g_la-volume.lo: volume.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-volume.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-volume.Tpo" -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-volume.Tpo" "$(DEPDIR)/libntfs_3g_la-volume.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-volume.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-volume.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-volume.Tpo -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-volume.Tpo $(DEPDIR)/libntfs_3g_la-volume.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='volume.c' object='libntfs_3g_la-volume.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-volume.lo `test -f 'volume.c' || echo '$(srcdir)/'`volume.c libntfs_3g_la-win32_io.lo: win32_io.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-win32_io.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-win32_io.Tpo" -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-win32_io.Tpo" "$(DEPDIR)/libntfs_3g_la-win32_io.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-win32_io.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-win32_io.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-win32_io.Tpo -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-win32_io.Tpo $(DEPDIR)/libntfs_3g_la-win32_io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32_io.c' object='libntfs_3g_la-win32_io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-win32_io.lo `test -f 'win32_io.c' || echo '$(srcdir)/'`win32_io.c libntfs_3g_la-unix_io.lo: unix_io.c -@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unix_io.lo -MD -MP -MF "$(DEPDIR)/libntfs_3g_la-unix_io.Tpo" -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libntfs_3g_la-unix_io.Tpo" "$(DEPDIR)/libntfs_3g_la-unix_io.Plo"; else rm -f "$(DEPDIR)/libntfs_3g_la-unix_io.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -MT libntfs_3g_la-unix_io.lo -MD -MP -MF $(DEPDIR)/libntfs_3g_la-unix_io.Tpo -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libntfs_3g_la-unix_io.Tpo $(DEPDIR)/libntfs_3g_la-unix_io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='unix_io.c' object='libntfs_3g_la-unix_io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libntfs_3g_la_CFLAGS) $(CFLAGS) -c -o libntfs_3g_la-unix_io.lo `test -f 'unix_io.c' || echo '$(srcdir)/'`unix_io.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgconfigdir)" || $(mkdir_p) "$(DESTDIR)$(pkgconfigdir)" + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" @list='$(pkgconfig_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ @@ -611,8 +620,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -624,8 +633,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -635,13 +644,12 @@ ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -655,22 +663,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -686,7 +693,7 @@ check: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(rootlibdir)" "$(DESTDIR)$(pkgconfigdir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am @@ -723,7 +730,7 @@ distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags + distclean-tags dvi: dvi-am @@ -737,14 +744,22 @@ info-am: install-data-am: install-pkgconfigDATA install-rootlibLTLIBRARIES +install-dvi: install-dvi-am + install-exec-am: install-libLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) 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 + installcheck-am: maintainer-clean: maintainer-clean-am @@ -765,25 +780,28 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \ - uninstall-local uninstall-pkgconfigDATA \ - uninstall-rootlibLTLIBRARIES +uninstall-am: uninstall-libLTLIBRARIES uninstall-local \ + uninstall-pkgconfigDATA uninstall-rootlibLTLIBRARIES + +.MAKE: install-am install-exec-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ clean-rootlibLTLIBRARIES ctags 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-exec install-exec-am \ - install-exec-hook install-info install-info-am \ - install-libLTLIBRARIES install-man install-pkgconfigDATA \ + 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-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am \ install-rootlibLTLIBRARIES 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 uninstall uninstall-am uninstall-info-am \ - uninstall-libLTLIBRARIES uninstall-local \ - uninstall-pkgconfigDATA uninstall-rootlibLTLIBRARIES + tags uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-local uninstall-pkgconfigDATA \ + uninstall-rootlibLTLIBRARIES # We may need to move .so files to root diff --git a/release/src/router/ntfs-3g/libntfs-3g/acls.c b/release/src/router/ntfs-3g/libntfs-3g/acls.c new file mode 100644 index 0000000000..887d75ae9d --- /dev/null +++ b/release/src/router/ntfs-3g/libntfs-3g/acls.c @@ -0,0 +1,4283 @@ +/** + * acls.c - General function to process NTFS ACLs + * + * This module is part of ntfs-3g library, but may also be + * integrated in tools running over Linux or Windows + * + * Copyright (c) 2007-2009 Jean-Pierre Andre + * + * This program/include file 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/include file 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H + /* + * integration into ntfs-3g + */ +#include "config.h" + +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYSLOG_H +#include +#endif +#include +#include +#include + +#include "types.h" +#include "layout.h" +#include "security.h" +#include "acls.h" +#include "misc.h" +#else + + /* + * integration into secaudit, check whether Win32, + * may have to be adapted to compiler or something else + */ + +#ifndef WIN32 +#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC) +#define WIN32 1 +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include + + /* + * integration into secaudit/Win32 + */ +#ifdef WIN32 +#include +#include +#define __LITTLE_ENDIAN 1234 +#define __BYTE_ORDER __LITTLE_ENDIAN +#else + /* + * integration into secaudit/STSC + */ +#ifdef STSC +#include +#undef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#else + /* + * integration into secaudit/Linux + */ +#include +#include +#include +#include +#endif /* STSC */ +#endif /* WIN32 */ +#include "secaudit.h" +#endif /* HAVE_CONFIG_H */ + +/* + * A few useful constants + */ + +/* + * null SID (S-1-0-0) + */ + +static const char nullsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 0, /* base */ + 0, 0, 0, 0 /* 1st level */ + }; + +static const SID *nullsid = (const SID*)nullsidbytes; + +/* + * SID for world (S-1-1-0) + */ + +static const char worldsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 1, /* base */ + 0, 0, 0, 0 /* 1st level */ +} ; + +const SID *worldsid = (const SID*)worldsidbytes; + +/* + * SID for administrator + */ + +static const char adminsidbytes[] = { + 1, /* revision */ + 2, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 32, 0, 0, 0, /* 1st level */ + 32, 2, 0, 0 /* 2nd level */ +}; + +const SID *adminsid = (const SID*)adminsidbytes; + +/* + * SID for system + */ + +static const char systemsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 18, 0, 0, 0 /* 1st level */ + }; + +static const SID *systemsid = (const SID*)systemsidbytes; + +/* + * SID for generic creator-owner + * S-1-3-0 + */ + +static const char ownersidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 3, /* base */ + 0, 0, 0, 0 /* 1st level */ +} ; + +static const SID *ownersid = (const SID*)ownersidbytes; + +/* + * SID for generic creator-group + * S-1-3-1 + */ + +static const char groupsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 3, /* base */ + 1, 0, 0, 0 /* 1st level */ +} ; + +static const SID *groupsid = (const SID*)groupsidbytes; + +/* + * Determine the size of a SID + */ + +int ntfs_sid_size(const SID * sid) +{ + return (sid->sub_authority_count * 4 + 8); +} + +/* + * Test whether two SID are equal + */ + +BOOL ntfs_same_sid(const SID *first, const SID *second) +{ + int size; + + size = ntfs_sid_size(first); + return ((ntfs_sid_size(second) == size) + && !memcmp(first, second, size)); +} + +/* + * Test whether a SID means "world user" + * Local users group also recognized as world + */ + +static int is_world_sid(const SID * usid) +{ + return ( + /* check whether S-1-1-0 : world */ + ((usid->sub_authority_count == 1) + && (usid->identifier_authority.high_part == const_cpu_to_be16(0)) + && (usid->identifier_authority.low_part == const_cpu_to_be32(1)) + && (usid->sub_authority[0] == const_cpu_to_le32(0))) + + /* check whether S-1-5-32-545 : local user */ + || ((usid->sub_authority_count == 2) + && (usid->identifier_authority.high_part == const_cpu_to_be16(0)) + && (usid->identifier_authority.low_part == const_cpu_to_be32(5)) + && (usid->sub_authority[0] == const_cpu_to_le32(32)) + && (usid->sub_authority[1] == const_cpu_to_le32(545))) + ); +} + +/* + * Test whether a SID means "some user (or group)" + * Currently we only check for S-1-5-21... but we should + * probably test for other configurations + */ + +BOOL ntfs_is_user_sid(const SID *usid) +{ + return ((usid->sub_authority_count == 5) + && (usid->identifier_authority.high_part == const_cpu_to_be16(0)) + && (usid->identifier_authority.low_part == const_cpu_to_be32(5)) + && (usid->sub_authority[0] == const_cpu_to_le32(21))); +} + +/* + * Determine the size of a security attribute + * whatever the order of fields + */ + +unsigned int ntfs_attr_size(const char *attr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pdacl; + const ACL *psacl; + const SID *psid; + unsigned int offdacl; + unsigned int offsacl; + unsigned int offowner; + unsigned int offgroup; + unsigned int endsid; + unsigned int endacl; + unsigned int attrsz; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + /* + * First check group, which is the last field in all descriptors + * we build, and in most descriptors built by Windows + */ + attrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + offgroup = le32_to_cpu(phead->group); + if (offgroup >= attrsz) { + /* find end of GSID */ + psid = (const SID*)&attr[offgroup]; + endsid = offgroup + ntfs_sid_size(psid); + if (endsid > attrsz) attrsz = endsid; + } + offowner = le32_to_cpu(phead->owner); + if (offowner >= attrsz) { + /* find end of USID */ + psid = (const SID*)&attr[offowner]; + endsid = offowner + ntfs_sid_size(psid); + attrsz = endsid; + } + offsacl = le32_to_cpu(phead->sacl); + if (offsacl >= attrsz) { + /* find end of SACL */ + psacl = (const ACL*)&attr[offsacl]; + endacl = offsacl + le16_to_cpu(psacl->size); + if (endacl > attrsz) + attrsz = endacl; + } + + + /* find end of DACL */ + offdacl = le32_to_cpu(phead->dacl); + if (offdacl >= attrsz) { + pdacl = (const ACL*)&attr[offdacl]; + endacl = offdacl + le16_to_cpu(pdacl->size); + if (endacl > attrsz) + attrsz = endacl; + } + return (attrsz); +} + +/* + * Do sanity checks on a SID read from storage + * (just check revision and number of authorities) + */ + +BOOL ntfs_valid_sid(const SID *sid) +{ + return ((sid->revision == SID_REVISION) + && (sid->sub_authority_count >= 1) + && (sid->sub_authority_count <= 8)); +} + +/* + * Check whether a SID is acceptable for an implicit + * mapping pattern. + * It should have been already checked it is a valid user SID. + * + * The last authority reference has to be >= 1000 (Windows usage) + * and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits + * from a gid an be inserted with no overflow. + */ + +BOOL ntfs_valid_pattern(const SID *sid) +{ + int cnt; + u32 auth; + le32 leauth; + + cnt = sid->sub_authority_count; + leauth = sid->sub_authority[cnt-1]; + auth = le32_to_cpu(leauth); + return ((auth >= 1000) && (auth <= 0x7fffffff)); +} + +/* + * Compute the uid or gid associated to a SID + * through an implicit mapping + * + * Returns 0 (root) if it does not match pattern + */ + +static u32 findimplicit(const SID *xsid, const SID *pattern, int parity) +{ + BIGSID defsid; + SID *psid; + u32 xid; /* uid or gid */ + int cnt; + u32 carry; + le32 leauth; + u32 uauth; + u32 xlast; + u32 rlast; + + memcpy(&defsid,pattern,ntfs_sid_size(pattern)); + psid = (SID*)&defsid; + cnt = psid->sub_authority_count; + xid = 0; + if (xsid->sub_authority_count == cnt) { + psid->sub_authority[cnt-1] = xsid->sub_authority[cnt-1]; + leauth = xsid->sub_authority[cnt-1]; + xlast = le32_to_cpu(leauth); + leauth = pattern->sub_authority[cnt-1]; + rlast = le32_to_cpu(leauth); + + if ((xlast > rlast) && !((xlast ^ rlast ^ parity) & 1)) { + /* direct check for basic situation */ + if (ntfs_same_sid(psid,xsid)) + xid = ((xlast - rlast) >> 1) & 0x3fffffff; + else { + /* + * check whether part of mapping had to be + * recorded in a higher level authority + */ + carry = 1; + do { + leauth = psid->sub_authority[cnt-2]; + uauth = le32_to_cpu(leauth) + 1; + psid->sub_authority[cnt-2] + = cpu_to_le32(uauth); + } while (!ntfs_same_sid(psid,xsid) + && (++carry < 4)); + if (carry < 4) + xid = (((xlast - rlast) >> 1) + & 0x3fffffff) | (carry << 30); + } + } + } + return (xid); +} + +/* + * Find usid mapped to a Linux user + * Returns NULL if not found + */ + +const SID *ntfs_find_usid(const struct MAPPING* usermapping, + uid_t uid, SID *defusid) +{ + const struct MAPPING *p; + const SID *sid; + le32 leauth; + u32 uauth; + int cnt; + + if (!uid) + sid = adminsid; + else { + p = usermapping; + while (p && p->xid && ((uid_t)p->xid != uid)) + p = p->next; + if (p && !p->xid) { + /* + * default pattern has been reached : + * build an implicit SID according to pattern + * (the pattern format was checked while reading + * the mapping file) + */ + memcpy(defusid, p->sid, ntfs_sid_size(p->sid)); + cnt = defusid->sub_authority_count; + leauth = defusid->sub_authority[cnt-1]; + uauth = le32_to_cpu(leauth) + 2*(uid & 0x3fffffff); + defusid->sub_authority[cnt-1] = cpu_to_le32(uauth); + if (uid & 0xc0000000) { + leauth = defusid->sub_authority[cnt-2]; + uauth = le32_to_cpu(leauth) + ((uid >> 30) & 3); + defusid->sub_authority[cnt-2] = cpu_to_le32(uauth); + } + sid = defusid; + } else + sid = (p ? p->sid : (const SID*)NULL); + } + return (sid); +} + +/* + * Find Linux group mapped to a gsid + * Returns 0 (root) if not found + */ + +const SID *ntfs_find_gsid(const struct MAPPING* groupmapping, + gid_t gid, SID *defgsid) +{ + const struct MAPPING *p; + const SID *sid; + le32 leauth; + u32 uauth; + int cnt; + + if (!gid) + sid = adminsid; + else { + p = groupmapping; + while (p && p->xid && ((gid_t)p->xid != gid)) + p = p->next; + if (p && !p->xid) { + /* + * default pattern has been reached : + * build an implicit SID according to pattern + * (the pattern format was checked while reading + * the mapping file) + */ + memcpy(defgsid, p->sid, ntfs_sid_size(p->sid)); + cnt = defgsid->sub_authority_count; + leauth = defgsid->sub_authority[cnt-1]; + uauth = le32_to_cpu(leauth) + 2*(gid & 0x3fffffff) + 1; + defgsid->sub_authority[cnt-1] = cpu_to_le32(uauth); + if (gid & 0xc0000000) { + leauth = defgsid->sub_authority[cnt-2]; + uauth = le32_to_cpu(leauth) + ((gid >> 30) & 3); + defgsid->sub_authority[cnt-2] = cpu_to_le32(uauth); + } + sid = defgsid; + } else + sid = (p ? p->sid : (const SID*)NULL); + } + return (sid); +} + +/* + * Find Linux owner mapped to a usid + * Returns 0 (root) if not found + */ + +uid_t ntfs_find_user(const struct MAPPING* usermapping, const SID *usid) +{ + uid_t uid; + const struct MAPPING *p; + + p = usermapping; + while (p && p->xid && !ntfs_same_sid(usid, p->sid)) + p = p->next; + if (p && !p->xid) + /* + * No explicit mapping found, try implicit mapping + */ + uid = findimplicit(usid,p->sid,0); + else + uid = (p ? p->xid : 0); + return (uid); +} + +/* + * Find Linux group mapped to a gsid + * Returns 0 (root) if not found + */ + +gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid) +{ + gid_t gid; + const struct MAPPING *p; + int gsidsz; + + gsidsz = ntfs_sid_size(gsid); + p = groupmapping; + while (p && p->xid && !ntfs_same_sid(gsid, p->sid)) + p = p->next; + if (p && !p->xid) + /* + * No explicit mapping found, try implicit mapping + */ + gid = findimplicit(gsid,p->sid,1); + else + gid = (p ? p->xid : 0); + return (gid); +} + +/* + * Check the validity of the ACEs in a DACL or SACL + */ + +static BOOL valid_acl(const ACL *pacl, unsigned int end) +{ + const ACCESS_ALLOWED_ACE *pace; + unsigned int offace; + unsigned int acecnt; + unsigned int acesz; + unsigned int nace; + BOOL ok; + + ok = TRUE; + acecnt = le16_to_cpu(pacl->ace_count); + offace = sizeof(ACL); + for (nace = 0; (nace < acecnt) && ok; nace++) { + /* be sure the beginning is within range */ + if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > end) + ok = FALSE; + else { + pace = (const ACCESS_ALLOWED_ACE*) + &((const char*)pacl)[offace]; + acesz = le16_to_cpu(pace->size); + if (((offace + acesz) > end) + || !ntfs_valid_sid(&pace->sid)) + ok = FALSE; + offace += acesz; + } + } + return (ok); +} + +/* + * Do sanity checks on security descriptors read from storage + * basically, we make sure that every field holds within + * allocated storage + * Should not be called with a NULL argument + * returns TRUE if considered safe + * if not, error should be logged by caller + */ + +BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pdacl; + const ACL *psacl; + unsigned int offdacl; + unsigned int offsacl; + unsigned int offowner; + unsigned int offgroup; + BOOL ok; + + ok = TRUE; + + /* + * first check overall size if within allocation range + * and a DACL is present + * and owner and group SID are valid + */ + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + offsacl = le32_to_cpu(phead->sacl); + offowner = le32_to_cpu(phead->owner); + offgroup = le32_to_cpu(phead->group); + pdacl = (const ACL*)&securattr[offdacl]; + psacl = (const ACL*)&securattr[offsacl]; + + /* + * size check occurs before the above pointers are used + * + * "DR Watson" standard directory on WinXP has an + * old revision and no DACL though SE_DACL_PRESENT is set + */ + if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + && (ntfs_attr_size(securattr) <= attrsz) + && (phead->revision == SECURITY_DESCRIPTOR_REVISION) + && (offowner >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + && ((offowner + 2) < attrsz) + && (offgroup >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + && ((offgroup + 2) < attrsz) + && (!offdacl + || ((offdacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + && (offdacl < attrsz))) + && (!offsacl + || ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + && (offsacl < attrsz))) + && !(phead->owner & const_cpu_to_le32(3)) + && !(phead->group & const_cpu_to_le32(3)) + && !(phead->dacl & const_cpu_to_le32(3)) + && !(phead->sacl & const_cpu_to_le32(3)) + && ntfs_valid_sid((const SID*)&securattr[offowner]) + && ntfs_valid_sid((const SID*)&securattr[offgroup]) + /* + * if there is an ACL, as indicated by offdacl, + * require SE_DACL_PRESENT + * but "Dr Watson" has SE_DACL_PRESENT though no DACL + */ + && (!offdacl + || ((phead->control & SE_DACL_PRESENT) + && ((pdacl->revision == ACL_REVISION) + || (pdacl->revision == ACL_REVISION_DS)))) + /* same for SACL */ + && (!offsacl + || ((phead->control & SE_SACL_PRESENT) + && ((psacl->revision == ACL_REVISION) + || (psacl->revision == ACL_REVISION_DS))))) { + /* + * Check the DACL and SACL if present + */ + if ((offdacl && !valid_acl(pdacl,attrsz - offdacl)) + || (offsacl && !valid_acl(psacl,attrsz - offsacl))) + ok = FALSE; + } else + ok = FALSE; + return (ok); +} + +/* + * Copy the inheritable parts of an ACL + * + * Returns the size of the new ACL + * or zero if nothing is inheritable + */ + +int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, + const SID *usid, const SID *gsid, BOOL fordir) +{ + unsigned int src; + unsigned int dst; + int oldcnt; + int newcnt; + unsigned int selection; + int nace; + int acesz; + int usidsz; + int gsidsz; + const ACCESS_ALLOWED_ACE *poldace; + ACCESS_ALLOWED_ACE *pnewace; + + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + + /* ACL header */ + + newacl->revision = ACL_REVISION; + newacl->alignment1 = 0; + newacl->alignment2 = const_cpu_to_le16(0); + src = dst = sizeof(ACL); + + selection = (fordir ? CONTAINER_INHERIT_ACE : OBJECT_INHERIT_ACE); + newcnt = 0; + oldcnt = le16_to_cpu(oldacl->ace_count); + for (nace = 0; nace < oldcnt; nace++) { + poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src); + acesz = le16_to_cpu(poldace->size); + /* inheritance for access */ + if (poldace->flags & selection) { + pnewace = (ACCESS_ALLOWED_ACE*) + ((char*)newacl + dst); + memcpy(pnewace,poldace,acesz); + /* + * Replace generic creator-owner and + * creator-group by owner and group + */ + if (ntfs_same_sid(&pnewace->sid, ownersid)) { + memcpy(&pnewace->sid, usid, usidsz); + acesz = usidsz + 8; + } + if (ntfs_same_sid(&pnewace->sid, groupsid)) { + memcpy(&pnewace->sid, gsid, gsidsz); + acesz = gsidsz + 8; + } + if (pnewace->mask & GENERIC_ALL) { + pnewace->mask &= ~GENERIC_ALL; + if (fordir) + pnewace->mask |= OWNER_RIGHTS + | DIR_READ + | DIR_WRITE + | DIR_EXEC; + else + /* + * The last flag is not defined for a file, + * however Windows sets it, so do the same + */ + pnewace->mask |= OWNER_RIGHTS + | FILE_READ + | FILE_WRITE + | FILE_EXEC + | cpu_to_le32(0x40); + } + /* remove inheritance flags */ + pnewace->flags &= ~(OBJECT_INHERIT_ACE + | CONTAINER_INHERIT_ACE + | INHERIT_ONLY_ACE); + dst += acesz; + newcnt++; + } + /* inheritance for further inheritance */ + if (fordir + && (poldace->flags + & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) { + pnewace = (ACCESS_ALLOWED_ACE*) + ((char*)newacl + dst); + memcpy(pnewace,poldace,acesz); + /* + * Replace generic creator-owner and + * creator-group by owner and group + */ + if (ntfs_same_sid(&pnewace->sid, ownersid)) { + memcpy(&pnewace->sid, usid, usidsz); + acesz = usidsz + 8; + } + if (ntfs_same_sid(&pnewace->sid, groupsid)) { + memcpy(&pnewace->sid, gsid, gsidsz); + acesz = gsidsz + 8; + } + dst += acesz; + newcnt++; + } + src += acesz; + } + /* + * Adjust header if something was inherited + */ + if (dst > sizeof(ACL)) { + newacl->ace_count = cpu_to_le16(newcnt); + newacl->size = cpu_to_le16(dst); + } else + dst = 0; + return (dst); +} + +#if POSIXACLS + +/* + * Do sanity checks on a Posix descriptor + * Should not be called with a NULL argument + * returns TRUE if considered safe + * if not, error should be logged by caller + */ + +BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc) +{ + const struct POSIX_ACL *pacl; + int i; + BOOL ok; + u16 tag; + u32 id; + int perms; + struct { + u16 previous; + u32 previousid; + u16 tagsset; + mode_t mode; + int owners; + int groups; + int others; + } checks[2], *pchk; + + for (i=0; i<2; i++) { + checks[i].mode = 0; + checks[i].tagsset = 0; + checks[i].owners = 0; + checks[i].groups = 0; + checks[i].others = 0; + checks[i].previous = 0; + checks[i].previousid = 0; + } + ok = TRUE; + pacl = &pxdesc->acl; + /* + * header (strict for now) + */ + if ((pacl->version != POSIX_VERSION) + || (pacl->flags != 0) + || (pacl->filler != 0)) + ok = FALSE; + /* + * Reject multiple owner, group or other + * but do not require them to be present + * Also check the ACEs are in correct order + * which implies there is no duplicates + */ + for (i=0; iacccnt + pxdesc->defcnt; i++) { + if (i >= pxdesc->firstdef) + pchk = &checks[1]; + else + pchk = &checks[0]; + perms = pacl->ace[i].perms; + tag = pacl->ace[i].tag; + pchk->tagsset |= tag; + id = pacl->ace[i].id; + if (perms & ~7) ok = FALSE; + if ((tag < pchk->previous) + || ((tag == pchk->previous) + && (id <= pchk->previousid))) + ok = FALSE; + pchk->previous = tag; + pchk->previousid = id; + switch (tag) { + case POSIX_ACL_USER_OBJ : + if (pchk->owners++) + ok = FALSE; + if (id != (u32)-1) + ok = FALSE; + pchk->mode |= perms << 6; + break; + case POSIX_ACL_GROUP_OBJ : + if (pchk->groups++) + ok = FALSE; + if (id != (u32)-1) + ok = FALSE; + pchk->mode = (pchk->mode & 07707) | (perms << 3); + break; + case POSIX_ACL_OTHER : + if (pchk->others++) + ok = FALSE; + if (id != (u32)-1) + ok = FALSE; + pchk->mode |= perms; + break; + case POSIX_ACL_USER : + case POSIX_ACL_GROUP : + if (id == (u32)-1) + ok = FALSE; + break; + case POSIX_ACL_MASK : + if (id != (u32)-1) + ok = FALSE; + pchk->mode = (pchk->mode & 07707) | (perms << 3); + break; + default : + ok = FALSE; + break; + } + } + if ((pxdesc->acccnt > 0) + && ((checks[0].owners != 1) || (checks[0].groups != 1) + || (checks[0].others != 1))) + ok = FALSE; + /* do not check owner, group or other are present in */ + /* the default ACL, Windows does not necessarily set them */ + /* descriptor */ + if (pxdesc->defcnt && (pxdesc->acccnt > pxdesc->firstdef)) + ok = FALSE; + if ((pxdesc->acccnt < 0) || (pxdesc->defcnt < 0)) + ok = FALSE; + /* check mode, unless null or no tag set */ + if (pxdesc->mode + && checks[0].tagsset + && (checks[0].mode != (pxdesc->mode & 0777))) + ok = FALSE; + /* check tagsset */ + if (pxdesc->tagsset != checks[0].tagsset) + ok = FALSE; + return (ok); +} + +/* + * Set standard header data into a Posix ACL + * The mode argument should provide the 3 upper bits of target mode + */ + +static mode_t posix_header(struct POSIX_SECURITY *pxdesc, mode_t basemode) +{ + mode_t mode; + u16 tagsset; + struct POSIX_ACE *pace; + int i; + + mode = basemode & 07000; + tagsset = 0; + for (i=0; iacccnt; i++) { + pace = &pxdesc->acl.ace[i]; + tagsset |= pace->tag; + switch(pace->tag) { + case POSIX_ACL_USER_OBJ : + mode |= (pace->perms & 7) << 6; + break; + case POSIX_ACL_GROUP_OBJ : + case POSIX_ACL_MASK : + mode = (mode & 07707) | ((pace->perms & 7) << 3); + break; + case POSIX_ACL_OTHER : + mode |= pace->perms & 7; + break; + default : + break; + } + } + pxdesc->tagsset = tagsset; + pxdesc->mode = mode; + pxdesc->acl.version = POSIX_VERSION; + pxdesc->acl.flags = 0; + pxdesc->acl.filler = 0; + return (mode); +} + +/* + * Sort ACEs in a Posix ACL + * This is useful for always getting reusable converted ACLs, + * it also helps in merging ACEs. + * Repeated tag+id are allowed and not merged here. + * + * Tags should be in ascending sequence and for a repeatable tag + * ids should be in ascending sequence. + */ + +void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc) +{ + struct POSIX_ACL *pacl; + struct POSIX_ACE ace; + int i; + int offs; + BOOL done; + u16 tag; + u16 previous; + u32 id; + u32 previousid; + + + /* + * Check sequencing of tag+id in access ACE's + */ + pacl = &pxdesc->acl; + do { + done = TRUE; + previous = pacl->ace[0].tag; + previousid = pacl->ace[0].id; + for (i=1; iacccnt; i++) { + tag = pacl->ace[i].tag; + id = pacl->ace[i].id; + + if ((tag < previous) + || ((tag == previous) && (id < previousid))) { + done = FALSE; + memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE)); + memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE)); + memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE)); + } else { + previous = tag; + previousid = id; + } + } + } while (!done); + /* + * Same for default ACEs + */ + do { + done = TRUE; + if ((pxdesc->defcnt) > 1) { + offs = pxdesc->firstdef; + previous = pacl->ace[offs].tag; + previousid = pacl->ace[offs].id; + for (i=offs+1; idefcnt; i++) { + tag = pacl->ace[i].tag; + id = pacl->ace[i].id; + + if ((tag < previous) + || ((tag == previous) && (id < previousid))) { + done = FALSE; + memcpy(&ace,&pacl->ace[i-1],sizeof(struct POSIX_ACE)); + memcpy(&pacl->ace[i-1],&pacl->ace[i],sizeof(struct POSIX_ACE)); + memcpy(&pacl->ace[i],&ace,sizeof(struct POSIX_ACE)); + } else { + previous = tag; + previousid = id; + } + } + } + } while (!done); +} + +/* + * Merge a new mode into a Posix descriptor + * The Posix descriptor is not reallocated, its size is unchanged + * + * returns 0 if ok + */ + +int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode) +{ + int i; + BOOL maskfound; + struct POSIX_ACE *pace; + int todo; + + maskfound = FALSE; + todo = POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER; + for (i=pxdesc->acccnt-1; i>=0; i--) { + pace = &pxdesc->acl.ace[i]; + switch(pace->tag) { + case POSIX_ACL_USER_OBJ : + pace->perms = (mode >> 6) & 7; + todo &= ~POSIX_ACL_USER_OBJ; + break; + case POSIX_ACL_GROUP_OBJ : + if (!maskfound) + pace->perms = (mode >> 3) & 7; + todo &= ~POSIX_ACL_GROUP_OBJ; + break; + case POSIX_ACL_MASK : + pace->perms = (mode >> 3) & 7; + maskfound = TRUE; + break; + case POSIX_ACL_OTHER : + pace->perms = mode & 7; + todo &= ~POSIX_ACL_OTHER; + break; + default : + break; + } + } + pxdesc->mode = mode; + return (todo ? -1 : 0); +} + +/* + * Replace an access or default Posix ACL + * The resulting ACL is checked for validity + * + * Returns a new ACL or NULL if there is a problem + */ + +struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc, + const struct POSIX_ACL *newacl, int count, BOOL deflt) +{ + struct POSIX_SECURITY *newpxdesc; + size_t newsize; + int offset; + int oldoffset; + int i; + + if (deflt) + newsize = sizeof(struct POSIX_SECURITY) + + (oldpxdesc->acccnt + count)*sizeof(struct POSIX_ACE); + else + newsize = sizeof(struct POSIX_SECURITY) + + (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE); + newpxdesc = (struct POSIX_SECURITY*)malloc(newsize); + if (newpxdesc) { + if (deflt) { + offset = oldpxdesc->acccnt; + newpxdesc->acccnt = oldpxdesc->acccnt; + newpxdesc->defcnt = count; + newpxdesc->firstdef = offset; + /* copy access ACEs */ + for (i=0; iacccnt; i++) + newpxdesc->acl.ace[i] = oldpxdesc->acl.ace[i]; + /* copy default ACEs */ + for (i=0; iacl.ace[i + offset] = newacl->ace[i]; + } else { + offset = count; + newpxdesc->acccnt = count; + newpxdesc->defcnt = oldpxdesc->defcnt; + newpxdesc->firstdef = count; + /* copy access ACEs */ + for (i=0; iacl.ace[i] = newacl->ace[i]; + /* copy default ACEs */ + oldoffset = oldpxdesc->firstdef; + for (i=0; idefcnt; i++) + newpxdesc->acl.ace[i + offset] = oldpxdesc->acl.ace[i + oldoffset]; + } + /* assume special flags unchanged */ + posix_header(newpxdesc, oldpxdesc->mode); + if (!ntfs_valid_posix(newpxdesc)) { + /* do not log, this is an application error */ + free(newpxdesc); + newpxdesc = (struct POSIX_SECURITY*)NULL; + errno = EINVAL; + } + } else + errno = ENOMEM; + return (newpxdesc); +} + +/* + * Build an inherited Posix descriptor from parent + * descriptor (if any) restricted to creation mode + * + * Returns the inherited descriptor or NULL if there is a problem + */ + +struct POSIX_SECURITY *ntfs_build_inherited_posix( + const struct POSIX_SECURITY *pxdesc, mode_t mode, + mode_t mask, BOOL isdir) +{ + struct POSIX_SECURITY *pydesc; + struct POSIX_ACE *pyace; + int count; + int defcnt; + int size; + int i; + s16 tagsset; + + if (pxdesc && pxdesc->defcnt) { + if (isdir) + count = 2*pxdesc->defcnt + 3; + else + count = pxdesc->defcnt + 3; + } else + count = 3; + pydesc = (struct POSIX_SECURITY*)malloc( + sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE)); + if (pydesc) { + /* + * Copy inherited tags and adapt perms + * Use requested mode, ignoring umask + * (not possible with older versions of fuse) + */ + tagsset = 0; + defcnt = (pxdesc ? pxdesc->defcnt : 0); + for (i=defcnt-1; i>=0; i--) { + pyace = &pydesc->acl.ace[i]; + *pyace = pxdesc->acl.ace[pxdesc->firstdef + i]; + switch (pyace->tag) { + case POSIX_ACL_USER_OBJ : + pyace->perms &= (mode >> 6) & 7; + break; + case POSIX_ACL_GROUP_OBJ : + if (!(tagsset & POSIX_ACL_MASK)) + pyace->perms &= (mode >> 3) & 7; + break; + case POSIX_ACL_OTHER : + pyace->perms &= mode & 7; + break; + case POSIX_ACL_MASK : + pyace->perms &= (mode >> 3) & 7; + break; + default : + break; + } + tagsset |= pyace->tag; + } + pydesc->acccnt = defcnt; + /* + * If some standard tags were missing, append them from mode + * and sort the list + * Here we have to use the umask'ed mode + */ + if (~tagsset & (POSIX_ACL_USER_OBJ + | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER)) { + i = defcnt; + /* owner was missing */ + if (!(tagsset & POSIX_ACL_USER_OBJ)) { + pyace = &pydesc->acl.ace[i]; + pyace->tag = POSIX_ACL_USER_OBJ; + pyace->id = -1; + pyace->perms = ((mode & ~mask) >> 6) & 7; + tagsset |= POSIX_ACL_USER_OBJ; + i++; + } + /* owning group was missing */ + if (!(tagsset & POSIX_ACL_GROUP_OBJ)) { + pyace = &pydesc->acl.ace[i]; + pyace->tag = POSIX_ACL_GROUP_OBJ; + pyace->id = -1; + pyace->perms = ((mode & ~mask) >> 3) & 7; + tagsset |= POSIX_ACL_GROUP_OBJ; + i++; + } + /* other was missing */ + if (!(tagsset & POSIX_ACL_OTHER)) { + pyace = &pydesc->acl.ace[i]; + pyace->tag = POSIX_ACL_OTHER; + pyace->id = -1; + pyace->perms = mode & ~mask & 7; + tagsset |= POSIX_ACL_OTHER; + i++; + } + pydesc->acccnt = i; + pydesc->firstdef = i; + pydesc->defcnt = 0; + ntfs_sort_posix(pydesc); + } + + /* + * append as a default ACL if a directory + */ + pydesc->firstdef = pydesc->acccnt; + if (defcnt && isdir) { + size = sizeof(struct POSIX_ACE)*defcnt; + memcpy(&pydesc->acl.ace[pydesc->firstdef], + &pxdesc->acl.ace[pxdesc->firstdef],size); + pydesc->defcnt = defcnt; + } else { + pydesc->defcnt = 0; + } + /* assume special bits are not inherited */ + posix_header(pydesc, mode & 07000); + if (!ntfs_valid_posix(pydesc)) { + ntfs_log_error("Error building an inherited Posix desc\n"); + errno = EIO; + free(pydesc); + pydesc = (struct POSIX_SECURITY*)NULL; + } + } else + errno = ENOMEM; + return (pydesc); +} + +static int merge_lists_posix(struct POSIX_ACE *targetace, + const struct POSIX_ACE *firstace, + const struct POSIX_ACE *secondace, + int firstcnt, int secondcnt) +{ + int k; + + k = 0; + /* + * No list is exhausted : + * if same tag+id in both list : + * ignore ACE from second list + * else take the one with smaller tag+id + */ + while ((firstcnt > 0) && (secondcnt > 0)) + if ((firstace->tag == secondace->tag) + && (firstace->id == secondace->id)) { + secondace++; + secondcnt--; + } else + if ((firstace->tag < secondace->tag) + || ((firstace->tag == secondace->tag) + && (firstace->id < secondace->id))) { + targetace->tag = firstace->tag; + targetace->id = firstace->id; + targetace->perms = firstace->perms; + firstace++; + targetace++; + firstcnt--; + k++; + } else { + targetace->tag = secondace->tag; + targetace->id = secondace->id; + targetace->perms = secondace->perms; + secondace++; + targetace++; + secondcnt--; + k++; + } + /* + * One list is exhausted, copy the other one + */ + while (firstcnt > 0) { + targetace->tag = firstace->tag; + targetace->id = firstace->id; + targetace->perms = firstace->perms; + firstace++; + targetace++; + firstcnt--; + k++; + } + while (secondcnt > 0) { + targetace->tag = secondace->tag; + targetace->id = secondace->id; + targetace->perms = secondace->perms; + secondace++; + targetace++; + secondcnt--; + k++; + } + return (k); +} + +/* + * Merge two Posix ACLs + * The input ACLs have to be adequately sorted + * + * Returns the merged ACL, which is allocated and has to be freed by caller, + * or NULL if failed + */ + +struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first, + const struct POSIX_SECURITY *second) +{ + struct POSIX_SECURITY *pxdesc; + struct POSIX_ACE *targetace; + const struct POSIX_ACE *firstace; + const struct POSIX_ACE *secondace; + size_t size; + int k; + + size = sizeof(struct POSIX_SECURITY) + + (first->acccnt + first->defcnt + + second->acccnt + second->defcnt)*sizeof(struct POSIX_ACE); + pxdesc = (struct POSIX_SECURITY*)malloc(size); + if (pxdesc) { + /* + * merge access ACEs + */ + firstace = first->acl.ace; + secondace = second->acl.ace; + targetace = pxdesc->acl.ace; + k = merge_lists_posix(targetace,firstace,secondace, + first->acccnt,second->acccnt); + pxdesc->acccnt = k; + /* + * merge default ACEs + */ + pxdesc->firstdef = k; + firstace = &first->acl.ace[first->firstdef]; + secondace = &second->acl.ace[second->firstdef]; + targetace = &pxdesc->acl.ace[k]; + k = merge_lists_posix(targetace,firstace,secondace, + first->defcnt,second->defcnt); + pxdesc->defcnt = k; + /* + * build header + */ + pxdesc->acl.version = POSIX_VERSION; + pxdesc->acl.flags = 0; + pxdesc->acl.filler = 0; + pxdesc->mode = 0; + pxdesc->tagsset = 0; + } else + errno = ENOMEM; + return (pxdesc); +} + +struct BUILD_CONTEXT { + BOOL isdir; + BOOL adminowns; + BOOL groupowns; + u16 selfuserperms; + u16 selfgrpperms; + u16 grpperms; + u16 othperms; + u16 mask; + u16 designates; + u16 withmask; + u16 rootspecial; +} ; + + + +static BOOL build_user_denials(ACL *pacl, + const SID *usid, struct MAPPING* const mapping[], + ACE_FLAGS flags, const struct POSIX_ACE *pxace, + struct BUILD_CONTEXT *pset) +{ + BIGSID defsid; + ACCESS_ALLOWED_ACE *pdace; + const SID *sid; + int sidsz; + int pos; + int acecnt; + le32 grants; + le32 denials; + u16 perms; + u16 mixperms; + u16 tag; + BOOL rejected; + BOOL rootuser; + BOOL avoidmask; + + rejected = FALSE; + tag = pxace->tag; + perms = pxace->perms; + rootuser = FALSE; + pos = le16_to_cpu(pacl->size); + acecnt = le16_to_cpu(pacl->ace_count); + avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X)) + && ((pset->designates && pset->withmask) + || (!pset->designates && !pset->withmask)); + if (tag == POSIX_ACL_USER_OBJ) { + sid = usid; + sidsz = ntfs_sid_size(sid); + grants = OWNER_RIGHTS; + } else { + if (pxace->id) { + sid = NTFS_FIND_USID(mapping[MAPUSERS], + pxace->id, (SID*)&defsid); + grants = WORLD_RIGHTS; + } else { + sid = adminsid; + rootuser = TRUE; + grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK; + } + if (sid) { + sidsz = ntfs_sid_size(sid); + /* + * Insert denial of complement of mask for + * each designated user (except root) + * WRITE_OWNER is inserted so that + * the mask can be identified + */ + if (!avoidmask && !rootuser) { + denials = WRITE_OWNER; + pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + if (pset->isdir) { + if (!(pset->mask & POSIX_PERM_X)) + denials |= DIR_EXEC; + if (!(pset->mask & POSIX_PERM_W)) + denials |= DIR_WRITE; + if (!(pset->mask & POSIX_PERM_R)) + denials |= DIR_READ; + } else { + if (!(pset->mask & POSIX_PERM_X)) + denials |= FILE_EXEC; + if (!(pset->mask & POSIX_PERM_W)) + denials |= FILE_WRITE; + if (!(pset->mask & POSIX_PERM_R)) + denials |= FILE_READ; + } + if (rootuser) + grants &= ~ROOT_OWNER_UNMARK; + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = flags; + pdace->size = cpu_to_le16(sidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt++; + } + } else + rejected = TRUE; + } + if (!rejected) { + if (pset->isdir) { + if (perms & POSIX_PERM_X) + grants |= DIR_EXEC; + if (perms & POSIX_PERM_W) + grants |= DIR_WRITE; + if (perms & POSIX_PERM_R) + grants |= DIR_READ; + } else { + if (perms & POSIX_PERM_X) + grants |= FILE_EXEC; + if (perms & POSIX_PERM_W) + grants |= FILE_WRITE; + if (perms & POSIX_PERM_R) + grants |= FILE_READ; + } + + /* a possible ACE to deny owner what he/she would */ + /* induely get from administrator, group or world */ + /* unless owner is administrator or group */ + + denials = const_cpu_to_le32(0); + pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + if (!pset->adminowns && !rootuser) { + if (!pset->groupowns) { + mixperms = pset->grpperms | pset->othperms; + if (tag == POSIX_ACL_USER_OBJ) + mixperms |= pset->selfuserperms; + if (pset->isdir) { + if (mixperms & POSIX_PERM_X) + denials |= DIR_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= DIR_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= DIR_READ; + } else { + if (mixperms & POSIX_PERM_X) + denials |= FILE_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= FILE_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= FILE_READ; + } + } else { + mixperms = ~pset->grpperms & pset->othperms; + if (tag == POSIX_ACL_USER_OBJ) + mixperms |= pset->selfuserperms; + if (pset->isdir) { + if (mixperms & POSIX_PERM_X) + denials |= DIR_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= DIR_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= DIR_READ; + } else { + if (mixperms & POSIX_PERM_X) + denials |= FILE_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= FILE_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= FILE_READ; + } + } + denials &= ~grants; + if (denials) { + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = flags; + pdace->size = cpu_to_le16(sidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt++; + } + } + } + pacl->size = cpu_to_le16(pos); + pacl->ace_count = cpu_to_le16(acecnt); + return (!rejected); +} + +static BOOL build_user_grants(ACL *pacl, + const SID *usid, struct MAPPING* const mapping[], + ACE_FLAGS flags, const struct POSIX_ACE *pxace, + struct BUILD_CONTEXT *pset) +{ + BIGSID defsid; + ACCESS_ALLOWED_ACE *pgace; + const SID *sid; + int sidsz; + int pos; + int acecnt; + le32 grants; + u16 perms; + u16 tag; + BOOL rejected; + BOOL rootuser; + + rejected = FALSE; + tag = pxace->tag; + perms = pxace->perms; + rootuser = FALSE; + pos = le16_to_cpu(pacl->size); + acecnt = le16_to_cpu(pacl->ace_count); + if (tag == POSIX_ACL_USER_OBJ) { + sid = usid; + sidsz = ntfs_sid_size(sid); + grants = OWNER_RIGHTS; + } else { + if (pxace->id) { + sid = NTFS_FIND_USID(mapping[MAPUSERS], + pxace->id, (SID*)&defsid); + if (sid) + sidsz = ntfs_sid_size(sid); + else + rejected = TRUE; + grants = WORLD_RIGHTS; + } else { + sid = adminsid; + sidsz = ntfs_sid_size(sid); + rootuser = TRUE; + grants = WORLD_RIGHTS & ~ROOT_OWNER_UNMARK; + } + } + if (!rejected) { + if (pset->isdir) { + if (perms & POSIX_PERM_X) + grants |= DIR_EXEC; + if (perms & POSIX_PERM_W) + grants |= DIR_WRITE; + if (perms & POSIX_PERM_R) + grants |= DIR_READ; + } else { + if (perms & POSIX_PERM_X) + grants |= FILE_EXEC; + if (perms & POSIX_PERM_W) + grants |= FILE_WRITE; + if (perms & POSIX_PERM_R) + grants |= FILE_READ; + } + if (rootuser) + grants &= ~ROOT_OWNER_UNMARK; + pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->size = cpu_to_le16(sidsz + 8); + pgace->flags = flags; + pgace->mask = grants; + memcpy((char*)&pgace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt = le16_to_cpu(pacl->ace_count) + 1; + pacl->ace_count = cpu_to_le16(acecnt); + pacl->size = cpu_to_le16(pos); + } + return (!rejected); +} + + + /* a grant ACE for group */ + /* unless group-obj has the same rights as world */ + /* but present if group is owner or owner is administrator */ + /* this ACE will be inserted after denials for group */ + +static BOOL build_group_denials_grant(ACL *pacl, + const SID *gsid, struct MAPPING* const mapping[], + ACE_FLAGS flags, const struct POSIX_ACE *pxace, + struct BUILD_CONTEXT *pset) +{ + BIGSID defsid; + ACCESS_ALLOWED_ACE *pdace; + ACCESS_ALLOWED_ACE *pgace; + const SID *sid; + int sidsz; + int pos; + int acecnt; + le32 grants; + le32 denials; + u16 perms; + u16 mixperms; + u16 tag; + BOOL avoidmask; + BOOL rootgroup; + BOOL rejected; + + rejected = FALSE; + tag = pxace->tag; + perms = pxace->perms; + pos = le16_to_cpu(pacl->size); + acecnt = le16_to_cpu(pacl->ace_count); + rootgroup = FALSE; + avoidmask = (pset->mask == (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X)) + && ((pset->designates && pset->withmask) + || (!pset->designates && !pset->withmask)); + if (tag == POSIX_ACL_GROUP_OBJ) + sid = gsid; + else + if (pxace->id) + sid = NTFS_FIND_GSID(mapping[MAPGROUPS], + pxace->id, (SID*)&defsid); + else { + sid = adminsid; + rootgroup = TRUE; + } + if (sid) { + sidsz = ntfs_sid_size(sid); + /* + * Insert denial of complement of mask for + * each group + * WRITE_OWNER is inserted so that + * the mask can be identified + * Note : this mask may lead on Windows to + * deny rights to administrators belonging + * to some user group + */ + if ((!avoidmask && !rootgroup) + || (pset->rootspecial + && (tag == POSIX_ACL_GROUP_OBJ))) { + denials = WRITE_OWNER; + pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + if (pset->isdir) { + if (!(pset->mask & POSIX_PERM_X)) + denials |= DIR_EXEC; + if (!(pset->mask & POSIX_PERM_W)) + denials |= DIR_WRITE; + if (!(pset->mask & POSIX_PERM_R)) + denials |= DIR_READ; + } else { + if (!(pset->mask & POSIX_PERM_X)) + denials |= FILE_EXEC; + if (!(pset->mask & POSIX_PERM_W)) + denials |= FILE_WRITE; + if (!(pset->mask & POSIX_PERM_R)) + denials |= FILE_READ; + } + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = flags; + pdace->size = cpu_to_le16(sidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt++; + } + } else + rejected = TRUE; + if (!rejected + && (pset->adminowns + || pset->groupowns + || avoidmask + || rootgroup + || (perms != pset->othperms))) { + grants = WORLD_RIGHTS; + if (rootgroup) + grants &= ~ROOT_GROUP_UNMARK; + if (pset->isdir) { + if (perms & POSIX_PERM_X) + grants |= DIR_EXEC; + if (perms & POSIX_PERM_W) + grants |= DIR_WRITE; + if (perms & POSIX_PERM_R) + grants |= DIR_READ; + } else { + if (perms & POSIX_PERM_X) + grants |= FILE_EXEC; + if (perms & POSIX_PERM_W) + grants |= FILE_WRITE; + if (perms & POSIX_PERM_R) + grants |= FILE_READ; + } + + /* a possible ACE to deny group what it would get from world */ + /* or administrator, unless owner is administrator or group */ + + denials = const_cpu_to_le32(0); + pdace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + if (!pset->adminowns + && !pset->groupowns + && !rootgroup) { + mixperms = pset->othperms; + if (tag == POSIX_ACL_GROUP_OBJ) + mixperms |= pset->selfgrpperms; + if (pset->isdir) { + if (mixperms & POSIX_PERM_X) + denials |= DIR_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= DIR_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= DIR_READ; + } else { + if (mixperms & POSIX_PERM_X) + denials |= FILE_EXEC; + if (mixperms & POSIX_PERM_W) + denials |= FILE_WRITE; + if (mixperms & POSIX_PERM_R) + denials |= FILE_READ; + } + denials &= ~(grants | OWNER_RIGHTS); + if (denials) { + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = flags; + pdace->size = cpu_to_le16(sidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt++; + } + } + + /* now insert grants to group if more than world */ + if (pset->adminowns + || pset->groupowns + || (avoidmask && (pset->designates || pset->withmask)) + || (perms & ~pset->othperms) + || (pset->rootspecial + && (tag == POSIX_ACL_GROUP_OBJ)) + || (tag == POSIX_ACL_GROUP)) { + if (rootgroup) + grants &= ~ROOT_GROUP_UNMARK; + pgace = (ACCESS_DENIED_ACE*)&((char*)pacl)[pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = flags; + pgace->size = cpu_to_le16(sidsz + 8); + pgace->mask = grants; + memcpy((char*)&pgace->sid, sid, sidsz); + pos += sidsz + 8; + acecnt++; + } + } + pacl->size = cpu_to_le16(pos); + pacl->ace_count = cpu_to_le16(acecnt); + return (!rejected); +} + + +/* + * Build an ACL composed of several ACE's + * returns size of ACL or zero if failed + * + * Three schemes are defined : + * + * 1) if root is neither owner nor group up to 7 ACE's are set up : + * - denials to owner (preventing grants to world or group to apply) + * + mask denials to designated user (unless mask allows all) + * + denials to designated user + * - grants to owner (always present - first grant) + * + grants to designated user + * + mask denial to group (unless mask allows all) + * - denials to group (preventing grants to world to apply) + * - grants to group (unless group has no more than world rights) + * + mask denials to designated group (unless mask allows all) + * + grants to designated group + * + denials to designated group + * - grants to world (unless none) + * - full privileges to administrator, always present + * - full privileges to system, always present + * + * The same scheme is applied for Posix ACLs, with the mask represented + * as denials prepended to grants for designated users and groups + * + * This is inspired by an Internet Draft from Marius Aamodt Eriksen + * for mapping NFSv4 ACLs to Posix ACLs (draft-ietf-nfsv4-acl-mapping-00.txt) + * More recent versions of the draft (draft-ietf-nfsv4-acl-mapping-05.txt) + * are not followed, as they ignore the Posix mask and lead to + * loss of compatibility with Linux implementations on other fs. + * + * Note that denials to group are located after grants to owner. + * This only occurs in the unfrequent situation where world + * has more rights than group and cannot be avoided if owner and other + * have some common right which is denied to group (eg for mode 745 + * executing has to be denied to group, but not to owner or world). + * This rare situation is processed by Windows correctly, but + * Windows utilities may want to change the order, with a + * consequence of applying the group denials to the Windows owner. + * The interpretation on Linux is not affected by the order change. + * + * 2) if root is either owner or group, two problems arise : + * - granting full rights to administrator (as needed to transpose + * to Windows rights bypassing granting to root) would imply + * Linux permissions to always be seen as rwx, no matter the chmod + * - there is no different SID to separate an administrator owner + * from an administrator group. Hence Linux permissions for owner + * would always be similar to permissions to group. + * + * as a work-around, up to 5 ACE's are set up if owner or group : + * - grants to owner, always present at first position + * - grants to group, always present + * - grants to world, unless none + * - full privileges to administrator, always present + * - full privileges to system, always present + * + * On Windows, these ACE's are processed normally, though they + * are redundant (owner, group and administrator are the same, + * as a consequence any denials would damage administrator rights) + * but on Linux, privileges to administrator are ignored (they + * are not needed as root has always full privileges), and + * neither grants to group are applied to owner, nor grants to + * world are applied to owner or group. + * + * 3) finally a similar situation arises when group is owner (they + * have the same SID), but is not root. + * In this situation up to 6 ACE's are set up : + * + * - denials to owner (preventing grants to world to apply) + * - grants to owner (always present) + * - grants to group (unless groups has same rights as world) + * - grants to world (unless none) + * - full privileges to administrator, always present + * - full privileges to system, always present + * + * On Windows, these ACE's are processed normally, though they + * are redundant (as owner and group are the same), but this has + * no impact on administrator rights + * + * Special flags (S_ISVTX, S_ISGID, S_ISUID) : + * an extra null ACE is inserted to hold these flags, using + * the same conventions as cygwin. + * + */ + +static int buildacls_posix(struct MAPPING* const mapping[], + char *secattr, int offs, const struct POSIX_SECURITY *pxdesc, + int isdir, const SID *usid, const SID *gsid) +{ + struct BUILD_CONTEXT aceset[2], *pset; + BOOL adminowns; + BOOL groupowns; + ACL *pacl; + ACCESS_ALLOWED_ACE *pgace; + ACCESS_ALLOWED_ACE *pdace; + const struct POSIX_ACE *pxace; + BOOL ok; + mode_t mode; + u16 tag; + u16 perms; + ACE_FLAGS flags; + int pos; + int i; + int k; + BIGSID defsid; + const SID *sid; + int acecnt; + int usidsz; + int gsidsz; + int wsidsz; + int asidsz; + int ssidsz; + int nsidsz; + le32 grants; + + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + wsidsz = ntfs_sid_size(worldsid); + asidsz = ntfs_sid_size(adminsid); + ssidsz = ntfs_sid_size(systemsid); + mode = pxdesc->mode; + /* adminowns and groupowns are used for both lists */ + adminowns = ntfs_same_sid(usid, adminsid) + || ntfs_same_sid(gsid, adminsid); + groupowns = !adminowns && ntfs_same_sid(usid, gsid); + + ok = TRUE; + + /* ACL header */ + pacl = (ACL*)&secattr[offs]; + pacl->revision = ACL_REVISION; + pacl->alignment1 = 0; + pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8); + pacl->ace_count = const_cpu_to_le16(0); + pacl->alignment2 = const_cpu_to_le16(0); + + /* + * Determine what is allowed to some group or world + * to prevent designated users or other groups to get + * rights from groups or world + * Do the same if owner and group appear as designated + * user or group + * Also get global mask + */ + for (k=0; k<2; k++) { + pset = &aceset[k]; + pset->selfuserperms = 0; + pset->selfgrpperms = 0; + pset->grpperms = 0; + pset->othperms = 0; + pset->mask = (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X); + pset->designates = 0; + pset->withmask = 0; + pset->rootspecial = 0; + pset->adminowns = adminowns; + pset->groupowns = groupowns; + pset->isdir = isdir; + } + + for (i=pxdesc->acccnt+pxdesc->defcnt-1; i>=0; i--) { + if (i >= pxdesc->acccnt) { + pset = &aceset[1]; + pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt]; + } else { + pset = &aceset[0]; + pxace = &pxdesc->acl.ace[i]; + } + switch (pxace->tag) { + case POSIX_ACL_USER : + pset->designates++; + if (pxace->id) { + sid = NTFS_FIND_USID(mapping[MAPUSERS], + pxace->id, (SID*)&defsid); + if (sid && ntfs_same_sid(sid,usid)) + pset->selfuserperms |= pxace->perms; + } else + /* root as designated user is processed apart */ + pset->rootspecial = TRUE; + break; + case POSIX_ACL_GROUP : + pset->designates++; + if (pxace->id) { + sid = NTFS_FIND_GSID(mapping[MAPUSERS], + pxace->id, (SID*)&defsid); + if (sid && ntfs_same_sid(sid,gsid)) + pset->selfgrpperms |= pxace->perms; + } else + /* root as designated group is processed apart */ + pset->rootspecial = TRUE; + /* fall through */ + case POSIX_ACL_GROUP_OBJ : + pset->grpperms |= pxace->perms; + break; + case POSIX_ACL_OTHER : + pset->othperms = pxace->perms; + break; + case POSIX_ACL_MASK : + pset->withmask++; + pset->mask = pxace->perms; + default : + break; + } + } + +if (pxdesc->defcnt && (pxdesc->firstdef != pxdesc->acccnt)) { +ntfs_log_error("** error : access and default not consecutive\n"); +return (0); +} + /* + * First insert all denials for owner and each + * designated user (with mask if needed) + */ + + pacl->ace_count = const_cpu_to_le16(0); + pacl->size = const_cpu_to_le16(sizeof(ACL)); + for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) { + if (i >= pxdesc->acccnt) { + flags = INHERIT_ONLY_ACE + | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + pset = &aceset[1]; + pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt]; + } else { + if (pxdesc->defcnt) + flags = NO_PROPAGATE_INHERIT_ACE; + else + flags = (isdir ? DIR_INHERITANCE + : FILE_INHERITANCE); + pset = &aceset[0]; + pxace = &pxdesc->acl.ace[i]; + } + tag = pxace->tag; + perms = pxace->perms; + switch (tag) { + + /* insert denial ACEs for each owner or allowed user */ + + case POSIX_ACL_USER : + case POSIX_ACL_USER_OBJ : + + ok = build_user_denials(pacl, + usid, mapping, flags, pxace, pset); + break; + default : + break; + } + } + + /* + * for directories, insert a world execution denial + * inherited to plain files. + * This is to prevent Windows from granting execution + * of files through inheritance from parent directory + */ + + if (isdir && ok) { + pos = le16_to_cpu(pacl->size); + pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos]; + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; + pdace->size = cpu_to_le16(wsidsz + 8); + pdace->mask = FILE_EXEC; + memcpy((char*)&pdace->sid, worldsid, wsidsz); + pos += wsidsz + 8; + acecnt = le16_to_cpu(pacl->ace_count) + 1; + pacl->ace_count = cpu_to_le16(acecnt); + pacl->size = cpu_to_le16(pos); + } + + /* + * now insert (if needed) + * - grants to owner and designated users + * - mask and denials for all groups + * - grants to other + */ + + for (i=0; (i<(pxdesc->acccnt + pxdesc->defcnt)) && ok; i++) { + if (i >= pxdesc->acccnt) { + flags = INHERIT_ONLY_ACE + | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + pset = &aceset[1]; + pxace = &pxdesc->acl.ace[i + pxdesc->firstdef - pxdesc->acccnt]; + } else { + if (pxdesc->defcnt) + flags = NO_PROPAGATE_INHERIT_ACE; + else + flags = (isdir ? DIR_INHERITANCE + : FILE_INHERITANCE); + pset = &aceset[0]; + pxace = &pxdesc->acl.ace[i]; + } + tag = pxace->tag; + perms = pxace->perms; + switch (tag) { + + /* ACE for each owner or allowed user */ + + case POSIX_ACL_USER : + case POSIX_ACL_USER_OBJ : + ok = build_user_grants(pacl,usid, + mapping,flags,pxace,pset); + break; + + case POSIX_ACL_GROUP : + case POSIX_ACL_GROUP_OBJ : + + /* denials and grants for groups */ + + ok = build_group_denials_grant(pacl,gsid, + mapping,flags,pxace,pset); + break; + + case POSIX_ACL_OTHER : + + /* grants for other users */ + + pos = le16_to_cpu(pacl->size); + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + grants = WORLD_RIGHTS; + if (isdir) { + if (perms & POSIX_PERM_X) + grants |= DIR_EXEC; + if (perms & POSIX_PERM_W) + grants |= DIR_WRITE; + if (perms & POSIX_PERM_R) + grants |= DIR_READ; + } else { + if (perms & POSIX_PERM_X) + grants |= FILE_EXEC; + if (perms & POSIX_PERM_W) + grants |= FILE_WRITE; + if (perms & POSIX_PERM_R) + grants |= FILE_READ; + } + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = flags; + pgace->size = cpu_to_le16(wsidsz + 8); + pgace->mask = grants; + memcpy((char*)&pgace->sid, worldsid, wsidsz); + pos += wsidsz + 8; + acecnt = le16_to_cpu(pacl->ace_count) + 1; + pacl->ace_count = cpu_to_le16(acecnt); + pacl->size = cpu_to_le16(pos); + break; + } + } + + if (!ok) { + errno = EINVAL; + pos = 0; + } else { + /* an ACE for administrators */ + /* always full access */ + + pos = le16_to_cpu(pacl->size); + acecnt = le16_to_cpu(pacl->ace_count); + if (isdir) + flags = OBJECT_INHERIT_ACE + | CONTAINER_INHERIT_ACE; + else + flags = NO_PROPAGATE_INHERIT_ACE; + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = flags; + pgace->size = cpu_to_le16(asidsz + 8); + grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC; + pgace->mask = grants; + memcpy((char*)&pgace->sid, adminsid, asidsz); + pos += asidsz + 8; + acecnt++; + + /* an ACE for system (needed ?) */ + /* always full access */ + + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = flags; + pgace->size = cpu_to_le16(ssidsz + 8); + grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC; + pgace->mask = grants; + memcpy((char*)&pgace->sid, systemsid, ssidsz); + pos += ssidsz + 8; + acecnt++; + + /* a null ACE to hold special flags */ + /* using the same representation as cygwin */ + + if (mode & (S_ISVTX | S_ISGID | S_ISUID)) { + nsidsz = ntfs_sid_size(nullsid); + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = NO_PROPAGATE_INHERIT_ACE; + pgace->size = cpu_to_le16(nsidsz + 8); + grants = const_cpu_to_le32(0); + if (mode & S_ISUID) + grants |= FILE_APPEND_DATA; + if (mode & S_ISGID) + grants |= FILE_WRITE_DATA; + if (mode & S_ISVTX) + grants |= FILE_READ_DATA; + pgace->mask = grants; + memcpy((char*)&pgace->sid, nullsid, nsidsz); + pos += nsidsz + 8; + acecnt++; + } + + /* fix ACL header */ + pacl->size = cpu_to_le16(pos); + pacl->ace_count = cpu_to_le16(acecnt); + } + return (ok ? pos : 0); +} + +#endif /* POSIXACLS */ + +static int buildacls(char *secattr, int offs, mode_t mode, int isdir, + const SID * usid, const SID * gsid) +{ + ACL *pacl; + ACCESS_ALLOWED_ACE *pgace; + ACCESS_ALLOWED_ACE *pdace; + BOOL adminowns; + BOOL groupowns; + ACE_FLAGS gflags; + int pos; + int acecnt; + int usidsz; + int gsidsz; + int wsidsz; + int asidsz; + int ssidsz; + int nsidsz; + le32 grants; + le32 denials; + + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + wsidsz = ntfs_sid_size(worldsid); + asidsz = ntfs_sid_size(adminsid); + ssidsz = ntfs_sid_size(systemsid); + adminowns = ntfs_same_sid(usid, adminsid) + || ntfs_same_sid(gsid, adminsid); + groupowns = !adminowns && ntfs_same_sid(usid, gsid); + + /* ACL header */ + pacl = (ACL*)&secattr[offs]; + pacl->revision = ACL_REVISION; + pacl->alignment1 = 0; + pacl->size = cpu_to_le16(sizeof(ACL) + usidsz + 8); + pacl->ace_count = const_cpu_to_le16(1); + pacl->alignment2 = const_cpu_to_le16(0); + pos = sizeof(ACL); + acecnt = 0; + + /* compute a grant ACE for owner */ + /* this ACE will be inserted after denial for owner */ + + grants = OWNER_RIGHTS; + if (isdir) { + gflags = DIR_INHERITANCE; + if (mode & S_IXUSR) + grants |= DIR_EXEC; + if (mode & S_IWUSR) + grants |= DIR_WRITE; + if (mode & S_IRUSR) + grants |= DIR_READ; + } else { + gflags = FILE_INHERITANCE; + if (mode & S_IXUSR) + grants |= FILE_EXEC; + if (mode & S_IWUSR) + grants |= FILE_WRITE; + if (mode & S_IRUSR) + grants |= FILE_READ; + } + + /* a possible ACE to deny owner what he/she would */ + /* induely get from administrator, group or world */ + /* unless owner is administrator or group */ + + denials = const_cpu_to_le32(0); + pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos]; + if (!adminowns) { + if (!groupowns) { + if (isdir) { + pdace->flags = DIR_INHERITANCE; + if (mode & (S_IXGRP | S_IXOTH)) + denials |= DIR_EXEC; + if (mode & (S_IWGRP | S_IWOTH)) + denials |= DIR_WRITE; + if (mode & (S_IRGRP | S_IROTH)) + denials |= DIR_READ; + } else { + pdace->flags = FILE_INHERITANCE; + if (mode & (S_IXGRP | S_IXOTH)) + denials |= FILE_EXEC; + if (mode & (S_IWGRP | S_IWOTH)) + denials |= FILE_WRITE; + if (mode & (S_IRGRP | S_IROTH)) + denials |= FILE_READ; + } + } else { + if (isdir) { + pdace->flags = DIR_INHERITANCE; + if ((mode & S_IXOTH) && !(mode & S_IXGRP)) + denials |= DIR_EXEC; + if ((mode & S_IWOTH) && !(mode & S_IWGRP)) + denials |= DIR_WRITE; + if ((mode & S_IROTH) && !(mode & S_IRGRP)) + denials |= DIR_READ; + } else { + pdace->flags = FILE_INHERITANCE; + if ((mode & S_IXOTH) && !(mode & S_IXGRP)) + denials |= FILE_EXEC; + if ((mode & S_IWOTH) && !(mode & S_IWGRP)) + denials |= FILE_WRITE; + if ((mode & S_IROTH) && !(mode & S_IRGRP)) + denials |= FILE_READ; + } + } + denials &= ~grants; + if (denials) { + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->size = cpu_to_le16(usidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, usid, usidsz); + pos += usidsz + 8; + acecnt++; + } + } + /* + * for directories, a world execution denial + * inherited to plain files + */ + + if (isdir) { + pdace = (ACCESS_DENIED_ACE*) &secattr[offs + pos]; + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->flags = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; + pdace->size = cpu_to_le16(wsidsz + 8); + pdace->mask = FILE_EXEC; + memcpy((char*)&pdace->sid, worldsid, wsidsz); + pos += wsidsz + 8; + acecnt++; + } + + + /* now insert grants to owner */ + pgace = (ACCESS_ALLOWED_ACE*) &secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->size = cpu_to_le16(usidsz + 8); + pgace->flags = gflags; + pgace->mask = grants; + memcpy((char*)&pgace->sid, usid, usidsz); + pos += usidsz + 8; + acecnt++; + + /* a grant ACE for group */ + /* unless group has the same rights as world */ + /* but present if group is owner or owner is administrator */ + /* this ACE will be inserted after denials for group */ + + if (adminowns + || groupowns + || (((mode >> 3) ^ mode) & 7)) { + grants = WORLD_RIGHTS; + if (isdir) { + gflags = DIR_INHERITANCE; + if (mode & S_IXGRP) + grants |= DIR_EXEC; + if (mode & S_IWGRP) + grants |= DIR_WRITE; + if (mode & S_IRGRP) + grants |= DIR_READ; + } else { + gflags = FILE_INHERITANCE; + if (mode & S_IXGRP) + grants |= FILE_EXEC; + if (mode & S_IWGRP) + grants |= FILE_WRITE; + if (mode & S_IRGRP) + grants |= FILE_READ; + } + + /* a possible ACE to deny group what it would get from world */ + /* or administrator, unless owner is administrator or group */ + + denials = const_cpu_to_le32(0); + pdace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + if (!adminowns && !groupowns) { + if (isdir) { + pdace->flags = DIR_INHERITANCE; + if (mode & S_IXOTH) + denials |= DIR_EXEC; + if (mode & S_IWOTH) + denials |= DIR_WRITE; + if (mode & S_IROTH) + denials |= DIR_READ; + } else { + pdace->flags = FILE_INHERITANCE; + if (mode & S_IXOTH) + denials |= FILE_EXEC; + if (mode & S_IWOTH) + denials |= FILE_WRITE; + if (mode & S_IROTH) + denials |= FILE_READ; + } + denials &= ~(grants | OWNER_RIGHTS); + if (denials) { + pdace->type = ACCESS_DENIED_ACE_TYPE; + pdace->size = cpu_to_le16(gsidsz + 8); + pdace->mask = denials; + memcpy((char*)&pdace->sid, gsid, gsidsz); + pos += gsidsz + 8; + acecnt++; + } + } + + if (adminowns + || groupowns + || ((mode >> 3) & ~mode & 7)) { + /* now insert grants to group */ + /* if more rights than other */ + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = gflags; + pgace->size = cpu_to_le16(gsidsz + 8); + pgace->mask = grants; + memcpy((char*)&pgace->sid, gsid, gsidsz); + pos += gsidsz + 8; + acecnt++; + } + } + + /* an ACE for world users */ + + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + grants = WORLD_RIGHTS; + if (isdir) { + pgace->flags = DIR_INHERITANCE; + if (mode & S_IXOTH) + grants |= DIR_EXEC; + if (mode & S_IWOTH) + grants |= DIR_WRITE; + if (mode & S_IROTH) + grants |= DIR_READ; + } else { + pgace->flags = FILE_INHERITANCE; + if (mode & S_IXOTH) + grants |= FILE_EXEC; + if (mode & S_IWOTH) + grants |= FILE_WRITE; + if (mode & S_IROTH) + grants |= FILE_READ; + } + pgace->size = cpu_to_le16(wsidsz + 8); + pgace->mask = grants; + memcpy((char*)&pgace->sid, worldsid, wsidsz); + pos += wsidsz + 8; + acecnt++; + + /* an ACE for administrators */ + /* always full access */ + + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + if (isdir) + pgace->flags = DIR_INHERITANCE; + else + pgace->flags = FILE_INHERITANCE; + pgace->size = cpu_to_le16(asidsz + 8); + grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC; + pgace->mask = grants; + memcpy((char*)&pgace->sid, adminsid, asidsz); + pos += asidsz + 8; + acecnt++; + + /* an ACE for system (needed ?) */ + /* always full access */ + + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + if (isdir) + pgace->flags = DIR_INHERITANCE; + else + pgace->flags = FILE_INHERITANCE; + pgace->size = cpu_to_le16(ssidsz + 8); + grants = OWNER_RIGHTS | FILE_READ | FILE_WRITE | FILE_EXEC; + pgace->mask = grants; + memcpy((char*)&pgace->sid, systemsid, ssidsz); + pos += ssidsz + 8; + acecnt++; + + /* a null ACE to hold special flags */ + /* using the same representation as cygwin */ + + if (mode & (S_ISVTX | S_ISGID | S_ISUID)) { + nsidsz = ntfs_sid_size(nullsid); + pgace = (ACCESS_ALLOWED_ACE*)&secattr[offs + pos]; + pgace->type = ACCESS_ALLOWED_ACE_TYPE; + pgace->flags = NO_PROPAGATE_INHERIT_ACE; + pgace->size = cpu_to_le16(nsidsz + 8); + grants = const_cpu_to_le32(0); + if (mode & S_ISUID) + grants |= FILE_APPEND_DATA; + if (mode & S_ISGID) + grants |= FILE_WRITE_DATA; + if (mode & S_ISVTX) + grants |= FILE_READ_DATA; + pgace->mask = grants; + memcpy((char*)&pgace->sid, nullsid, nsidsz); + pos += nsidsz + 8; + acecnt++; + } + + /* fix ACL header */ + pacl->size = cpu_to_le16(pos); + pacl->ace_count = cpu_to_le16(acecnt); + return (pos); +} + +#if POSIXACLS + +/* + * Build a full security descriptor from a Posix ACL + * returns descriptor in allocated memory, must free() after use + */ + +char *ntfs_build_descr_posix(struct MAPPING* const mapping[], + struct POSIX_SECURITY *pxdesc, + int isdir, const SID *usid, const SID *gsid) +{ + int newattrsz; + SECURITY_DESCRIPTOR_RELATIVE *pnhead; + char *newattr; + int aclsz; + int usidsz; + int gsidsz; + int wsidsz; + int asidsz; + int ssidsz; + int k; + + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + wsidsz = ntfs_sid_size(worldsid); + asidsz = ntfs_sid_size(adminsid); + ssidsz = ntfs_sid_size(systemsid); + + /* allocate enough space for the new security attribute */ + newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE) /* header */ + + usidsz + gsidsz /* usid and gsid */ + + sizeof(ACL) /* acl header */ + + 2*(8 + usidsz) /* two possible ACE for user */ + + 3*(8 + gsidsz) /* three possible ACE for group and mask */ + + 8 + wsidsz /* one ACE for world */ + + 8 + asidsz /* one ACE for admin */ + + 8 + ssidsz; /* one ACE for system */ + if (isdir) /* a world denial for directories */ + newattrsz += 8 + wsidsz; + if (pxdesc->mode & 07000) /* a NULL ACE for special modes */ + newattrsz += 8 + ntfs_sid_size(nullsid); + /* account for non-owning users and groups */ + for (k=0; kacccnt; k++) { + if ((pxdesc->acl.ace[k].tag == POSIX_ACL_USER) + || (pxdesc->acl.ace[k].tag == POSIX_ACL_GROUP)) + newattrsz += 3*40; /* fixme : maximum size */ + } + /* account for default ACE's */ + newattrsz += 2*40*pxdesc->defcnt; /* fixme : maximum size */ + newattr = (char*)ntfs_malloc(newattrsz); + if (newattr) { + /* build the main header part */ + pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr; + pnhead->revision = SECURITY_DESCRIPTOR_REVISION; + pnhead->alignment = 0; + /* + * The flag SE_DACL_PROTECTED prevents the ACL + * to be changed in an inheritance after creation + */ + pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED + | SE_SELF_RELATIVE; + /* + * Windows prefers ACL first, do the same to + * get the same hash value and avoid duplication + */ + /* build permissions */ + aclsz = buildacls_posix(mapping,newattr, + sizeof(SECURITY_DESCRIPTOR_RELATIVE), + pxdesc, isdir, usid, gsid); + if (aclsz && ((int)(sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz + gsidsz) <= newattrsz)) { + /* append usid and gsid */ + memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz], usid, usidsz); + memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz], gsid, gsidsz); + /* positions of ACL, USID and GSID into header */ + pnhead->owner = + cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz); + pnhead->group = + cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz); + pnhead->sacl = const_cpu_to_le32(0); + pnhead->dacl = + const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)); + } else { + /* ACL failure (errno set) or overflow */ + free(newattr); + newattr = (char*)NULL; + if (aclsz) { + /* hope error was detected before overflowing */ + ntfs_log_error("Security descriptor is longer than expected\n"); + errno = EIO; + } + } + } else + errno = ENOMEM; + return (newattr); +} + +#endif /* POSIXACLS */ + +/* + * Build a full security descriptor + * returns descriptor in allocated memory, must free() after use + */ + +char *ntfs_build_descr(mode_t mode, + int isdir, const SID * usid, const SID * gsid) +{ + int newattrsz; + SECURITY_DESCRIPTOR_RELATIVE *pnhead; + char *newattr; + int aclsz; + int usidsz; + int gsidsz; + int wsidsz; + int asidsz; + int ssidsz; + + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + wsidsz = ntfs_sid_size(worldsid); + asidsz = ntfs_sid_size(adminsid); + ssidsz = ntfs_sid_size(systemsid); + + /* allocate enough space for the new security attribute */ + newattrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE) /* header */ + + usidsz + gsidsz /* usid and gsid */ + + sizeof(ACL) /* acl header */ + + 2*(8 + usidsz) /* two possible ACE for user */ + + 2*(8 + gsidsz) /* two possible ACE for group */ + + 8 + wsidsz /* one ACE for world */ + + 8 + asidsz /* one ACE for admin */ + + 8 + ssidsz; /* one ACE for system */ + if (isdir) /* a world denial for directories */ + newattrsz += 8 + wsidsz; + if (mode & 07000) /* a NULL ACE for special modes */ + newattrsz += 8 + ntfs_sid_size(nullsid); + newattr = (char*)ntfs_malloc(newattrsz); + if (newattr) { + /* build the main header part */ + pnhead = (SECURITY_DESCRIPTOR_RELATIVE*) newattr; + pnhead->revision = SECURITY_DESCRIPTOR_REVISION; + pnhead->alignment = 0; + /* + * The flag SE_DACL_PROTECTED prevents the ACL + * to be changed in an inheritance after creation + */ + pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED + | SE_SELF_RELATIVE; + /* + * Windows prefers ACL first, do the same to + * get the same hash value and avoid duplication + */ + /* build permissions */ + aclsz = buildacls(newattr, + sizeof(SECURITY_DESCRIPTOR_RELATIVE), + mode, isdir, usid, gsid); + if (((int)sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz + gsidsz) <= newattrsz) { + /* append usid and gsid */ + memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz], usid, usidsz); + memcpy(&newattr[sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz], gsid, gsidsz); + /* positions of ACL, USID and GSID into header */ + pnhead->owner = + cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz); + pnhead->group = + cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE) + + aclsz + usidsz); + pnhead->sacl = const_cpu_to_le32(0); + pnhead->dacl = + const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)); + } else { + /* hope error was detected before overflowing */ + free(newattr); + newattr = (char*)NULL; + ntfs_log_error("Security descriptor is longer than expected\n"); + errno = EIO; + } + } else + errno = ENOMEM; + return (newattr); +} + +/* + * Create a mode_t permission set + * from owner, group and world grants as represented in ACEs + */ + +static int merge_permissions(BOOL isdir, + le32 owner, le32 group, le32 world, le32 special) + +{ + int perm; + + perm = 0; + /* build owner permission */ + if (owner) { + if (isdir) { + /* exec if any of list, traverse */ + if (owner & DIR_GEXEC) + perm |= S_IXUSR; + /* write if any of addfile, adddir, delchild */ + if (owner & DIR_GWRITE) + perm |= S_IWUSR; + /* read if any of list */ + if (owner & DIR_GREAD) + perm |= S_IRUSR; + } else { + /* exec if execute or generic execute */ + if (owner & FILE_GEXEC) + perm |= S_IXUSR; + /* write if any of writedata or generic write */ + if (owner & FILE_GWRITE) + perm |= S_IWUSR; + /* read if any of readdata or generic read */ + if (owner & FILE_GREAD) + perm |= S_IRUSR; + } + } + /* build group permission */ + if (group) { + if (isdir) { + /* exec if any of list, traverse */ + if (group & DIR_GEXEC) + perm |= S_IXGRP; + /* write if any of addfile, adddir, delchild */ + if (group & DIR_GWRITE) + perm |= S_IWGRP; + /* read if any of list */ + if (group & DIR_GREAD) + perm |= S_IRGRP; + } else { + /* exec if execute */ + if (group & FILE_GEXEC) + perm |= S_IXGRP; + /* write if any of writedata, appenddata */ + if (group & FILE_GWRITE) + perm |= S_IWGRP; + /* read if any of readdata */ + if (group & FILE_GREAD) + perm |= S_IRGRP; + } + } + /* build world permission */ + if (world) { + if (isdir) { + /* exec if any of list, traverse */ + if (world & DIR_GEXEC) + perm |= S_IXOTH; + /* write if any of addfile, adddir, delchild */ + if (world & DIR_GWRITE) + perm |= S_IWOTH; + /* read if any of list */ + if (world & DIR_GREAD) + perm |= S_IROTH; + } else { + /* exec if execute */ + if (world & FILE_GEXEC) + perm |= S_IXOTH; + /* write if any of writedata, appenddata */ + if (world & FILE_GWRITE) + perm |= S_IWOTH; + /* read if any of readdata */ + if (world & FILE_GREAD) + perm |= S_IROTH; + } + } + /* build special permission flags */ + if (special) { + if (special & FILE_APPEND_DATA) + perm |= S_ISUID; + if (special & FILE_WRITE_DATA) + perm |= S_ISGID; + if (special & FILE_READ_DATA) + perm |= S_ISVTX; + } + return (perm); +} + +#if POSIXACLS + +/* + * Normalize a Posix ACL either from a sorted raw set of + * access ACEs or default ACEs + * (standard case : different owner, group and administrator) + */ + +static int norm_std_permissions_posix(struct POSIX_SECURITY *posix_desc, + BOOL groupowns, int start, int count, int target) +{ + int j,k; + s32 id; + u16 tag; + u16 tagsset; + struct POSIX_ACE *pxace; + mode_t grantgrps; + mode_t grantwrld; + mode_t denywrld; + mode_t allow; + mode_t deny; + mode_t perms; + mode_t mode; + + mode = 0; + tagsset = 0; + /* + * Determine what is granted to some group or world + * Also get denials to world which are meant to prevent + * execution flags to be inherited by plain files + */ + pxace = posix_desc->acl.ace; + grantgrps = 0; + grantwrld = 0; + denywrld = 0; + for (j=start; j<(start + count); j++) { + if (pxace[j].perms & POSIX_PERM_DENIAL) { + /* deny world exec unless for default */ + if ((pxace[j].tag == POSIX_ACL_OTHER) + && !start) + denywrld = pxace[j].perms; + } else { + switch (pxace[j].tag) { + case POSIX_ACL_GROUP_OBJ : + grantgrps |= pxace[j].perms; + break; + case POSIX_ACL_GROUP : + if (pxace[j].id) + grantgrps |= pxace[j].perms; + break; + case POSIX_ACL_OTHER : + grantwrld = pxace[j].perms; + break; + default : + break; + } + } + } + /* + * Collect groups of ACEs related to the same id + * and determine what is granted and what is denied. + * It is important the ACEs have been sorted + */ + j = start; + k = target; + while (j < (start + count)) { + tag = pxace[j].tag; + id = pxace[j].id; + if (pxace[j].perms & POSIX_PERM_DENIAL) { + deny = pxace[j].perms | denywrld; + allow = 0; + } else { + deny = denywrld; + allow = pxace[j].perms; + } + j++; + while ((j < (start + count)) + && (pxace[j].tag == tag) + && (pxace[j].id == id)) { + if (pxace[j].perms & POSIX_PERM_DENIAL) + deny |= pxace[j].perms; + else + allow |= pxace[j].perms; + j++; + } + /* + * Build the permissions equivalent to grants and denials + */ + if (groupowns) { + if (tag == POSIX_ACL_MASK) + perms = ~deny; + else + perms = allow & ~deny; + } else + switch (tag) { + case POSIX_ACL_USER_OBJ : + perms = (allow | grantgrps | grantwrld) & ~deny; + break; + case POSIX_ACL_USER : + if (id) + perms = (allow | grantgrps | grantwrld) + & ~deny; + else + perms = allow; + break; + case POSIX_ACL_GROUP_OBJ : + perms = (allow | grantwrld) & ~deny; + break; + case POSIX_ACL_GROUP : + if (id) + perms = (allow | grantwrld) & ~deny; + else + perms = allow; + break; + case POSIX_ACL_MASK : + perms = ~deny; + break; + default : + perms = allow & ~deny; + break; + } + /* + * Store into a Posix ACE + */ + if (tag != POSIX_ACL_SPECIAL) { + pxace[k].tag = tag; + pxace[k].id = id; + pxace[k].perms = perms + & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X); + tagsset |= tag; + k++; + } + switch (tag) { + case POSIX_ACL_USER_OBJ : + mode |= ((perms & 7) << 6); + break; + case POSIX_ACL_GROUP_OBJ : + case POSIX_ACL_MASK : + mode = (mode & 07707) | ((perms & 7) << 3); + break; + case POSIX_ACL_OTHER : + mode |= perms & 7; + break; + case POSIX_ACL_SPECIAL : + mode |= (perms & (S_ISVTX | S_ISUID | S_ISGID)); + break; + default : + break; + } + } + if (!start) { /* not satisfactory */ + posix_desc->mode = mode; + posix_desc->tagsset = tagsset; + } + return (k - target); +} + +#endif /* POSIXACLS */ + +/* + * Interpret an ACL and extract meaningful grants + * (standard case : different owner, group and administrator) + */ + +static int build_std_permissions(const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + int offdacl; + int offace; + int acecnt; + int nace; + BOOL noown; + le32 special; + le32 allowown, allowgrp, allowall; + le32 denyown, denygrp, denyall; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + pacl = (const ACL*)&securattr[offdacl]; + special = const_cpu_to_le32(0); + allowown = allowgrp = allowall = const_cpu_to_le32(0); + denyown = denygrp = denyall = const_cpu_to_le32(0); + noown = TRUE; + if (offdacl) { + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + } else + acecnt = 0; + for (nace = 0; nace < acecnt; nace++) { + pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; + if (!(pace->flags & INHERIT_ONLY_ACE)) { + if (ntfs_same_sid(usid, &pace->sid) + || ntfs_same_sid(ownersid, &pace->sid)) { + noown = FALSE; + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowown |= pace->mask; + else if (pace->type == ACCESS_DENIED_ACE_TYPE) + denyown |= pace->mask; + } else + if (ntfs_same_sid(gsid, &pace->sid) + && !(pace->mask & WRITE_OWNER)) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowgrp |= pace->mask; + else if (pace->type == ACCESS_DENIED_ACE_TYPE) + denygrp |= pace->mask; + } else + if (is_world_sid((const SID*)&pace->sid)) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowall |= pace->mask; + else + if (pace->type == ACCESS_DENIED_ACE_TYPE) + denyall |= pace->mask; + } else + if ((ntfs_same_sid((const SID*)&pace->sid,nullsid)) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) + special |= pace->mask; + } + offace += le16_to_cpu(pace->size); + } + /* + * No indication about owner's rights : grant basic rights + * This happens for files created by Windows in directories + * created by Linux and owned by root, because Windows + * merges the admin ACEs + */ + if (noown) + allowown = (FILE_READ_DATA | FILE_WRITE_DATA | FILE_EXECUTE); + /* + * Add to owner rights granted to group or world + * unless denied personaly, and add to group rights + * granted to world unless denied specifically + */ + allowown |= (allowgrp | allowall); + allowgrp |= allowall; + return (merge_permissions(isdir, + allowown & ~(denyown | denyall), + allowgrp & ~(denygrp | denyall), + allowall & ~denyall, + special)); +} + +/* + * Interpret an ACL and extract meaningful grants + * (special case : owner and group are the same, + * and not administrator) + */ + +static int build_owngrp_permissions(const char *securattr, + const SID *usid, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + int offdacl; + int offace; + int acecnt; + int nace; + le32 special; + BOOL grppresent; + le32 allowown, allowgrp, allowall; + le32 denyown, denygrp, denyall; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + pacl = (const ACL*)&securattr[offdacl]; + special = const_cpu_to_le32(0); + allowown = allowgrp = allowall = const_cpu_to_le32(0); + denyown = denygrp = denyall = const_cpu_to_le32(0); + grppresent = FALSE; + if (offdacl) { + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + } else + acecnt = 0; + for (nace = 0; nace < acecnt; nace++) { + pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; + if (!(pace->flags & INHERIT_ONLY_ACE)) { + if ((ntfs_same_sid(usid, &pace->sid) + || ntfs_same_sid(ownersid, &pace->sid)) + && (pace->mask & WRITE_OWNER)) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowown |= pace->mask; + } else + if (ntfs_same_sid(usid, &pace->sid) + && (!(pace->mask & WRITE_OWNER))) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) { + allowgrp |= pace->mask; + grppresent = TRUE; + } + } else + if (is_world_sid((const SID*)&pace->sid)) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowall |= pace->mask; + else + if (pace->type == ACCESS_DENIED_ACE_TYPE) + denyall |= pace->mask; + } else + if ((ntfs_same_sid((const SID*)&pace->sid,nullsid)) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) + special |= pace->mask; + } + offace += le16_to_cpu(pace->size); + } + if (!grppresent) + allowgrp = allowall; + return (merge_permissions(isdir, + allowown & ~(denyown | denyall), + allowgrp & ~(denygrp | denyall), + allowall & ~denyall, + special)); +} + +#if POSIXACLS + +/* + * Normalize a Posix ACL either from a sorted raw set of + * access ACEs or default ACEs + * (special case : owner or/and group is administrator) + */ + +static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc, + int start, int count, int target) +{ + int j,k; + s32 id; + u16 tag; + u16 tagsset; + struct POSIX_ACE *pxace; + int acccnt; + mode_t denywrld; + mode_t allow; + mode_t deny; + mode_t perms; + mode_t mode; + + mode = 0; + pxace = posix_desc->acl.ace; + acccnt = posix_desc->acccnt; + tagsset = 0; + denywrld = 0; + /* + * Get denials to world which are meant to prevent + * execution flags to be inherited by plain files + */ + for (j=start; j<(start + count); j++) { + if (pxace[j].perms & POSIX_PERM_DENIAL) { + /* deny world exec not for default */ + if ((pxace[j].tag == POSIX_ACL_OTHER) + && !start) + denywrld = pxace[j].perms; + } + } + /* + * Collect groups of ACEs related to the same id + * and determine what is granted (denials are ignored) + * It is important the ACEs have been sorted + */ + j = start; + k = target; + deny = 0; + while (j < (start + count)) { + allow = 0; + tag = pxace[j].tag; + id = pxace[j].id; + if (tag == POSIX_ACL_MASK) { + deny = pxace[j].perms; + j++; + while ((j < (start + count)) + && (pxace[j].tag == POSIX_ACL_MASK)) + j++; + } else { + if (!(pxace[j].perms & POSIX_PERM_DENIAL)) + allow = pxace[j].perms; + j++; + while ((j < (start + count)) + && (pxace[j].tag == tag) + && (pxace[j].id == id)) { + if (!(pxace[j].perms & POSIX_PERM_DENIAL)) + allow |= pxace[j].perms; + j++; + } + } + + /* + * Store the grants into a Posix ACE + */ + if (tag == POSIX_ACL_MASK) + perms = ~deny; + else + perms = allow & ~denywrld; + if (tag != POSIX_ACL_SPECIAL) { + pxace[k].tag = tag; + pxace[k].id = id; + pxace[k].perms = perms + & (POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X); + tagsset |= tag; + k++; + } + switch (tag) { + case POSIX_ACL_USER_OBJ : + mode |= ((perms & 7) << 6); + break; + case POSIX_ACL_GROUP_OBJ : + case POSIX_ACL_MASK : + mode = (mode & 07707) | ((perms & 7) << 3); + break; + case POSIX_ACL_OTHER : + mode |= perms & 7; + break; + case POSIX_ACL_SPECIAL : + mode |= perms & (S_ISVTX | S_ISUID | S_ISGID); + break; + default : + break; + } + } + if (!start) { /* not satisfactory */ + posix_desc->mode = mode; + posix_desc->tagsset = tagsset; + } + return (k - target); +} + +#endif /* POSIXACLS */ + +/* + * Interpret an ACL and extract meaningful grants + * (special case : owner or/and group is administrator) + */ + + +static int build_ownadmin_permissions(const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + int offdacl; + int offace; + int acecnt; + int nace; + BOOL firstapply; + int isforeign; + le32 special; + le32 allowown, allowgrp, allowall; + le32 denyown, denygrp, denyall; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + pacl = (const ACL*)&securattr[offdacl]; + special = const_cpu_to_le32(0); + allowown = allowgrp = allowall = const_cpu_to_le32(0); + denyown = denygrp = denyall = const_cpu_to_le32(0); + if (offdacl) { + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + } else + acecnt = 0; + firstapply = TRUE; + isforeign = 3; + for (nace = 0; nace < acecnt; nace++) { + pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; + if (!(pace->flags & INHERIT_ONLY_ACE) + && !(~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK))) { + if ((ntfs_same_sid(usid, &pace->sid) + || ntfs_same_sid(ownersid, &pace->sid)) + && (((pace->mask & WRITE_OWNER) && firstapply))) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) { + allowown |= pace->mask; + isforeign &= ~1; + } else + if (pace->type == ACCESS_DENIED_ACE_TYPE) + denyown |= pace->mask; + } else + if (ntfs_same_sid(gsid, &pace->sid) + && (!(pace->mask & WRITE_OWNER))) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) { + allowgrp |= pace->mask; + isforeign &= ~2; + } else + if (pace->type == ACCESS_DENIED_ACE_TYPE) + denygrp |= pace->mask; + } else if (is_world_sid((const SID*)&pace->sid)) { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + allowall |= pace->mask; + else + if (pace->type == ACCESS_DENIED_ACE_TYPE) + denyall |= pace->mask; + } + firstapply = FALSE; + } else + if (!(pace->flags & INHERIT_ONLY_ACE)) + if ((ntfs_same_sid((const SID*)&pace->sid,nullsid)) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) + special |= pace->mask; + offace += le16_to_cpu(pace->size); + } + if (isforeign) { + allowown |= (allowgrp | allowall); + allowgrp |= allowall; + } + return (merge_permissions(isdir, + allowown & ~(denyown | denyall), + allowgrp & ~(denygrp | denyall), + allowall & ~denyall, + special)); +} + +#if OWNERFROMACL + +/* + * Define the owner of a file as the first user allowed + * to change the owner, instead of the user defined as owner. + * + * This produces better approximations for files written by a + * Windows user in an inheritable directory owned by another user, + * as the access rights are inheritable but the ownership is not. + * + * An important case is the directories "Documents and Settings/user" + * which the users must have access to, though Windows considers them + * as owned by administrator. + */ + +const SID *ntfs_acl_owner(const char *securattr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const SID *usid; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + int offdacl; + int offace; + int acecnt; + int nace; + BOOL found; + + found = FALSE; + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + if (offdacl) { + pacl = (const ACL*)&securattr[offdacl]; + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + nace = 0; + do { + pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; + if ((pace->mask & WRITE_OWNER) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE) + && ntfs_is_user_sid(&pace->sid)) + found = TRUE; + offace += le16_to_cpu(pace->size); + } while (!found && (++nace < acecnt)); + } + if (found) + usid = &pace->sid; + else + usid = (const SID*)&securattr[le32_to_cpu(phead->owner)]; + return (usid); +} + +#else + +/* + * Special case for files owned by administrator with full + * access granted to a mapped user : consider this user as the tenant + * of the file. + * + * This situation cannot be represented with Linux concepts and can + * only be found for files or directories created by Windows. + * Typical situation : directory "Documents and Settings/user" which + * is on the path to user's files and must be given access to user + * only. + * + * Check file is owned by administrator and no user has rights before + * calling. + * Returns the uid of tenant or zero if none + */ + + +static uid_t find_tenant(struct MAPPING *const mapping[], + const char *securattr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + int offdacl; + int offace; + int acecnt; + int nace; + uid_t tid; + uid_t xid; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + pacl = (const ACL*)&securattr[offdacl]; + tid = 0; + if (offdacl) { + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + } else + acecnt = 0; + for (nace = 0; nace < acecnt; nace++) { + pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; + if ((pace->type == ACCESS_ALLOWED_ACE_TYPE) + && (pace->mask & DIR_WRITE)) { + xid = NTFS_FIND_USER(mapping[MAPUSERS], &pace->sid); + if (xid) tid = xid; + } + offace += le16_to_cpu(pace->size); + } + return (tid); +} + +#endif /* OWNERFROMACL */ + +#if POSIXACLS + +/* + * Build Posix permissions from an ACL + * returns a pointer to the requested permissions + * or a null pointer (with errno set) if there is a problem + * + * If the NTFS ACL was created according to our rules, the retrieved + * Posix ACL should be the exact ACL which was set. However if + * the NTFS ACL was built by a different tool, the result could + * be a a poor approximation of what was expected + */ + +struct POSIX_SECURITY *ntfs_build_permissions_posix( + struct MAPPING *const mapping[], + const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + struct POSIX_SECURITY *pxdesc; + const ACL *pacl; + const ACCESS_ALLOWED_ACE *pace; + struct POSIX_ACE *pxace; + struct { + uid_t prevuid; + gid_t prevgid; + int groupmasks; + s16 tagsset; + BOOL gotowner; + BOOL gotownermask; + BOOL gotgroup; + mode_t permswrld; + } ctx[2], *pctx; + int offdacl; + int offace; + int alloccnt; + int acecnt; + uid_t uid; + gid_t gid; + int i,j; + int k,l; + BOOL ignore; + BOOL adminowns; + BOOL groupowns; + BOOL firstinh; + BOOL genericinh; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + offdacl = le32_to_cpu(phead->dacl); + if (offdacl) { + pacl = (const ACL*)&securattr[offdacl]; + acecnt = le16_to_cpu(pacl->ace_count); + offace = offdacl + sizeof(ACL); + } else { + acecnt = 0; + offace = 0; + } + adminowns = FALSE; + groupowns = ntfs_same_sid(gsid,usid); + firstinh = FALSE; + genericinh = FALSE; + /* + * Build a raw posix security descriptor + * by just translating permissions and ids + * Add 2 to the count of ACE to be able to insert + * a group ACE later in access and default ACLs + * and add 2 more to be able to insert ACEs for owner + * and 2 more for other + */ + alloccnt = acecnt + 6; + pxdesc = (struct POSIX_SECURITY*)malloc( + sizeof(struct POSIX_SECURITY) + + alloccnt*sizeof(struct POSIX_ACE)); + k = 0; + l = alloccnt; + for (i=0; i<2; i++) { + pctx = &ctx[i]; + pctx->permswrld = 0; + pctx->prevuid = -1; + pctx->prevgid = -1; + pctx->groupmasks = 0; + pctx->tagsset = 0; + pctx->gotowner = FALSE; + pctx->gotgroup = FALSE; + pctx->gotownermask = FALSE; + } + for (j=0; jflags & INHERIT_ONLY_ACE) { + pxace = &pxdesc->acl.ace[l - 1]; + pctx = &ctx[1]; + } else { + pxace = &pxdesc->acl.ace[k]; + pctx = &ctx[0]; + } + ignore = FALSE; + /* + * grants for root as a designated user or group + */ + if ((~pace->mask & (ROOT_OWNER_UNMARK | ROOT_GROUP_UNMARK)) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE) + && ntfs_same_sid(&pace->sid, adminsid)) { + pxace->tag = (pace->mask & ROOT_OWNER_UNMARK ? POSIX_ACL_GROUP : POSIX_ACL_USER); + pxace->id = 0; + if ((pace->mask & (GENERIC_ALL | WRITE_OWNER)) + && (pace->flags & INHERIT_ONLY_ACE)) + ignore = genericinh = TRUE; + } else + if (ntfs_same_sid(usid, &pace->sid)) { + pxace->id = -1; + /* + * Owner has no write-owner right : + * a group was defined same as owner + * or admin was owner or group : + * denials are meant to owner + * and grants are meant to group + */ + if (!(pace->mask & (WRITE_OWNER | GENERIC_ALL)) + && (pace->type == ACCESS_ALLOWED_ACE_TYPE)) { + if (ntfs_same_sid(gsid,usid)) { + pxace->tag = POSIX_ACL_GROUP_OBJ; + pxace->id = -1; + } else { + if (ntfs_same_sid(&pace->sid,usid)) + groupowns = TRUE; + gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid); + if (gid) { + pxace->tag = POSIX_ACL_GROUP; + pxace->id = gid; + pctx->prevgid = gid; + } else { + uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid); + if (uid) { + pxace->tag = POSIX_ACL_USER; + pxace->id = uid; + } else + ignore = TRUE; + } + } + } else { + /* + * when group owns, late denials for owner + * mean group mask + */ + if ((pace->type == ACCESS_DENIED_ACE_TYPE) + && (pace->mask & WRITE_OWNER)) { + pxace->tag = POSIX_ACL_MASK; + pctx->gotownermask = TRUE; + if (pctx->gotowner) + pctx->groupmasks++; + } else { + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + pctx->gotowner = TRUE; + if (pctx->gotownermask && !pctx->gotowner) { + uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid); + pxace->id = uid; + pxace->tag = POSIX_ACL_USER; + } else + pxace->tag = POSIX_ACL_USER_OBJ; + /* system ignored, and admin */ + /* ignored at first position */ + if (pace->flags & INHERIT_ONLY_ACE) { + if ((firstinh && ntfs_same_sid(&pace->sid,adminsid)) + || ntfs_same_sid(&pace->sid,systemsid)) + ignore = TRUE; + if (!firstinh) { + firstinh = TRUE; + } + } else { + if ((adminowns && ntfs_same_sid(&pace->sid,adminsid)) + || ntfs_same_sid(&pace->sid,systemsid)) + ignore = TRUE; + if (ntfs_same_sid(usid,adminsid)) + adminowns = TRUE; + } + } + } + } else if (ntfs_same_sid(gsid, &pace->sid)) { + if ((pace->type == ACCESS_DENIED_ACE_TYPE) + && (pace->mask & WRITE_OWNER)) { + pxace->tag = POSIX_ACL_MASK; + pxace->id = -1; + if (pctx->gotowner) + pctx->groupmasks++; + } else { + if (pctx->gotgroup || (pctx->groupmasks > 1)) { + gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid); + if (gid) { + pxace->id = gid; + pxace->tag = POSIX_ACL_GROUP; + pctx->prevgid = gid; + } else + ignore = TRUE; + } else { + pxace->id = -1; + pxace->tag = POSIX_ACL_GROUP_OBJ; + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + pctx->gotgroup = TRUE; + } + + if (ntfs_same_sid(gsid,adminsid) + || ntfs_same_sid(gsid,systemsid)) { + if (pace->mask & (WRITE_OWNER | GENERIC_ALL)) + ignore = TRUE; + if (ntfs_same_sid(gsid,adminsid)) + adminowns = TRUE; + else + genericinh = ignore; + } + } + } else if (is_world_sid((const SID*)&pace->sid)) { + pxace->id = -1; + pxace->tag = POSIX_ACL_OTHER; + if ((pace->type == ACCESS_DENIED_ACE_TYPE) + && (pace->flags & INHERIT_ONLY_ACE)) + ignore = TRUE; + } else if (ntfs_same_sid((const SID*)&pace->sid,nullsid)) { + pxace->id = -1; + pxace->tag = POSIX_ACL_SPECIAL; + } else { + uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid); + if (uid) { + if ((pace->type == ACCESS_DENIED_ACE_TYPE) + && (pace->mask & WRITE_OWNER) + && (pctx->prevuid != uid)) { + pxace->id = -1; + pxace->tag = POSIX_ACL_MASK; + } else { + pxace->id = uid; + pxace->tag = POSIX_ACL_USER; + } + pctx->prevuid = uid; + } else { + gid = NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid); + if (gid) { + if ((pace->type == ACCESS_DENIED_ACE_TYPE) + && (pace->mask & WRITE_OWNER) + && (pctx->prevgid != gid)) { + pxace->tag = POSIX_ACL_MASK; + pctx->groupmasks++; + } else { + pxace->tag = POSIX_ACL_GROUP; + } + pxace->id = gid; + pctx->prevgid = gid; + } else { + /* + * do not grant rights to unknown + * people and do not define root as a + * designated user or group + */ + ignore = TRUE; + } + } + } + if (!ignore) { + pxace->perms = 0; + /* specific decoding for vtx/uid/gid */ + if (pxace->tag == POSIX_ACL_SPECIAL) { + if (pace->mask & FILE_APPEND_DATA) + pxace->perms |= S_ISUID; + if (pace->mask & FILE_WRITE_DATA) + pxace->perms |= S_ISGID; + if (pace->mask & FILE_READ_DATA) + pxace->perms |= S_ISVTX; + } else + if (isdir) { + if (pace->mask & DIR_GEXEC) + pxace->perms |= POSIX_PERM_X; + if (pace->mask & DIR_GWRITE) + pxace->perms |= POSIX_PERM_W; + if (pace->mask & DIR_GREAD) + pxace->perms |= POSIX_PERM_R; + if ((pace->mask & GENERIC_ALL) + && (pace->flags & INHERIT_ONLY_ACE)) + pxace->perms |= POSIX_PERM_X + | POSIX_PERM_W + | POSIX_PERM_R; + } else { + if (pace->mask & FILE_GEXEC) + pxace->perms |= POSIX_PERM_X; + if (pace->mask & FILE_GWRITE) + pxace->perms |= POSIX_PERM_W; + if (pace->mask & FILE_GREAD) + pxace->perms |= POSIX_PERM_R; + } + + if (pace->type != ACCESS_ALLOWED_ACE_TYPE) + pxace->perms |= POSIX_PERM_DENIAL; + else + if (pxace->tag == POSIX_ACL_OTHER) + pctx->permswrld = pxace->perms; + pctx->tagsset |= pxace->tag; + if (pace->flags & INHERIT_ONLY_ACE) { + l--; + } else { + k++; + } + } + offace += le16_to_cpu(pace->size); + } + /* + * Create world perms if none (both lists) + */ + for (i=0; i<2; i++) + if ((genericinh || !i) + && !(ctx[i].tagsset & POSIX_ACL_OTHER)) { + if (i) + pxace = &pxdesc->acl.ace[--l]; + else + pxace = &pxdesc->acl.ace[k++]; + pxace->tag = POSIX_ACL_OTHER; + pxace->id = -1; + pxace->perms = 0; + ctx[i].tagsset |= POSIX_ACL_OTHER; + ctx[i].permswrld = 0; + } + /* + * Set basic owner perms if none (both lists) + * This happens for files created by Windows in directories + * created by Linux and owned by root, because Windows + * merges the admin ACEs + */ + for (i=0; i<2; i++) + if (!(ctx[i].tagsset & POSIX_ACL_USER_OBJ) + && (ctx[i].tagsset & POSIX_ACL_OTHER)) { + if (i) + pxace = &pxdesc->acl.ace[--l]; + else + pxace = &pxdesc->acl.ace[k++]; + pxace->tag = POSIX_ACL_USER_OBJ; + pxace->id = -1; + pxace->perms = POSIX_PERM_R | POSIX_PERM_W | POSIX_PERM_X; + ctx[i].tagsset |= POSIX_ACL_USER_OBJ; + } + /* + * Duplicate world perms as group_obj perms if none + */ + for (i=0; i<2; i++) + if ((ctx[i].tagsset & POSIX_ACL_OTHER) + && !(ctx[i].tagsset & POSIX_ACL_GROUP_OBJ)) { + if (i) + pxace = &pxdesc->acl.ace[--l]; + else + pxace = &pxdesc->acl.ace[k++]; + pxace->tag = POSIX_ACL_GROUP_OBJ; + pxace->id = -1; + pxace->perms = ctx[i].permswrld; + ctx[i].tagsset |= POSIX_ACL_GROUP_OBJ; + } + /* + * Also duplicate world perms as group perms if they + * were converted to mask and not followed by a group entry + */ + if (ctx[0].groupmasks) { + for (j=k-2; j>=0; j--) { + if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK) + && (pxdesc->acl.ace[j].id != -1) + && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP) + || (pxdesc->acl.ace[j+1].id + != pxdesc->acl.ace[j].id))) { + pxace = &pxdesc->acl.ace[k]; + pxace->tag = POSIX_ACL_GROUP; + pxace->id = pxdesc->acl.ace[j].id; + pxace->perms = ctx[0].permswrld; + ctx[0].tagsset |= POSIX_ACL_GROUP; + k++; + } + if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK) + pxdesc->acl.ace[j].id = -1; + } + } + if (ctx[1].groupmasks) { + for (j=l; j<(alloccnt-1); j++) { + if ((pxdesc->acl.ace[j].tag == POSIX_ACL_MASK) + && (pxdesc->acl.ace[j].id != -1) + && ((pxdesc->acl.ace[j+1].tag != POSIX_ACL_GROUP) + || (pxdesc->acl.ace[j+1].id + != pxdesc->acl.ace[j].id))) { + pxace = &pxdesc->acl.ace[l - 1]; + pxace->tag = POSIX_ACL_GROUP; + pxace->id = pxdesc->acl.ace[j].id; + pxace->perms = ctx[1].permswrld; + ctx[1].tagsset |= POSIX_ACL_GROUP; + l--; + } + if (pxdesc->acl.ace[j].tag == POSIX_ACL_MASK) + pxdesc->acl.ace[j].id = -1; + } + } + + /* + * Insert default mask if none present and + * there are designated users or groups + * (the space for it has not beed used) + */ + for (i=0; i<2; i++) + if ((ctx[i].tagsset & (POSIX_ACL_USER | POSIX_ACL_GROUP)) + && !(ctx[i].tagsset & POSIX_ACL_MASK)) { + if (i) + pxace = &pxdesc->acl.ace[--l]; + else + pxace = &pxdesc->acl.ace[k++]; + pxace->tag = POSIX_ACL_MASK; + pxace->id = -1; + pxace->perms = POSIX_PERM_DENIAL; + ctx[i].tagsset |= POSIX_ACL_MASK; + } + + if (k > l) { + ntfs_log_error("Posix descriptor is longer than expected\n"); + errno = EIO; + free(pxdesc); + pxdesc = (struct POSIX_SECURITY*)NULL; + } else { + pxdesc->acccnt = k; + pxdesc->defcnt = alloccnt - l; + pxdesc->firstdef = l; + pxdesc->tagsset = ctx[0].tagsset; + pxdesc->acl.version = POSIX_VERSION; + pxdesc->acl.flags = 0; + pxdesc->acl.filler = 0; + ntfs_sort_posix(pxdesc); + if (adminowns) { + k = norm_ownadmin_permissions_posix(pxdesc, + 0, pxdesc->acccnt, 0); + pxdesc->acccnt = k; + l = norm_ownadmin_permissions_posix(pxdesc, + pxdesc->firstdef, pxdesc->defcnt, k); + pxdesc->firstdef = k; + pxdesc->defcnt = l; + } else { + k = norm_std_permissions_posix(pxdesc,groupowns, + 0, pxdesc->acccnt, 0); + pxdesc->acccnt = k; + l = norm_std_permissions_posix(pxdesc,groupowns, + pxdesc->firstdef, pxdesc->defcnt, k); + pxdesc->firstdef = k; + pxdesc->defcnt = l; + } + } + if (pxdesc && !ntfs_valid_posix(pxdesc)) { + ntfs_log_error("Invalid Posix descriptor built\n"); + errno = EIO; + free(pxdesc); + pxdesc = (struct POSIX_SECURITY*)NULL; + } + return (pxdesc); +} + +#endif /* POSIXACLS */ + +/* + * Build unix-style (mode_t) permissions from an ACL + * returns the requested permissions + * or a negative result (with errno set) if there is a problem + */ + +int ntfs_build_permissions(const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + int perm; + BOOL adminowns; + BOOL groupowns; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + adminowns = ntfs_same_sid(usid,adminsid) + || ntfs_same_sid(gsid,adminsid); + groupowns = !adminowns && ntfs_same_sid(gsid,usid); + if (adminowns) + perm = build_ownadmin_permissions(securattr, usid, gsid, isdir); + else + if (groupowns) + perm = build_owngrp_permissions(securattr, usid, isdir); + else + perm = build_std_permissions(securattr, usid, gsid, isdir); + return (perm); +} + +/* + * The following must be in some library... + */ + +static unsigned long atoul(const char *p) +{ /* must be somewhere ! */ + unsigned long v; + + v = 0; + while ((*p >= '0') && (*p <= '9')) + v = v * 10 + (*p++) - '0'; + return (v); +} + +/* + * Build an internal representation of a SID + * Returns a copy in allocated memory if it succeeds + * The SID is checked to be a valid user one. + */ + +static SID *encodesid(const char *sidstr) +{ + SID *sid; + int cnt; + BIGSID bigsid; + SID *bsid; + u32 auth; + const char *p; + + sid = (SID*) NULL; + if (!strncmp(sidstr, "S-1-", 4)) { + bsid = (SID*)&bigsid; + bsid->revision = SID_REVISION; + p = &sidstr[4]; + auth = atoul(p); + bsid->identifier_authority.high_part = const_cpu_to_be16(0); + bsid->identifier_authority.low_part = cpu_to_be32(auth); + cnt = 0; + p = strchr(p, '-'); + while (p && (cnt < 8)) { + p++; + auth = atoul(p); + bsid->sub_authority[cnt] = cpu_to_le32(auth); + p = strchr(p, '-'); + cnt++; + } + bsid->sub_authority_count = cnt; + if ((cnt > 0) && ntfs_valid_sid(bsid) && ntfs_is_user_sid(bsid)) { + sid = (SID*) ntfs_malloc(4 * cnt + 8); + if (sid) + memcpy(sid, bsid, 4 * cnt + 8); + } + } + return (sid); +} + +/* + * Early logging before the logs are redirected + * + * (not quite satisfactory : this appears before the ntfs-g banner, + * and with a different pid) + */ + +static void log_early_error(const char *format, ...) + __attribute__((format(printf, 1, 2))); + +static void log_early_error(const char *format, ...) +{ + va_list args; + + va_start(args, format); +#ifdef HAVE_SYSLOG_H + openlog("ntfs-3g", LOG_PID, LOG_USER); + ntfs_log_handler_syslog(NULL, NULL, 0, + NTFS_LOG_LEVEL_ERROR, NULL, + format, args); +#else + vfprintf(stderr,format,args); +#endif + va_end(args); +} + + +/* + * Get a single mapping item from buffer + * + * Always reads a full line, truncating long lines + * Refills buffer when exhausted + * Returns pointer to item, or NULL when there is no more + */ + +static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid, + off_t *poffs, char *buf, int *psrc, s64 *psize) +{ + int src; + int dst; + char *p; + char *q; + char *pu; + char *pg; + int gotend; + struct MAPLIST *item; + + src = *psrc; + dst = 0; + /* allocate and get a full line */ + item = (struct MAPLIST*)ntfs_malloc(sizeof(struct MAPLIST)); + if (item) { + do { + gotend = 0; + while ((src < *psize) + && (buf[src] != '\n')) { + if (dst < LINESZ) + item->maptext[dst++] = buf[src]; + src++; + } + if (src >= *psize) { + *poffs += *psize; + *psize = reader(fileid, buf, (size_t)BUFSZ, *poffs); + src = 0; + } else { + gotend = 1; + src++; + item->maptext[dst] = '\0'; + dst = 0; + } + } while (*psize && ((item->maptext[0] == '#') || !gotend)); + if (gotend) { + pu = pg = (char*)NULL; + /* decompose into uid, gid and sid */ + p = item->maptext; + item->uidstr = item->maptext; + item->gidstr = strchr(item->uidstr, ':'); + if (item->gidstr) { + pu = item->gidstr++; + item->sidstr = strchr(item->gidstr, ':'); + if (item->sidstr) { + pg = item->sidstr++; + q = strchr(item->sidstr, ':'); + if (q) *q = 0; + } + } + if (pu && pg) + *pu = *pg = '\0'; + else { + log_early_error("Bad mapping item \"%s\"\n", + item->maptext); + free(item); + item = (struct MAPLIST*)NULL; + } + } else { + free(item); /* free unused item */ + item = (struct MAPLIST*)NULL; + } + } + *psrc = src; + return (item); +} + +/* + * Read user mapping file and split into their attribute. + * Parameters are kept as text in a chained list until logins + * are converted to uid. + * Returns the head of list, if any + * + * If an absolute path is provided, the mapping file is assumed + * to be located in another mounted file system, and plain read() + * are used to get its contents. + * If a relative path is provided, the mapping file is assumed + * to be located on the current file system, and internal IO + * have to be used since we are still mounting and we have not + * entered the fuse loop yet. + */ + +struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid) +{ + char buf[BUFSZ]; + struct MAPLIST *item; + struct MAPLIST *firstitem; + struct MAPLIST *lastitem; + int src; + off_t offs; + s64 size; + + firstitem = (struct MAPLIST*)NULL; + lastitem = (struct MAPLIST*)NULL; + offs = 0; + size = reader(fileid, buf, (size_t)BUFSZ, (off_t)0); + if (size > 0) { + src = 0; + do { + item = getmappingitem(reader, fileid, &offs, + buf, &src, &size); + if (item) { + item->next = (struct MAPLIST*)NULL; + if (lastitem) + lastitem->next = item; + else + firstitem = item; + lastitem = item; + } + } while (item); + } + return (firstitem); +} + +/* + * Free memory used to store the user mapping + * The only purpose is to facilitate the detection of memory leaks + */ + +void ntfs_free_mapping(struct MAPPING *mapping[]) +{ + struct MAPPING *user; + struct MAPPING *group; + + /* free user mappings */ + while (mapping[MAPUSERS]) { + user = mapping[MAPUSERS]; + /* do not free SIDs used for group mappings */ + group = mapping[MAPGROUPS]; + while (group && (group->sid != user->sid)) + group = group->next; + if (!group) + free(user->sid); + /* free group list if any */ + if (user->grcnt) + free(user->groups); + /* unchain item and free */ + mapping[MAPUSERS] = user->next; + free(user); + } + /* free group mappings */ + while (mapping[MAPGROUPS]) { + group = mapping[MAPGROUPS]; + free(group->sid); + /* unchain item and free */ + mapping[MAPGROUPS] = group->next; + free(group); + } +} + + +/* + * Build the user mapping list + * user identification may be given in symbolic or numeric format + * + * ! Note ! : does getpwnam() read /etc/passwd or some other file ? + * if so there is a possible recursion into fuse if this + * file is on NTFS, and fuse is not recursion safe. + */ + +struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem) +{ + struct MAPLIST *item; + struct MAPPING *firstmapping; + struct MAPPING *lastmapping; + struct MAPPING *mapping; + struct passwd *pwd; + SID *sid; + int uid; + + firstmapping = (struct MAPPING*)NULL; + lastmapping = (struct MAPPING*)NULL; + for (item = firstitem; item; item = item->next) { + if ((item->uidstr[0] >= '0') && (item->uidstr[0] <= '9')) + uid = atoi(item->uidstr); + else { + uid = 0; + if (item->uidstr[0]) { + pwd = getpwnam(item->uidstr); + if (pwd) + uid = pwd->pw_uid; + else + log_early_error("Invalid user \"%s\"\n", + item->uidstr); + } + } + /* + * Records with no uid and no gid are inserted + * to define the implicit mapping pattern + */ + if (uid + || (!item->uidstr[0] && !item->gidstr[0])) { + sid = encodesid(item->sidstr); + if (sid && !item->uidstr[0] && !item->gidstr[0] + && !ntfs_valid_pattern(sid)) { + ntfs_log_error("Bad implicit SID pattern %s\n", + item->sidstr); + sid = (SID*)NULL; + } + if (sid) { + mapping = + (struct MAPPING*) + ntfs_malloc(sizeof(struct MAPPING)); + if (mapping) { + mapping->sid = sid; + mapping->xid = uid; + mapping->grcnt = 0; + mapping->next = (struct MAPPING*)NULL; + if (lastmapping) + lastmapping->next = mapping; + else + firstmapping = mapping; + lastmapping = mapping; + } + } + } + } + return (firstmapping); +} + +/* + * Build the group mapping list + * group identification may be given in symbolic or numeric format + * + * gid not associated to a uid are processed first in order + * to favour real groups + * + * ! Note ! : does getgrnam() read /etc/group or some other file ? + * if so there is a possible recursion into fuse if this + * file is on NTFS, and fuse is not recursion safe. + */ + +struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem) +{ + struct MAPLIST *item; + struct MAPPING *firstmapping; + struct MAPPING *lastmapping; + struct MAPPING *mapping; + struct group *grp; + BOOL secondstep; + BOOL ok; + int step; + SID *sid; + int gid; + + firstmapping = (struct MAPPING*)NULL; + lastmapping = (struct MAPPING*)NULL; + for (step=1; step<=2; step++) { + for (item = firstitem; item; item = item->next) { + secondstep = (item->uidstr[0] != '\0') + || !item->gidstr[0]; + ok = (step == 1 ? !secondstep : secondstep); + if ((item->gidstr[0] >= '0') + && (item->gidstr[0] <= '9')) + gid = atoi(item->gidstr); + else { + gid = 0; + if (item->gidstr[0]) { + grp = getgrnam(item->gidstr); + if (grp) + gid = grp->gr_gid; + else + log_early_error("Invalid group \"%s\"\n", + item->gidstr); + } + } + /* + * Records with no uid and no gid are inserted in the + * second step to define the implicit mapping pattern + */ + if (ok + && (gid + || (!item->uidstr[0] && !item->gidstr[0]))) { + sid = encodesid(item->sidstr); + if (sid && !item->uidstr[0] && !item->gidstr[0] + && !ntfs_valid_pattern(sid)) { + /* error already logged */ + sid = (SID*)NULL; + } + if (sid) { + mapping = (struct MAPPING*) + ntfs_malloc(sizeof(struct MAPPING)); + if (mapping) { + mapping->sid = sid; + mapping->xid = gid; + mapping->grcnt = 0; + mapping->next = (struct MAPPING*)NULL; + if (lastmapping) + lastmapping->next = mapping; + else + firstmapping = mapping; + lastmapping = mapping; + } + } + } + } + } + return (firstmapping); +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/attrib.c b/release/src/router/ntfs-3g/libntfs-3g/attrib.c index edd70df6d4..bf21544c41 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/attrib.c +++ b/release/src/router/ntfs-3g/libntfs-3g/attrib.c @@ -5,7 +5,7 @@ * Copyright (c) 2002-2005 Richard Russon * Copyright (c) 2002-2008 Szabolcs Szakacsits * Copyright (c) 2004-2007 Yura Pakhuchiy - * Copyright (c) 2007-2008 Jean-Pierre Andre + * Copyright (c) 2007-2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -58,8 +58,16 @@ #include "bitmap.h" #include "logging.h" #include "misc.h" +#include "efs.h" + +#define STANDARD_COMPRESSION_UNIT 4 ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') }; +ntfschar STREAM_SDS[] = { const_cpu_to_le16('$'), + const_cpu_to_le16('S'), + const_cpu_to_le16('D'), + const_cpu_to_le16('S'), + const_cpu_to_le16('\0') }; static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag) { @@ -325,15 +333,17 @@ static void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni, * Final initialization for an ntfs attribute. */ void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, - const BOOL compressed, const BOOL encrypted, const BOOL sparse, + const ATTR_FLAGS data_flags, + const BOOL encrypted, const BOOL sparse, const s64 allocated_size, const s64 data_size, const s64 initialized_size, const s64 compressed_size, const u8 compression_unit) { if (!NAttrInitialized(na)) { + na->data_flags = data_flags; if (non_resident) NAttrSetNonResident(na); - if (compressed) + if (data_flags & ATTR_COMPRESSION_MASK) NAttrSetCompressed(na); if (encrypted) NAttrSetEncrypted(na); @@ -342,7 +352,7 @@ void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, na->allocated_size = allocated_size; na->data_size = data_size; na->initialized_size = initialized_size; - if (compressed || sparse) { + if ((data_flags & ATTR_COMPRESSION_MASK) || sparse) { ntfs_volume *vol = na->ni->vol; na->compressed_size = compressed_size; @@ -429,12 +439,25 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, */ if (type == AT_ATTRIBUTE_LIST) a->flags = 0; + + if ((type == AT_DATA) && !a->initialized_size) { + /* + * Define/redefine the compression state if stream is + * empty, based on the compression mark on parent + * directory (for unnamed data streams) or on current + * inode (for named data streams). The compression mark + * may change any time, the compression state can only + * change when stream is wiped out. + */ + a->flags &= ~ATTR_COMPRESSION_MASK; + if (na->ni->flags & FILE_ATTR_COMPRESSED) + a->flags |= ATTR_IS_COMPRESSED; + } cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE); if (na->type == AT_DATA && na->name == AT_UNNAMED && - ((!(a->flags & ATTR_IS_COMPRESSED) != !NAttrCompressed(na)) || - (!(a->flags & ATTR_IS_SPARSE) != !NAttrSparse(na)) || + ((!(a->flags & ATTR_IS_SPARSE) != !NAttrSparse(na)) || (!(a->flags & ATTR_IS_ENCRYPTED) != !NAttrEncrypted(na)))) { errno = EIO; ntfs_log_perror("Inode %lld has corrupt attribute flags " @@ -444,14 +467,15 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, } if (a->non_resident) { - if ((a->flags & ATTR_IS_COMPRESSED) && !a->compression_unit) { + if ((a->flags & ATTR_COMPRESSION_MASK) + && !a->compression_unit) { errno = EIO; ntfs_log_perror("Compressed inode %lld attr 0x%x has " "no compression unit", (unsigned long long)ni->mft_no, type); goto put_err_out; } - ntfs_attr_init(na, TRUE, a->flags & ATTR_IS_COMPRESSED, + ntfs_attr_init(na, TRUE, a->flags, a->flags & ATTR_IS_ENCRYPTED, a->flags & ATTR_IS_SPARSE, sle64_to_cpu(a->allocated_size), @@ -461,7 +485,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, cs ? a->compression_unit : 0); } else { s64 l = le32_to_cpu(a->value_length); - ntfs_attr_init(na, FALSE, a->flags & ATTR_IS_COMPRESSED, + ntfs_attr_init(na, FALSE, a->flags, a->flags & ATTR_IS_ENCRYPTED, a->flags & ATTR_IS_SPARSE, (l + 7) & ~7, l, l, cs ? (l + 7) & ~7 : 0, 0); @@ -494,7 +518,8 @@ void ntfs_attr_close(ntfs_attr *na) if (NAttrNonResident(na) && na->rl) free(na->rl); /* Don't release if using an internal constant. */ - if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30) + if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30 + && na->name != STREAM_SDS) free(na->name); free(na); } @@ -782,31 +807,57 @@ map_rl: */ static s64 ntfs_attr_pread_i(ntfs_attr *na, const s64 pos, s64 count, void *b) { - s64 br, to_read, ofs, total, total2; + s64 br, to_read, ofs, total, total2, max_read, max_init; ntfs_volume *vol; runlist_element *rl; + u16 efs_padding_length; /* Sanity checking arguments is done in ntfs_attr_pread(). */ - if (NAttrCompressed(na) && NAttrNonResident(na)) - return ntfs_compressed_attr_pread(na, pos, count, b); + if ((na->data_flags & ATTR_COMPRESSION_MASK) && NAttrNonResident(na)) { + if ((na->data_flags & ATTR_COMPRESSION_MASK) + == ATTR_IS_COMPRESSED) + return ntfs_compressed_attr_pread(na, pos, count, b); + else { + /* compression mode not supported */ + errno = EOPNOTSUPP; + return -1; + } + } /* * Encrypted non-resident attributes are not supported. We return * access denied, which is what Windows NT4 does, too. + * However, allow if mounted with efs_raw option */ - if (NAttrEncrypted(na) && NAttrNonResident(na)) { + vol = na->ni->vol; + if (!vol->efs_raw && NAttrEncrypted(na) && NAttrNonResident(na)) { errno = EACCES; return -1; } - vol = na->ni->vol; if (!count) return 0; - /* Truncate reads beyond end of attribute. */ - if (pos + count > na->data_size) { - if (pos >= na->data_size) + /* + * Truncate reads beyond end of attribute, + * but round to next 512 byte boundary for encrypted + * attributes with efs_raw mount option + */ + max_read = na->data_size; + max_init = na->initialized_size; + if (na->ni->vol->efs_raw + && (na->data_flags & ATTR_IS_ENCRYPTED) + && NAttrNonResident(na)) { + if (na->data_size != na->initialized_size) { + ntfs_log_error("uninitialized encrypted file not supported\n"); + errno = EINVAL; + return -1; + } + max_init = max_read = ((na->data_size + 511) & ~511) + 2; + } + if (pos + count > max_read) { + if (pos >= max_read) return 0; - count = na->data_size - pos; + count = max_read - pos; } /* If it is a resident attribute, get the value from the mft record. */ if (!NAttrNonResident(na)) { @@ -836,15 +887,42 @@ res_err_out: } total = total2 = 0; /* Zero out reads beyond initialized size. */ - if (pos + count > na->initialized_size) { - if (pos >= na->initialized_size) { + if (pos + count > max_init) { + if (pos >= max_init) { memset(b, 0, count); return count; } - total2 = pos + count - na->initialized_size; + total2 = pos + count - max_init; count -= total2; memset((u8*)b + count, 0, total2); } + /* + * for encrypted non-resident attributes with efs_raw set + * the last two bytes aren't read from disk but contain + * the number of padding bytes so original size can be + * restored + */ + if (na->ni->vol->efs_raw && + (na->data_flags & ATTR_IS_ENCRYPTED) && + ((pos + count) > max_init-2)) { + efs_padding_length = 511 - ((na->data_size - 1) & 511); + if (pos+count == max_init) { + if (count == 1) { + *((u8*)b+count-1) = (u8)(efs_padding_length >> 8); + count--; + total2++; + } else { + *(u16*)((u8*)b+count-2) = cpu_to_le16(efs_padding_length); + count -= 2; + total2 +=2; + } + } else { + *((u8*)b+count-1) = (u8)(efs_padding_length & 0xff); + count--; + total2++; + } + } + /* Find the runlist element containing the vcn. */ rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits); if (!rl) { @@ -982,6 +1060,9 @@ static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count) { char *buf; s64 written, size, end = pos + count; + s64 ofsi; + const runlist_element *rli; + ntfs_volume *vol; int ret = -1; ntfs_log_trace("pos %lld, count %lld\n", (long long)pos, @@ -996,9 +1077,17 @@ static int ntfs_attr_fill_zero(ntfs_attr *na, s64 pos, s64 count) if (!buf) goto err_out; + rli = na->rl; + ofsi = 0; + vol = na->ni->vol; while (pos < end) { + while (rli->length && (ofsi + (rli->length << + vol->cluster_size_bits) <= pos)) { + ofsi += (rli->length << vol->cluster_size_bits); + rli++; + } size = min(end - pos, NTFS_BUF_SIZE); - written = ntfs_rl_pwrite(na->ni->vol, na->rl, pos, size, buf); + written = ntfs_rl_pwrite(vol, rli, ofsi, pos, size, buf); if (written <= 0) { ntfs_log_perror("Failed to zero space"); goto err_free; @@ -1017,6 +1106,7 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs, runlist_element **rl, VCN *update_from) { s64 to_write; + s64 need; ntfs_volume *vol = na->ni->vol; int eo, ret = -1; runlist *rlc; @@ -1050,7 +1140,16 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs, while (rlc->vcn) { rlc--; if (rlc->lcn >= 0) { - lcn_seek_from = rlc->lcn + (from_vcn - rlc->vcn); + /* + * avoid fragmenting a compressed file + * Windows does not do that, and that may + * not be desirable for files which can + * be updated + */ + if (na->data_flags & ATTR_COMPRESSION_MASK) + lcn_seek_from = rlc->lcn + rlc->length; + else + lcn_seek_from = rlc->lcn + (from_vcn - rlc->vcn); break; } } @@ -1068,14 +1167,29 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs, } } - rlc = ntfs_cluster_alloc(vol, from_vcn, - ((*ofs + to_write - 1) >> vol->cluster_size_bits) - + 1 + (*rl)->vcn - from_vcn, + need = ((*ofs + to_write - 1) >> vol->cluster_size_bits) + + 1 + (*rl)->vcn - from_vcn; + if ((na->data_flags & ATTR_COMPRESSION_MASK) + && (need < na->compression_block_clusters)) { + /* + * for a compressed file, be sure to allocate the full hole. + * We may need space to decompress existing compressed data. + */ + rlc = ntfs_cluster_alloc(vol, (*rl)->vcn, (*rl)->length, + lcn_seek_from, DATA_ZONE); + } else + rlc = ntfs_cluster_alloc(vol, from_vcn, need, lcn_seek_from, DATA_ZONE); if (!rlc) goto err_out; *rl = ntfs_runlists_merge(na->rl, rlc); + /* + * For a compressed attribute, we must be sure there is an + * available entry, so reserve it before it gets too late. + */ + if (*rl && (na->data_flags & ATTR_COMPRESSION_MASK)) + *rl = ntfs_rl_extend(*rl,1); if (!*rl) { eo = errno; ntfs_log_perror("Failed to merge runlists"); @@ -1135,6 +1249,8 @@ err_out: return ret; } +static int stuff_hole(ntfs_attr *na, const s64 pos); + /** * ntfs_attr_pwrite - positioned write to an ntfs attribute * @na: ntfs attribute to write to @@ -1160,14 +1276,19 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) s64 total = 0; VCN update_from = -1; ntfs_volume *vol; + s64 fullcount; ntfs_attr_search_ctx *ctx = NULL; runlist_element *rl; s64 hole_end; int eo; + int compressed_part; struct { unsigned int undo_initialized_size : 1; unsigned int undo_data_size : 1; } need_to = { 0, 0 }; + BOOL makingnonresident = FALSE; + BOOL wasnonresident = FALSE; + BOOL compressed; ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count " "0x%llx.\n", (long long)na->ni->mft_no, na->type, @@ -1179,25 +1300,54 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) goto errno_set; } vol = na->ni->vol; + compressed = (na->data_flags & ATTR_COMPRESSION_MASK) + != const_cpu_to_le16(0); /* - * Encrypted non-resident attributes are not supported. We return + * Encrypted attributes are only supported in raw mode. We return * access denied, which is what Windows NT4 does, too. + * Moreover a file cannot be both encrypted and compressed. */ - if (NAttrEncrypted(na) && NAttrNonResident(na)) { + if ((na->data_flags & ATTR_IS_ENCRYPTED) + && (compressed || !vol->efs_raw)) { errno = EACCES; goto errno_set; } + /* + * Fill the gap, when writing beyond the end of a compressed + * file. This will make recursive calls + */ + if (compressed + && (na->type == AT_DATA) + && (pos > na->initialized_size) + && stuff_hole(na,pos)) + goto errno_set; /* If this is a compressed attribute it needs special treatment. */ - if (NAttrCompressed(na)) { + wasnonresident = NAttrNonResident(na) != 0; + makingnonresident = wasnonresident /* yes : already changed */ + && !pos && (count == na->initialized_size); + /* + * Writing to compressed files is currently restricted + * to appending data. However we have to accept + * recursive write calls to make the attribute non resident. + * These are writing at position 0 up to initialized_size. + * Compression is also restricted to data streams. + * Only ATTR_IS_COMPRESSED compression mode is supported. + */ + if (compressed + && ((na->type != AT_DATA) + || ((na->data_flags & ATTR_COMPRESSION_MASK) + != ATTR_IS_COMPRESSED) + || ((pos != na->initialized_size) + && (pos || (count != na->initialized_size))))) { // TODO: Implement writing compressed attributes! (AIA) - // return ntfs_attr_pwrite_compressed(ntfs_attr *na, - // const s64 pos, s64 count, void *b); errno = EOPNOTSUPP; goto errno_set; } if (!count) goto out; + /* for a compressed file, get prepared to reserve a full block */ + fullcount = count; /* If the write reaches beyond the end, extend the attribute. */ old_data_size = na->data_size; if (pos + count > na->data_size) { @@ -1205,8 +1355,24 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) ntfs_log_perror("Failed to enlarge attribute"); goto errno_set; } + /* resizing may change the compression mode */ + compressed = (na->data_flags & ATTR_COMPRESSION_MASK) + != const_cpu_to_le16(0); need_to.undo_data_size = 1; } + /* + * For compressed data, a single full block was allocated + * to deal with compression, possibly in a previous call. + * We are not able to process several blocks because + * some clusters are freed after compression and + * new allocations have to be done before proceeding, + * so truncate the requested count if needed (big buffers). + */ + if (compressed) { + fullcount = na->data_size - pos; + if (count > fullcount) + count = fullcount; + } old_initialized_size = na->initialized_size; /* If it is a resident attribute, write the data to the mft record. */ if (!NAttrNonResident(na)) { @@ -1250,6 +1416,17 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) if (pos + count > na->initialized_size) { if (ntfs_attr_map_whole_runlist(na)) goto err_out; + /* + * For a compressed attribute, we must be sure there is an + * available entry, and, when reopening a compressed file, + * we may need to split a hole. So reserve the entries + * before it gets too late. + */ + if (compressed) { + na->rl = ntfs_rl_extend(na->rl,2); + if (!na->rl) + goto err_out; + } /* Set initialized_size to @pos + @count. */ ctx = ntfs_attr_get_search_ctx(na->ni, NULL); if (!ctx) @@ -1265,6 +1442,9 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) goto err_out; ctx->attr->initialized_size = cpu_to_sle64(pos + count); + /* fix data_size for compressed files */ + if (compressed) + ctx->attr->data_size = ctx->attr->initialized_size; if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no, ctx->mrec)) { /* @@ -1298,16 +1478,73 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) */ if (errno == ENOENT) { errno = EIO; - ntfs_log_perror("%s: Failed to find VCN #1", __FUNCTION__); + ntfs_log_perror("%s: Failed to find VCN #3", __FUNCTION__); } goto err_out; } + ofs = pos - (rl->vcn << vol->cluster_size_bits); + /* + * Determine if there is compressed data in the current + * compression block (when appending to an existing file). + * If so, decompression will be needed, and the full block + * must be allocated to be identified as uncompressed. + * This comes in two variants, depending on whether + * compression has saved at least one cluster. + * The compressed size can never be over full size by + * more than 485 (maximum for 15 compression blocks + * compressed to 4098 and the last 3640 bytes compressed + * to 3640 + 3640/8 = 4095, with 15*2 + 4095 - 3640 = 485) + * This is less than the smallest cluster, so the hole is + * is never beyond the cluster next to the position of + * the first uncompressed byte to write. + */ + compressed_part = 0; + if (compressed) { + if ((rl->lcn == (LCN)LCN_HOLE) + && wasnonresident) { + if (rl->length < na->compression_block_clusters) + compressed_part + = na->compression_block_clusters + - rl->length; + else { + compressed_part + = na->compression_block_clusters; + if (rl->length > na->compression_block_clusters) { + rl[2].lcn = rl[1].lcn; + rl[2].vcn = rl[1].vcn; + rl[2].length = rl[1].length; + rl[1].vcn -= compressed_part; + rl[1].lcn = LCN_HOLE; + rl[1].length = compressed_part; + rl[0].length -= compressed_part; + ofs -= rl->length << vol->cluster_size_bits; + rl++; + } + } + /* normal hole filling will do later */ + } else + if ((rl->lcn >= 0) && (rl[1].lcn == (LCN)LCN_HOLE)) { + s64 xofs; + + if (wasnonresident) + compressed_part = na->compression_block_clusters + - rl[1].length; + rl++; + xofs = 0; + if (ntfs_attr_fill_hole(na, + rl->length << vol->cluster_size_bits, + &xofs, &rl, &update_from)) + goto err_out; + /* the fist allocated cluster was not merged */ + if (!xofs) + rl--; + } + } /* * Scatter the data from the linear data buffer to the volume. Note, a * partial final vcn is taken care of by the @count capping of write * length. */ - ofs = pos - (rl->vcn << vol->cluster_size_bits); for (hole_end = 0; count; rl++, ofs = 0, hole_end = 0) { if (rl->lcn == LCN_RL_NOT_MAPPED) { rl = ntfs_attr_find_vcn(na, rl->vcn); @@ -1315,7 +1552,7 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) if (errno == ENOENT) { errno = EIO; ntfs_log_perror("%s: Failed to find VCN" - " #2", __FUNCTION__); + " #4", __FUNCTION__); } goto rl_err_out; } @@ -1328,7 +1565,6 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) goto rl_err_out; } if (rl->lcn < (LCN)0) { - hole_end = rl->vcn + rl->length; if (rl->lcn != (LCN)LCN_HOLE) { @@ -1338,10 +1574,18 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) (long long)rl->lcn); goto rl_err_out; } - - if (ntfs_attr_fill_hole(na, count, &ofs, &rl, &update_from)) + if (ntfs_attr_fill_hole(na, fullcount, &ofs, &rl, + &update_from)) goto err_out; } + if (compressed) { + while (rl->length + && (ofs >= (rl->length << vol->cluster_size_bits))) { + ofs -= rl->length << vol->cluster_size_bits; + rl++; + } + } + /* It is a real lcn, write it to the volume. */ to_write = min(count, (rl->length << vol->cluster_size_bits) - ofs); retry: @@ -1361,6 +1605,9 @@ retry: * This will cause the kernel not to seek and read disk * blocks during write(2) to fill the end of the buffer * which increases write speed by 2-10 fold typically. + * + * This is done even for compressed files, because + * data is generally first written uncompressed. */ if (rounding && ((wend == na->initialized_size) || (wend < (hole_end << vol->cluster_size_bits)))){ @@ -1376,35 +1623,53 @@ retry: memcpy(cb, b, to_write); memset(cb + to_write, 0, rounding - to_write); - written = ntfs_pwrite(vol->dev, wpos, rounding, cb); - if (written == rounding) - written = to_write; + if (compressed) { + written = ntfs_compressed_pwrite(na, + rl, wpos, ofs, to_write, + rounding, b, compressed_part); + } else { + written = ntfs_pwrite(vol->dev, wpos, + rounding, cb); + if (written == rounding) + written = to_write; + } free(cb); - } else - written = ntfs_pwrite(vol->dev, wpos, to_write, b); + } else { + if (compressed) { + written = ntfs_compressed_pwrite(na, + rl, wpos, ofs, to_write, + to_write, b, compressed_part); + } else + written = ntfs_pwrite(vol->dev, wpos, + to_write, b); + } } else written = to_write; /* If everything ok, update progress counters and continue. */ if (written > 0) { total += written; count -= written; + fullcount -= written; b = (const u8*)b + written; } - if (written == to_write) - continue; - /* If the syscall was interrupted, try again. */ - if (written == (s64)-1 && errno == EINTR) - goto retry; - if (!written) - errno = EIO; - goto rl_err_out; + if (written != to_write) { + /* Partial write cannot be dealt with, stop there */ + /* If the syscall was interrupted, try again. */ + if (written == (s64)-1 && errno == EINTR) + goto retry; + if (!written) + errno = EIO; + goto rl_err_out; + } + compressed_part = 0; } done: if (ctx) ntfs_attr_put_search_ctx(ctx); /* Update mapping pairs if needed. */ - if (update_from != -1) + if ((update_from != -1) + || (compressed && !makingnonresident)) if (ntfs_attr_update_mapping_pairs(na, 0 /*update_from*/)) { /* * FIXME: trying to recover by goto rl_err_out; @@ -1480,6 +1745,177 @@ errno_set: goto out; } +int ntfs_attr_pclose(ntfs_attr *na) +{ + s64 written, ofs; + BOOL ok = TRUE; + VCN update_from = -1; + ntfs_volume *vol; + ntfs_attr_search_ctx *ctx = NULL; + runlist_element *rl; + int eo; + s64 hole; + int compressed_part; + BOOL compressed; + + ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x.\n", + na->ni->mft_no, na->type); + + if (!na || !na->ni || !na->ni->vol) { + errno = EINVAL; + ntfs_log_perror("%s", __FUNCTION__); + goto errno_set; + } + vol = na->ni->vol; + compressed = (na->data_flags & ATTR_COMPRESSION_MASK) + != const_cpu_to_le16(0); + /* + * Encrypted non-resident attributes are not supported. We return + * access denied, which is what Windows NT4 does, too. + */ + if (NAttrEncrypted(na) && NAttrNonResident(na)) { + errno = EACCES; + goto errno_set; + } + /* If this is not a compressed attribute get out */ + /* same if it is resident */ + if (!compressed || !NAttrNonResident(na)) + goto out; + + /* + * For a compressed attribute, we must be sure there is an + * available entry, so reserve it before it gets too late. + */ + if (ntfs_attr_map_whole_runlist(na)) + goto err_out; + na->rl = ntfs_rl_extend(na->rl,1); + if (!na->rl) + goto err_out; + /* Find the runlist element containing the terminal vcn. */ + rl = ntfs_attr_find_vcn(na, (na->initialized_size - 1) >> vol->cluster_size_bits); + if (!rl) { + /* + * If the vcn is not present it is an out of bounds write. + * However, we have already written the last byte uncompressed, + * so getting this here must be an error of some kind. + */ + if (errno == ENOENT) { + errno = EIO; + ntfs_log_perror("%s: Failed to find VCN #5", __FUNCTION__); + } + goto err_out; + } + /* + * Scatter the data from the linear data buffer to the volume. Note, a + * partial final vcn is taken care of by the @count capping of write + * length. + */ + compressed_part = 0; + if ((rl->lcn >= 0) && (rl[1].lcn == (LCN)LCN_HOLE)) + compressed_part + = na->compression_block_clusters - rl[1].length; + else + if (rl->lcn == (LCN)LCN_HOLE) { + if (rl->length < na->compression_block_clusters) + compressed_part + = na->compression_block_clusters + - rl->length; + else + compressed_part + = na->compression_block_clusters; + } + /* done, if the last block set was compressed */ + if (compressed_part) + goto out; + + ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits); + + if (rl->lcn == LCN_RL_NOT_MAPPED) { + rl = ntfs_attr_find_vcn(na, rl->vcn); + if (!rl) { + if (errno == ENOENT) { + errno = EIO; + ntfs_log_perror("%s: Failed to find VCN" + " #6", __FUNCTION__); + } + goto rl_err_out; + } + /* Needed for case when runs merged. */ + ofs = na->initialized_size - (rl->vcn << vol->cluster_size_bits); + } + if (!rl->length) { + errno = EIO; + ntfs_log_perror("%s: Zero run length", __FUNCTION__); + goto rl_err_out; + } + if (rl->lcn < (LCN)0) { + hole = rl->vcn + rl->length; + if (rl->lcn != (LCN)LCN_HOLE) { + errno = EIO; + ntfs_log_perror("%s: Unexpected LCN (%lld)", + __FUNCTION__, + (long long)rl->lcn); + goto rl_err_out; + } + + if (ntfs_attr_fill_hole(na, (s64)0, &ofs, &rl, &update_from)) + goto err_out; + } + while (rl->length + && (ofs >= (rl->length << vol->cluster_size_bits))) { + ofs -= rl->length << vol->cluster_size_bits; + rl++; + } + +retry: + if (!NVolReadOnly(vol)) { + + written = ntfs_compressed_close(na, rl, ofs); + /* If everything ok, update progress counters and continue. */ + if (!written) + goto done; + } + /* If the syscall was interrupted, try again. */ + if (written == (s64)-1 && errno == EINTR) + goto retry; + if (!written) + errno = EIO; + goto rl_err_out; + +done: + if (ctx) + ntfs_attr_put_search_ctx(ctx); + /* Update mapping pairs if needed. */ + if (ntfs_attr_update_mapping_pairs(na, 0 /*update_from*/)) { + /* + * FIXME: trying to recover by goto rl_err_out; + * could cause driver hang by infinite looping. + */ + ok = FALSE; + goto out; + } +out: + ntfs_log_leave("\n"); + return (!ok); +rl_err_out: + /* + * need not restore old sizes, only compressed_size + * can have changed. It has been set according to + * the current runlist while updating the mapping pairs, + * and must be kept consistent with the runlists. + */ +err_out: + eo = errno; + if (ctx) + ntfs_attr_put_search_ctx(ctx); + /* Update mapping pairs if needed. */ + ntfs_attr_update_mapping_pairs(na, 0 /*update_from*/); + errno = eo; +errno_set: + ok = FALSE; + goto out; +} + /** * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read * @na: multi sector transfer protected ntfs attribute to read from @@ -2710,7 +3146,7 @@ int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size) */ int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, ntfschar *name, u8 name_len, u8 *val, u32 size, - ATTR_FLAGS flags) + ATTR_FLAGS data_flags) { ntfs_attr_search_ctx *ctx; u32 length; @@ -2720,7 +3156,7 @@ int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, ntfs_inode *base_ni; ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n", - (long long) ni->mft_no, (unsigned) type, (unsigned) flags); + (long long) ni->mft_no, (unsigned) type, (unsigned) data_flags); if (!ni || (!name && name_len)) { errno = EINVAL; @@ -2773,8 +3209,10 @@ int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, a->length = cpu_to_le32(length); a->non_resident = 0; a->name_length = name_len; - a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, resident_end)); - a->flags = flags; + a->name_offset = (name_len + ? cpu_to_le16(offsetof(ATTR_RECORD, resident_end)) + : const_cpu_to_le16(0)); + a->flags = data_flags; a->instance = m->next_attr_instance; a->value_length = cpu_to_le32(size); a->value_offset = cpu_to_le16(length - ((size + 7) & ~7)); @@ -2911,7 +3349,8 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, a->instance = m->next_attr_instance; a->lowest_vcn = cpu_to_sle64(lowest_vcn); a->mapping_pairs_offset = cpu_to_le16(length - dataruns_size); - a->compression_unit = (flags & ATTR_IS_COMPRESSED) ? 4 : 0; + a->compression_unit = (flags & ATTR_IS_COMPRESSED) + ? STANDARD_COMPRESSION_UNIT : 0; /* If @lowest_vcn == 0, than setup empty attribute. */ if (!lowest_vcn) { a->highest_vcn = cpu_to_sle64(-1); @@ -3127,6 +3566,7 @@ int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, BOOL can_be_non_resident = FALSE; ntfs_inode *attr_ni; ntfs_attr *na; + ATTR_FLAGS data_flags; if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) { errno = EINVAL; @@ -3236,10 +3676,16 @@ int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, } add_attr_record: + if ((ni->flags & FILE_ATTR_COMPRESSED) + && ((type == AT_DATA) + || ((type == AT_INDEX_ROOT) && (name == NTFS_INDEX_I30)))) + data_flags = ATTR_IS_COMPRESSED; + else + data_flags = const_cpu_to_le16(0); if (is_resident) { /* Add resident attribute. */ offset = ntfs_resident_attr_record_add(attr_ni, type, name, - name_len, val, size, 0); + name_len, val, size, data_flags); if (offset < 0) { if (errno == ENOSPC && can_be_non_resident) goto add_non_resident; @@ -3253,7 +3699,7 @@ add_attr_record: add_non_resident: /* Add non resident attribute. */ offset = ntfs_non_resident_attr_record_add(attr_ni, type, name, - name_len, 0, 8, 0); + name_len, 0, 8, data_flags); if (offset < 0) { err = errno; ntfs_log_perror("Failed to add non resident attribute"); @@ -3300,6 +3746,34 @@ err_out: return -1; } +/* + * Change an attribute flag + */ + +int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, + ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask) +{ + ntfs_attr_search_ctx *ctx; + int res; + + res = -1; + /* Search for designated attribute */ + ctx = ntfs_attr_get_search_ctx(ni, NULL); + if (ctx) { + if (!ntfs_attr_lookup(type, name, name_len, + CASE_SENSITIVE, 0, NULL, 0, ctx)) { + /* do the requested change (all small endian le16) */ + ctx->attr->flags = (ctx->attr->flags & ~mask) + | (flags & mask); + NInoSetDirty(ni); + res = 0; + } + ntfs_attr_put_search_ctx(ctx); + } + return (res); +} + + /** * ntfs_attr_rm - remove attribute from ntfs inode * @na: opened ntfs attribute to delete @@ -3659,7 +4133,7 @@ int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra) * We expect the caller to do this as this is a fairly low level * function and it is likely there will be further changes made. */ -static int ntfs_attr_make_non_resident(ntfs_attr *na, +int ntfs_attr_make_non_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) { s64 new_allocated_size, bw; @@ -3706,9 +4180,14 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, * FIXME: For now just clear all of these as we don't support them when * writing. */ - NAttrClearCompressed(na); NAttrClearSparse(na); NAttrClearEncrypted(na); + if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) { + /* set compression writing parameters */ + na->compression_block_size + = 1 << (STANDARD_COMPRESSION_UNIT + vol->cluster_size_bits); + na->compression_block_clusters = 1 << STANDARD_COMPRESSION_UNIT; + } if (rl) { /* Now copy the attribute value to the allocated cluster(s). */ @@ -3725,7 +4204,7 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, } } /* Determine the size of the mapping pairs array. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0); + mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX); if (mp_size < 0) { err = errno; ntfs_log_debug("Eeek! Failed to get size for mapping pairs array. " @@ -3733,7 +4212,10 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, goto cluster_free_err_out; } /* Calculate new offsets for the name and the mapping pairs array. */ - name_ofs = (sizeof(ATTR_REC) - sizeof(a->compressed_size) + 7) & ~7; + if (na->ni->flags & FILE_ATTR_COMPRESSED) + name_ofs = (sizeof(ATTR_REC) + 7) & ~7; + else + name_ofs = (sizeof(ATTR_REC) - sizeof(a->compressed_size) + 7) & ~7; mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; /* * Determine the size of the resident part of the non-resident @@ -3760,10 +4242,6 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, a->name_length * sizeof(ntfschar)); a->name_offset = cpu_to_le16(name_ofs); - /* Update the flags to match the in-memory ones. */ - a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED | - ATTR_COMPRESSION_MASK); - /* Setup the fields specific to non-resident attributes. */ a->lowest_vcn = cpu_to_sle64(0); a->highest_vcn = cpu_to_sle64((new_allocated_size - 1) >> @@ -3771,7 +4249,23 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, a->mapping_pairs_offset = cpu_to_le16(mp_ofs); - a->compression_unit = 0; + /* + * Update the flags to match the in-memory ones. + * However cannot change the compression state if we had + * a fuse_file_info open with a mark for release. + * The decisions about compression can only be made when + * creating/recreating the stream, not when making non resident. + */ + a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED); + if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) { + /* support only ATTR_IS_COMPRESSED compression mode */ + a->compression_unit = STANDARD_COMPRESSION_UNIT; + a->compressed_size = const_cpu_to_le64(0); + } else { + a->compression_unit = 0; + a->flags &= ~ATTR_COMPRESSION_MASK; + na->data_flags = a->flags; + } memset(&a->reserved1, 0, sizeof(a->reserved1)); @@ -3868,7 +4362,8 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize) /* Update attribute size everywhere. */ na->data_size = na->initialized_size = newsize; na->allocated_size = (newsize + 7) & ~7; - if (NAttrCompressed(na) || NAttrSparse(na)) + if ((na->data_flags & ATTR_COMPRESSION_MASK) + || NAttrSparse(na)) na->compressed_size = na->allocated_size; if (na->type == AT_DATA && na->name == AT_UNNAMED) { na->ni->data_size = na->data_size; @@ -4091,8 +4586,8 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) if (ntfs_attr_can_be_resident(vol, na->type)) return -1; - if (NAttrCompressed(na) || NAttrEncrypted(na)) { - ntfs_log_trace("Making compressed or encrypted files resident is not " + if (na->data_flags & ATTR_IS_ENCRYPTED) { + ntfs_log_trace("Making encrypted streams resident is not " "implemented yet.\n"); errno = EOPNOTSUPP; return -1; @@ -4141,6 +4636,16 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) a->value_length = cpu_to_le32(na->data_size); a->value_offset = cpu_to_le16(val_ofs); /* + * If a data stream was wiped out, adjust the compression mode + * to current state of compression flag + */ + if (!na->data_size + && (na->type == AT_DATA) + && (na->ni->flags & FILE_ATTR_COMPRESSED)) { + a->flags |= ATTR_IS_COMPRESSED; + na->data_flags = a->flags; + } + /* * File names cannot be non-resident so we would never see this here * but at least it serves as a reminder that there may be attributes * for which we do need to set this flag. (AIA) @@ -4193,7 +4698,6 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) /* Update in-memory struct ntfs_attr. */ NAttrClearNonResident(na); - NAttrClearCompressed(na); NAttrClearSparse(na); NAttrClearEncrypted(na); na->initialized_size = na->data_size; @@ -4261,8 +4765,8 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m, NAttrSetSparse(na); a->flags |= ATTR_IS_SPARSE; - a->compression_unit = 4; /* Windows set it so, even if attribute - is not actually compressed. */ + a->compression_unit = STANDARD_COMPRESSION_UNIT; /* Windows + set it so, even if attribute is not actually compressed. */ memmove((u8*)a + le16_to_cpu(a->name_offset) + 8, (u8*)a + le16_to_cpu(a->name_offset), @@ -4294,7 +4798,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m, } /* Update compressed size if required. */ - if (sparse) { + if (sparse || (na->data_flags & ATTR_COMPRESSION_MASK)) { s64 new_compr_size; new_compr_size = ntfs_rl_get_compressed_size(na->ni->vol, na->rl); @@ -4333,8 +4837,10 @@ static int ntfs_attr_update_mapping_pairs_i(ntfs_attr *na, VCN from_vcn) MFT_RECORD *m; ATTR_RECORD *a; VCN stop_vcn; + const runlist_element *stop_rl; int err, mp_size, cur_max_mp_size, exp_max_mp_size, ret = -1; BOOL finished_build; + retry: if (!na || !na->rl || from_vcn) { errno = EINVAL; @@ -4362,6 +4868,7 @@ retry: /* Fill attribute records with new mapping pairs. */ stop_vcn = 0; + stop_rl = na->rl; finished_build = FALSE; while (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE, from_vcn, NULL, 0, ctx)) { @@ -4415,13 +4922,6 @@ retry: case -3: goto put_err_out; } - /* Get the size for the rest of mapping pairs array. */ - mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl, - stop_vcn); - if (mp_size <= 0) { - ntfs_log_perror("%s: get MP size failed", __FUNCTION__); - goto put_err_out; - } /* * Determine maximum possible length of mapping pairs, * if we shall *not* expand space for mapping pairs. @@ -4435,6 +4935,13 @@ retry: */ exp_max_mp_size = le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use) + cur_max_mp_size; + /* Get the size for the rest of mapping pairs array. */ + mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, stop_rl, + stop_vcn, exp_max_mp_size); + if (mp_size <= 0) { + ntfs_log_perror("%s: get MP size failed", __FUNCTION__); + goto put_err_out; + } /* Test mapping pairs for fitting in the current mft record. */ if (mp_size > exp_max_mp_size) { /* @@ -4499,8 +5006,12 @@ retry: */ if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu( a->mapping_pairs_offset), mp_size, na->rl, - stop_vcn, &stop_vcn)) + stop_vcn, &stop_rl)) finished_build = TRUE; + if (stop_rl) + stop_vcn = stop_rl->vcn; + else + stop_vcn = 0; if (!finished_build && errno != ENOSPC) { ntfs_log_perror("Failed to build mapping pairs"); goto put_err_out; @@ -4544,7 +5055,7 @@ retry: while (1) { /* Calculate size of rest mapping pairs. */ mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, - na->rl, stop_vcn); + na->rl, stop_vcn, INT_MAX); if (mp_size <= 0) { ntfs_log_perror("%s: get mp size failed", __FUNCTION__); goto put_err_out; @@ -4563,14 +5074,16 @@ retry: cur_max_mp_size = le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use) - (offsetof(ATTR_RECORD, compressed_size) + - ((NAttrCompressed(na) || NAttrSparse(na)) ? + (((na->data_flags & ATTR_COMPRESSION_MASK) + || NAttrSparse(na)) ? sizeof(a->compressed_size) : 0)) - ((sizeof(ntfschar) * na->name_len + 7) & ~7); if (mp_size > cur_max_mp_size) mp_size = cur_max_mp_size; /* Add attribute extent to new record. */ err = ntfs_non_resident_attr_record_add(ni, na->type, - na->name, na->name_len, stop_vcn, mp_size, 0); + na->name, na->name_len, stop_vcn, mp_size, + na->data_flags); if (err == -1) { err = errno; ntfs_log_perror("Could not add attribute extent"); @@ -4583,7 +5096,11 @@ retry: err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp_size, na->rl, - stop_vcn, &stop_vcn); + stop_vcn, &stop_rl); + if (stop_rl) + stop_vcn = stop_rl->vcn; + else + stop_vcn = 0; if (err < 0 && errno != ENOSPC) { err = errno; ntfs_log_perror("Failed to build MP"); @@ -5018,6 +5535,8 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) { int ret = STATUS_ERROR; + s64 fullsize; + BOOL compressed; if (!na || newsize < 0 || (na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) { @@ -5039,24 +5558,49 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) * Encrypted attributes are not supported. We return access denied, * which is what Windows NT4 does, too. */ - if (NAttrEncrypted(na)) { + if (na->data_flags & ATTR_IS_ENCRYPTED) { errno = EACCES; - ntfs_log_perror("Failed to truncate encrypted attribute"); + ntfs_log_info("Failed to truncate encrypted attribute"); goto out; } /* * TODO: Implement making handling of compressed attributes. + * Currently we can only expand the attribute or delete it, + * and only for ATTR_IS_COMPRESSED. This is however possible + * for resident attributes when there is no open fuse context + * (important case : $INDEX_ROOT:$I30) */ - if (NAttrCompressed(na)) { + compressed = (na->data_flags & ATTR_COMPRESSION_MASK) + != const_cpu_to_le16(0); + if (compressed + && NAttrNonResident(na) + && (((na->data_flags & ATTR_COMPRESSION_MASK) != ATTR_IS_COMPRESSED) + || (newsize && (newsize < na->data_size)))) { errno = EOPNOTSUPP; ntfs_log_perror("Failed to truncate compressed attribute"); goto out; } if (NAttrNonResident(na)) { - if (newsize > na->data_size) - ret = ntfs_non_resident_attr_expand(na, newsize); + /* + * For compressed data, the last block must be fully + * allocated, and we do not known the size of compression + * block until the attribute has been made non-resident. + * Moreover we can only process a single compression + * block at a time (from where we are about to write), + * so we silently do not allocate more. + * + * Note : do not request truncate on compressed files + * unless being able to face the consequences ! + */ + if (compressed && newsize) + fullsize = (na->initialized_size + | (na->compression_block_size - 1)) + 1; + else + fullsize = newsize; + if (fullsize > na->data_size) + ret = ntfs_non_resident_attr_expand(na, fullsize); else - ret = ntfs_non_resident_attr_shrink(na, newsize); + ret = ntfs_non_resident_attr_shrink(na, fullsize); } else ret = ntfs_resident_attr_resize(na, newsize); out: @@ -5064,6 +5608,93 @@ out: return ret; } +/* + * Stuff a hole in a compressed file + * + * An unallocated hole must be aligned on compression block size. + * If needed current block and target block are stuffed with zeroes. + * + * Returns 0 if succeeded, + * -1 if it failed (as explained in errno) + */ + +static int stuff_hole(ntfs_attr *na, const s64 pos) +{ + s64 size; + s64 begin_size; + s64 end_size; + char *buf; + int ret; + + ret = 0; + /* + * If the attribute is resident, the compression block size + * is not defined yet and we can make no decision. + * So we first try resizing to the target and if the + * attribute is still resident, we're done + */ + if (!NAttrNonResident(na)) { + ret = ntfs_resident_attr_resize(na, pos); + if (!ret && !NAttrNonResident(na)) + na->initialized_size = na->data_size = pos; + } + if (!ret && NAttrNonResident(na)) { + /* does the hole span over several compression block ? */ + if ((pos ^ na->initialized_size) + & ~(na->compression_block_size - 1)) { + begin_size = ((na->initialized_size - 1) + | (na->compression_block_size - 1)) + + 1 - na->initialized_size; + end_size = pos & (na->compression_block_size - 1); + size = (begin_size > end_size ? begin_size : end_size); + } else { + /* short stuffing in a single compression block */ + begin_size = size = pos - na->initialized_size; + end_size = 0; + } + if (size) + buf = (char*)ntfs_malloc(size); + else + buf = (char*)NULL; + if (buf || !size) { + memset(buf,0,size); + /* stuff into current block */ + if (begin_size + && (ntfs_attr_pwrite(na, + na->initialized_size, begin_size, buf) + != begin_size)) + ret = -1; + /* create an unstuffed hole */ + if (!ret + && ((na->initialized_size + end_size) < pos) + && ntfs_non_resident_attr_expand(na, + pos - end_size)) + ret = -1; + else + na->initialized_size + = na->data_size = pos - end_size; + /* stuff into the target block */ + if (!ret && end_size + && (ntfs_attr_pwrite(na, + na->initialized_size, end_size, buf) + != end_size)) + ret = -1; + if (buf) + free(buf); + } else + ret = -1; + } + /* make absolutely sure we have reached the target */ + if (!ret && (na->initialized_size != pos)) { + ntfs_log_error("Failed to stuff a compressed file" + "target %lld reached %lld\n", + (long long)pos, (long long)na->initialized_size); + errno = EIO; + ret = -1; + } + return (ret); +} + /** * ntfs_attr_readall - read the entire data from an ntfs attribute * @ni: open ntfs inode in which the ntfs attribute resides @@ -5155,8 +5786,11 @@ int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, na = ntfs_attr_open(ni, type, name, name_len); if (!na) { - ntfs_log_perror("Failed to open attribute 0x%02x of inode " + /* do not log removal of non-existent stream */ + if (type != AT_DATA) { + ntfs_log_perror("Failed to open attribute 0x%02x of inode " "0x%llx", type, (unsigned long long)ni->mft_no); + } return -1; } @@ -5228,4 +5862,3 @@ out: return -1; return nr_free; } - diff --git a/release/src/router/ntfs-3g/libntfs-3g/collate.c b/release/src/router/ntfs-3g/libntfs-3g/collate.c index 2352423f9f..20e5db1e6c 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/collate.c +++ b/release/src/router/ntfs-3g/libntfs-3g/collate.c @@ -35,22 +35,18 @@ BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) { - int i; - /* * FIXME: At the moment we only support COLLATION_BINARY, * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return false * for everything else. + * JPA added COLLATION_NTOFS_SECURITY_HASH */ - if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG && - cr != COLLATION_FILE_NAME) + if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG + && cr != COLLATION_FILE_NAME + && cr != COLLATION_NTOFS_SECURITY_HASH + && cr != COLLATION_NTOFS_ULONGS) return FALSE; - i = le32_to_cpu(cr); - if (((i >= 0) && (i <= 0x02)) || - ((i >= 0x10) && (i <= 0x13))) - return TRUE; - - return FALSE; + return TRUE; } /** @@ -122,6 +118,101 @@ static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), } /** + * ntfs_collate_ntofs_ulongs - Which of two le32 arrays should be listed first + * + * Returns: -1, 0 or 1 depending of how the arrays compare + */ + +static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)), + const void *data1, const int data1_len, + const void *data2, const int data2_len) +{ + int rc; + int len; + const le32 *p1, *p2; + u32 d1, d2; + + ntfs_log_trace("Entering.\n"); + if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) { + ntfs_log_error("data1_len or data2_len not valid\n"); + return NTFS_COLLATION_ERROR; + } + p1 = (const le32*)data1; + p2 = (const le32*)data2; + len = data1_len; + do { + d1 = le32_to_cpup(p1); + p1++; + d2 = le32_to_cpup(p2); + p2++; + } while ((d1 == d2) && ((len -= 4) > 0)); + if (d1 < d2) + rc = -1; + else { + if (d1 == d2) + rc = 0; + else + rc = 1; + } + ntfs_log_trace("Done, returning %i.\n", rc); + return rc; +} + +/** + * ntfs_collate_ntofs_security_hash - Which of two security descriptors + * should be listed first + * @vol: unused + * @data1: + * @data1_len: + * @data2: + * @data2_len: + * + * JPA compare two security hash keys made of two unsigned le32 + * + * Returns: -1, 0 or 1 depending of how the keys compare + */ +static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unused)), + const void *data1, const int data1_len, + const void *data2, const int data2_len) +{ + int rc; + u32 d1, d2; + const u32 *p1, *p2; + + ntfs_log_trace("Entering.\n"); + if (data1_len != data2_len || data1_len != 8) { + ntfs_log_error("data1_len or/and data2_len not equal to 8.\n"); + return NTFS_COLLATION_ERROR; + } + p1 = (const u32*)data1; + p2 = (const u32*)data2; + d1 = le32_to_cpup(p1); + d2 = le32_to_cpup(p2); + if (d1 < d2) + rc = -1; + else { + if (d1 > d2) + rc = 1; + else { + p1++; + p2++; + d1 = le32_to_cpup(p1); + d2 = le32_to_cpup(p2); + if (d1 < d2) + rc = -1; + else { + if (d1 > d2) + rc = 1; + else + rc = 0; + } + } + } + ntfs_log_trace("Done, returning %i.\n", rc); + return rc; +} + +/** * ntfs_collate_file_name - Which of two filenames should be listed first * @vol: * @data1: @@ -162,8 +253,8 @@ static ntfs_collate_func_t ntfs_do_collate0x0[3] = { static ntfs_collate_func_t ntfs_do_collate0x1[4] = { ntfs_collate_ntofs_ulong, NULL/*ntfs_collate_ntofs_sid*/, - NULL/*ntfs_collate_ntofs_security_hash*/, - NULL/*ntfs_collate_ntofs_ulongs*/, + ntfs_collate_ntofs_security_hash, + ntfs_collate_ntofs_ulongs }; /** @@ -199,9 +290,13 @@ int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, * FIXME: At the moment we only support COLLATION_BINARY, * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME so we return error * for everything else. + * JPA added COLLATION_NTOFS_SECURITY_HASH + * JPA added COLLATION_NTOFS_ULONGS */ - if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG && - cr != COLLATION_FILE_NAME) + if (cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG + && cr != COLLATION_FILE_NAME + && cr != COLLATION_NTOFS_SECURITY_HASH + && cr != COLLATION_NTOFS_ULONGS) goto err; i = le32_to_cpu(cr); if (i < 0) diff --git a/release/src/router/ntfs-3g/libntfs-3g/compat.c b/release/src/router/ntfs-3g/libntfs-3g/compat.c index 81f95a673c..e9b3d5df44 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/compat.c +++ b/release/src/router/ntfs-3g/libntfs-3g/compat.c @@ -77,7 +77,7 @@ int ffs(int x) #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: compat.c,v 1.2 2008/07/17 15:01:48 szaka Exp $"; +static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.7 2009/03/27 09:09:59 jpandre Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -164,7 +164,7 @@ int daemon(int nochdir, int noclose) { #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$Id: compat.c,v 1.2 2008/07/17 15:01:48 szaka Exp $"; +static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.7 2009/03/27 09:09:59 jpandre Exp $"; #endif /* LIBC_SCCS and not lint */ /* diff --git a/release/src/router/ntfs-3g/libntfs-3g/compress.c b/release/src/router/ntfs-3g/libntfs-3g/compress.c index 09f874bbc3..4db1826d39 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/compress.c +++ b/release/src/router/ntfs-3g/libntfs-3g/compress.c @@ -5,6 +5,7 @@ * Copyright (c) 2004-2005 Anton Altaparmakov * Copyright (c) 2004-2006 Szabolcs Szakacsits * Copyright (c) 2005 Yura Pakhuchiy + * Copyright (c) 2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -20,6 +21,17 @@ * along with this program (in the main directory of the NTFS-3G * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * A part of the compression algorithm is based on lzhuf.c whose header + * describes the roles of the original authors (with no apparent copyright + * notice, and according to http://home.earthlink.net/~neilbawd/pall.html + * this was put into public domain in 1988 by Haruhiko OKUMURA). + * + * LZHUF.C English version 1.0 + * Based on Japanese version 29-NOV-1988 + * LZSS coded by Haruhiko OKUMURA + * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI + * Edited and translated to English by Kenji RIKITAKE */ #ifdef HAVE_CONFIG_H @@ -46,6 +58,7 @@ #include "layout.h" #include "runlist.h" #include "compress.h" +#include "lcnalloc.h" #include "logging.h" #include "misc.h" @@ -64,6 +77,263 @@ typedef enum { NTFS_SB_IS_COMPRESSED = 0x8000, } ntfs_compression_constants; +#define THRESHOLD 3 /* minimal match length for compression */ +#define NIL NTFS_SB_SIZE /* End of tree's node */ + +struct COMPRESS_CONTEXT { + const unsigned char *inbuf; + unsigned int len; + unsigned int nbt; + int match_position; + unsigned int match_length; + u16 lson[NTFS_SB_SIZE + 1]; + u16 rson[NTFS_SB_SIZE + 257]; + u16 dad[NTFS_SB_SIZE + 1]; +} ; + +/* + * Initialize the match tree + */ + +static void ntfs_init_compress_tree(struct COMPRESS_CONTEXT *pctx) +{ + int i; + + for (i = NTFS_SB_SIZE + 1; i <= NTFS_SB_SIZE + 256; i++) + pctx->rson[i] = NIL; /* root */ + for (i = 0; i < NTFS_SB_SIZE; i++) + pctx->dad[i] = NIL; /* node */ +} + +/* + * Insert a new node into match tree for quickly locating + * further similar strings + */ + +static void ntfs_new_node (struct COMPRESS_CONTEXT *pctx, + unsigned int r) +{ + unsigned int pp; + BOOL less; + BOOL done; + const unsigned char *key; + int c; + unsigned int mxi; + unsigned int mxl; + + mxl = (1 << (16 - pctx->nbt)) + 2; + less = FALSE; + done = FALSE; + key = &pctx->inbuf[r]; + pp = NTFS_SB_SIZE + 1 + key[0]; + pctx->rson[r] = pctx->lson[r] = NIL; + pctx->match_length = 0; + do { + if (!less) { + if (pctx->rson[pp] != NIL) + pp = pctx->rson[pp]; + else { + pctx->rson[pp] = r; + pctx->dad[r] = pp; + done = TRUE; + } + } else { + if (pctx->lson[pp] != NIL) + pp = pctx->lson[pp]; + else { + pctx->lson[pp] = r; + pctx->dad[r] = pp; + done = TRUE; + } + } + if (!done) { + register unsigned int i; + register const unsigned char *p1,*p2; + + i = 1; + p1 = key; + p2 = &pctx->inbuf[pp]; + mxi = NTFS_SB_SIZE - r; + do { + } while ((p1[i] == p2[i]) && (++i < mxi)); + less = (i < mxi) && (p1[i] < p2[i]); + if (i >= THRESHOLD) { + if (i > pctx->match_length) { + pctx->match_position = + r - pp + 2*NTFS_SB_SIZE - 1; + if ((pctx->match_length = i) > mxl) { + i = pctx->rson[pp]; + pctx->rson[r] = i; + pctx->dad[i] = r; + i = pctx->lson[pp]; + pctx->lson[r] = i; + pctx->dad[i] = r; + i = pctx->dad[pp]; + pctx->dad[r] = i; + if (pctx->rson[i] == pp) + pctx->rson[i] = r; + else + pctx->lson[i] = r; + pctx->dad[pp] = NIL; /* remove pp */ + done = TRUE; + pctx->match_length = mxl; + } + } else + if ((i == pctx->match_length) + && ((c = (r - pp + 2*NTFS_SB_SIZE - 1)) + < pctx->match_position)) + pctx->match_position = c; + } + } + } while (!done); +} + +/* + * Search for the longest previous string matching the + * current one + * + * Returns the end of the longest current string which matched + * or zero if there was a bug + */ + +static unsigned int ntfs_nextmatch(struct COMPRESS_CONTEXT *pctx, unsigned int rr, int dd) +{ + unsigned int bestlen = 0; + + do { + rr++; + if (pctx->match_length > 0) + pctx->match_length--; + if (!pctx->len) { + ntfs_log_error("compress bug : void run\n"); + goto bug; + } + if (--pctx->len) { + if (rr >= NTFS_SB_SIZE) { + ntfs_log_error("compress bug : buffer overflow\n"); + goto bug; + } + if (((rr + bestlen) < NTFS_SB_SIZE)) { + while ((unsigned int)(1 << pctx->nbt) <= (rr - 1)) + pctx->nbt++; + ntfs_new_node(pctx,rr); + if (pctx->match_length > bestlen) + bestlen = pctx->match_length; + } else + if (dd > 0) { + rr += dd; + if ((int)pctx->match_length > dd) + pctx->match_length -= dd; + else + pctx->match_length = 0; + if ((int)pctx->len < dd) { + ntfs_log_error("compress bug : run overflows\n"); + goto bug; + } + pctx->len -= dd; + dd = 0; + } + } + } while (dd-- > 0); + return (rr); +bug : + return (0); +} + +/* + * Compress an input block + * + * Returns the size of the compressed block (including header) + * or zero if there was an error + */ + +static unsigned int ntfs_compress_block(const char *inbuf, unsigned int size, char *outbuf) +{ + struct COMPRESS_CONTEXT *pctx; + char *ptag; + int dd; + unsigned int rr; + unsigned int last_match_length; + unsigned int q; + unsigned int xout; + unsigned int ntag; + + pctx = (struct COMPRESS_CONTEXT*)malloc(sizeof(struct COMPRESS_CONTEXT)); + if (pctx) { + pctx->inbuf = (const unsigned char*)inbuf; + ntfs_init_compress_tree(pctx); + xout = 2; + ntag = 0; + ptag = &outbuf[xout++]; + *ptag = 0; + rr = 0; + pctx->nbt = 4; + pctx->len = size; + pctx->match_length = 0; + ntfs_new_node(pctx,0); + do { + if (pctx->match_length > pctx->len) + pctx->match_length = pctx->len; + if (pctx->match_length < THRESHOLD) { + pctx->match_length = 1; + if (ntag >= 8) { + ntag = 0; + ptag = &outbuf[xout++]; + *ptag = 0; + } + outbuf[xout++] = inbuf[rr]; + ntag++; + } else { + while ((unsigned int)(1 << pctx->nbt) <= (rr - 1)) + pctx->nbt++; + q = (pctx->match_position << (16 - pctx->nbt)) + + pctx->match_length - THRESHOLD; + if (ntag >= 8) { + ntag = 0; + ptag = &outbuf[xout++]; + *ptag = 0; + } + *ptag |= 1 << ntag++; + outbuf[xout++] = q & 255; + outbuf[xout++] = (q >> 8) & 255; + } + last_match_length = pctx->match_length; + dd = last_match_length; + if (dd-- > 0) { + rr = ntfs_nextmatch(pctx,rr,dd); + if (!rr) + goto bug; + } + /* + * stop if input is exhausted or output has exceeded + * the maximum size. Two extra bytes have to be + * reserved in output buffer, as 3 bytes may be + * output in a loop. + */ + } while ((pctx->len > 0) + && (rr < size) && (xout < (NTFS_SB_SIZE + 2))); + /* uncompressed must be full size, so accept if better */ + if (xout < (NTFS_SB_SIZE + 2)) { + outbuf[0] = (xout - 3) & 255; + outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15); + } else { + memcpy(&outbuf[2],inbuf,size); + if (size < NTFS_SB_SIZE) + memset(&outbuf[size+2],0,NTFS_SB_SIZE - size); + outbuf[0] = 0xff; + outbuf[1] = 0x3f; + xout = NTFS_SB_SIZE + 2; + } + free(pctx); + } else { + xout = 0; + errno = ENOMEM; + } + return (xout); /* 0 for an error, > size if cannot compress */ +bug : + return (0); +} + /** * ntfs_decompress - decompress a compression block into an array of pages * @dest: buffer to which to write the decompressed data @@ -108,7 +378,7 @@ do_next_sb: * position in the compression block is one byte before its end so the * first two checks do not detect it. */ - if (cb == cb_end || !le16_to_cpup((u16*)cb) || dest == dest_end) { + if (cb == cb_end || !le16_to_cpup((le16*)cb) || dest == dest_end) { ntfs_log_debug("Completed. Returning success (0).\n"); return 0; } @@ -123,12 +393,12 @@ do_next_sb: goto return_overflow; /* Setup the current sub-block source pointers and validate range. */ cb_sb_start = cb; - cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK) + cb_sb_end = cb_sb_start + (le16_to_cpup((le16*)cb) & NTFS_SB_SIZE_MASK) + 3; if (cb_sb_end > cb_end) goto return_overflow; /* Now, we are ready to process the current sub-block (sb). */ - if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) { + if (!(le16_to_cpup((le16*)cb) & NTFS_SB_IS_COMPRESSED)) { ntfs_log_debug("Found uncompressed sub-block.\n"); /* This sb is not compressed, just copy it into destination. */ /* Advance source position to first data byte. */ @@ -202,7 +472,7 @@ do_next_tag: for (i = dest - dest_sb_start - 1; i >= 0x10; i >>= 1) lg++; /* Get the phrase token into i. */ - pt = le16_to_cpup((u16*)cb); + pt = le16_to_cpup((le16*)cb); /* * Calculate starting position of the byte sequence in * the destination using the fact that p = (pt >> (12 - lg)) + 1 @@ -332,13 +602,19 @@ s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b) u8 *dest, *cb, *cb_pos, *cb_end; u32 cb_size; int err; + ATTR_FLAGS data_flags; + FILE_ATTR_FLAGS compression; unsigned int nr_cbs, cb_clusters; ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count 0x%llx.\n", (unsigned long long)na->ni->mft_no, na->type, (long long)pos, (long long)count); - if (!na || !NAttrCompressed(na) || !na->ni || !na->ni->vol || !b || - pos < 0 || count < 0) { + data_flags = na->data_flags; + compression = na->ni->flags & FILE_ATTR_COMPRESSED; + if (!na || !na->ni || !na->ni->vol || !b + || ((data_flags & ATTR_COMPRESSION_MASK) + != ATTR_IS_COMPRESSED) + || pos < 0 || count < 0) { errno = EINVAL; return -1; } @@ -379,12 +655,12 @@ s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b) cb_clusters = na->compression_block_clusters; /* Need a temporary buffer for each loaded compression block. */ - cb = ntfs_malloc(cb_size); + cb = (u8*)ntfs_malloc(cb_size); if (!cb) return -1; /* Need a temporary buffer for each uncompressed block. */ - dest = ntfs_malloc(cb_size); + dest = (u8*)ntfs_malloc(cb_size); if (!dest) { free(cb); return -1; @@ -450,6 +726,7 @@ do_next_cb: to_read = min(count, cb_size - ofs); ofs += vcn << vol->cluster_size_bits; NAttrClearCompressed(na); + na->data_flags &= ~ATTR_COMPRESSION_MASK; tdata_size = na->data_size; tinitialized_size = na->initialized_size; na->data_size = na->initialized_size = na->allocated_size; @@ -459,7 +736,8 @@ do_next_cb: err = errno; na->data_size = tdata_size; na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); + na->ni->flags |= compression; + na->data_flags = data_flags; free(cb); free(dest); if (total) @@ -475,7 +753,8 @@ do_next_cb: } while (to_read > 0); na->data_size = tdata_size; na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); + na->ni->flags |= compression; + na->data_flags = data_flags; ofs = 0; } else { s64 tdata_size, tinitialized_size; @@ -496,6 +775,7 @@ do_next_cb: */ to_read = cb_size; NAttrClearCompressed(na); + na->data_flags &= ~ATTR_COMPRESSION_MASK; tdata_size = na->data_size; tinitialized_size = na->initialized_size; na->data_size = na->initialized_size = na->allocated_size; @@ -507,7 +787,8 @@ do_next_cb: err = errno; na->data_size = tdata_size; na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); + na->ni->flags |= compression; + na->data_flags = data_flags; free(cb); free(dest); if (total) @@ -520,7 +801,8 @@ do_next_cb: } while (to_read > 0); na->data_size = tdata_size; na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); + na->ni->flags |= compression; + na->data_flags = data_flags; /* Just a precaution. */ if (cb_pos + 2 <= cb_end) *(u16*)cb_pos = 0; @@ -550,3 +832,599 @@ do_next_cb: /* Return number of bytes read. */ return total + total2; } + +/* + * Read data from a set of clusters + * + * Returns the amount of data read + */ + +static u32 read_clusters(ntfs_volume *vol, const runlist_element *rl, + s64 offs, u32 to_read, char *inbuf) +{ + u32 count; + int xgot; + u32 got; + s64 xpos; + BOOL first; + char *xinbuf; + const runlist_element *xrl; + + got = 0; + xrl = rl; + xinbuf = inbuf; + first = TRUE; + do { + count = xrl->length << vol->cluster_size_bits; + xpos = xrl->lcn << vol->cluster_size_bits; + if (first) { + count -= offs; + xpos += offs; + } + if ((to_read - got) < count) + count = to_read - got; + xgot = ntfs_pread(vol->dev, xpos, count, xinbuf); + if (xgot == (int)count) { + got += count; + xpos += count; + xinbuf += count; + xrl++; + } + first = FALSE; + } while ((xgot == (int)count) && (got < to_read)); + return (got); +} + +/* + * Write data to a set of clusters + * + * Returns the amount of data written + */ + +static int write_clusters(ntfs_volume *vol, const runlist_element *rl, + s64 offs, int to_write, const char *outbuf) +{ + int count; + int put, xput; + s64 xpos; + BOOL first; + const char *xoutbuf; + const runlist_element *xrl; + + put = 0; + xrl = rl; + xoutbuf = outbuf; + first = TRUE; + do { + count = xrl->length << vol->cluster_size_bits; + xpos = xrl->lcn << vol->cluster_size_bits; + if (first) { + count -= offs; + xpos += offs; + } + if ((to_write - put) < count) + count = to_write - put; + xput = ntfs_pwrite(vol->dev, xpos, count, xoutbuf); + if (xput == count) { + put += count; + xpos += count; + xoutbuf += count; + xrl++; + } + first = FALSE; + } while ((xput == count) && (put < to_write)); + return (put); +} + + +/* + * Compress and write a set of blocks + * + * returns the size actually written (rounded to a full cluster) + * or 0 if all zeroes (nothing is written) + * or -1 if could not compress (nothing is written) + * or -2 if there were an irrecoverable error (errno set) + */ + +static int ntfs_comp_set(ntfs_attr *na, runlist_element *rl, + s64 offs, unsigned int insz, const char *inbuf) +{ + ntfs_volume *vol; + char *outbuf; + char *pbuf; + unsigned int compsz; + int written; + int rounded; + unsigned int clsz; + unsigned int p; + unsigned int sz; + unsigned int bsz; + BOOL fail; + BOOL allzeroes; + /* a single compressed zero */ + static char onezero[] = { 0x01, 0xb0, 0x00, 0x00 } ; + /* a couple of compressed zeroes */ + static char twozeroes[] = { 0x02, 0xb0, 0x00, 0x00, 0x00 } ; + /* more compressed zeroes, to be followed by some count */ + static char morezeroes[] = { 0x03, 0xb0, 0x02, 0x00 } ; + + vol = na->ni->vol; + written = -1; /* default return */ + clsz = 1 << vol->cluster_size_bits; + /* may need 2 extra bytes per block and 2 more bytes */ + outbuf = (char*)ntfs_malloc(na->compression_block_size + + 2*(na->compression_block_size/NTFS_SB_SIZE) + + 2); + if (outbuf) { + fail = FALSE; + compsz = 0; + allzeroes = TRUE; + for (p=0; (p na->compression_block_size)) + fail = TRUE; + else { + if (allzeroes) { + /* check whether this is all zeroes */ + switch (sz) { + case 4 : + allzeroes = !memcmp( + pbuf,onezero,4); + break; + case 5 : + allzeroes = !memcmp( + pbuf,twozeroes,5); + break; + case 6 : + allzeroes = !memcmp( + pbuf,morezeroes,4); + break; + default : + allzeroes = FALSE; + break; + } + } + compsz += sz; + } + } + if (!fail && !allzeroes) { + /* add a couple of null bytes, space has been checked */ + outbuf[compsz++] = 0; + outbuf[compsz++] = 0; + /* write a full cluster, to avoid partial reading */ + rounded = ((compsz - 1) | (clsz - 1)) + 1; + written = write_clusters(vol, rl, offs, rounded, outbuf); + if (written != rounded) { +// previously written text has been spoilt, should return a specific error + ntfs_log_error("error writing compressed data\n"); + errno = EIO; + written = -2; + } + } else + if (!fail) + written = 0; + free(outbuf); + } + return (written); +} + +/* + * Free unneeded clusters after compression + * + * This generally requires an empty slot at the end of runlist, + * but we do not want to reallocate the runlist here because + * there are many pointers to it. + * So the empty slot has to be reserved beforehand + * + * Returns zero unless some error occurred (described by errno) + */ + +static int ntfs_compress_free(ntfs_attr *na, runlist_element *rl, + s64 used, s64 reserved) +{ + int freecnt; + int usedcnt; + int res; + s64 freelcn; + s64 freevcn; + int freelength; + BOOL mergeholes; + BOOL beginhole; + ntfs_volume *vol; + runlist_element *freerl; + + res = -1; /* default return */ + vol = na->ni->vol; + freecnt = (reserved - used) >> vol->cluster_size_bits; + usedcnt = (reserved >> vol->cluster_size_bits) - freecnt; + /* skip entries fully used, if any */ + while (rl->length && (rl->length < usedcnt)) { + usedcnt -= rl->length; + rl++; + } + if (rl->length) { + /* + * Splitting the current allocation block requires + * an extra runlist element to create the hole. + * The required entry has been prereserved when + * mapping the runlist. + */ + freelcn = rl->lcn + usedcnt; + freevcn = rl->vcn + usedcnt; + freelength = rl->length - usedcnt; + /* new count of allocated clusters */ + rl->length = usedcnt; /* warning : can be zero */ + if (!((freevcn + freecnt) + & (na->compression_block_clusters - 1))) { + beginhole = !usedcnt && !rl->vcn; + mergeholes = !usedcnt + && rl[0].vcn + && (rl[-1].lcn == LCN_HOLE); + if (mergeholes) { + freerl = rl; + freerl->length = freecnt; + } else + freerl = ++rl; + if ((freelength > 0) + && !mergeholes + && (usedcnt || beginhole)) { + /* + * move the unused part to the end. Doing so, + * the vcn will be out of order. This does + * not harm, the vcn are meaningless now, and + * only the lcn are meaningful for freeing. + */ + /* locate current end */ + while (rl->length) + rl++; + /* new terminator relocated */ + rl[1].vcn = rl->vcn; + rl[1].lcn = LCN_ENOENT; + rl[1].length = 0; + /* hole, currently allocated */ + rl->vcn = freevcn; + rl->lcn = freelcn; + rl->length = freelength; + } + /* free the hole */ + res = ntfs_cluster_free_from_rl(vol,freerl); + if (!res) { + if (mergeholes) { + /* merge with adjacent hole */ + freerl--; + freerl->length += freecnt; + } else { + if (beginhole) + freerl--; + /* mark hole as free */ + freerl->lcn = LCN_HOLE; + freerl->vcn = freevcn; + freerl->length = freecnt; + } + /* and set up the new end */ + freerl[1].lcn = LCN_ENOENT; + freerl[1].vcn = freevcn + freecnt; + freerl[1].length = 0; + } + } else { + ntfs_log_error("Bad end of a compression block set\n"); + errno = EIO; + } + } else { + ntfs_log_error("No cluster to free after compression\n"); + errno = EIO; + } + return (res); +} + +/* + * Read existing data, decompress and append buffer + * Do nothing if something fails + */ + +static int ntfs_read_append(ntfs_attr *na, const runlist_element *rl, + s64 offs, u32 compsz, int pos, + char *outbuf, s64 to_write, const void *b) +{ + int fail = 1; + char *compbuf; + u32 decompsz; + u32 got; + + if (compsz == na->compression_block_size) { + /* if the full block was requested, it was a hole */ + memset(outbuf,0,compsz); + memcpy(&outbuf[pos],b,to_write); + fail = 0; + } else { + compbuf = (char*)ntfs_malloc(compsz); + if (compbuf) { + /* must align to full block for decompression */ + decompsz = ((pos - 1) | (NTFS_SB_SIZE - 1)) + 1; + got = read_clusters(na->ni->vol, rl, offs, + compsz, compbuf); + if ((got == compsz) + && !ntfs_decompress((u8*)outbuf,decompsz, + (u8*)compbuf,compsz)) { + memcpy(&outbuf[pos],b,to_write); + fail = 0; + } + free(compbuf); + } + } + return (fail); +} + +/* + * Flush a full compression block + * + * returns the size actually written (rounded to a full cluster) + * or 0 if could not compress (and written uncompressed) + * or -1 if there were an irrecoverable error (errno set) + */ + +static int ntfs_flush(ntfs_attr *na, runlist_element *rl, s64 offs, + const char *outbuf, int count, BOOL compress) +{ + int rounded; + int written; + int clsz; + + if (compress) { + written = ntfs_comp_set(na, rl, offs, count, outbuf); + if (written == -1) + compress = FALSE; + if ((written >= 0) + && ntfs_compress_free(na,rl,offs + written, + offs + na->compression_block_size)) + written = -1; + } + if (!compress) { + clsz = 1 << na->ni->vol->cluster_size_bits; + rounded = ((count - 1) | (clsz - 1)) + 1; + written = write_clusters(na->ni->vol, rl, + offs, rounded, outbuf); + if (written != rounded) + written = -1; + } + return (written); +} + +/* + * Write some data to be compressed. + * Compression only occurs when a few clusters (usually 16) are + * full. When this occurs an extra runlist slot may be needed, so + * it has to be reserved beforehand. + * + * Returns the size of uncompressed data written, + * or zero if an error occurred. + * When the returned size is less than requested, new clusters have + * to be allocated before the function is called again. + */ + +s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *wrl, s64 wpos, + s64 offs, s64 to_write, s64 rounded, + const void *b, int compressed_part) +{ + ntfs_volume *vol; + runlist_element *brl; /* entry containing the beginning of block */ + int compression_length; + s64 written; + s64 to_read; + s64 roffs; + s64 got; + s64 start_vcn; + s64 nextblock; + u32 compsz; + char *inbuf; + char *outbuf; + BOOL fail; + BOOL done; + BOOL compress; + + written = 0; /* default return */ + vol = na->ni->vol; + compression_length = na->compression_block_clusters; + compress = FALSE; + done = FALSE; + /* + * Cannot accept writing beyond the current compression set + * because when compression occurs, clusters are freed + * and have to be reallocated. + * (cannot happen with standard fuse 4K buffers) + * Caller has to avoid this situation, or face consequences. + */ + nextblock = ((offs + (wrl->vcn << vol->cluster_size_bits)) + | (na->compression_block_size - 1)) + 1; + if ((offs + to_write + (wrl->vcn << vol->cluster_size_bits)) + >= nextblock) { + /* it is time to compress */ + compress = TRUE; + /* only process what we can */ + to_write = rounded = nextblock + - (offs + (wrl->vcn << vol->cluster_size_bits)); + } + start_vcn = 0; + fail = FALSE; + brl = wrl; + roffs = 0; + /* + * If we are about to compress or we need to decompress + * existing data, we have to process a full set of blocks. + * So relocate the parameters to the beginning of allocation + * containing the first byte of the set of blocks. + */ + if (compress || compressed_part) { + /* find the beginning of block */ + start_vcn = (wrl->vcn + (offs >> vol->cluster_size_bits)) + & -compression_length; + while (brl->vcn && (brl->vcn > start_vcn)) { + /* jumping back a hole means big trouble */ + if (brl->lcn == (LCN)LCN_HOLE) { + ntfs_log_error("jump back over a hole when appending\n"); + fail = TRUE; + errno = EIO; + } + brl--; + offs += brl->length << vol->cluster_size_bits; + } + roffs = (start_vcn - brl->vcn) << vol->cluster_size_bits; + } + if (compressed_part && !fail) { + /* + * The set of compression blocks contains compressed data + * (we are reopening an existing file to append to it) + * Decompress the data and append + */ + compsz = compressed_part << vol->cluster_size_bits; +// improve the needed size + outbuf = (char*)ntfs_malloc(na->compression_block_size); + if (outbuf) { + to_read = offs - roffs; + if (!ntfs_read_append(na, brl, roffs, compsz, + to_read, outbuf, to_write, b)) { + written = ntfs_flush(na, brl, roffs, + outbuf, to_read + to_write, compress); + if (written >= 0) { + written = to_write; + done = TRUE; + } + } + free(outbuf); + } + } else { + if (compress && !fail) { + /* + * we are filling up a block, read the full set of blocks + * and compress it + */ + inbuf = (char*)ntfs_malloc(na->compression_block_size); + if (inbuf) { + to_read = offs - roffs; + if (to_read) + got = read_clusters(vol, brl, roffs, + to_read, inbuf); + else + got = 0; + if (got == to_read) { + memcpy(&inbuf[to_read],b,to_write); + written = ntfs_comp_set(na, brl, roffs, + to_read + to_write, inbuf); + /* + * if compression was not successful, + * only write the part which was requested + */ + if ((written >= 0) + /* free the unused clusters */ + && !ntfs_compress_free(na,brl, + written + roffs, + na->compression_block_size + + roffs)) { + done = TRUE; + written = to_write; + } + } + free(inbuf); + } + } + if (!done) { + /* + * if the compression block is not full, or + * if compression failed for whatever reason, + * write uncompressed + */ + /* check we are not overflowing current allocation */ + if ((wpos + rounded) + > ((wrl->lcn + wrl->length) + << vol->cluster_size_bits)) { + ntfs_log_error("writing on unallocated clusters\n"); + errno = EIO; + } else { + written = ntfs_pwrite(vol->dev, wpos, + rounded, b); + if (written == rounded) + written = to_write; + } + } + } + return (written); +} + +/* + * Close a file written compressed. + * This compresses the last partial compression block of the file. + * An empty runlist slot has to be reserved beforehand. + * + * Returns zero if closing is successful. + */ + +int ntfs_compressed_close(ntfs_attr *na, runlist_element *wrl, s64 offs) +{ + ntfs_volume *vol; + runlist_element *brl; /* entry containing the beginning of block */ + int compression_length; + s64 written; + s64 to_read; + s64 roffs; + s64 got; + s64 start_vcn; + char *inbuf; + BOOL fail; + BOOL done; + + vol = na->ni->vol; + compression_length = na->compression_block_clusters; + done = FALSE; + /* + * There generally is an uncompressed block at end of file, + * read the full block and compress it + */ + inbuf = (char*)ntfs_malloc(na->compression_block_size); + if (inbuf) { + start_vcn = (wrl->vcn + (offs >> vol->cluster_size_bits)) + & -compression_length; + to_read = offs + ((wrl->vcn - start_vcn) << vol->cluster_size_bits); + brl = wrl; + fail = FALSE; + while (brl->vcn && (brl->vcn > start_vcn)) { + if (brl->lcn == (LCN)LCN_HOLE) { + ntfs_log_error("jump back over a hole when closing\n"); + fail = TRUE; + errno = EIO; + } + brl--; + } + if (!fail) { + /* roffs can be an offset from another uncomp block */ + roffs = (start_vcn - brl->vcn) << vol->cluster_size_bits; + if (to_read) { + got = read_clusters(vol, brl, roffs, to_read, + inbuf); + if (got == to_read) { + written = ntfs_comp_set(na, brl, roffs, + to_read, inbuf); + if ((written >= 0) + /* free the unused clusters */ + && !ntfs_compress_free(na,brl, + written + roffs, + na->compression_block_size + roffs)) { + done = TRUE; + } else + /* if compression failed, leave uncompressed */ + if (written == -1) + done = TRUE; + } + } else + done = TRUE; + free(inbuf); + } + } + return (!done); +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/dir.c b/release/src/router/ntfs-3g/libntfs-3g/dir.c index ebc0803b84..297f10f1b6 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/dir.c +++ b/release/src/router/ntfs-3g/libntfs-3g/dir.c @@ -5,6 +5,7 @@ * Copyright (c) 2004-2005 Richard Russon * Copyright (c) 2004-2008 Szabolcs Szakacsits * Copyright (c) 2005-2007 Yura Pakhuchiy + * Copyright (c) 2008-2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -56,6 +57,11 @@ #include "logging.h" #include "misc.h" #include "security.h" +#include "reparse.h" + +#ifdef HAVE_SETXATTR +#include +#endif /* * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O" @@ -77,6 +83,45 @@ ntfschar NTFS_INDEX_Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'), ntfschar NTFS_INDEX_R[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('R'), const_cpu_to_le16('\0') }; +#if CACHE_INODE_SIZE + +/* + * Pathname comparing for entering/fetching from cache + */ + +static int inode_cache_compare(const struct CACHED_GENERIC *cached, + const struct CACHED_GENERIC *wanted) +{ + return (!cached->variable + || strcmp(cached->variable, wanted->variable)); +} + +/* + * Pathname comparing for invalidating entries in cache + * + * A partial path is compared in order to invalidate all paths + * related to a renamed directory + * inode numbers are also checked, as deleting a long name may + * imply deleting a short name and conversely + */ + +static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached, + const struct CACHED_GENERIC *wanted) +{ + int len; + + len = strlen(wanted->variable); + return (!cached->variable + || ((((const struct CACHED_INODE*)wanted)->inum + != MREF(((const struct CACHED_INODE*)cached)->inum)) + && (strncmp((const char*)cached->variable, + (const char*)wanted->variable,len) + || ((((const char*)cached->variable)[len] != '\0') + && (((const char*)cached->variable)[len] != '/'))))); +} + +#endif + /** * ntfs_inode_lookup_by_name - find an inode in a directory given its name * @dir_ni: ntfs inode of the directory in which to search for the name @@ -441,6 +486,11 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, ntfs_inode *result = NULL; ntfschar *unicode = NULL; char *ascii = NULL; +#if CACHE_INODE_SIZE + struct CACHED_INODE item; + struct CACHED_INODE *cached; + char *fullname; +#endif if (!vol || !pathname) { errno = EINVAL; @@ -449,35 +499,68 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, ntfs_log_trace("path: '%s'\n", pathname); + ascii = strdup(pathname); + if (!ascii) { + ntfs_log_error("Out of memory.\n"); + err = ENOMEM; + goto out; + } + + p = ascii; + /* Remove leading /'s. */ + while (p && *p && *p == PATH_SEP) + p++; +#if CACHE_INODE_SIZE + fullname = p; + if (p[0] && (p[strlen(p)-1] == PATH_SEP)) + ntfs_log_error("Unnormalized path %s\n",ascii); +#endif if (parent) { ni = parent; } else { +#if CACHE_INODE_SIZE + /* + * fetch inode for full path from cache + */ + if (*fullname) { + item.pathname = fullname; + item.varsize = strlen(fullname) + 1; + cached = (struct CACHED_INODE*)ntfs_fetch_cache( + vol->xinode_cache, GENERIC(&item), + inode_cache_compare); + } else + cached = (struct CACHED_INODE*)NULL; + if (cached) { + /* + * return opened inode if found in cache + */ + inum = MREF(cached->inum); + ni = ntfs_inode_open(vol, inum); + if (!ni) { + ntfs_log_debug("Cannot open inode %llu: %s.\n", + (unsigned long long)inum, p); + err = EIO; + } + result = ni; + goto out; + } +#endif ni = ntfs_inode_open(vol, FILE_root); if (!ni) { ntfs_log_debug("Couldn't open the inode of the root " "directory.\n"); err = EIO; - goto close; + result = (ntfs_inode*)NULL; + goto out; } } - ascii = strdup(pathname); - if (!ascii) { - ntfs_log_error("Out of memory.\n"); - err = ENOMEM; - goto close; - } - - p = ascii; - /* Remove leading /'s. */ - while (p && *p && *p == PATH_SEP) - p++; while (p && *p) { /* Find the end of the first token. */ q = strchr(p, PATH_SEP); if (q != NULL) { *q = '\0'; - q++; + /* q++; JPA */ } len = ntfs_mbstoucs(p, &unicode); @@ -490,8 +573,34 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, err = ENAMETOOLONG; goto close; } - +#if CACHE_INODE_SIZE + /* + * fetch inode for partial path from cache + * if not available, compute and store into cache + */ + if (parent) + inum = ntfs_inode_lookup_by_name(ni, unicode, len); + else { + item.pathname = fullname; + item.varsize = strlen(fullname) + 1; + cached = (struct CACHED_INODE*)ntfs_fetch_cache( + vol->xinode_cache, GENERIC(&item), + inode_cache_compare); + if (cached) { + inum = cached->inum; + } else { + inum = ntfs_inode_lookup_by_name(ni, unicode, len); + if (inum != (u64) -1) { + item.inum = inum; + ntfs_enter_cache(vol->xinode_cache, + GENERIC(&item), + inode_cache_compare); + } + } + } +#else inum = ntfs_inode_lookup_by_name(ni, unicode, len); +#endif if (inum == (u64) -1) { ntfs_log_debug("Couldn't find name '%s' in pathname " "'%s'.\n", p, pathname); @@ -513,10 +622,11 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, err = EIO; goto close; } - + free(unicode); unicode = NULL; + if (q) *q++ = PATH_SEP; /* JPA */ p = q; while (p && *p && *p == PATH_SEP) p++; @@ -1030,6 +1140,7 @@ err_out: /** * __ntfs_create - create object on ntfs volume * @dir_ni: ntfs inode for directory in which create new object + * @securid: id of inheritable security descriptor, 0 if none * @name: unicode name of new object * @name_len: length of the name in unicode characters * @type: type of the object to create @@ -1058,8 +1169,8 @@ err_out: * Return opened ntfs inode that describes created object on success or NULL * on error with errno set to the error code. */ -static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, - ntfschar *name, u8 name_len, dev_t type, dev_t dev, +static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid, + ntfschar *name, u8 name_len, mode_t type, dev_t dev, ntfschar *target, int target_len) { ntfs_inode *ni; @@ -1086,10 +1197,14 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, if (!ni) return NULL; /* - * Create STANDARD_INFORMATION attribute. Write STANDARD_INFORMATION - * version 1.2, windows will upgrade it to version 3 if needed. + * Create STANDARD_INFORMATION attribute. + * JPA Depending on available inherited security descriptor, + * Write STANDARD_INFORMATION v1.2 (no inheritance) or v3 */ - si_len = offsetof(STANDARD_INFORMATION, v1_end); + if (securid) + si_len = sizeof(STANDARD_INFORMATION); + else + si_len = offsetof(STANDARD_INFORMATION, v1_end); si = ntfs_calloc(si_len); if (!si) { err = errno; @@ -1099,10 +1214,21 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, si->last_data_change_time = utc2ntfs(ni->last_data_change_time); si->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); si->last_access_time = utc2ntfs(ni->last_access_time); + if (securid) { + set_nino_flag(ni, v3_Extensions); + ni->owner_id = si->owner_id = 0; + ni->security_id = si->security_id = securid; + ni->quota_charged = si->quota_charged = const_cpu_to_le64(0); + ni->usn = si->usn = const_cpu_to_le64(0); + } else + clear_nino_flag(ni, v3_Extensions); if (!S_ISREG(type) && !S_ISDIR(type)) { si->file_attributes = FILE_ATTR_SYSTEM; ni->flags = FILE_ATTR_SYSTEM; } + if ((dir_ni->flags & FILE_ATTR_COMPRESSED) + && (S_ISREG(type) || S_ISDIR(type))) + ni->flags |= FILE_ATTR_COMPRESSED; /* Add STANDARD_INFORMATION to inode. */ if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, (u8*)si, si_len)) { @@ -1111,10 +1237,12 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, "attribute.\n"); goto err_out; } - - if (ntfs_sd_add_everyone(ni)) { - err = errno; - goto err_out; + + if (!securid) { + if (ntfs_sd_add_everyone(ni)) { + err = errno; + goto err_out; + } } rollback_sd = 1; @@ -1225,6 +1353,8 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT; if (!S_ISREG(type) && !S_ISDIR(type)) fn->file_attributes = FILE_ATTR_SYSTEM; + else + fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED; fn->creation_time = utc2ntfs(ni->creation_time); fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); @@ -1287,36 +1417,36 @@ err_out: * Some wrappers around __ntfs_create() ... */ -ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type) +ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name, + u8 name_len, mode_t type) { if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO && type != S_IFSOCK) { ntfs_log_error("Invalid arguments.\n"); return NULL; } - return __ntfs_create(dir_ni, name, name_len, type, 0, NULL, 0); + return __ntfs_create(dir_ni, securid, name, name_len, type, 0, NULL, 0); } -ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type, dev_t dev) +ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, + ntfschar *name, u8 name_len, mode_t type, dev_t dev) { if (type != S_IFCHR && type != S_IFBLK) { ntfs_log_error("Invalid arguments.\n"); return NULL; } - return __ntfs_create(dir_ni, name, name_len, type, dev, NULL, 0); + return __ntfs_create(dir_ni, securid, name, name_len, type, dev, NULL, 0); } -ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - ntfschar *target, int target_len) +ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, + ntfschar *name, u8 name_len, ntfschar *target, int target_len) { if (!target || !target_len) { ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__, target, target_len); return NULL; } - return __ntfs_create(dir_ni, name, name_len, S_IFLNK, 0, + return __ntfs_create(dir_ni, securid, name, name_len, S_IFLNK, 0, target, target_len); } @@ -1383,13 +1513,20 @@ no_hardlink: * * Return 0 on success or -1 on error with errno set to the error code. */ -int ntfs_delete(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) +int ntfs_delete(ntfs_volume *vol, const char *pathname, + ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) { ntfs_attr_search_ctx *actx = NULL; FILE_NAME_ATTR *fn = NULL; BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE; BOOL case_sensitive_match = TRUE; int err = 0; +#if CACHE_INODE_SIZE + struct CACHED_INODE item; + const char *p; + u64 inum = (u64)-1; + int count; +#endif ntfs_log_trace("Entering.\n"); @@ -1481,7 +1618,7 @@ search: if (ntfs_check_unlinkable_dir(ni, fn) < 0) goto err_out; - if (ntfs_index_remove(dir_ni, fn, le32_to_cpu(actx->attr->value_length))) + if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length))) goto err_out; if (ntfs_attr_record_rm(actx)) @@ -1503,10 +1640,22 @@ search: * case there are no reference to this inode left, so we should free all * non-resident attributes and mark all MFT record as not in use. */ +#if CACHE_INODE_SIZE + inum = ni->mft_no; +#endif if (ni->mrec->link_count) { ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME); goto ok; } + if (ntfs_delete_reparse_index(ni)) { + /* + * Failed to remove the reparse index : proceed anyway + * This is not a critical error, the entry is useless + * because of sequence_number, and stopping file deletion + * would be much worse as the file is not referenced now. + */ + err = errno; + } ntfs_attr_reinit_search_ctx(actx); while (!ntfs_attrs_walk(actx)) { if (actx->attr->non_resident) { @@ -1556,6 +1705,24 @@ out: err = errno; if (ntfs_inode_close(ni) && !err) err = errno; +#if CACHE_INODE_SIZE + if (pathname) { + /* invalide cache entry, even if there was an error */ + /* Remove leading /'s. */ + p = pathname; + while (*p == PATH_SEP) + p++; + if (p[0] && (p[strlen(p)-1] == PATH_SEP)) + ntfs_log_error("Unnormalized path %s\n",pathname); + item.pathname = p; + item.inum = inum; + count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item), + inode_cache_inv_compare); + if (!count) + ntfs_log_error("Could not delete inode cache entry for %s\n", + pathname); + } +#endif if (err) { errno = err; ntfs_log_debug("Could not delete file: %s\n", strerror(errno)); @@ -1583,7 +1750,8 @@ err_out: * * Return 0 on success or -1 on error with errno set to the error code. */ -int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) +static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, + u8 name_len, FILE_NAME_TYPE_FLAGS nametype) { FILE_NAME_ATTR *fn = NULL; int fn_len, err; @@ -1597,7 +1765,8 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) goto err_out; } - if (ni->flags & FILE_ATTR_REPARSE_POINT) { + if ((ni->flags & FILE_ATTR_REPARSE_POINT) + && !ntfs_possible_symlink(ni)) { err = EOPNOTSUPP; goto err_out; } @@ -1612,7 +1781,7 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, le16_to_cpu(dir_ni->mrec->sequence_number)); fn->file_name_length = name_len; - fn->file_name_type = FILE_NAME_POSIX; + fn->file_name_type = nametype; fn->file_attributes = ni->flags; if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT; @@ -1635,7 +1804,7 @@ int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) ntfs_log_error("Failed to add FILE_NAME attribute.\n"); err = errno; /* Try to remove just added attribute from index. */ - if (ntfs_index_remove(dir_ni, fn, fn_len)) + if (ntfs_index_remove(dir_ni, ni, fn, fn_len)) goto rollback_failed; goto err_out; } @@ -1655,3 +1824,478 @@ err_out: return -1; } +int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) +{ + return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX)); +} + +#ifdef HAVE_SETXATTR + +#define MAX_DOS_NAME_LENGTH 12 + +/* + * Get a DOS name for a file in designated directory + * + * Returns size if found + * 0 if not found + * -1 if there was an error (described by errno) + */ + +static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) +{ + size_t outsize = 0; + FILE_NAME_ATTR *fn; + ntfs_attr_search_ctx *ctx; + + /* find the name in the attributes */ + ctx = ntfs_attr_get_search_ctx(ni, NULL); + if (!ctx) + return -1; + + while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, + 0, NULL, 0, ctx)) { + /* We know this will always be resident. */ + fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + + le16_to_cpu(ctx->attr->value_offset)); + + if ((fn->file_name_type & FILE_NAME_DOS) + && (MREF_LE(fn->parent_directory) == dnum)) { + /* + * Found a DOS or WIN32+DOS name for the entry + * copy name, after truncation for safety + */ + outsize = fn->file_name_length; +/* TODO : reject if name is too long ? */ + if (outsize > MAX_DOS_NAME_LENGTH) + outsize = MAX_DOS_NAME_LENGTH; + memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar)); + } + } + ntfs_attr_put_search_ctx(ctx); + return (outsize); +} + + +/* + * Get the ntfs DOS name into an extended attribute + */ + +int ntfs_get_ntfs_dos_name(const char *path, + char *value, size_t size, ntfs_inode *ni) +{ + int outsize = 0; + char *outname = (char*)NULL; + ntfs_inode *dir_ni = NULL; + u64 dnum; + char *dirname; + const char *rdirname; + char *p; + int doslen; + ntfschar dosname[MAX_DOS_NAME_LENGTH]; + + /* get the parent directory */ + dirname = strdup(path); + if (dirname) { + p = strrchr(dirname,'/'); + if (p) { + *p++ = 0; + rdirname = (dirname[0] ? dirname : "/"); + dir_ni = ntfs_pathname_to_inode(ni->vol, NULL, rdirname); + dnum = dir_ni->mft_no; + free(dirname); + } + } + if (dir_ni) { + doslen = get_dos_name(ni, dnum, dosname); + if (doslen > 0) { + /* + * Found a DOS name for the entry, make + * uppercase and encode into the buffer + * if there is enough space + */ + ntfs_name_upcase(dosname, doslen, + ni->vol->upcase, ni->vol->upcase_len); + if (ntfs_ucstombs(dosname, doslen, &outname, size) < 0) { + ntfs_log_error("Cannot represent dosname in current locale.\n"); + outsize = -errno; + } else { + outsize = strlen(outname); + if (value && (outsize <= (int)size)) + memcpy(value, outname, outsize); + else + if (size && (outsize > (int)size)) + outsize = -ERANGE; + free(outname); + } + } else { + if (doslen == 0) + errno = ENODATA; + outsize = -errno; + } + ntfs_inode_close(dir_ni); + } else + outsize = -errno; + return (outsize); +} + +/* + * Change the name space of an existing file or directory + * + * Returns the old namespace if successful + * -1 if an error occurred (described by errno) + */ + +static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni, + ntfschar *name, int len, + FILE_NAME_TYPE_FLAGS nametype) +{ + ntfs_attr_search_ctx *actx; + ntfs_index_context *icx; + FILE_NAME_ATTR *fnx; + FILE_NAME_ATTR *fn = NULL; + BOOL found; + int lkup; + int ret; + + ret = -1; + actx = ntfs_attr_get_search_ctx(ni, NULL); + if (actx) { + found = FALSE; + do { + lkup = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, + CASE_SENSITIVE, 0, NULL, 0, actx); + if (!lkup) { + fn = (FILE_NAME_ATTR*)((u8*)actx->attr + + le16_to_cpu(actx->attr->value_offset)); + found = (MREF_LE(fn->parent_directory) + == dir_ni->mft_no) + && !memcmp(fn->file_name, name, + len*sizeof(ntfschar)); + } + } while (!lkup && !found); + if (found) { + icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); + if (icx) { + lkup = ntfs_index_lookup((char*)fn, len, icx); + if (!lkup && icx->data && icx->data_len) { + fnx = (FILE_NAME_ATTR*)icx->data; + ret = fn->file_name_type; + fn->file_name_type = nametype; + fnx->file_name_type = nametype; + ntfs_inode_mark_dirty(ni); + ntfs_index_entry_mark_dirty(icx); + } + ntfs_index_ctx_put(icx); + } + } + ntfs_attr_put_search_ctx(actx); + } + return (ret); +} + +/* + * Set a DOS name to a file and adjust name spaces + * + * If the new names are collapsible (same uppercased chars) : + * + * - the existing DOS name or DOS+Win32 name is made Posix + * - if it was a real DOS name, the existing long name is made DOS+Win32 + * and the existing DOS name is deleted + * - finally the existing long name is made DOS+Win32 unless already done + * + * If the new names are not collapsible : + * + * - insert the short name as a DOS name + * - delete the old long name or existing short name + * - insert the new long name (as a Win32 or DOS+Win32 name) + * + * Deleting the old long name will not delete the file + * provided the old name was in the Posix name space, + * because the alternate name has been set before. + * + * The inodes of file and parent directory are always closed + * + * Returns 0 if successful + * -1 if failed + */ + +static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, + const char *fullpath, + ntfschar *shortname, int shortlen, + ntfschar *longname, int longlen, + ntfschar *deletename, int deletelen, BOOL existed) +{ + unsigned int linkcount; + ntfs_volume *vol; + BOOL collapsible; + BOOL deleted; + BOOL done; + FILE_NAME_TYPE_FLAGS oldnametype; + u64 dnum; + u64 fnum; + int res; + + res = -1; + vol = ni->vol; + dnum = dir_ni->mft_no; + fnum = ni->mft_no; + /* save initial link count */ + linkcount = le16_to_cpu(ni->mrec->link_count); + + /* check whether the same name may be used as DOS and WIN32 */ + collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen, + longname, longlen); + if (collapsible) { + deleted = FALSE; + done = FALSE; + if (existed) { + oldnametype = set_namespace(ni, dir_ni, deletename, + deletelen, FILE_NAME_POSIX); + if (oldnametype == FILE_NAME_DOS) { + if (set_namespace(ni, dir_ni, longname, longlen, + FILE_NAME_WIN32_AND_DOS) >= 0) { + if (!ntfs_delete(vol, + (const char*)NULL, ni, dir_ni, + deletename, deletelen)) + res = 0; + deleted = TRUE; + } else + done = TRUE; + } + } + if (!deleted) { + if (!done && (set_namespace(ni, dir_ni, + longname, longlen, + FILE_NAME_WIN32_AND_DOS) >= 0)) + res = 0; + ntfs_inode_close(ni); + ntfs_inode_close(dir_ni); + } + } else + if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, + FILE_NAME_DOS) + /* make sure a new link was recorded */ + && (le16_to_cpu(ni->mrec->link_count) > linkcount)) { + /* delete the existing long name or short name */ + if (!ntfs_delete(vol, fullpath, ni, dir_ni, + deletename, deletelen)) { + /* delete closes the inodes, so have to open again */ + dir_ni = ntfs_inode_open(vol, dnum); + if (dir_ni) { + ni = ntfs_inode_open(vol, fnum); + if (ni) { + if (!ntfs_link_i(ni, dir_ni, + longname, longlen, + FILE_NAME_WIN32)) + res = 0; + ntfs_inode_close(ni); + } + ntfs_inode_close(dir_ni); + } + } + } else { + ntfs_inode_close(ni); + ntfs_inode_close(dir_ni); + } + return (res); +} + + +/* + * Set the ntfs DOS name into an extended attribute + * + * The DOS name will be added as another file name attribute + * using the existing file name information from the original + * name or overwriting the DOS Name if one exists. + * + * The inode of the file is always closed + */ + +int ntfs_set_ntfs_dos_name(const char *path, const char *value, size_t size, + int flags, ntfs_inode *ni) +{ + int res = 0; + int longlen = 0; + int shortlen = 0; + char newname[MAX_DOS_NAME_LENGTH + 1]; + ntfschar oldname[MAX_DOS_NAME_LENGTH]; + int oldlen; + ntfs_volume *vol; + u64 fnum; + u64 dnum; + BOOL closed = FALSE; + ntfschar *shortname = NULL; + ntfschar *longname = NULL; + ntfs_inode *dir_ni = NULL; + char *dirname = (char*)NULL; + const char *rdirname; + char *p; + + vol = ni->vol; + fnum = ni->mft_no; + /* convert the string to the NTFS wide chars */ + if (size > MAX_DOS_NAME_LENGTH) + size = MAX_DOS_NAME_LENGTH; + strncpy(newname, value, size); + newname[size] = 0; + shortlen = ntfs_mbstoucs(newname, &shortname); + /* make sure the short name has valid chars */ + if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) { + ntfs_inode_close(ni); + res = -errno; + return res; + } + /* get the parent directory */ + dirname = strdup(path); + if (dirname) { + p = strrchr(dirname,'/'); + if (p) { + *p++ = 0; + longlen = ntfs_mbstoucs(p, &longname); + /* make sure the long name had valid chars */ + if (!ntfs_forbidden_chars(longname,longlen)) { + rdirname = (dirname[0] ? dirname : "/"); + dir_ni = ntfs_pathname_to_inode(vol, NULL, rdirname); + } + } + } + if (dir_ni) { + dnum = dir_ni->mft_no; + oldlen = get_dos_name(ni, dnum, oldname); + if (oldlen >= 0) { + if (oldlen > 0) { + if (flags & XATTR_CREATE) { + res = -1; + errno = EEXIST; + } else + if ((shortlen == oldlen) + && !memcmp(shortname,oldname, + oldlen*sizeof(ntfschar))) + /* already set, done */ + res = 0; + else { + res = set_dos_name(ni, dir_ni, + path, + shortname, shortlen, + longname, longlen, + oldname, oldlen, TRUE); + closed = TRUE; + } + } else { + if (flags & XATTR_REPLACE) { + res = -1; + errno = ENODATA; + } else { + res = set_dos_name(ni, dir_ni, path, + shortname, shortlen, + longname, longlen, + longname, longlen, FALSE); + closed = TRUE; + } + } + } else + res = -1; + if (!closed) + ntfs_inode_close(dir_ni); + } else { + res = -1; + errno = EINVAL; + } + free(dirname); + free(longname); + free(shortname); + if (!closed) + ntfs_inode_close(ni); + return (res ? -1 : 0); +} + +/* + * Delete the ntfs DOS name + */ + +int ntfs_remove_ntfs_dos_name(const char *path, ntfs_inode *ni) +{ + int res; + int oldnametype; + int longlen = 0; + int shortlen; + u64 dnum; + ntfs_volume *vol; + BOOL deleted = FALSE; + ntfschar shortname[MAX_DOS_NAME_LENGTH]; + ntfschar *longname = NULL; + ntfs_inode *dir_ni = NULL; + char *dirname = (char*)NULL; + const char *rdirname; + char *p; + + res = -1; + vol = ni->vol; + /* get the parent directory */ + dirname = strdup(path); + if (dirname) { + p = strrchr(dirname,'/'); + if (p) { + *p++ = 0; + longlen = ntfs_mbstoucs(p, &longname); + rdirname = (dirname[0] ? dirname : "/"); + dir_ni = ntfs_pathname_to_inode(vol, NULL, rdirname); + } + } + if (dir_ni) { + dnum = dir_ni->mft_no; + shortlen = get_dos_name(ni, dnum, shortname); + if (shortlen >= 0) { + /* migrate the long name as Posix */ + oldnametype = set_namespace(ni,dir_ni,longname,longlen, + FILE_NAME_POSIX); + switch (oldnametype) { + case FILE_NAME_WIN32_AND_DOS : + /* name was Win32+DOS : done */ + res = 0; + break; + case FILE_NAME_DOS : + /* name was DOS, make it back to DOS */ + set_namespace(ni,dir_ni,longname,longlen, + FILE_NAME_DOS); + errno = ENOENT; + break; + case FILE_NAME_WIN32 : + /* name was Win32, make it Posix and delete */ + if (set_namespace(ni,dir_ni,shortname,shortlen, + FILE_NAME_POSIX) >= 0) { + if (!ntfs_delete(vol, + (const char*)NULL, ni, + dir_ni, shortname, + shortlen)) + res = 0; + deleted = TRUE; + } else { + /* + * DOS name has been found, but cannot + * migrate to Posix : something bad + * has happened + */ + errno = EIO; + ntfs_log_error("Could not change" + " DOS name of %s to Posix\n", + path); + } + break; + default : + /* name was Posix or not found : error */ + errno = ENOENT; + break; + } + } + if (!deleted) + ntfs_inode_close(dir_ni); + } + if (!deleted) + ntfs_inode_close(ni); + free(longname); + free(dirname); + return (res); +} + +#endif diff --git a/release/src/router/ntfs-3g/libntfs-3g/efs.c b/release/src/router/ntfs-3g/libntfs-3g/efs.c new file mode 100644 index 0000000000..3b7e53ae6c --- /dev/null +++ b/release/src/router/ntfs-3g/libntfs-3g/efs.c @@ -0,0 +1,339 @@ +/** + * efs.c - Limited processing of encrypted files + * + * This module is part of ntfs-3g library + * + * Copyright (c) 2009 Martin Bene + * Copyright (c) 2009 Jean-Pierre Andre + * + * This program/include file 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/include file 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SETXATTR +#include +#endif + +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include "types.h" +#include "debug.h" +#include "attrib.h" +#include "inode.h" +#include "dir.h" +#include "efs.h" +#include "index.h" +#include "logging.h" +#include "misc.h" +#include "efs.h" + +static ntfschar logged_utility_stream_name[] = { + const_cpu_to_le16('$'), + const_cpu_to_le16('E'), + const_cpu_to_le16('F'), + const_cpu_to_le16('S'), + const_cpu_to_le16(0) +} ; + + +/* + * Get the ntfs EFS info into an extended attribute + */ + +int ntfs_get_efs_info(const char *path, + char *value, size_t size, ntfs_inode *ni) +{ + EFS_ATTR_HEADER *efs_info; + s64 attr_size = 0; + + if (ni) { + if (ni->flags & FILE_ATTR_ENCRYPTED) { + efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni, + AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0, + &attr_size); + if (efs_info + && (le32_to_cpu(efs_info->length) == attr_size)) { + if (attr_size <= (s64)size) { + if (value) + memcpy(value,efs_info,attr_size); + else { + errno = EFAULT; + attr_size = 0; + } + } else + if (size) { + errno = ERANGE; + attr_size = 0; + } + free (efs_info); + } else { + if (efs_info) { + free(efs_info); + ntfs_log_info("Bad efs_info for file %s\n",path); + } else { + ntfs_log_info("Could not get efsinfo" + " for file %s\n", path); + } + errno = EIO; + attr_size = 0; + } + } else { + errno = ENODATA; + ntfs_log_info("File %s is not encrypted",path); + } + } + return (attr_size ? (int)attr_size : -errno); +} + +/* + * Set the efs data from an extended attribute + * Warning : the new data is not checked + * Returns 0, or -1 if there is a problem + */ + +int ntfs_set_efs_info(const char *path __attribute__((unused)), + const char *value, size_t size, int flags, + ntfs_inode *ni) +{ + int res; + int written; + ntfs_attr *na; + const EFS_ATTR_HEADER *info_header; + ntfs_attr_search_ctx *ctx; + + res = 0; + if (ni && value && size) { + if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) { + if (ni->flags & FILE_ATTR_ENCRYPTED) { + ntfs_log_info("File %s already encrypted",path); + errno = EEXIST; + } else { + /* + * Possible problem : if encrypted file was + * restored in a compressed directory, it was + * restored as compressed. + * TODO : decompress first. + */ + ntfs_log_error("File %s cannot be encrypted and compressed\n", + path); + errno = EIO; + } + return -1; + } + info_header = (const EFS_ATTR_HEADER*)value; + /* make sure we get a likely efsinfo */ + if (le32_to_cpu(info_header->length) != size) { + errno = EINVAL; + return (-1); + } + if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM, + (ntfschar*)NULL,0)) { + if (!(flags & XATTR_REPLACE)) { + /* + * no logged_utility_stream attribute : add one, + * apparently, this does not feed the new value in + */ + res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM, + logged_utility_stream_name,4, + (u8*)NULL,(s64)size); + } else { + errno = ENODATA; + res = -1; + } + } else { + errno = EEXIST; + res = -1; + } + if (!res) { + /* + * open and update the existing efs data + */ + na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, + logged_utility_stream_name, 4); + if (na) { + /* resize attribute */ + res = ntfs_attr_truncate(na, (s64)size); + /* overwrite value if any */ + if (!res && value) { + written = (int)ntfs_attr_pwrite(na, + (s64)0, (s64)size, value); + if (written != (s64)size) { + ntfs_log_error("Failed to " + "update efs data\n"); + errno = EIO; + res = -1; + } + } + ntfs_attr_close(na); + } else + res = -1; + } + if (!res) { + /* Don't handle AT_DATA Attribute(s) if inode is a directory */ + if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { + /* iterate over AT_DATA attributes */ + /* set encrypted flag, truncate attribute to match padding bytes */ + + ctx = ntfs_attr_get_search_ctx(ni, NULL); + if (!ctx) { + ntfs_log_error("Failed to get ctx for efs\n"); + return (-1); + } + while (!ntfs_attr_lookup(AT_DATA, NULL, 0, + CASE_SENSITIVE, 0, NULL, 0, ctx)) { + if (ntfs_efs_fixup_attribute(ctx, NULL)) { + ntfs_log_error("Error in efs fixup of AT_DATA Attribute"); + ntfs_attr_put_search_ctx(ctx); + return(-1); + } + } + ntfs_attr_put_search_ctx(ctx); + } + ni->flags |= FILE_ATTR_ENCRYPTED; + NInoSetDirty(ni); + NInoFileNameSetDirty(ni); + } + } else { + errno = EINVAL; + res = -1; + } + return (res ? -1 : 0); +} + +/* + * Fixup raw encrypted AT_DATA Attribute + * read padding length from last two bytes + * truncate attribute, make non-resident, + * set data size to match padding length + * set ATTR_IS_ENCRYPTED flag on attribute + * + * Return 0 if successful + * -1 if failed (errno tells why) + */ + +int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na) +{ + u64 newsize; + le16 appended_bytes; + u16 padding_length; + ATTR_RECORD *a; + ntfs_inode *ni; + BOOL close_na = FALSE; + BOOL close_ctx = FALSE; + + if (!ctx && !na) { + ntfs_log_error("neither ctx nor na specified for efs_fixup_attribute\n"); + goto err_out; + } + if (!ctx) { + ctx = ntfs_attr_get_search_ctx(na->ni, NULL); + if (!ctx) { + ntfs_log_error("Failed to get ctx for efs\n"); + goto err_out; + } + close_ctx=TRUE; + if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, + CASE_SENSITIVE, 0, NULL, 0, ctx)) { + ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); + goto err_out; + } + } + + a = ctx->attr; + if (!na) { + na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA, + (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), + a->name_length); + if (!na) { + ntfs_log_error("can't open DATA Attribute\n"); + return (-1); + } + close_na = TRUE; + } + /* make sure size is valid for a raw encrypted stream */ + if ((na->data_size & 511) != 2) { + ntfs_log_error("Bad raw encrypted stream"); + goto err_out; + } + /* read padding length from last two bytes of attribute */ + if (ntfs_attr_pread(na, na->data_size-2, 2, &appended_bytes) != 2) { + ntfs_log_error("Error reading padding length\n"); + goto err_out; + } + padding_length = le16_to_cpu(appended_bytes); + if (padding_length > 511 || padding_length > na->data_size-2) { + errno = EINVAL; + ntfs_log_error("invalid padding length %d for data_size %lld\n", + padding_length, (long long)na->data_size); + goto err_out; + } + newsize = na->data_size - padding_length - 2; + /* truncate attribute to possibly free clusters allocated + for the last two bytes */ + if (ntfs_attr_truncate(na, na->data_size-2)) { + ntfs_log_error("Error truncating attribute\n"); + goto err_out; + } + + /* Encrypted AT_DATA Attributes MUST be non-resident */ + if (!NAttrNonResident(na) + && ntfs_attr_make_non_resident(na, ctx)) { + ntfs_log_error("Error making DATA attribute non-resident\n"); + goto err_out; + } + ni = na->ni; + if (!na->name_len) { + ni->data_size = newsize; + ni->allocated_size = na->allocated_size; + } + NInoSetDirty(ni); + NInoFileNameSetDirty(ni); + if (close_na) + ntfs_attr_close(na); + + ctx->attr->data_size = cpu_to_le64(newsize); + if (le64_to_cpu(ctx->attr->initialized_size) > newsize) + ctx->attr->initialized_size = ctx->attr->data_size; + ctx->attr->flags |= ATTR_IS_ENCRYPTED; + if (close_ctx) + ntfs_attr_put_search_ctx(ctx); + + return (0); +err_out: + if (close_na && na) + ntfs_attr_close(na); + if (close_ctx && ctx) + ntfs_attr_put_search_ctx(ctx); + return (-1); +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/index.c b/release/src/router/ntfs-3g/libntfs-3g/index.c index acd6394c53..f78336aa78 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/index.c +++ b/release/src/router/ntfs-3g/libntfs-3g/index.c @@ -5,6 +5,7 @@ * Copyright (c) 2004-2005 Richard Russon * Copyright (c) 2005-2006 Yura Pakhuchiy * Copyright (c) 2005-2008 Szabolcs Szakacsits + * Copyright (c) 2007 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -44,6 +45,7 @@ #include "dir.h" #include "logging.h" #include "bitmap.h" +#include "reparse.h" #include "misc.h" /** @@ -556,7 +558,7 @@ static int ntfs_ie_lookup(const void *key, const int key_len, *vcn = ntfs_ie_get_vcn(ie); if (*vcn < 0) { errno = EINVAL; - ntfs_log_perror("Negative vcn in inode %llu\n", + ntfs_log_perror("Negative vcn in inode %llu", (unsigned long long)icx->ni->mft_no); return STATUS_ERROR; } @@ -1418,18 +1420,20 @@ static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib) return ret; } - -static int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) +/* JPA static */ +int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) { INDEX_HEADER *ih; int allocated_size, new_size; int ret = STATUS_ERROR; #ifdef DEBUG +/* removed by JPA to make function usable for security indexes char *fn; fn = ntfs_ie_filename_get(ie); ntfs_log_trace("file: '%s'\n", fn); ntfs_attr_name_free(&fn); +*/ #endif while (1) { @@ -1767,7 +1771,8 @@ out: * * Return 0 on success or -1 on error with errno set to the error code. */ -static int ntfs_index_rm(ntfs_index_context *icx) +/*static JPA*/ +int ntfs_index_rm(ntfs_index_context *icx) { INDEX_HEADER *ih; int err, ret = STATUS_OK; @@ -1810,12 +1815,13 @@ err_out: goto out; } -int ntfs_index_remove(ntfs_inode *ni, const void *key, const int keylen) +int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni, + const void *key, const int keylen) { int ret = STATUS_ERROR; ntfs_index_context *icx; - icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4); + icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); if (!icx) return -1; @@ -1824,8 +1830,9 @@ int ntfs_index_remove(ntfs_inode *ni, const void *key, const int keylen) if (ntfs_index_lookup(key, keylen, icx)) goto err_out; - if (((FILE_NAME_ATTR *)icx->data)->file_attributes & - FILE_ATTR_REPARSE_POINT) { + if ((((FILE_NAME_ATTR *)icx->data)->file_attributes & + FILE_ATTR_REPARSE_POINT) + && !ntfs_possible_symlink(ni)) { errno = EOPNOTSUPP; goto err_out; } @@ -1885,3 +1892,167 @@ out: } +/* + * Walk down the index tree (leaf bound) + * until there are no subnode in the first index entry + * returns the entry at the bottom left in subnode + */ + +static INDEX_ENTRY *ntfs_index_walk_down(INDEX_ENTRY *ie, + ntfs_index_context *ictx) +{ + INDEX_ENTRY *entry; + s64 vcn; + + entry = ie; + do { + vcn = ntfs_ie_get_vcn(entry); + if (ictx->is_in_root) { + + /* down from level zero */ + + ictx->ir = (INDEX_ROOT*)NULL; + ictx->ib = (INDEX_BLOCK*)ntfs_malloc(ictx->block_size); + ictx->pindex = 1; + ictx->is_in_root = FALSE; + } else { + + /* down from non-zero level */ + + ictx->pindex++; + } + ictx->parent_pos[ictx->pindex] = 0; + ictx->parent_vcn[ictx->pindex] = vcn; + if (!ntfs_ib_read(ictx,vcn,ictx->ib)) { + ictx->entry = ntfs_ie_get_first(&ictx->ib->index); + entry = ictx->entry; + } else + entry = (INDEX_ENTRY*)NULL; + } while (entry && (entry->ie_flags & INDEX_ENTRY_NODE)); + return (entry); +} + +/* + * Walk up the index tree (root bound) + * until there is a valid data entry in parent + * returns the parent entry or NULL if no more parent + */ + +static INDEX_ENTRY *ntfs_index_walk_up(INDEX_ENTRY *ie, + ntfs_index_context *ictx) +{ + INDEX_ENTRY *entry; + s64 vcn; + + entry = ie; + if (ictx->pindex > 0) { + do { + ictx->pindex--; + if (!ictx->pindex) { + + /* we have reached the root */ + + free(ictx->ib); + ictx->ib = (INDEX_BLOCK*)NULL; + ictx->is_in_root = TRUE; + /* a new search context is to be allocated */ + if (ictx->actx) + free(ictx->actx); + ictx->ir = ntfs_ir_lookup(ictx->ni, + ictx->name, ictx->name_len, + &ictx->actx); + if (ictx->ir) + entry = ntfs_ie_get_by_pos( + &ictx->ir->index, + ictx->parent_pos[ictx->pindex]); + else + entry = (INDEX_ENTRY*)NULL; + } else { + /* up into non-root node */ + vcn = ictx->parent_vcn[ictx->pindex]; + if (!ntfs_ib_read(ictx,vcn,ictx->ib)) { + entry = ntfs_ie_get_by_pos( + &ictx->ib->index, + ictx->parent_pos[ictx->pindex]); + } else + entry = (INDEX_ENTRY*)NULL; + } + ictx->entry = entry; + } while (entry && (ictx->pindex > 0) + && (entry->ie_flags & INDEX_ENTRY_END)); + } else + entry = (INDEX_ENTRY*)NULL; + return (entry); +} + +/* + * Get next entry in an index according to collating sequence. + * Must be initialized through a ntfs_index_lookup() + * + * Returns next entry or NULL if none + * + * Sample layout : + * + * +---+---+---+---+---+---+---+---+ n ptrs to subnodes + * | | | 10| 25| 33| | | | n-1 keys in between + * +---+---+---+---+---+---+---+---+ no key in last entry + * | A | A + * | | | +-------------------------------+ + * +--------------------------+ | +-----+ | + * | +--+ | | + * V | V | + * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ + * | 11| 12| 13| 14| 15| 16| 17| | | | 26| 27| 28| 29| 30| 31| 32| | + * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ + * | | + * +-----------------------+ | + * | | + * +---+---+---+---+---+---+---+---+ + * | 18| 19| 20| 21| 22| 23| 24| | + * +---+---+---+---+---+---+---+---+ + */ + +INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie, ntfs_index_context *ictx) +{ + INDEX_ENTRY *next; + int flags; + + /* + * lookup() may have returned an invalid node + * when searching for a partial key + * if this happens, walk up + */ + + if (ie->ie_flags & INDEX_ENTRY_END) + next = ntfs_index_walk_up(ie, ictx); + else { + /* + * get next entry in same node + * there is always one after any entry with data + */ + + next = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length)); + ++ictx->parent_pos[ictx->pindex]; + flags = next->ie_flags; + + /* walk down if it has a subnode */ + + if (flags & INDEX_ENTRY_NODE) { + next = ntfs_index_walk_down(next,ictx); + } else { + + /* walk up it has no subnode, nor data */ + + if (flags & INDEX_ENTRY_END) { + next = ntfs_index_walk_up(next, ictx); + } + } + } + /* return NULL if stuck at end of a block */ + + if (next && (next->ie_flags & INDEX_ENTRY_END)) + next = (INDEX_ENTRY*)NULL; + return (next); +} + + diff --git a/release/src/router/ntfs-3g/libntfs-3g/inode.c b/release/src/router/ntfs-3g/libntfs-3g/inode.c index e1c24ce83d..d1a108490b 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/inode.c +++ b/release/src/router/ntfs-3g/libntfs-3g/inode.c @@ -35,6 +35,9 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_SETXATTR +#include +#endif #include "compat.h" #include "types.h" @@ -155,6 +158,8 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) ntfs_inode *ni = NULL; ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; + le32 lthle; + int olderrno; ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref)); if (!vol) { @@ -177,7 +182,9 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) /* Receive some basic information about inode. */ if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { - ntfs_log_perror("No STANDARD_INFORMATION in base record\n"); + if (!ni->mrec->base_mft_record) + ntfs_log_perror("No STANDARD_INFORMATION in base record" + " %lld", (long long)MREF(mref)); goto put_err_out; } std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + @@ -187,12 +194,29 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time); ni->last_mft_change_time = ntfs2utc(std_info->last_mft_change_time); ni->last_access_time = ntfs2utc(std_info->last_access_time); + /* JPA insert v3 extensions if present */ + /* length may be seen as 72 (v1.x) or 96 (v3.x) */ + lthle = ctx->attr->length; + if (le32_to_cpu(lthle) > sizeof(STANDARD_INFORMATION)) { + set_nino_flag(ni, v3_Extensions); + ni->owner_id = std_info->owner_id; + ni->security_id = std_info->security_id; + ni->quota_charged = std_info->quota_charged; + ni->usn = std_info->usn; + } else { + clear_nino_flag(ni, v3_Extensions); + ni->owner_id = 0; + ni->security_id = 0; + } /* Set attribute list information. */ + olderrno = errno; if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { if (errno != ENOENT) goto put_err_out; /* Attribute list attribute does not present. */ + /* restore previous errno to avoid misinterpretation */ + errno = olderrno; goto get_size; } NInoSetAttrList(ni); @@ -201,7 +225,8 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) goto put_err_out; if (l > 0x40000) { errno = EIO; - ntfs_log_perror("Too large attrlist (%lld)\n", (long long)l); + ntfs_log_perror("Too large attrlist attribute (%lld), inode " + "%lld", (long long)l, (long long)MREF(mref)); goto put_err_out; } ni->attr_list_size = l; @@ -213,15 +238,19 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) goto put_err_out; if (l != ni->attr_list_size) { errno = EIO; - ntfs_log_perror("Unexpected attrlist size (%lld <> %u)\n", - (long long)l, ni->attr_list_size); + ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode " + "%lld", (long long)l, ni->attr_list_size, + (long long)MREF(mref)); goto put_err_out; } get_size: + olderrno = errno; if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { if (errno != ENOENT) goto put_err_out; /* Directory or special file. */ + /* restore previous errno to avoid misinterpretation */ + errno = olderrno; ni->data_size = ni->allocated_size = 0; } else { if (ctx->attr->non_resident) { @@ -514,6 +543,8 @@ static int ntfs_inode_sync_standard_information(ntfs_inode *ni) { ntfs_attr_search_ctx *ctx; STANDARD_INFORMATION *std_info; + u32 lth; + le32 lthle; ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no); @@ -530,10 +561,27 @@ static int ntfs_inode_sync_standard_information(ntfs_inode *ni) std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); std_info->file_attributes = ni->flags; - std_info->creation_time = utc2ntfs(ni->creation_time); - std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time); - std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - std_info->last_access_time = utc2ntfs(ni->last_access_time); + if (test_nino_flag(ni, TimesDirty)) { + std_info->creation_time = utc2ntfs(ni->creation_time); + std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time); + std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); + std_info->last_access_time = utc2ntfs(ni->last_access_time); + } + + /* JPA update v3.x extensions, ensuring consistency */ + + lthle = ctx->attr->length; + lth = le32_to_cpu(lthle); + if (test_nino_flag(ni, v3_Extensions) + && (lth <= sizeof(STANDARD_INFORMATION))) + ntfs_log_error("bad sync of standard information\n"); + + if (lth > sizeof(STANDARD_INFORMATION)) { + std_info->owner_id = ni->owner_id; + std_info->security_id = ni->security_id; + std_info->quota_charged = ni->quota_charged; + std_info->usn = ni->usn; + } ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_attr_put_search_ctx(ctx); return 0; @@ -616,10 +664,12 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni) (ni->flags & FILE_ATTR_VALID_FLAGS); fn->allocated_size = cpu_to_sle64(ni->allocated_size); fn->data_size = cpu_to_sle64(ni->data_size); - fn->creation_time = utc2ntfs(ni->creation_time); - fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); - fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - fn->last_access_time = utc2ntfs(ni->last_access_time); + if (test_nino_flag(ni, TimesDirty)) { + fn->creation_time = utc2ntfs(ni->creation_time); + fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); + fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); + fn->last_access_time = utc2ntfs(ni->last_access_time); + } ntfs_index_entry_mark_dirty(ictx); ntfs_index_ctx_put(ictx); if ((ni != index_ni) && ntfs_inode_close(index_ni) && !err) @@ -1098,6 +1148,7 @@ void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask) if (mask & NTFS_UPDATE_CTIME) ni->last_mft_change_time = now; + set_nino_flag(ni, TimesDirty); NInoFileNameSetDirty(ni); NInoSetDirty(ni); } @@ -1145,3 +1196,151 @@ int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr) return ret; } + +/* + * Get high precision NTFS times + * + * They are returned in following order : create, update, access, change + * provided they fit in requested size. + * + * Returns the modified size if successfull (or 32 if buffer size is null) + * -errno if failed + */ + +int ntfs_inode_get_times(const char *path __attribute__((unused)), + char *value, size_t size, ntfs_inode *ni) +{ + ntfs_attr_search_ctx *ctx; + STANDARD_INFORMATION *std_info; + u64 *times; + int ret; + + ret = 0; + ctx = ntfs_attr_get_search_ctx(ni, NULL); + if (ctx) { + if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, + 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { + ntfs_log_perror("Failed to get standard info (inode %lld)", + (long long)ni->mft_no); + } else { + std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + + le16_to_cpu(ctx->attr->value_offset)); + if (value && (size >= 8)) { + times = (u64*)value; + times[0] = le64_to_cpu(std_info->creation_time); + ret = 8; + if (size >= 16) { + times[1] = le64_to_cpu(std_info->last_data_change_time); + ret = 16; + } + if (size >= 24) { + times[2] = le64_to_cpu(std_info->last_access_time); + ret = 24; + } + if (size >= 32) { + times[3] = le64_to_cpu(std_info->last_mft_change_time); + ret = 32; + } + } else + if (!size) + ret = 32; + else + ret = -ERANGE; + } + ntfs_attr_put_search_ctx(ctx); + } + return (ret ? ret : -errno); +} + +/* + * Set high precision NTFS times + * + * They are expected in this order : create, update, access + * provided they are present in input. The change time is set to + * current time. + * + * The times are inserted directly in the standard_information and + * file names attributes to avoid manipulating low precision times + * + * Returns 0 if success + * -1 if there were an error (described by errno) + */ + +int ntfs_inode_set_times(const char *path __attribute__((unused)), + const char *value, size_t size, + int flags, ntfs_inode *ni) +{ + ntfs_attr_search_ctx *ctx; + STANDARD_INFORMATION *std_info; + FILE_NAME_ATTR *fn; + const u64 *times; + le64 now; + int cnt; + int ret; + + ret = -1; + if ((size >= 8) && !(flags & XATTR_CREATE)) { + times = (const u64*)value; + now = utc2ntfs(time((time_t*)NULL)); + /* update the standard information attribute */ + ctx = ntfs_attr_get_search_ctx(ni, NULL); + if (ctx) { + if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, + AT_UNNAMED, 0, CASE_SENSITIVE, + 0, NULL, 0, ctx)) { + ntfs_log_perror("Failed to get standard info (inode %lld)", + (long long)ni->mft_no); + } else { + std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + + le16_to_cpu(ctx->attr->value_offset)); + /* + * Do not mark times dirty to avoid + * overwriting them when the inode is closed. + */ + std_info->creation_time = cpu_to_le64(times[0]); + if (size >= 16) + std_info->last_data_change_time = cpu_to_le64(times[1]); + if (size >= 24) + std_info->last_access_time = cpu_to_le64(times[2]); + std_info->last_mft_change_time = now; + ntfs_inode_mark_dirty(ctx->ntfs_ino); + + /* update the file names attributes */ + ntfs_attr_reinit_search_ctx(ctx); + cnt = 0; + while (!ntfs_attr_lookup(AT_FILE_NAME, + AT_UNNAMED, 0, CASE_SENSITIVE, + 0, NULL, 0, ctx)) { + fn = (FILE_NAME_ATTR*)((u8 *)ctx->attr + + le16_to_cpu(ctx->attr->value_offset)); + /* + * Do not mark times dirty to avoid + * overwriting them when the inode is closed. + */ + fn->creation_time + = cpu_to_le64(times[0]); + if (size >= 16) + fn->last_data_change_time + = cpu_to_le64(times[1]); + if (size >= 24) + fn->last_access_time + = cpu_to_le64(times[2]); + fn->last_mft_change_time = now; + cnt++; + } + if (cnt) + ret = 0; + else { + ntfs_log_perror("Failed to get file names (inode %lld)", + (long long)ni->mft_no); + } + } + ntfs_attr_put_search_ctx(ctx); + } + } else + if (size < 8) + errno = ERANGE; + else + errno = EEXIST; + return (ret); +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/lcnalloc.c b/release/src/router/ntfs-3g/libntfs-3g/lcnalloc.c index 3a8d5ed79f..ae67843081 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/lcnalloc.c +++ b/release/src/router/ntfs-3g/libntfs-3g/lcnalloc.c @@ -4,6 +4,7 @@ * Copyright (c) 2002-2004 Anton Altaparmakov * Copyright (c) 2004 Yura Pakhuchiy * Copyright (c) 2004-2008 Szabolcs Szakacsits + * Copyright (c) 2008-2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -54,6 +55,12 @@ #define NTFS_LCNALLOC_BSIZE 4096 #define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE +enum { + ZONE_MFT = 1, + ZONE_DATA1 = 2, + ZONE_DATA2 = 4 +} ; + static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc) { ntfs_log_trace("pos: %lld tc: %lld\n", (long long)*pos, (long long)tc); @@ -68,17 +75,44 @@ static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc) { ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone); - if (zone == 1) + if (zone == ZONE_MFT) ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end, &vol->mft_zone_pos, tc); - else if (zone == 2) + else if (zone == ZONE_DATA1) ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters, &vol->data1_zone_pos, tc); - else /* zone == 4 */ + else /* zone == ZONE_DATA2 */ ntfs_cluster_set_zone_pos(0, vol->mft_zone_start, &vol->data2_zone_pos, tc); } +/* + * Unmark full zones when a cluster has been freed in a full zone + * + * Next allocation will reuse the freed cluster + */ + +static void update_full_status(ntfs_volume *vol, LCN lcn) +{ + if (lcn >= vol->mft_zone_end) { + if (vol->full_zones & ZONE_DATA1) { + ntfs_cluster_update_zone_pos(vol, ZONE_DATA1, lcn); + vol->full_zones &= ~ZONE_DATA1; + } + } else + if (lcn < vol->mft_zone_start) { + if (vol->full_zones & ZONE_DATA2) { + ntfs_cluster_update_zone_pos(vol, ZONE_DATA2, lcn); + vol->full_zones &= ~ZONE_DATA2; + } + } else { + if (vol->full_zones & ZONE_MFT) { + ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn); + vol->full_zones &= ~ZONE_MFT; + } + } +} + static s64 max_empty_bit_range(unsigned char *buf, int size) { int i, j, run = 0; @@ -87,30 +121,49 @@ static s64 max_empty_bit_range(unsigned char *buf, int size) ntfs_log_trace("Entering\n"); - for (i = 0; i < size; i++, buf++) { - - if (*buf == 0) { - run += 8; - continue; - } - - for (j = 0; j < 8; j++) { + i = 0; + while (i < size) { + switch (*buf) { + case 0 : + do { + buf++; + run += 8; + i++; + } while ((i < size) && !*buf); + break; + case 255 : + if (run > max_range) { + max_range = run; + start_pos = (s64)i * 8 - run; + } + run = 0; + do { + buf++; + i++; + } while ((i < size) && (*buf == 255)); + break; + default : + for (j = 0; j < 8; j++) { - int bit = *buf & (1 << j); + int bit = *buf & (1 << j); - if (bit) { - if (run > max_range) { - max_range = run; - start_pos = i * 8 + j - run; - } - run = 0; - } else - run++; - } + if (bit) { + if (run > max_range) { + max_range = run; + start_pos = (s64)i * 8 + (j - run); + } + run = 0; + } else + run++; + } + i++; + buf++; + + } } if (run > max_range) - start_pos = i * 8 - run; + start_pos = (s64)i * 8 - run; return start_pos; } @@ -245,13 +298,13 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, if (zone_start < vol->mft_zone_start) { zone_end = vol->mft_zone_start; - search_zone = 4; + search_zone = ZONE_DATA2; } else if (zone_start < vol->mft_zone_end) { zone_end = vol->mft_zone_end; - search_zone = 1; + search_zone = ZONE_MFT; } else { zone_end = vol->nr_clusters; - search_zone = 2; + search_zone = ZONE_DATA1; } bmp_pos = zone_start; @@ -260,6 +313,9 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, clusters = count; rlpos = rlsize = 0; while (1) { + /* check whether we have exhausted the current zone */ + if (search_zone & vol->full_zones) + goto zone_pass_done; last_read_pos = bmp_pos >> 3; br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, NTFS_LCNALLOC_BSIZE, buf); @@ -371,9 +427,9 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, used_zone_pos = 1; - if (search_zone == 1) + if (search_zone == ZONE_MFT) zone_start = vol->mft_zone_pos; - else if (search_zone == 2) + else if (search_zone == ZONE_DATA1) zone_start = vol->data1_zone_pos; else zone_start = vol->data2_zone_pos; @@ -391,13 +447,12 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, zone_pass_done: ntfs_log_trace("Finished current zone pass(%i).\n", pass); if (pass == 1) { - pass = 2; zone_end = zone_start; - if (search_zone == 1) + if (search_zone == ZONE_MFT) zone_start = vol->mft_zone_start; - else if (search_zone == 2) + else if (search_zone == ZONE_DATA1) zone_start = vol->mft_zone_end; else zone_start = 0; @@ -413,7 +468,8 @@ zone_pass_done: /* pass == 2 */ done_zones_check: done_zones |= search_zone; - if (done_zones < 7) { + vol->full_zones |= search_zone; + if (done_zones < (ZONE_MFT + ZONE_DATA1 + ZONE_DATA2)) { ntfs_log_trace("Switching zone.\n"); pass = 1; if (rlpos) { @@ -426,29 +482,29 @@ done_zones_check: } switch (search_zone) { - case 1: + case ZONE_MFT: ntfs_log_trace("Zone switch: mft -> data1\n"); -switch_to_data1_zone: search_zone = 2; +switch_to_data1_zone: search_zone = ZONE_DATA1; zone_start = vol->data1_zone_pos; zone_end = vol->nr_clusters; if (zone_start == vol->mft_zone_end) pass = 2; break; - case 2: + case ZONE_DATA1: ntfs_log_trace("Zone switch: data1 -> data2\n"); - search_zone = 4; + search_zone = ZONE_DATA2; zone_start = vol->data2_zone_pos; zone_end = vol->mft_zone_start; if (!zone_start) pass = 2; break; - case 4: - if (!(done_zones & 2)) { + case ZONE_DATA2: + if (!(done_zones & ZONE_DATA1)) { ntfs_log_trace("data2 -> data1\n"); goto switch_to_data1_zone; } ntfs_log_trace("Zone switch: data2 -> mft\n"); - search_zone = 1; + search_zone = ZONE_MFT; zone_start = vol->mft_zone_pos; zone_end = vol->mft_zone_end; if (zone_start == vol->mft_zone_start) @@ -530,6 +586,7 @@ int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl) (long long)rl->lcn, (long long)rl->length); if (rl->lcn >= 0) { + update_full_status(vol,rl->lcn); if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, rl->length)) { ntfs_log_perror("Cluster deallocation failed " @@ -609,6 +666,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) if (rl->lcn != LCN_HOLE) { /* Do the actual freeing of the clusters in this run. */ + update_full_status(vol,rl->lcn + delta); if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta, to_free)) goto leave; @@ -641,6 +699,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) to_free = count; if (rl->lcn != LCN_HOLE) { + update_full_status(vol,rl->lcn); if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, to_free)) { // FIXME: Eeek! We need rollback! (AIA) diff --git a/release/src/router/ntfs-3g/libntfs-3g/mft.c b/release/src/router/ntfs-3g/libntfs-3g/mft.c index dc47f61f76..09aaaee9f9 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/mft.c +++ b/release/src/router/ntfs-3g/libntfs-3g/mft.c @@ -718,7 +718,7 @@ static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol) goto undo_alloc; } /* Get the size for the new mapping pairs array for this extent. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); + mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX); if (mp_size <= 0) { ntfs_log_error("Get size for mapping pairs failed for " "mft bitmap attribute extent.\n"); @@ -1067,7 +1067,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) goto undo_alloc; } /* Get the size for the new mapping pairs array for this extent. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); + mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll, INT_MAX); if (mp_size <= 0) { ntfs_log_error("Get size for mapping pairs failed for " "mft data attribute extent.\n"); @@ -1359,7 +1359,7 @@ static ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol) ntfs_inode *ni = NULL; ntfs_inode *base_ni; int err; - u16 seq_no, usn; + le16 seq_no, usn; ntfs_log_enter("Entering\n"); @@ -1413,17 +1413,17 @@ found_free_rec: } seq_no = m->sequence_number; - usn = *(u16*)((u8*)m + le16_to_cpu(m->usa_ofs)); + usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); if (ntfs_mft_record_layout(vol, bit, m)) { ntfs_log_error("Failed to re-format mft record.\n"); free(m); goto undo_mftbmp_alloc; } - if (le16_to_cpu(seq_no)) + if (seq_no) m->sequence_number = seq_no; - seq_no = le16_to_cpu(usn); - if (seq_no && seq_no != 0xffff) - *(u16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn; + seq_no = usn; + if (seq_no && seq_no != const_cpu_to_le16(0xffff)) + *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn; /* Set the mft record itself in use. */ m->flags |= MFT_RECORD_IN_USE; /* Now need to open an ntfs inode for the mft record. */ @@ -1476,6 +1476,7 @@ found_free_rec: ni->creation_time = ni->last_data_change_time = ni->last_mft_change_time = ni->last_access_time = time(NULL); + set_nino_flag(ni, TimesDirty); /* Update the default mft allocation position if it was used. */ if (!base_ni) vol->mft_data_pos = bit + 1; @@ -1588,7 +1589,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni) MFT_RECORD *m; ntfs_inode *ni = NULL; int err; - u16 seq_no, usn; + le16 seq_no, usn; if (base_ni) ntfs_log_enter("Entering (allocating an extent mft record for " @@ -1714,17 +1715,17 @@ found_free_rec: goto retry; } seq_no = m->sequence_number; - usn = *(u16*)((u8*)m + le16_to_cpu(m->usa_ofs)); + usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); if (ntfs_mft_record_layout(vol, bit, m)) { ntfs_log_error("Failed to re-format mft record.\n"); free(m); goto undo_mftbmp_alloc; } - if (le16_to_cpu(seq_no)) + if (seq_no) m->sequence_number = seq_no; - seq_no = le16_to_cpu(usn); - if (seq_no && seq_no != 0xffff) - *(u16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn; + seq_no = usn; + if (seq_no && seq_no != const_cpu_to_le16(0xffff)) + *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn; /* Set the mft record itself in use. */ m->flags |= MFT_RECORD_IN_USE; /* Now need to open an ntfs inode for the mft record. */ @@ -1778,6 +1779,7 @@ found_free_rec: ni->creation_time = ni->last_data_change_time = ni->last_mft_change_time = ni->last_access_time = time(NULL); + set_nino_flag(ni, TimesDirty); /* Update the default mft allocation position if it was used. */ if (!base_ni) vol->mft_data_pos = bit + 1; @@ -1816,7 +1818,8 @@ int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni) { u64 mft_no; int err; - u16 seq_no, old_seq_no; + u16 seq_no; + le16 old_seq_no; ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); @@ -1883,13 +1886,14 @@ sync_rollback: */ int ntfs_mft_usn_dec(MFT_RECORD *mrec) { - u16 usn, *usnp; + u16 usn; + le16 *usnp; if (!mrec) { errno = EINVAL; return -1; } - usnp = (u16 *)((char *)mrec + le16_to_cpu(mrec->usa_ofs)); + usnp = (le16*)((char*)mrec + le16_to_cpu(mrec->usa_ofs)); usn = le16_to_cpup(usnp); if (usn-- <= 1) usn = 0xfffe; diff --git a/release/src/router/ntfs-3g/libntfs-3g/misc.c b/release/src/router/ntfs-3g/libntfs-3g/misc.c index 9e38347e47..8e662a6a8c 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/misc.c +++ b/release/src/router/ntfs-3g/libntfs-3g/misc.c @@ -1,3 +1,26 @@ +/** + * misc.c : miscellaneous : + * - dealing with errors in memory allocation + * - data caching + * + * Copyright (c) 2008 Jean-Pierre Andre + * + * This program/include file 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/include file 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -5,7 +28,12 @@ #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_STRING_H +#include +#endif +#include "types.h" +#include "security.h" #include "misc.h" #include "logging.h" @@ -34,3 +62,303 @@ void *ntfs_malloc(size_t size) return p; } +/* + * General functions to deal with LRU caches + * + * The cached data have to be organized in a structure in which + * the first fields must follow a mandatory pattern and further + * fields may contain any fixed size data. They are stored in an + * LRU list. + * + * A compare function must be provided for finding a wanted entry + * in the cache. Another function may be provided for invalidating + * an entry to facilitate multiple invalidation. + * + * These functions never return error codes. When there is a + * shortage of memory, data is simply not cached. + */ + +/* + * Fetch an entry from cache + * + * returns the cache entry, or NULL if not available + */ + +struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *wanted, cache_compare compare) +{ + struct CACHED_GENERIC *current; + struct CACHED_GENERIC *previous; + + current = (struct CACHED_GENERIC*)NULL; + if (cache) { + /* + * Search sequentially in LRU list + */ + current = cache->most_recent_entry; + previous = (struct CACHED_GENERIC*)NULL; + while (current + && compare(current, wanted)) { + previous = current; + current = current->next; + } + if (current) + cache->hits++; + if (current && previous) { + /* + * found and not at head of list, unlink from current + * position and relink as head of list + */ + previous->next = current->next; + current->next = cache->most_recent_entry; + cache->most_recent_entry = current; + } + cache->reads++; + } + return (current); +} + +/* + * Enter an inode number into cache + * returns the cache entry or NULL if not possible + */ + +struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *item, cache_compare compare) +{ + struct CACHED_GENERIC *current; + struct CACHED_GENERIC *previous; + struct CACHED_GENERIC *before; + + current = (struct CACHED_GENERIC*)NULL; + if (cache) { + + /* + * Search sequentially in LRU list to locate the end, + * and find out whether the entry is already in list + * As we normally go to the end, no statistics is + * kept. + */ + current = cache->most_recent_entry; + previous = (struct CACHED_GENERIC*)NULL; + before = (struct CACHED_GENERIC*)NULL; + while (current + && compare(current, item)) { + before = previous; + previous = current; + current = current->next; + } + + if (!current) { + /* + * Not in list, get a free entry or reuse the + * last entry, and relink as head of list + * Note : we assume at least three entries, so + * before, previous and first are different when + * an entry is reused. + */ + + if (cache->free_entry) { + current = cache->free_entry; + cache->free_entry = cache->free_entry->next; + if (item->varsize) { + current->variable = ntfs_malloc( + item->varsize); + } else + current->variable = (void*)NULL; + current->varsize = item->varsize; + } else { + before->next = (struct CACHED_GENERIC*)NULL; + current = previous; + if (item->varsize) { + if (current->varsize) + current->variable = realloc( + current->variable, + item->varsize); + else + current->variable = ntfs_malloc( + item->varsize); + } else { + if (current->varsize) + free(current->variable); + current->variable = (void*)NULL; + } + current->varsize = item->varsize; + } + current->next = cache->most_recent_entry; + cache->most_recent_entry = current; + memcpy(current->fixed, item->fixed, cache->fixed_size); + if (item->varsize) { + if (current->variable) { + memcpy(current->variable, + item->variable, item->varsize); + } else { + /* + * no more memory for variable part + * recycle entry in free list + * not an error, just uncacheable + */ + cache->most_recent_entry = current->next; + current->next = cache->free_entry; + cache->free_entry = current; + current = (struct CACHED_GENERIC*)NULL; + } + } else { + current->variable = (void*)NULL; + current->varsize = 0; + } + } + cache->writes++; + } + return (current); +} + +/* + * Invalidate entries in cache + * + * Several entries may have to be invalidated (at least for inodes + * associated to directories which have been renamed), a different + * compare function may be provided to select entries to invalidate + * + * Returns the number of deleted entries, this can be used by + * the caller to signal a cache corruption if the entry was + * supposed to be found. + */ + +int ntfs_invalidate_cache(struct CACHE_HEADER *cache, + const struct CACHED_GENERIC *item, cache_compare compare) +{ + struct CACHED_GENERIC *current; + struct CACHED_GENERIC *previous; + int count; + + current = (struct CACHED_GENERIC*)NULL; + count = 0; + if (cache) { + /* + * Search sequentially in LRU list + */ + current = cache->most_recent_entry; + previous = (struct CACHED_GENERIC*)NULL; + while (current) { + if (!compare(current, item)) { + /* + * Relink into free list + */ + if (previous) + previous->next = current->next; + else + cache->most_recent_entry = current->next; + current->next = cache->free_entry; + cache->free_entry = current; + if (current->variable) + free(current->variable); + current->varsize = 0; + if (previous) + current = previous->next; + else + current = cache->most_recent_entry; + count++; + } else { + previous = current; + current = current->next; + } + } + } + return (count); +} + +/* + * Free memory allocated to a cache + */ + +static void ntfs_free_cache(struct CACHE_HEADER *cache) +{ + struct CACHED_GENERIC *entry; + + if (cache) { + for (entry=cache->most_recent_entry; entry; entry=entry->next) + if (entry->variable) + free(entry->variable); + free(cache); + } +} + +/* + * Create a cache + * + * Returns the cache header, or NULL if the cache could not be created + */ + +static struct CACHE_HEADER *ntfs_create_cache(const char *name, + int full_item_size, int item_count) +{ + struct CACHE_HEADER *cache; + struct CACHED_GENERIC *p; + struct CACHED_GENERIC *q; + int i; + + cache = (struct CACHE_HEADER*) + ntfs_malloc(sizeof(struct CACHE_HEADER) + + item_count*full_item_size); + if (cache) { + cache->name = name; + cache->fixed_size = full_item_size - sizeof(struct CACHED_GENERIC); + cache->reads = 0; + cache->writes = 0; + cache->hits = 0; + /* chain the entries, and mark an invalid entry */ + cache->most_recent_entry = (struct CACHED_GENERIC*)NULL; + cache->free_entry = &cache->entry[0]; + p = &cache->entry[0]; + for (i=0; i<(item_count - 1); i++) { + q = (struct CACHED_GENERIC*)((char*)p + full_item_size); + p->next = q; + p->variable = (void*)NULL; + p->varsize = 0; + p = q; + } + /* special for the last entry */ + p->next = (struct CACHED_GENERIC*)NULL; + p->variable = (void*)NULL; + p->varsize = 0; + } + return (cache); +} + +/* + * Create all LRU caches + * + * No error return, if creation is not possible, cacheing will + * just be not available + */ + +void ntfs_create_lru_caches(ntfs_volume *vol) +{ +#if CACHE_INODE_SIZE + /* inode cache */ + vol->xinode_cache = ntfs_create_cache("inode", + sizeof(struct CACHED_INODE), CACHE_INODE_SIZE); +#endif + vol->securid_cache = ntfs_create_cache("securid", + sizeof(struct CACHED_SECURID), CACHE_SECURID_SIZE); +#if CACHE_LEGACY_SIZE + vol->legacy_cache = ntfs_create_cache("legacy", + sizeof(struct CACHED_PERMISSIONS_LEGACY), CACHE_LEGACY_SIZE); +#endif +} + +/* + * Free all LRU caches + */ + +void ntfs_free_lru_caches(ntfs_volume *vol) +{ +#if CACHE_INODE_SIZE + ntfs_free_cache(vol->xinode_cache); +#endif + ntfs_free_cache(vol->securid_cache); +#if CACHE_LEGACY_SIZE + ntfs_free_cache(vol->legacy_cache); +#endif +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/reparse.c b/release/src/router/ntfs-3g/libntfs-3g/reparse.c new file mode 100644 index 0000000000..2093443674 --- /dev/null +++ b/release/src/router/ntfs-3g/libntfs-3g/reparse.c @@ -0,0 +1,1296 @@ +/** + * reparse.c - Processing of reparse points + * + * This module is part of ntfs-3g library, but may also be + * integrated in tools running over Linux or Windows + * + * Copyright (c) 2008-2009 Jean-Pierre Andre + * + * This program/include file 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/include file 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SETXATTR +#include +#endif + +#ifdef HAVE_SYS_SYSMACROS_H +#include +#endif + +#include "types.h" +#include "debug.h" +#include "attrib.h" +#include "inode.h" +#include "dir.h" +#include "volume.h" +#include "mft.h" +#include "index.h" +#include "lcnalloc.h" +#include "logging.h" +#include "misc.h" +#include "reparse.h" + +/* the definitions in layout.h are wrong, we use names defined in + http://msdn.microsoft.com/en-us/library/aa365740(VS.85).aspx +*/ + +#define IO_REPARSE_TAG_DFS const_cpu_to_le32(0x8000000A) +#define IO_REPARSE_TAG_DFSR const_cpu_to_le32(0x80000012) +#define IO_REPARSE_TAG_HSM const_cpu_to_le32(0xC0000004) +#define IO_REPARSE_TAG_HSM2 const_cpu_to_le32(0x80000006) +#define IO_REPARSE_TAG_MOUNT_POINT const_cpu_to_le32(0xA0000003) +#define IO_REPARSE_TAG_SIS const_cpu_to_le32(0x80000007) +#define IO_REPARSE_TAG_SYMLINK const_cpu_to_le32(0xA000000C) + +struct MOUNT_POINT_REPARSE_DATA { /* reparse data for junctions */ + le16 subst_name_offset; + le16 subst_name_length; + le16 print_name_offset; + le16 print_name_length; + char path_buffer[0]; /* above data assume this is char array */ +} ; + +struct SYMLINK_REPARSE_DATA { /* reparse data for symlinks */ + le16 subst_name_offset; + le16 subst_name_length; + le16 print_name_offset; + le16 print_name_length; + le32 flags; /* 1 for full target, otherwise 0 */ + char path_buffer[0]; /* above data assume this is char array */ +} ; + +struct INODE_STACK { + struct INODE_STACK *previous; + struct INODE_STACK *next; + ntfs_inode *ni; +} ; + +struct REPARSE_INDEX { /* index entry in $Extend/$Reparse */ + INDEX_ENTRY_HEADER header; + REPARSE_INDEX_KEY key; + le32 filling; +} ; + +static const ntfschar dir_junction_head[] = { + const_cpu_to_le16('\\'), + const_cpu_to_le16('?'), + const_cpu_to_le16('?'), + const_cpu_to_le16('\\') +} ; + +static const ntfschar vol_junction_head[] = { + const_cpu_to_le16('\\'), + const_cpu_to_le16('?'), + const_cpu_to_le16('?'), + const_cpu_to_le16('\\'), + const_cpu_to_le16('V'), + const_cpu_to_le16('o'), + const_cpu_to_le16('l'), + const_cpu_to_le16('u'), + const_cpu_to_le16('m'), + const_cpu_to_le16('e'), + const_cpu_to_le16('{'), +} ; + +static ntfschar reparse_index_name[] = { const_cpu_to_le16('$'), + const_cpu_to_le16('R') }; + +static const char mappingdir[] = ".NTFS-3G/"; + +/* + * Fix a file name with doubtful case in some directory index + * and return the name with the casing used in directory. + * + * Should only be used to translate paths stored with case insensitivity + * (such as directory junctions) when no case conflict is expected. + * If there some ambiguity, the name which collates first is returned. + * + * The name is converted to upper case and searched the usual way. + * The collation rules for file names are such that we should get the + * first candidate if any. + */ + +static u64 ntfs_fix_file_name(ntfs_inode *dir_ni, ntfschar *uname, + int uname_len) +{ + ntfs_volume *vol = dir_ni->vol; + ntfs_index_context *icx; + u64 mref; + le64 lemref; + int lkup; + int olderrno; + int i; + u32 cpuchar; + INDEX_ENTRY *entry; + FILE_NAME_ATTR *found; + struct { + FILE_NAME_ATTR attr; + ntfschar file_name[NTFS_MAX_NAME_LEN + 1]; + } find; + + mref = (u64)-1; /* default return (not found) */ + icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); + if (icx) { + if (uname_len > NTFS_MAX_NAME_LEN) + uname_len = NTFS_MAX_NAME_LEN; + find.attr.file_name_length = uname_len; + for (i=0; iupcase_len) + && (le16_to_cpu(vol->upcase[cpuchar]) < cpuchar)) + find.attr.file_name[i] = vol->upcase[cpuchar]; + else + find.attr.file_name[i] = uname[i]; + } + olderrno = errno; + lkup = ntfs_index_lookup((char*)&find, uname_len, icx); + if (errno == ENOENT) + errno = olderrno; + /* + * We generally only get the first matching candidate, + * so we still have to check whether this is a real match + */ + if (icx->entry && (icx->entry->ie_flags & INDEX_ENTRY_END)) + /* get next entry if reaching end of block */ + entry = ntfs_index_next(icx->entry, icx); + else + entry = icx->entry; + if (entry) { + found = &entry->key.file_name; + if (lkup + && !ntfs_names_collate(find.attr.file_name, + find.attr.file_name_length, + found->file_name, found->file_name_length, + 1, IGNORE_CASE, + vol->upcase, vol->upcase_len)) + lkup = 0; + if (!lkup) { + /* + * name found : + * fix original name and return inode + */ + lemref = *(le64*)((char*)found->file_name + - sizeof(INDEX_ENTRY_HEADER) + - sizeof(FILE_NAME_ATTR)); + mref = le64_to_cpu(lemref); + for (i=0; ifile_name_length; i++) + uname[i] = found->file_name[i]; + } + } + ntfs_index_ctx_put(icx); + } + return (mref); +} + +/* + * Search for a directory junction or a symbolic link + * along the target path, with target defined as a full absolute path + * + * Returns the path translated to a Linux path + * or NULL if the path is not valid + */ + +static char *search_absolute(ntfs_volume *vol, ntfschar *path, + int count, BOOL isdir) +{ + ntfs_inode *ni; + u64 inum; + char *target; + int start; + int len; + + target = (char*)NULL; /* default return */ + ni = ntfs_inode_open(vol, (MFT_REF)FILE_root); + if (ni) { + start = 0; + do { + len = 0; + while (((start + len) < count) + && (path[start + len] != const_cpu_to_le16('\\'))) + len++; + inum = ntfs_fix_file_name(ni, &path[start], len); + ntfs_inode_close(ni); + ni = (ntfs_inode*)NULL; + if (inum != (u64)-1) { + inum = MREF(inum); + ni = ntfs_inode_open(vol, inum); + start += len; + if (start < count) + path[start++] = const_cpu_to_le16('/'); + } + } while (ni + && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + && (start < count)); + if (ni + && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)) + if (ntfs_ucstombs(path, count, &target, 0) < 0) { + if (target) { + free(target); + target = (char*)NULL; + } + } + if (ni) + ntfs_inode_close(ni); + } + return (target); +} + +/* + * Stack the next inode in the path + * + * Returns the new top of stack + * or NULL (with stack unchanged) if there is a problem + */ + +static struct INODE_STACK *stack_inode(struct INODE_STACK *topni, + ntfschar *name, int len, BOOL fix) +{ + struct INODE_STACK *curni; + u64 inum; + + if (fix) + inum = ntfs_fix_file_name(topni->ni, name, len); + else + inum = ntfs_inode_lookup_by_name(topni->ni, name, len); + if (inum != (u64)-1) { + inum = MREF(inum); + curni = (struct INODE_STACK*)malloc(sizeof(struct INODE_STACK)); + if (curni) { + curni->ni = ntfs_inode_open(topni->ni->vol, inum); + topni->next = curni; + curni->previous = topni; + curni->next = (struct INODE_STACK*)NULL; + } + } else + curni = (struct INODE_STACK*)NULL; + return (curni); +} + +/* + * Destack and close the current inode in the path + * + * Returns the new top of stack + * or NULL (with stack unchanged) if there is a problem + */ + +static struct INODE_STACK *pop_inode(struct INODE_STACK *topni) +{ + struct INODE_STACK *curni; + + curni = (struct INODE_STACK*)NULL; + if (topni->previous) { + if (!ntfs_inode_close(topni->ni)) { + curni = topni->previous; + free(topni); + curni->next = (struct INODE_STACK*)NULL; + } + } else { + /* ".." reached the root of fs */ + errno = ENOENT; + } + return (curni); +} + +/* + * Search for a symbolic link along the target path, + * with the target defined as a relative path + * + * Returns the path translated to a Linux path + * or NULL if the path is not valid + */ + +static char *search_relative(ntfs_volume *vol, ntfschar *path, int count, + const char *base, BOOL isdir) +{ + struct INODE_STACK *topni; + struct INODE_STACK *curni; + char *target; + ntfschar *unicode; + int unisz; + int start; + int len; + + target = (char*)NULL; /* default return */ + topni = (struct INODE_STACK*)malloc(sizeof(struct INODE_STACK)); + if (topni) { + topni->ni = ntfs_inode_open(vol, FILE_root); + topni->previous = (struct INODE_STACK*)NULL; + topni->next = (struct INODE_STACK*)NULL; + } + if (topni && topni->ni) { + /* + * Process the base path + */ + unicode = (ntfschar*)NULL; + unisz = ntfs_mbstoucs(base, &unicode); + if ((unisz > 0) && unicode) { + start = 1; + do { + len = 0; + while (((start + len) < unisz) + && (unicode[start + len] + != const_cpu_to_le16('/'))) + len++; + curni = (struct INODE_STACK*)NULL; + if ((start + len) < unisz) { + curni = stack_inode(topni, + &unicode[start], len, FALSE); + if (curni) + topni = curni; + } else + curni = topni; + start += len + 1; + } while (curni + && topni->ni + && (topni->ni->mrec->flags + & MFT_RECORD_IS_DIRECTORY) + && (start < unisz)); + free(unicode); + if (curni + && topni->ni + && (topni->ni->mrec->flags + & MFT_RECORD_IS_DIRECTORY)) { + start = 0; + do { + len = 0; + while (((start + len) < count) + && (path[start + len] + != const_cpu_to_le16('\\'))) + len++; + curni = (struct INODE_STACK*)NULL; + if ((path[start] + == const_cpu_to_le16('.')) + && ((len == 1) + || ((len == 2) + && (path[start+1] + == const_cpu_to_le16('.'))))) { + /* leave the .. or . in the path */ + curni = topni; + if (len == 2) { + curni = pop_inode(topni); + if (curni) + topni = curni; + } + } else { + curni = stack_inode(topni, + &path[start], len, TRUE); + if (curni) + topni = curni; + } + if (topni->ni) { + start += len; + if (start < count) + path[start++] + = const_cpu_to_le16('/'); + } + } while (curni + && topni->ni + && (topni->ni->mrec->flags + & MFT_RECORD_IS_DIRECTORY) + && (start < count)); + if (curni + && topni->ni + && (topni->ni->mrec->flags + & MFT_RECORD_IS_DIRECTORY + ? isdir : !isdir)) { + if (ntfs_ucstombs(path, count, + &target, 0) < 0) { + if (target) { + free(target); + target = (char*)NULL; + } + } + } + } + } + do { + if (topni->ni) + ntfs_inode_close(topni->ni); + curni = topni; + topni = topni->previous; + free(curni); + } while (topni); + } + return (target); +} + +/* + * Check whether a drive letter has been defined in .NTFS-3G + * + * Returns 1 if found, + * 0 if not found, + * -1 if there was an error (described by errno) + */ + +static int ntfs_drive_letter(ntfs_volume *vol, ntfschar letter) +{ + char defines[NTFS_MAX_NAME_LEN + 5]; + char *drive; + int ret; + int sz; + int olderrno; + ntfs_inode *ni; + + ret = -1; + drive = (char*)NULL; + sz = ntfs_ucstombs(&letter, 1, &drive, 0); + if (sz > 0) { + strcpy(defines,mappingdir); + if ((*drive >= 'a') && (*drive <= 'z')) + *drive += 'A' - 'a'; + strcat(defines,drive); + strcat(defines,":"); + olderrno = errno; + ni = ntfs_pathname_to_inode(vol, NULL, defines); + if (ni && !ntfs_inode_close(ni)) + ret = 1; + else + if (errno == ENOENT) { + ret = 0; + /* avoid errno pollution */ + errno = olderrno; + } + } + if (drive) + free(drive); + return (ret); +} + +/* + * Check and translate the target of a junction point or + * a full absolute symbolic link. + * + * A full target definition begins with "\??\" or "\\?\" + * + * The fully defined target is redefined as a relative link, + * - either to the target if found on the same device. + * - or into the /.NTFS-3G directory for the user to define + * In the first situation, the target is translated to case-sensitive path. + * + * returns the target converted to a relative symlink + * or NULL if there were some problem, as described by errno + */ + + +static char *ntfs_get_fulllink(ntfs_volume *vol, ntfschar *junction, + int count, const char *path, BOOL isdir) +{ + char *target; + char *fulltarget; + int i; + int sz; + int level; + const char *p; + char *q; + enum { DIR_JUNCTION, VOL_JUNCTION, NO_JUNCTION } kind; + + target = (char*)NULL; + fulltarget = (char*)NULL; + /* + * For a valid directory junction we want \??\x:\ + * where \ is an individual char and x a non-null char + */ + if ((count >= 7) + && !memcmp(junction,dir_junction_head,8) + && junction[4] + && (junction[5] == const_cpu_to_le16(':')) + && (junction[6] == const_cpu_to_le16('\\'))) + kind = DIR_JUNCTION; + else + /* + * For a valid volume junction we want \\?\Volume{ + * and a final \ (where \ is an individual char) + */ + if ((count >= 12) + && !memcmp(junction,vol_junction_head,22) + && (junction[count-1] == const_cpu_to_le16('\\'))) + kind = VOL_JUNCTION; + else + kind = NO_JUNCTION; + /* + * Directory junction with an explicit path and + * no specific definition for the drive letter : + * try to interpret as a target on the same volume + */ + if ((kind == DIR_JUNCTION) + && (count >= 7) + && junction[7] + && !ntfs_drive_letter(vol, junction[4])) { + target = search_absolute(vol,&junction[7],count - 7, isdir); + if (target) { + level = 0; + for (p=path; *p; p++) + if (*p == '/') + level++; + fulltarget = (char*)ntfs_malloc(3*level + + strlen(target) + 1); + if (fulltarget) { + fulltarget[0] = 0; + if (level > 1) { + for (i=1; i 0) && target) { + /* reverse slashes */ + for (q=target; *q; q++) + if (*q == '\\') + *q = '/'; + /* force uppercase drive letter */ + if ((target[1] == ':') + && (target[0] >= 'a') + && (target[0] <= 'z')) + target[0] += 'A' - 'a'; + level = 0; + for (p=path; *p; p++) + if (*p == '/') + level++; + fulltarget = (char*)ntfs_malloc(3*level + + sizeof(mappingdir) + count - 4); + if (fulltarget) { + fulltarget[0] = 0; + if (level > 1) { + for (i=1; i= 3) + && junction[0] + && (junction[1] == const_cpu_to_le16(':')) + && (junction[2] == const_cpu_to_le16('\\'))) + kind = FULL_PATH; + else + /* + * For an absolute path we want an initial \ + */ + if ((count >= 0) + && (junction[0] == const_cpu_to_le16('\\'))) + kind = ABS_PATH; + else + kind = REJECTED_PATH; + /* + * Full path, with a drive letter and + * no specific definition for the drive letter : + * try to interpret as a target on the same volume. + * Do the same for an abs path with no drive letter. + */ + if (((kind == FULL_PATH) + && (count >= 3) + && junction[3] + && !ntfs_drive_letter(vol, junction[0])) + || (kind == ABS_PATH)) { + if (kind == ABS_PATH) + target = search_absolute(vol, &junction[1], + count - 1, isdir); + else + target = search_absolute(vol, &junction[3], + count - 3, isdir); + if (target) { + level = 0; + for (p=path; *p; p++) + if (*p == '/') + level++; + fulltarget = (char*)ntfs_malloc(3*level + + strlen(target) + 1); + if (fulltarget) { + fulltarget[0] = 0; + if (level > 1) { + for (i=1; i 0) && target) { + /* reverse slashes */ + for (q=target; *q; q++) + if (*q == '\\') + *q = '/'; + /* force uppercase drive letter */ + if ((target[1] == ':') + && (target[0] >= 'a') + && (target[0] <= 'z')) + target[0] += 'A' - 'a'; + level = 0; + for (p=path; *p; p++) + if (*p == '/') + level++; + fulltarget = (char*)ntfs_malloc(3*level + + sizeof(mappingdir) + count - 4); + if (fulltarget) { + fulltarget[0] = 0; + if (level > 1) { + for (i=1; imrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + vol = ni->vol; + reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, + AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); + if (reparse_attr && attr_size) { + switch (reparse_attr->reparse_tag) { + case IO_REPARSE_TAG_MOUNT_POINT : + mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*) + reparse_attr->reparse_data; + offs = le16_to_cpu(mount_point_data->subst_name_offset); + lth = le16_to_cpu(mount_point_data->subst_name_length); + /* consistency checks */ + if (isdir + && ((le16_to_cpu(reparse_attr->reparse_data_length) + + 8) == attr_size) + && ((int)((sizeof(REPARSE_POINT) + + sizeof(struct MOUNT_POINT_REPARSE_DATA) + + offs + lth)) <= attr_size)) { + target = ntfs_get_fulllink(vol, + (ntfschar*)&mount_point_data->path_buffer[offs], + lth/2, org_path, isdir); + if (target) + bad = FALSE; + } + break; + case IO_REPARSE_TAG_SYMLINK : + symlink_data = (struct SYMLINK_REPARSE_DATA*) + reparse_attr->reparse_data; + offs = le16_to_cpu(symlink_data->subst_name_offset); + lth = le16_to_cpu(symlink_data->subst_name_length); + p = (ntfschar*)&symlink_data->path_buffer[offs]; + /* + * Predetermine the kind of target, + * the called function has to make a full check + */ + if (*p++ == const_cpu_to_le16('\\')) { + if ((*p == const_cpu_to_le16('?')) + || (*p == const_cpu_to_le16('\\'))) + kind = FULL_TARGET; + else + kind = ABS_TARGET; + } else + if (*p == const_cpu_to_le16(':')) + kind = ABS_TARGET; + else + kind = REL_TARGET; + p--; + /* consistency checks */ + if (((le16_to_cpu(reparse_attr->reparse_data_length) + + 8) == attr_size) + && ((int)((sizeof(REPARSE_POINT) + + sizeof(struct SYMLINK_REPARSE_DATA) + + offs + lth)) <= attr_size)) { + switch (kind) { + case FULL_TARGET : + if (!(symlink_data->flags + & const_cpu_to_le32(1))) { + target = ntfs_get_fulllink(vol, + p, lth/2, + org_path, isdir); + if (target) + bad = FALSE; + } + break; + case ABS_TARGET : + if (symlink_data->flags + & const_cpu_to_le32(1)) { + target = ntfs_get_abslink(vol, + p, lth/2, + org_path, isdir); + if (target) + bad = FALSE; + } + break; + case REL_TARGET : + if (symlink_data->flags + & const_cpu_to_le32(1)) { + target = ntfs_get_rellink(vol, + p, lth/2, + org_path, isdir); + if (target) + bad = FALSE; + } + break; + } + } + break; + } + free(reparse_attr); + } + *pattr_size = attr_size; + if (bad) + errno = EOPNOTSUPP; + return (target); +} + +/* + * Check whether a reparse point looks like a junction point + * or a symbolic link. + * Should only be called for files or directories with reparse data + * + * The validity of the target is not checked. + */ + +BOOL ntfs_possible_symlink(ntfs_inode *ni) +{ + s64 attr_size = 0; + REPARSE_POINT *reparse_attr; + BOOL possible; + + possible = FALSE; + reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, + AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); + if (reparse_attr && attr_size) { + switch (reparse_attr->reparse_tag) { + case IO_REPARSE_TAG_MOUNT_POINT : + case IO_REPARSE_TAG_SYMLINK : + possible = TRUE; + default : ; + } + free(reparse_attr); + } + return (possible); +} + +/* + * Set the index for new reparse data + * + * Returns 0 if success + * -1 if failure, explained by errno + */ + +static int set_reparse_index(ntfs_inode *ni, ntfs_index_context *xr, + le32 reparse_tag) +{ + struct REPARSE_INDEX indx; + u64 file_id_cpu; + le64 file_id; + le16 seqn; + + seqn = ni->mrec->sequence_number; + file_id_cpu = MK_MREF(ni->mft_no,le16_to_cpu(seqn)); + file_id = cpu_to_le64(file_id_cpu); + indx.header.data_offset = const_cpu_to_le16( + sizeof(INDEX_ENTRY_HEADER) + + sizeof(REPARSE_INDEX_KEY)); + indx.header.data_length = const_cpu_to_le16(0); + indx.header.reservedV = const_cpu_to_le32(0); + indx.header.length = const_cpu_to_le16( + sizeof(struct REPARSE_INDEX)); + indx.header.key_length = const_cpu_to_le16( + sizeof(REPARSE_INDEX_KEY)); + indx.header.flags = const_cpu_to_le16(0); + indx.header.reserved = const_cpu_to_le16(0); + indx.key.reparse_tag = reparse_tag; + /* danger on processors which require proper alignment ! */ + memcpy(&indx.key.file_id, &file_id, 8); + indx.filling = const_cpu_to_le32(0); + ntfs_index_ctx_reinit(xr); + return (ntfs_ie_add(xr,(INDEX_ENTRY*)&indx)); +} + +/* + * Remove a reparse data index entry if attribute present + * + * Returns the size of existing reparse data + * (the existing reparse tag is returned) + * -1 if failure, explained by errno + */ + +static int remove_reparse_index(ntfs_attr *na, ntfs_index_context *xr, + le32 *preparse_tag) +{ + REPARSE_INDEX_KEY key; + u64 file_id_cpu; + le64 file_id; + s64 size; + le16 seqn; + int ret; + + ret = na->data_size; + if (ret) { + /* read the existing reparse_tag */ + size = ntfs_attr_pread(na, 0, 4, preparse_tag); + if (size == 4) { + seqn = na->ni->mrec->sequence_number; + file_id_cpu = MK_MREF(na->ni->mft_no,le16_to_cpu(seqn)); + file_id = cpu_to_le64(file_id_cpu); + key.reparse_tag = *preparse_tag; + /* danger on processors which require proper alignment ! */ + memcpy(&key.file_id, &file_id, 8); + if (!ntfs_index_lookup(&key, sizeof(REPARSE_INDEX_KEY), xr)) + ret = ntfs_index_rm(xr); + } else { + ret = -1; + errno = ENODATA; + } + } + return (ret); +} + +/* + * Open the $Extend/$Reparse file and its index + * + * Return the index context if opened + * or NULL if an error occurred (errno tells why) + * + * The index has to be freed and inode closed when not needed any more. + */ + +static ntfs_index_context *open_reparse_index(ntfs_volume *vol) +{ + ntfs_inode *ni; + ntfs_index_context *xr; + + ni = ntfs_pathname_to_inode(vol, NULL, "$Extend/$Reparse"); + if (ni) { + xr = ntfs_index_ctx_get(ni, reparse_index_name, 2); + if (!xr) { + ntfs_inode_close(ni); + } + } else + xr = (ntfs_index_context*)NULL; + return (xr); +} + +/* + * Update the reparse data and index + * + * The reparse data attribute should have been created, and + * an existing index is expected if there is an existing value. + * + * Returns 0 if success + * -1 if failure, explained by errno + * If could not remove the existing index, nothing is done, + * If could not write the new data, no index entry is inserted + * If failed to insert the index, data is removed + */ + +static int update_reparse_data(ntfs_inode *ni, ntfs_index_context *xr, + const char *value, size_t size) +{ + int res; + int written; + int oldsize; + ntfs_attr *na; + le32 reparse_tag; + + res = 0; + na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0); + if (na) { + /* remove the existing reparse data */ + oldsize = remove_reparse_index(na,xr,&reparse_tag); + if (oldsize < 0) + res = -1; + else { + /* resize attribute */ + res = ntfs_attr_truncate(na, (s64)size); + /* overwrite value if any */ + if (!res && value) { + written = (int)ntfs_attr_pwrite(na, + (s64)0, (s64)size, value); + if (written != (s64)size) { + ntfs_log_error("Failed to update " + "reparse data\n"); + errno = EIO; + res = -1; + } + } + if (!res + && set_reparse_index(ni,xr, + ((const REPARSE_POINT*)value)->reparse_tag) + && (oldsize > 0)) { + /* + * If cannot index, try to remove the reparse + * data and log the error. There will be an + * inconsistency if removal fails. + */ + ntfs_attr_rm(na); + ntfs_log_error("Failed to index reparse data." + " Possible corruption.\n"); + } + } + ntfs_attr_close(na); + NInoSetDirty(ni); + } else + res = -1; + return (res); +} + +/* + * Delete a reparse index entry + * + * Returns 0 if success + * -1 if failure, explained by errno + */ + +int ntfs_delete_reparse_index(ntfs_inode *ni) +{ + ntfs_index_context *xr; + ntfs_inode *xrni; + ntfs_attr *na; + le32 reparse_tag; + int res; + + res = 0; + na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0); + if (na) { + /* + * read the existing reparse data (the tag is enough) + * and un-index it + */ + xr = open_reparse_index(ni->vol); + if (xr) { + if (remove_reparse_index(na,xr,&reparse_tag) < 0) + res = -1; + xrni = xr->ni; + ntfs_index_entry_mark_dirty(xr); + NInoSetDirty(xrni); + ntfs_index_ctx_put(xr); + ntfs_inode_close(xrni); + } + ntfs_attr_close(na); + } + return (res); +} + +/* + * Get the ntfs reparse data into an extended attribute + * + * Returns the reparse data size + * and the buffer is updated if it is long enough + */ + +int ntfs_get_ntfs_reparse_data(const char *path __attribute__((unused)), + char *value, size_t size, ntfs_inode *ni) +{ + REPARSE_POINT *reparse_attr; + s64 attr_size; + + attr_size = 0; /* default to no data and no error */ + if (ni) { + if (ni->flags & FILE_ATTR_REPARSE_POINT) { + reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni, + AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size); + if (reparse_attr) { + if (attr_size <= (s64)size) { + if (value) + memcpy(value,reparse_attr, + attr_size); + else + errno = EINVAL; + } + free(reparse_attr); + } + } else + errno = ENODATA; + } + return (attr_size ? (int)attr_size : -errno); +} + +/* + * Set the reparse data from an extended attribute + * + * Warning : the new data is not checked + * + * Returns 0, or -1 if there is a problem + */ + +int ntfs_set_ntfs_reparse_data(const char *path __attribute__((unused)), + const char *value, size_t size, int flags, + ntfs_inode *ni) +{ + int res; + u8 dummy; + ntfs_inode *xrni; + ntfs_index_context *xr; + + res = 0; + if (ni && value && (size >= 4)) { + xr = open_reparse_index(ni->vol); + if (xr) { + if (!ntfs_attr_exist(ni,AT_REPARSE_POINT, + AT_UNNAMED,0)) { + if (!(flags & XATTR_REPLACE)) { + /* + * no reparse data attribute : add one, + * apparently, this does not feed the new value in + * Note : NTFS version must be >= 3 + */ + if (ni->vol->major_ver >= 3) { + res = ntfs_attr_add(ni, + AT_REPARSE_POINT, + AT_UNNAMED,0,&dummy, + (s64)0); + if (!res) + ni->flags |= + FILE_ATTR_REPARSE_POINT; + NInoSetDirty(ni); + } else { + errno = EOPNOTSUPP; + res = -1; + } + } else { + errno = ENODATA; + res = -1; + } + } else { + if (flags & XATTR_CREATE) { + errno = EEXIST; + res = -1; + } + } + if (!res) { + /* update value and index */ + res = update_reparse_data(ni,xr,value,size); + } + xrni = xr->ni; + ntfs_index_entry_mark_dirty(xr); + NInoSetDirty(xrni); + ntfs_index_ctx_put(xr); + ntfs_inode_close(xrni); + } else { + res = -1; + } + } else { + errno = EINVAL; + res = -1; + } + return (res ? -1 : 0); +} + +/* + * Remove the reparse data + * + * Returns 0, or -1 if there is a problem + */ + +int ntfs_remove_ntfs_reparse_data(const char *path __attribute__((unused)), + ntfs_inode *ni) +{ + int res; + int olderrno; + ntfs_attr *na; + ntfs_inode *xrni; + ntfs_index_context *xr; + le32 reparse_tag; + + res = 0; + if (ni) { + /* + * open and delete the reparse data + */ + na = ntfs_attr_open(ni, AT_REPARSE_POINT, + AT_UNNAMED,0); + if (na) { + /* first remove index (reparse data needed) */ + xr = open_reparse_index(ni->vol); + if (xr) { + if (remove_reparse_index(na,xr, + &reparse_tag) < 0) { + res = -1; + } else { + /* now remove attribute */ + res = ntfs_attr_rm(na); + if (!res) { + ni->flags &= + ~FILE_ATTR_REPARSE_POINT; + } else { + /* + * If we could not remove the + * attribute, try to restore the + * index and log the error. There + * will be an inconsistency if + * the reindexing fails. + */ + set_reparse_index(ni, xr, + reparse_tag); + ntfs_log_error( + "Failed to remove reparse data." + " Possible corruption.\n"); + } + } + xrni = xr->ni; + ntfs_index_entry_mark_dirty(xr); + NInoSetDirty(xrni); + ntfs_index_ctx_put(xr); + ntfs_inode_close(xrni); + } + olderrno = errno; + ntfs_attr_close(na); + /* avoid errno pollution */ + if (errno == ENOENT) + errno = olderrno; + } else { + errno = ENODATA; + res = -1; + } + NInoSetDirty(ni); + } else { + errno = EINVAL; + res = -1; + } + return (res ? -1 : 0); +} diff --git a/release/src/router/ntfs-3g/libntfs-3g/runlist.c b/release/src/router/ntfs-3g/libntfs-3g/runlist.c index f39698de94..f81996bd55 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/runlist.c +++ b/release/src/router/ntfs-3g/libntfs-3g/runlist.c @@ -5,6 +5,7 @@ * Copyright (c) 2002-2005 Richard Russon * Copyright (c) 2002-2008 Szabolcs Szakacsits * Copyright (c) 2004 Yura Pakhuchiy + * Copyright (c) 2007-2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -110,6 +111,27 @@ static runlist_element *ntfs_rl_realloc(runlist_element *rl, int old_size, return realloc(rl, new_size); } +/* + * Extend a runlist by some entry count + * The runlist may have to be reallocated + * + * Returns the reallocated runlist + * or NULL if reallocation was not possible (with errno set) + */ + +runlist_element *ntfs_rl_extend(runlist_element *rl, int more_entries) +{ + int last; + + last = 0; + while (rl[last].length) + last++; + rl = ntfs_rl_realloc(rl,last+1,last+more_entries+1); + if (!rl) + errno = ENOMEM; + return (rl); +} + /** * ntfs_rl_are_mergeable - test if two runlists can be joined together * @dst: original runlist @@ -1124,8 +1146,9 @@ rl_err_out: /** * ntfs_rl_pwrite - scatter write to disk * @vol: ntfs volume to write to - * @rl: runlist specifying where to write the data to - * @pos: byte position within runlist @rl at which to begin the write + * @rl: runlist entry specifying where to write the data to + * @ofs: offset in file for runlist element indicated in @rl + * @pos: byte position from runlist beginning at which to begin the write * @count: number of bytes to write * @b: data buffer to write to disk * @@ -1144,9 +1167,9 @@ rl_err_out: * of invalid arguments. */ s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b) + s64 ofs, const s64 pos, s64 count, void *b) { - s64 written, to_write, ofs, total = 0; + s64 written, to_write, total = 0; int err = EIO; if (!vol || !rl || pos < 0 || count < 0) { @@ -1159,9 +1182,11 @@ s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl, if (!count) goto out; /* Seek in @rl to the run containing @pos. */ - for (ofs = 0; rl->length && (ofs + (rl->length << - vol->cluster_size_bits) <= pos); rl++) + while (rl->length && (ofs + (rl->length << + vol->cluster_size_bits) <= pos)) { ofs += (rl->length << vol->cluster_size_bits); + rl++; + } /* Offset in the run at which to begin writing. */ ofs = pos - ofs; for (total = 0LL; count; rl++, ofs = 0) { @@ -1230,19 +1255,18 @@ errno_set: */ int ntfs_get_nr_significant_bytes(const s64 n) { - s64 l = n; + u64 l; int i; - s8 j; - i = 0; - do { - l >>= 8; - i++; - } while (l != 0LL && l != -1LL); - j = (n >> 8 * (i - 1)) & 0xff; - /* If the sign bit is wrong, we need an extra byte. */ - if ((n < 0LL && j >= 0) || (n > 0LL && j < 0)) - i++; + l = (n < 0 ? ~n : n); + i = 1; + if (l >= 128) { + l >>= 7; + do { + i++; + l >>= 8; + } while (l); + } return i; } @@ -1267,7 +1291,7 @@ int ntfs_get_nr_significant_bytes(const s64 n) * EIO - The runlist is corrupt. */ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, - const runlist_element *rl, const VCN start_vcn) + const runlist_element *rl, const VCN start_vcn, int max_size) { LCN prev_lcn; int rls; @@ -1326,7 +1350,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, rl++; } /* Do the full runs. */ - for (; rl->length; rl++) { + for (; rl->length && (rls <= max_size); rl++) { if (rl->length < 0 || rl->lcn < LCN_HOLE) goto err_out; /* Header byte + length. */ @@ -1441,7 +1465,7 @@ err_out: */ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, const int dst_len, const runlist_element *rl, - const VCN start_vcn, VCN *const stop_vcn) + const VCN start_vcn, runlist_element const **stop_rl) { LCN prev_lcn; u8 *dst_max, *dst_next; @@ -1453,8 +1477,8 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, if (!rl) { if (start_vcn) goto val_err; - if (stop_vcn) - *stop_vcn = 0; + if (stop_rl) + *stop_rl = rl; if (dst_len < 1) goto nospc_err; goto ok; @@ -1549,8 +1573,8 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, dst += 1 + len_len + lcn_len; } /* Set stop vcn. */ - if (stop_vcn) - *stop_vcn = rl->vcn; + if (stop_rl) + *stop_rl = rl; ok: /* Add terminator byte. */ *dst = 0; @@ -1558,8 +1582,8 @@ out: return ret; size_err: /* Set stop vcn. */ - if (stop_vcn) - *stop_vcn = rl->vcn; + if (stop_rl) + *stop_rl = rl; /* Add terminator byte. */ *dst = 0; nospc_err: diff --git a/release/src/router/ntfs-3g/libntfs-3g/security.c b/release/src/router/ntfs-3g/libntfs-3g/security.c index 4b54b699da..aed9ff1ba3 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/security.c +++ b/release/src/router/ntfs-3g/libntfs-3g/security.c @@ -4,6 +4,7 @@ * Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2005-2006 Szabolcs Szakacsits * Copyright (c) 2006 Yura Pakhuchiy + * Copyright (c) 2007-2009 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -37,20 +38,112 @@ #ifdef HAVE_ERRNO_H #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SETXATTR +#include +#endif + +#include +#include +#include #include "types.h" #include "layout.h" #include "attrib.h" +#include "index.h" +#include "dir.h" +#include "bitmap.h" #include "security.h" +#include "acls.h" #include "misc.h" -#include "bitmap.h" + +/* + * JPA NTFS constants or structs + * should be moved to layout.h + */ + +#define ALIGN_SDS_BLOCK 0x40000 /* Alignment for a $SDS block */ +#define ALIGN_SDS_ENTRY 16 /* Alignment for a $SDS entry */ +#define STUFFSZ 0x4000 /* unitary stuffing size for $SDS */ +#define FIRST_SECURITY_ID 0x100 /* Lowest security id */ + + /* Mask for attributes which can be forced */ +#define FILE_ATTR_SETTABLE ( FILE_ATTR_READONLY \ + | FILE_ATTR_HIDDEN \ + | FILE_ATTR_SYSTEM \ + | FILE_ATTR_ARCHIVE \ + | FILE_ATTR_TEMPORARY \ + | FILE_ATTR_OFFLINE \ + | FILE_ATTR_NOT_CONTENT_INDEXED ) + +struct SII { /* this is an image of an $SII index entry */ + le16 offs; + le16 size; + le32 fill1; + le16 indexsz; + le16 indexksz; + le16 flags; + le16 fill2; + le32 keysecurid; + + /* did not find official description for the following */ + le32 hash; + le32 securid; + le32 dataoffsl; /* documented as badly aligned */ + le32 dataoffsh; + le32 datasize; +} ; + +struct SDH { /* this is an image of an $SDH index entry */ + le16 offs; + le16 size; + le32 fill1; + le16 indexsz; + le16 indexksz; + le16 flags; + le16 fill2; + le32 keyhash; + le32 keysecurid; + + /* did not find official description for the following */ + le32 hash; + le32 securid; + le32 dataoffsl; + le32 dataoffsh; + le32 datasize; + le32 fill3; + } ; + +/* + * A few useful constants + */ + +static ntfschar sii_stream[] = { const_cpu_to_le16('$'), + const_cpu_to_le16('S'), + const_cpu_to_le16('I'), + const_cpu_to_le16('I'), + const_cpu_to_le16(0) }; +static ntfschar sdh_stream[] = { const_cpu_to_le16('$'), + const_cpu_to_le16('S'), + const_cpu_to_le16('D'), + const_cpu_to_le16('H'), + const_cpu_to_le16(0) }; + +/* + * null SID (S-1-0-0) + */ + +extern const SID *nullsid; /* * The zero GUID. */ + static const GUID __zero_guid = { const_cpu_to_le32(0), const_cpu_to_le16(0), const_cpu_to_le16(0), { 0, 0, 0, 0, 0, 0, 0, 0 } }; -const GUID *const zero_guid = &__zero_guid; +static const GUID *const zero_guid = &__zero_guid; /** * ntfs_guid_is_zero - check if a GUID is zero @@ -91,7 +184,7 @@ char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str) } _guid_str = guid_str; if (!_guid_str) { - _guid_str = ntfs_malloc(37); + _guid_str = (char*)ntfs_malloc(37); if (!_guid_str) return _guid_str; } @@ -191,6 +284,7 @@ int ntfs_sid_to_mbs_size(const SID *sid) char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size) { u64 u; + le32 leauth; char *s; int i, j, cnt; @@ -207,7 +301,7 @@ char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size) cnt = ntfs_sid_to_mbs_size(sid); if (cnt < 0) return NULL; - s = ntfs_malloc(cnt); + s = (char*)ntfs_malloc(cnt); if (!s) return s; sid_str = s; @@ -236,8 +330,9 @@ char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size) cnt -= i; /* Finally, add the sub authorities. */ for (j = 0; j < sid->sub_authority_count; j++) { + leauth = sid->sub_authority[j]; i = snprintf(s, cnt, "-%u", (unsigned int) - le32_to_cpu(sid->sub_authority[j])); + le32_to_cpu(leauth)); if (i < 0 || i >= cnt) goto err_out; s += i; @@ -275,70 +370,6 @@ void ntfs_generate_guid(GUID *guid) } } -int ntfs_sd_add_everyone(ntfs_inode *ni) -{ - SECURITY_DESCRIPTOR_ATTR *sd; - ACL *acl; - ACCESS_ALLOWED_ACE *ace; - SID *sid; - int ret, sd_len; - - /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ - /* - * Calculate security descriptor length. We have 2 sub-authorities in - * owner and group SIDs, but structure SID contain only one, so add - * 4 bytes to every SID. - */ - sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + - sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); - sd = ntfs_calloc(sd_len); - if (!sd) - return -1; - - sd->revision = 1; - sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; - - sid = (SID *)((u8 *)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); - sid->revision = 1; - sid->sub_authority_count = 2; - sid->sub_authority[0] = cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - sid->identifier_authority.value[5] = 5; - sd->owner = cpu_to_le32((u8 *)sid - (u8 *)sd); - - sid = (SID *)((u8 *)sid + sizeof(SID) + 4); - sid->revision = 1; - sid->sub_authority_count = 2; - sid->sub_authority[0] = cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - sid->identifier_authority.value[5] = 5; - sd->group = cpu_to_le32((u8 *)sid - (u8 *)sd); - - acl = (ACL *)((u8 *)sid + sizeof(SID) + 4); - acl->revision = 2; - acl->size = cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); - acl->ace_count = cpu_to_le16(1); - sd->dacl = cpu_to_le32((u8 *)acl - (u8 *)sd); - - ace = (ACCESS_ALLOWED_ACE *)((u8 *)acl + sizeof(ACL)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; - ace->size = cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE)); - ace->mask = cpu_to_le32(0x1f01ff); /* FIXME */ - ace->sid.revision = 1; - ace->sid.sub_authority_count = 1; - ace->sid.sub_authority[0] = 0; - ace->sid.identifier_authority.value[5] = 1; - - ret = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, (u8 *)sd, - sd_len); - if (ret) - ntfs_log_perror("Failed to add SECURITY_DESCRIPTOR\n"); - - free(sd); - return ret; -} - /** * ntfs_security_hash - calculate the hash of a security descriptor * @sd: self-relative security descriptor whose hash to calculate @@ -357,14 +388,4595 @@ int ntfs_sd_add_everyone(ntfs_inode *ni) */ le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len) { - const le32 *pos = (const le32 *)sd; - const le32 *end = pos + (len >> 2); - u32 hash = 0; + const le32 *pos = (const le32*)sd; + const le32 *end = pos + (len >> 2); + u32 hash = 0; - while (pos < end) { - hash = le32_to_cpup(pos) + ntfs_rol32(hash, 3); + while (pos < end) { + hash = le32_to_cpup(pos) + ntfs_rol32(hash, 3); pos++; } - return cpu_to_le32(hash); + return cpu_to_le32(hash); +} + +/* + * Internal read + * copied and pasted from ntfs_fuse_read() and made independent + * of fuse context + */ + +static int ntfs_local_read(ntfs_inode *ni, + ntfschar *stream_name, int stream_name_len, + char *buf, size_t size, off_t offset) +{ + ntfs_attr *na = NULL; + int res, total = 0; + + na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); + if (!na) { + res = -errno; + goto exit; + } + if ((size_t)offset < (size_t)na->data_size) { + if (offset + size > (size_t)na->data_size) + size = na->data_size - offset; + while (size) { + res = ntfs_attr_pread(na, offset, size, buf); + if ((off_t)res < (off_t)size) + ntfs_log_perror("ntfs_attr_pread partial read " + "(%lld : %lld <> %d)", + (long long)offset, + (long long)size, res); + if (res <= 0) { + res = -errno; + goto exit; + } + size -= res; + offset += res; + total += res; + } + } + res = total; +exit: + if (na) + ntfs_attr_close(na); + return res; +} + + +/* + * Internal write + * copied and pasted from ntfs_fuse_write() and made independent + * of fuse context + */ + +static int ntfs_local_write(ntfs_inode *ni, + ntfschar *stream_name, int stream_name_len, + char *buf, size_t size, off_t offset) +{ + ntfs_attr *na = NULL; + int res, total = 0; + + na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); + if (!na) { + res = -errno; + goto exit; + } + while (size) { + res = ntfs_attr_pwrite(na, offset, size, buf); + if (res < (s64)size) + ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: " + "%lld <> %d)", (long long)offset, + (long long)size, res); + if (res <= 0) { + res = -errno; + goto exit; + } + size -= res; + offset += res; + total += res; + } + res = total; +exit: + if (na) + ntfs_attr_close(na); + return res; +} + + +/* + * Get the first entry of current index block + * cut and pasted form ntfs_ie_get_first() in index.c + */ + +static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih) +{ + return (INDEX_ENTRY*)((u8*)ih + le32_to_cpu(ih->entries_offset)); +} + +/* + * Stuff a 256KB block into $SDS before writing descriptors + * into the block. + * + * This prevents $SDS from being automatically declared as sparse + * when the second copy of the first security descriptor is written + * 256KB further ahead. + * + * Having $SDS declared as a sparse file is not wrong by itself + * and chkdsk leaves it as a sparse file. It does however complain + * and add a sparse flag (0x0200) into field file_attributes of + * STANDARD_INFORMATION of $Secure. This probably means that a + * sparse attribute (ATTR_IS_SPARSE) is only allowed in sparse + * files (FILE_ATTR_SPARSE_FILE). + * + * Windows normally does not convert to sparse attribute or sparse + * file. Stuffing is just a way to get to the same result. + */ + +static int entersecurity_stuff(ntfs_volume *vol, off_t offs) +{ + int res; + int written; + unsigned long total; + char *stuff; + + res = 0; + total = 0; + stuff = (char*)ntfs_malloc(STUFFSZ); + if (stuff) { + memset(stuff, 0, STUFFSZ); + do { + written = ntfs_local_write(vol->secure_ni, + STREAM_SDS, 4, stuff, STUFFSZ, offs); + if (written == STUFFSZ) { + total += STUFFSZ; + offs += STUFFSZ; + } else { + errno = ENOSPC; + res = -1; + } + } while (!res && (total < ALIGN_SDS_BLOCK)); + free(stuff); + } else { + errno = ENOMEM; + res = -1; + } + return (res); +} + +/* + * Enter a new security descriptor into $Secure (data only) + * it has to be written twice with an offset of 256KB + * + * Should only be called by entersecurityattr() to ensure consistency + * + * Returns zero if sucessful + */ + +static int entersecurity_data(ntfs_volume *vol, + const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz, + le32 hash, le32 keyid, off_t offs, int gap) +{ + int res; + int written1; + int written2; + char *fullattr; + int fullsz; + SECURITY_DESCRIPTOR_HEADER *phsds; + + res = -1; + fullsz = attrsz + gap + sizeof(SECURITY_DESCRIPTOR_HEADER); + fullattr = (char*)ntfs_malloc(fullsz); + if (fullattr) { + /* + * Clear the gap from previous descriptor + * this could be useful for appending the second + * copy to the end of file. When creating a new + * 256K block, the gap is cleared while writing + * the first copy + */ + if (gap) + memset(fullattr,0,gap); + memcpy(&fullattr[gap + sizeof(SECURITY_DESCRIPTOR_HEADER)], + attr,attrsz); + phsds = (SECURITY_DESCRIPTOR_HEADER*)&fullattr[gap]; + phsds->hash = hash; + phsds->security_id = keyid; + phsds->offset = cpu_to_le64(offs); + phsds->length = cpu_to_le32(fullsz - gap); + written1 = ntfs_local_write(vol->secure_ni, + STREAM_SDS, 4, fullattr, fullsz, + offs - gap); + written2 = ntfs_local_write(vol->secure_ni, + STREAM_SDS, 4, fullattr, fullsz, + offs - gap + ALIGN_SDS_BLOCK); + if ((written1 == fullsz) + && (written2 == written1)) + res = 0; + else + errno = ENOSPC; + free(fullattr); + } else + errno = ENOMEM; + return (res); +} + +/* + * Enter a new security descriptor in $Secure (indexes only) + * + * Should only be called by entersecurityattr() to ensure consistency + * + * Returns zero if sucessful + */ + +static int entersecurity_indexes(ntfs_volume *vol, s64 attrsz, + le32 hash, le32 keyid, off_t offs) +{ + union { + struct { + le32 dataoffsl; + le32 dataoffsh; + } parts; + le64 all; + } realign; + int res; + ntfs_index_context *xsii; + ntfs_index_context *xsdh; + struct SII newsii; + struct SDH newsdh; + + res = -1; + /* enter a new $SII record */ + + xsii = vol->secure_xsii; + ntfs_index_ctx_reinit(xsii); + newsii.offs = const_cpu_to_le16(20); + newsii.size = const_cpu_to_le16(sizeof(struct SII) - 20); + newsii.fill1 = const_cpu_to_le32(0); + newsii.indexsz = const_cpu_to_le16(sizeof(struct SII)); + newsii.indexksz = const_cpu_to_le16(sizeof(SII_INDEX_KEY)); + newsii.flags = const_cpu_to_le16(0); + newsii.fill2 = const_cpu_to_le16(0); + newsii.keysecurid = keyid; + newsii.hash = hash; + newsii.securid = keyid; + realign.all = cpu_to_le64(offs); + newsii.dataoffsh = realign.parts.dataoffsh; + newsii.dataoffsl = realign.parts.dataoffsl; + newsii.datasize = cpu_to_le32(attrsz + + sizeof(SECURITY_DESCRIPTOR_HEADER)); + if (!ntfs_ie_add(xsii,(INDEX_ENTRY*)&newsii)) { + + /* enter a new $SDH record */ + + xsdh = vol->secure_xsdh; + ntfs_index_ctx_reinit(xsdh); + newsdh.offs = const_cpu_to_le16(24); + newsdh.size = const_cpu_to_le16( + sizeof(SECURITY_DESCRIPTOR_HEADER)); + newsdh.fill1 = const_cpu_to_le32(0); + newsdh.indexsz = const_cpu_to_le16( + sizeof(struct SDH)); + newsdh.indexksz = const_cpu_to_le16( + sizeof(SDH_INDEX_KEY)); + newsdh.flags = const_cpu_to_le16(0); + newsdh.fill2 = const_cpu_to_le16(0); + newsdh.keyhash = hash; + newsdh.keysecurid = keyid; + newsdh.hash = hash; + newsdh.securid = keyid; + newsdh.dataoffsh = realign.parts.dataoffsh; + newsdh.dataoffsl = realign.parts.dataoffsl; + newsdh.datasize = cpu_to_le32(attrsz + + sizeof(SECURITY_DESCRIPTOR_HEADER)); + /* special filler value, Windows generally */ + /* fills with 0x00490049, sometimes with zero */ + newsdh.fill3 = const_cpu_to_le32(0x00490049); + if (!ntfs_ie_add(xsdh,(INDEX_ENTRY*)&newsdh)) + res = 0; + } + return (res); +} + +/* + * Enter a new security descriptor in $Secure (data and indexes) + * Returns id of entry, or zero if there is a problem. + * (should not be called for NTFS version < 3.0) + * + * important : calls have to be serialized, however no locking is + * needed while fuse is not multithreaded + */ + +static le32 entersecurityattr(ntfs_volume *vol, + const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz, + le32 hash) +{ + union { + struct { + le32 dataoffsl; + le32 dataoffsh; + } parts; + le64 all; + } realign; + le32 securid; + le32 keyid; + u32 newkey; + off_t offs; + int gap; + int size; + BOOL found; + struct SII *psii; + INDEX_ENTRY *entry; + INDEX_ENTRY *next; + ntfs_index_context *xsii; + ntfs_attr *na; + int olderrno; + + /* find the first available securid beyond the last key */ + /* in $Secure:$SII. This also determines the first */ + /* available location in $Secure:$SDS, as this stream */ + /* is always appended to and the id's are allocated */ + /* in sequence */ + + securid = const_cpu_to_le32(0); + xsii = vol->secure_xsii; + ntfs_index_ctx_reinit(xsii); + offs = size = 0; + keyid = const_cpu_to_le32(-1); + olderrno = errno; + found = !ntfs_index_lookup((char*)&keyid, + sizeof(SII_INDEX_KEY), xsii); + if (!found && (errno != ENOENT)) { + ntfs_log_perror("Inconsistency in index $SII"); + psii = (struct SII*)NULL; + } else { + /* restore errno to avoid misinterpretation */ + errno = olderrno; + entry = xsii->entry; + psii = (struct SII*)xsii->entry; + } + if (psii) { + /* + * Get last entry in block, but must get first one + * one first, as we should already be beyond the + * last one. For some reason the search for the last + * entry sometimes does not return the last block... + * we assume this can only happen in root block + */ + if (xsii->is_in_root) + entry = ntfs_ie_get_first + ((INDEX_HEADER*)&xsii->ir->index); + else + entry = ntfs_ie_get_first + ((INDEX_HEADER*)&xsii->ib->index); + /* + * All index blocks should be at least half full + * so there always is a last entry but one, + * except when creating the first entry in index root. + * A simplified version of next(), limited to + * current index node, could be used + */ + keyid = const_cpu_to_le32(0); + while (entry) { + next = ntfs_index_next(entry,xsii); + if (next) { + psii = (struct SII*)next; + /* save last key and */ + /* available position */ + keyid = psii->keysecurid; + realign.parts.dataoffsh + = psii->dataoffsh; + realign.parts.dataoffsl + = psii->dataoffsl; + offs = le64_to_cpu(realign.all); + size = le32_to_cpu(psii->datasize); + } + entry = next; + } + } + if (!keyid) { + /* + * could not find any entry, before creating the first + * entry, make a double check by making sure size of $SII + * is less than needed for one entry + */ + securid = const_cpu_to_le32(0); + na = ntfs_attr_open(vol->secure_ni,AT_INDEX_ROOT,sii_stream,4); + if (na) { + if ((size_t)na->data_size < sizeof(struct SII)) { + ntfs_log_error("Creating the first security_id\n"); + securid = const_cpu_to_le32(FIRST_SECURITY_ID); + } + ntfs_attr_close(na); + } + if (!securid) { + ntfs_log_error("Error creating a security_id\n"); + errno = EIO; + } + } else { + newkey = le32_to_cpu(keyid) + 1; + securid = cpu_to_le32(newkey); + } + /* + * The security attr has to be written twice 256KB + * apart. This implies that offsets like + * 0x40000*odd_integer must be left available for + * the second copy. So align to next block when + * the last byte overflows on a wrong block. + */ + + if (securid) { + gap = (-size) & (ALIGN_SDS_ENTRY - 1); + offs += gap + size; + if ((offs + attrsz + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1) + & ALIGN_SDS_BLOCK) { + offs = ((offs + attrsz + + sizeof(SECURITY_DESCRIPTOR_HEADER) - 1) + | (ALIGN_SDS_BLOCK - 1)) + 1; + } + if (!(offs & (ALIGN_SDS_BLOCK - 1))) + entersecurity_stuff(vol, offs); + /* + * now write the security attr to storage : + * first data, then SII, then SDH + * If failure occurs while writing SDS, data will never + * be accessed through indexes, and will be overwritten + * by the next allocated descriptor + * If failure occurs while writing SII, the id has not + * recorded and will be reallocated later + * If failure occurs while writing SDH, the space allocated + * in SDS or SII will not be reused, an inconsistency + * will persist with no significant consequence + */ + if (entersecurity_data(vol, attr, attrsz, hash, securid, offs, gap) + || entersecurity_indexes(vol, attrsz, hash, securid, offs)) + securid = const_cpu_to_le32(0); + } + /* inode now is dirty, synchronize it all */ + ntfs_index_entry_mark_dirty(vol->secure_xsii); + ntfs_index_ctx_reinit(vol->secure_xsii); + ntfs_index_entry_mark_dirty(vol->secure_xsdh); + ntfs_index_ctx_reinit(vol->secure_xsdh); + NInoSetDirty(vol->secure_ni); + if (ntfs_inode_sync(vol->secure_ni)) + ntfs_log_perror("Could not sync $Secure\n"); + return (securid); +} + +/* + * Find a matching security descriptor in $Secure, + * if none, allocate a new id and write the descriptor to storage + * Returns id of entry, or zero if there is a problem. + * + * important : calls have to be serialized, however no locking is + * needed while fuse is not multithreaded + */ + +static le32 setsecurityattr(ntfs_volume *vol, + const SECURITY_DESCRIPTOR_RELATIVE *attr, s64 attrsz) +{ + struct SDH *psdh; /* this is an image of index (le) */ + union { + struct { + le32 dataoffsl; + le32 dataoffsh; + } parts; + le64 all; + } realign; + BOOL found; + BOOL collision; + size_t size; + size_t rdsize; + s64 offs; + int res; + ntfs_index_context *xsdh; + char *oldattr; + SDH_INDEX_KEY key; + INDEX_ENTRY *entry; + le32 securid; + le32 hash; + int olderrno; + + hash = ntfs_security_hash(attr,attrsz); + oldattr = (char*)NULL; + securid = const_cpu_to_le32(0); + res = 0; + xsdh = vol->secure_xsdh; + if (vol->secure_ni && xsdh && !vol->secure_reentry++) { + ntfs_index_ctx_reinit(xsdh); + /* + * find the nearest key as (hash,0) + * (do not search for partial key : in case of collision, + * it could return a key which is not the first one which + * collides) + */ + key.hash = hash; + key.security_id = const_cpu_to_le32(0); + olderrno = errno; + found = !ntfs_index_lookup((char*)&key, + sizeof(SDH_INDEX_KEY), xsdh); + if (!found && (errno != ENOENT)) + ntfs_log_perror("Inconsistency in index $SDH"); + else { + /* restore errno to avoid misinterpretation */ + errno = olderrno; + entry = xsdh->entry; + found = FALSE; + /* + * lookup() may return a node with no data, + * if so get next + */ + if (entry->ie_flags & INDEX_ENTRY_END) + entry = ntfs_index_next(entry,xsdh); + do { + collision = FALSE; + psdh = (struct SDH*)entry; + if (psdh) + size = (size_t) le32_to_cpu(psdh->datasize) + - sizeof(SECURITY_DESCRIPTOR_HEADER); + else size = 0; + /* if hash is not the same, the key is not present */ + if (psdh && (size > 0) + && (psdh->keyhash == hash)) { + /* if hash is the same */ + /* check the whole record */ + realign.parts.dataoffsh = psdh->dataoffsh; + realign.parts.dataoffsl = psdh->dataoffsl; + offs = le64_to_cpu(realign.all) + + sizeof(SECURITY_DESCRIPTOR_HEADER); + oldattr = (char*)ntfs_malloc(size); + if (oldattr) { + rdsize = ntfs_local_read( + vol->secure_ni, + STREAM_SDS, 4, + oldattr, size, offs); + found = (rdsize == size) + && !memcmp(oldattr,attr,size); + free(oldattr); + /* if the records do not compare */ + /* (hash collision), try next one */ + if (!found) { + entry = ntfs_index_next( + entry,xsdh); + collision = TRUE; + } + } else + res = ENOMEM; + } + } while (collision && entry); + if (found) + securid = psdh->keysecurid; + else { + if (res) { + errno = res; + securid = const_cpu_to_le32(0); + } else { + /* + * no matching key : + * have to build a new one + */ + securid = entersecurityattr(vol, + attr, attrsz, hash); + } + } + } + } + if (--vol->secure_reentry) + ntfs_log_perror("Reentry error, check no multithreading\n"); + return (securid); +} + + +/* + * Update the security descriptor of a file + * Either as an attribute (complying with pre v3.x NTFS version) + * or, when possible, as an entry in $Secure (for NTFS v3.x) + * + * returns 0 if success + */ + +static int update_secur_descr(ntfs_volume *vol, + char *newattr, ntfs_inode *ni) +{ + int newattrsz; + int written; + int res; + ntfs_attr *na; + + newattrsz = ntfs_attr_size(newattr); + +#if !FORCE_FORMAT_v1x + if ((vol->major_ver < 3) || !vol->secure_ni) { +#endif + + /* update for NTFS format v1.x */ + + /* update the old security attribute */ + na = ntfs_attr_open(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); + if (na) { + /* resize attribute */ + res = ntfs_attr_truncate(na, (s64) newattrsz); + /* overwrite value */ + if (!res) { + written = (int)ntfs_attr_pwrite(na, (s64) 0, + (s64) newattrsz, newattr); + if (written != newattrsz) { + ntfs_log_error("Failed to update " + "a v1.x security descriptor\n"); + errno = EIO; + res = -1; + } + } + + ntfs_attr_close(na); + /* if old security attribute was found, also */ + /* truncate standard information attribute to v1.x */ + /* this is needed when security data is wanted */ + /* as v1.x though volume is formatted for v3.x */ + na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, + AT_UNNAMED, 0); + if (na) { + clear_nino_flag(ni, v3_Extensions); + /* + * Truncating the record does not sweep extensions + * from copy in memory. Clear security_id to be safe + */ + ni->security_id = const_cpu_to_le32(0); + res = ntfs_attr_truncate(na, (s64)48); + ntfs_attr_close(na); + clear_nino_flag(ni, v3_Extensions); + } + } else { + /* + * insert the new security attribute if there + * were none + */ + res = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, + AT_UNNAMED, 0, (u8*)newattr, + (s64) newattrsz); + } +#if !FORCE_FORMAT_v1x + } else { + + /* update for NTFS format v3.x */ + + le32 securid; + + securid = setsecurityattr(vol, + (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, + (s64)newattrsz); + if (securid) { + na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, + AT_UNNAMED, 0); + if (na) { + res = 0; + if (!test_nino_flag(ni, v3_Extensions)) { + /* expand standard information attribute to v3.x */ + res = ntfs_attr_truncate(na, + (s64)sizeof(STANDARD_INFORMATION)); + ni->owner_id = const_cpu_to_le32(0); + ni->quota_charged = const_cpu_to_le64(0); + ni->usn = const_cpu_to_le64(0); + ntfs_attr_remove(ni, + AT_SECURITY_DESCRIPTOR, + AT_UNNAMED, 0); + } + set_nino_flag(ni, v3_Extensions); + ni->security_id = securid; + ntfs_attr_close(na); + } else { + ntfs_log_error("Failed to update " + "standard informations\n"); + errno = EIO; + res = -1; + } + } else + res = -1; + } +#endif + + /* mark node as dirty */ + NInoSetDirty(ni); + ntfs_inode_sync(ni); /* useful ? */ + return (res); +} + +/* + * Upgrade the security descriptor of a file + * This is intended to allow graceful upgrades for files which + * were created in previous versions, with a security attributes + * and no security id. + * + * It will allocate a security id and replace the individual + * security attribute by a reference to the global one + * + * Special files are not upgraded (currently / and files in + * directories /$*) + * + * Though most code is similar to update_secur_desc() it has + * been kept apart to facilitate the further processing of + * special cases or even to remove it if found dangerous. + * + * returns 0 if success, + * 1 if not upgradable. This is not an error. + * -1 if there is a problem + */ + +static int upgrade_secur_desc(ntfs_volume *vol, const char *path, + const char *attr, ntfs_inode *ni) +{ + int attrsz; + int res; + le32 securid; + ntfs_attr *na; + + /* + * upgrade requires NTFS format v3.x + * also refuse upgrading for special files + */ + + if ((vol->major_ver >= 3) + && (path[0] == '/') + && (path[1] != '$') && (path[1] != '\0')) { + attrsz = ntfs_attr_size(attr); + securid = setsecurityattr(vol, + (const SECURITY_DESCRIPTOR_RELATIVE*)attr, + (s64)attrsz); + if (securid) { + na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, + AT_UNNAMED, 0); + if (na) { + res = 0; + /* expand standard information attribute to v3.x */ + res = ntfs_attr_truncate(na, + (s64)sizeof(STANDARD_INFORMATION)); + ni->owner_id = const_cpu_to_le32(0); + ni->quota_charged = const_cpu_to_le64(0); + ni->usn = const_cpu_to_le64(0); + ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, + AT_UNNAMED, 0); + set_nino_flag(ni, v3_Extensions); + ni->security_id = securid; + ntfs_attr_close(na); + } else { + ntfs_log_error("Failed to upgrade " + "standard informations\n"); + errno = EIO; + res = -1; + } + } else + res = -1; + /* mark node as dirty */ + NInoSetDirty(ni); + ntfs_inode_sync(ni); /* useful ? */ + } else + res = 1; + + return (res); +} + +/* + * Optional simplified checking of group membership + * + * This only takes into account the groups defined in + * /etc/group at initialization time. + * It does not take into account the groups dynamically set by + * setgroups() nor the changes in /etc/group since initialization + * + * This optional method could be useful if standard checking + * leads to a performance concern. + * + * Should not be called for user root, however the group may be root + * + */ + +static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) +{ + BOOL ingroup; + int grcnt; + gid_t *groups; + struct MAPPING *user; + + ingroup = FALSE; + if (uid) { + user = scx->mapping[MAPUSERS]; + while (user && ((uid_t)user->xid != uid)) + user = user->next; + if (user) { + groups = user->groups; + grcnt = user->grcnt; + while ((--grcnt >= 0) && (groups[grcnt] != gid)) { } + ingroup = (grcnt >= 0); + } + } + return (ingroup); +} + + +/* + * Check whether current thread owner is member of file group + * + * Should not be called for user root, however the group may be root + * + * As indicated by Miklos Szeredi : + * + * The group list is available in + * + * /proc/$PID/task/$TID/status + * + * and fuse supplies TID in get_fuse_context()->pid. The only problem is + * finding out PID, for which I have no good solution, except to iterate + * through all processes. This is rather slow, but may be speeded up + * with caching and heuristics (for single threaded programs PID = TID). + * + * The following implementation gets the group list from + * /proc/$TID/task/$TID/status which apparently exists and + * contains the same data. + */ + +static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) +{ + static char key[] = "\nGroups:"; + char buf[BUFSZ+1]; + char filename[64]; + enum { INKEY, INSEP, INNUM, INEND } state; + int fd; + char c; + int matched; + BOOL ismember; + int got; + char *p; + gid_t grp; + pid_t tid; + + if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS)) + ismember = staticgroupmember(scx, uid, gid); + else { + ismember = FALSE; /* default return */ + tid = scx->tid; + sprintf(filename,"/proc/%u/task/%u/status",tid,tid); + fd = open(filename,O_RDONLY); + if (fd >= 0) { + got = read(fd, buf, BUFSZ); + buf[got] = 0; + state = INKEY; + matched = 0; + p = buf; + grp = 0; + /* + * A simple automaton to process lines like + * Groups: 14 500 513 + */ + do { + c = *p++; + if (!c) { + /* refill buffer */ + got = read(fd, buf, BUFSZ); + buf[got] = 0; + p = buf; + c = *p++; /* 0 at end of file */ + } + switch (state) { + case INKEY : + if (key[matched] == c) { + if (!key[++matched]) + state = INSEP; + } else + if (key[0] == c) + matched = 1; + else + matched = 0; + break; + case INSEP : + if ((c >= '0') && (c <= '9')) { + grp = c - '0'; + state = INNUM; + } else + if ((c != ' ') && (c != '\t')) + state = INEND; + break; + case INNUM : + if ((c >= '0') && (c <= '9')) + grp = grp*10 + c - '0'; + else { + ismember = (grp == gid); + if ((c != ' ') && (c != '\t')) + state = INEND; + else + state = INSEP; + } + default : + break; + } + } while (!ismember && c && (state != INEND)); + close(fd); + if (!c) + ntfs_log_error("No group record found in %s\n",filename); + } else + ntfs_log_error("Could not open %s\n",filename); + } + return (ismember); +} + +/* + * Cacheing is done two-way : + * - from uid, gid and perm to securid (CACHED_SECURID) + * - from a securid to uid, gid and perm (CACHED_PERMISSIONS) + * + * CACHED_SECURID data is kept in a most-recent-first list + * which should not be too long to be efficient. Its optimal + * size is depends on usage and is hard to determine. + * + * CACHED_PERMISSIONS data is kept in a two-level indexed array. It + * is optimal at the expense of storage. Use of a most-recent-first + * list would save memory and provide similar performances for + * standard usage, but not for file servers with too many file + * owners + * + * CACHED_PERMISSIONS_LEGACY is a special case for CACHED_PERMISSIONS + * for legacy directories which were not allocated a security_id + * it is organized in a most-recent-first list. + * + * In main caches, data is never invalidated, as the meaning of + * a security_id only changes when user mapping is changed, which + * current implies remounting. However returned entries may be + * overwritten at next update, so data has to be copied elsewhere + * before another cache update is made. + * In legacy cache, data has to be invalidated when protection is + * changed. + * + * Though the same data may be found in both list, they + * must be kept separately : the interpretation of ACL + * in both direction are approximations which could be non + * reciprocal for some configuration of the user mapping data + * + * During the process of recompiling ntfs-3g from a tgz archive, + * security processing added 7.6% to the cpu time used by ntfs-3g + * and 30% if the cache is disabled. + */ + +static struct PERMISSIONS_CACHE *create_caches(struct SECURITY_CONTEXT *scx, + u32 securindex) +{ + struct PERMISSIONS_CACHE *cache; + unsigned int index1; + unsigned int i; + + cache = (struct PERMISSIONS_CACHE*)NULL; + /* create the first permissions blocks */ + index1 = securindex >> CACHE_PERMISSIONS_BITS; + cache = (struct PERMISSIONS_CACHE*) + ntfs_malloc(sizeof(struct PERMISSIONS_CACHE) + + index1*sizeof(struct CACHED_PERMISSIONS*)); + if (cache) { + cache->head.last = index1; + cache->head.p_reads = 0; + cache->head.p_hits = 0; + cache->head.p_writes = 0; + *scx->pseccache = cache; + for (i=0; i<=index1; i++) + cache->cachetable[i] + = (struct CACHED_PERMISSIONS*)NULL; + } + return (cache); +} + +/* + * Free memory used by caches + * The only purpose is to facilitate the detection of memory leaks + */ + +static void free_caches(struct SECURITY_CONTEXT *scx) +{ + unsigned int index1; + struct PERMISSIONS_CACHE *pseccache; + + pseccache = *scx->pseccache; + if (pseccache) { + for (index1=0; index1<=pseccache->head.last; index1++) + if (pseccache->cachetable[index1]) { +#if POSIXACLS + struct CACHED_PERMISSIONS *cacheentry; + unsigned int index2; + + for (index2=0; index2<(1<< CACHE_PERMISSIONS_BITS); index2++) { + cacheentry = &pseccache->cachetable[index1][index2]; + if (cacheentry->valid + && cacheentry->pxdesc) + free(cacheentry->pxdesc); + } +#endif + free(pseccache->cachetable[index1]); + } + free(pseccache); + } +} + +static int compare(const struct CACHED_SECURID *cached, + const struct CACHED_SECURID *item) +{ +#if POSIXACLS + size_t csize; + size_t isize; + + /* only compare data and sizes */ + csize = (cached->variable ? + sizeof(struct POSIX_ACL) + + (((struct POSIX_SECURITY*)cached->variable)->acccnt + + ((struct POSIX_SECURITY*)cached->variable)->defcnt) + *sizeof(struct POSIX_ACE) : + 0); + isize = (item->variable ? + sizeof(struct POSIX_ACL) + + (((struct POSIX_SECURITY*)item->variable)->acccnt + + ((struct POSIX_SECURITY*)item->variable)->defcnt) + *sizeof(struct POSIX_ACE) : + 0); + return ((cached->uid != item->uid) + || (cached->gid != item->gid) + || (cached->dmode != item->dmode) + || (csize != isize) + || (csize + && isize + && memcmp(&((struct POSIX_SECURITY*)cached->variable)->acl, + &((struct POSIX_SECURITY*)item->variable)->acl, csize))); +#else + return ((cached->uid != item->uid) + || (cached->gid != item->gid) + || (cached->dmode != item->dmode)); +#endif +} + +static int leg_compare(const struct CACHED_PERMISSIONS_LEGACY *cached, + const struct CACHED_PERMISSIONS_LEGACY *item) +{ + return (cached->mft_no != item->mft_no); +} + +/* + * Resize permission cache table + * do not call unless resizing is needed + * + * If allocation fails, the cache size is not updated + * Lack of memory is not considered as an error, the cache is left + * consistent and errno is not set. + */ + +static void resize_cache(struct SECURITY_CONTEXT *scx, + u32 securindex) +{ + struct PERMISSIONS_CACHE *oldcache; + struct PERMISSIONS_CACHE *newcache; + int newcnt; + int oldcnt; + unsigned int index1; + unsigned int i; + + oldcache = *scx->pseccache; + index1 = securindex >> CACHE_PERMISSIONS_BITS; + newcnt = index1 + 1; + if (newcnt <= ((CACHE_PERMISSIONS_SIZE + + (1 << CACHE_PERMISSIONS_BITS) + - 1) >> CACHE_PERMISSIONS_BITS)) { + /* expand cache beyond current end, do not use realloc() */ + /* to avoid losing data when there is no more memory */ + oldcnt = oldcache->head.last + 1; + newcache = (struct PERMISSIONS_CACHE*) + ntfs_malloc( + sizeof(struct PERMISSIONS_CACHE) + + (newcnt - 1)*sizeof(struct CACHED_PERMISSIONS*)); + if (newcache) { + memcpy(newcache,oldcache, + sizeof(struct PERMISSIONS_CACHE) + + (oldcnt - 1)*sizeof(struct CACHED_PERMISSIONS*)); + free(oldcache); + /* mark new entries as not valid */ + for (i=newcache->head.last+1; i<=index1; i++) + newcache->cachetable[i] + = (struct CACHED_PERMISSIONS*)NULL; + newcache->head.last = index1; + *scx->pseccache = newcache; + } + } +} + +/* + * Enter uid, gid and mode into cache, if possible + * + * returns the updated or created cache entry, + * or NULL if not possible (typically if there is no + * security id associated) + */ + +#if POSIXACLS +static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, + struct POSIX_SECURITY *pxdesc) +#else +static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode) +#endif +{ + struct CACHED_PERMISSIONS *cacheentry; + struct CACHED_PERMISSIONS *cacheblock; + struct PERMISSIONS_CACHE *pcache; + u32 securindex; +#if POSIXACLS + int pxsize; + struct POSIX_SECURITY *pxcached; +#endif + unsigned int index1; + unsigned int index2; + int i; + + /* cacheing is only possible if a security_id has been defined */ + if (test_nino_flag(ni, v3_Extensions) + && ni->security_id) { + /* + * Immediately test the most frequent situation + * where the entry exists + */ + securindex = le32_to_cpu(ni->security_id); + index1 = securindex >> CACHE_PERMISSIONS_BITS; + index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1); + pcache = *scx->pseccache; + if (pcache + && (pcache->head.last >= index1) + && pcache->cachetable[index1]) { + cacheentry = &pcache->cachetable[index1][index2]; + cacheentry->uid = uid; + cacheentry->gid = gid; +#if POSIXACLS + if (cacheentry->valid && cacheentry->pxdesc) + free(cacheentry->pxdesc); + if (pxdesc) { + pxsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + pxcached = (struct POSIX_SECURITY*)malloc(pxsize); + if (pxcached) { + memcpy(pxcached, pxdesc, pxsize); + cacheentry->pxdesc = pxcached; + } else { + cacheentry->valid = 0; + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + } + cacheentry->mode = pxdesc->mode & 07777; + } else + cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL; +#else + cacheentry->mode = mode & 07777; +#endif + cacheentry->inh_fileid = const_cpu_to_le32(0); + cacheentry->inh_dirid = const_cpu_to_le32(0); + cacheentry->valid = 1; + pcache->head.p_writes++; + } else { + if (!pcache) { + /* create the first cache block */ + pcache = create_caches(scx, securindex); + } else { + if (index1 > pcache->head.last) { + resize_cache(scx, securindex); + pcache = *scx->pseccache; + } + } + /* allocate block, if cache table was allocated */ + if (pcache && (index1 <= pcache->head.last)) { + cacheblock = (struct CACHED_PERMISSIONS*) + malloc(sizeof(struct CACHED_PERMISSIONS) + << CACHE_PERMISSIONS_BITS); + pcache->cachetable[index1] = cacheblock; + for (i=0; i<(1 << CACHE_PERMISSIONS_BITS); i++) + cacheblock[i].valid = 0; + cacheentry = &cacheblock[index2]; + if (cacheentry) { + cacheentry->uid = uid; + cacheentry->gid = gid; +#if POSIXACLS + if (pxdesc) { + pxsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + pxcached = (struct POSIX_SECURITY*)malloc(pxsize); + if (pxcached) { + memcpy(pxcached, pxdesc, pxsize); + cacheentry->pxdesc = pxcached; + } else { + cacheentry->valid = 0; + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + } + cacheentry->mode = pxdesc->mode & 07777; + } else + cacheentry->pxdesc = (struct POSIX_SECURITY*)NULL; +#else + cacheentry->mode = mode & 07777; +#endif + cacheentry->inh_fileid = const_cpu_to_le32(0); + cacheentry->inh_dirid = const_cpu_to_le32(0); + cacheentry->valid = 1; + pcache->head.p_writes++; + } + } else + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + } + } else { + cacheentry = (struct CACHED_PERMISSIONS*)NULL; +#if CACHE_LEGACY_SIZE + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + struct CACHED_PERMISSIONS_LEGACY wanted; + struct CACHED_PERMISSIONS_LEGACY *legacy; + + wanted.perm.uid = uid; + wanted.perm.gid = gid; +#if POSIXACLS + wanted.perm.mode = pxdesc->mode & 07777; + wanted.perm.inh_fileid = const_cpu_to_le32(0); + wanted.perm.inh_dirid = const_cpu_to_le32(0); + wanted.mft_no = ni->mft_no; + wanted.variable = (void*)pxdesc; + wanted.varsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); +#else + wanted.perm.mode = mode & 07777; + wanted.perm.inh_fileid = const_cpu_to_le32(0); + wanted.perm.inh_dirid = const_cpu_to_le32(0); + wanted.mft_no = ni->mft_no; + wanted.variable = (void*)NULL; + wanted.varsize = 0; +#endif + legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_enter_cache( + scx->vol->legacy_cache, GENERIC(&wanted), + (cache_compare)leg_compare); + if (legacy) { + cacheentry = &legacy->perm; +#if POSIXACLS + /* + * give direct access to the cached pxdesc + * in the permissions structure + */ + cacheentry->pxdesc = legacy->variable; +#endif + } + } +#endif + } + return (cacheentry); +} + +/* + * Fetch owner, group and permission of a file, if cached + * + * Beware : do not use the returned entry after a cache update : + * the cache may be relocated making the returned entry meaningless + * + * returns the cache entry, or NULL if not available + */ + +static struct CACHED_PERMISSIONS *fetch_cache(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni) +{ + struct CACHED_PERMISSIONS *cacheentry; + struct PERMISSIONS_CACHE *pcache; + u32 securindex; + unsigned int index1; + unsigned int index2; + + /* cacheing is only possible if a security_id has been defined */ + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + if (test_nino_flag(ni, v3_Extensions) + && (ni->security_id)) { + securindex = le32_to_cpu(ni->security_id); + index1 = securindex >> CACHE_PERMISSIONS_BITS; + index2 = securindex & ((1 << CACHE_PERMISSIONS_BITS) - 1); + pcache = *scx->pseccache; + if (pcache + && (pcache->head.last >= index1) + && pcache->cachetable[index1]) { + cacheentry = &pcache->cachetable[index1][index2]; + /* reject if entry is not valid */ + if (!cacheentry->valid) + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + else + pcache->head.p_hits++; + if (pcache) + pcache->head.p_reads++; + } + } +#if CACHE_LEGACY_SIZE + else { + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + struct CACHED_PERMISSIONS_LEGACY wanted; + struct CACHED_PERMISSIONS_LEGACY *legacy; + + wanted.mft_no = ni->mft_no; + wanted.variable = (void*)NULL; + wanted.varsize = 0; + legacy = (struct CACHED_PERMISSIONS_LEGACY*)ntfs_fetch_cache( + scx->vol->legacy_cache, GENERIC(&wanted), + (cache_compare)leg_compare); + if (legacy) cacheentry = &legacy->perm; + } + } +#endif +#if POSIXACLS + if (cacheentry && !cacheentry->pxdesc) { + ntfs_log_error("No Posix descriptor in cache\n"); + cacheentry = (struct CACHED_PERMISSIONS*)NULL; + } +#endif + return (cacheentry); +} + +/* + * Retrieve a security attribute from $Secure + */ + +static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id) +{ + struct SII *psii; + union { + struct { + le32 dataoffsl; + le32 dataoffsh; + } parts; + le64 all; + } realign; + int found; + size_t size; + size_t rdsize; + s64 offs; + ntfs_inode *ni; + ntfs_index_context *xsii; + char *securattr; + + securattr = (char*)NULL; + ni = vol->secure_ni; + xsii = vol->secure_xsii; + if (ni && xsii) { + ntfs_index_ctx_reinit(xsii); + found = + !ntfs_index_lookup((char*)&id, + sizeof(SII_INDEX_KEY), xsii); + if (found) { + psii = (struct SII*)xsii->entry; + size = + (size_t) le32_to_cpu(psii->datasize) + - sizeof(SECURITY_DESCRIPTOR_HEADER); + /* work around bad alignment problem */ + realign.parts.dataoffsh = psii->dataoffsh; + realign.parts.dataoffsl = psii->dataoffsl; + offs = le64_to_cpu(realign.all) + + sizeof(SECURITY_DESCRIPTOR_HEADER); + + securattr = (char*)ntfs_malloc(size); + if (securattr) { + rdsize = ntfs_local_read( + ni, STREAM_SDS, 4, + securattr, size, offs); + if ((rdsize != size) + || !ntfs_valid_descr(securattr, + rdsize)) { + /* error to be logged by caller */ + free(securattr); + securattr = (char*)NULL; + } + } + } else + if (errno != ENOENT) + ntfs_log_perror("Inconsistency in index $SII"); + } + if (!securattr) { + ntfs_log_error("Failed to retrieve a security descriptor\n"); + errno = EIO; + } + return (securattr); +} + +/* + * Get the security descriptor associated to a file + * + * Either : + * - read the security descriptor attribute (v1.x format) + * - or find the descriptor in $Secure:$SDS (v3.x format) + * + * in both case, sanity checks are done on the attribute and + * the descriptor can be assumed safe + * + * The returned descriptor is dynamically allocated and has to be freed + */ + +static char *getsecurityattr(ntfs_volume *vol, + const char *path, ntfs_inode *ni) +{ + SII_INDEX_KEY securid; + char *securattr; + s64 readallsz; + + /* + * Warning : in some situations, after fixing by chkdsk, + * v3_Extensions are marked present (long standard informations) + * with a default security descriptor inserted in an + * attribute + */ + if (test_nino_flag(ni, v3_Extensions) + && vol->secure_ni && ni->security_id) { + /* get v3.x descriptor in $Secure */ + securid.security_id = ni->security_id; + securattr = retrievesecurityattr(vol,securid); + if (!securattr) + ntfs_log_error("Bad security descriptor for 0x%lx\n", + (long)le32_to_cpu(ni->security_id)); + } else { + /* get v1.x security attribute */ + readallsz = 0; + securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR, + AT_UNNAMED, 0, &readallsz); + if (securattr && !ntfs_valid_descr(securattr, readallsz)) { + ntfs_log_error("Bad security descriptor for %s\n", + path); + free(securattr); + securattr = (char*)NULL; + } + } + if (!securattr) { + /* + * in some situations, there is no security + * descriptor, and chkdsk does not detect or fix + * anything. This could be a normal situation. + * When this happens, simulate a descriptor with + * minimum rights, so that a real descriptor can + * be created by chown or chmod + */ + ntfs_log_error("No security descriptor found for %s\n",path); + securattr = ntfs_build_descr(0, 0, adminsid, adminsid); + } + return (securattr); +} + +#if POSIXACLS + +/* + * Determine which access types to a file are allowed + * according to the relation of current process to the file + * + * Do not call if default_permissions is set + */ + +static int access_check_posix(struct SECURITY_CONTEXT *scx, + struct POSIX_SECURITY *pxdesc, mode_t request, + uid_t uid, gid_t gid) +{ + struct POSIX_ACE *pxace; + int userperms; + int groupperms; + int mask; + BOOL somegroup; + mode_t perms; + int i; + + perms = pxdesc->mode; + /* owner and root access */ + if (!scx->uid || (uid == scx->uid)) { + if (!scx->uid) { + /* root access if owner or other execution */ + if (perms & 0101) + perms = 07777; + else { + /* root access if some group execution */ + groupperms = 0; + mask = 7; + for (i=pxdesc->acccnt-1; i>=0 ; i--) { + pxace = &pxdesc->acl.ace[i]; + switch (pxace->tag) { + case POSIX_ACL_USER_OBJ : + case POSIX_ACL_GROUP_OBJ : + case POSIX_ACL_GROUP : + groupperms |= pxace->perms; + break; + case POSIX_ACL_MASK : + mask = pxace->perms & 7; + break; + default : + break; + } + } + perms = (groupperms & mask & 1) | 6; + } + } else + perms &= 07700; + } else { + /* analyze designated users and get mask */ + userperms = -1; + groupperms = -1; + mask = 7; + for (i=pxdesc->acccnt-1; i>=0 ; i--) { + pxace = &pxdesc->acl.ace[i]; + switch (pxace->tag) { + case POSIX_ACL_USER : + if ((uid_t)pxace->id == scx->uid) + userperms = pxace->perms; + break; + case POSIX_ACL_MASK : + mask = pxace->perms & 7; + break; + default : + break; + } + } + /* designated users */ + if (userperms >= 0) + perms = (perms & 07000) + (userperms & mask); + else { + /* owning group */ + if (!(~(perms >> 3) & request & mask) + && ((gid == scx->gid) + || groupmember(scx, scx->uid, gid))) + perms &= 07070; + else { + /* other groups */ + groupperms = -1; + somegroup = FALSE; + for (i=pxdesc->acccnt-1; i>=0 ; i--) { + pxace = &pxdesc->acl.ace[i]; + if ((pxace->tag == POSIX_ACL_GROUP) + && groupmember(scx, uid, pxace->id)) { + if (!(~pxace->perms & request & mask)) + groupperms = pxace->perms; + somegroup = TRUE; + } + } + if (groupperms >= 0) + perms = (perms & 07000) + (groupperms & mask); + else + if (somegroup) + perms = 0; + else + perms &= 07007; + } + } + } + return (perms); +} + +/* + * Get permissions to access a file + * Takes into account the relation of user to file (owner, group, ...) + * Do no use as mode of the file + * Do no call if default_permissions is set + * + * returns -1 if there is a problem + */ + +static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode * ni, mode_t request) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const struct CACHED_PERMISSIONS *cached; + char *securattr; + const SID *usid; /* owner of file/directory */ + const SID *gsid; /* group of file/directory */ + uid_t uid; + gid_t gid; + int perm; + BOOL isdir; + struct POSIX_SECURITY *pxdesc; + + if (!scx->mapping[MAPUSERS]) + perm = 07777; + else { + /* check whether available in cache */ + cached = fetch_cache(scx,ni); + if (cached) { + uid = cached->uid; + gid = cached->gid; + perm = access_check_posix(scx,cached->pxdesc,request,uid,gid); + } else { + perm = 0; /* default to no permission */ + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + securattr = getsecurityattr(scx->vol, path, ni); + if (securattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*) + securattr; + gsid = (const SID*)& + securattr[le32_to_cpu(phead->group)]; + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); +#if OWNERFROMACL + usid = ntfs_acl_owner(securattr); + pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, + usid, gsid, isdir); + if (pxdesc) + perm = pxdesc->mode & 07777; + else + perm = -1; + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#else + usid = (const SID*)& + securattr[le32_to_cpu(phead->owner)]; + pxdesc = ntfs_build_permissions_posix(scx,securattr, + usid, gsid, isdir); + if (pxdesc) + perm = pxdesc->mode & 07777; + else + perm = -1; + if (!perm && ntfs_same_sid(usid, adminsid)) { + uid = find_tenant(scx, securattr); + if (uid) + perm = 0700; + } else + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#endif + /* + * Create a security id if there were none + * and upgrade option is selected + */ + if (!test_nino_flag(ni, v3_Extensions) + && (perm >= 0) + && (scx->vol->secure_flags + & (1 << SECURITY_ADDSECURIDS))) { + upgrade_secur_desc(scx->vol, path, + securattr, ni); + /* + * fetch owner and group for cacheing + * if there is a securid + */ + } + if (test_nino_flag(ni, v3_Extensions) + && (perm >= 0)) { + enter_cache(scx, ni, uid, + gid, pxdesc); + } + if (pxdesc) { + perm = access_check_posix(scx,pxdesc,request,uid,gid); + free(pxdesc); + } + free(securattr); + } else { + perm = -1; + uid = gid = 0; + } + } + } + return (perm); +} + +/* + * Get a Posix ACL + * + * returns size or -errno if there is a problem + * if size was too small, no copy is done and errno is not set, + * the caller is expected to issue a new call + */ + +int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, char *value, size_t size, + ntfs_inode *ni) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + struct POSIX_SECURITY *pxdesc; + const struct CACHED_PERMISSIONS *cached; + char *securattr; + const SID *usid; /* owner of file/directory */ + const SID *gsid; /* group of file/directory */ + uid_t uid; + gid_t gid; + int perm; + BOOL isdir; + size_t outsize; + + outsize = 0; /* default to error */ + if (!scx->mapping[MAPUSERS]) + errno = ENOTSUP; + else { + /* check whether available in cache */ + cached = fetch_cache(scx,ni); + if (cached) + pxdesc = cached->pxdesc; + else { + securattr = getsecurityattr(scx->vol, path, ni); + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + if (securattr) { + phead = + (const SECURITY_DESCRIPTOR_RELATIVE*) + securattr; + gsid = (const SID*)& + securattr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + usid = ntfs_acl_owner(securattr); +#else + usid = (const SID*)& + securattr[le32_to_cpu(phead->owner)]; +#endif + pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, + usid, gsid, isdir); + + /* + * fetch owner and group for cacheing + */ + if (pxdesc) { + perm = pxdesc->mode & 07777; + /* + * Create a security id if there were none + * and upgrade option is selected + */ + if (!test_nino_flag(ni, v3_Extensions) + && (scx->vol->secure_flags + & (1 << SECURITY_ADDSECURIDS))) { + upgrade_secur_desc(scx->vol, + path, securattr, ni); + } +#if OWNERFROMACL + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#else + if (!perm && ntfs_same_sid(usid, adminsid)) { + uid = find_tenant(scx, + securattr); + if (uid) + perm = 0700; + } else + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#endif + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + if (pxdesc->tagsset & POSIX_ACL_EXTENSIONS) + enter_cache(scx, ni, uid, + gid, pxdesc); + } + free(securattr); + } else + pxdesc = (struct POSIX_SECURITY*)NULL; + } + + if (pxdesc) { + if (ntfs_valid_posix(pxdesc)) { + if (!strcmp(name,"system.posix_acl_default")) { + if (ni->mrec->flags + & MFT_RECORD_IS_DIRECTORY) + outsize = sizeof(struct POSIX_ACL) + + pxdesc->defcnt*sizeof(struct POSIX_ACE); + else { + /* + * getting default ACL from plain file : + * return EACCES if size > 0 as + * indicated in the man, but return ok + * if size == 0, so that ls does not + * display an error + */ + if (size > 0) { + outsize = 0; + errno = EACCES; + } else + outsize = sizeof(struct POSIX_ACL); + } + if (outsize && (outsize <= size)) { + memcpy(value,&pxdesc->acl,sizeof(struct POSIX_ACL)); + memcpy(&value[sizeof(struct POSIX_ACL)], + &pxdesc->acl.ace[pxdesc->firstdef], + outsize-sizeof(struct POSIX_ACL)); + } + } else { + outsize = sizeof(struct POSIX_ACL) + + pxdesc->acccnt*sizeof(struct POSIX_ACE); + if (outsize <= size) + memcpy(value,&pxdesc->acl,outsize); + } + } else { + outsize = 0; + errno = EIO; + ntfs_log_error("Invalid Posix ACL built\n"); + } + if (!cached) + free(pxdesc); + } else + outsize = 0; + } + return (outsize ? (int)outsize : -errno); +} + +#else /* POSIXACLS */ + + +/* + * Get permissions to access a file + * Takes into account the relation of user to file (owner, group, ...) + * Do no use as mode of the file + * + * returns -1 if there is a problem + * + * This is only used for checking creation of DOS file names + */ + +static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, + mode_t request __attribute__((unused))) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const struct CACHED_PERMISSIONS *cached; + char *securattr; + const SID *usid; /* owner of file/directory */ + const SID *gsid; /* group of file/directory */ + BOOL isdir; + uid_t uid; + gid_t gid; + int perm; + + if (!scx->mapping[MAPUSERS] || !scx->uid) + perm = 07777; + else { + /* check whether available in cache */ + cached = fetch_cache(scx,ni); + if (cached) { + perm = cached->mode; + uid = cached->uid; + gid = cached->gid; + } else { + perm = 0; /* default to no permission */ + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + securattr = getsecurityattr(scx->vol, path, ni); + if (securattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*) + securattr; + gsid = (const SID*)& + securattr[le32_to_cpu(phead->group)]; + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); +#if OWNERFROMACL + usid = ntfs_acl_owner(securattr); + perm = ntfs_build_permissions(securattr, + usid, gsid, isdir); + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#else + usid = (const SID*)& + securattr[le32_to_cpu(phead->owner)]; + perm = ntfs_build_permissions(securattr, + usid, gsid, isdir); + if (!perm && ntfs_same_sid(usid, adminsid)) { + uid = find_tenant(scx, securattr); + if (uid) + perm = 0700; + } else + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#endif + /* + * Create a security id if there were none + * and upgrade option is selected + */ + if (!test_nino_flag(ni, v3_Extensions) + && (perm >= 0) + && (scx->vol->secure_flags + & (1 << SECURITY_ADDSECURIDS))) { + upgrade_secur_desc(scx->vol, path, + securattr, ni); + /* + * fetch owner and group for cacheing + * if there is a securid + */ + } + if (test_nino_flag(ni, v3_Extensions) + && (perm >= 0)) { + enter_cache(scx, ni, uid, + gid, perm); + } + free(securattr); + } else { + perm = -1; + uid = gid = 0; + } + } + if (perm >= 0) { + if (uid == scx->uid) + perm &= 07700; + else + if ((gid == scx->gid) + || groupmember(scx, scx->uid, gid)) + perm &= 07070; + else + perm &= 07007; + } + } + return (perm); +} + +#endif /* POSIXACLS */ + +/* + * Get an NTFS ACL + * + * Returns size or -errno if there is a problem + * if size was too small, no copy is done and errno is not set, + * the caller is expected to issue a new call + */ + +int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name __attribute__((unused)), + char *value, size_t size, ntfs_inode *ni) +{ + char *securattr; + size_t outsize; + + outsize = 0; /* default to no data and no error */ + securattr = getsecurityattr(scx->vol, path, ni); + if (securattr) { + outsize = ntfs_attr_size(securattr); + if (outsize <= size) { + memcpy(value,securattr,outsize); + } + free(securattr); + } + return (outsize ? (int)outsize : -errno); +} + +/* + * Get owner, group and permissions in an stat structure + * returns permissions, or -1 if there is a problem + */ + +int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode * ni, + struct stat *stbuf) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + char *securattr; + const SID *usid; /* owner of file/directory */ + const SID *gsid; /* group of file/directory */ + const struct CACHED_PERMISSIONS *cached; + int perm; + BOOL isdir; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + + if (!scx->mapping[MAPUSERS]) + perm = 07777; + else { + /* check whether available in cache */ + cached = fetch_cache(scx,ni); + if (cached) { + perm = cached->mode; + stbuf->st_uid = cached->uid; + stbuf->st_gid = cached->gid; + stbuf->st_mode = (stbuf->st_mode & ~07777) + perm; + } else { + perm = -1; /* default to error */ + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + securattr = getsecurityattr(scx->vol, path, ni); + if (securattr) { + phead = + (const SECURITY_DESCRIPTOR_RELATIVE*) + securattr; + gsid = (const SID*)& + securattr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + usid = ntfs_acl_owner(securattr); +#else + usid = (const SID*)& + securattr[le32_to_cpu(phead->owner)]; +#endif +#if POSIXACLS + pxdesc = ntfs_build_permissions_posix(scx->mapping, securattr, + usid, gsid, isdir); + if (pxdesc) + perm = pxdesc->mode & 07777; + else + perm = -1; +#else + perm = ntfs_build_permissions(securattr, + usid, gsid, isdir); +#endif + /* + * fetch owner and group for cacheing + */ + if (perm >= 0) { + /* + * Create a security id if there were none + * and upgrade option is selected + */ + if (!test_nino_flag(ni, v3_Extensions) + && (scx->vol->secure_flags + & (1 << SECURITY_ADDSECURIDS))) { + upgrade_secur_desc(scx->vol, + path, securattr, ni); + } +#if OWNERFROMACL + stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#else + if (!perm && ntfs_same_sid(usid, adminsid)) { + stbuf->st_uid = + find_tenant(scx, + securattr); + if (stbuf->st_uid) + perm = 0700; + } else + stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#endif + stbuf->st_gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + stbuf->st_mode = + (stbuf->st_mode & ~07777) + perm; +#if POSIXACLS + enter_cache(scx, ni, stbuf->st_uid, + stbuf->st_gid, pxdesc); + free(pxdesc); +#else + enter_cache(scx, ni, stbuf->st_uid, + stbuf->st_gid, perm); +#endif + } + free(securattr); + } + } + } + return (perm); +} + +#if POSIXACLS + +/* + * Get the base for a Posix inheritance and + * build an inherited Posix descriptor + */ + +static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, + const char *dir_path, ntfs_inode *dir_ni, + mode_t mode, BOOL isdir) +{ + const struct CACHED_PERMISSIONS *cached; + const SECURITY_DESCRIPTOR_RELATIVE *phead; + struct POSIX_SECURITY *pxdesc; + struct POSIX_SECURITY *pydesc; + char *securattr; + const SID *usid; + const SID *gsid; + uid_t uid; + gid_t gid; + + pydesc = (struct POSIX_SECURITY*)NULL; + /* check whether parent directory is available in cache */ + cached = fetch_cache(scx,dir_ni); + if (cached) { + uid = cached->uid; + gid = cached->gid; + pxdesc = cached->pxdesc; + if (pxdesc) { + pydesc = ntfs_build_inherited_posix(pxdesc,mode, + scx->umask,isdir); + } + } else { + securattr = getsecurityattr(scx->vol, dir_path, dir_ni); + if (securattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*) + securattr; + gsid = (const SID*)& + securattr[le32_to_cpu(phead->group)]; + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); +#if OWNERFROMACL + usid = ntfs_acl_owner(securattr); + pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, + usid, gsid, TRUE); + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#else + usid = (const SID*)& + securattr[le32_to_cpu(phead->owner)]; + pxdesc = ntfs_build_permissions_posix(scx->mapping,securattr, + usid, gsid, TRUE); + if (pxdesc && ntfs_same_sid(usid, adminsid)) { + uid = find_tenant(scx, securattr); + } else + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); +#endif + if (pxdesc) { + /* + * Create a security id if there were none + * and upgrade option is selected + */ + if (!test_nino_flag(dir_ni, v3_Extensions) + && (scx->vol->secure_flags + & (1 << SECURITY_ADDSECURIDS))) { + upgrade_secur_desc(scx->vol, dir_path, + securattr, dir_ni); + /* + * fetch owner and group for cacheing + * if there is a securid + */ + } + if (test_nino_flag(dir_ni, v3_Extensions)) { + enter_cache(scx, dir_ni, uid, + gid, pxdesc); + } + pydesc = ntfs_build_inherited_posix(pxdesc, + mode, scx->umask, isdir); + free(pxdesc); + } + free(securattr); + } + } + return (pydesc); +} + +/* + * Allocate a security_id for a file being created + * + * Returns zero if not possible (NTFS v3.x required) + */ + +le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, + uid_t uid, gid_t gid, const char *dir_path, + ntfs_inode *dir_ni, mode_t mode, BOOL isdir) +{ +#if !FORCE_FORMAT_v1x + const struct CACHED_SECURID *cached; + struct CACHED_SECURID wanted; + struct POSIX_SECURITY *pxdesc; + char *newattr; + int newattrsz; + const SID *usid; + const SID *gsid; + BIGSID defusid; + BIGSID defgsid; + le32 securid; +#endif + + securid = const_cpu_to_le32(0); + +#if !FORCE_FORMAT_v1x + + pxdesc = inherit_posix(scx, dir_path, dir_ni, mode, isdir); + if (pxdesc) { + /* check whether target securid is known in cache */ + + wanted.uid = uid; + wanted.gid = gid; + wanted.dmode = pxdesc->mode & mode & 07777; + if (isdir) wanted.dmode |= 0x10000; + wanted.variable = (void*)pxdesc; + wanted.varsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( + scx->vol->securid_cache, GENERIC(&wanted), + (cache_compare)compare); + /* quite simple, if we are lucky */ + if (cached) + securid = cached->securid; + + /* not in cache : make sure we can create ids */ + + if (!cached && (scx->vol->major_ver >= 3)) { + usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); + gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); + if (!usid || !gsid) { + ntfs_log_error("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); + usid = gsid = adminsid; + } + newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, + isdir, usid, gsid); + if (newattr) { + newattrsz = ntfs_attr_size(newattr); + securid = setsecurityattr(scx->vol, + (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, + newattrsz); + if (securid) { + /* update cache, for subsequent use */ + wanted.securid = securid; + ntfs_enter_cache(scx->vol->securid_cache, + GENERIC(&wanted), + (cache_compare)compare); + } + free(newattr); + } else { + /* + * could not build new security attribute + * errno set by ntfs_build_descr() + */ + } + } + free(pxdesc); + } +#endif + return (securid); +} + +/* + * Apply Posix inheritance to a newly created file + * (for NTFS 1.x only : no securid) + */ + +int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, uid_t uid, gid_t gid, + const char *dir_path, ntfs_inode *dir_ni, mode_t mode) +{ + struct POSIX_SECURITY *pxdesc; + char *newattr; + const SID *usid; + const SID *gsid; + BIGSID defusid; + BIGSID defgsid; + BOOL isdir; + int res; + + res = -1; + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); + pxdesc = inherit_posix(scx, dir_path, dir_ni, mode, isdir); + if (pxdesc) { + usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); + gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); + if (!usid || !gsid) { + ntfs_log_error("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); + usid = gsid = adminsid; + } + newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, + isdir, usid, gsid); + if (newattr) { + /* Adjust Windows read-only flag */ + res = update_secur_descr(scx->vol, newattr, ni); + if (!res) { + if (mode & S_IWUSR) + ni->flags &= ~FILE_ATTR_READONLY; + else + ni->flags |= FILE_ATTR_READONLY; + } +#if CACHE_LEGACY_SIZE + /* also invalidate legacy cache */ + if (isdir && !ni->security_id) { + struct CACHED_PERMISSIONS_LEGACY legacy; + + legacy.mft_no = ni->mft_no; + legacy.variable = pxdesc; + legacy.varsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + ntfs_invalidate_cache(scx->vol->legacy_cache, + GENERIC(&legacy), + (cache_compare)leg_compare); + } +#endif + free(newattr); + + } else { + /* + * could not build new security attribute + * errno set by ntfs_build_descr() + */ + } + } + return (res); +} + +#else + +le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, + uid_t uid, gid_t gid, mode_t mode, BOOL isdir) +{ +#if !FORCE_FORMAT_v1x + const struct CACHED_SECURID *cached; + struct CACHED_SECURID wanted; + char *newattr; + int newattrsz; + const SID *usid; + const SID *gsid; + BIGSID defusid; + BIGSID defgsid; + le32 securid; +#endif + + securid = const_cpu_to_le32(0); + +#if !FORCE_FORMAT_v1x + /* check whether target securid is known in cache */ + + wanted.uid = uid; + wanted.gid = gid; + wanted.dmode = mode & 07777; + if (isdir) wanted.dmode |= 0x10000; + wanted.variable = (void*)NULL; + wanted.varsize = 0; + cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( + scx->vol->securid_cache, GENERIC(&wanted), + (cache_compare)compare); + /* quite simple, if we are lucky */ + if (cached) + securid = cached->securid; + + /* not in cache : make sure we can create ids */ + + if (!cached && (scx->vol->major_ver >= 3)) { + usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); + gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); + if (!usid || !gsid) { + ntfs_log_error("File created by an unmapped user/group %d/%d\n", + (int)uid, (int)gid); + usid = gsid = adminsid; + } + newattr = ntfs_build_descr(mode, isdir, usid, gsid); + if (newattr) { + newattrsz = ntfs_attr_size(newattr); + securid = setsecurityattr(scx->vol, + (const SECURITY_DESCRIPTOR_RELATIVE*)newattr, + newattrsz); + if (securid) { + /* update cache, for subsequent use */ + wanted.securid = securid; + ntfs_enter_cache(scx->vol->securid_cache, + GENERIC(&wanted), + (cache_compare)compare); + } + free(newattr); + } else { + /* + * could not build new security attribute + * errno set by ntfs_build_descr() + */ + } + } +#endif + return (securid); +} + +#endif + +/* + * Update ownership and mode of a file, reusing an existing + * security descriptor when possible + * + * Returns zero if successful + */ + +#if POSIXACLS +int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + uid_t uid, gid_t gid, mode_t mode, + struct POSIX_SECURITY *pxdesc) +#else +int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + uid_t uid, gid_t gid, mode_t mode) +#endif +{ + int res; + const struct CACHED_SECURID *cached; + struct CACHED_SECURID wanted; + char *newattr; + const SID *usid; + const SID *gsid; + BIGSID defusid; + BIGSID defgsid; + BOOL isdir; + + res = 0; + + /* check whether target securid is known in cache */ + + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); + wanted.uid = uid; + wanted.gid = gid; + wanted.dmode = mode & 07777; + if (isdir) wanted.dmode |= 0x10000; +#if POSIXACLS + wanted.variable = (void*)pxdesc; + if (pxdesc) + wanted.varsize = sizeof(struct POSIX_SECURITY) + + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + else + wanted.varsize = 0; +#else + wanted.variable = (void*)NULL; + wanted.varsize = 0; +#endif + if (test_nino_flag(ni, v3_Extensions)) { + cached = (const struct CACHED_SECURID*)ntfs_fetch_cache( + scx->vol->securid_cache, GENERIC(&wanted), + (cache_compare)compare); + /* quite simple, if we are lucky */ + if (cached) { + ni->security_id = cached->securid; + NInoSetDirty(ni); + } + } else cached = (struct CACHED_SECURID*)NULL; + + if (!cached) { + /* + * Do not use usid and gsid from former attributes, + * but recompute them to get repeatable results + * which can be kept in cache. + */ + usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); + gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); + if (!usid || !gsid) { + ntfs_log_error("File made owned by an unmapped user/group %d/%d\n", + uid, gid); + usid = gsid = adminsid; + } +#if POSIXACLS + if (pxdesc) + newattr = ntfs_build_descr_posix(scx->mapping, pxdesc, + isdir, usid, gsid); + else + newattr = ntfs_build_descr(mode, + isdir, usid, gsid); +#else + newattr = ntfs_build_descr(mode, + isdir, usid, gsid); +#endif + if (newattr) { + res = update_secur_descr(scx->vol, newattr, ni); + if (!res) { + /* adjust Windows read-only flag */ + if (mode & S_IWUSR) + ni->flags &= ~FILE_ATTR_READONLY; + else + ni->flags |= FILE_ATTR_READONLY; + /* update cache, for subsequent use */ + if (test_nino_flag(ni, v3_Extensions)) { + wanted.securid = ni->security_id; + ntfs_enter_cache(scx->vol->securid_cache, + GENERIC(&wanted), + (cache_compare)compare); + } +#if CACHE_LEGACY_SIZE + /* also invalidate legacy cache */ + if (isdir && !ni->security_id) { + struct CACHED_PERMISSIONS_LEGACY legacy; + + legacy.mft_no = ni->mft_no; +#if POSIXACLS + legacy.variable = wanted.variable; + legacy.varsize = wanted.varsize; +#else + legacy.variable = (void*)NULL; + legacy.varsize = 0; +#endif + ntfs_invalidate_cache(scx->vol->legacy_cache, + GENERIC(&legacy), + (cache_compare)leg_compare); + } +#endif + } + free(newattr); + } else { + /* + * could not build new security attribute + * errno set by ntfs_build_descr() + */ + res = -1; + } + } + return (res); +} + +/* + * Check whether user has ownership rights on a file + * + * Returns TRUE if allowed + * if not, errno tells why + */ + +BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni) +{ + const struct CACHED_PERMISSIONS *cached; + char *oldattr; + const SID *usid; + uid_t processuid; + uid_t uid; + BOOL gotowner; + int allowed; + + gotowner = FALSE; /* default */ + processuid = scx->uid; + /* get the owner, either from cache or from old attribute */ + cached = fetch_cache(scx, ni); + if (cached) { + uid = cached->uid; + gotowner = TRUE; + } else { + oldattr = getsecurityattr(scx->vol,path, ni); + if (oldattr) { +#if OWNERFROMACL + usid = ntfs_acl_owner(oldattr); +#else + const SECURITY_DESCRIPTOR_RELATIVE *phead; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; + usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)]; +#endif + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + gotowner = TRUE; + free(oldattr); + } + } + allowed = FALSE; + if (gotowner) { +/* TODO : use CAP_FOWNER process capability */ + if (!processuid || (processuid == uid)) + allowed = TRUE; + else + errno = EPERM; + } + return (allowed); +} + +#if POSIXACLS + +/* + * Set a new access or default Posix ACL to a file + * (or remove ACL if no input data) + * Validity of input data is checked after merging + * + * Returns 0, or -1 if there is a problem which errno describes + */ + +int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, const char *value, size_t size, + int flags, ntfs_inode *ni) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const struct CACHED_PERMISSIONS *cached; + char *oldattr; + uid_t processuid; + const SID *usid; + const SID *gsid; + uid_t uid; + uid_t gid; + int res; + mode_t mode; + BOOL isdir; + BOOL deflt; + BOOL exist; + int count; + struct POSIX_SECURITY *oldpxdesc; + struct POSIX_SECURITY *newpxdesc; + + /* get the current pxsec, either from cache or from old attribute */ + res = -1; + deflt = !strcmp(name,"system.posix_acl_default"); + if (size) + count = (size - sizeof(struct POSIX_ACL)) / sizeof(struct POSIX_ACE); + else + count = 0; + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); + newpxdesc = (struct POSIX_SECURITY*)NULL; + if (!deflt || isdir || !size) { + cached = fetch_cache(scx, ni); + if (cached) { + uid = cached->uid; + gid = cached->gid; + oldpxdesc = cached->pxdesc; + if (oldpxdesc) { + mode = oldpxdesc->mode; + newpxdesc = ntfs_replace_acl(oldpxdesc, + (const struct POSIX_ACL*)value,count,deflt); + } + } else { + oldattr = getsecurityattr(scx->vol,path, ni); + if (oldattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; +#if OWNERFROMACL + usid = ntfs_acl_owner(oldattr); +#else + usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)]; +#endif + gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)]; + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + oldpxdesc = ntfs_build_permissions_posix(scx->mapping, + oldattr, usid, gsid, isdir); + if (oldpxdesc) { + if (deflt) + exist = oldpxdesc->defcnt > 0; + else + exist = oldpxdesc->acccnt > 3; + if ((exist && (flags & XATTR_CREATE)) + || (!exist && (flags & XATTR_REPLACE))) { + errno = (exist ? EEXIST : ENODATA); + } else { + mode = oldpxdesc->mode; + newpxdesc = ntfs_replace_acl(oldpxdesc, + (const struct POSIX_ACL*)value,count,deflt); + } + free(oldpxdesc); + } + free(oldattr); + } + } + } else + errno = EINVAL; + + if (newpxdesc) { + processuid = scx->uid; +/* TODO : use CAP_FOWNER process capability */ + if (!processuid || (uid == processuid)) { + /* + * clear setgid if file group does + * not match process group + */ + if (processuid && (gid != scx->gid) + && !groupmember(scx, scx->uid, gid)) { + newpxdesc->mode &= ~S_ISGID; + } + res = ntfs_set_owner_mode(scx, ni, uid, gid, + newpxdesc->mode, newpxdesc); + } else + errno = EPERM; + free(newpxdesc); + } + return (res ? -1 : 0); +} + +/* + * Remove a default Posix ACL from a file + * + * Returns 0, or -1 if there is a problem which errno describes + */ + +int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + const char *name, ntfs_inode *ni) +{ + return (ntfs_set_posix_acl(scx, path, name, + (const char*)NULL, 0, 0, ni)); +} + +#endif + +/* + * Set a new NTFS ACL to a file + * + * Returns 0, or -1 if there is a problem + */ + +int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, + const char *path __attribute__((unused)), + const char *name __attribute__((unused)), + const char *value, size_t size, int flags, + ntfs_inode *ni) +{ + char *attr; + int res; + + res = -1; + if ((size > 0) + && !(flags & XATTR_CREATE) + && ntfs_valid_descr(value,size) + && (ntfs_attr_size(value) == size)) { + /* need copying in order to write */ + attr = (char*)ntfs_malloc(size); + if (attr) { + memcpy(attr,value,size); + res = update_secur_descr(scx->vol, attr, ni); + /* + * No need to invalidate standard caches : + * the relation between a securid and + * the associated protection is unchanged, + * only the relation between a file and + * its securid and protection is changed. + */ +#if CACHE_LEGACY_SIZE + /* + * we must however invalidate the legacy + * cache, which is based on inode numbers. + * For safety, invalidate even if updating + * failed. + */ + if ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + && !ni->security_id) { + struct CACHED_PERMISSIONS_LEGACY legacy; + + legacy.mft_no = ni->mft_no; + legacy.variable = (char*)NULL; + legacy.varsize = 0; + ntfs_invalidate_cache(scx->vol->legacy_cache, + GENERIC(&legacy), + (cache_compare)leg_compare); + } +#endif + free(attr); + } else + errno = ENOMEM; + } else + errno = EINVAL; + return (res ? -1 : 0); +} + +/* + * Set new permissions to a file + * Checks user mapping has been defined before request for setting + * + * rejected if request is not originated by owner or root + * + * returns 0 on success + * -1 on failure, with errno = EIO + */ + +int ntfs_set_mode(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, mode_t mode) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const struct CACHED_PERMISSIONS *cached; + char *oldattr; + const SID *usid; + const SID *gsid; + uid_t processuid; + uid_t uid; + uid_t gid; + int res; +#if POSIXACLS + BOOL isdir; + int pxsize; + const struct POSIX_SECURITY *oldpxdesc; + struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL; +#endif + + /* get the current owner, either from cache or from old attribute */ + res = 0; + cached = fetch_cache(scx, ni); + if (cached) { + uid = cached->uid; + gid = cached->gid; +#if POSIXACLS + oldpxdesc = cached->pxdesc; + if (oldpxdesc) { + /* must copy before merging */ + pxsize = sizeof(struct POSIX_SECURITY) + + (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE); + newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize); + if (newpxdesc) { + memcpy(newpxdesc, oldpxdesc, pxsize); + if (ntfs_merge_mode_posix(newpxdesc, mode)) + res = -1; + } else + res = -1; + } else + newpxdesc = (struct POSIX_SECURITY*)NULL; +#endif + } else { + oldattr = getsecurityattr(scx->vol,path, ni); + if (oldattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; +#if OWNERFROMACL + usid = ntfs_acl_owner(oldattr); +#else + usid = (const SID*)&oldattr[le32_to_cpu(phead->owner)]; +#endif + gsid = (const SID*)&oldattr[le32_to_cpu(phead->group)]; + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); +#if POSIXACLS + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); + newpxdesc = ntfs_build_permissions_posix(scx->mapping, + oldattr, usid, gsid, isdir); + if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode)) + res = -1; +#endif + free(oldattr); + } else + res = -1; + } + + if (!res) { + processuid = scx->uid; +/* TODO : use CAP_FOWNER process capability */ + if (!processuid || (uid == processuid)) { + /* + * clear setgid if file group does + * not match process group + */ + if (processuid && (gid != scx->gid) + && !groupmember(scx, scx->uid, gid)) + mode &= ~S_ISGID; +#if POSIXACLS + if (newpxdesc) { + newpxdesc->mode = mode; + res = ntfs_set_owner_mode(scx, ni, uid, gid, + mode, newpxdesc); + } else + res = ntfs_set_owner_mode(scx, ni, uid, gid, + mode, newpxdesc); +#else + res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); +#endif + } else { + errno = EPERM; + res = -1; /* neither owner nor root */ + } + } else { + /* + * Should not happen : a default descriptor is generated + * by getsecurityattr() when there are none + */ + ntfs_log_error("File has no security descriptor\n"); + res = -1; + errno = EIO; + } +#if POSIXACLS + if (newpxdesc) free(newpxdesc); +#endif + return (res ? -1 : 0); +} + +/* + * Create a default security descriptor for files whose descriptor + * cannot be inherited + */ + +int ntfs_sd_add_everyone(ntfs_inode *ni) +{ + /* JPA SECURITY_DESCRIPTOR_ATTR *sd; */ + SECURITY_DESCRIPTOR_RELATIVE *sd; + ACL *acl; + ACCESS_ALLOWED_ACE *ace; + SID *sid; + int ret, sd_len; + + /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ + /* + * Calculate security descriptor length. We have 2 sub-authorities in + * owner and group SIDs, but structure SID contain only one, so add + * 4 bytes to every SID. + */ + sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); + sd = (SECURITY_DESCRIPTOR_RELATIVE*)ntfs_calloc(sd_len); + if (!sd) + return -1; + + sd->revision = SECURITY_DESCRIPTOR_REVISION; + sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; + + sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); + sid->revision = SID_REVISION; + sid->sub_authority_count = 2; + sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); + sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); + sid->identifier_authority.value[5] = 5; + sd->owner = cpu_to_le32((u8*)sid - (u8*)sd); + + sid = (SID*)((u8*)sid + sizeof(SID) + 4); + sid->revision = SID_REVISION; + sid->sub_authority_count = 2; + sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); + sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); + sid->identifier_authority.value[5] = 5; + sd->group = cpu_to_le32((u8*)sid - (u8*)sd); + + acl = (ACL*)((u8*)sid + sizeof(SID) + 4); + acl->revision = ACL_REVISION; + acl->size = const_cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); + acl->ace_count = const_cpu_to_le16(1); + sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd); + + ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); + ace->type = ACCESS_ALLOWED_ACE_TYPE; + ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + ace->size = const_cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE)); + ace->mask = const_cpu_to_le32(0x1f01ff); /* FIXME */ + ace->sid.revision = SID_REVISION; + ace->sid.sub_authority_count = 1; + ace->sid.sub_authority[0] = const_cpu_to_le32(0); + ace->sid.identifier_authority.value[5] = 1; + + ret = ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, (u8*)sd, + sd_len); + if (ret) + ntfs_log_perror("Failed to add initial SECURITY_DESCRIPTOR"); + + free(sd); + return ret; +} + +/* + * Check whether user can access a file in a specific way + * + * Returns 1 if access is allowed, including user is root or no + * user mapping defined + * 2 if sticky and accesstype is S_IWRITE + S_IEXEC + S_ISVTX + * 0 and sets errno if there is a problem or if access + * is not allowed + * + * This is used for Posix ACL and checking creation of DOS file names + */ + +int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, + int accesstype) /* access type required (S_Ixxx values) */ +{ + int perm; + int res; + int allow; + struct stat stbuf; + +#if POSIXACLS + /* shortcut, use only if Posix ACLs in use */ + if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (1); +#endif + /* + * Always allow for root unless execution is requested. + * (was checked by fuse until kernel 2.6.29) + * Also always allow if no mapping has been defined + */ + if (!scx->mapping[MAPUSERS] + || (!scx->uid + && (!(accesstype & S_IEXEC) + || (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)))) + allow = 1; + else { + perm = ntfs_get_perm(scx, path, ni, accesstype); + if (perm >= 0) { + res = EACCES; + switch (accesstype) { + case S_IEXEC: + allow = (perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0; + break; + case S_IWRITE: + allow = (perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0; + break; + case S_IWRITE + S_IEXEC: + allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) + && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); + break; + case S_IREAD: + allow = (perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0; + break; + case S_IREAD + S_IEXEC: + allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0) + && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); + break; + case S_IREAD + S_IWRITE: + allow = ((perm & (S_IRUSR | S_IRGRP | S_IROTH)) != 0) + && ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0); + break; + case S_IWRITE + S_IEXEC + S_ISVTX: + if (perm & S_ISVTX) { + if ((ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0) + && (stbuf.st_uid == scx->uid)) + allow = 1; + else + allow = 2; + } else + allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) + && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); + break; + default : + res = EINVAL; + allow = 0; + break; + } + if (!allow) + errno = res; + } else + allow = 0; + } + return (allow); +} + +/* + * Check whether user can access the parent directory + * of a file in a specific way + * + * Returns true if access is allowed, including user is root and + * no user mapping defined + * + * Sets errno if there is a problem or if not allowed + * + * This is used for Posix ACL and checking creation of DOS file names + */ + +BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, + const char *path, int accesstype) +{ + int allow; + char *dirpath; + char *name; + ntfs_inode *ni; + ntfs_inode *dir_ni; + struct stat stbuf; + +#if POSIXACLS + /* shortcut, use only if Posix ACLs in use */ + if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (TRUE); +#endif + allow = 0; + dirpath = strdup(path); + if (dirpath) { + /* the root of file system is seen as a parent of itself */ + /* is that correct ? */ + name = strrchr(dirpath, '/'); + *name = 0; + dir_ni = ntfs_pathname_to_inode(scx->vol, NULL, dirpath); + if (dir_ni) { + allow = ntfs_allowed_access(scx,dirpath, + dir_ni, accesstype); + ntfs_inode_close(dir_ni); + /* + * for an not-owned sticky directory, have to + * check whether file itself is owned + */ + if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX)) + && (allow == 2)) { + ni = ntfs_pathname_to_inode(scx->vol, NULL, + path); + allow = FALSE; + if (ni) { + allow = (ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0) + && (stbuf.st_uid == scx->uid); + ntfs_inode_close(ni); + } + } + } + free(dirpath); + } + return (allow); /* errno is set if not allowed */ +} + +/* + * Define a new owner/group to a file + * + * returns zero if successful + */ + +int ntfs_set_owner(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *ni, uid_t uid, gid_t gid) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const struct CACHED_PERMISSIONS *cached; + char *oldattr; + const SID *usid; + const SID *gsid; + uid_t fileuid; + uid_t filegid; + mode_t mode; + int perm; + BOOL isdir; + int res; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; + BOOL pxdescbuilt = FALSE; +#endif + + res = 0; + /* get the current owner and mode from cache or security attributes */ + oldattr = (char*)NULL; + cached = fetch_cache(scx,ni); + if (cached) { + fileuid = cached->uid; + filegid = cached->gid; + mode = cached->mode; +#if POSIXACLS + pxdesc = cached->pxdesc; + if (!pxdesc) + res = -1; +#endif + } else { + fileuid = 0; + filegid = 0; + mode = 0; + oldattr = getsecurityattr(scx->vol, path, ni); + if (oldattr) { + isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + != const_cpu_to_le16(0); + phead = (const SECURITY_DESCRIPTOR_RELATIVE*) + oldattr; + gsid = (const SID*) + &oldattr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + usid = ntfs_acl_owner(oldattr); +#else + usid = (const SID*) + &oldattr[le32_to_cpu(phead->owner)]; +#endif +#if POSIXACLS + pxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr, + usid, gsid, isdir); + if (pxdesc) { + pxdescbuilt = TRUE; + fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + mode = perm = pxdesc->mode; + } else + res = -1; +#else + mode = perm = ntfs_build_permissions(oldattr, + usid, gsid, isdir); + if (perm >= 0) { + fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + } else + res = -1; +#endif + free(oldattr); + } else + res = -1; + } + if (!res) { + /* check requested by root */ + /* or chgrp requested by owner to an owned group */ + if (!scx->uid + || ((((int)uid < 0) || (uid == fileuid)) + && ((gid == scx->gid) || groupmember(scx, scx->uid, gid)) + && (fileuid == scx->uid))) { + /* replace by the new usid and gsid */ + /* or reuse old gid and sid for cacheing */ + if ((int)uid < 0) + uid = fileuid; + if ((int)gid < 0) + gid = filegid; + /* clear setuid and setgid if owner has changed */ + /* unless request originated by root */ + if (uid && (fileuid != uid)) + mode &= 01777; +#if POSIXACLS + res = ntfs_set_owner_mode(scx, ni, uid, gid, + mode, pxdesc); +#else + res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); +#endif + } else { + res = -1; /* neither owner nor root */ + errno = EPERM; + } +#if POSIXACLS + if (pxdescbuilt) + free(pxdesc); +#endif + } else { + /* + * Should not happen : a default descriptor is generated + * by getsecurityattr() when there are none + */ + ntfs_log_error("File has no security descriptor\n"); + res = -1; + errno = EIO; + } + return (res ? -1 : 0); +} + +/* + * Build a security id for a descriptor inherited from + * parent directory the Windows way + */ + +static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, + const char *parentattr, BOOL fordir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *pphead; + const ACL *ppacl; + const SID *usid; + const SID *gsid; + BIGSID defusid; + BIGSID defgsid; + int offpacl; + int offowner; + int offgroup; + SECURITY_DESCRIPTOR_RELATIVE *pnhead; + ACL *pnacl; + int parentattrsz; + char *newattr; + int newattrsz; + int aclsz; + int usidsz; + int gsidsz; + int pos; + le32 securid; + + parentattrsz = ntfs_attr_size(parentattr); + pphead = (const SECURITY_DESCRIPTOR_RELATIVE*)parentattr; + if (scx->mapping[MAPUSERS]) { + usid = ntfs_find_usid(scx->mapping[MAPUSERS], scx->uid, (SID*)&defusid); + gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS], scx->gid, (SID*)&defgsid); + if (!usid) + usid = adminsid; + if (!gsid) + gsid = adminsid; + } else { + /* + * If there is no user mapping, we have to copy owner + * and group from parent directory. + * Windows never has to do that, because it can always + * rely on a user mapping + */ + offowner = le32_to_cpu(pphead->owner); + usid = (const SID*)&parentattr[offowner]; + offgroup = le32_to_cpu(pphead->group); + gsid = (const SID*)&parentattr[offgroup]; + } + /* + * new attribute is smaller than parent's + * except for differences in SIDs which appear in + * owner, group and possible grants and denials in + * generic creator-owner and creator-group ACEs. + * For directories, an ACE may be duplicated for + * access and inheritance, so we double the count. + */ + usidsz = ntfs_sid_size(usid); + gsidsz = ntfs_sid_size(gsid); + newattrsz = parentattrsz + 3*usidsz + 3*gsidsz; + if (fordir) + newattrsz *= 2; + newattr = (char*)ntfs_malloc(newattrsz); + if (newattr) { + pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr; + pnhead->revision = SECURITY_DESCRIPTOR_REVISION; + pnhead->alignment = 0; + pnhead->control = SE_SELF_RELATIVE; + pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + /* + * locate and inherit DACL + * do not test SE_DACL_PRESENT (wrong for "DR Watson") + */ + pnhead->dacl = const_cpu_to_le32(0); + if (pphead->dacl) { + offpacl = le32_to_cpu(pphead->dacl); + ppacl = (const ACL*)&parentattr[offpacl]; + pnacl = (ACL*)&newattr[pos]; + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); + if (aclsz) { + pnhead->dacl = cpu_to_le32(pos); + pos += aclsz; + pnhead->control |= SE_DACL_PRESENT; + } + } + /* + * locate and inherit SACL + */ + pnhead->sacl = const_cpu_to_le32(0); + if (pphead->sacl) { + offpacl = le32_to_cpu(pphead->sacl); + ppacl = (const ACL*)&parentattr[offpacl]; + pnacl = (ACL*)&newattr[pos]; + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); + if (aclsz) { + pnhead->sacl = cpu_to_le32(pos); + pos += aclsz; + pnhead->control |= SE_SACL_PRESENT; + } + } + /* + * inherit or redefine owner + */ + memcpy(&newattr[pos],usid,usidsz); + pnhead->owner = cpu_to_le32(pos); + pos += usidsz; + /* + * inherit or redefine group + */ + memcpy(&newattr[pos],gsid,gsidsz); + pnhead->group = cpu_to_le32(pos); + pos += usidsz; + securid = setsecurityattr(scx->vol, + (SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos); + free(newattr); + } else + securid = const_cpu_to_le32(0); + return (securid); +} + +/* + * Get an inherited security id + * + * For Windows compatibility, the normal initial permission setting + * may be inherited from the parent directory instead of being + * defined by the creation arguments. + * + * The following creates an inherited id for that purpose. + * + * Note : the owner and group of parent directory are also + * inherited (which is not the case on Windows) if no user mapping + * is defined. + * + * Returns the inherited id, or zero if not possible (eg on NTFS 1.x) + */ + +le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, + const char *dir_path, ntfs_inode *dir_ni, BOOL fordir) +{ + struct CACHED_PERMISSIONS *cached; + char *parentattr; + le32 securid; + + securid = const_cpu_to_le32(0); + cached = (struct CACHED_PERMISSIONS*)NULL; + /* + * Try to get inherited id from cache + */ + if (test_nino_flag(dir_ni, v3_Extensions) + && dir_ni->security_id) { + cached = fetch_cache(scx, dir_ni); + if (cached) + securid = (fordir ? cached->inh_dirid + : cached->inh_fileid); + } + /* + * Not cached or not available in cache, compute it all + * Note : if parent directory has no id, it is not cacheable + */ + if (!securid) { + parentattr = getsecurityattr(scx->vol, dir_path, dir_ni); + if (parentattr) { + securid = build_inherited_id(scx, + parentattr, fordir); + free(parentattr); + /* + * Store the result into cache for further use + */ + if (securid) { + cached = fetch_cache(scx, dir_ni); + if (cached) { + if (fordir) + cached->inh_dirid = securid; + else + cached->inh_fileid = securid; + } + } + } + } + return (securid); +} + +/* + * Link a group to a member of group + * + * Returns 0 if OK, -1 (and errno set) if error + */ + +static int link_single_group(struct MAPPING *usermapping, struct passwd *user, + gid_t gid) +{ + struct group *group; + char **grmem; + int grcnt; + gid_t *groups; + int res; + + res = 0; + group = getgrgid(gid); + if (group && group->gr_mem) { + grcnt = usermapping->grcnt; + groups = usermapping->groups; + grmem = group->gr_mem; + while (*grmem && strcmp(user->pw_name, *grmem)) + grmem++; + if (*grmem) { + if (!grcnt) + groups = (gid_t*)malloc(sizeof(gid_t)); + else + groups = (gid_t*)realloc(groups, + (grcnt+1)*sizeof(gid_t)); + if (groups) + groups[grcnt++] = gid; + else { + res = -1; + errno = ENOMEM; + } + } + usermapping->grcnt = grcnt; + usermapping->groups = groups; + } + return (res); +} + + +/* + * Statically link group to users + * This is based on groups defined in /etc/group and does not take + * the groups dynamically set by setgroups() nor any changes in + * /etc/group into account + * + * Only mapped groups and root group are linked to mapped users + * + * Returns 0 if OK, -1 (and errno set) if error + * + */ + +static int link_group_members(struct SECURITY_CONTEXT *scx) +{ + struct MAPPING *usermapping; + struct MAPPING *groupmapping; + struct passwd *user; + int res; + + res = 0; + for (usermapping=scx->mapping[MAPUSERS]; usermapping && !res; + usermapping=usermapping->next) { + usermapping->grcnt = 0; + usermapping->groups = (gid_t*)NULL; + user = getpwuid(usermapping->xid); + if (user && user->pw_name) { + for (groupmapping=scx->mapping[MAPGROUPS]; + groupmapping && !res; + groupmapping=groupmapping->next) { + if (link_single_group(usermapping, user, + groupmapping->xid)) + res = -1; + } + if (!res && link_single_group(usermapping, + user, (gid_t)0)) + res = -1; + } + } + return (res); +} + + +/* + * Apply default single user mapping + * returns zero if successful + */ + +static int ntfs_do_default_mapping(struct SECURITY_CONTEXT *scx, + const SID *usid) +{ + struct MAPPING *usermapping; + struct MAPPING *groupmapping; + SID *sid; + int sidsz; + int res; + + res = -1; + sidsz = ntfs_sid_size(usid); + sid = (SID*)ntfs_malloc(sidsz); + if (sid) { + memcpy(sid,usid,sidsz); + usermapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); + if (usermapping) { + groupmapping = (struct MAPPING*)ntfs_malloc(sizeof(struct MAPPING)); + if (groupmapping) { + usermapping->sid = sid; + usermapping->xid = scx->uid; + usermapping->next = (struct MAPPING*)NULL; + groupmapping->sid = sid; + groupmapping->xid = scx->uid; + groupmapping->next = (struct MAPPING*)NULL; + scx->mapping[MAPUSERS] = usermapping; + scx->mapping[MAPGROUPS] = groupmapping; + res = 0; + } + } + } + return (res); + +} + +/* + * Make sure there are no ambiguous mapping + * Ambiguous mapping may lead to undesired configurations and + * we had rather be safe until the consequences are understood + */ + +#if 0 /* not activated for now */ + +static BOOL check_mapping(const struct MAPPING *usermapping, + const struct MAPPING *groupmapping) +{ + const struct MAPPING *mapping1; + const struct MAPPING *mapping2; + BOOL ambiguous; + + ambiguous = FALSE; + for (mapping1=usermapping; mapping1; mapping1=mapping1->next) + for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next) + if (ntfs_same_sid(mapping1->sid,mapping2->sid)) { + if (mapping1->xid != mapping2->xid) + ambiguous = TRUE; + } else { + if (mapping1->xid == mapping2->xid) + ambiguous = TRUE; + } + for (mapping1=groupmapping; mapping1; mapping1=mapping1->next) + for (mapping2=mapping1->next; mapping2; mapping1=mapping2->next) + if (ntfs_same_sid(mapping1->sid,mapping2->sid)) { + if (mapping1->xid != mapping2->xid) + ambiguous = TRUE; + } else { + if (mapping1->xid == mapping2->xid) + ambiguous = TRUE; + } + return (ambiguous); +} + +#endif + +/* + * Try and apply default single user mapping + * returns zero if successful + */ + +static int ntfs_default_mapping(struct SECURITY_CONTEXT *scx) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + ntfs_inode *ni; + char *securattr; + const SID *usid; + int res; + + res = -1; + ni = ntfs_pathname_to_inode(scx->vol, NULL, "/."); + if (ni) { + securattr = getsecurityattr(scx->vol,"/.",ni); + if (securattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; + usid = (SID*)&securattr[le32_to_cpu(phead->owner)]; + if (ntfs_is_user_sid(usid)) + res = ntfs_do_default_mapping(scx,usid); + free(securattr); + } + ntfs_inode_close(ni); + } + return (res); +} + +/* + * Basic read from a user mapping file on another volume + */ + +static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribute__((unused))) +{ + return (read(*(int*)fileid, buf, size)); +} + + +/* + * Read from a user mapping file on current NTFS partition + */ + +static int localread(void *fileid, char *buf, size_t size, off_t offs) +{ + return (ntfs_local_read((ntfs_inode*)fileid, + AT_UNNAMED, 0, buf, size, offs)); +} + +/* + * Build the user mapping + * - according to a mapping file if defined (or default present), + * - or try default single user mapping if possible + * + * The mapping is specific to a mounted device + * No locking done, mounting assumed non multithreaded + * + * returns zero if mapping is successful + * (failure should not be interpreted as an error) + */ + +int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path) +{ + struct MAPLIST *item; + struct MAPLIST *firstitem; + struct MAPPING *usermapping; + struct MAPPING *groupmapping; + ntfs_inode *ni; + int fd; + + /* be sure not to map anything until done */ + scx->mapping[MAPUSERS] = (struct MAPPING*)NULL; + scx->mapping[MAPGROUPS] = (struct MAPPING*)NULL; + + if (!usermap_path) usermap_path = MAPPINGFILE; + if (usermap_path[0] == '/') { + fd = open(usermap_path,O_RDONLY); + if (fd > 0) { + firstitem = ntfs_read_mapping(basicread, (void*)&fd); + close(fd); + } else + firstitem = (struct MAPLIST*)NULL; + } else { + ni = ntfs_pathname_to_inode(scx->vol, NULL, usermap_path); + if (ni) { + firstitem = ntfs_read_mapping(localread, ni); + ntfs_inode_close(ni); + } else + firstitem = (struct MAPLIST*)NULL; + } + + + if (firstitem) { + usermapping = ntfs_do_user_mapping(firstitem); + groupmapping = ntfs_do_group_mapping(firstitem); + if (usermapping && groupmapping) { + scx->mapping[MAPUSERS] = usermapping; + scx->mapping[MAPGROUPS] = groupmapping; + } else + ntfs_log_error("There were no valid user or no valid group\n"); + /* now we can free the memory copy of input text */ + /* and rely on internal representation */ + while (firstitem) { + item = firstitem->next; + free(firstitem); + firstitem = item; + } + } else { + /* no mapping file, try default mapping */ + if (scx->uid && scx->gid) { + if (!ntfs_default_mapping(scx)) + ntfs_log_info("Using default user mapping\n"); + } + } + return (!scx->mapping[MAPUSERS] || link_group_members(scx)); +} + +/* + * Get the ntfs attribute into an extended attribute + * The attribute is returned according to cpu endianness + */ + +int ntfs_get_ntfs_attrib(const char *path __attribute__((unused)), + char *value, size_t size, ntfs_inode *ni) +{ + u32 attrib; + size_t outsize; + + outsize = 0; /* default to no data and no error */ + if (ni) { + attrib = le32_to_cpu(ni->flags); + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); + else + attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); + if (!attrib) + attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); + outsize = sizeof(FILE_ATTR_FLAGS); + if (size >= outsize) { + if (value) + memcpy(value,&attrib,outsize); + else + errno = EINVAL; + } + } + return (outsize ? (int)outsize : -errno); +} + +/* + * Return the ntfs attribute into an extended attribute + * The attribute is expected according to cpu endianness + * + * Returns 0, or -1 if there is a problem + */ + +int ntfs_set_ntfs_attrib(const char *path __attribute__((unused)), + const char *value, size_t size, int flags, + ntfs_inode *ni) +{ + u32 attrib; + le32 settable; + ATTR_FLAGS dirflags; + int res; + + res = -1; + if (ni && value && (size >= sizeof(FILE_ATTR_FLAGS))) { + if (!(flags & XATTR_CREATE)) { + /* copy to avoid alignment problems */ + memcpy(&attrib,value,sizeof(FILE_ATTR_FLAGS)); + settable = FILE_ATTR_SETTABLE; + res = 0; + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + /* + * Accept changing compression for a directory + * and set index root accordingly + */ + settable |= FILE_ATTR_COMPRESSED; + if ((ni->flags ^ cpu_to_le32(attrib)) + & FILE_ATTR_COMPRESSED) { + if (ni->flags & FILE_ATTR_COMPRESSED) + dirflags = const_cpu_to_le16(0); + else + dirflags = ATTR_IS_COMPRESSED; + res = ntfs_attr_set_flags(ni, + AT_INDEX_ROOT, + NTFS_INDEX_I30, 4, + dirflags, + ATTR_COMPRESSION_MASK); + } + } + if (!res) { + ni->flags = (ni->flags & ~settable) + | (cpu_to_le32(attrib) & settable); + NInoSetDirty(ni); + } + } else + errno = EEXIST; + } else + errno = EINVAL; + return (res ? -1 : 0); +} + +/* + * Open $Secure once for all + * returns zero if it succeeds + * non-zero if it fails. This is not an error (on NTFS v1.x) + */ + + +int ntfs_open_secure(ntfs_volume *vol) +{ + ntfs_inode *ni; + int res; + + res = -1; + vol->secure_ni = (ntfs_inode*)NULL; + vol->secure_xsii = (ntfs_index_context*)NULL; + vol->secure_xsdh = (ntfs_index_context*)NULL; + if (vol->major_ver >= 3) { + /* make sure this is a genuine $Secure inode 9 */ + ni = ntfs_pathname_to_inode(vol, NULL, "$Secure"); + if (ni && (ni->mft_no == 9)) { + vol->secure_reentry = 0; + vol->secure_xsii = ntfs_index_ctx_get(ni, + sii_stream, 4); + vol->secure_xsdh = ntfs_index_ctx_get(ni, + sdh_stream, 4); + if (ni && vol->secure_xsii && vol->secure_xsdh) { + vol->secure_ni = ni; + res = 0; + } + } + } + return (res); +} + +/* + * Final cleaning + * Allocated memory is freed to facilitate the detection of memory leaks + */ + +void ntfs_close_secure(struct SECURITY_CONTEXT *scx) +{ + ntfs_volume *vol; + + vol = scx->vol; + if (vol->secure_ni) { + ntfs_index_ctx_put(vol->secure_xsii); + ntfs_index_ctx_put(vol->secure_xsdh); + ntfs_inode_close(vol->secure_ni); + + } + ntfs_free_mapping(scx->mapping); + free_caches(scx); +} + +/* + * API for direct access to security descriptors + * based on Win32 API + */ + + +/* + * Selective feeding of a security descriptor into user buffer + * + * Returns TRUE if successful + */ + +static BOOL feedsecurityattr(const char *attr, u32 selection, + char *buf, u32 buflen, u32 *psize) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + SECURITY_DESCRIPTOR_RELATIVE *pnhead; + const ACL *pdacl; + const ACL *psacl; + const SID *pusid; + const SID *pgsid; + unsigned int offdacl; + unsigned int offsacl; + unsigned int offowner; + unsigned int offgroup; + unsigned int daclsz; + unsigned int saclsz; + unsigned int usidsz; + unsigned int gsidsz; + unsigned int size; /* size of requested attributes */ + BOOL ok; + unsigned int pos; + unsigned int avail; + le16 control; + + avail = 0; + control = SE_SELF_RELATIVE; + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + size = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + + /* locate DACL if requested and available */ + if (phead->dacl && (selection & DACL_SECURITY_INFORMATION)) { + offdacl = le32_to_cpu(phead->dacl); + pdacl = (const ACL*)&attr[offdacl]; + daclsz = le16_to_cpu(pdacl->size); + size += daclsz; + avail |= DACL_SECURITY_INFORMATION; + } else + offdacl = daclsz = 0; + + /* locate owner if requested and available */ + offowner = le32_to_cpu(phead->owner); + if (offowner && (selection & OWNER_SECURITY_INFORMATION)) { + /* find end of USID */ + pusid = (const SID*)&attr[offowner]; + usidsz = ntfs_sid_size(pusid); + size += usidsz; + avail |= OWNER_SECURITY_INFORMATION; + } else + offowner = usidsz = 0; + + /* locate group if requested and available */ + offgroup = le32_to_cpu(phead->group); + if (offgroup && (selection & GROUP_SECURITY_INFORMATION)) { + /* find end of GSID */ + pgsid = (const SID*)&attr[offgroup]; + gsidsz = ntfs_sid_size(pgsid); + size += gsidsz; + avail |= GROUP_SECURITY_INFORMATION; + } else + offgroup = gsidsz = 0; + + /* locate SACL if requested and available */ + if (phead->sacl && (selection & SACL_SECURITY_INFORMATION)) { + /* find end of SACL */ + offsacl = le32_to_cpu(phead->sacl); + psacl = (const ACL*)&attr[offsacl]; + saclsz = le16_to_cpu(psacl->size); + size += saclsz; + avail |= SACL_SECURITY_INFORMATION; + } else + offsacl = saclsz = 0; + + /* + * Check having enough size in destination buffer + * (required size is returned nevertheless so that + * the request can be reissued with adequate size) + */ + if (size > buflen) { + *psize = size; + errno = EINVAL; + ok = FALSE; + } else { + if (selection & OWNER_SECURITY_INFORMATION) + control |= phead->control & SE_OWNER_DEFAULTED; + if (selection & GROUP_SECURITY_INFORMATION) + control |= phead->control & SE_GROUP_DEFAULTED; + if (selection & DACL_SECURITY_INFORMATION) + control |= phead->control + & (SE_DACL_PRESENT + | SE_DACL_DEFAULTED + | SE_DACL_AUTO_INHERITED + | SE_DACL_PROTECTED); + if (selection & SACL_SECURITY_INFORMATION) + control |= phead->control + & (SE_SACL_PRESENT + | SE_SACL_DEFAULTED + | SE_SACL_AUTO_INHERITED + | SE_SACL_PROTECTED); + /* + * copy header and feed new flags, even if no detailed data + */ + memcpy(buf,attr,sizeof(SECURITY_DESCRIPTOR_RELATIVE)); + pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)buf; + pnhead->control = control; + pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + + /* copy DACL if requested and available */ + if (selection & avail & DACL_SECURITY_INFORMATION) { + pnhead->dacl = cpu_to_le32(pos); + memcpy(&buf[pos],&attr[offdacl],daclsz); + pos += daclsz; + } else + pnhead->dacl = const_cpu_to_le32(0); + + /* copy SACL if requested and available */ + if (selection & avail & SACL_SECURITY_INFORMATION) { + pnhead->sacl = cpu_to_le32(pos); + memcpy(&buf[pos],&attr[offsacl],saclsz); + pos += saclsz; + } else + pnhead->sacl = const_cpu_to_le32(0); + + /* copy owner if requested and available */ + if (selection & avail & OWNER_SECURITY_INFORMATION) { + pnhead->owner = cpu_to_le32(pos); + memcpy(&buf[pos],&attr[offowner],usidsz); + pos += usidsz; + } else + pnhead->owner = const_cpu_to_le32(0); + + /* copy group if requested and available */ + if (selection & avail & GROUP_SECURITY_INFORMATION) { + pnhead->group = cpu_to_le32(pos); + memcpy(&buf[pos],&attr[offgroup],gsidsz); + pos += gsidsz; + } else + pnhead->group = const_cpu_to_le32(0); + if (pos != size) + ntfs_log_error("Error in security descriptor size\n"); + *psize = size; + ok = TRUE; + } + + return (ok); +} + +/* + * Merge a new security descriptor into the old one + * and assign to designated file + * + * Returns TRUE if successful + */ + +static BOOL mergesecurityattr(ntfs_volume *vol, const char *oldattr, + const char *newattr, u32 selection, ntfs_inode *ni) +{ + const SECURITY_DESCRIPTOR_RELATIVE *oldhead; + const SECURITY_DESCRIPTOR_RELATIVE *newhead; + SECURITY_DESCRIPTOR_RELATIVE *targhead; + const ACL *pdacl; + const ACL *psacl; + const SID *powner; + const SID *pgroup; + int offdacl; + int offsacl; + int offowner; + int offgroup; + unsigned int size; + le16 control; + char *target; + int pos; + int oldattrsz; + int newattrsz; + BOOL ok; + + ok = FALSE; /* default return */ + oldhead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; + newhead = (const SECURITY_DESCRIPTOR_RELATIVE*)newattr; + oldattrsz = ntfs_attr_size(oldattr); + newattrsz = ntfs_attr_size(newattr); + target = (char*)ntfs_malloc(oldattrsz + newattrsz); + if (target) { + targhead = (SECURITY_DESCRIPTOR_RELATIVE*)target; + pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + control = SE_SELF_RELATIVE; + /* + * copy new DACL if selected + * or keep old DACL if any + */ + if ((selection & DACL_SECURITY_INFORMATION) ? + newhead->dacl : oldhead->dacl) { + if (selection & DACL_SECURITY_INFORMATION) { + offdacl = le32_to_cpu(newhead->dacl); + pdacl = (const ACL*)&newattr[offdacl]; + } else { + offdacl = le32_to_cpu(oldhead->dacl); + pdacl = (const ACL*)&oldattr[offdacl]; + } + size = le16_to_cpu(pdacl->size); + memcpy(&target[pos], pdacl, size); + targhead->dacl = cpu_to_le32(pos); + pos += size; + } else + targhead->dacl = const_cpu_to_le32(0); + if (selection & DACL_SECURITY_INFORMATION) { + control |= newhead->control + & (SE_DACL_PRESENT + | SE_DACL_DEFAULTED + | SE_DACL_PROTECTED); + if (newhead->control & SE_DACL_AUTO_INHERIT_REQ) + control |= SE_DACL_AUTO_INHERITED; + } else + control |= oldhead->control + & (SE_DACL_PRESENT + | SE_DACL_DEFAULTED + | SE_DACL_AUTO_INHERITED + | SE_DACL_PROTECTED); + /* + * copy new SACL if selected + * or keep old SACL if any + */ + if ((selection & SACL_SECURITY_INFORMATION) ? + newhead->sacl : oldhead->sacl) { + if (selection & SACL_SECURITY_INFORMATION) { + offsacl = le32_to_cpu(newhead->sacl); + psacl = (const ACL*)&newattr[offsacl]; + } else { + offsacl = le32_to_cpu(oldhead->sacl); + psacl = (const ACL*)&oldattr[offsacl]; + } + size = le16_to_cpu(psacl->size); + memcpy(&target[pos], psacl, size); + targhead->sacl = cpu_to_le32(pos); + pos += size; + } else + targhead->sacl = const_cpu_to_le32(0); + if (selection & SACL_SECURITY_INFORMATION) { + control |= newhead->control + & (SE_SACL_PRESENT + | SE_SACL_DEFAULTED + | SE_SACL_PROTECTED); + if (newhead->control & SE_SACL_AUTO_INHERIT_REQ) + control |= SE_SACL_AUTO_INHERITED; + } else + control |= oldhead->control + & (SE_SACL_PRESENT + | SE_SACL_DEFAULTED + | SE_SACL_AUTO_INHERITED + | SE_SACL_PROTECTED); + /* + * copy new OWNER if selected + * or keep old OWNER if any + */ + if ((selection & OWNER_SECURITY_INFORMATION) ? + newhead->owner : oldhead->owner) { + if (selection & OWNER_SECURITY_INFORMATION) { + offowner = le32_to_cpu(newhead->owner); + powner = (const SID*)&newattr[offowner]; + } else { + offowner = le32_to_cpu(oldhead->owner); + powner = (const SID*)&oldattr[offowner]; + } + size = ntfs_sid_size(powner); + memcpy(&target[pos], powner, size); + targhead->owner = cpu_to_le32(pos); + pos += size; + } else + targhead->owner = const_cpu_to_le32(0); + if (selection & OWNER_SECURITY_INFORMATION) + control |= newhead->control & SE_OWNER_DEFAULTED; + else + control |= oldhead->control & SE_OWNER_DEFAULTED; + /* + * copy new GROUP if selected + * or keep old GROUP if any + */ + if ((selection & GROUP_SECURITY_INFORMATION) ? + newhead->group : oldhead->group) { + if (selection & GROUP_SECURITY_INFORMATION) { + offgroup = le32_to_cpu(newhead->group); + pgroup = (const SID*)&newattr[offgroup]; + control |= newhead->control + & SE_GROUP_DEFAULTED; + } else { + offgroup = le32_to_cpu(oldhead->group); + pgroup = (const SID*)&oldattr[offgroup]; + control |= oldhead->control + & SE_GROUP_DEFAULTED; + } + size = ntfs_sid_size(pgroup); + memcpy(&target[pos], pgroup, size); + targhead->group = cpu_to_le32(pos); + pos += size; + } else + targhead->group = const_cpu_to_le32(0); + if (selection & GROUP_SECURITY_INFORMATION) + control |= newhead->control & SE_GROUP_DEFAULTED; + else + control |= oldhead->control & SE_GROUP_DEFAULTED; + targhead->revision = SECURITY_DESCRIPTOR_REVISION; + targhead->alignment = 0; + targhead->control = control; + ok = !update_secur_descr(vol, target, ni); + free(target); + } + return (ok); +} + +/* + * Return the security descriptor of a file + * This is intended to be similar to GetFileSecurity() from Win32 + * in order to facilitate the development of portable tools + * + * returns zero if unsuccessful (following Win32 conventions) + * -1 if no securid + * the securid if any + * + * The Win32 API is : + * + * BOOL WINAPI GetFileSecurity( + * __in LPCTSTR lpFileName, + * __in SECURITY_INFORMATION RequestedInformation, + * __out_opt PSECURITY_DESCRIPTOR pSecurityDescriptor, + * __in DWORD nLength, + * __out LPDWORD lpnLengthNeeded + * ); + * + */ + +int ntfs_get_file_security(struct SECURITY_API *scapi, + const char *path, u32 selection, + char *buf, u32 buflen, u32 *psize) +{ + ntfs_inode *ni; + char *attr; + int res; + + res = 0; /* default return */ + if (scapi && (scapi->magic == MAGIC_API)) { + ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); + if (ni) { + attr = getsecurityattr(scapi->security.vol, path, ni); + if (attr) { + if (feedsecurityattr(attr,selection, + buf,buflen,psize)) { + if (test_nino_flag(ni, v3_Extensions) + && ni->security_id) + res = le32_to_cpu( + ni->security_id); + else + res = -1; + } + free(attr); + } + ntfs_inode_close(ni); + } else + errno = ENOENT; + if (!res) *psize = 0; + } else + errno = EINVAL; /* do not clear *psize */ + return (res); +} + + +/* + * Set the security descriptor of a file or directory + * This is intended to be similar to SetFileSecurity() from Win32 + * in order to facilitate the development of portable tools + * + * returns zero if unsuccessful (following Win32 conventions) + * -1 if no securid + * the securid if any + * + * The Win32 API is : + * + * BOOL WINAPI SetFileSecurity( + * __in LPCTSTR lpFileName, + * __in SECURITY_INFORMATION SecurityInformation, + * __in PSECURITY_DESCRIPTOR pSecurityDescriptor + * ); + */ + +int ntfs_set_file_security(struct SECURITY_API *scapi, + const char *path, u32 selection, const char *attr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + ntfs_inode *ni; + int attrsz; + BOOL missing; + char *oldattr; + int res; + + res = 0; /* default return */ + if (scapi && (scapi->magic == MAGIC_API) && attr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + attrsz = ntfs_attr_size(attr); + /* if selected, owner and group must be present or defaulted */ + missing = ((selection & OWNER_SECURITY_INFORMATION) + && !phead->owner + && !(phead->control & SE_OWNER_DEFAULTED)) + || ((selection & GROUP_SECURITY_INFORMATION) + && !phead->group + && !(phead->control & SE_GROUP_DEFAULTED)); + if (!missing + && (phead->control & SE_SELF_RELATIVE) + && ntfs_valid_descr(attr, attrsz)) { + ni = ntfs_pathname_to_inode(scapi->security.vol, + NULL, path); + if (ni) { + oldattr = getsecurityattr(scapi->security.vol, + path, ni); + if (oldattr) { + if (mergesecurityattr( + scapi->security.vol, + oldattr, attr, + selection, ni)) { + if (test_nino_flag(ni, + v3_Extensions)) + res = le32_to_cpu( + ni->security_id); + else + res = -1; + } + free(oldattr); + } + ntfs_inode_close(ni); + } + } else + errno = EINVAL; + } else + errno = EINVAL; + return (res); +} + + +/* + * Return the attributes of a file + * This is intended to be similar to GetFileAttributes() from Win32 + * in order to facilitate the development of portable tools + * + * returns -1 if unsuccessful (Win32 : INVALID_FILE_ATTRIBUTES) + * + * The Win32 API is : + * + * DWORD WINAPI GetFileAttributes( + * __in LPCTSTR lpFileName + * ); + */ + +int ntfs_get_file_attributes(struct SECURITY_API *scapi, const char *path) +{ + ntfs_inode *ni; + s32 attrib; + + attrib = -1; /* default return */ + if (scapi && (scapi->magic == MAGIC_API) && path) { + ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); + if (ni) { + attrib = le32_to_cpu(ni->flags); + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); + else + attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); + if (!attrib) + attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); + + ntfs_inode_close(ni); + } else + errno = ENOENT; + } else + errno = EINVAL; /* do not clear *psize */ + return (attrib); +} + + +/* + * Set attributes to a file or directory + * This is intended to be similar to SetFileAttributes() from Win32 + * in order to facilitate the development of portable tools + * + * Only a few flags can be set (same list as Win32) + * + * returns zero if unsuccessful (following Win32 conventions) + * nonzero if successful + * + * The Win32 API is : + * + * BOOL WINAPI SetFileAttributes( + * __in LPCTSTR lpFileName, + * __in DWORD dwFileAttributes + * ); + */ + +BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi, + const char *path, s32 attrib) +{ + ntfs_inode *ni; + le32 settable; + ATTR_FLAGS dirflags; + int res; + + res = 0; /* default return */ + if (scapi && (scapi->magic == MAGIC_API) && path) { + ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); + if (ni) { + settable = FILE_ATTR_SETTABLE; + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + /* + * Accept changing compression for a directory + * and set index root accordingly + */ + settable |= FILE_ATTR_COMPRESSED; + if ((ni->flags ^ cpu_to_le32(attrib)) + & FILE_ATTR_COMPRESSED) { + if (ni->flags & FILE_ATTR_COMPRESSED) + dirflags = const_cpu_to_le16(0); + else + dirflags = ATTR_IS_COMPRESSED; + res = ntfs_attr_set_flags(ni, + AT_INDEX_ROOT, + NTFS_INDEX_I30, 4, + dirflags, + ATTR_COMPRESSION_MASK); + } + } + if (!res) { + ni->flags = (ni->flags & ~settable) + | (cpu_to_le32(attrib) & settable); + NInoSetDirty(ni); + } + if (!ntfs_inode_close(ni)) + res = -1; + } else + errno = ENOENT; + } + return (res); +} + + +BOOL ntfs_read_directory(struct SECURITY_API *scapi, + const char *path, ntfs_filldir_t callback, void *context) +{ + ntfs_inode *ni; + BOOL ok; + s64 pos; + + ok = FALSE; /* default return */ + if (scapi && (scapi->magic == MAGIC_API) && callback) { + ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); + if (ni) { + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + pos = 0; + ntfs_readdir(ni,&pos,context,callback); + ok = !ntfs_inode_close(ni); + } else { + ntfs_inode_close(ni); + errno = ENOTDIR; + } + } else + errno = ENOENT; + } else + errno = EINVAL; /* do not clear *psize */ + return (ok); +} + +/* + * read $SDS (for auditing security data) + * + * Returns the number or read bytes, or -1 if there is an error + */ + +int ntfs_read_sds(struct SECURITY_API *scapi, + char *buf, u32 size, u32 offset) +{ + int got; + + got = -1; /* default return */ + if (scapi && (scapi->magic == MAGIC_API)) { + if (scapi->security.vol->secure_ni) + got = ntfs_local_read(scapi->security.vol->secure_ni, + STREAM_SDS, 4, buf, size, offset); + else + errno = EOPNOTSUPP; + } else + errno = EINVAL; + return (got); +} + +/* + * read $SII (for auditing security data) + * + * Returns next entry, or NULL if there is an error + */ + +INDEX_ENTRY *ntfs_read_sii(struct SECURITY_API *scapi, + INDEX_ENTRY *entry) +{ + SII_INDEX_KEY key; + INDEX_ENTRY *ret; + BOOL found; + ntfs_index_context *xsii; + + ret = (INDEX_ENTRY*)NULL; /* default return */ + if (scapi && (scapi->magic == MAGIC_API)) { + xsii = scapi->security.vol->secure_xsii; + if (xsii) { + if (!entry) { + key.security_id = const_cpu_to_le32(0); + found = !ntfs_index_lookup((char*)&key, + sizeof(SII_INDEX_KEY), xsii); + /* not supposed to find */ + if (!found && (errno == ENOENT)) + ret = xsii->entry; + } else + ret = ntfs_index_next(entry,xsii); + if (!ret) + errno = ENODATA; + } else + errno = EOPNOTSUPP; + } else + errno = EINVAL; + return (ret); +} + +/* + * read $SDH (for auditing security data) + * + * Returns next entry, or NULL if there is an error + */ + +INDEX_ENTRY *ntfs_read_sdh(struct SECURITY_API *scapi, + INDEX_ENTRY *entry) +{ + SDH_INDEX_KEY key; + INDEX_ENTRY *ret; + BOOL found; + ntfs_index_context *xsdh; + + ret = (INDEX_ENTRY*)NULL; /* default return */ + if (scapi && (scapi->magic == MAGIC_API)) { + xsdh = scapi->security.vol->secure_xsdh; + if (xsdh) { + if (!entry) { + key.hash = const_cpu_to_le32(0); + key.security_id = const_cpu_to_le32(0); + found = !ntfs_index_lookup((char*)&key, + sizeof(SDH_INDEX_KEY), xsdh); + /* not supposed to find */ + if (!found && (errno == ENOENT)) + ret = xsdh->entry; + } else + ret = ntfs_index_next(entry,xsdh); + if (!ret) + errno = ENODATA; + } else errno = ENOTSUP; + } else + errno = EINVAL; + return (ret); +} + +/* + * Get the mapped user SID + * A buffer of 40 bytes has to be supplied + * + * returns the size of the SID, or zero and errno set if not found + */ + +int ntfs_get_usid(struct SECURITY_API *scapi, uid_t uid, char *buf) +{ + const SID *usid; + BIGSID defusid; + int size; + + size = 0; + if (scapi && (scapi->magic == MAGIC_API)) { + usid = ntfs_find_usid(scapi->security.mapping[MAPUSERS], uid, (SID*)&defusid); + if (usid) { + size = ntfs_sid_size(usid); + memcpy(buf,usid,size); + } else + errno = ENODATA; + } else + errno = EINVAL; + return (size); +} + +/* + * Get the mapped group SID + * A buffer of 40 bytes has to be supplied + * + * returns the size of the SID, or zero and errno set if not found + */ + +int ntfs_get_gsid(struct SECURITY_API *scapi, gid_t gid, char *buf) +{ + const SID *gsid; + BIGSID defgsid; + int size; + + size = 0; + if (scapi && (scapi->magic == MAGIC_API)) { + gsid = ntfs_find_gsid(scapi->security.mapping[MAPGROUPS], gid, (SID*)&defgsid); + if (gsid) { + size = ntfs_sid_size(gsid); + memcpy(buf,gsid,size); + } else + errno = ENODATA; + } else + errno = EINVAL; + return (size); +} + +/* + * Get the user mapped to a SID + * + * returns the uid, or -1 if not found + */ + +int ntfs_get_user(struct SECURITY_API *scapi, const SID *usid) +{ + int uid; + + uid = -1; + if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(usid)) { + if (ntfs_same_sid(usid,adminsid)) + uid = 0; + else { + uid = ntfs_find_user(scapi->security.mapping[MAPUSERS], usid); + if (!uid) { + uid = -1; + errno = ENODATA; + } + } + } else + errno = EINVAL; + return (uid); +} + +/* + * Get the group mapped to a SID + * + * returns the uid, or -1 if not found + */ + +int ntfs_get_group(struct SECURITY_API *scapi, const SID *gsid) +{ + int gid; + + gid = -1; + if (scapi && (scapi->magic == MAGIC_API) && ntfs_valid_sid(gsid)) { + if (ntfs_same_sid(gsid,adminsid)) + gid = 0; + else { + gid = ntfs_find_group(scapi->security.mapping[MAPGROUPS], gsid); + if (!gid) { + gid = -1; + errno = ENODATA; + } + } + } else + errno = EINVAL; + return (gid); +} + +/* + * Initializations before calling ntfs_get_file_security() + * ntfs_set_file_security() and ntfs_read_directory() + * + * Only allowed for root + * + * Returns an (obscured) struct SECURITY_API* needed for further calls + * NULL if not root (EPERM) or device is mounted (EBUSY) + */ + +struct SECURITY_API *ntfs_initialize_file_security(const char *device, + int flags) +{ + ntfs_volume *vol; + unsigned long mntflag; + int mnt; + struct SECURITY_API *scapi; + struct SECURITY_CONTEXT *scx; + + scapi = (struct SECURITY_API*)NULL; + mnt = ntfs_check_if_mounted(device, &mntflag); + if (!mnt && !(mntflag & NTFS_MF_MOUNTED) && !getuid()) { + vol = ntfs_mount(device, flags); + if (vol) { + scapi = (struct SECURITY_API*) + ntfs_malloc(sizeof(struct SECURITY_API)); + if (!ntfs_volume_get_free_space(vol) + && scapi) { + scapi->magic = MAGIC_API; + scapi->seccache = (struct PERMISSIONS_CACHE*)NULL; + scx = &scapi->security; + scx->vol = vol; + scx->uid = getuid(); + scx->gid = getgid(); + scx->pseccache = &scapi->seccache; + scx->vol->secure_flags = 0; + /* accept no mapping and no $Secure */ + ntfs_build_mapping(scx,(const char*)NULL); + ntfs_open_secure(vol); + } else { + if (scapi) + free(scapi); + else + errno = ENOMEM; + mnt = ntfs_umount(vol,FALSE); + scapi = (struct SECURITY_API*)NULL; + } + } + } else + if (getuid()) + errno = EPERM; + else + errno = EBUSY; + return (scapi); +} + +/* + * Leaving after ntfs_initialize_file_security() + * + * Returns FALSE if FAILED + */ + +BOOL ntfs_leave_file_security(struct SECURITY_API *scapi) +{ + int ok; + ntfs_volume *vol; + + ok = FALSE; + if (scapi && (scapi->magic == MAGIC_API) && scapi->security.vol) { + vol = scapi->security.vol; + ntfs_close_secure(&scapi->security); + free(scapi); + if (!ntfs_umount(vol, 0)) + ok = TRUE; + } + return (ok); } diff --git a/release/src/router/ntfs-3g/libntfs-3g/unistr.c b/release/src/router/ntfs-3g/libntfs-3g/unistr.c index e3dac62555..22eb2c61b4 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/unistr.c +++ b/release/src/router/ntfs-3g/libntfs-3g/unistr.c @@ -45,6 +45,12 @@ #include #endif +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV +#include +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + #include "compat.h" #include "attrib.h" #include "types.h" @@ -65,6 +71,18 @@ static int use_utf8 = 1; /* use UTF-8 encoding for file names */ +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV +/** + * This variable controls whether or not automatic normalization form conversion + * should be performed when translating NTFS unicode file names to UTF-8. + * Defaults to on, but can be controlled from the outside using the function + * int ntfs_macosx_normalize_filenames(int normalize); + */ +static int nfconvert_utf8 = 1; +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + /* * This is used by the name collation functions to quickly determine what * characters are (in)valid. @@ -133,7 +151,10 @@ BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len, * @err_val if an invalid character is found in @name1 during the comparison. * * The following characters are considered invalid: '"', '*', '<', '>' and '?'. + * + * A few optimizations made by JPA */ + int ntfs_names_collate(const ntfschar *name1, const u32 name1_len, const ntfschar *name2, const u32 name2_len, const int err_val __attribute__((unused)), @@ -149,21 +170,29 @@ int ntfs_names_collate(const ntfschar *name1, const u32 name1_len, exit(1); } #endif - for (cnt = 0; cnt < min(name1_len, name2_len); ++cnt) { - c1 = le16_to_cpu(*name1); - name1++; - c2 = le16_to_cpu(*name2); - name2++; - if (ic) { - if (c1 < upcase_len) - c1 = le16_to_cpu(upcase[c1]); - if (c2 < upcase_len) - c2 = le16_to_cpu(upcase[c2]); - } -#if 0 - if (c1 < 64 && legal_ansi_char_array[c1] & 8) - return err_val; -#endif + cnt = min(name1_len, name2_len); + /* JPA average loop count is 8 */ + if (cnt > 0) { + if (ic) + /* JPA this loop in 76% cases */ + do { + c1 = le16_to_cpu(*name1); + name1++; + c2 = le16_to_cpu(*name2); + name2++; + if (c1 < upcase_len) + c1 = le16_to_cpu(upcase[c1]); + if (c2 < upcase_len) + c2 = le16_to_cpu(upcase[c2]); + } while ((c1 == c2) && --cnt); + else + do { + /* JPA this loop in 24% cases */ + c1 = le16_to_cpu(*name1); + name1++; + c2 = le16_to_cpu(*name2); + name2++; + } while ((c1 == c2) && --cnt); if (c1 < c2) return -1; if (c1 > c2) @@ -173,12 +202,6 @@ int ntfs_names_collate(const ntfschar *name1, const u32 name1_len, return -1; if (name1_len == name2_len) return 0; - /* name1_len > name2_len */ -#if 0 - c1 = le16_to_cpu(*name1); - if (c1 < 64 && legal_ansi_char_array[c1] & 8) - return err_val; -#endif return 1; } @@ -473,6 +496,13 @@ fail: static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, char **outs, int outs_len) { +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV + char *original_outs_value = *outs; + int original_outs_len = outs_len; +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + char *t; int i, size, ret = -1; ntfschar halfpair; @@ -528,6 +558,36 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, } } *t = '\0'; + +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV + if(nfconvert_utf8 && (t - *outs) > 0) { + char *new_outs = NULL; + int new_outs_len = ntfs_macosx_normalize_utf8(*outs, &new_outs, 0); // Normalize to decomposed form + if(new_outs_len >= 0 && new_outs != NULL) { + if(original_outs_value != *outs) { + // We have allocated outs ourselves. + free(*outs); + *outs = new_outs; + t = *outs + new_outs_len; + } + else { + // We need to copy new_outs into the fixed outs buffer. + memset(*outs, 0, original_outs_len); + strncpy(*outs, new_outs, original_outs_len-1); + t = *outs + original_outs_len; + free(new_outs); + } + } + else { + ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFD: %s\n", *outs); + ntfs_log_error(" new_outs=0x%p\n", new_outs); + ntfs_log_error(" new_outs_len=%d\n", new_outs_len); + } + } +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + ret = t - *outs; out: return ret; @@ -662,6 +722,19 @@ fail: */ static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs) { +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV + char *new_ins = NULL; + if(nfconvert_utf8) { + int new_ins_len; + new_ins_len = ntfs_macosx_normalize_utf8(ins, &new_ins, 1); // Normalize to composed form + if(new_ins_len >= 0) + ins = new_ins; + else + ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFC: %s\n", ins); + } +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ const char *t = ins; u32 wc; ntfschar *outpos; @@ -697,6 +770,12 @@ static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs) ret = --outpos - *outs; fail: +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV + if(new_ins != NULL) + free(new_ins); +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ return ret; } @@ -998,21 +1077,26 @@ void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len) {0} }; int i, r; + int k, off; memset((char*)uc, 0, uc_len); uc_len >>= 1; if (uc_len > 65536) uc_len = 65536; for (i = 0; (u32)i < uc_len; i++) - uc[i] = i; - for (r = 0; uc_run_table[r][0]; r++) + uc[i] = cpu_to_le16(i); + for (r = 0; uc_run_table[r][0]; r++) { + off = uc_run_table[r][2]; for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++) - uc[i] += uc_run_table[r][2]; + uc[i] = cpu_to_le16(i + off); + } for (r = 0; uc_dup_table[r][0]; r++) for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2) - uc[i + 1]--; - for (r = 0; uc_byte_table[r][0]; r++) - uc[uc_byte_table[r][0]] = uc_byte_table[r][1]; + uc[i + 1] = cpu_to_le16(i); + for (r = 0; uc_byte_table[r][0]; r++) { + k = uc_byte_table[r][1]; + uc[uc_byte_table[r][0]] = cpu_to_le16(k); + } } /** @@ -1067,6 +1151,69 @@ void ntfs_ucsfree(ntfschar *ucs) } /* + * Check whether a name contains no chars forbidden + * for DOS or Win32 use + * + * If there is a bad char, errno is set to EINVAL + */ + +BOOL ntfs_forbidden_chars(const ntfschar *name, int len) +{ + BOOL forbidden; + int ch; + int i; + u32 mainset = (1L << ('\"' - 0x20)) + | (1L << ('*' - 0x20)) + | (1L << ('/' - 0x20)) + | (1L << (':' - 0x20)) + | (1L << ('<' - 0x20)) + | (1L << ('>' - 0x20)) + | (1L << ('?' - 0x20)); + + forbidden = (len == 0) || (le16_to_cpu(name[len-1]) == ' '); + for (i=0; i= vol->upcase_len) + || ((shortname[i] != longname[i]) + && (shortname[i] != vol->upcase[ch]))) + collapsible = FALSE; + } + return (collapsible); +} + +/* * Define the character encoding to be used. * Use UTF-8 unless specified otherwise. */ @@ -1087,3 +1234,81 @@ int ntfs_set_char_encoding(const char *locale) return 0; /* always successful */ } +#if defined(__APPLE__) || defined(__DARWIN__) + +int ntfs_macosx_normalize_filenames(int normalize) { +#ifdef ENABLE_NFCONV + if(normalize == 0 || normalize == 1) { + nfconvert_utf8 = normalize; + return 0; + } + else + return -1; +#else + return -1; +#endif /* ENABLE_NFCONV */ +} + +int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, + int composed) { +#ifdef ENABLE_NFCONV + /* For this code to compile, the CoreFoundation framework must be fed to the linker. */ + CFStringRef cfSourceString; + CFMutableStringRef cfMutableString; + CFRange rangeToProcess; + CFIndex requiredBufferLength; + char *result = NULL; + int resultLength = -1; + + /* Convert the UTF-8 string to a CFString. */ + cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8); + if(cfSourceString == NULL) { + ntfs_log_error("CFStringCreateWithCString failed!\n"); + return -2; + } + + /* Create a mutable string from cfSourceString that we are free to modify. */ + cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString); + CFRelease(cfSourceString); /* End-of-life. */ + if(cfMutableString == NULL) { + ntfs_log_error("CFStringCreateMutableCopy failed!\n"); + return -3; + } + + /* Normalize the mutable string to the desired normalization form. */ + CFStringNormalize(cfMutableString, (composed != 0 ? kCFStringNormalizationFormC : kCFStringNormalizationFormD)); + + /* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */ + rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString)); + if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) { + resultLength = sizeof(char)*(requiredBufferLength + 1); + result = ntfs_calloc(resultLength); + + if(result != NULL) { + if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, + 0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) { + ntfs_log_error("Could not perform UTF-8 conversion of normalized CFMutableString.\n"); + free(result); + result = NULL; + } + } + else + ntfs_log_error("Could not perform a ntfs_calloc of %d bytes for char *result.\n", resultLength); + } + else + ntfs_log_error("Could not perform check for required length of UTF-8 conversion of normalized CFMutableString.\n"); + + + CFRelease(cfMutableString); + + if(result != NULL) { + *target = result; + return resultLength - 1; + } + else + return -1; +#else + return -1; +#endif /* ENABLE_NFCONV */ +} +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ diff --git a/release/src/router/ntfs-3g/libntfs-3g/unix_io.c b/release/src/router/ntfs-3g/libntfs-3g/unix_io.c index 75aebceced..64b41d3e71 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/unix_io.c +++ b/release/src/router/ntfs-3g/libntfs-3g/unix_io.c @@ -69,6 +69,40 @@ #endif /** + * fsync replacement which makes every effort to try to get the data down to + * disk, using different means for different operating systems. Specifically, + * it issues the proper fcntl for Mac OS X or does fsync where it is available + * or as a last resort calls the fsync function. Information on this problem + * was retrieved from: + * http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf + */ +static int ntfs_fsync(int fildes) +{ + int ret = -1; +#if defined(__APPLE__) || defined(__DARWIN__) +# ifndef F_FULLFSYNC +# error "Mac OS X: F_FULLFSYNC is not defined. Either you didn't include fcntl.h or you're using an older, unsupported version of Mac OS X (pre-10.3)." +# endif + /* + * Apple has disabled fsync() for internal disk drives in OS X. + * To force a synchronization of disk contents, we use a Mac OS X + * specific fcntl, F_FULLFSYNC. + */ + ret = fcntl(fildes, F_FULLFSYNC, NULL); + if (ret) { + /* + * If we are not on a file system that supports this, + * then fall back to a plain fsync. + */ + ret = fsync(fildes); + } +#else + ret = fsync(fildes); +#endif + return ret; +} + +/** * ntfs_device_unix_io_open - Open a device and lock it exclusively * @dev: * @flags: @@ -155,7 +189,7 @@ static int ntfs_device_unix_io_close(struct ntfs_device *dev) return -1; } if (NDevDirty(dev)) - if (fsync(DEV_FD(dev))) { + if (ntfs_fsync(DEV_FD(dev))) { ntfs_log_perror("Failed to fsync device %s", dev->d_name); return -1; } @@ -281,7 +315,7 @@ static int ntfs_device_unix_io_sync(struct ntfs_device *dev) int res = 0; if (!NDevReadOnly(dev)) { - res = fsync(DEV_FD(dev)); + res = ntfs_fsync(DEV_FD(dev)); if (res) ntfs_log_perror("Failed to sync device %s", dev->d_name); else diff --git a/release/src/router/ntfs-3g/libntfs-3g/volume.c b/release/src/router/ntfs-3g/libntfs-3g/volume.c index ab8b8803e0..74037d0226 100644 --- a/release/src/router/ntfs-3g/libntfs-3g/volume.c +++ b/release/src/router/ntfs-3g/libntfs-3g/volume.c @@ -197,6 +197,7 @@ static int __ntfs_volume_release(ntfs_volume *v) ntfs_error_set(&err); } + ntfs_free_lru_caches(v); free(v->vol_name); free(v->upcase); free(v->attrdef); @@ -525,6 +526,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags) "%s\n", strerror(errno)); /* We now initialize the cluster allocator. */ + vol->full_zones = 0; mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */ /* Setup the mft zone. */ @@ -1166,7 +1168,8 @@ ntfs_volume *ntfs_mount(const char *name __attribute__((unused)), int eo = errno; ntfs_device_free(dev); errno = eo; - } + } else + ntfs_create_lru_caches(vol); return vol; #else /* @@ -1562,3 +1565,30 @@ int ntfs_set_locale(void) return 0; } +/* + * Feed the counts of free clusters and free mft records + */ + +int ntfs_volume_get_free_space(ntfs_volume *vol) +{ + ntfs_attr *na; + int ret; + + ret = -1; /* default return */ + vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na); + if (vol->free_clusters < 0) { + ntfs_log_perror("Failed to read NTFS $Bitmap"); + } else { + na = vol->mftbmp_na; + vol->free_mft_records = ntfs_attr_get_free_bits(na); + + if (vol->free_mft_records >= 0) + vol->free_mft_records += (na->allocated_size - na->data_size) << 3; + + if (vol->free_mft_records < 0) + ntfs_log_perror("Failed to calculate free MFT records"); + else + ret = 0; + } + return (ret); +} diff --git a/release/src/router/ntfs-3g/ltmain.sh b/release/src/router/ntfs-3g/ltmain.sh index 22f58dfa55..27d498a080 100644 --- a/release/src/router/ntfs-3g/ltmain.sh +++ b/release/src/router/ntfs-3g/ltmain.sh @@ -1,8 +1,8 @@ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify @@ -33,9 +33,6 @@ basename="s,^.*/,,g" # function. progpath="$0" -# define SED for historic ltconfig's generated by Libtool 1.3 -test -z "$SED" && SED=sed - # The name of this program: progname=`echo "$progpath" | $SED $basename` modename="$progname" @@ -46,8 +43,8 @@ EXIT_FAILURE=1 PROGRAM=ltmain.sh PACKAGE=libtool -VERSION=1.5.22 -TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" +VERSION=1.5.26 +TIMESTAMP=" (1.1220.2.492 2008/01/30 06:40:56)" # Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE). if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then @@ -60,6 +57,8 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh # Check that we have a working $echo. if test "X$1" = X--no-reexec; then @@ -114,15 +113,21 @@ esac # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). # We save the old values to restore during execute mode. -for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +lt_env= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - fi" + save_$lt_var=\$$lt_var + lt_env=\"$lt_var=\$$lt_var \$lt_env\" + $lt_var=C + export $lt_var + fi" done +if test -n "$lt_env"; then + lt_env="env $lt_env" +fi + # Make sure IFS has a sensible default lt_nl=' ' @@ -209,7 +214,13 @@ func_win32_libid () if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ - $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + $SED -n -e '1,100{ + / I /{ + s,.*,import, + p + q + } + }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -343,11 +354,11 @@ func_extract_archives () my_xlib_u=$my_xlib while :; do case " $extracted_archives " in - *" $my_xlib_u "*) - extracted_serial=`expr $extracted_serial + 1` - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac + *" $my_xlib_u "*) + extracted_serial=`expr $extracted_serial + 1` + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" @@ -411,19 +422,8 @@ func_extract_archives () ##################################### # Darwin sucks -#eval std_shrext=\"$shrext_cmds\" - -# And fixing for Darwin sucks for everybody else -if test -z "$shrext_cmds" && test -n "$shrext"; then - eval shrext_cmds=\"$shrext\" -fi - eval std_shrext=\"$shrext_cmds\" -# This value is evaluated to 32768, so place it here as a compatilibity hack -# because older libtool.m4 didn't define this variable -test -z "$max_cmd_len" && max_cmd_len=32768 - disable_libs=no # Parse our command line options once, thoroughly. @@ -488,11 +488,12 @@ do ;; --version) - $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - $echo - $echo "Copyright (C) 2005 Free Software Foundation, Inc." - $echo "This is free software; see the source for copying conditions. There is NO" - $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + echo "\ +$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP + +Copyright (C) 2008 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit $? ;; @@ -789,10 +790,11 @@ if test -z "$show_help"; then *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; + *.[fF][09]?) xform=[fF][09]. ;; *.for) xform=for ;; *.java) xform=java ;; *.obj) xform=obj ;; + *.sx) xform=sx ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` @@ -961,7 +963,7 @@ EOF $run $rm "$lobj" "$output_obj" $show "$command" - if $run eval "$command"; then : + if $run eval $lt_env "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit $EXIT_FAILURE @@ -1033,7 +1035,7 @@ EOF command="$command$suppress_output" $run $rm "$obj" "$output_obj" $show "$command" - if $run eval "$command"; then : + if $run eval $lt_env "$command"; then : else $run $rm $removelist exit $EXIT_FAILURE @@ -1166,6 +1168,7 @@ EOF thread_safe=no vinfo= vinfo_number=no + single_module="${wl}-single_module" func_infer_tag $base_compile @@ -1174,8 +1177,8 @@ EOF do case $arg in -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) + case $arg in + -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi @@ -1184,19 +1187,19 @@ EOF fi prefer_static_libs=yes ;; - -static) + -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac build_libtool_libs=no build_old_libs=yes break @@ -1644,13 +1647,18 @@ EOF continue ;; - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" continue ;; + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + -module) module=yes continue @@ -1664,10 +1672,11 @@ EOF # -m* pass through architecture-specific compiler args for GCC # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC - # -pg pass through profiling flag for GCC + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin # @file GCC response files - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ - -t[45]*|-txscale*|@*) + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. @@ -1695,9 +1704,9 @@ EOF -no-install) case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) # The PATH hackery in wrapper scripts is required on Windows - # in order for the loader to find any dlls it needs. + # and Darwin in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no @@ -2138,7 +2147,7 @@ EOF lib= found=no case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" @@ -2153,7 +2162,12 @@ EOF continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` - for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" @@ -2534,9 +2548,9 @@ EOF if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. @@ -2949,12 +2963,18 @@ EOF # we do not want to link against static libs, # but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + eval deplibdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done - if test -f "$path/$depdepl" ; then + if test -f "$deplibdir/$depdepl" ; then + depdepl="$deplibdir/$depdepl" + elif test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" + else + # Can't find it, oh well... + depdepl= fi # do not add paths which are already there case " $newlib_search_path " in @@ -3102,9 +3122,10 @@ EOF case $linkmode in oldlib) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi + case " $deplibs" in + *\ -l* | *\ -L*) + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 ;; + esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 @@ -3243,9 +3264,10 @@ EOF age="0" ;; irix|nonstopux) - current=`expr $number_major + $number_minor - 1` + current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_minor" + lt_irix_increment=no ;; esac ;; @@ -3304,7 +3326,8 @@ EOF versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` - verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) @@ -3318,8 +3341,11 @@ EOF ;; irix | nonstopux) - major=`expr $current - $age + 1` - + if test "X$lt_irix_increment" = "Xno"; then + major=`expr $current - $age` + else + major=`expr $current - $age + 1` + fi case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; @@ -3456,11 +3482,11 @@ EOF fi # Eliminate all temporary directories. -# for path in $notinst_path; do -# lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` -# deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` -# dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` -# done + #for path in $notinst_path; do + # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. @@ -3561,7 +3587,7 @@ EOF int main() { return 0; } EOF $rm conftest - if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then + if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then ldd_output=`ldd conftest` for i in $deplibs; do name=`expr $i : '-l\(.*\)'` @@ -3923,7 +3949,10 @@ EOF test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then - eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + case $archive_cmds in + *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;; + *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;; + esac else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi @@ -4011,23 +4040,15 @@ EOF fi tmp_deplibs= - inst_prefix_arg= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) - if test -n "$inst_prefix_dir" && (echo "$test_deplib" | grep -- "$inst_prefix_dir" >/dev/null); then - inst_prefix_arg="$inst_prefix_arg $test_deplib" - else - tmp_deplibs="$tmp_deplibs $test_deplib" - fi + tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" - if test -n "$inst_prefix_arg"; then - deplibs="$inst_prefix_arg $deplibs" - fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then @@ -4241,9 +4262,10 @@ EOF ;; obj) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi + case " $deplibs" in + *\ -l* | *\ -L*) + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 ;; + esac if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 @@ -4297,7 +4319,7 @@ EOF if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" @@ -5317,6 +5339,8 @@ if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. @@ -6413,8 +6437,10 @@ relink_command=\"$relink_command\"" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit $EXIT_FAILURE + if test ! -f "$dir/$dlname"; then + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi fi ;; @@ -6478,16 +6504,13 @@ relink_command=\"$relink_command\"" fi # Restore saved environment variables - for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + fi" done - # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else diff --git a/release/src/router/ntfs-3g/missing b/release/src/router/ntfs-3g/missing index 894e786e16..1c8ff7049d 100755 --- a/release/src/router/ntfs-3g/missing +++ b/release/src/router/ntfs-3g/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -scriptversion=2005-06-08.21 +scriptversion=2006-05-10.23 -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. @@ -33,6 +33,8 @@ if test $# -eq 0; then fi run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. @@ -44,7 +46,7 @@ fi msg="missing on your system" -case "$1" in +case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= @@ -77,6 +79,7 @@ Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c @@ -106,7 +109,7 @@ esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). -case "$1" in +case $1 in lex|yacc) # Not GNU programs, they don't have --version. ;; @@ -135,7 +138,7 @@ esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. -case "$1" in +case $1 in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if @@ -164,7 +167,7 @@ WARNING: \`$1' is $msg. You should only need it if test -z "$files" && files="config.h" touch_files= for f in $files; do - case "$f" in + case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; @@ -192,8 +195,8 @@ WARNING: \`$1' is needed, but is $msg. You can get \`$1' as part of \`Autoconf' from any GNU archive site." - file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` - test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else @@ -214,25 +217,25 @@ WARNING: \`$1' $msg. You should only need it if in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then + if test $# -ne 1; then eval LASTARG="\${$#}" - case "$LASTARG" in + case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then + if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then + if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi - if [ ! -f y.tab.h ]; then + if test ! -f y.tab.h; then echo >y.tab.h fi - if [ ! -f y.tab.c ]; then + if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; @@ -244,18 +247,18 @@ WARNING: \`$1' is $msg. You should only need it if in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c - if [ $# -ne 1 ]; then + if test $# -ne 1; then eval LASTARG="\${$#}" - case "$LASTARG" in + case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then + if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi - if [ ! -f lex.yy.c ]; then + if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; @@ -267,11 +270,9 @@ WARNING: \`$1' is $msg. You should only need it if \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then touch $file else test -z "$file" || exec >$file @@ -289,11 +290,17 @@ WARNING: \`$1' is $msg. You should only need it if DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi @@ -317,13 +324,13 @@ WARNING: \`$1' is $msg. You should only need it if fi firstarg="$1" if shift; then - case "$firstarg" in + case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac - case "$firstarg" in + case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 diff --git a/release/src/router/ntfs-3g/src/Makefile.am b/release/src/router/ntfs-3g/src/Makefile.am index 22d702542c..153ef63eaf 100644 --- a/release/src/router/ntfs-3g/src/Makefile.am +++ b/release/src/router/ntfs-3g/src/Makefile.am @@ -9,10 +9,13 @@ FUSE_CFLAGS = $(FUSE_MODULE_CFLAGS) FUSE_LIBS = $(FUSE_MODULE_LIBS) endif -bin_PROGRAMS = ntfs-3g.probe +bin_PROGRAMS = ntfs-3g.probe ntfs-3g.usermap ntfs-3g.secaudit rootbin_PROGRAMS = ntfs-3g rootsbin_DATA = #Create directory -man_MANS = ntfs-3g.8 ntfs-3g.probe.8 +man_MANS = ntfs-3g.8 \ + ntfs-3g.probe.8 \ + ntfs-3g.usermap.8 \ + ntfs-3g.secaudit.8 ntfs_3g_LDADD = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la if REALLYSTATIC @@ -26,11 +29,20 @@ ntfs_3g_CFLAGS = \ ntfs_3g_SOURCES = ntfs-3g.c ntfs_3g_probe_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_usermap_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_secaudit_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la if REALLYSTATIC ntfs_3g_probe_LDFLAGS = $(AM_LDFLAGS) -all-static +ntfs_3g_usermap_LDFLAGS = $(AM_LDFLAGS) -all-static +ntfs_3g_secaudit_LDFLAGS= $(AM_LDFLAGS) -all-static endif ntfs_3g_probe_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g +ntfs_3g_usermap_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g +ntfs_3g_secaudit_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g + ntfs_3g_probe_SOURCES = ntfs-3g.probe.c +ntfs_3g_usermap_SOURCES = usermap.c +ntfs_3g_secaudit_SOURCES= secaudit.c if RUN_LDCONFIG install-exec-hook: diff --git a/release/src/router/ntfs-3g/src/Makefile.in b/release/src/router/ntfs-3g/src/Makefile.in index e4f27b5d03..e6335fc259 100644 --- a/release/src/router/ntfs-3g/src/Makefile.in +++ b/release/src/router/ntfs-3g/src/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008 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. @@ -15,15 +15,11 @@ @SET_MAKE@ -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -38,18 +34,21 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -bin_PROGRAMS = ntfs-3g.probe$(EXEEXT) +bin_PROGRAMS = ntfs-3g.probe$(EXEEXT) ntfs-3g.usermap$(EXEEXT) \ + ntfs-3g.secaudit$(EXEEXT) rootbin_PROGRAMS = ntfs-3g$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/ntfs-3g.8.in $(srcdir)/ntfs-3g.probe.8.in + $(srcdir)/ntfs-3g.8.in $(srcdir)/ntfs-3g.probe.8.in \ + $(srcdir)/ntfs-3g.secaudit.8.in $(srcdir)/ntfs-3g.usermap.8.in 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) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = ntfs-3g.8 ntfs-3g.probe.8 +CONFIG_CLEAN_FILES = ntfs-3g.8 ntfs-3g.probe.8 ntfs-3g.usermap.8 \ + ntfs-3g.secaudit.8 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(rootbindir)" \ "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(rootsbindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -61,22 +60,45 @@ am__DEPENDENCIES_1 = @FUSE_INTERNAL_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) ntfs_3g_DEPENDENCIES = $(am__DEPENDENCIES_2) \ $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(ntfs_3g_CFLAGS) $(CFLAGS) \ + $(ntfs_3g_LDFLAGS) $(LDFLAGS) -o $@ am_ntfs_3g_probe_OBJECTS = ntfs_3g_probe-ntfs-3g.probe.$(OBJEXT) ntfs_3g_probe_OBJECTS = $(am_ntfs_3g_probe_OBJECTS) ntfs_3g_probe_DEPENDENCIES = $(top_builddir)/libntfs-3g/libntfs-3g.la -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +ntfs_3g_probe_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfs_3g_probe_CFLAGS) \ + $(CFLAGS) $(ntfs_3g_probe_LDFLAGS) $(LDFLAGS) -o $@ +am_ntfs_3g_secaudit_OBJECTS = ntfs_3g_secaudit-secaudit.$(OBJEXT) +ntfs_3g_secaudit_OBJECTS = $(am_ntfs_3g_secaudit_OBJECTS) +ntfs_3g_secaudit_DEPENDENCIES = \ + $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_secaudit_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfs_3g_secaudit_CFLAGS) \ + $(CFLAGS) $(ntfs_3g_secaudit_LDFLAGS) $(LDFLAGS) -o $@ +am_ntfs_3g_usermap_OBJECTS = ntfs_3g_usermap-usermap.$(OBJEXT) +ntfs_3g_usermap_OBJECTS = $(am_ntfs_3g_usermap_OBJECTS) +ntfs_3g_usermap_DEPENDENCIES = \ + $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_usermap_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ntfs_3g_usermap_CFLAGS) \ + $(CFLAGS) $(ntfs_3g_usermap_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(ntfs_3g_SOURCES) $(ntfs_3g_probe_SOURCES) -DIST_SOURCES = $(ntfs_3g_SOURCES) $(ntfs_3g_probe_SOURCES) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(ntfs_3g_SOURCES) $(ntfs_3g_probe_SOURCES) \ + $(ntfs_3g_secaudit_SOURCES) $(ntfs_3g_usermap_SOURCES) +DIST_SOURCES = $(ntfs_3g_SOURCES) $(ntfs_3g_probe_SOURCES) \ + $(ntfs_3g_secaudit_SOURCES) $(ntfs_3g_usermap_SOURCES) man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) @@ -92,8 +114,6 @@ ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -112,26 +132,20 @@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ -ENABLE_MOUNT_HELPER_FALSE = @ENABLE_MOUNT_HELPER_FALSE@ -ENABLE_MOUNT_HELPER_TRUE = @ENABLE_MOUNT_HELPER_TRUE@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ -FUSE_INTERNAL_FALSE = @FUSE_INTERNAL_FALSE@ -FUSE_INTERNAL_TRUE = @FUSE_INTERNAL_TRUE@ FUSE_MODULE_CFLAGS = @FUSE_MODULE_CFLAGS@ FUSE_MODULE_LIBS = @FUSE_MODULE_LIBS@ -GENERATE_LDSCRIPT_FALSE = @GENERATE_LDSCRIPT_FALSE@ -GENERATE_LDSCRIPT_TRUE = @GENERATE_LDSCRIPT_TRUE@ GREP = @GREP@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LIBRARY_FALSE = @INSTALL_LIBRARY_FALSE@ -INSTALL_LIBRARY_TRUE = @INSTALL_LIBRARY_TRUE@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ @@ -145,13 +159,10 @@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MV = @MV@ -NTFS_DEVICE_DEFAULT_IO_OPS_FALSE = @NTFS_DEVICE_DEFAULT_IO_OPS_FALSE@ -NTFS_DEVICE_DEFAULT_IO_OPS_TRUE = @NTFS_DEVICE_DEFAULT_IO_OPS_TRUE@ +NMEDIT = @NMEDIT@ OBJEXT = @OBJEXT@ OUTPUT_FORMAT = @OUTPUT_FORMAT@ PACKAGE = @PACKAGE@ @@ -163,25 +174,19 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ -REALLYSTATIC_FALSE = @REALLYSTATIC_FALSE@ -REALLYSTATIC_TRUE = @REALLYSTATIC_TRUE@ RM = @RM@ -RUN_LDCONFIG_FALSE = @RUN_LDCONFIG_FALSE@ -RUN_LDCONFIG_TRUE = @RUN_LDCONFIG_TRUE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ -WINDOWS_FALSE = @WINDOWS_FALSE@ -WINDOWS_TRUE = @WINDOWS_TRUE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -193,6 +198,7 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -225,19 +231,26 @@ rootlibdir = @rootlibdir@ rootsbindir = @rootsbindir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in @FUSE_INTERNAL_FALSE@FUSE_CFLAGS = $(FUSE_MODULE_CFLAGS) @FUSE_INTERNAL_TRUE@FUSE_CFLAGS = -I$(top_srcdir)/include/fuse-lite @FUSE_INTERNAL_FALSE@FUSE_LIBS = $(FUSE_MODULE_LIBS) @FUSE_INTERNAL_TRUE@FUSE_LIBS = rootsbin_DATA = #Create directory -man_MANS = ntfs-3g.8 ntfs-3g.probe.8 +man_MANS = ntfs-3g.8 \ + ntfs-3g.probe.8 \ + ntfs-3g.usermap.8 \ + ntfs-3g.secaudit.8 + ntfs_3g_LDADD = $(FUSE_LIBS) $(top_builddir)/libntfs-3g/libntfs-3g.la @REALLYSTATIC_TRUE@ntfs_3g_LDFLAGS = $(AM_LDFLAGS) -all-static ntfs_3g_CFLAGS = \ @@ -248,9 +261,17 @@ ntfs_3g_CFLAGS = \ ntfs_3g_SOURCES = ntfs-3g.c ntfs_3g_probe_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_usermap_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la +ntfs_3g_secaudit_LDADD = $(top_builddir)/libntfs-3g/libntfs-3g.la @REALLYSTATIC_TRUE@ntfs_3g_probe_LDFLAGS = $(AM_LDFLAGS) -all-static +@REALLYSTATIC_TRUE@ntfs_3g_usermap_LDFLAGS = $(AM_LDFLAGS) -all-static +@REALLYSTATIC_TRUE@ntfs_3g_secaudit_LDFLAGS = $(AM_LDFLAGS) -all-static ntfs_3g_probe_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g +ntfs_3g_usermap_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g +ntfs_3g_secaudit_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g ntfs_3g_probe_SOURCES = ntfs-3g.probe.c +ntfs_3g_usermap_SOURCES = usermap.c +ntfs_3g_secaudit_SOURCES = secaudit.c all: all-am .SUFFIXES: @@ -288,17 +309,21 @@ ntfs-3g.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.8.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ ntfs-3g.probe.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.probe.8.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +ntfs-3g.usermap.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.usermap.8.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +ntfs-3g.secaudit.8: $(top_builddir)/config.status $(srcdir)/ntfs-3g.secaudit.8.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done @@ -318,15 +343,15 @@ clean-binPROGRAMS: done install-rootbinPROGRAMS: $(rootbin_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(rootbindir)" || $(mkdir_p) "$(DESTDIR)$(rootbindir)" + test -z "$(rootbindir)" || $(MKDIR_P) "$(DESTDIR)$(rootbindir)" @list='$(rootbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(rootbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(rootbindir)/$$f'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(rootbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(rootbindir)/$$f" || exit 1; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(rootbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(rootbindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(rootbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(rootbindir)/$$f" || exit 1; \ else :; fi; \ done @@ -346,10 +371,16 @@ clean-rootbinPROGRAMS: done ntfs-3g$(EXEEXT): $(ntfs_3g_OBJECTS) $(ntfs_3g_DEPENDENCIES) @rm -f ntfs-3g$(EXEEXT) - $(LINK) $(ntfs_3g_LDFLAGS) $(ntfs_3g_OBJECTS) $(ntfs_3g_LDADD) $(LIBS) + $(ntfs_3g_LINK) $(ntfs_3g_OBJECTS) $(ntfs_3g_LDADD) $(LIBS) ntfs-3g.probe$(EXEEXT): $(ntfs_3g_probe_OBJECTS) $(ntfs_3g_probe_DEPENDENCIES) @rm -f ntfs-3g.probe$(EXEEXT) - $(LINK) $(ntfs_3g_probe_LDFLAGS) $(ntfs_3g_probe_OBJECTS) $(ntfs_3g_probe_LDADD) $(LIBS) + $(ntfs_3g_probe_LINK) $(ntfs_3g_probe_OBJECTS) $(ntfs_3g_probe_LDADD) $(LIBS) +ntfs-3g.secaudit$(EXEEXT): $(ntfs_3g_secaudit_OBJECTS) $(ntfs_3g_secaudit_DEPENDENCIES) + @rm -f ntfs-3g.secaudit$(EXEEXT) + $(ntfs_3g_secaudit_LINK) $(ntfs_3g_secaudit_OBJECTS) $(ntfs_3g_secaudit_LDADD) $(LIBS) +ntfs-3g.usermap$(EXEEXT): $(ntfs_3g_usermap_OBJECTS) $(ntfs_3g_usermap_DEPENDENCIES) + @rm -f ntfs-3g.usermap$(EXEEXT) + $(ntfs_3g_usermap_LINK) $(ntfs_3g_usermap_OBJECTS) $(ntfs_3g_usermap_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -359,68 +390,94 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g-ntfs-3g.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_secaudit-secaudit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfs_3g_usermap-usermap.Po@am__quote@ .c.o: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< ntfs_3g-ntfs-3g.o: ntfs-3g.c -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.o -MD -MP -MF "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo" -c -o ntfs_3g-ntfs-3g.o `test -f 'ntfs-3g.c' || echo '$(srcdir)/'`ntfs-3g.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo" "$(DEPDIR)/ntfs_3g-ntfs-3g.Po"; else rm -f "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.o -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo -c -o ntfs_3g-ntfs-3g.o `test -f 'ntfs-3g.c' || echo '$(srcdir)/'`ntfs-3g.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntfs-3g.c' object='ntfs_3g-ntfs-3g.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g.o `test -f 'ntfs-3g.c' || echo '$(srcdir)/'`ntfs-3g.c ntfs_3g-ntfs-3g.obj: ntfs-3g.c -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.obj -MD -MP -MF "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo" -c -o ntfs_3g-ntfs-3g.obj `if test -f 'ntfs-3g.c'; then $(CYGPATH_W) 'ntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.c'; fi`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo" "$(DEPDIR)/ntfs_3g-ntfs-3g.Po"; else rm -f "$(DEPDIR)/ntfs_3g-ntfs-3g.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -MT ntfs_3g-ntfs-3g.obj -MD -MP -MF $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo -c -o ntfs_3g-ntfs-3g.obj `if test -f 'ntfs-3g.c'; then $(CYGPATH_W) 'ntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g-ntfs-3g.Tpo $(DEPDIR)/ntfs_3g-ntfs-3g.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntfs-3g.c' object='ntfs_3g-ntfs-3g.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_CFLAGS) $(CFLAGS) -c -o ntfs_3g-ntfs-3g.obj `if test -f 'ntfs-3g.c'; then $(CYGPATH_W) 'ntfs-3g.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.c'; fi` ntfs_3g_probe-ntfs-3g.probe.o: ntfs-3g.probe.c -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.o -MD -MP -MF "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo" -c -o ntfs_3g_probe-ntfs-3g.probe.o `test -f 'ntfs-3g.probe.c' || echo '$(srcdir)/'`ntfs-3g.probe.c; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo" "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po"; else rm -f "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.o -MD -MP -MF $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo -c -o ntfs_3g_probe-ntfs-3g.probe.o `test -f 'ntfs-3g.probe.c' || echo '$(srcdir)/'`ntfs-3g.probe.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntfs-3g.probe.c' object='ntfs_3g_probe-ntfs-3g.probe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -c -o ntfs_3g_probe-ntfs-3g.probe.o `test -f 'ntfs-3g.probe.c' || echo '$(srcdir)/'`ntfs-3g.probe.c ntfs_3g_probe-ntfs-3g.probe.obj: ntfs-3g.probe.c -@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.obj -MD -MP -MF "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo" -c -o ntfs_3g_probe-ntfs-3g.probe.obj `if test -f 'ntfs-3g.probe.c'; then $(CYGPATH_W) 'ntfs-3g.probe.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.probe.c'; fi`; \ -@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo" "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po"; else rm -f "$(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo"; exit 1; fi +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -MT ntfs_3g_probe-ntfs-3g.probe.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo -c -o ntfs_3g_probe-ntfs-3g.probe.obj `if test -f 'ntfs-3g.probe.c'; then $(CYGPATH_W) 'ntfs-3g.probe.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.probe.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Tpo $(DEPDIR)/ntfs_3g_probe-ntfs-3g.probe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntfs-3g.probe.c' object='ntfs_3g_probe-ntfs-3g.probe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_probe_CFLAGS) $(CFLAGS) -c -o ntfs_3g_probe-ntfs-3g.probe.obj `if test -f 'ntfs-3g.probe.c'; then $(CYGPATH_W) 'ntfs-3g.probe.c'; else $(CYGPATH_W) '$(srcdir)/ntfs-3g.probe.c'; fi` +ntfs_3g_secaudit-secaudit.o: secaudit.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -MT ntfs_3g_secaudit-secaudit.o -MD -MP -MF $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo -c -o ntfs_3g_secaudit-secaudit.o `test -f 'secaudit.c' || echo '$(srcdir)/'`secaudit.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo $(DEPDIR)/ntfs_3g_secaudit-secaudit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='secaudit.c' object='ntfs_3g_secaudit-secaudit.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -c -o ntfs_3g_secaudit-secaudit.o `test -f 'secaudit.c' || echo '$(srcdir)/'`secaudit.c + +ntfs_3g_secaudit-secaudit.obj: secaudit.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -MT ntfs_3g_secaudit-secaudit.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo -c -o ntfs_3g_secaudit-secaudit.obj `if test -f 'secaudit.c'; then $(CYGPATH_W) 'secaudit.c'; else $(CYGPATH_W) '$(srcdir)/secaudit.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_secaudit-secaudit.Tpo $(DEPDIR)/ntfs_3g_secaudit-secaudit.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='secaudit.c' object='ntfs_3g_secaudit-secaudit.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_secaudit_CFLAGS) $(CFLAGS) -c -o ntfs_3g_secaudit-secaudit.obj `if test -f 'secaudit.c'; then $(CYGPATH_W) 'secaudit.c'; else $(CYGPATH_W) '$(srcdir)/secaudit.c'; fi` + +ntfs_3g_usermap-usermap.o: usermap.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -MT ntfs_3g_usermap-usermap.o -MD -MP -MF $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo -c -o ntfs_3g_usermap-usermap.o `test -f 'usermap.c' || echo '$(srcdir)/'`usermap.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo $(DEPDIR)/ntfs_3g_usermap-usermap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='usermap.c' object='ntfs_3g_usermap-usermap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -c -o ntfs_3g_usermap-usermap.o `test -f 'usermap.c' || echo '$(srcdir)/'`usermap.c + +ntfs_3g_usermap-usermap.obj: usermap.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -MT ntfs_3g_usermap-usermap.obj -MD -MP -MF $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo -c -o ntfs_3g_usermap-usermap.obj `if test -f 'usermap.c'; then $(CYGPATH_W) 'usermap.c'; else $(CYGPATH_W) '$(srcdir)/usermap.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/ntfs_3g_usermap-usermap.Tpo $(DEPDIR)/ntfs_3g_usermap-usermap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='usermap.c' object='ntfs_3g_usermap-usermap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntfs_3g_usermap_CFLAGS) $(CFLAGS) -c -o ntfs_3g_usermap-usermap.obj `if test -f 'usermap.c'; then $(CYGPATH_W) 'usermap.c'; else $(CYGPATH_W) '$(srcdir)/usermap.c'; fi` + mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) - test -z "$(man8dir)" || $(mkdir_p) "$(DESTDIR)$(man8dir)" + test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ @@ -465,7 +522,7 @@ uninstall-man8: done install-rootsbinDATA: $(rootsbin_DATA) @$(NORMAL_INSTALL) - test -z "$(rootsbindir)" || $(mkdir_p) "$(DESTDIR)$(rootsbindir)" + test -z "$(rootsbindir)" || $(MKDIR_P) "$(DESTDIR)$(rootsbindir)" @list='$(rootsbin_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ @@ -486,8 +543,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -499,8 +556,8 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ @@ -510,13 +567,12 @@ ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique @@ -530,22 +586,21 @@ 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)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @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; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -561,7 +616,7 @@ check: check-am all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(rootbindir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(rootsbindir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am @@ -599,7 +654,7 @@ distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags + distclean-tags dvi: dvi-am @@ -614,14 +669,22 @@ info-am: install-data-am: install-data-local install-man \ install-rootbinPROGRAMS install-rootsbinDATA +install-dvi: install-dvi-am + install-exec-am: install-binPROGRAMS install-exec-local @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + install-info: install-info-am install-man: install-man8 +install-pdf: install-pdf-am + +install-ps: install-ps-am + installcheck-am: maintainer-clean: maintainer-clean-am @@ -642,25 +705,29 @@ ps: ps-am ps-am: -uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-local \ - uninstall-man uninstall-rootbinPROGRAMS uninstall-rootsbinDATA +uninstall-am: uninstall-binPROGRAMS uninstall-local uninstall-man \ + uninstall-rootbinPROGRAMS uninstall-rootsbinDATA uninstall-man: uninstall-man8 +.MAKE: install-am install-exec-am install-strip + .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-rootbinPROGRAMS ctags \ 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-data-local install-exec \ - install-exec-am install-exec-hook install-exec-local \ - install-info install-info-am install-man install-man8 \ + install-data install-data-am install-data-local install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-hook \ + install-exec-local install-html install-html-am install-info \ + install-info-am install-man install-man8 install-pdf \ + install-pdf-am install-ps install-ps-am \ install-rootbinPROGRAMS install-rootsbinDATA 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 uninstall uninstall-am uninstall-binPROGRAMS \ - uninstall-info-am uninstall-local uninstall-man uninstall-man8 \ + uninstall-local uninstall-man uninstall-man8 \ uninstall-rootbinPROGRAMS uninstall-rootsbinDATA diff --git a/release/src/router/ntfs-3g/src/ntfs-3g.8.in b/release/src/router/ntfs-3g/src/ntfs-3g.8.in index d2c75646a5..ec18c51c9b 100644 --- a/release/src/router/ntfs-3g/src/ntfs-3g.8.in +++ b/release/src/router/ntfs-3g/src/ntfs-3g.8.in @@ -1,26 +1,27 @@ .\" Copyright (c) 2005-2006 Yura Pakhuchiy. .\" Copyright (c) 2005 Richard Russon. .\" Copyright (c) 2006-2009 Szabolcs Szakacsits. +.\" Copyright (c) 2009 Jean-Pierre Andre .\" This file may be copied under the terms of the GNU Public License. .\" -.TH NTFS-3G 8 "March 2009" "ntfs-3g @VERSION@" +.TH NTFS-3G 8 "November 2009" "ntfs-3g @VERSION@" .SH NAME ntfs-3g \- Third Generation Read/Write NTFS Driver .SH SYNOPSIS .B ntfs-3g -\fB[-o \fIoption\fP\fB[,...]]\fR .I volume mount_point +\fB[-o \fIoption\fP\fB[,...]]\fR .br .B mount \-t ntfs-3g -\fB[-o \fIoption\fP\fB[,...]]\fR .I volume mount_point +\fB[-o \fIoption\fP\fB[,...]]\fR .SH DESCRIPTION \fBntfs-3g\fR is an NTFS driver, which can create, remove, rename, move files, directories, hard links, and streams; it can read and write files, including streams and sparse files; it can handle special files like symbolic links, devices, and FIFOs; moreover it can also read -transparently compressed files. +and create transparently compressed files. .PP The \fIvolume\fR to be mounted can be either a block device or an image file. @@ -28,7 +29,7 @@ an image file. By default, files and directories are owned by the effective user and group of the mounting process and everybody has full read, write, execution and directory browsing permissions. -If you want to use permissions handling then use the +You can also assign permissions to a single user by using the .B uid and/or the .B gid @@ -40,12 +41,13 @@ and .B dmask options. .PP -Windows users have full access to the files created by +Doing so, Windows users have full access to the files created by .B ntfs-3g. .PP -Full ownership and permission support, including Windows user mapping -and POSIX file system compliance, is provided by the Advanced NTFS-3G -driver. +But, by defining a Windows-to-Linux user mapping in the file +\fB.NTFS-3G/UserMapping\fP, you can benefit from the full ownership and +permissions features as defined by Posix and those ownership and +permissions will be applied to Windows users and conversely. .PP If .B ntfs-3g @@ -73,16 +75,11 @@ For example: cat some.mp3:artist .sp .RE -Named data streams act like normals files, so you can read from them, write to +Named data streams act like normal files, so you can read from them, write to them and even delete them (using rm). You can list all the named data streams a file has by getting the "ntfs.streams.list" extended attribute. .SH OPTIONS -Most of the generic mount options described in -. BR mount (8) -are -supported (ro, rw, suid, nosuid, dev, nodev, exec, noexec). -Below is a summary of the options that \fBntfs-3g\fR additionally -accepts. +Below is a summary of the options that \fBntfs-3g\fR accepts. .TP \fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP Set the owner and the group of files and directories. The values are numerical. @@ -103,8 +100,45 @@ Set the bitmask of the directory permissions that are not present. The value is given in octal. The default value is 0 which means full access to everybody. .TP +.BI usermapping= file-name +Use file \fIfile-name\fP as the user mapping file instead of the default +\fB.NTFS-3G/UserMapping\fP. If \fIfile-name\fP defines a full path, the +file must be located on a partition previously mounted. If it defines a +relative path, it is interpreted relative to the root of NTFS partition +being mounted. +.P +.RS +When a user mapping file is defined, the options \fBuid=\fP, \fBgid=\fP, +\fBumask=\fP, \fBfmask=\fP, \fBdmask=\fP and \fBdsilent=\fP are ignored. +.RE +.TP +.B default_permissions +Use standard access control. This option requires either a user mapping +file to be present, or the options \fIuid=\fP and \fIgid=\fP of a user +to be defined. This option is set by default when a user mapping file +or an ownership related option is present. +.TP +.B inherit +When creating a new file, set its initial ownership and protections +according to inheritance rules defined in parent directory. These rules +deviate from Posix specifications, but yield a better Windows +compatibility. A valid user mapping file is required for this option +to be effective. +.TP .B ro -Mount filesystem read\-only. Useful if Windows is hibernated. +Mount filesystem read\-only. Useful if Windows is hibernated or the +NTFS journal file is unclean. +.TP +.BI locale= value +This option can be useful when wanting a language specific locale environment. +It is however discouraged as it leads to files with untranslatable chars +to not be visible. Please see more information about this topic at +http://ntfs-3g.org/support.html#locale +.TP +.B force +Force the mounting even if the NTFS logfile is unclean. The logfile +will be unconditionally cleared. Use this option with caution and for +your own responsibility. .TP .B remove_hiberfile Unlike in case of read-only mount, the read-write mount is denied if @@ -114,11 +148,6 @@ hibernation file. Please note, this means that the saved Windows session will be completely lost. Use this option for your own responsibility. .TP -.B recover, norecover -Recover and repair a corrupted or inconsistent -NTFS volume if it's possible. The default behaviour is -.B recover. -.TP .B atime, noatime, relatime The .B atime @@ -151,26 +180,22 @@ Furthermore, irrespectively of show_sys_files, all files are accessible by name, for example you can always do "ls \-l '$UpCase'". .TP +.B allow_other +This option overrides the security measure restricting file access +to the user mounting the filesystem. This option is only +allowed to root, but this restriction can be overridden by +the 'user_allow_other' option in the /etc/fuse.conf file. +.TP .BI max_read= value With this option the maximum size of read operations can be set. The default is infinite. Note that the size of read requests is limited anyway to 32 pages (which is 128kbyte on i386). .TP .B silent -Do not return error for chown and chmod unless access right -handling is turned on by either of the -.B uid, -.B gid, -.B umask, -.B fmask, -or -.B dmask -option. +Do nothing on chmod and chown operations, but do not return error +when the user mapping file required by these operations is not defined. This option is on by default. .TP -.BI locale= value -Prints informative and diagnostic messages in the set locale. -.TP .B no_def_opts By default ntfs-3g acts as "silent" was passed to it, this option cancel this behaviour. @@ -183,22 +208,65 @@ to, one of \fBnone\fR, \fBwindows\fR or \fBxattr\fR. If the option is set to to \fBwindows\fR, then the user can access them just like in Windows (eg. cat file:stream). If it's set to \fBxattr\fR, then the named data streams are mapped to xattrs and user can manipulate them using \fB{get,set}fattr\fR -utilities. The default is \fBxattr\fR on Linux, \fBnone\fR on other OSes. +utilities. The default is \fBxattr\fR. .TP -.B force -This mount option is not used anymore. It was superseded by the -.B recover -and -.B norecover -options. +.B user_xattr +Same as \fBstreams_interface=\fP\fIxattr\fP. +.TP +.B efs_raw +This option should only be used in backup or restore situation. +It changes the apparent size of files and the behavior of read and +write operation so that encrypted files can be saved and restored +without being decrypted. The \fBuser.ntfs.efsinfo\fP extended attribute +has also to be saved and restored for the file to be decrypted. .TP .B debug -Makes ntfs-3g to not detach from terminal and print a lot of driver debug output. +Makes ntfs-3g to not detach from terminal and print a lot of debug output from +libntfs-3g and FUSE. .TP .B no_detach Same as above but with less debug output. +.SH USER MAPPING +NTFS uses specific ids to record the ownership of files instead of +the \fBuid\fP and \fBgid\fP used by Linux. As a consequence a mapping +between the ids has to be defined for ownerships to be recorded into +NTFS and recognized. +.P +By default this mapping is fetched from the file \fB.NTFS-3G/UserMapping\fP +located in the NTFS partition. The option \fBusermapping=\fP may be used +to define another location. +.P +Each line in the user mapping file defines a mapping. It is organized +in three fields separated by colons. The first field identifies a \fBuid\fP, +the second field identifies a \fBgid\fP and the third one identifies the +corresponding NTFS id, known as a \fBSID\fP. The \fBuid\fP and the \fBgid\fP +are optional and defining both of them for the same \fBSID\fP is not +recommended. +.P +If no interoperation with Windows is needed, a single default mapping +with no uid and gid can be used. Just copy the example below and replace +the 9 and 10-digit numbers by any number not greater than 4294967295. +.RS +.sp +.B ::S-1-5-21-3141592653-589793238-462643383-10000 +.sp +.RE +If interoperation with Windows is needed, the mapping has to be defined +for each user and group known in both system, and the \fBSID\fPs used +by Windows has to be collected. This will lead to a user mapping file +like : +.RS +.sp +.B john::S-1-5-21-3141592653-589793238-462643383-1008 +.B mary::S-1-5-21-3141592653-589793238-462643383-1009 +.B :smith:S-1-5-21-3141592653-589793238-462643383-513 +.B ::S-1-5-21-3141592653-589793238-462643383-10000 +.sp +.RE +.P +The utility \fBntfs-3g.usermap\fP may be used to create the user mapping file. .SH EXAMPLES -Mount /dev/sda1 to /mnt/windows (make sure /mnt/windows exists): +Mount /dev/sda1 to /mnt/windows: .RS .sp .B ntfs-3g /dev/sda1 /mnt/windows @@ -214,7 +282,7 @@ Read\-only mount /dev/sda5 to /home/user/mnt and make user with uid 1000 to be the owner of all files: .RS .sp -.B ntfs-3g \-o ro,uid=1000 /dev/sda5 /home/user/mnt +.B ntfs-3g /dev/sda5 /home/user/mnt \-o ro,uid=1000 .sp .RE /etc/fstab entry for the above: @@ -241,21 +309,29 @@ manual page. Please see .RS .sp -http://ntfs-3g.org/support.html +http://www.tuxera.com/support/ .sp .RE -for common questions, known issues and support. -.SH ACKNOWLEDGEMENT +for common questions and known issues. +If you would find a new one in the latest release of +the software then please send an email describing it +in detail. You can contact the +development team on the ntfs\-3g\-devel@lists.sf.net +address. +.SH AUTHORS +.B ntfs-3g +was based on and a major improvement to ntfsmount and libntfs which were +written by Yura Pakhuchiy and the Linux-NTFS team. The improvements were +made, the ntfs-3g project was initiated and currently led by long time +Linux-NTFS team developer Szabolcs Szakacsits (szaka@tuxera.com). +.SH THANKS Several people made heroic efforts, often over five or more years which resulted the ntfs-3g driver. Most importantly they are -Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy, -Yuval Fledel, Jean-Pierre Andre, Alon Bar-Lev, Dominique L Bouix, -Csaba Henk, Bernhard Kaindl, Erik Larsson, Alejandro Pulver, and -the author of the groundbreaking FUSE filesystem development -framework, Miklos Szeredi. +Anton Altaparmakov, Jean-Pierre André, Richard Russon, Szabolcs Szakacsits, +Yura Pakhuchiy, Yuval Fledel, and the author of the groundbreaking FUSE +filesystem development framework, Miklos Szeredi. .SH SEE ALSO .BR ntfs-3g.probe (8), .BR ntfsprogs (8), .BR attr (5), -.BR getfattr (1), -.BR setfattr (1) +.BR getfattr (1) diff --git a/release/src/router/ntfs-3g/src/ntfs-3g.c b/release/src/router/ntfs-3g/src/ntfs-3g.c index 8785bae08a..2ec127aaa5 100644 --- a/release/src/router/ntfs-3g/src/ntfs-3g.c +++ b/release/src/router/ntfs-3g/src/ntfs-3g.c @@ -83,6 +83,10 @@ #include #endif +#if defined(__APPLE__) || defined(__DARWIN__) +#include +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + #include "compat.h" #include "attrib.h" #include "inode.h" @@ -92,8 +96,14 @@ #include "layout.h" #include "index.h" #include "ntfstime.h" +#include "security.h" +#include "reparse.h" +#include "efs.h" +#include "logging.h" #include "misc.h" +#define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE + typedef enum { FSTYPE_NONE, FSTYPE_UNKNOWN, @@ -115,9 +125,15 @@ typedef struct { typedef enum { NF_STREAMS_INTERFACE_NONE, /* No access to named data streams. */ NF_STREAMS_INTERFACE_XATTR, /* Map named data streams to xattrs. */ + NF_STREAMS_INTERFACE_OPENXATTR, /* Same, not limited to "user." */ NF_STREAMS_INTERFACE_WINDOWS, /* "file:stream" interface. */ } ntfs_fuse_streams_interface; +enum { + CLOSE_COMPRESSED = 1, + CLOSE_ENCRYPTED = 2 +}; + typedef struct { ntfs_volume *vol; unsigned int uid; @@ -135,7 +151,13 @@ typedef struct { BOOL no_detach; BOOL blkdev; BOOL mounted; + BOOL efs_raw; struct fuse_chan *fc; + BOOL inherit; + unsigned int secure_flags; + char *usermap_path; + struct PERMISSIONS_CACHE *seccache; + struct SECURITY_CONTEXT security; } ntfs_fuse_context_t; static struct options { @@ -152,6 +174,17 @@ static u32 ntfs_sequence; static const char *usage_msg = "\n" "%s %s %s %d - Third Generation NTFS Driver\n" +"\t\t" +#ifdef HAVE_SETXATTR +"XATTRS are on, " +#else +"XATTRS are off, " +#endif +#if POSIXACLS +"POSIX ACLS are on\n" +#else +"POSIX ACLS are off\n" +#endif "\n" "Copyright (C) 2005-2007 Yura Pakhuchiy\n" "Copyright (C) 2006-2009 Szabolcs Szakacsits\n" @@ -168,6 +201,8 @@ static const char *usage_msg = "\n" "%s"; +static const char ntfs_bad_reparse[] = "unsupported reparse point"; + #ifdef FUSE_INTERNAL int drop_privs(void); int restore_privs(void); @@ -227,6 +262,37 @@ static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol) return nr_free; } +/* + * Fill a security context as needed by security functions + * returns TRUE if there is a user mapping, + * FALSE if there is none + * This is not an error and the context is filled anyway, + * it is used for implicit Windows-like inheritance + */ + +static BOOL ntfs_fuse_fill_security_context(struct SECURITY_CONTEXT *scx) +{ + struct fuse_context *fusecontext; + + scx->vol = ctx->vol; + scx->mapping[MAPUSERS] = ctx->security.mapping[MAPUSERS]; + scx->mapping[MAPGROUPS] = ctx->security.mapping[MAPGROUPS]; + scx->pseccache = &ctx->seccache; + fusecontext = fuse_get_context(); + scx->uid = fusecontext->uid; + scx->gid = fusecontext->gid; + scx->tid = fusecontext->pid; +#ifdef FUSE_CAP_DONT_MASK + /* the umask can be processed by the file system */ + scx->umask = fusecontext->umask; +#else + /* the umask if forced by fuse on creation */ + scx->umask = 0; +#endif + + return (ctx->security.mapping[MAPUSERS] != (struct MAPPING*)NULL); +} + /** * ntfs_fuse_statfs - return information about mounted NTFS volume * @path: ignored (but fuse requires it) @@ -413,14 +479,44 @@ int ntfs_macfuse_setbkuptime(const char *path, const struct timespec *tv) return -errno; /* - * Doing nothing while pretending to do something. NTFS has no backup - * time. If this function is not implemented then some apps break. + * Only pretending to set backup time successfully to please the APIs of + * Mac OS X. In reality, NTFS has no backup time. */ if (ntfs_inode_close(ni)) set_fuse_error(&res); return res; } + +int ntfs_macfuse_setchgtime(const char *path, const struct timespec *tv) +{ + ntfs_inode *ni; + int res = 0; + + if (ntfs_fuse_is_named_data_stream(path)) + return -EINVAL; /* n/a for named data streams. */ + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (!ni) + return -errno; + + if (tv) { + ni->last_mft_change_time = tv->tv_sec; + ntfs_fuse_update_times(ni, 0); + } + + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + return res; +} +#else /* defined(__APPLE__) || defined(__DARWIN__) */ +#ifdef FUSE_CAP_DONT_MASK +static void *ntfs_init(struct fuse_conn_info *conn) +{ + /* request umask not to be enforced by fuse */ + conn->want |= FUSE_CAP_DONT_MASK; + return NULL; +} +#endif #endif /* defined(__APPLE__) || defined(__DARWIN__) */ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) @@ -431,6 +527,8 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) char *path = NULL; ntfschar *stream_name; int stream_name_len; + BOOL withusermapping; + struct SECURITY_CONTEXT security; stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -441,20 +539,68 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) res = -errno; goto exit; } - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY && !stream_name_len) { - /* Directory. */ - stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask); - na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); - if (na) { - stbuf->st_size = na->data_size; - stbuf->st_blocks = na->allocated_size >> 9; - ntfs_attr_close(na); + withusermapping = ntfs_fuse_fill_security_context(&security); +#if POSIXACLS + /* + * make sure the parent directory is searchable + */ + if (withusermapping + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + res = -EACCES; + goto exit; + } +#endif + if (((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + || (ni->flags & FILE_ATTR_REPARSE_POINT)) + && !stream_name_len) { + if (ni->flags & FILE_ATTR_REPARSE_POINT) { + char *target; + int attr_size; + + errno = 0; + target = ntfs_make_symlink(org_path, ni, &attr_size); + /* + * If the reparse point is not a valid + * directory junction, and there is no error + * we still display as a symlink + */ + if (target || (errno == EOPNOTSUPP)) { + /* returning attribute size */ + if (target) + stbuf->st_size = attr_size; + else + stbuf->st_size = sizeof(ntfs_bad_reparse); + stbuf->st_blocks = (ni->allocated_size + 511) >> 9; + stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count); + stbuf->st_mode = S_IFLNK; + free(target); + } else { + res = -errno; + goto exit; + } + } else { + /* Directory. */ + stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask); + na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); + if (na) { + stbuf->st_size = na->data_size; + stbuf->st_blocks = na->allocated_size >> 9; + ntfs_attr_close(na); + } + stbuf->st_nlink = 1; /* Make find(1) work */ } - stbuf->st_nlink = 1; /* Make find(1) work */ } else { /* Regular or Interix (INTX) file. */ stbuf->st_mode = S_IFREG; stbuf->st_size = ni->data_size; + /* + * return data size rounded to next 512 byte boundary for + * encrypted files to include padding required for decryption + * also include 2 bytes for padding info + */ + if (ctx->efs_raw && ni->flags & FILE_ATTR_ENCRYPTED) + stbuf->st_size = ((ni->data_size + 511) & ~511) + 2; + /* * Temporary fix to make ActiveSync work via Samba 3.0. * See more on the ntfs-3g-devel list. @@ -483,14 +629,21 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) if (na->data_size == 1) stbuf->st_mode = S_IFSOCK; } + /* encrypted named stream */ + /* round size up to next 512 byte boundary */ + if (ctx->efs_raw && stream_name_len && + (na->data_flags & ATTR_IS_ENCRYPTED) && + NAttrNonResident(na)) + stbuf->st_size = ((na->data_size+511) & ~511)+2; /* * Check whether it's Interix symbolic link, block or * character device. */ - if (na->data_size <= sizeof(INTX_FILE_TYPES) + - sizeof(ntfschar) * PATH_MAX && - na->data_size > sizeof(INTX_FILE_TYPES) && - !stream_name_len) { + if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES) + + sizeof(ntfschar) * PATH_MAX + && (size_t)na->data_size > + sizeof(INTX_FILE_TYPES) + && !stream_name_len) { INTX_FILE *intx_file; @@ -533,8 +686,15 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) } stbuf->st_mode |= (0777 & ~ctx->fmask); } - stbuf->st_uid = ctx->uid; - stbuf->st_gid = ctx->gid; + if (withusermapping) { + if (ntfs_get_owner_mode(&security,path,ni,stbuf) < 0) + set_fuse_error(&res); + } else { + stbuf->st_uid = ctx->uid; + stbuf->st_gid = ctx->gid; + } + if (S_ISLNK(stbuf->st_mode)) + stbuf->st_mode |= 0777; stbuf->st_ino = ni->mft_no; stbuf->st_atime = ni->last_access_time; stbuf->st_ctime = ni->last_mft_change_time; @@ -570,6 +730,26 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size) res = -errno; goto exit; } + /* + * Reparse point : analyze as a junction point + */ + if (ni->flags & FILE_ATTR_REPARSE_POINT) { + char *target; + int attr_size; + + errno = 0; + res = 0; + target = ntfs_make_symlink(org_path, ni, &attr_size); + if (target) { + strncpy(buf,target,buf_size); + free(target); + } else + if (errno == EOPNOTSUPP) + strcpy(buf,ntfs_bad_reparse); + else + res = -errno; + goto exit; + } /* Sanity checks. */ if (!(ni->flags & FILE_ATTR_SYSTEM)) { res = -EINVAL; @@ -580,11 +760,11 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size) res = -errno; goto exit; } - if (na->data_size <= sizeof(INTX_FILE_TYPES)) { + if ((size_t)na->data_size <= sizeof(INTX_FILE_TYPES)) { res = -EINVAL; goto exit; } - if (na->data_size > sizeof(INTX_FILE_TYPES) + + if ((size_t)na->data_size > sizeof(INTX_FILE_TYPES) + sizeof(ntfschar) * PATH_MAX) { res = -ENAMETOOLONG; goto exit; @@ -631,11 +811,12 @@ static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx, { char *filename = NULL; int ret = 0; + int filenamelen = -1; if (name_type == FILE_NAME_DOS) return 0; - if (ntfs_ucstombs(name, name_len, &filename, 0) < 0) { + if ((filenamelen = ntfs_ucstombs(name, name_len, &filename, 0)) < 0) { ntfs_log_perror("Filename decoding failed (inode %llu)", (unsigned long long)MREF(mref)); return -1; @@ -658,6 +839,20 @@ static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx, else if (dt_type == NTFS_DT_DIR) st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); +#if defined(__APPLE__) || defined(__DARWIN__) + /* + * Returning file names larger than MAXNAMLEN (255) bytes + * causes Darwin/Mac OS X to bug out and skip the entry. + */ + if (filenamelen > MAXNAMLEN) { + ntfs_log_debug("Truncating %d byte filename to " + "%d bytes.\n", filenamelen, MAXNAMLEN); + ntfs_log_debug(" before: '%s'\n", filename); + memset(filename + MAXNAMLEN, 0, filenamelen - MAXNAMLEN); + ntfs_log_debug(" after: '%s'\n", filename); + } +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ + ret = fill_ctx->filler(fill_ctx->buf, filename, &st, 0); } @@ -665,6 +860,44 @@ static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx, return ret; } +#if POSIXACLS + +static int ntfs_fuse_opendir(const char *path, + struct fuse_file_info *fi) +{ + int res = 0; + ntfs_inode *ni; + int accesstype; + struct SECURITY_CONTEXT security; + + if (ntfs_fuse_is_named_data_stream(path)) + return -EINVAL; /* n/a for named data streams. */ + + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (ni) { + if (ntfs_fuse_fill_security_context(&security)) { + if (fi->flags & O_WRONLY) + accesstype = S_IWRITE; + else + if (fi->flags & O_RDWR) + accesstype = S_IWRITE | S_IREAD; + else + accesstype = S_IREAD; + /* directory must be searchable */ + if (!ntfs_allowed_dir_access(&security,path,S_IEXEC) + /* check whether requested access is allowed */ + || !ntfs_allowed_access(&security,path,ni,accesstype)) + res = -EACCES; + } + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + return res; +} + +#endif + static int ntfs_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset __attribute__((unused)), struct fuse_file_info *fi __attribute__((unused))) @@ -689,7 +922,11 @@ static int ntfs_fuse_readdir(const char *path, void *buf, } static int ntfs_fuse_open(const char *org_path, +#if POSIXACLS + struct fuse_file_info *fi) +#else struct fuse_file_info *fi __attribute__((unused))) +#endif { ntfs_inode *ni; ntfs_attr *na; @@ -697,6 +934,10 @@ static int ntfs_fuse_open(const char *org_path, char *path = NULL; ntfschar *stream_name; int stream_name_len; +#if POSIXACLS + int accesstype; + struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -705,8 +946,35 @@ static int ntfs_fuse_open(const char *org_path, if (ni) { na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); if (na) { - if (NAttrEncrypted(na)) - res = -EACCES; +#if POSIXACLS + if (ntfs_fuse_fill_security_context(&security)) { + if (fi->flags & O_WRONLY) + accesstype = S_IWRITE; + else + if (fi->flags & O_RDWR) + accesstype = S_IWRITE | S_IREAD; + else + accesstype = S_IREAD; + /* JPA directory must be searchable */ + if (!ntfs_allowed_dir_access(&security, + path,S_IEXEC) + /* JPA check whether requested access is allowed */ + || !ntfs_allowed_access(&security, + path,ni,accesstype)) + res = -EACCES; + } +#endif + if ((res >= 0) + && (fi->flags & (O_WRONLY | O_RDWR))) { + /* mark a future need to compress the last chunk */ + if (na->data_flags & ATTR_COMPRESSION_MASK) + fi->fh |= CLOSE_COMPRESSED; + /* mark a future need to fixup encrypted inode */ + if (ctx->efs_raw + && !(na->data_flags & ATTR_IS_ENCRYPTED) + && (ni->flags & FILE_ATTR_ENCRYPTED)) + fi->fh |= CLOSE_ENCRYPTED; + } ntfs_attr_close(na); } else res = -errno; @@ -729,6 +997,7 @@ static int ntfs_fuse_read(const char *org_path, char *buf, size_t size, ntfschar *stream_name; int stream_name_len, res; s64 total = 0; + s64 max_read; if (!size) return 0; @@ -746,13 +1015,19 @@ static int ntfs_fuse_read(const char *org_path, char *buf, size_t size, res = -errno; goto exit; } - if (offset + size > na->data_size) { - if (na->data_size < offset) + /* limit reads at next 512 byte boundary for encrypted attributes */ + max_read = na->data_size; + if (ctx->efs_raw && (na->data_flags & ATTR_IS_ENCRYPTED) && + NAttrNonResident(na)) { + max_read = ((na->data_size+511) & ~511) + 2; + } + if (offset + (off_t)size > max_read) { + if (max_read < offset) goto ok; - size = na->data_size - offset; + size = max_read - offset; } while (size > 0) { - s64 ret = ntfs_attr_pread(na, offset, size, buf); + s64 ret = ntfs_attr_pread(na, offset, size, buf + total); if (ret != (s64)size) ntfs_log_perror("ntfs_attr_pread error reading '%s' at " "offset %lld: %lld <> %lld", org_path, @@ -804,11 +1079,7 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size, goto exit; } while (size) { - s64 ret = ntfs_attr_pwrite(na, offset, size, buf); - if (0 <= ret && ret < (s64)size) - ntfs_log_perror("ntfs_attr_pwrite partial write to '%s'" - " (%lld: %lld <> %lld)", path, (long long)offset, - (long long)size, (long long)ret); + s64 ret = ntfs_attr_pwrite(na, offset, size, buf + total); if (ret <= 0) { res = -errno; goto exit; @@ -823,6 +1094,8 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size, exit: if (na) ntfs_attr_close(na); + if (total) + set_archive(ni); if (ntfs_inode_close(ni)) set_fuse_error(&res); free(path); @@ -832,7 +1105,62 @@ out: return res; } -static int ntfs_fuse_truncate(const char *org_path, off_t size) +static int ntfs_fuse_release(const char *org_path, + struct fuse_file_info *fi) +{ + ntfs_inode *ni = NULL; + ntfs_attr *na = NULL; + char *path = NULL; + ntfschar *stream_name; + int stream_name_len, res; + + /* Only for marked descriptors there is something to do */ + if (!(fi->fh & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED))) { + res = 0; + goto out; + } + stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); + if (stream_name_len < 0) { + res = stream_name_len; + goto out; + } + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (!ni) { + res = -errno; + goto exit; + } + na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); + if (!na) { + res = -errno; + goto exit; + } + res = 0; + if (fi->fh & CLOSE_COMPRESSED) + res = ntfs_attr_pclose(na); + if (fi->fh & CLOSE_ENCRYPTED) + res = ntfs_efs_fixup_attribute(NULL, na); +exit: + if (na) + ntfs_attr_close(na); + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + free(path); + if (stream_name_len) + free(stream_name); +out: + return res; +} + +/* + * Common part for truncate() and ftruncate() + */ + +static int ntfs_fuse_trunc(const char *org_path, off_t size, +#if POSIXACLS + BOOL chkwrite) +#else + BOOL chkwrite __attribute__((unused))) +#endif { ntfs_inode *ni = NULL; ntfs_attr *na = NULL; @@ -840,6 +1168,10 @@ static int ntfs_fuse_truncate(const char *org_path, off_t size) char *path = NULL; ntfschar *stream_name; int stream_name_len; + s64 oldsize; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -851,9 +1183,41 @@ static int ntfs_fuse_truncate(const char *org_path, off_t size) na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); if (!na) goto exit; - - if (ntfs_attr_truncate(na, size)) +#if POSIXACLS + /* + * JPA deny truncation if cannot search in parent directory + * or cannot write to file (already checked for ftruncate()) + */ + if (ntfs_fuse_fill_security_context(&security) + && (!ntfs_allowed_dir_access(&security, path, S_IEXEC) + || (chkwrite + && !ntfs_allowed_access(&security, path, ni, S_IWRITE)))) { + errno = EACCES; + goto exit; + } +#endif + /* + * for compressed files, only deleting contents and expanding + * are implemented. Expanding is done by inserting a final + * zero, which is optimized as creating a hole when possible. + */ + if ((na->data_flags & ATTR_COMPRESSION_MASK) + && size + && (size < na->initialized_size)) { + errno = EOPNOTSUPP; goto exit; + } + oldsize = na->data_size; + if ((na->data_flags & ATTR_COMPRESSION_MASK) + && (size > na->initialized_size)) { + char zero = 0; + if (ntfs_attr_pwrite(na, size - 1, 1, &zero) <= 0) + goto exit; + } else + if (ntfs_attr_truncate(na, size)) + goto exit; + if (oldsize != size) + set_archive(ni); ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME); errno = 0; @@ -868,92 +1232,310 @@ exit: return res; } +static int ntfs_fuse_truncate(const char *org_path, off_t size) +{ + return ntfs_fuse_trunc(org_path, size, TRUE); +} + +static int ntfs_fuse_ftruncate(const char *org_path, off_t size, + struct fuse_file_info *fi __attribute__((unused))) +{ + /* + * in ->ftruncate() the file handle is guaranteed + * to have been opened for write. + */ + return (ntfs_fuse_trunc(org_path, size, FALSE)); +} + static int ntfs_fuse_chmod(const char *path, - mode_t mode __attribute__((unused))) + mode_t mode) { + int res = 0; + ntfs_inode *ni; + struct SECURITY_CONTEXT security; + if (ntfs_fuse_is_named_data_stream(path)) return -EINVAL; /* n/a for named data streams. */ - if (ctx->silent) - return 0; - return -EOPNOTSUPP; + + /* JPA return unsupported if no user mapping has been defined */ + if (!ntfs_fuse_fill_security_context(&security)) { + if (ctx->silent) + res = 0; + else + res = -EOPNOTSUPP; + } else { +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { +#endif + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (!ni) + res = -errno; + else { + if (ntfs_set_mode(&security,path,ni,mode)) + res = -errno; + else + ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); + NInoSetDirty(ni); + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } +#if POSIXACLS + } else + res = -errno; +#endif + } + return res; } static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid) { + ntfs_inode *ni; + int res; + struct SECURITY_CONTEXT security; + if (ntfs_fuse_is_named_data_stream(path)) return -EINVAL; /* n/a for named data streams. */ - if (ctx->silent) - return 0; - if (uid == ctx->uid && gid == ctx->gid) - return 0; - return -EOPNOTSUPP; + if (!ntfs_fuse_fill_security_context(&security)) { + if (ctx->silent) + return 0; + if (uid == ctx->uid && gid == ctx->gid) + return 0; + return -EOPNOTSUPP; + } else { + res = 0; + if (((int)uid != -1) || ((int)gid != -1)) { +#if POSIXACLS + /* parent directory must be executable */ + + if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { +#endif + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (!ni) + res = -errno; + else { + if (ntfs_set_owner(&security, + path,ni,uid,gid)) + res = -errno; + else + ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } +#if POSIXACLS + } else + res = -errno; +#endif + } + } + return (res); +} + +#if POSIXACLS + +static int ntfs_fuse_access(const char *path, int type) +{ + int res = 0; + int mode; + ntfs_inode *ni; + struct SECURITY_CONTEXT security; + + if (ntfs_fuse_is_named_data_stream(path)) + return -EINVAL; /* n/a for named data streams. */ + + /* JPA return unsupported if no user mapping has been defined */ + if (!ntfs_fuse_fill_security_context(&security)) { + if (ctx->silent) + res = 0; + else + res = -EOPNOTSUPP; + } else { + /* parent directory must be readable */ + if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (!ni) { + res = -errno; + } else { + mode = 0; + if (type & (X_OK | W_OK | R_OK)) { + if (type & X_OK) mode += S_IEXEC; + if (type & W_OK) mode += S_IWRITE; + if (type & R_OK) mode += S_IREAD; + if (!ntfs_allowed_access(&security, + path, ni, mode)) + res = -errno; + } + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } + } else + res = -errno; + } + return (res); } -static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev, - const char *target) +#endif + +static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev, + const char *target, struct fuse_file_info *fi) { char *name; ntfschar *uname = NULL, *utarget = NULL; ntfs_inode *dir_ni = NULL, *ni; + char *dir_path; + le32 securid; char *path; + ntfschar *stream_name; + int stream_name_len; + mode_t type = typemode & ~07777; + mode_t perm; + struct SECURITY_CONTEXT security; int res = 0, uname_len, utarget_len; - path = strdup(org_path); - if (!path) + dir_path = strdup(org_path); + if (!dir_path) return -errno; /* Generate unicode filename. */ - name = strrchr(path, '/'); + name = strrchr(dir_path, '/'); name++; uname_len = ntfs_mbstoucs(name, &uname); if (uname_len < 0) { res = -errno; goto exit; } + stream_name_len = ntfs_fuse_parse_path(org_path, + &path, &stream_name); + if (stream_name_len < 0) { + res = stream_name_len; + goto exit; + } /* Open parent directory. */ - *name = 0; - dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + *--name = 0; + dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, dir_path); if (!dir_ni) { + free(path); res = -errno; goto exit; } - /* Create object specified in @type. */ - switch (type) { - case S_IFCHR: - case S_IFBLK: - ni = ntfs_create_device(dir_ni, uname, uname_len, type, - dev); - break; - case S_IFLNK: - utarget_len = ntfs_mbstoucs(target, &utarget); - if (utarget_len < 0) { - res = -errno; - goto exit; +#if POSIXACLS + /* make sure parent directory is writeable and executable */ + if (!ntfs_fuse_fill_security_context(&security) + || ntfs_allowed_access(&security,dir_path, + dir_ni,S_IWRITE + S_IEXEC)) { +#else + ntfs_fuse_fill_security_context(&security); +#endif + if (S_ISDIR(type)) + perm = typemode & ~ctx->dmask & 0777; + else + perm = typemode & ~ctx->fmask & 0777; + /* + * Try to get a security id available for + * file creation (from inheritance or argument). + * This is not possible for NTFS 1.x, and we will + * have to build a security attribute later. + */ + if (!ctx->security.mapping[MAPUSERS]) + securid = 0; + else + if (ctx->inherit) + securid = ntfs_inherited_id(&security, dir_path, + dir_ni, S_ISDIR(type)); + else +#if POSIXACLS + securid = ntfs_alloc_securid(&security, + security.uid, security.gid, + dir_path, dir_ni, perm, S_ISDIR(type)); +#else + securid = ntfs_alloc_securid(&security, + security.uid, security.gid, + perm & ~security.umask, S_ISDIR(type)); +#endif + /* Create object specified in @type. */ + switch (type) { + case S_IFCHR: + case S_IFBLK: + ni = ntfs_create_device(dir_ni, securid, + uname, uname_len, type, dev); + break; + case S_IFLNK: + utarget_len = ntfs_mbstoucs(target, &utarget); + if (utarget_len < 0) { + res = -errno; + goto exit; + } + ni = ntfs_create_symlink(dir_ni, securid, + uname, uname_len, + utarget, utarget_len); + break; + default: + ni = ntfs_create(dir_ni, securid, uname, + uname_len, type); + break; + } + if (ni) { + /* + * set the security attribute if a security id + * could not be allocated (eg NTFS 1.x) + */ + if (ctx->security.mapping[MAPUSERS]) { +#if POSIXACLS + if (!securid + && ntfs_set_inherited_posix(&security, ni, + security.uid, security.gid, + dir_path, dir_ni, perm) < 0) + set_fuse_error(&res); +#else + if (!securid + && ntfs_set_owner_mode(&security, ni, + security.uid, security.gid, + perm & ~security.umask) < 0) + set_fuse_error(&res); +#endif } - ni = ntfs_create_symlink(dir_ni, uname, uname_len, - utarget, utarget_len); - break; - default: - ni = ntfs_create(dir_ni, uname, uname_len, type); - break; - } - if (ni) { - if (ntfs_inode_close(ni)) - set_fuse_error(&res); - ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME); + set_archive(ni); + /* mark a need to compress the end of file */ + if (fi && (ni->flags & FILE_ATTR_COMPRESSED)) { + fi->fh |= CLOSE_COMPRESSED; + } + /* mark a future need to fixup encrypted inode */ + if (fi + && ctx->efs_raw + && (ni->flags & FILE_ATTR_ENCRYPTED)) + fi->fh |= CLOSE_ENCRYPTED; + NInoSetDirty(ni); + /* + * closing ni will necessitate to open dir_ni to + * synchronize the index. + * Better avoid a dangerous double opening. + */ + ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME); + if (ntfs_inode_close(dir_ni)) + set_fuse_error(&res); + dir_ni = (ntfs_inode*)NULL; + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; +#if POSIXACLS } else res = -errno; +#endif + free(path); + exit: free(uname); if (ntfs_inode_close(dir_ni)) set_fuse_error(&res); if (utarget) free(utarget); - free(path); + free(dir_path); return res; } static int ntfs_fuse_create_stream(const char *path, - ntfschar *stream_name, const int stream_name_len) + ntfschar *stream_name, const int stream_name_len, + struct fuse_file_info *fi) { ntfs_inode *ni; int res = 0; @@ -965,11 +1547,13 @@ static int ntfs_fuse_create_stream(const char *path, /* * If such file does not exist, create it and try once * again to add stream to it. + * Note : no fuse_file_info for creation of main file */ - res = ntfs_fuse_create(path, S_IFREG, 0, NULL); + res = ntfs_fuse_create(path, S_IFREG, 0, NULL, + (struct fuse_file_info*)NULL); if (!res) return ntfs_fuse_create_stream(path, - stream_name, stream_name_len); + stream_name, stream_name_len,fi); else res = -errno; } @@ -977,12 +1561,26 @@ static int ntfs_fuse_create_stream(const char *path, } if (ntfs_attr_add(ni, AT_DATA, stream_name, stream_name_len, NULL, 0)) res = -errno; + + if ((res >= 0) + && (fi->flags & (O_WRONLY | O_RDWR))) { + set_archive(ni); + /* mark a future need to compress the last block */ + if (ni->flags & FILE_ATTR_COMPRESSED) + fi->fh |= CLOSE_COMPRESSED; + /* mark a future need to fixup encrypted inode */ + if (ctx->efs_raw + && (ni->flags & FILE_ATTR_ENCRYPTED)) + fi->fh |= CLOSE_ENCRYPTED; + } + if (ntfs_inode_close(ni)) set_fuse_error(&res); return res; } -static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev) +static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev, + struct fuse_file_info *fi) { char *path = NULL; ntfschar *stream_name; @@ -997,10 +1595,11 @@ static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev) goto exit; } if (!stream_name_len) - res = ntfs_fuse_create(path, mode & S_IFMT, dev, NULL); + res = ntfs_fuse_create(path, mode & (S_IFMT | 07777), dev, + NULL,fi); else res = ntfs_fuse_create_stream(path, stream_name, - stream_name_len); + stream_name_len,fi); exit: free(path); if (stream_name_len) @@ -1010,20 +1609,22 @@ exit: static int ntfs_fuse_mknod(const char *path, mode_t mode, dev_t dev) { - return ntfs_fuse_mknod_common(path, mode, dev); + return ntfs_fuse_mknod_common(path, mode, dev, + (struct fuse_file_info*)NULL); } static int ntfs_fuse_create_file(const char *path, mode_t mode, - struct fuse_file_info *fi __attribute__((unused))) + struct fuse_file_info *fi) { - return ntfs_fuse_mknod_common(path, mode, 0); + return ntfs_fuse_mknod_common(path, mode, 0, fi); } static int ntfs_fuse_symlink(const char *to, const char *from) { if (ntfs_fuse_is_named_data_stream(from)) return -EINVAL; /* n/a for named data streams. */ - return ntfs_fuse_create(from, S_IFLNK, 0, to); + return ntfs_fuse_create(from, S_IFLNK, 0, to, + (struct fuse_file_info*)NULL); } static int ntfs_fuse_link(const char *old_path, const char *new_path) @@ -1033,6 +1634,9 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) ntfs_inode *dir_ni = NULL, *ni; char *path; int res = 0, uname_len; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif if (ntfs_fuse_is_named_data_stream(old_path)) return -EINVAL; /* n/a for named data streams. */ @@ -1057,20 +1661,31 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) goto exit; } /* Open parent directory. */ - *name = 0; + *--name = 0; dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!dir_ni) { res = -errno; goto exit; } - if (ntfs_link(ni, dir_ni, uname, uname_len)) { - res = -errno; - goto exit; +#if POSIXACLS + /* JPA make sure the parent directories are writeable */ + if (ntfs_fuse_fill_security_context(&security) + && (!ntfs_allowed_dir_access(&security,old_path,S_IWRITE + S_IEXEC) + || !ntfs_allowed_access(&security,path,dir_ni,S_IWRITE + S_IEXEC))) + res = -EACCES; + else +#endif + { + if (ntfs_link(ni, dir_ni, uname, uname_len)) { + res = -errno; + goto exit; + } + + set_archive(ni); + ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); + ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME); } - - ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); - ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME); exit: /* * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni) @@ -1092,6 +1707,9 @@ static int ntfs_fuse_rm(const char *org_path) ntfs_inode *dir_ni = NULL, *ni; char *path; int res = 0, uname_len; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif path = strdup(org_path); if (!path) @@ -1111,17 +1729,28 @@ static int ntfs_fuse_rm(const char *org_path) goto exit; } /* Open parent directory. */ - *name = 0; + *--name = 0; dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!dir_ni) { res = -errno; goto exit; } - if (ntfs_delete(ni, dir_ni, uname, uname_len)) - res = -errno; - /* ntfs_delete() always closes ni and dir_ni */ - ni = dir_ni = NULL; +#if POSIXACLS + /* JPA deny unlinking if directory is not writable and executable */ + if (!ntfs_fuse_fill_security_context(&security) + || ntfs_allowed_dir_access(&security, org_path, + S_IEXEC + S_IWRITE + S_ISVTX)) { +#endif + if (ntfs_delete(ctx->vol, org_path, ni, dir_ni, + uname, uname_len)) + res = -errno; + /* ntfs_delete() always closes ni and dir_ni */ + ni = dir_ni = NULL; +#if POSIXACLS + } else + res = -EACCES; +#endif exit: if (ntfs_inode_close(dir_ni)) set_fuse_error(&res); @@ -1156,14 +1785,31 @@ static int ntfs_fuse_unlink(const char *org_path) ntfschar *stream_name; int stream_name_len; int res = 0; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) return stream_name_len; if (!stream_name_len) res = ntfs_fuse_rm(path); - else + else { +#if POSIXACLS + /* + * JPA deny unlinking stream if directory is not + * writable and executable (debatable) + */ + if (!ntfs_fuse_fill_security_context(&security) + || ntfs_allowed_dir_access(&security, path, + S_IEXEC + S_IWRITE + S_ISVTX)) + res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len); + else + res = -errno; +#else res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len); +#endif + } free(path); if (stream_name_len) free(stream_name); @@ -1205,7 +1851,15 @@ err: "to '%s'", new_path, tmp); } else { cleanup: - ntfs_fuse_unlink(tmp); + /* + * Condition for this unlink has already been checked in + * "ntfs_fuse_rename_existing_dest()", so it should never + * fail (unless concurrent access to directories when fuse + * is multithreaded) + */ + if (ntfs_fuse_unlink(tmp) < 0) + ntfs_log_perror("Rename failed. Existing file '%s' still present " + "as '%s'", new_path, tmp); } return ret; } @@ -1215,6 +1869,9 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ int ret, len; char *tmp; const char *ext = ".ntfs-3g-"; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif ntfs_log_trace("Entering\n"); @@ -1227,9 +1884,25 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ if (ret != len - 1) { ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1); ret = -EOVERFLOW; - } else + } else { +#if POSIXACLS + /* + * Make sure existing dest can be removed. + * This is only needed if parent directory is + * sticky, because in this situation condition + * for unlinking is different from condition for + * linking + */ + if (!ntfs_fuse_fill_security_context(&security) + || ntfs_allowed_dir_access(&security, new_path, + S_IEXEC + S_IWRITE + S_ISVTX)) + ret = ntfs_fuse_safe_rename(old_path, new_path, tmp); + else + ret = -EACCES; +#else ret = ntfs_fuse_safe_rename(old_path, new_path, tmp); - +#endif + } free(tmp); return ret; } @@ -1283,11 +1956,12 @@ out: } static int ntfs_fuse_mkdir(const char *path, - mode_t mode __attribute__((unused))) + mode_t mode) { if (ntfs_fuse_is_named_data_stream(path)) return -EINVAL; /* n/a for named data streams. */ - return ntfs_fuse_create(path, S_IFDIR, 0, NULL); + return ntfs_fuse_create(path, S_IFDIR | (mode & 07777), 0, NULL, + (struct fuse_file_info*)NULL); } static int ntfs_fuse_rmdir(const char *path) @@ -1301,19 +1975,61 @@ static int ntfs_fuse_utime(const char *path, struct utimbuf *buf) { ntfs_inode *ni; int res = 0; +#if POSIXACLS + BOOL ownerok; + BOOL writeok; + struct SECURITY_CONTEXT security; +#endif if (ntfs_fuse_is_named_data_stream(path)) return -EINVAL; /* n/a for named data streams. */ +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; - +#if POSIXACLS + ownerok = ntfs_allowed_as_owner(&security, path, ni); + if (buf) { + /* + * fuse never calls with a NULL buf and we do not + * know whether the specific condition can be applied + * So we have to accept updating by a non-owner having + * write access. + */ + writeok = !ownerok + && (buf->actime == buf->modtime) + && ntfs_allowed_access(&security, path, ni, S_IWRITE); + /* Must be owner */ + if (!ownerok && !writeok) + res = (buf->actime == buf->modtime ? -EACCES : -EPERM); + else { + ni->last_access_time = buf->actime; + ni->last_data_change_time = buf->modtime; + ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); + } + } else { + /* Must be owner or have write access */ + writeok = !ownerok + && ntfs_allowed_access(&security, path, ni, S_IWRITE); + if (!ownerok && !writeok) + res = -EACCES; + else + ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME); + } +#else if (buf) { ni->last_access_time = buf->actime; ni->last_data_change_time = buf->modtime; ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); } else ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME); +#endif if (ntfs_inode_close(ni)) set_fuse_error(&res); @@ -1344,7 +2060,8 @@ static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx) goto close_inode; } - if (NAttrCompressed(na) || NAttrEncrypted(na) || !NAttrNonResident(na)){ + if ((na->data_flags & (ATTR_COMPRESSION_MASK | ATTR_IS_ENCRYPTED)) + || !NAttrNonResident(na)) { ret = -EINVAL; goto close_attr; } @@ -1367,8 +2084,207 @@ close_inode: #ifdef HAVE_SETXATTR -static const char nf_ns_xattr_preffix[] = "user."; -static const int nf_ns_xattr_preffix_len = 5; +/* + * Name space identifications and prefixes + */ + +enum { XATTRNS_NONE, + XATTRNS_USER, + XATTRNS_SYSTEM, + XATTRNS_SECURITY, + XATTRNS_TRUSTED, + XATTRNS_OPEN } ; + +static const char nf_ns_user_prefix[] = "user."; +static const int nf_ns_user_prefix_len = sizeof(nf_ns_user_prefix) - 1; +static const char nf_ns_system_prefix[] = "system."; +static const int nf_ns_system_prefix_len = sizeof(nf_ns_system_prefix) - 1; +static const char nf_ns_security_prefix[] = "security."; +static const int nf_ns_security_prefix_len = sizeof(nf_ns_security_prefix) - 1; +static const char nf_ns_trusted_prefix[] = "trusted."; +static const int nf_ns_trusted_prefix_len = sizeof(nf_ns_trusted_prefix) - 1; + +static const char xattr_ntfs_3g[] = "ntfs-3g."; + +/* + * Identification of data mapped to the system name space + */ + +enum { XATTR_UNMAPPED, + XATTR_NTFS_ACL, + XATTR_NTFS_ATTRIB, + XATTR_NTFS_EFSINFO, + XATTR_NTFS_REPARSE_DATA, + XATTR_NTFS_DOS_NAME, + XATTR_NTFS_TIMES, + XATTR_POSIX_ACC, + XATTR_POSIX_DEF } ; + +static const char nf_ns_xattr_ntfs_acl[] = "system.ntfs_acl"; +static const char nf_ns_xattr_attrib[] = "system.ntfs_attrib"; +static const char nf_ns_xattr_efsinfo[] = "user.ntfs.efsinfo"; +static const char nf_ns_xattr_reparse[] = "system.ntfs_reparse_data"; +static const char nf_ns_xattr_dos_name[] = "system.ntfs_dos_name"; +static const char nf_ns_xattr_times[] = "system.ntfs_times"; +static const char nf_ns_xattr_posix_access[] = "system.posix_acl_access"; +static const char nf_ns_xattr_posix_default[] = "system.posix_acl_default"; + +struct XATTRNAME { + int xattr; + const char *name; +} ; + +static struct XATTRNAME nf_ns_xattr_names[] = { + { XATTR_NTFS_ACL, nf_ns_xattr_ntfs_acl }, + { XATTR_NTFS_ATTRIB, nf_ns_xattr_attrib }, + { XATTR_NTFS_EFSINFO, nf_ns_xattr_efsinfo }, + { XATTR_NTFS_REPARSE_DATA, nf_ns_xattr_reparse }, + { XATTR_NTFS_DOS_NAME, nf_ns_xattr_dos_name }, + { XATTR_NTFS_TIMES, nf_ns_xattr_times }, + { XATTR_POSIX_ACC, nf_ns_xattr_posix_access }, + { XATTR_POSIX_DEF, nf_ns_xattr_posix_default }, + { XATTR_UNMAPPED, (char*)NULL } /* terminator */ +}; + +/* + * Check whether access to internal data as an extended + * attribute in system name space is allowed + * + * Returns pointer to inode if allowed, + * NULL and errno set if not allowed + */ + +static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security, + const char *path, int attr, BOOL setting) +{ + ntfs_inode *ni; + BOOL foracl; + mode_t acctype; + + ni = (ntfs_inode*)NULL; + if (ntfs_fuse_is_named_data_stream(path)) + errno = EINVAL; /* n/a for named data streams. */ + else { + foracl = (attr == XATTR_POSIX_ACC) + || (attr == XATTR_POSIX_DEF); + /* + * When accessing Posix ACL, return unsupported if ACL + * were disabled or no user mapping has been defined. + * However no error will be returned to getfacl + */ + if ((!ntfs_fuse_fill_security_context(security) + || (ctx->secure_flags + & ((1 << SECURITY_DEFAULT) | (1 << SECURITY_RAW)))) + && foracl) { + errno = EOPNOTSUPP; + } else { + /* + * parent directory must be executable, and + * for setting a DOS name it must be writeable + */ + if (setting && (attr == XATTR_NTFS_DOS_NAME)) + acctype = S_IEXEC | S_IWRITE; + else + acctype = S_IEXEC; + if (ntfs_allowed_dir_access(security,path,acctype)) { + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + } + } + } + return (ni); +} + +/* + * Determine whether an extended attribute is in the system + * name space and mapped to internal data + */ + +static int mapped_xattr_system(const char *name) +{ + struct XATTRNAME *p; + + p = nf_ns_xattr_names; + while (p->name && strcmp(p->name,name)) + p++; + return (p->xattr); +} + +/* + * Determine the name space of an extended attribute + */ + +static int xattr_namespace(const char *name) +{ + int namespace; + + if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) { + namespace = XATTRNS_NONE; + if (!strncmp(name, nf_ns_user_prefix, + nf_ns_user_prefix_len) + && (strlen(name) != (size_t)nf_ns_user_prefix_len)) + namespace = XATTRNS_USER; + else if (!strncmp(name, nf_ns_system_prefix, + nf_ns_system_prefix_len) + && (strlen(name) != (size_t)nf_ns_system_prefix_len)) + namespace = XATTRNS_SYSTEM; + else if (!strncmp(name, nf_ns_security_prefix, + nf_ns_security_prefix_len) + && (strlen(name) != (size_t)nf_ns_security_prefix_len)) + namespace = XATTRNS_SECURITY; + else if (!strncmp(name, nf_ns_trusted_prefix, + nf_ns_trusted_prefix_len) + && (strlen(name) != (size_t)nf_ns_trusted_prefix_len)) + namespace = XATTRNS_TRUSTED; + } else + namespace = XATTRNS_OPEN; + return (namespace); +} + +/* + * Fix the prefix of an extended attribute + */ + +static int fix_xattr_prefix(const char *name, int namespace, ntfschar **lename) +{ + int len; + char *prefixed; + + *lename = (ntfschar*)NULL; + switch (namespace) { + case XATTRNS_USER : + /* + * user name space : remove user prefix + */ + len = ntfs_mbstoucs(name + nf_ns_user_prefix_len, lename); + break; + case XATTRNS_SYSTEM : + case XATTRNS_SECURITY : + case XATTRNS_TRUSTED : + /* + * security, trusted and unmapped system name spaces : + * insert ntfs-3g prefix + */ + prefixed = ntfs_malloc(strlen(xattr_ntfs_3g) + + strlen(name) + 1); + if (prefixed) { + strcpy(prefixed,xattr_ntfs_3g); + strcat(prefixed,name); + len = ntfs_mbstoucs(prefixed, lename); + free(prefixed); + } else + len = -1; + break; + case XATTRNS_OPEN : + /* + * in open name space mode : do no fix prefix + */ + len = ntfs_mbstoucs(name, lename); + break; + default : + len = -1; + } + return (len); +} static int ntfs_fuse_listxattr(const char *path, char *list, size_t size) { @@ -1376,49 +2292,96 @@ static int ntfs_fuse_listxattr(const char *path, char *list, size_t size) ntfs_inode *ni; char *to = list; int ret = 0; - - if (ctx->streams != NF_STREAMS_INTERFACE_XATTR) - return -EOPNOTSUPP; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; +#if POSIXACLS + /* file must be readable */ + if (!ntfs_allowed_access(&security,path,ni,S_IREAD)) { + ret = -EACCES; + goto exit; + } +#endif actx = ntfs_attr_get_search_ctx(ni, NULL); if (!actx) { ret = -errno; - ntfs_inode_close(ni); goto exit; } - while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, - 0, NULL, 0, actx)) { - char *tmp_name = NULL; - int tmp_name_len; - if (!actx->attr->name_length) - continue; - tmp_name_len = ntfs_ucstombs((ntfschar *)((u8*)actx->attr + - le16_to_cpu(actx->attr->name_offset)), + if ((ctx->streams == NF_STREAMS_INTERFACE_XATTR) + || (ctx->streams == NF_STREAMS_INTERFACE_OPENXATTR)) { + while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, + 0, NULL, 0, actx)) { + char *tmp_name = NULL; + int tmp_name_len; + + if (!actx->attr->name_length) + continue; + tmp_name_len = ntfs_ucstombs( + (ntfschar *)((u8*)actx->attr + + le16_to_cpu(actx->attr->name_offset)), actx->attr->name_length, &tmp_name, 0); - if (tmp_name_len < 0) { - ret = -errno; - goto exit; - } - ret += tmp_name_len + nf_ns_xattr_preffix_len + 1; - if (size) { - if ((size_t)ret <= size) { - strcpy(to, nf_ns_xattr_preffix); - to += nf_ns_xattr_preffix_len; - strncpy(to, tmp_name, tmp_name_len); - to += tmp_name_len; - *to = 0; - to++; - } else { - free(tmp_name); - ret = -ERANGE; + if (tmp_name_len < 0) { + ret = -errno; goto exit; } + /* + * When using name spaces, do not return + * security, trusted nor system attributes + * (filtered elsewhere anyway) + * otherwise insert "user." prefix + */ + if (ctx->streams == NF_STREAMS_INTERFACE_XATTR) { + if ((strlen(tmp_name) > sizeof(xattr_ntfs_3g)) + && !strncmp(tmp_name,xattr_ntfs_3g, + sizeof(xattr_ntfs_3g)-1)) + tmp_name_len = 0; + else + ret += tmp_name_len + + nf_ns_user_prefix_len + 1; + } else + ret += tmp_name_len + 1; + if (size && tmp_name_len) { + if ((size_t)ret <= size) { + if (ctx->streams + == NF_STREAMS_INTERFACE_XATTR) { + strcpy(to, nf_ns_user_prefix); + to += nf_ns_user_prefix_len; + } + strncpy(to, tmp_name, tmp_name_len); + to += tmp_name_len; + *to = 0; + to++; + } else { + free(tmp_name); + ret = -ERANGE; + goto exit; + } + } + free(tmp_name); + } + } + + /* List efs info xattr for encrypted files */ + if (ctx->efs_raw && (ni->flags & FILE_ATTR_ENCRYPTED)) { + ret += sizeof(nf_ns_xattr_efsinfo); + if ((size_t)ret <= size) { + memcpy(to, nf_ns_xattr_efsinfo, + sizeof(nf_ns_xattr_efsinfo)); + to += sizeof(nf_ns_xattr_efsinfo); } - free(tmp_name); } + if (errno != ENOENT) ret = -errno; exit: @@ -1436,16 +2399,31 @@ static int ntfs_fuse_getxattr_windows(const char *path, const char *name, ntfs_inode *ni; char *to = value; int ret = 0; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif if (strcmp(name, "ntfs.streams.list")) return -EOPNOTSUPP; +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; +#if POSIXACLS + if (!ntfs_allowed_access(&security,path,ni,S_IREAD)) { + ret = -errno; + goto exit; + } +#endif actx = ntfs_attr_get_search_ctx(ni, NULL); if (!actx) { ret = -errno; - ntfs_inode_close(ni); goto exit; } while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE, @@ -1499,18 +2477,164 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, ntfs_attr *na = NULL; ntfschar *lename = NULL; int res, lename_len; - + s64 rsize; + int attr; + int namespace; + struct SECURITY_CONTEXT security; + + attr = mapped_xattr_system(name); + if (attr != XATTR_UNMAPPED) { +#if POSIXACLS + /* + * hijack internal data and ACL retrieval, whatever + * mode was selected for xattr (from the user's + * point of view, ACLs are not xattr) + */ + ni = ntfs_check_access_xattr(&security,path,attr,FALSE); + if (ni) { + if (ntfs_allowed_access(&security,path,ni,S_IREAD)) { + /* + * the returned value is the needed + * size. If it is too small, no copy + * is done, and the caller has to + * issue a new call with correct size. + */ + switch (attr) { + case XATTR_NTFS_ACL : + res = ntfs_get_ntfs_acl(&security,path, + name,value,size,ni); + break; + case XATTR_POSIX_ACC : + case XATTR_POSIX_DEF : + res = ntfs_get_posix_acl(&security,path, + name,value,size,ni); + break; + case XATTR_NTFS_ATTRIB : + res = ntfs_get_ntfs_attrib(path, + value,size,ni); + break; + case XATTR_NTFS_EFSINFO : + if (ctx->efs_raw) + res = ntfs_get_efs_info(path, + value,size,ni); + else + res = -EPERM; + break; + case XATTR_NTFS_REPARSE_DATA : + res = ntfs_get_ntfs_reparse_data(path, + value,size,ni); + break; + case XATTR_NTFS_DOS_NAME: + res = ntfs_get_ntfs_dos_name(path, + value,size,ni); + break; + case XATTR_NTFS_TIMES: + res = ntfs_inode_get_times(path, + value,size,ni); + break; + default : /* not possible */ + break; + } + } else { + res = -errno; + } + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; +#else + /* + * Only hijack NTFS ACL retrieval if POSIX ACLS + * option is not selected + * Access control is done by fuse + */ + if (ntfs_fuse_is_named_data_stream(path)) + res = -EINVAL; /* n/a for named data streams. */ + else { + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (ni) { + /* user mapping not mandatory */ + ntfs_fuse_fill_security_context(&security); + /* + * the returned value is the needed + * size. If it is too small, no copy + * is done, and the caller has to + * issue a new call with correct size. + */ + switch (attr) { + case XATTR_NTFS_ACL : + res = ntfs_get_ntfs_acl(&security,path, + name,value,size,ni); + break; + case XATTR_NTFS_ATTRIB : + res = ntfs_get_ntfs_attrib(path, + value,size,ni); + break; + case XATTR_NTFS_EFSINFO : + if (ctx->efs_raw) + res = ntfs_get_efs_info(path, + value,size,ni); + else + res = -EPERM; + break; + case XATTR_NTFS_REPARSE_DATA : + res = ntfs_get_ntfs_reparse_data(path, + value,size,ni); + break; + case XATTR_NTFS_DOS_NAME: + res = ntfs_get_ntfs_dos_name(path, + value,size,ni); + break; + case XATTR_NTFS_TIMES: + res = ntfs_inode_get_times(path, + value,size,ni); + break; + default : + /* + * make sure applications do not see + * Posix ACL not consistent with mode + */ + errno = EOPNOTSUPP; + res = -errno; + break; + } + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + } +#endif + return (res); + } if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS) return ntfs_fuse_getxattr_windows(path, name, value, size); - if (ctx->streams != NF_STREAMS_INTERFACE_XATTR) + if (ctx->streams == NF_STREAMS_INTERFACE_NONE) + return -EOPNOTSUPP; + namespace = xattr_namespace(name); + if (namespace == XATTRNS_NONE) return -EOPNOTSUPP; - if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || - strlen(name) == (size_t)nf_ns_xattr_preffix_len) - return -ENODATA; +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } + /* trusted only readable by root */ + if ((namespace == XATTRNS_TRUSTED) + && security.uid) + return -EPERM; +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; - lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); +#if POSIXACLS + /* file must be readable */ + if (!ntfs_allowed_access(&security, path, ni, S_IREAD)) { + res = -errno; + goto exit; + } +#endif + lename_len = fix_xattr_prefix(name, namespace, &lename); if (lename_len == -1) { res = -errno; goto exit; @@ -1520,15 +2644,20 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, res = -ENODATA; goto exit; } + rsize = na->data_size; + if (ctx->efs_raw && + (na->data_flags & ATTR_IS_ENCRYPTED) && + NAttrNonResident(na)) + rsize = ((na->data_size + 511) & ~511)+2; if (size) { - if (size >= na->data_size) { - res = ntfs_attr_pread(na, 0, na->data_size, value); - if (res != na->data_size) + if (size >= (size_t)rsize) { + res = ntfs_attr_pread(na, 0, rsize, value); + if (res != rsize) res = -errno; } else res = -ERANGE; } else - res = na->data_size; + res = rsize; exit: if (na) ntfs_attr_close(na); @@ -1545,16 +2674,186 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, ntfs_attr *na = NULL; ntfschar *lename = NULL; int res, lename_len; - - if (ctx->streams != NF_STREAMS_INTERFACE_XATTR) + size_t part, total; + int attr; + int namespace; + struct SECURITY_CONTEXT security; + + attr = mapped_xattr_system(name); + if (attr != XATTR_UNMAPPED) { +#if POSIXACLS + /* + * hijack internal data and ACL setting, whatever + * mode was selected for xattr (from the user's + * point of view, ACLs are not xattr) + * Note : updating an ACL does not set ctime + */ + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + if (ni) { + if (ntfs_allowed_as_owner(&security,path,ni)) { + switch (attr) { + case XATTR_NTFS_ACL : + res = ntfs_set_ntfs_acl(&security,path, + name,value,size,flags,ni); + break; + case XATTR_POSIX_ACC : + case XATTR_POSIX_DEF : + res = ntfs_set_posix_acl(&security,path, + name,value,size,flags,ni); + break; + case XATTR_NTFS_ATTRIB : + res = ntfs_set_ntfs_attrib(path, + value,size,flags,ni); + break; + case XATTR_NTFS_EFSINFO : + if (ctx->efs_raw) + res = ntfs_set_efs_info(path, + value,size,flags,ni); + else + res = -EPERM; + break; + case XATTR_NTFS_REPARSE_DATA : + res = ntfs_set_ntfs_reparse_data(path, + value,size,flags,ni); + break; + case XATTR_NTFS_DOS_NAME: + /* warning : this closes the inode */ + res = ntfs_set_ntfs_dos_name(path, + value,size,flags,ni); + break; + case XATTR_NTFS_TIMES: + res = ntfs_inode_set_times(path, + value,size,flags,ni); + break; + default : /* not possible */ + break; + } + if (res) + res = -errno; + } else + res = -errno; + if ((attr != XATTR_NTFS_DOS_NAME) + && ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; +#else + /* + * Only hijack NTFS ACL setting if POSIX ACLS + * option is not selected + * Access control is partially done by fuse + */ + if (ntfs_fuse_is_named_data_stream(path)) + res = -EINVAL; /* n/a for named data streams. */ + else { + /* creation of a new name is not controlled by fuse */ + if (attr == XATTR_NTFS_DOS_NAME) + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + else + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (ni) { + /* + * user mapping is not mandatory + * if defined, only owner is allowed + */ + if (!ntfs_fuse_fill_security_context(&security) + || ntfs_allowed_as_owner(&security,path,ni)) { + switch (attr) { + case XATTR_NTFS_ACL : + res = ntfs_set_ntfs_acl(&security,path, + name,value,size,flags,ni); + break; + case XATTR_NTFS_ATTRIB : + res = ntfs_set_ntfs_attrib(path, + value,size,flags,ni); + break; + case XATTR_NTFS_EFSINFO : + if (ctx->efs_raw) + res = ntfs_set_efs_info(path, + value,size,flags,ni); + else + res = -EPERM; + break; + case XATTR_NTFS_REPARSE_DATA : + res = ntfs_set_ntfs_reparse_data(path, + value,size,flags,ni); + break; + case XATTR_NTFS_DOS_NAME: + /* warning : this closes the inode */ + res = ntfs_set_ntfs_dos_name(path, + value,size,flags,ni); + break; + case XATTR_NTFS_TIMES: + res = ntfs_inode_set_times(path, + value,size,flags,ni); + break; + default : + /* + * make sure applications do not see + * Posix ACL not consistent with mode + */ + errno = EOPNOTSUPP; + res = -errno; + break; + } + if (res) + res = -errno; + } else + res = -errno; + if ((attr != XATTR_NTFS_DOS_NAME) + && ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + } +#endif + return (res); + } + if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR) + && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) return -EOPNOTSUPP; - if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || - strlen(name) == (size_t)nf_ns_xattr_preffix_len) + namespace = xattr_namespace(name); + if (namespace == XATTRNS_NONE) return -EOPNOTSUPP; +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } + /* security and trusted only settable by root */ + if (((namespace == XATTRNS_SECURITY) + || (namespace == XATTRNS_TRUSTED)) + && security.uid) + return -EPERM; +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; - lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); +#if POSIXACLS + switch (namespace) { + case XATTRNS_SECURITY : + case XATTRNS_TRUSTED : + if (security.uid) { + res = -EPERM; + goto exit; + } + break; + case XATTRNS_SYSTEM : + if (!ntfs_allowed_as_owner(&security,path,ni)) { + res = -EACCES; + goto exit; + } + break; + default : + if (!ntfs_allowed_access(&security,path,ni,S_IWRITE)) { + res = -EACCES; + goto exit; + } + break; + } +#endif + lename_len = fix_xattr_prefix(name, namespace, &lename); if (lename_len == -1) { res = -errno; goto exit; @@ -1573,21 +2872,38 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, res = -errno; goto exit; } + set_archive(ni); na = ntfs_attr_open(ni, AT_DATA, lename, lename_len); if (!na) { res = -errno; goto exit; } } else { - if (ntfs_attr_truncate(na, (s64)size)) { + /* currently compressed streams can only be wiped out */ + if (ntfs_attr_truncate(na, (s64)0 /* size */)) { res = -errno; goto exit; } } - res = ntfs_attr_pwrite(na, 0, size, value); - if (res != (s64) size) - res = -errno; - else + total = 0; + if (size) { + do { + part = ntfs_attr_pwrite(na, total, size - total, + &value[total]); + if (part > 0) + total += part; + } while ((part > 0) && (total < size)); + if (total != size) + res = -errno; + else + if (!(res = ntfs_attr_pclose(na))) + if (ctx->efs_raw + && (ni->flags & FILE_ATTR_ENCRYPTED)) + res = ntfs_efs_fixup_attribute(NULL, + na); + if (total) + set_archive(ni); + } else res = 0; exit: if (na) @@ -1603,17 +2919,172 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) ntfs_inode *ni; ntfschar *lename = NULL; int res = 0, lename_len; + int attr; + int namespace; + struct SECURITY_CONTEXT security; + attr = mapped_xattr_system(name); + if (attr != XATTR_UNMAPPED) { +#if POSIXACLS - if (ctx->streams != NF_STREAMS_INTERFACE_XATTR) + /* + * hijack internal data and ACL removal, whatever + * mode was selected for xattr (from the user's + * point of view, ACLs are not xattr) + * Note : updating an ACL does not set ctime + */ + res = 0; + switch (attr) { + /* + * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES + * is never allowed + */ + case XATTR_NTFS_ACL : + case XATTR_NTFS_ATTRIB : + case XATTR_NTFS_EFSINFO : + case XATTR_NTFS_TIMES : + res = -EPERM; + break; + case XATTR_POSIX_ACC : + case XATTR_POSIX_DEF : + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + if (ni) { + if (!ntfs_allowed_as_owner(&security,path,ni) + || ntfs_remove_posix_acl(&security,path, + name,ni)) + res = -errno; + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + break; + case XATTR_NTFS_REPARSE_DATA : + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + if (ni) { + if (!ntfs_allowed_as_owner(&security,path,ni) + || ntfs_remove_ntfs_reparse_data(path,ni)) + res = -errno; + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + break; + case XATTR_NTFS_DOS_NAME: + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + if (ni) { + if (ntfs_remove_ntfs_dos_name(path,ni)) + res = -errno; + } else + res = -errno; + break; + default : + errno = EOPNOTSUPP; + res = -errno; + break; + break; + } +#else + /* + * Only hijack NTFS ACL and ATTRIB removal if POSIX ACLS + * option is not selected + * Access control is partially done by fuse + */ + if (ntfs_fuse_is_named_data_stream(path)) + res = -EINVAL; /* n/a for named data streams. */ + else { + switch (attr) { + /* + * Removal of NTFS ACL, ATTRIB, EFSINFO or TIMES + * is never allowed + */ + case XATTR_NTFS_ACL : + case XATTR_NTFS_ATTRIB : + case XATTR_NTFS_EFSINFO : + case XATTR_NTFS_TIMES : + res = -EPERM; + break; + case XATTR_NTFS_REPARSE_DATA : + ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if (ni) { + /* + * user mapping is not mandatory + * if defined, only owner is allowed + */ + if ((ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_as_owner(&security,path,ni)) + || ntfs_remove_ntfs_reparse_data(path,ni)) + res = -errno; + if (ntfs_inode_close(ni)) + set_fuse_error(&res); + } else + res = -errno; + break; + case XATTR_NTFS_DOS_NAME: + ni = ntfs_check_access_xattr(&security,path,attr,TRUE); + if (ni) { + if (ntfs_remove_ntfs_dos_name(path,ni)) + res = -errno; + } else + res = -errno; + break; + default : + /* + * make sure applications do not see + * Posix ACL not consistent with mode + */ + errno = EOPNOTSUPP; + res = -errno; + break; + } + } +#endif + return (res); + } + if ((ctx->streams != NF_STREAMS_INTERFACE_XATTR) + && (ctx->streams != NF_STREAMS_INTERFACE_OPENXATTR)) return -EOPNOTSUPP; - if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) || - strlen(name) == (size_t)nf_ns_xattr_preffix_len) - return -ENODATA; + namespace = xattr_namespace(name); + if (namespace == XATTRNS_NONE) + return -EOPNOTSUPP; +#if POSIXACLS + /* parent directory must be executable */ + if (ntfs_fuse_fill_security_context(&security) + && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + return (-errno); + } + /* security and trusted only settable by root */ + if (((namespace == XATTRNS_SECURITY) + || (namespace == XATTRNS_TRUSTED)) + && security.uid) + return -EACCES; +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; - lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename); +#if POSIXACLS + switch (namespace) { + case XATTRNS_SECURITY : + case XATTRNS_TRUSTED : + if (security.uid) { + res = -EPERM; + goto exit; + } + break; + case XATTRNS_SYSTEM : + if (!ntfs_allowed_as_owner(&security,path,ni)) { + res = -EACCES; + goto exit; + } + break; + default : + if (!ntfs_allowed_access(&security,path,ni,S_IWRITE)) { + res = -EACCES; + goto exit; + } + break; + } +#endif + lename_len = fix_xattr_prefix(name, namespace, &lename); if (lename_len == -1) { res = -errno; goto exit; @@ -1623,7 +3094,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) errno = ENODATA; res = -errno; } - + set_archive(ni); exit: free(lename); if (ntfs_inode_close(ni)) @@ -1631,19 +3102,39 @@ exit: return res; } +#else +#if POSIXACLS +#error "Option inconsistency : POSIXACLS requires SETXATTR" +#endif #endif /* HAVE_SETXATTR */ static void ntfs_close(void) { + struct SECURITY_CONTEXT security; + if (!ctx) return; if (!ctx->vol) return; - if (ctx->mounted) + if (ctx->mounted) { ntfs_log_info("Unmounting %s (%s)\n", opts.device, ctx->vol->vol_name); + if (ntfs_fuse_fill_security_context(&security)) { + if (ctx->seccache && ctx->seccache->head.p_reads) { + ntfs_log_info("Permissions cache : %lu writes, " + "%lu reads, %lu.%1lu%% hits\n", + ctx->seccache->head.p_writes, + ctx->seccache->head.p_reads, + 100 * ctx->seccache->head.p_hits + / ctx->seccache->head.p_reads, + 1000 * ctx->seccache->head.p_hits + / ctx->seccache->head.p_reads % 10); + } + } + ntfs_close_secure(&security); + } if (ntfs_umount(ctx->vol, FALSE)) ntfs_log_perror("Failed to close volume %s", opts.device); @@ -1661,9 +3152,11 @@ static struct fuse_operations ntfs_3g_ops = { .readlink = ntfs_fuse_readlink, .readdir = ntfs_fuse_readdir, .open = ntfs_fuse_open, + .release = ntfs_fuse_release, .read = ntfs_fuse_read, .write = ntfs_fuse_write, .truncate = ntfs_fuse_truncate, + .ftruncate = ntfs_fuse_ftruncate, .statfs = ntfs_fuse_statfs, .chmod = ntfs_fuse_chmod, .chown = ntfs_fuse_chown, @@ -1678,6 +3171,10 @@ static struct fuse_operations ntfs_3g_ops = { .utime = ntfs_fuse_utime, .bmap = ntfs_fuse_bmap, .destroy = ntfs_fuse_destroy2, +#if POSIXACLS + .access = ntfs_fuse_access, + .opendir = ntfs_fuse_opendir, +#endif #ifdef HAVE_SETXATTR .getxattr = ntfs_fuse_getxattr, .setxattr = ntfs_fuse_setxattr, @@ -1689,7 +3186,12 @@ static struct fuse_operations ntfs_3g_ops = { /* MacFUSE extensions. */ .getxtimes = ntfs_macfuse_getxtimes, .setcrtime = ntfs_macfuse_setcrtime, - .setbkuptime = ntfs_macfuse_setbkuptime + .setbkuptime = ntfs_macfuse_setbkuptime, + .setchgtime = ntfs_macfuse_setchgtime, +#else /* defined(__APPLE__) || defined(__DARWIN__) */ +#ifdef FUSE_CAP_DONT_MASK + .init = ntfs_init +#endif #endif /* defined(__APPLE__) || defined(__DARWIN__) */ }; @@ -1816,7 +3318,10 @@ static char *parse_mount_options(const char *orig_opts) char *options, *s, *opt, *val, *ret = NULL; BOOL no_def_opts = FALSE; int default_permissions = 0; + int want_permissions = 0; + ctx->secure_flags = 0; + ctx->efs_raw = FALSE; options = strdup(orig_opts ? orig_opts : ""); if (!options) { ntfs_log_perror("%s: strdup failed", EXEC_NAME); @@ -1866,30 +3371,29 @@ static char *parse_mount_options(const char *orig_opts) goto err_exit; sscanf(val, "%o", &ctx->fmask); ctx->dmask = ctx->fmask; - if (ctx->fmask) - default_permissions = 1; +#if !POSIXACLS + default_permissions = 1; +#endif } else if (!strcmp(opt, "fmask")) { if (missing_option_value(val, "fmask")) goto err_exit; sscanf(val, "%o", &ctx->fmask); - if (ctx->fmask) - default_permissions = 1; + want_permissions = 1; } else if (!strcmp(opt, "dmask")) { if (missing_option_value(val, "dmask")) goto err_exit; sscanf(val, "%o", &ctx->dmask); - if (ctx->dmask) - default_permissions = 1; + want_permissions = 1; } else if (!strcmp(opt, "uid")) { if (missing_option_value(val, "uid")) goto err_exit; sscanf(val, "%i", &ctx->uid); - default_permissions = 1; + want_permissions = 1; } else if (!strcmp(opt, "gid")) { if (missing_option_value(val, "gid")) goto err_exit; sscanf(val, "%i", &ctx->gid); - default_permissions = 1; + want_permissions = 1; } else if (!strcmp(opt, "show_sys_files")) { if (bogus_option_value(val, "show_sys_files")) goto err_exit; @@ -1913,7 +3417,25 @@ static char *parse_mount_options(const char *orig_opts) } else if (!strcmp(opt, "locale")) { if (missing_option_value(val, "locale")) goto err_exit; - setlocale(LC_ALL, val); + ntfs_set_char_encoding(val); +#if defined(__APPLE__) || defined(__DARWIN__) +#ifdef ENABLE_NFCONV + } else if (!strcmp(opt, "nfconv")) { + if (bogus_option_value(val, "nfconv")) + goto err_exit; + if (ntfs_macosx_normalize_filenames(1)) { + ntfs_log_error("ntfs_macosx_normalize_filenames(1) failed!\n"); + goto err_exit; + } + } else if (!strcmp(opt, "nonfconv")) { + if (bogus_option_value(val, "nonfconv")) + goto err_exit; + if (ntfs_macosx_normalize_filenames(0)) { + ntfs_log_error("ntfs_macosx_normalize_filenames(0) failed!\n"); + goto err_exit; + } +#endif /* ENABLE_NFCONV */ +#endif /* defined(__APPLE__) || defined(__DARWIN__) */ } else if (!strcmp(opt, "streams_interface")) { if (missing_option_value(val, "streams_interface")) goto err_exit; @@ -1921,6 +3443,8 @@ static char *parse_mount_options(const char *orig_opts) ctx->streams = NF_STREAMS_INTERFACE_NONE; else if (!strcmp(val, "xattr")) ctx->streams = NF_STREAMS_INTERFACE_XATTR; + else if (!strcmp(val, "openxattr")) + ctx->streams = NF_STREAMS_INTERFACE_OPENXATTR; else if (!strcmp(val, "windows")) ctx->streams = NF_STREAMS_INTERFACE_WINDOWS; else { @@ -1928,6 +3452,8 @@ static char *parse_mount_options(const char *orig_opts) "access interface.\n"); goto err_exit; } + } else if (!strcmp(opt, "user_xattr")) { + ctx->streams = NF_STREAMS_INTERFACE_XATTR; } else if (!strcmp(opt, "noauto")) { /* Don't pass noauto option to fuse. */ } else if (!strcmp(opt, "debug")) { @@ -1948,6 +3474,40 @@ static char *parse_mount_options(const char *orig_opts) } else if (!strcmp(opt, "blksize")) { ntfs_log_info("WARNING: blksize option is ignored " "because ntfs-3g must calculate it.\n"); + } else if (!strcmp(opt, "inherit")) { + /* + * JPA do not overwrite inherited permissions + * in create() + */ + ctx->inherit = TRUE; + } else if (!strcmp(opt, "addsecurids")) { + /* + * JPA create security ids for files being read + * with an individual security attribute + */ + ctx->secure_flags |= (1 << SECURITY_ADDSECURIDS); + } else if (!strcmp(opt, "staticgrps")) { + /* + * JPA use static definition of groups + * for file access control + */ + ctx->secure_flags |= (1 << SECURITY_STATICGRPS); + } else if (!strcmp(opt, "usermapping")) { + if (!val) { + ntfs_log_error("'usermapping' option should have " + "a value.\n"); + goto err_exit; + } + ctx->usermap_path = strdup(val); + if (!ctx->usermap_path) { + ntfs_log_error("no more memory to store " + "'usermapping' option.\n"); + goto err_exit; + } + } else if (!strcmp(opt, "efs_raw")) { + if (bogus_option_value(val, "efs_raw")) + goto err_exit; + ctx->efs_raw = TRUE; } else { /* Probably FUSE option. */ if (strappend(&ret, opt)) goto err_exit; @@ -1977,6 +3537,12 @@ static char *parse_mount_options(const char *orig_opts) goto err_exit; if (strappend(&ret, opts.device)) goto err_exit; + if (default_permissions) + ctx->secure_flags |= (1 << SECURITY_DEFAULT); + if (want_permissions) + ctx->secure_flags |= (1 << SECURITY_WANTED); + if (ctx->ro) + ctx->secure_flags &= ~(1 << SECURITY_ADDSECURIDS); exit: free(options); return ret; @@ -2285,6 +3851,8 @@ static void setup_logging(char *parsed_options) } } + ctx->seccache = (struct PERMISSIONS_CACHE*)NULL; + ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version()); ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n", opts.device, (ctx->ro) ? "Read-Only" : "Read-Write", @@ -2299,6 +3867,8 @@ int main(int argc, char *argv[]) char *parsed_options = NULL; struct fuse *fh; fuse_fstype fstype = FSTYPE_UNKNOWN; + const char *permissions_mode = (const char*)NULL; + const char *failed_secure = (const char*)NULL; struct stat sbuf; int err, fd; @@ -2340,6 +3910,15 @@ int main(int argc, char *argv[]) goto err_out; } + ctx->security.uid = 0; + ctx->security.gid = 0; + if ((opts.mnt_point[0] == '/') + && !stat(opts.mnt_point,&sbuf)) { + /* collect owner of mount point, useful for default mapping */ + ctx->security.uid = sbuf.st_uid; + ctx->security.gid = sbuf.st_gid; + } + #if defined(linux) || defined(__uClinux__) fstype = get_fuse_fstype(); @@ -2380,7 +3959,53 @@ int main(int argc, char *argv[]) /* We must do this after ntfs_open() to be able to set the blksize */ if (ctx->blkdev && set_fuseblk_options(&parsed_options)) goto err_out; - + + ctx->security.vol = ctx->vol; + ctx->vol->secure_flags = ctx->secure_flags; + ctx->vol->efs_raw = ctx->efs_raw; + /* JPA open $Secure, (whatever NTFS version !) */ + /* to initialize security data */ + if (ntfs_open_secure(ctx->vol) && (ctx->vol->major_ver >= 3)) + failed_secure = "Could not open file $Secure"; + if (!ntfs_build_mapping(&ctx->security,ctx->usermap_path)) { +#if POSIXACLS + if (ctx->vol->secure_flags & (1 << SECURITY_DEFAULT)) + permissions_mode = "User mapping built, Posix ACLs not used"; + else + permissions_mode = "User mapping built, Posix ACLs in use"; +#else + if (!(ctx->vol->secure_flags & (1 << SECURITY_DEFAULT))) { + /* + * No explicit option but user mapping found + * force default security + */ + ctx->vol->secure_flags |= (1 << SECURITY_DEFAULT); + if (strappend(&parsed_options, ",default_permissions")) { + err = NTFS_VOLUME_SYNTAX_ERROR; + goto err_out; + } + } + permissions_mode = "User mapping built"; +#endif + } else { + ctx->security.uid = ctx->uid; + ctx->security.gid = ctx->gid; + /* same ownership/permissions for all files */ + ctx->security.mapping[MAPUSERS] = (struct MAPPING*)NULL; + ctx->security.mapping[MAPGROUPS] = (struct MAPPING*)NULL; + if (ctx->secure_flags & (1 << SECURITY_WANTED)) + ctx->secure_flags |= (1 << SECURITY_DEFAULT); + if (ctx->secure_flags & (1 << SECURITY_DEFAULT)) { + ctx->secure_flags |= (1 << SECURITY_RAW); + permissions_mode = "Global ownership and permissions enforced"; + } else { + ctx->secure_flags &= ~(1 << SECURITY_RAW); + permissions_mode = "Ownership and permissions disabled"; + } + } + if (ctx->usermap_path) + free (ctx->usermap_path); + fh = mount_fuse(parsed_options); if (!fh) { err = NTFS_VOLUME_FUSE_ERROR; @@ -2394,6 +4019,10 @@ int main(int argc, char *argv[]) ntfs_log_info("%s", fuse26_kmod_msg); #endif setup_logging(parsed_options); + if (failed_secure) + ntfs_log_info("%s\n",failed_secure); + if (permissions_mode) + ntfs_log_info("%s\n",permissions_mode); fuse_loop(fh); diff --git a/release/src/router/ntfs-3g/src/ntfs-3g.probe.8.in b/release/src/router/ntfs-3g/src/ntfs-3g.probe.8.in index 231e804b93..3e8a2678ef 100644 --- a/release/src/router/ntfs-3g/src/ntfs-3g.probe.8.in +++ b/release/src/router/ntfs-3g/src/ntfs-3g.probe.8.in @@ -1,7 +1,7 @@ .\" Copyright (c) 2008 Szabolcs Szakacsits. .\" This file may be copied under the terms of the GNU Public License. .\" -.TH NTFS-3G.PROBE 8 "February 2008" "ntfs-3g.probe @VERSION@" +.TH NTFS-3G.PROBE 8 "January 2008" "ntfs-3g.probe @VERSION@" .SH NAME ntfs-3g.probe \- Probe an NTFS volume mountability .SH SYNOPSIS @@ -43,19 +43,14 @@ The volume doesn't have a valid NTFS. Inconsistent NTFS, hardware or device driver fault, or unsetup SoftRAID/FakeRAID hardware. .IP 14 -The NTFS partition is hibernated. Use the 'remove_hiberfile' -.B ntfs-3g -mount option to be able to read-write mount such volumes. +The NTFS partition is hibernated. .IP 15 -The volume was not cleanly unmounted. The 'force' -.B ntfs-3g -mount option can overcome this scenario by resetting the NTFS -journal file. +The volume was not cleanly unmounted. .IP 16 The volume is already exclusively opened and in use by a kernel driver or software. .IP 17 -SoftRAID/FakeRAID hardware without setup, or missing, or powered down device. +Unsetup SoftRAID/FakeRAID hardware. .IP 18 Unknown reason. .IP 19 @@ -64,8 +59,6 @@ Not enough privilege to mount. Out of memory. .IP 21 Unclassified FUSE error. -.IP 22 -Security hazard. Execution is denied because it would be exploitable. .SH KNOWN ISSUES Please see .RS diff --git a/release/src/router/ntfs-3g/src/ntfs-3g.secaudit.8.in b/release/src/router/ntfs-3g/src/ntfs-3g.secaudit.8.in new file mode 100644 index 0000000000..7633ab9d47 --- /dev/null +++ b/release/src/router/ntfs-3g/src/ntfs-3g.secaudit.8.in @@ -0,0 +1,171 @@ +.\" Copyright (c) 2007-2009 Jean-Pierre André. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH NTFS-3G.SECAUDIT 8 "November 2009" "ntfs-3g.secaudit 1.3.8" +.SH NAME +ntfs-3g.secaudit \- NTFS Security Data Auditing +.SH SYNOPSIS +.B ntfs-3g.secaudit +\fB[\fIoptions\fP\fB]\fR +.I args +.PP +Where \fIoptions\fP is a combination of : +.RS +-a full auditing of security data (Linux only) +.RE +.RS +-b backup ACLs +.RE +.RS +-e setting extra backed-up parameters (in conjunction with -s) +.RE +.RS +-h displaying hexadecimal security descriptors saved in a file +.RE +.RS +-r recursing in a directory +.RE +.RS +-s setting backed-up ACLs +.RE +.RS +-v verbose (very verbose if set twice) +.RE +.PP +and args define the parameters and the set of files acted upon. +.PP +Typing secaudit with no args will display a summary of available options. +.SH DESCRIPTION +\fBntfs-3g.secaudit\fR +displays the ownership and permissions of a set of files on an NTFS +file system, and checks their consistency. It can be started in terminal +mode only (no graphical user interface is available.) +.PP +When a \fIvolume\fR is required, it has to be unmounted, and the command +has to be issued as \fBroot\fP. The \fIvolume\fR can be either a block +device (i.e. a disk partition) or an image file. +.PP +When acting on a directory or volume, the command may produce a lot +of information. It is therefore advisable to redirect the output to +a file or pipe it to a text editor for examination. +.SH OPTIONS +Below are the valid combinations of options and arguments that +\fBntfs-3g.secaudit\fR accepts. All the indicated arguments are +mandatory and must be unique (if wildcards are used, they must +resolve to a single name.) +.TP +\fB-h\fP \fIfile\fP +Displays in an human readable form the hexadecimal security descriptors +saved in \fIfile\fP. This can be used to turn a verbose output into a very +verbose output. +.TP +\fB-a[rv]\fP \fIvolume\fP +Audits the volume : all the global security data on \fIvolume\fP are scanned +and errors are displayed. If option \fB-r\fP is present, all files and +directories are also scanned and their relations to global security data +are checked. This can produce a lot of data. + +This option is not effective on volumes formatted for old NTFS versions (pre +NTFS 3.0). Such volumes have no global security data. + +When errors are signalled, it is advisable to repair the volume with an +appropriate tool (such as \fBchkdsk\fP on Windows.) +.TP +\fB[-v]\fP \fIvolume\fP \fIfile\fP +Displays the security parameters of \fIfile\fP : its interpreted Linux mode +(rwx flags in octal) and Posix ACL[1], its security key if any, and its +security descriptor if verbose output. +.TP +\fB-r[v]\fP \fIvolume\fP \fIdirectory\fP +displays the security parameters of all files and subdirectories in +\fIdirectory\fP : their interpreted Linux mode (rwx flags in octal) and Posix +ACL[1], their security key if any, and their security descriptor if +verbose output. +.TP +.B -b[v] \fIvolume\fP \fI[directory]\fP +Recursively extracts to standard output the NTFS ACLs of files in \fIvolume\fP +and \fIdirectory\fP. +.TP +\fB-s[ev]\fP \fIvolume\fP \fI[backup-file]\fP +Sets the NTFS ACLS as indicated in \fIbackup-file\fP or standard input. The +input data must have been created on Linux. With option \fB-e\fP, also sets +extra parameters (currently Windows attrib). +.TP +\fIvolume\fP \fIperms\fP \fIfile\fP +Sets the security parameters of file to perms. Perms is the Linux +requested mode (rwx flags, expressed in octal form as in chmod) or +a Posix ACL[1] (expressed like in setfacl -m). This sets a new ACL +which is effective for Linux and Windows. +.TP +\fB-r[v]\fP \fIvolume\fP \fIperms\fP \fIdirectory\fP +Sets the security parameters of all files and subdirectories in +\fIdirectory\fP to \fIperms\fP. Perms is the Linux requested mode (rwx flags, +expressed in octal form as in \fBchmod\fP), or a Posix ACL[1] (expressed like +in \fBsetfacl -m\fP.) This sets new ACLs which are effective for Linux and +Windows. +.TP +\fB[-v]\fP \fImounted-file\fP +Displays the security parameters of \fImounted-file\fP : its interpreted +Linux mode (rwx flags in octal) and Posix ACL[1], its security key if any, +and its security descriptor if verbose output. This is a special case which +acts on a mounted file (or directory) and does not require being root. The +Posix ACL interpretation can only be displayed if the full path to +\fImounted-file\fP from the root of the global file tree is provided. +.SH NOTE +[1] provided the POSIX ACL option was selected at compile time. A Posix ACL +specification looks like "\fB[d:]{ugmo}:[id]:[perms],...\fP" where id is a +numeric user or group id, and perms an octal digit or a set from the letters +r, w and x. +.RS +Example : "\fBu::7,g::5,o:0,u:510:rwx,g:500:5,d:u:510:7\fP" +.SH EXAMPLES +Audit the global security data on /dev/sda1 +.RS +.sp +.B ntfs-3g.secaudit -ar /dev/sda1 +.sp +.RE +Display the ownership and permissions parameters for files in directory +/audio/music on device /dev/sda5, excluding sub-directories : +.RS +.sp +.B ntfs-3g.secaudit /dev/sda5 /audio/music +.sp +.RE +Set all files in directory /audio/music on device /dev/sda5 as writeable +by owner and read-only for everybody : +.RS +.sp +.B ntfs-3g.secaudit -r /dev/sda5 644 /audio/music +.sp +.RE +.SH EXIT CODES +.B ntfs-3g.secaudit +exits with a value of 0 when no error was detected, and with a value +of 1 when an error was detected. +.SH KNOWN ISSUES +Please see +.RS +.sp +http://www.tuxera.com/community/ntfs-3g-faq/ +.sp +.RE +for common questions and known issues. +If you would find a new one in the latest release of +the software then please send an email describing it +in detail. You can contact the +development team on the ntfs\-3g\-devel@lists.sf.net +address. +.SH AUTHORS +.B ntfs-3g.secaudit +has been developed by Jean-Pierre André. +.SH THANKS +Several people made heroic efforts, often over five or more +years which resulted the ntfs-3g driver. Most importantly they are +Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy, +Yuval Fledel, and the author of the groundbreaking FUSE filesystem development +framework, Miklos Szeredi. +.SH SEE ALSO +.BR ntfsprogs (8), +.BR attr (5), +.BR getfattr (1) diff --git a/release/src/router/ntfs-3g/src/ntfs-3g.usermap.8.in b/release/src/router/ntfs-3g/src/ntfs-3g.usermap.8.in new file mode 100644 index 0000000000..02d4edd489 --- /dev/null +++ b/release/src/router/ntfs-3g/src/ntfs-3g.usermap.8.in @@ -0,0 +1,96 @@ +.\" Copyright (c) 2007-2009 Jean-Pierre André. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH NTFS-3G.USERMAP 8 "November 2009" "ntfs-3g.usermap 1.1.2" +.SH NAME +ntfs-3g.usermap \- NTFS Building a User Mapping File +.SH SYNOPSIS +.B ntfs-3g.usermap +\fIwindows-system-device\fP +\fB[\fIother-ntfs-device\fP...\fB]\fR +.PP +Where \fIwindows-system-device\fP is the device containing the Windows system +whose users are to be mapped to current Linux system. +.PP +And \fIother-ntfs-device\fP is another device containing files which are +to be accessed both by the Windows mentioned above and current Linux system. +.PP +the ntfs-3g.usermap command must be started as root, and the designated devices +must not be mounted. +.PP +Typing ntfs-3g.usermap with no args will display a summary of command +arguments. +.SH DESCRIPTION +\fBntfs-3g.usermap\fR +creates the file defining the mapping of Windows accounts to Linux logins for +users who owns files which should be visible from both Windows and +Linux. +.PP +It relies on existing files which were created on Windows, trying +to locate significant files and asking which Linux user or group should +own them. When a Linux owner or group is requested, the reply may be : +.PP +- the uid or gid (numeric or symbolic) of Linux owner or group of the file. +.RS +In that situation, no more file with the same Windows owner will be selected. +.RE +- or no answer, when not able to define the owner or group. +.RS +In that situation another file owned by the same Windows user or group +may be selected later so that a mapping can be defined. +.RE +.PP +The mappings for standard Windows users, such as "Administrator" or +"All Users" are defined implicitly. As a consequence a user mapping should +never be defined as Linux root. +.PP +When there are no more significant files, ntfs-3g.usermap create the +mapping file into the file UserMapping in the current directory. This +file has to be moved to the hidden directory .NTFS-3G in the root of +all the NTFS file systems to be shared between Windows and Linux. This +requires the file system to be mounted, but the created file will not +be taken into account if not present at mount time, which means the +file system has to be unmounted and mounted again for the new mapping +file to be taken into account. +.SH OPTIONS +No option is defined for ntfs-3g.usermap. +.SH EXAMPLES +Map the users defined on the Windows system present on /dev/sda1 : +.RS +.sp +.B ntfs-3g.usermap /dev/sda1 +.sp +.RE +.PP +A detailed example, with screen displays is available on +http://pagesperso-orange.fr/b.andre/usermap.html +.SH EXIT CODES +.B ntfs-3g.usermap +exits with a value of 0 when no error was detected, and with a value +of 1 when an error was detected. +.SH KNOWN ISSUES +Please see +.RS +.sp +http://www.tuxera.com/community/ntfs-3g-faq/ +.sp +.RE +for common questions and known issues. +If you would find a new one in the latest release of +the software then please send an email describing it +in detail. You can contact the +development team on the ntfs\-3g\-devel@lists.sf.net +address. +.SH AUTHORS +.B ntfs-3g.secaudit +has been developed by Jean-Pierre André. +.SH THANKS +Several people made heroic efforts, often over five or more +years which resulted the ntfs-3g driver. Most importantly they are +Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy, +Yuval Fledel, and the author of the groundbreaking FUSE filesystem development +framework, Miklos Szeredi. +.SH SEE ALSO +.BR ntfsprogs (8), +.BR attr (5), +.BR getfattr (1) diff --git a/release/src/router/ntfs-3g/src/secaudit.c b/release/src/router/ntfs-3g/src/secaudit.c new file mode 100644 index 0000000000..026b3ec795 --- /dev/null +++ b/release/src/router/ntfs-3g/src/secaudit.c @@ -0,0 +1,7113 @@ +/* + * Display and audit security attributes in an NTFS volume + * + * Copyright (c) 2007-2009 Jean-Pierre Andre + * + * Options : + * -a auditing security data + * -b backing up NTFS ACLs + * -e set extra backed-up parameters (in conjunction with -s) + * -h displaying hexadecimal security descriptors within a file + * -r recursing in a directory + * -s setting backed-up NTFS ACLs + * -v verbose (very verbose if set twice) + * also, if compile-time option is set + * -t run internal tests (with no access to storage) + * + * On Linux (being root, with volume not mounted) : + * secaudit -h [file] + * display the security descriptors found in file + * secaudit -a[rv] volume + * audit the volume + * secaudit [-v] volume file + * display the security parameters of file + * secaudit -r[v] volume directory + * display the security parameters of files in directory + * secaudit -b[v] volume [directory] + * backup the security parameters of files in directory + * secaudit -s[ve] volume [backupfile] + * set the security parameters as indicated in backup + * with -e set extra parameters (Windows attrib) + * secaudit volume perms file + * set the security parameters of file to perms (mode or acl) + * secaudit -r[v] volume perms directory + * set the security parameters of files in directory to perms + * special case, does not require being root : + * secaudit [-v] mounted-file + * display the security parameters of mounted file + * + * + * On Windows (the volume being part of file name) + * secaudit -h [file] + * display the security descriptors found in file + * secaudit [-v] file + * display the security parameters of file + * secaudit -r[v] directory + * display the security parameters of files in directory + * secaudit -b[v] directory + * backup the security parameters of files in directory + * secaudit -s[v] [backupfile] + * set the security parameters as indicated in backup + * with -e set extra parameters (Windows attrib) + * secaudit perms file + * set the security parameters of file to perms (mode or acl) + * secaudit -r[v] perms directory + * set the security parameters of files in directory to perms + */ + +/* History + * + * Nov 2007 + * - first version, by concatenating miscellaneous utilities + * + * Jan 2008, version 1.0.1 + * - fixed mode displaying + * - added a global severe errors count + * + * Feb 2008, version 1.0.2 + * - implemented conversions for big-endian machines + * + * Mar 2008, version 1.0.3 + * - avoided consistency checks on $Secure when there is no such file + * + * Mar 2008, version 1.0.4 + * - changed ordering of ACE's + * - changed representation for special flags + * - defaulted to stdin for option -h + * - added self tests (compile time option) + * - fixed errors specific to big-endian computers + * + * Apr 2008, version 1.1.0 + * - developped Posix ACLs to NTFS ACLs conversions + * - developped NTFS ACLs backup and restore + * + * Apr 2008, version 1.1.1 + * - fixed an error specific to big-endian computers + * - checked hash value and fixed error report in restore + * - improved display in showhex() and restore() + * + * Apr 2008, version 1.1.2 + * - improved and fixed Posix ACLs to NTFS ACLs conversions + * + * Apr 2008, version 1.1.3 + * - reenabled recursion for setting a new mode or ACL + * - processed Unicode file names and displayed them as UTF-8 + * - allocated dynamically memory for file names when recursing + * + * May 2008, version 1.1.4 + * - all Unicode/UTF-8 strings checked and processed + * + * Jul 2008, version 1.1.5 + * - made Windows owner consistent with Linux owner when changing mode + * - allowed owner change on Windows when it does not match Linux owner + * - skipped currently unused code + * + * Aug 2008, version 1.2.0 + * - processed \.NTFS-3G\UserMapping on Windows + * - made use of user mappings through the security API or direct access + * - fixed a bug in restore + * - fixed UTF-8 conversions + * + * Sep 2008, version 1.3.0 + * - split the code to have part of it shared with ntfs-3g library + * - fixed testing for end of SDS block + * - added samples checking in selftest for easier debugging + * + * Oct 2008, version 1.3.1 + * - fixed outputting long long data when testing on a Palm organizer + * + * Dec 2008, version 1.3.2 + * - fixed restoring ACLs + * - added optional logging of ACL hashes to facilitate restore checks + * - fixed collecting SACLs + * - fixed setting special control flags + * - fixed clearing existing SACLs (Linux only) and DACLs + * - changed the sequencing of items when quering a security descriptor + * - avoided recursing on junctions and symlinks on Windows + * + * Jan 2009, version 1.3.3 + * - save/restore Windows attributes (code from Faisal) + * + * Mar 2009, version 1.3.4 + * - enabled displaying attributes of a mounted file over Linux + * + * Apr 2009, version 1.3.5 + * - fixed initialisation of stand-alone user mapping + * - fixed POSIXACL redefinition when included in the ntfs-3g package + * - fixed displaying of options + * - fixed a dependency on the shared library version used + * + * May 2009, version 1.3.6 + * - added new samples for self testing + * + * Jun 2009, version 1.3.7 + * - fixed displaying owner and group of a mounted file over Linux + * + * Jul 2009, version 1.3.8 + * - fixed again displaying owner and group of a mounted file over Linux + * - cleaned some code to avoid warnings + * + * Nov 2009, version 1.3.9 + * - allowed security descriptors up to 64K + */ + +/* + * 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * General parameters which may have to be adapted to needs + */ + +#define AUDT_VERSION "1.3.9" + +#define GET_FILE_SECURITY "ntfs_get_file_security" +#define SET_FILE_SECURITY "ntfs_set_file_security" +#define GET_FILE_ATTRIBUTES "ntfs_get_file_attributes" +#define SET_FILE_ATTRIBUTES "ntfs_set_file_attributes" +#define READ_DIRECTORY "ntfs_read_directory" +#define READ_SDS "ntfs_read_sds" +#define READ_SII "ntfs_read_sii" +#define READ_SDH "ntfs_read_sdh" +#define GET_USER "ntfs_get_user" +#define GET_GROUP "ntfs_get_group" +#define GET_USID "ntfs_get_usid" +#define GET_GSID "ntfs_get_gsid" +#define INIT_FILE_SECURITY "ntfs_initialize_file_security" +#define LEAVE_FILE_SECURITY "ntfs_leave_file_security" + +/* + * External declarations + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + /* + * integration into secaudit, check whether Win32, + * may have to be adapted to compiler or something else + */ + +#ifndef WIN32 +#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC) +#define WIN32 1 +#endif +#endif + + /* + * integration into secaudit/Win32 + */ +#ifdef WIN32 +#include +#define __LITTLE_ENDIAN 1234 +#define __BYTE_ORDER __LITTLE_ENDIAN +#else + /* + * integration into secaudit/STSC + */ +#ifdef STSC +#include +#undef __BYTE_ORDER +#define __BYTE_ORDER __BIG_ENDIAN +#else + /* + * integration into secaudit/Linux + */ + +#include +#include +#include +#include +#endif /* STSC */ +#endif /* WIN32 */ +#include "secaudit.h" + +#ifndef WIN32 + +#ifndef STSC + +#if !defined(HAVE_CONFIG_H) && POSIXACLS + /* require if not integrated into ntfs-3g package */ +#define HAVE_SETXATTR 1 +#endif + +#ifdef HAVE_CONFIG_H + /* according to config.h if integrated into ntfs-3g package */ +#include "config.h" +#ifndef POSIXACLS +#define POSIXACLS 0 +#endif +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_SETXATTR +#include +#else +#warning "The extended attribute package is not available" +#endif /* HAVE_SETXATTR */ + +#endif /* STSC */ + +#define MS_NONE 0 /* no flag for mounting the device */ +#define MS_RDONLY 1 /* flag for mounting the device read-only */ + +struct CALLBACK; + +typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname, + int length, int type, long long pos, u64 mft_ref, + unsigned int dt_type); + +#if USESTUBS | defined(STSC) + +int ntfs_get_file_security(void *scapi, + const char *path, DWORD selection, + char *buf, DWORD buflen, LPDWORD psize); +BOOL ntfs_set_file_security(void *scapi, + const char *path, DWORD selection, const char *attr); +int ntfs_get_file_attributes(void *scapi, + const char *path); +BOOL ntfs_set_file_attributes(void *scapi, + const char *path, DWORD attrib); +BOOL ntfs_read_directory(void *scapi, + const char *path, dircallback callback, void *context); +int ntfs_read_sds(void *scapi, + char *buf, DWORD buflen, DWORD offset); +void *ntfs_read_sii(void *scapi, void *entry); +void *ntfs_read_sdh(void *scapi, void *entry); + +int ntfs_get_usid(void *scapi, uid_t uid, char *buf); +int ntfs_get_gsid(void *scapi, gid_t gid, char *buf); +int ntfs_get_user(void *scapi, const char *usid); +int ntfs_get_group(void *scapi, const char *gsid); + +void *ntfs_initialize_file_security(const char *device, int flags); +BOOL ntfs_leave_file_security(void *scapi); + +#else + +typedef int (*type_get_file_security)(void *scapi, + const char *path, DWORD selection, + char *buf, DWORD buflen, LPDWORD psize); +typedef BOOL (*type_set_file_security)(void *scapi, + const char *path, DWORD selection, const char *attr); +typedef int (*type_get_file_attributes)(void *scapi, + const char *path); +typedef BOOL (*type_set_file_attributes)(void *scapi, + const char *path, DWORD attrib); +typedef BOOL (*type_read_directory)(void *scapi, + const char *path, dircallback callback, void *context); +typedef int (*type_read_sds)(void *scapi, + char *buf, DWORD buflen, DWORD offset); +typedef void *(*type_read_sii)(void *scapi, void *entry); +typedef void *(*type_read_sdh)(void *scapi, void *entry); + +typedef int (*type_get_usid)(void *scapi, uid_t uid, char *buf); +typedef int (*type_get_gsid)(void *scapi, gid_t gid, char *buf); +typedef int (*type_get_user)(void *scapi, const char *usid); +typedef int (*type_get_group)(void *scapi, const char *gsid); + +typedef void *(*type_initialize_file_security)(const char *device, int flags); +typedef BOOL (*type_leave_file_security)(void *scapi); + +type_get_file_security ntfs_get_file_security; +type_set_file_security ntfs_set_file_security; +type_get_file_attributes ntfs_get_file_attributes; +type_set_file_attributes ntfs_set_file_attributes; +type_read_directory ntfs_read_directory; +type_read_sds ntfs_read_sds; +type_read_sii ntfs_read_sii; +type_read_sdh ntfs_read_sdh; + +type_get_usid ntfs_get_usid; +type_get_gsid ntfs_get_gsid; +type_get_user ntfs_get_user; +type_get_group ntfs_get_group; + +type_initialize_file_security ntfs_initialize_file_security; +type_leave_file_security ntfs_leave_file_security; + + +#endif /* USESTUBS | defined(STSC) */ +#endif /* WIN32 */ + +/* + * Prototypes for local functions + */ + +BOOL open_security_api(void); +BOOL close_security_api(void); +#ifndef WIN32 +BOOL open_volume(const char*, int flags); +BOOL close_volume(const char*); +#endif +unsigned int get2l(const char*, int); +unsigned long get4l(const char*, int); +u64 get6l(const char*, int); +u64 get6h(const char*, int); +u64 get8l(const char*, int); +void set2l(char*, unsigned int); +void set4l(char*, unsigned long); +void hexdump(const char*, int, int); +u32 hash(const le32*, int); +unsigned int utf8size(const char*, int); +unsigned int makeutf8(char*, const char*, int); +unsigned int utf16size(const char*); +unsigned int makeutf16(char*, const char*); +unsigned int utf16len(const char*); +void printname(FILE*, const char*); +void printerror(FILE*); +BOOL guess_dir(const char*); +void showsid(const char*, int, int); +void showusid(const char*, int); +void showgsid(const char*, int); +void showheader(const char*, int); +void showace(const char*, int, int, int); +void showacl(const char*, int, int, int); +void showdacl(const char*, int, int); +void showsacl(const char*, int, int); +void showall(const char*, int); +void showposix(const struct POSIX_SECURITY*); +int linux_permissions(const char*, BOOL); +uid_t linux_owner(const char*); +gid_t linux_group(const char*); +int basicread(void*, char*, size_t, off_t); +int dummyread(void*, char*, size_t, off_t); +int local_build_mapping(struct MAPPING *[], const char*); +void newblock(s32); +void freeblocks(void); +u32 getmsbhex(const char*); +u32 getlsbhex(const char*); +BOOL ishexdump(const char*, int, int); +void showhex(FILE*); +void showfull(const char*, BOOL); +BOOL applyattr(const char*, const char*, BOOL, int, s32); +BOOL restore(FILE*); +BOOL dorestore(const char*, FILE*); +u32 merge_rights(const struct POSIX_SECURITY*, BOOL); +void tryposix(struct POSIX_SECURITY*); +void check_samples(void); +void basictest(int, BOOL, const SID*, const SID*); +void posixtest(int, BOOL, const SID*, const SID*); +void selftests(void); +unsigned int getfull(char*, const char*); +BOOL updatefull(const char *name, DWORD flags, char *attr); +BOOL setfull(const char*, int, BOOL); +BOOL singleshow(const char*); +void showmounted(const char*); +BOOL recurseshow(const char*); +BOOL singleset(const char*, int); +BOOL recurseset(const char*, int); +#ifdef WIN32 +BOOL backup(const char*); +BOOL listfiles(const char*); +#if POSIXACLS +BOOL iterate(RECURSE, const char*, const struct POSIX_SECURITY*); +#else +BOOL iterate(RECURSE, const char*, mode_t); +#endif +#else +BOOL backup(const char*, const char*); +BOOL listfiles(const char*, const char*); +#endif +#if POSIXACLS +BOOL setfull_posix(const char *, const struct POSIX_SECURITY*, BOOL); +struct POSIX_SECURITY *linux_permissions_posix(const char*, BOOL); +BOOL recurseset_posix(const char*, const struct POSIX_SECURITY*); +BOOL singleset_posix(const char*, const struct POSIX_SECURITY*); +struct POSIX_SECURITY *encode_posix_acl(const char*); +#endif +static void stdfree(void*); + +BOOL valid_sds(const char*, unsigned int, unsigned int, + unsigned int, u32, BOOL); +BOOL valid_sii(const char*, u32); +BOOL valid_sdh(const char*, u32, u32); +int consist_sds(const char*, unsigned int, unsigned int, BOOL); +int consist_sii(const char*); +int consist_sdh(const char*); +int audit_sds(BOOL); +int audit_sii(void); +int audit_sdh(void); +void audit_summary(void); +BOOL audit(const char*); +int getoptions(int, char*[]); + +#ifndef WIN32 + +/* + * Structures for collecting directory contents (Linux only) + */ + +struct LINK { + struct LINK *next; + char name[1]; +} ; + +struct CALLBACK { + struct LINK *head; + const char *dir; +} ; + +int callback(struct CALLBACK *context, char *ntfsname, + int length, int type, long long pos, u64 mft_ref, + unsigned int dt_type); +#endif + +/* + * Global constants + */ + +#define BANNER "secaudit " AUDT_VERSION " : NTFS security data auditing" + +#if SELFTESTS & !USESTUBS + +/* + * Dummy mapping file (self tests only) + */ + +#define DUMMYAUTH "S-1-5-21-3141592653-589793238-462843383-" +char dummymapping[] = "500::" DUMMYAUTH "1000\n" + "501::" DUMMYAUTH "1001\n" + "502::" DUMMYAUTH "1002\n" + "503::" DUMMYAUTH "1003\n" + "516::" DUMMYAUTH "1016\n" + ":500:" DUMMYAUTH "513\r\n" + ":511:S-1-5-21-1607551490-981732888-1819828000-513\n" + ":516:" DUMMYAUTH "1012\r\n" + "::" DUMMYAUTH "10000\n"; + +/* + * SID for world (S-1-1-0) + */ + +static const char worldsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 1, /* base */ + 0, 0, 0, 0 /* 1st level */ +} ; +static const SID *worldsid = (const SID*)worldsidbytes; + +/* + * SID for administrator + */ + +static const char adminsidbytes[] = { + 1, /* revision */ + 2, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 32, 0, 0, 0, /* 1st level */ + 32, 2, 0, 0 /* 2nd level */ +}; + +static const SID *adminsid = (const SID*)adminsidbytes; + +/* + * SID for system + */ + +static const char systemsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 18, 0, 0, 0 /* 1st level */ + }; + +static const SID *systemsid = (const SID*)systemsidbytes; + +#endif + +/* + * Global variables + */ + +BOOL opt_a; /* audit security data */ +BOOL opt_b; /* backup NTFS ACLs */ +BOOL opt_e; /* restore extra (currently windows attribs) */ +BOOL opt_h; /* display an hexadecimal descriptor in a file */ +BOOL opt_r; /* recursively apply to subdirectories */ +BOOL opt_s; /* restore NTFS ACLs */ +#if SELFTESTS & !USESTUBS +BOOL opt_t; /* run self-tests */ +#endif +int opt_v; /* verbose or very verbose*/ +struct SECURITY_DATA *securdata[(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ)]; +#if FORCEMASK +BOOL opt_m; /* force a mask - dangerous */ +u32 forcemsk /* mask to force */ +#endif +unsigned int errors; /* number of severe errors */ +unsigned int warnings; /* number of non-severe errors */ + +struct CHKALLOC *firstalloc; +struct SECURITY_CONTEXT context; +MAPTYPE mappingtype; + +#ifdef STSC +#define static +#endif + +#ifndef WIN32 + +void *ntfs_handle; +void *ntfs_context = (void*)NULL; + +/* + * Open and close the security API (platform dependent) + */ + +BOOL open_security_api(void) +{ +#if USESTUBS | defined(STSC) + return (TRUE); +#else + char *error; + BOOL err; + const char *libfile; + + err = TRUE; + libfile = getenv(ENVNTFS3G); + if (!libfile) + libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE); + ntfs_handle = dlopen(libfile,RTLD_LAZY); + if (ntfs_handle) { + ntfs_initialize_file_security = (type_initialize_file_security) + dlsym(ntfs_handle,INIT_FILE_SECURITY); + error = dlerror(); + if (error) + fprintf(stderr," %s\n",error); + else { + ntfs_leave_file_security = (type_leave_file_security) + dlsym(ntfs_handle,LEAVE_FILE_SECURITY); + ntfs_get_file_security = (type_get_file_security) + dlsym(ntfs_handle,GET_FILE_SECURITY); + ntfs_set_file_security = (type_set_file_security) + dlsym(ntfs_handle,SET_FILE_SECURITY); + ntfs_get_file_attributes = (type_get_file_attributes) + dlsym(ntfs_handle,GET_FILE_ATTRIBUTES); + ntfs_set_file_attributes = (type_set_file_attributes) + dlsym(ntfs_handle,SET_FILE_ATTRIBUTES); + ntfs_read_directory = (type_read_directory) + dlsym(ntfs_handle,READ_DIRECTORY); + ntfs_read_sds = (type_read_sds) + dlsym(ntfs_handle,READ_SDS); + ntfs_read_sii = (type_read_sii) + dlsym(ntfs_handle,READ_SII); + ntfs_read_sdh = (type_read_sdh) + dlsym(ntfs_handle,READ_SDH); + ntfs_get_user = (type_get_user) + dlsym(ntfs_handle,GET_USER); + ntfs_get_group = (type_get_group) + dlsym(ntfs_handle,GET_GROUP); + ntfs_get_usid = (type_get_usid) + dlsym(ntfs_handle,GET_USID); + ntfs_get_gsid = (type_get_gsid) + dlsym(ntfs_handle,GET_GSID); + err = !ntfs_initialize_file_security + || !ntfs_leave_file_security + || !ntfs_get_file_security + || !ntfs_set_file_security + || !ntfs_get_file_attributes + || !ntfs_set_file_attributes + || !ntfs_read_directory + || !ntfs_read_sds + || !ntfs_read_sii + || !ntfs_read_sdh + || !ntfs_get_user + || !ntfs_get_group + || !ntfs_get_usid + || !ntfs_get_gsid; + + if (error) + fprintf(stderr,"ntfs-3g API not available\n"); + } + } else { + fprintf(stderr,"Could not open ntfs-3g library\n"); + fprintf(stderr,"\nPlease set environment variable \"" ENVNTFS3G "\"\n"); + fprintf(stderr,"to appropriate path and retry\n"); + } + return (!err); +#endif /* USESTUBS | defined(STSC) */ +} + +BOOL close_security_api(void) +{ +#if USESTUBS | defined(STSC) + return (0); +#else + return (!dlclose(ntfs_handle)); +#endif /* USESTUBS | defined(STSC) */ +} + +/* + * Open and close a volume (platform dependent) + * Assumes a single volume is opened + */ + +BOOL open_volume(const char *volume, int flags) +{ + BOOL ok; + + ok = FALSE; + if (!ntfs_context) { + ntfs_context = (*ntfs_initialize_file_security)(volume,flags); + if (ntfs_context) { + if (*(u32*)ntfs_context != MAGIC_API) { + fprintf(stderr,"Versions of ntfs-3g and secaudit" + " are not compatible\n"); + } else { + fprintf(stderr,"\"%s\" opened\n",volume); + mappingtype = MAPEXTERN; + ok = TRUE; + } + } else { + fprintf(stderr,"Could not open \"%s\"\n",volume); + fprintf(stderr,"Make sure \"%s\" is not mounted\n",volume); + } + } else + fprintf(stderr,"A volume is already open\n"); + return (ok); +} + +BOOL close_volume(const char *volume) +{ + BOOL r; + + r = (*ntfs_leave_file_security)(ntfs_context); + if (r) + fprintf(stderr,"\"%s\" closed\n",volume); + else + fprintf(stderr,"Could not close \"%s\"\n",volume); + ntfs_context = (void*)NULL; + return (r); +} + +#endif /* WIN32 */ + +/* + * Extract small or big endian data from an array of bytes + */ + +unsigned int get2l(const char *attr, int p) +{ + int i; + unsigned int v; + + v = 0; + for (i=0; i<2; i++) + v += (attr[p+i] & 255) << (8*i); + return (v); +} + +unsigned long get4l(const char *attr, int p) +{ + int i; + unsigned long v; + + v = 0; + for (i=0; i<4; i++) + v += ((long)(attr[p+i] & 255)) << (8*i); + return (v); +} + +u64 get6l(const char *attr, int p) +{ + int i; + u64 v; + + v = 0; + for (i=0; i<6; i++) + v += ((long long)(attr[p+i] & 255)) << (8*i); + return (v); +} + +u64 get6h(const char *attr, int p) +{ + int i; + u64 v; + + v = 0; + for (i=0; i<6; i++) + v = (v << 8) + (attr[p+i] & 255); + return (v); +} + +u64 get8l(const char *attr, int p) +{ + int i; + u64 v; + + v = 0; + for (i=0; i<8; i++) + v += ((long long)(attr[p+i] & 255)) << (8*i); + return (v); +} + +/* + * Set small or big endian data into an array of bytes + */ + +void set2l(char *p, unsigned int v) +{ + int i; + + for (i=0; i<2; i++) + p[i] = ((v >> 8*i) & 255); +} + +void set4l(char *p, unsigned long v) +{ + int i; + + for (i=0; i<4; i++) + p[i] = ((v >> 8*i) & 255); +} + + +/* + * hexadecimal dump of an array of bytes + */ + +void hexdump(const char *attr, int size, int level) +{ + int i,j; + + for (i=0; i> 29) & 7); + return (h); +} + +/* + * Evaluate the size of UTS-8 conversion of a UTF-16LE text + * trailing '\0' not accounted for + * Returns 0 for invalid input + */ + +unsigned int utf8size(const char *utf16, int length) +{ + int i; + unsigned int size; + enum { BASE, SURR, ERR } state; + + size = 0; + state = BASE; + for (i=0; i<2*length; i+=2) { + switch (state) { + case BASE : + if (utf16[i+1] & 0xf8) { + if ((utf16[i+1] & 0xf8) == 0xd8) + state = (utf16[i+1] & 4 ? ERR : SURR); + else +#if NOREVBOM + if (((utf16[i+1] & 0xff) == 0xff) + && ((utf16[i] & 0xfe) == 0xfe)) + state = ERR; + else + size += 3; +#else + size += 3; +#endif + } else + if ((utf16[i] & 0x80) || utf16[i+1]) + size += 2; + else + size++; + break; + case SURR : + if ((utf16[i+1] & 0xfc) == 0xdc) { + state = BASE; + size += 4; + } else + state = ERR; + break; + case ERR : + break; + } + } + if (state != BASE) + size = 0; + return (size); +} + +/* + * Convert a UTF-16LE text to UTF-8 + * Note : wcstombs() not used because on Linux it fails for characters + * not present in current locale + * Returns size or zero for invalid input + */ + +unsigned int makeutf8(char *utf8, const char *utf16, int length) +{ + int i; + unsigned int size; + unsigned int rem; + enum { BASE, SURR, ERR } state; + + size = 0; + rem = 0; + state = BASE; + for (i=0; i<2*length; i+=2) { + switch (state) { + case BASE : + if (utf16[i+1] & 0xf8) { + if ((utf16[i+1] & 0xf8) == 0xd8) { + if (utf16[i+1] & 4) + state = ERR; + else { + utf8[size++] = 0xf0 + (utf16[i+1] & 7) + + ((utf16[i] & 0xc0) == 0xc0); + utf8[size++] = 0x80 + (((utf16[i] + 64) >> 2) & 63); + rem = utf16[i] & 3; + state = SURR; + } + } else { +#if NOREVBOM + if (((utf16[i+1] & 0xff) == 0xff) + && ((utf16[i] & 0xfe) == 0xfe)) + state = ERR; + else { + utf8[size++] = 0xe0 + ((utf16[i+1] >> 4) & 15); + utf8[size++] = 0x80 + + ((utf16[i+1] & 15) << 2) + + ((utf16[i] >> 6) & 3); + utf8[size++] = 0x80 + (utf16[i] & 63); + } +#else + utf8[size++] = 0xe0 + ((utf16[i+1] >> 4) & 15); + utf8[size++] = 0x80 + + ((utf16[i+1] & 15) << 2) + + ((utf16[i] >> 6) & 3); + utf8[size++] = 0x80 + (utf16[i] & 63); +#endif + } + } else + if ((utf16[i] & 0x80) || utf16[i+1]) { + utf8[size++] = 0xc0 + + ((utf16[i+1] & 15) << 2) + + ((utf16[i] >> 6) & 3); + utf8[size++] = 0x80 + (utf16[i] & 63); + } else + utf8[size++] = utf16[i]; + break; + case SURR : + if ((utf16[i+1] & 0xfc) == 0xdc) { + utf8[size++] = 0x80 + (rem << 4) + + ((utf16[i+1] & 3) << 2) + + ((utf16[i] >> 6) & 3); + utf8[size++] = 0x80 + (utf16[i] & 63); + state = BASE; + } else + state = ERR; + break; + case ERR : + break; + } + } + utf8[size] = 0; + if (state != BASE) + state = ERR; + return (state == ERR ? 0 : size); +} + +#ifdef WIN32 + +/* + * Evaluate the size of UTF-16LE conversion of a UTF-8 text + * (basic conversions only) + * trailing '\0' not accounted for + */ + +unsigned int utf16size(const char *utf8) +{ + unsigned int size; + const char *p; + int c; + unsigned int code; + enum { BASE, TWO, THREE, THREE2, THREE3, FOUR, ERR } state; + + p = utf8; + size = 0; + state = BASE; + while (*p) { + c = *p++ & 255; + switch (state) { + case BASE : + if (!(c & 0x80)) + size++; + else + if (c < 0xc2) + state = ERR; + else + if (c < 0xe0) + state = TWO; + else + if (c < 0xf0) { + if (c == 0xe0) + state = THREE2; + else + if (c == 0xed) + state = THREE3; + else + state = THREE; + } else + if (c < 0xf8) { + state = FOUR; + code = c & 7; + } else + state = ERR; + break; + case TWO : + if ((c & 0xc0) != 0x80) + state = ERR; + else { + size++; + state = BASE; + } + break; + case THREE : + if ((c & 0xc0) != 0x80) + state = ERR; + else + state = TWO; + break; + case THREE2 : + if ((c & 0xe0) != 0xa0) + state = ERR; + else + state = TWO; + break; + case THREE3 : + if ((c & 0xe0) != 0x80) + state = ERR; + else + state = TWO; + break; + case FOUR : + if ((((code << 6) + (c & 63)) > 0x10f) + || (((code << 6) + (c & 63)) < 0x10)) + state = ERR; + else { + size++; + state = THREE; + } + break; + case ERR : + break; + } + } + if (state != BASE) size = 0; + return (size); +} + +/* + * Convert a UTF8 text to UTF-16LE + * (basic conversions only) + * Note : mbstowcs() not used because on Linux it fails for characters + * not present in current locale + */ + +unsigned int makeutf16(char *target, const char *utf8) +{ + unsigned int size; + unsigned int code; + const char *p; + int c; + enum { BASE, TWO, THREE, THREE2, THREE3, FOUR, FOUR2, FOUR3, ERR } state; + + p = utf8; + size = 0; + c = 0; + state = BASE; + while (*p) { + c = *p++ & 255; + switch (state) { + case BASE : + if (!(c & 0x80)) { + target[2*size] = c; + target[2*size + 1] = 0; + size++; + } else { + if (c < 0xc2) + state = ERR; + else + if (c < 0xe0) { + code = c & 31; + state = TWO; + } else + if (c < 0xf0) { + code = c & 15; + if (c == 0xe0) + state = THREE2; + else + if (c == 0xed) + state = THREE3; + else + state = THREE; + } else + if (c < 0xf8) { + code = c & 7; + state = FOUR; + } else + state = ERR; + } + break; + case TWO : +#if NOREVBOM + if (((c & 0xc0) != 0x80) + || ((code == 0x3ff) && (c >= 0xbe))) +#else + if ((c & 0xc0) != 0x80) +#endif + state = ERR; + else { + target[2*size] = ((code & 3) << 6) + (c & 63); + target[2*size + 1] = ((code >> 2) & 255); + size++; + state = BASE; + } + break; + case THREE : + if ((c & 0xc0) != 0x80) + state = ERR; + else { + code = ((code & 15) << 6) + (c & 63); + state = TWO; + } + break; + case THREE2 : + if ((c & 0xe0) != 0xa0) + state = ERR; + else { + code = ((code & 15) << 6) + (c & 63); + state = TWO; + } + break; + case THREE3 : + if ((c & 0xe0) != 0x80) + state = ERR; + else { + code = ((code & 15) << 6) + (c & 63); + state = TWO; + } + break; + case FOUR : + if ((c & 0xc0) != 0x80) + state = ERR; + else { + code = (code << 6) + (c & 63); + state = FOUR2; + } + break; + case FOUR2 : + if ((c & 0xc0) != 0x80) + state = ERR; + else { + code = (code << 6) + (c & 63); + state = FOUR3; + } + break; + case FOUR3 : + if ((code > 0x43ff) + || (code < 0x400) + || ((c & 0xc0) != 0x80)) + state = ERR; + else { + target[2*size] = ((code - 0x400) >> 4) & 255; + target[2*size+1] = 0xd8 + (((code - 0x400) >> 12) & 3); + target[2*size+2] = ((code & 3) << 6) + (c & 63); + target[2*size+3] = 0xdc + ((code >> 2) & 3); + size += 2; + state = BASE; + } + break; + case ERR : + break; + } + } + if (state != BASE) + size = 0; + target[2*size] = 0; + target[2*size + 1] = 0; + return (size); +} + +unsigned int utf16len(const char *str) +{ + unsigned int len; + + len = 0; + while (str[2*len] || str[2*len+1]) len++; + return (len); +} + +#endif + +/* + * Print a file name + * on Windows it prints UTF-16LE names as UTF-8 + */ + +void printname(FILE *file, const char *name) +{ +#ifdef WIN32 + char utf8name[MAXFILENAME]; + + makeutf8(utf8name,name,utf16len(name)); + fprintf(file,"%s",utf8name); +#else + fprintf(file,"%s",name); +#endif +} + +/* + * Print the last error code + */ + +void printerror(FILE *file) +{ +#ifdef WIN32 + int err; + const char *txt; + + err = GetLastError(); + switch (err) { + case 5 : + txt = "Access to security descriptor was denied"; + break; + case 1307 : + txt = "This SID may not be assigned as the owner of this object"; + break; + case 1308 : + txt = "This SID may not be assigned as the group of this object"; + break; + case 1314 : + txt = "You do not have the privilege to change this SID"; + break; + default : + txt = (const char*)NULL; + break; + } + if (txt) + fprintf(file,"Error %d : %s\n",err,txt); + else + fprintf(file,"Error %d\n",err); +#else +#ifdef STSC + if (errno) fprintf(file,"Error code %d\n",errno); +#else + if (errno) fprintf(file,"Error code %d : %s\n",errno,strerror(errno)); +#endif +#endif +} + +/* + * Guess whether a security attribute is intended for a directory + * based on the presence of inheritable ACE + * (not 100% reliable) + */ + +BOOL guess_dir(const char *attr) +{ + int off; + int isdir; + int cnt; + int i; + int x; + + isdir = 0; + off = get4l(attr,16); + if (off) { + cnt = get2l(attr,off+4); + x = 8; + for (i=0; i> 16) & 127); + if (rights & 0x10000) + printf("%*cDelete\n",-level-8,marker); + if (rights & 0x20000) + printf("%*cRead control\n",-level-8,marker); + if (rights & 0x40000) + printf("%*cWrite DAC\n",-level-8,marker); + if (rights & 0x80000) + printf("%*cWrite owner\n",-level-8,marker); + if (rights & 0x100000) + printf("%*cSynchronize\n",-level-8,marker); + if (rights & 0x800000) + printf("%*cCan access security ACL\n",-level-4,marker); + if (rights & 0x10000000) + printf("%*cGeneric all\n",-level-4,marker); + if (rights & 0x20000000) + printf("%*cGeneric execute\n",-level-4,marker); + if (rights & 0x40000000) + printf("%*cGeneric write\n",-level-4,marker); + if (rights & 0x80000000) + printf("%*cGeneric read\n",-level-4,marker); + + printf("%*cSID at 0x%x\n",-level,marker,off+8); + showsid(attr,off+8,level+4); + printf("%*cSummary :",-level,marker); + if (attr[off] == 0) + printf(" grant"); + if (attr[off] == 1) + printf(" deny"); + if (rights & le32_to_cpu(FILE_GREAD | FILE_GWRITE | FILE_GEXEC)) { + printf(" "); + if (rights & le32_to_cpu(FILE_GREAD)) + printf("r"); + if (rights & le32_to_cpu(FILE_GWRITE)) + printf("w"); + if (rights & le32_to_cpu(FILE_GEXEC)) + printf("x"); + } else + printf(" none"); + if (flags & 11) + printf(" inherited"); + if (!(flags & 8)) { + int sz; + + printf(" applied"); + sz = attr[off+9]*4 + 8; + if (!memcmp(&attr[off+8],&attr[get4l(attr,4)],sz)) + printf(" to owner"); + if (!memcmp(&attr[off+8],&attr[get4l(attr,8)],sz)) + printf(" to group"); + } + printf("\n"); + +} + +void showacl(const char *attr, int off, int isdir, int level) +{ + int i; + int cnt; + int size; + int x; + char marker; + + if (opt_b) + marker = '#'; + else + marker = ' '; + size = get2l(attr,off+2); + printf("%*crevision %d\n",-level,marker,attr[off]); + printf("%*cACL size %d\n",-level,marker,size); + cnt = get2l(attr,off+4); + printf("%*cACE cnt %d\n",-level,marker,cnt); + x = 8; + for (i=0; (iacccnt; + defcnt = pxdesc->defcnt; + firstdef = pxdesc->firstdef; + acl = &pxdesc->acl; + printf("Posix descriptor :\n"); + printf(" acccnt %d\n",acccnt); + printf(" defcnt %d\n",defcnt); + printf(" firstdef %d\n",firstdef); + printf(" mode : 0%03o\n",(int)pxdesc->mode); + printf(" tagsset : 0x%02x\n",(int)pxdesc->tagsset); + printf("Posix ACL :\n"); + printf(" version %d\n",(int)acl->version); + printf(" flags 0x%02x\n",(int)acl->flags); + for (k=0; k<(acccnt + defcnt); k++) { + if (k < acccnt) + l = k; + else + l = firstdef + k - acccnt; + pxace = &acl->ace[l]; + tag = pxace->tag; + perms = pxace->perms; + if (tag == POSIX_ACL_SPECIAL) { + txperm[0] = (perms & S_ISVTX ? 's' : '-'); + txperm[1] = (perms & S_ISUID ? 'u' : '-'); + txperm[2] = (perms & S_ISGID ? 'g' : '-'); + } else { + txperm[0] = (perms & 4 ? 'r' : '-'); + txperm[1] = (perms & 2 ? 'w' : '-'); + txperm[2] = (perms & 1 ? 'x' : '-'); + } + txperm[3] = 0; + if (k >= acccnt) + txtype = "default"; + else + txtype = "access "; + switch (tag) { + case POSIX_ACL_USER : + txtag = "USER "; + break; + case POSIX_ACL_USER_OBJ : + txtag = "USR-O"; + break; + case POSIX_ACL_GROUP : + txtag = "GROUP"; + break; + case POSIX_ACL_GROUP_OBJ : + txtag = "GRP-O"; + break; + case POSIX_ACL_MASK : + txtag = "MASK "; + break; + case POSIX_ACL_OTHER : + txtag = "OTHER"; + break; + case POSIX_ACL_SPECIAL : + txtag = "SPECL"; + break; + default : + txtag = "UNKWN"; + break; + } + id = pxace->id; + printf("ace %d : %s %s %4ld perms 0%03o %s\n", + l,txtype,txtag,(long)id, + perms,txperm); + } + } else + printf("** NULL ACL\n"); +} + +#endif /* POSIXACLS */ + +#if defined(WIN32) | defined(STSC) + +#else + +/* + * Relay to get usid as defined during mounting + */ + +const SID *relay_find_usid(const struct MAPPING *usermapping __attribute__((unused)), + uid_t uid, SID *defusid) +{ + return (ntfs_get_usid(ntfs_context,uid,(char*)defusid) ? + defusid : (SID*)NULL); +} + +/* + * Relay to get gsid as defined during mounting + */ + +const SID *relay_find_gsid(const struct MAPPING *groupmapping __attribute__((unused)), + uid_t gid, SID *defgsid) +{ + return (ntfs_get_usid(ntfs_context,gid,(char*)defgsid) ? + defgsid : (SID*)NULL); +} + +/* + * Relay to get uid as defined during mounting + */ + +uid_t relay_find_user(const struct MAPPING *mapping __attribute__((unused)), + const SID *usid) +{ + int uid; + + uid = ntfs_get_user(ntfs_context,(const char*)usid); + return (uid < 0 ? 0 : uid); +} + +/* + * Relay to get gid as defined during mounting + */ + +gid_t relay_find_group(const struct MAPPING *mapping __attribute__((unused)), + const SID *gsid) +{ + int gid; + + gid = ntfs_get_group(ntfs_context,(const char*)gsid); + return (gid < 0 ? 0 : gid); +} + +#endif + +#if defined(WIN32) | defined(STSC) + +/* + * Dummy get uid from user name, out of a Linux environment + */ + +struct passwd *getpwnam(const char *user) +{ + ntfs_log_error("Cannot interpret id \"%s\"", user); + ntfs_log_error("please use numeric uids in UserMapping file\n"); + return ((struct passwd*)NULL); +} + +/* + * Dummy get gid from group name, out of a Linux environment + */ + +struct group *getgrnam(const char *group) +{ + ntfs_log_error("Cannot interpret id \"%s\"", group); + ntfs_log_error("please use numeric gids in UserMapping file\n"); + return ((struct group*)NULL); +} + +#endif /* defined(WIN32) | defined(STSC) */ + +#if POSIXACLS + +struct POSIX_SECURITY *linux_permissions_posix(const char *attr, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; +#if OWNERFROMACL + const SID *osid; +#endif + const SID *usid; + const SID *gsid; + struct POSIX_SECURITY *posix_desc; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + gsid = (const SID*)&attr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + osid = (const SID*)&attr[le32_to_cpu(phead->owner)]; + usid = ntfs_acl_owner((const char*)attr); +#if SELFTESTS & !USESTUBS + if (!opt_t && !ntfs_same_sid(usid,osid)) + printf("== Linux owner is different from Windows owner\n"); +#else + if (!ntfs_same_sid(usid,osid)) + printf("== Linux owner is different from Windows owner\n"); +#endif +#else + usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; +#endif + posix_desc = ntfs_build_permissions_posix(context.mapping, + (const char*)attr, usid, gsid, isdir); + if (!posix_desc) { + printf("** Failed to build a Posix descriptor\n"); + errors++; + } + return (posix_desc); +} + +#endif /* POSIXACLS */ + +int linux_permissions(const char *attr, BOOL isdir) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; +#if OWNERFROMACL + const SID *osid; +#endif + const SID *usid; + const SID *gsid; + int perm; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + gsid = (const SID*)&attr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + osid = (const SID*)&attr[le32_to_cpu(phead->owner)]; + usid = ntfs_acl_owner((const char*)attr); +#if SELFTESTS & !USESTUBS + if (!opt_t && !ntfs_same_sid(usid,osid)) + printf("== Linux owner is different from Windows owner\n"); +#else + if (!ntfs_same_sid(usid,osid)) + printf("== Linux owner is different from Windows owner\n"); +#endif +#else + usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; +#endif + perm = ntfs_build_permissions((const char*)attr, usid, gsid, isdir); + if (perm < 0) { + printf("** Failed to build permissions\n"); + errors++; + } + return (perm); +} + +uid_t linux_owner(const char *attr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const SID *usid; + uid_t uid; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; +#if OWNERFROMACL + usid = ntfs_acl_owner((const char*)attr); +#else + usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; +#endif +#if defined(WIN32) | defined(STSC) + uid = ntfs_find_user(context.mapping[MAPUSERS],usid); +#else + if (mappingtype == MAPEXTERN) + uid = relay_find_user(context.mapping[MAPUSERS],usid); + else + uid = ntfs_find_user(context.mapping[MAPUSERS],usid); +#endif + return (uid); +} + +gid_t linux_group(const char *attr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const SID *gsid; + gid_t gid; + + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + gsid = (const SID*)&attr[le32_to_cpu(phead->group)]; +#if defined(WIN32) | defined(STSC) + gid = ntfs_find_group(context.mapping[MAPGROUPS],gsid); +#else + if (mappingtype == MAPEXTERN) + gid = relay_find_group(context.mapping[MAPGROUPS],gsid); + else + gid = ntfs_find_group(context.mapping[MAPGROUPS],gsid); +#endif + return (gid); +} + +void newblock(s32 key) +{ + struct SECURITY_DATA *psecurdata; + int i; + + if ((key > 0) && (key < MAXSECURID) && !securdata[key >> SECBLKSZ]) { + securdata[key >> SECBLKSZ] = + (struct SECURITY_DATA*)malloc((1 << SECBLKSZ)*sizeof(struct SECURITY_DATA)); + if (securdata[key >> SECBLKSZ]) + for (i=0; i<(1 << SECBLKSZ); i++) { + psecurdata = &securdata[key >> SECBLKSZ][i]; + psecurdata->filecount = 0; + psecurdata->mode = 0; + psecurdata->flags = 0; + psecurdata->attr = (char*)NULL; + } + } +} + +void freeblocks(void) +{ + int i,j; + struct SECURITY_DATA *psecurdata; + + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + if (securdata[i]) { + for (j=0; j<(1 << SECBLKSZ); j++) { + psecurdata = &securdata[i][j]; + if (psecurdata->attr) + free(psecurdata->attr); + } + free(securdata[i]); + } +} + +/* + * Basic read from a user mapping file (Win32) + */ + +int basicread(void *fileid, char *buf, size_t size, + off_t pos __attribute__((unused))) +{ + return (read(*(int*)fileid, buf, size)); +} + +#if POSIXACLS & SELFTESTS & !USESTUBS + +/* + * Read a dummy mapping file for tests + */ + +int dummyread(void *fileid __attribute__((unused)), + char *buf, size_t size, off_t pos) +{ + size_t sz; + + if (pos >= (off_t)(sizeof(dummymapping) - 1)) + sz = 0; + else + if ((size + pos) >= (sizeof(dummymapping) - 1)) + sz = sizeof(dummymapping) - 1 - pos; + else + sz = size; + if (sz > 0) + memcpy(buf,&dummymapping[pos],sz); + return (sz); +} + +#endif /* POSIXACLS & SELFTESTS & !USESTUBS */ + +/* + * Build the user mapping + * - according to a mapping file if defined (or default present), + * - or try default single user mapping if possible + * + * The mapping is specific to a mounted device + * No locking done, mounting assumed non multithreaded + * + * returns zero if mapping is successful + * (failure should not be interpreted as an error) + */ + +int local_build_mapping(struct MAPPING *mapping[], const char *usermap_path) +{ +#ifdef WIN32 + char mapfile[sizeof(MAPDIR) + sizeof(MAPFILE) + 6]; +#else + char *mapfile; + char *p; +#endif + int fd; + struct MAPLIST *item; + struct MAPLIST *firstitem = (struct MAPLIST*)NULL; + struct MAPPING *usermapping; + struct MAPPING *groupmapping; + + /* be sure not to map anything until done */ + mapping[MAPUSERS] = (struct MAPPING*)NULL; + mapping[MAPGROUPS] = (struct MAPPING*)NULL; + + if (usermap_path) { +#ifdef WIN32 +/* TODO : check whether the device can store acls */ + strcpy(mapfile,"x:\\" MAPDIR "\\" MAPFILE); + if (((le16*)usermap_path)[1] == ':') + mapfile[0] = usermap_path[0]; + else + mapfile[0] = getdrive() + 'A' - 1; + fd = open(mapfile,O_RDONLY); +#else + fd = 0; + mapfile = (char*)malloc(MAXFILENAME); + if (mapfile) { + /* build a full path to locate the mapping file */ + if ((usermap_path[0] != '/') + && getcwd(mapfile,MAXFILENAME)) { + strcat(mapfile,"/"); + strcat(mapfile,usermap_path); + } else + strcpy(mapfile,usermap_path); + p = strrchr(mapfile,'/'); + if (p) + do { + strcpy(p,"/" MAPDIR "/" MAPFILE); + fd = open(mapfile,O_RDONLY); + if (fd <= 0) { + *p = 0; + p = strrchr(mapfile,'/'); + if (p == mapfile) + p = (char*)NULL; + } + } while ((fd <= 0) && p); + free(mapfile); + if (!p) { + printf("** Could not find the user mapping file\n"); + if (usermap_path[0] != '/') + printf(" Retry with full path of file\n"); + errors++; + } + } +#endif + if (fd > 0) { + firstitem = ntfs_read_mapping(basicread, (void*)&fd); + close(fd); + } + } else { +#if SELFTESTS & !USESTUBS + firstitem = ntfs_read_mapping(dummyread, (void*)NULL); +#endif + } + + if (firstitem) { + usermapping = ntfs_do_user_mapping(firstitem); + groupmapping = ntfs_do_group_mapping(firstitem); + if (usermapping && groupmapping) { + mapping[MAPUSERS] = usermapping; + mapping[MAPGROUPS] = groupmapping; + } else + ntfs_log_error("There were no valid user or no valid group\n"); + /* now we can free the memory copy of input text */ + /* and rely on internal representation */ + while (firstitem) { + item = firstitem->next; +#if USESTUBS + stdfree(firstitem); /* allocated within library */ +#else + free(firstitem); +#endif + firstitem = item; + } + } + if (mapping[MAPUSERS]) + mappingtype = MAPLOCAL; + return (!mapping[MAPUSERS]); +} + +/* + * Get an hexadecimal number (source with MSB first) + */ + +u32 getmsbhex(const char *text) +{ + u32 v; + int b; + BOOL ok; + + v = 0; + ok = TRUE; + do { + b = *text++; + if ((b >= '0') && (b <= '9')) + v = (v << 4) + b - '0'; + else + if ((b >= 'a') && (b <= 'f')) + v = (v << 4) + b - 'a' + 10; + else + if ((b >= 'A') && (b <= 'F')) + v = (v << 4) + b - 'A' + 10; + else ok = FALSE; + } while (ok); + return (v); +} + + +/* + * Get an hexadecimal number (source with LSB first) + * An odd number of digits might yield a strange result + */ + +u32 getlsbhex(const char *text) +{ + u32 v; + int b; + BOOL ok; + int pos; + + v = 0; + ok = TRUE; + pos = 0; + do { + b = *text++; + if ((b >= '0') && (b <= '9')) + v |= (u32)(b - '0') << (pos ^ 4); + else + if ((b >= 'a') && (b <= 'f')) + v |= (u32)(b - 'a' + 10) << (pos ^ 4); + else + if ((b >= 'A') && (b <= 'F')) + v |= (u32)(b - 'A' + 10) << (pos ^ 4); + else ok = FALSE; + pos += 4; + } while (ok); + return (v); +} + + +/* + * Check whether a line looks like an hex dump + */ + +BOOL ishexdump(const char *line, int first, int lth) +{ + BOOL ok; + int i; + int b; + + ok = (first >= 0) && (lth >= (first + 16)); + for (i=0; ((first+i)= '0') && (b <= '9')) + || ((b >= 'a') && (b <= 'f')) + || ((b >= 'A') && (b <= 'F')); + } + return (ok); +} + + +/* + * Display security descriptors from a file + * This is typically to convert a verbose output to a very verbose one + */ + +void showhex(FILE *fd) +{ + static char attr[MAXATTRSZ]; + char line[MAXLINE+1]; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + int lth; + int first; + unsigned int pos; + unsigned char b; + u32 v; + int c; + int isdir; + int mode; + unsigned int off; + int i; + BOOL isdump; + BOOL done; + + b = 0; + pos = 0; + off = 0; + done = FALSE; + do { + /* input a (partial) line without displaying */ + lth = 0; + first = -1; + do { + c = getc(fd); + if ((c != ' ') && (first < 0)) + first = lth; + if (c == EOF) + done = TRUE; + else + if (c != '\r') + line[lth++] = c; + } while (!done && (c != '\n') && (lth < MAXLINE)); + /* check whether this looks like an hexadecimal dump */ + isdump = ishexdump(line, first, lth); + if (isdump) off = getmsbhex(&line[first]); + /* line is not an hexadecimal dump */ + /* display what we have in store */ + if ((!isdump || !off) && pos && ntfs_valid_descr((char*)attr,pos)) { + printf(" Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr, + ntfs_attr_size(attr))); + isdir = guess_dir(attr); + printf(" Estimated type : %s\n",(isdir ? "directory" : "file")); + showheader(attr,4); + showusid(attr,4); + showgsid(attr,4); + showdacl(attr,isdir,4); + showsacl(attr,isdir,4); + mode = linux_permissions(attr,isdir); + printf("Interpreted Unix mode 0%03o\n",mode); +#if POSIXACLS + /* + * Posix display not possible when user + * mapping is not available (option -h) + */ + if (mappingtype != MAPNONE) { + pxdesc = linux_permissions_posix(attr,isdir); + if (pxdesc) { + showposix(pxdesc); + free(pxdesc); + } + } +#endif + pos = 0; + } + if (isdump && !off) + pos = off; + /* line looks like an hexadecimal dump */ + /* decode it into attribute */ + if (isdump && (off == pos)) { + for (i=first+8; i 0) && (key < MAXSECURID)) { + if (!securdata[key >> SECBLKSZ]) + newblock(key); + if (securdata[key >> SECBLKSZ]) { + psecurdata = &securdata[key >> SECBLKSZ] + [key & ((1 << SECBLKSZ) - 1)]; + } + } + + /* If we have a usable attrib value. Try applying */ + badattrib = FALSE; + if (opt_e && (attrib != INVALID_FILE_ATTRIBUTES)) { +#ifdef WIN32 + badattrib = !SetFileAttributesW((LPCWSTR)fullname, attrib); +#else + badattrib = !ntfs_set_file_attributes(ntfs_context, fullname, attrib); +#endif + if (badattrib) { + printf("** Could not set Windows attrib of "); + printname(stdout,fullname); + printf(" to 0x%x\n", attrib); + printerror(stdout); + warnings++; + } + } + + if (withattr) { + if (psecurdata) { + newattr = (char*)malloc(ntfs_attr_size(attr)); + if (newattr) { + memcpy(newattr,attr,ntfs_attr_size(attr)); + psecurdata->attr = newattr; + } + } + curattr = attr; + } else + /* + * No explicit attr in backup, use attr defined + * previously for the same id + */ + if (psecurdata) + curattr = psecurdata->attr; + + + if (curattr) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)curattr; +#ifdef WIN32 + /* SACL currently not set, need some special privilege */ + selection = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION; + bad = !SetFileSecurityW((LPCWSTR)fullname, + selection, (char*)curattr); + if (bad) + switch (GetLastError()) { + case 1307 : + case 1314 : + printf("** Could not set owner of "); + printname(stdout,fullname); + printf(", retrying with no owner setting\n"); + warnings++; + bad = !SetFileSecurityW((LPCWSTR)fullname, + selection & ~OWNER_SECURITY_INFORMATION, (char*)curattr); + break; + default : + break; + } +#else + selection = OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION + | SACL_SECURITY_INFORMATION; + bad = !ntfs_set_file_security(ntfs_context,fullname, + selection, (const char*)curattr); +#endif + if (bad) { + printf("** Could not set the ACL of "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + err = TRUE; + } else + if (opt_v) { + if (opt_e && !badattrib) + printf("ACL and attrib have been applied to "); + else + printf("ACL has been applied to "); + printname(stdout,fullname); + printf("\n"); + + } + } else { + printf("** There was no valid ACL for "); + printname(stdout,fullname); + printf("\n"); + err = TRUE; + } + return (!err); +} + +/* + * Restore security descriptors from a file + */ + +BOOL restore(FILE *fd) +{ + static char attr[MAXATTRSZ]; + char line[MAXFILENAME+25]; + char fullname[MAXFILENAME+25]; + SECURITY_DESCRIPTOR_RELATIVE *phead; + int lth; + int first; + unsigned int pos; + unsigned int size; + unsigned char b; + int c; + int isdir; + int mode; + s32 key; + BOOL isdump; + unsigned int off; + u32 v; + u32 oldhash; + int i; + int count; + int attrib; + BOOL withattr; + BOOL done; + + b = 0; + pos = 0; + size = 0; + off = 0; + done = FALSE; + withattr = FALSE; + oldhash = 0; + key = 0; + errors = 0; + count = 0; + fullname[0] = 0; + attrib = INVALID_FILE_ATTRIBUTES; + do { + /* input a (partial) line without processing */ + lth = 0; + first = -1; + do { + c = getc(fd); + if ((c != ' ') && (first < 0)) + first = lth; + if (c == EOF) + done = TRUE; + else + if (c != '\r') + line[lth++] = c; + } while (!done && (c != '\n') && (lth < (MAXFILENAME + 24))); + /* check whether this looks like an hexadecimal dump */ + isdump = ishexdump(line, first, lth); + if (isdump) off = getmsbhex(&line[first]); + /* line is not an hexadecimal dump */ + /* apply what we have in store */ + if ((!isdump || !off) && pos && ntfs_valid_descr((char*)attr,pos)) { + withattr = TRUE; + if (opt_v >= 2) { + printf(" Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr, + ntfs_attr_size(attr))); + isdir = guess_dir(attr); + printf(" Estimated type : %s\n",(isdir ? "directory" : "file")); + showheader(attr,4); + showusid(attr,4); + showgsid(attr,4); + showdacl(attr,isdir,4); + showsacl(attr,isdir,4); + mode = linux_permissions(attr,isdir); + printf("Interpreted Unix mode 0%03o\n",mode); + } + size = pos; + pos = 0; + } + if (isdump && !off) + pos = off; + /* line looks like an hexadecimal dump */ + /* decode it into attribute */ + if (isdump && (off == pos)) { + for (i=first+8; i 0) + && ((line[lth-1] == '\n') || (line[lth-1] == '\r'))) + line[--lth] = 0; + if (!strncmp(line,"Computed hash : 0x",18)) + oldhash = getmsbhex(&line[18]); + if (!strncmp(line,"Security key : 0x",17)) + key = getmsbhex(&line[17]); + if (!strncmp(line,"Windows attrib : 0x",19)) + attrib = getmsbhex(&line[19]); + if (done + || !strncmp(line,"File ",5) + || !strncmp(line,"Directory ",10)) { + /* + * New file or directory (or end of file) : + * apply attribute just collected + * or apply attribute defined from current key + */ + + if (withattr + && oldhash + && (hash((const le32*)attr,ntfs_attr_size(attr)) != oldhash)) { + printf("** ACL rejected, its hash is not as expected\n"); + errors++; + } else + if (fullname[0]) { + phead = (SECURITY_DESCRIPTOR_RELATIVE*)attr; + /* set the request for auto-inheritance */ + if (phead->control & SE_DACL_AUTO_INHERITED) + phead->control |= SE_DACL_AUTO_INHERIT_REQ; + if (!applyattr(fullname,attr,withattr, + attrib,key)) + errors++; + else + count++; + } + /* save current file or directory name */ + withattr = FALSE; + key = 0; + oldhash = 0; + attrib = INVALID_FILE_ATTRIBUTES; + if (!done) { +#ifdef WIN32 + if (!strncmp(line,"File ",5)) + makeutf16(fullname,&line[5]); + else + makeutf16(fullname,&line[10]); +#else + if (!strncmp(line,"File ",5)) + strcpy(fullname,&line[5]); + else + strcpy(fullname,&line[10]); +#endif + } + } + } while (!done); + printf("%d ACLs have been applied\n",count); + return (FALSE); +} + +/* + * Open the security API in rw mode for an ACL restoration + */ + +#ifdef WIN32 +#else +BOOL dorestore(const char *volume, FILE *fd) +{ + BOOL err; + + if (!getuid()) { + if (open_security_api()) { + if (open_volume(volume,MS_NONE)) { + if (!restore(fd)) err = TRUE; + close_volume(volume); + } else { + fprintf(stderr,"Could not open volume %s\n",volume); + printerror(stderr); + err = TRUE; + } + close_security_api(); + } else { + fprintf(stderr,"Could not open security API\n"); + printerror(stderr); + err = TRUE; + } + } else { + fprintf(stderr,"Restore is only possible as root\n"); + err = TRUE; + } + return (!err); +} +#endif /* WIN32 */ + +#if POSIXACLS & SELFTESTS & !USESTUBS + +/* + * Merge Posix ACL rights into an u32 (self test only) + * + * Result format : -----rwxrwxrwxrwxrwx---rwxrwxrwx + * U1 U2 G1 G2 M o g w + * + * Only two users (U1, U2) and two groups (G1, G2) taken into account + */ +u32 merge_rights(const struct POSIX_SECURITY *pxdesc, BOOL def) +{ + const struct POSIX_ACE *pxace; + int i; + int users; + int groups; + int first; + int last; + u32 rights; + + rights = 0; + users = 0; + groups = 0; + if (def) { + first = pxdesc->firstdef; + last = pxdesc->firstdef + pxdesc->defcnt - 1; + } else { + first = 0; + last = pxdesc->acccnt - 1; + } + pxace = pxdesc->acl.ace; + for (i=first; i<=last; i++) { + switch (pxace[i].tag) { + case POSIX_ACL_USER_OBJ : + rights |= (pxace[i].perms & 7) << 6; + break; + case POSIX_ACL_USER : + if (users < 2) + rights |= ((u32)pxace[i].perms & 7) << (24 - 3*users); + users++; + break; + case POSIX_ACL_GROUP_OBJ : + rights |= (pxace[i].perms & 7) << 3; + break; + case POSIX_ACL_GROUP : + if (groups < 2) + rights |= ((u32)pxace[i].perms & 7) << (18 - 3*groups); + groups++; + break; + case POSIX_ACL_MASK : + rights |= ((u32)pxace[i].perms & 7) << 12; + break; + case POSIX_ACL_OTHER : + rights |= (pxace[i].perms & 7); + break; + default : + break; + } + } + return (rights); +} + +void tryposix(struct POSIX_SECURITY *pxdesc) +{ + le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(1016) + } ; + le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(513) + } ; + + char *attr; + BOOL isdir; + mode_t mode; + struct POSIX_SECURITY *newpxdesc; + struct POSIX_SECURITY *oldpxdesc; + static char *oldattr = (char*)NULL; + + isdir = FALSE; + if (oldattr) { + oldpxdesc = linux_permissions_posix(oldattr, isdir); + newpxdesc = ntfs_merge_descr_posix(pxdesc, oldpxdesc); + if (!newpxdesc) + newpxdesc = pxdesc; + free(oldpxdesc); + if (opt_v) { + printf("merged descriptors :\n"); + showposix(newpxdesc); + } + } else + newpxdesc = pxdesc; + attr = ntfs_build_descr_posix(context.mapping,newpxdesc, + isdir,(SID*)owner_sid,(SID*)group_sid); + if (attr && ntfs_valid_descr(attr, ntfs_attr_size(attr))) { + if (opt_v) + hexdump(attr,ntfs_attr_size(attr),8); + if (opt_v >= 2) { + showheader(attr,4); + showusid(attr,4); + showgsid(attr,4); + showdacl(attr,isdir,4); + showsacl(attr,isdir,4); + mode = linux_permissions(attr,isdir); + printf("Interpreted Unix mode 0%03o\n",mode); + printf("Interpreted back Posix descriptor :\n"); + newpxdesc = linux_permissions_posix(attr,isdir); + showposix(newpxdesc); + free(newpxdesc); + } + if (oldattr) free(oldattr); + oldattr = attr; + } +} + +static BOOL same_posix(struct POSIX_SECURITY *pxdesc1, + struct POSIX_SECURITY *pxdesc2) +{ + BOOL same; + int i; + + same = pxdesc1 + && pxdesc2 + && (pxdesc1->mode == pxdesc2->mode) + && (pxdesc1->acccnt == pxdesc2->acccnt) + && (pxdesc1->defcnt == pxdesc2->defcnt) + && (pxdesc1->firstdef == pxdesc2->firstdef) + && (pxdesc1->tagsset == pxdesc2->tagsset) + && (pxdesc1->acl.version == pxdesc2->acl.version) + && (pxdesc1->acl.flags == pxdesc2->acl.flags); + i = 0; + while (same && (i < pxdesc1->acccnt)) { + same = (pxdesc1->acl.ace[i].tag == pxdesc2->acl.ace[i].tag) + && (pxdesc1->acl.ace[i].perms == pxdesc2->acl.ace[i].perms) + && (pxdesc1->acl.ace[i].id == pxdesc2->acl.ace[i].id); + i++; + } + i = pxdesc1->firstdef; + while (same && (i < pxdesc1->firstdef + pxdesc1->defcnt)) { + same = (pxdesc1->acl.ace[i].tag == pxdesc2->acl.ace[i].tag) + && (pxdesc1->acl.ace[i].perms == pxdesc2->acl.ace[i].perms) + && (pxdesc1->acl.ace[i].id == pxdesc2->acl.ace[i].id); + i++; + } + return (same); +} + +#endif /* POSIXACLS & SELFTESTS & !USESTUBS */ + +#if SELFTESTS & !USESTUBS + +/* + * Build a dummy security descriptor + * returns descriptor in allocated memory, must free() after use + */ + +static char *build_dummy_descr(BOOL isdir __attribute__((unused)), + const SID *usid, const SID *gsid, + int cnt, + /* seq of int allow, SID *sid, int flags, u32 mask */ + ...) +{ + char *attr; + int attrsz; + SECURITY_DESCRIPTOR_RELATIVE *pnhead; + ACL *pacl; + ACCESS_ALLOWED_ACE *pace; + va_list ap; + const SID *sid; + u32 umask; + le32 mask; + int flags; + BOOL allow; + int pos; + int usidsz; + int gsidsz; + int sidsz; + int aclsz; + int i; + + if (usid) + usidsz = ntfs_sid_size(usid); + else + usidsz = 0; + if (gsid) + gsidsz = ntfs_sid_size(gsid); + else + gsidsz = 0; + + + /* allocate enough space for the new security attribute */ + attrsz = sizeof(SECURITY_DESCRIPTOR_RELATIVE) /* header */ + + usidsz + gsidsz /* usid and gsid */ + + sizeof(ACL) /* acl header */ + + cnt*40; + + attr = (char*)ntfs_malloc(attrsz); + if (attr) { + /* build the main header part */ + pnhead = (SECURITY_DESCRIPTOR_RELATIVE*) attr; + pnhead->revision = SECURITY_DESCRIPTOR_REVISION; + pnhead->alignment = 0; + /* + * The flag SE_DACL_PROTECTED prevents the ACL + * to be changed in an inheritance after creation + */ + pnhead->control = SE_DACL_PRESENT | SE_DACL_PROTECTED + | SE_SELF_RELATIVE; + /* + * Windows prefers ACL first, do the same to + * get the same hash value and avoid duplication + */ + /* build the ACL header */ + pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + pacl = (ACL*)&attr[pos]; + pacl->revision = ACL_REVISION; + pacl->alignment1 = 0; + pacl->size = cpu_to_le16(0); /* fixed later */ + pacl->ace_count = cpu_to_le16(cnt); + pacl->alignment2 = cpu_to_le16(0); + + /* enter the ACEs */ + + pos += sizeof(ACL); + aclsz = sizeof(ACL); + va_start(ap,cnt); + for (i=0; itype = (allow ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE); + pace->flags = flags; + pace->size = cpu_to_le16(sidsz + 8); + pace->mask = mask; + memcpy(&pace->sid,sid,sidsz); + aclsz += sidsz + 8; + pos += sidsz + 8; + } + va_end(ap); + + /* append usid and gsid if defined */ + /* positions of ACL, USID and GSID into header */ + pnhead->owner = cpu_to_le32(0); + pnhead->group = cpu_to_le32(0); + if (usid) { + memcpy(&attr[pos], usid, usidsz); + pnhead->owner = cpu_to_le32(pos); + } + if (gsid) { + memcpy(&attr[pos + usidsz], gsid, gsidsz); + pnhead->group = cpu_to_le32(pos + usidsz); + } + /* positions of DACL and SACL into header */ + pnhead->sacl = cpu_to_le32(0); + if (cnt) { + pacl->size = cpu_to_le16(aclsz); + pnhead->dacl = + cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)); + } else + pnhead->dacl = cpu_to_le32(0); + if (!ntfs_valid_descr(attr,pos+usidsz+gsidsz)) { + printf("** Bad sample descriptor\n"); + free(attr); + attr = (char*)NULL; + errors++; + } + } else + errno = ENOMEM; + return (attr); +} + +/* + * Check a few samples with special conditions + */ + +void check_samples() +{ + char *descr = (char*)NULL; + BOOL isdir = FALSE; + mode_t perms; + mode_t expect = 0; + int cnt; + u32 expectacc; + u32 expectdef; +#if POSIXACLS + u32 accrights; + u32 defrights; + mode_t mixmode; + struct POSIX_SECURITY *pxdesc; + struct POSIX_SECURITY *pxsample; + const char *txsample; +#endif + le32 owner1[] = /* S-1-5-21-1833069642-4243175381-1340018762-1003 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(1833069642), cpu_to_le32(4243175381), + cpu_to_le32(1340018762), cpu_to_le32(1003) + } ; + le32 group1[] = /* S-1-5-21-1833069642-4243175381-1340018762-513 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(1833069642), cpu_to_le32(4243175381), + cpu_to_le32(1340018762), cpu_to_le32(513) + } ; + le32 group2[] = /* S-1-5-21-1607551490-981732888-1819828000-513 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(1607551490), cpu_to_le32(981732888), + cpu_to_le32(1819828000), cpu_to_le32(513) + } ; + le32 owner3[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(1016) + } ; + le32 group3[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(513) + } ; + +#if POSIXACLS + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[4]; + } sampletry1 = + { + { 0645, 4, 0, 4, 0x35, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 6, -1 }, + { 4, 5, -1 }, + { 16, 4, -1 }, + { 32, 5, -1 } + } + } ; + + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[6]; + } sampletry3 = + { + { 0100, 6, 0, 6, 0x3f, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 1, -1 }, + { 2, 3, 1000 }, + { 4, 1, -1 }, + { 8, 3, 1002 }, + { 16, 0, -1 }, + { 32, 0, -1 } + } + } ; + + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[8]; + } sampletry4 = + { + { 0140, 8, 0, 8, 0x3f, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 1, -1 }, + { 2, 3, 516 }, + { 2, 6, 1000 }, + { 4, 1, -1 }, + { 8, 6, 500 }, + { 8, 3, 1002 }, + { 16, 4, -1 }, + { 32, 0, -1 } + } + } ; + + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[6]; + } sampletry5 = + { + { 0454, 6, 0, 6, 0x3f, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 4, -1 }, + { 2, 5, 516 }, + { 4, 4, -1 }, + { 8, 6, 500 }, + { 16, 5, -1 }, + { 32, 4, -1 } + } + } ; + + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[8]; + } sampletry6 = + { + { 0332, 8, 0, 8, 0x3f, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 3, -1 }, + { 2, 1, 0 }, + { 2, 2, 1000 }, + { 4, 6, -1 }, + { 8, 4, 0 }, + { 8, 5, 1002 }, + { 16, 3, -1 }, + { 32, 2, -1 } + } + } ; + + struct { + struct POSIX_SECURITY head; + struct POSIX_ACE ace[4]; + } sampletry8 = + { + { 0677, 4, 0, 4, 0x35, + { POSIX_VERSION, 0, 0 } + }, + { + { 1, 6, -1 }, + { 4, 7, -1 }, + { 16, 7, -1 }, + { 32, 7, -1 } + } + } ; + +#endif /* POSIXACLS */ + + +#if POSIXACLS + for (cnt=1; cnt<=8; cnt++) { + switch (cnt) { + case 1 : + pxsample = &sampletry1.head; + txsample = "sampletry1-a"; + isdir = FALSE; + descr = ntfs_build_descr_posix(context.mapping,&sampletry1.head, + isdir, (const SID*)owner3, (const SID*)group3); + break; + case 2 : + pxsample = &sampletry1.head; + txsample = "sampletry1-b"; + isdir = FALSE; + descr = ntfs_build_descr_posix(context.mapping,&sampletry1.head, + isdir, (const SID*)adminsid, (const SID*)group3); + break; + case 3 : + isdir = FALSE; + pxsample = &sampletry3.head; + txsample = "sampletry3"; + descr = ntfs_build_descr_posix(context.mapping,pxsample, + isdir, (const SID*)group3, (const SID*)group3); + break; + case 4 : + isdir = FALSE; + pxsample = &sampletry4.head; + txsample = "sampletry4"; + descr = ntfs_build_descr_posix(context.mapping,pxsample, + isdir, (const SID*)owner3, (const SID*)group3); + break; + case 5 : + isdir = FALSE; + pxsample = &sampletry5.head; + txsample = "sampletry5"; + descr = ntfs_build_descr_posix(context.mapping,pxsample, + isdir, (const SID*)owner3, (const SID*)group3); + break; + case 6 : + isdir = FALSE; + pxsample = &sampletry6.head; + txsample = "sampletry6-a"; + descr = ntfs_build_descr_posix(context.mapping,pxsample, + isdir, (const SID*)owner3, (const SID*)group3); + break; + case 7 : + isdir = FALSE; + pxsample = &sampletry6.head; + txsample = "sampletry6-b"; + descr = ntfs_build_descr_posix(context.mapping,pxsample, + isdir, (const SID*)adminsid, (const SID*)adminsid); + break; + case 8 : + pxsample = &sampletry8.head; + txsample = "sampletry8"; + isdir = FALSE; + descr = ntfs_build_descr_posix(context.mapping,&sampletry8.head, + isdir, (const SID*)owner3, (const SID*)group3); + break; + default : + pxsample = (struct POSIX_SECURITY*)NULL; + txsample = (const char*)NULL; + } + /* check we get original back */ + if (descr) + pxdesc = linux_permissions_posix(descr, isdir); + else + pxdesc = (struct POSIX_SECURITY*)NULL; + if (!descr || !pxdesc || !same_posix(pxsample,pxdesc)) { + printf("** Error in %s\n",txsample); + showposix(pxsample); + showall(descr,0); + showposix(pxdesc); + errors++; + } + free(descr); + free(pxdesc); + } + +#endif /* POSIXACLS */ + + + /* + * Check a few samples built by Windows, + * which cannot be generated by Linux + */ + + for (cnt=1; cnt<=8; cnt++) { + switch(cnt) { + case 1 : /* hp/tmp */ + isdir = TRUE; + descr = build_dummy_descr(isdir, + (const SID*)owner1, (const SID*)group1, + 1, + (int)TRUE, worldsid, (int)0x3, (u32)0x1f01ff); + expectacc = expect = 0777; + expectdef = 0; + break; + case 2 : /* swsetup */ + isdir = TRUE; + descr = build_dummy_descr(isdir, adminsid, (const SID*)group2, + 2, + (int)TRUE, worldsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, worldsid, (int)0xb, (u32)0x1f01ff); + expectacc = expect = 0777; + expectdef = 0777; + break; + case 3 : /* Dr Watson */ + isdir = TRUE; + descr = build_dummy_descr(isdir, (const SID*)owner3, (const SID*)group3, + 0); + expectacc = expect = 0700; + expectdef = 0; + break; + case 4 : + isdir = FALSE; + descr = build_dummy_descr(isdir, + (const SID*)owner3, (const SID*)group3, + 4, + (int)TRUE, (const SID*)owner3, 0, + le32_to_cpu(FILE_READ_DATA | OWNER_RIGHTS), + (int)TRUE, (const SID*)group3, 0, + le32_to_cpu(FILE_WRITE_DATA), + (int)TRUE, (const SID*)group2, 0, + le32_to_cpu(FILE_WRITE_DATA | FILE_READ_DATA), + (int)TRUE, (const SID*)worldsid, 0, + le32_to_cpu(FILE_EXECUTE)); + expect = 0731; + expectacc = 07070731; + expectdef = 0; + break; + case 5 : /* Vista/JP */ + isdir = TRUE; + descr = build_dummy_descr(isdir, systemsid, systemsid, + 6, + (int)TRUE, owner1, (int)0x0, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, owner1, (int)0xb, (u32)0x10000000, + (int)TRUE, systemsid, (int)0xb, (u32)0x10000000, + (int)TRUE, adminsid, (int)0xb, (u32)0x10000000); + expectacc = expect = 0700; + expectdef = 0700; + break; + case 6 : /* Vista/JP2 */ + isdir = TRUE; + descr = build_dummy_descr(isdir, systemsid, systemsid, + 7, + (int)TRUE, owner1, (int)0x0, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, owner1, (int)0xb, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0xb, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0xb, (u32)0x1f01ff, + (int)TRUE, owner3, (int)0x3, (u32)0x1200a9); + expectacc = 0500070700; + expectdef = 0700; + expect = 0700; + break; + case 7 : /* WinXP/JP */ + isdir = TRUE; + descr = build_dummy_descr(isdir, adminsid, systemsid, + 6, + (int)TRUE, owner1, (int)0x0, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, owner1, (int)0xb, (u32)0x10000000, + (int)TRUE, systemsid, (int)0xb, (u32)0x10000000, + (int)TRUE, adminsid, (int)0xb, (u32)0x10000000); + expectacc = expect = 0700; + expectdef = 0700; + break; + case 8 : /* WinXP/JP2 */ + isdir = TRUE; + descr = build_dummy_descr(isdir, adminsid, systemsid, + 6, + (int)TRUE, owner1, (int)0x0, (u32)0x1f01ff, + (int)TRUE, systemsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, adminsid, (int)0x0, (u32)0x1f01ff, + (int)TRUE, owner1, (int)0xb, (u32)0x10000000, + (int)TRUE, systemsid, (int)0xb, (u32)0x10000000, + (int)TRUE, adminsid, (int)0xb, (u32)0x10000000); + expectacc = expect = 0700; + expectdef = 0700; + break; + default : + expectacc = expectdef = 0; + break; + } + if (descr) { + perms = linux_permissions(descr, isdir); + if (perms != expect) { + printf("** Error in sample %d, perms 0%03o expected 0%03o\n", + cnt,perms,expect); + showall(descr,0); + errors++; + } else { +#if POSIXACLS + pxdesc = linux_permissions_posix(descr, isdir); + if (pxdesc) { + accrights = merge_rights(pxdesc,FALSE); + defrights = merge_rights(pxdesc,TRUE); + if (!(pxdesc->tagsset & ~(POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER))) + mixmode = expect; + else + mixmode = (expect & 07707) | ((accrights >> 9) & 070); + if ((pxdesc->mode != mixmode) + || (accrights != expectacc) + || (defrights != expectdef)) { + printf("** Error in sample %d : mode %03o expected 0%03o\n", + cnt,pxdesc->mode,mixmode); + printf(" Posix access rights 0%03lo expected 0%03lo\n", + (long)accrights,(long)expectacc); + printf(" default rights 0%03lo expected 0%03lo\n", + (long)defrights,(long)expectdef); + showall(descr,0); + showposix(pxdesc); +exit(1); + } + free(pxdesc); + } +#endif + } + free(descr); + } + } +} + + +/* + * Check whether any basic permission setting is interpreted + * back exactly as set + */ + +void basictest(int kind, BOOL isdir, const SID *owner, const SID *group) +{ + char *attr; + mode_t perm; + mode_t gotback; + u32 count; + u32 acecount; + u32 globhash; + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + enum { ERRNO, + ERRMA, ERRPA, /* error converting mode or Posix ACL to NTFS */ + ERRAM, ERRAP, /* error converting NTFS to mode or Posix ACL */ + } err; + u32 expectcnt[] = { + 27800, 31896, + 24064, 28160, + 24064, 28160, + 24064, 28160, + 25416, 29512 + } ; + u32 expecthash[] = { + 0x8f80865b, 0x7bc7960, + 0x8fd9ecfe, 0xddd4db0, + 0xa8b07400, 0xa189c20, + 0xc5689a00, 0xb6c09000, + 0x94bfb419, 0xa4311791 + } ; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; + char *pxattr; + u32 pxcount; + u32 pxacecount; + u32 pxglobhash; +#endif + + count = 0; + acecount = 0; + globhash = 0; +#if POSIXACLS + pxcount = 0; + pxacecount = 0; + pxglobhash = 0; +#endif + for (perm=0; (perm<=07777) && (errors < 10); perm++) { + err = ERRNO; + /* file owned by plain user and group */ + attr = ntfs_build_descr(perm,isdir,owner,(const SID*)group); + if (attr && ntfs_valid_descr(attr, ntfs_attr_size(attr))) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + pacl = (const ACL*)&attr[le32_to_cpu(phead->dacl)]; + acecount += le16_to_cpu(pacl->ace_count); + globhash += hash((const le32*)attr,ntfs_attr_size(attr)); + count++; +#if POSIXACLS + /* + * Build a NTFS ACL from a mode, and + * decode to a Posix ACL, expecting to + * get the original mode back. + */ + pxdesc = linux_permissions_posix(attr, isdir); + if (!pxdesc || (pxdesc->mode != perm)) { + err = ERRAP; + if (pxdesc) + gotback = pxdesc->mode; + else + gotback = 0; + } else { + /* + * Build a NTFS ACL from the Posix ACL, expecting to + * get exactly the same NTFS ACL, then decode to a + * mode, expecting to get the original mode back. + */ + pxattr = ntfs_build_descr_posix(context.mapping, + pxdesc,isdir,owner, + (const SID*)group); + if (pxattr && !memcmp(pxattr,attr, + ntfs_attr_size(attr))) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + pacl = (const ACL*)&attr[le32_to_cpu(phead->dacl)]; + pxacecount += le16_to_cpu(pacl->ace_count); + pxglobhash += hash((const le32*)attr,ntfs_attr_size(attr)); + pxcount++; + gotback = linux_permissions(pxattr, isdir); + if (gotback != perm) + err = ERRAM; + else + free(pxattr); + } else + err = ERRPA; + free(attr); + } + free(pxdesc); +#else + gotback = linux_permissions(attr, isdir); + if (gotback != perm) + err = ERRAM; + else + free(attr); +#endif /* POSIXACLS */ + } else + err = ERRMA; + + switch (err) { + case ERRMA : + printf("** no or wrong permission settings " + "for kind %d perm %03o\n",kind,perm); + if (attr && opt_v) + hexdump(attr,ntfs_attr_size(attr),8); + if (attr && (opt_v >= 2)) { + showheader(attr,4); + showusid(attr,4); + showgsid(attr,4); + showdacl(attr,isdir,4); + showsacl(attr,isdir,4); + } + errors++; + break; + case ERRPA : + printf("** no or wrong permission settings from PX " + "for kind %d perm %03o\n",kind,perm); + errors++; + break; +#if POSIXACLS + case ERRAM : + printf("** wrong permission settings, " + "kind %d perm 0%03o, gotback %03o\n", + kind, perm, gotback); + if (opt_v) + hexdump(pxattr,ntfs_attr_size(pxattr),8); + if (opt_v >= 2) { + showheader(pxattr,4); + showusid(pxattr,4); + showgsid(pxattr,4); + showdacl(pxattr,isdir,4); + showsacl(pxattr,isdir,4); + } + errors++; + break; + case ERRAP : + /* continued */ +#else + case ERRAM : + case ERRAP : +#endif /* POSIXACLS */ + printf("** wrong permission settings, " + "kind %d perm 0%03o, gotback %03o\n", + kind, perm, gotback); + if (opt_v) + hexdump(attr,ntfs_attr_size(attr),8); + if (opt_v >= 2) { + showheader(attr,4); + showusid(attr,4); + showgsid(attr,4); + showdacl(attr,isdir,4); + showsacl(attr,isdir,4); + } + errors++; + free(attr); + break; + default : + break; + } + } + printf("%lu ACLs built from mode, %lu ACE built, mean count %lu.%02lu\n", + (unsigned long)count,(unsigned long)acecount, + (unsigned long)acecount/count,acecount*100L/count%100L); + if (acecount != expectcnt[kind]) { + printf("** Error : expected ACE count %lu\n", + (unsigned long)expectcnt[kind]); + errors++; + } + if (globhash != expecthash[kind]) { + printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n", + (unsigned long)globhash, (unsigned long)expecthash[kind]); + errors++; + } +#if POSIXACLS + printf("%lu ACLs built from Posix ACLs, %lu ACE built, mean count %lu.%02lu\n", + (unsigned long)pxcount,(unsigned long)pxacecount, + (unsigned long)pxacecount/pxcount,pxacecount*100L/pxcount%100L); + if (pxacecount != expectcnt[kind]) { + printf("** Error : expected ACE count %lu\n", + (unsigned long)expectcnt[kind]); + errors++; + } + if (pxglobhash != expecthash[kind]) { + printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n", + (unsigned long)pxglobhash, (unsigned long)expecthash[kind]); + errors++; + } +#endif /* POSIXACLS */ +} + +#if POSIXACLS + +/* + * Check whether Posix ACL settings are interpreted + * back exactly as set + */ + +void posixtest(int kind, BOOL isdir, + const SID *owner, const SID *group) +{ + struct POSIX_SECURITY *pxdesc; + struct { + struct POSIX_SECURITY pxdesc; + struct POSIX_ACE aces[10]; + } desc; + int ownobj; + int grpobj; + int usr; + int grp; + int wrld; + int mask; + int mindes, maxdes; + int minmsk, maxmsk; + char *pxattr; + u32 count; + u32 acecount; + u32 globhash; + const SECURITY_DESCRIPTOR_RELATIVE *phead; + const ACL *pacl; + struct POSIX_SECURITY *gotback; + enum { ERRNO, + ERRMA, ERRPA, /* error converting mode or Posix ACL to NTFS */ + ERRAM, ERRAP, /* error converting NTFS to mode or Posix ACL */ + } err; + u32 expectcnt[] = { +#ifdef STSC + 32400, 34992, + 25920, 28512, + 25920, 28512, + 25920, 28512, + 26460, 29052, + 0, 0, + 0, 0, + 0, 0, + 24516, 27108, + 20736, 23328, + 20736, 23328, + 20736, 23328, + 21060, 23652, +#else + 252720, 273456, + 199584, 220320, + 199584, 220320, + 199584, 220320, + 203904, 224640, + 0, 0, + 0, 0, + 0, 0, + 196452, 217188, + 165888, 186624, + 165888, 186624, + 165888, 186624, + 168480, 189216, +#endif + 0, 0, + 0, 0, + 0, 0, + 16368, 18672, + 0, 0, + 13824, 0, + 0, 0, + 14640, 0 + } ; + u32 expecthash[] = { +#ifdef STSC + 0xf9f82115, 0x40666647, + 0xde826d30, 0xa181b660, + 0x952d4500, 0x8ac49450, + 0xf80acee0, 0xbd9ec6c0, + 0xfe09b868, 0xde24e84d, + 0, 0, + 0, 0, + 0, 0, + 0x2381438d, 0x3ab42dc6, + 0x7cccf6f8, 0x108ad430, + 0x5e448840, 0x83ab6c40, + 0x9b037100, 0x8f7c3b40, + 0x04a359dc, 0xa4619609, +#else + 0x1808a6cd, 0xd82f7c60, + 0x5ad29e85, 0x518c7620, + 0x188ce270, 0x7e44e590, + 0x48a64800, 0x5bdf0030, + 0x1c64aec6, 0x8b0168fa, + 0, 0, + 0, 0, + 0, 0, + 0x169fb80e, 0x382d9a59, + 0xf9c28164, 0x1855d352, + 0xf9685700, 0x44d16700, + 0x587ebe90, 0xf7c51480, + 0x2cb1b518, 0x52408df6, +#endif + 0, 0, + 0, 0, + 0, 0, + 0x905f2e38, 0xd40c22f0, + 0, 0, + 0xdd76da00, 0, + 0, 0, + 0x718e34a0, 0 + }; + + count = 0; + acecount = 0; + globhash = 0; + /* fill headers */ + pxdesc = &desc.pxdesc; + pxdesc->mode = 0; + pxdesc->defcnt = 0; + if (kind & 32) { + pxdesc->acccnt = 4; + pxdesc->firstdef = 4; + pxdesc->tagsset = 0x35; + } else { + pxdesc->acccnt = 6;; + pxdesc->firstdef = 6; + pxdesc->tagsset = 0x3f; + } + pxdesc->acl.version = POSIX_VERSION; + pxdesc->acl.flags = 0; + pxdesc->acl.filler = 0; + /* prefill aces */ + pxdesc->acl.ace[0].tag = POSIX_ACL_USER_OBJ; + pxdesc->acl.ace[0].id = -1; + if (kind & 32) { + pxdesc->acl.ace[1].tag = POSIX_ACL_GROUP_OBJ; + pxdesc->acl.ace[1].id = -1; + pxdesc->acl.ace[2].tag = POSIX_ACL_MASK; + pxdesc->acl.ace[2].id = -1; + pxdesc->acl.ace[3].tag = POSIX_ACL_OTHER; + pxdesc->acl.ace[3].id = -1; + } else { + pxdesc->acl.ace[1].tag = POSIX_ACL_USER; + pxdesc->acl.ace[1].id = (kind & 16 ? 0 : 1000); + pxdesc->acl.ace[2].tag = POSIX_ACL_GROUP_OBJ; + pxdesc->acl.ace[2].id = -1; + pxdesc->acl.ace[3].tag = POSIX_ACL_GROUP; + pxdesc->acl.ace[3].id = (kind & 16 ? 0 : 1002); + pxdesc->acl.ace[4].tag = POSIX_ACL_MASK; + pxdesc->acl.ace[4].id = -1; + pxdesc->acl.ace[5].tag = POSIX_ACL_OTHER; + pxdesc->acl.ace[5].id = -1; + } + + mindes = 3; + maxdes = (kind & 32 ? mindes : 6); +#ifdef STSC + minmsk = (kind & 32 ? 0 : 3); + maxmsk = (kind & 32 ? 7 : 3); +#else + minmsk = 0; + maxmsk = 7; +#endif + for (mask=minmsk; mask<=maxmsk; mask++) + for (ownobj=1; ownobj<7; ownobj++) + for (grpobj=1; grpobj<7; grpobj++) + for (wrld=0; wrld<8; wrld++) + for (usr=mindes; usr<=maxdes; usr++) + if (usr != 4) + for (grp=mindes; grp<=maxdes; grp++) + if (grp != 4) { + pxdesc->mode = (ownobj << 6) | (mask << 3) | wrld; + + pxdesc->acl.ace[0].perms = ownobj; + if (kind & 32) { + pxdesc->acl.ace[1].perms = grpobj; + pxdesc->acl.ace[2].perms = mask; + pxdesc->acl.ace[3].perms = wrld; + } else { + pxdesc->acl.ace[1].perms = usr; + pxdesc->acl.ace[2].perms = grpobj; + pxdesc->acl.ace[3].perms = grp; + pxdesc->acl.ace[4].perms = mask; + pxdesc->acl.ace[5].perms = wrld; + } + + err = ERRNO; + gotback = (struct POSIX_SECURITY*)NULL; + pxattr = ntfs_build_descr_posix(context.mapping, + pxdesc,isdir,owner,group); + if (pxattr && ntfs_valid_descr(pxattr, ntfs_attr_size(pxattr))) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)pxattr; + pacl = (const ACL*)&pxattr[le32_to_cpu(phead->dacl)]; + acecount += le16_to_cpu(pacl->ace_count); + globhash += hash((const le32*)pxattr,ntfs_attr_size(pxattr)); + count++; + gotback = linux_permissions_posix(pxattr, isdir); + if (gotback) { + if (ntfs_valid_posix(gotback)) { + if (!same_posix(pxdesc,gotback)) { + printf("Non matching got back Posix ACL\n"); + printf("input ACL\n"); + showposix(pxdesc); + printf("NTFS owner\n"); + showusid(pxattr,4); + printf("NTFS group\n"); + showgsid(pxattr,4); + printf("NTFS DACL\n"); + showdacl(pxattr,isdir,4); + printf("gotback ACL\n"); + showposix(gotback); + errors++; +exit(1); + } + } else { + printf("Got back an invalid Posix ACL\n"); + errors++; + } + free(gotback); + } else { + printf("Could not get Posix ACL back\n"); + errors++; + } + + } else { + printf("NTFS ACL incorrect or not build\n"); + printf("input ACL\n"); + showposix(pxdesc); + printf("NTFS DACL\n"); + if (pxattr) + showdacl(pxattr,isdir,4); + else + printf(" (none)\n"); + if (gotback) { + printf("gotback ACL\n"); + showposix(gotback); + } else + printf("no gotback ACL\n"); + errors++; + } + if (pxattr) + free(pxattr); + } + printf("%lu ACLs built from Posix ACLs, %lu ACE built, mean count %lu.%02lu\n", + (unsigned long)count,(unsigned long)acecount, + (unsigned long)acecount/count,acecount*100L/count%100L); + if (acecount != expectcnt[kind]) { + printf("** Error ! expected ACE count %lu\n", + (unsigned long)expectcnt[kind]); + errors++; + } + if (globhash != expecthash[kind]) { + printf("** Error : wrong global hash 0x%lx instead of 0x%lx\n", + (unsigned long)globhash, (unsigned long)expecthash[kind]); + errors++; + } +} + +#endif /* POSIXACLS */ + +void selftests(void) +{ + le32 owner_sid[] = /* S-1-5-21-3141592653-589793238-462843383-1016 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(1016) + } ; + le32 group_sid[] = /* S-1-5-21-3141592653-589793238-462843383-513 */ + { + cpu_to_le32(0x501), cpu_to_le32(0x05000000), cpu_to_le32(21), + cpu_to_le32(AUTH1), cpu_to_le32(AUTH2), + cpu_to_le32(AUTH3), cpu_to_le32(513) + } ; +#ifdef STSC + unsigned char kindlist[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 16, 17, 18, 20, 22, 24, + 32, 33, 36, 40 } ; +#else + unsigned char kindlist[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 16, 17, 18, 20, 22, 24, 19, 21, 23, 25, + 32, 33, 36, 40 } ; +#endif + unsigned int k; + int kind; + const SID *owner; + const SID *group; + BOOL isdir; + +#if POSIXACLS + local_build_mapping(context.mapping, (const char*)NULL); +#endif + /* first check samples */ + mappingtype = MAPDUMMY; + check_samples(); +if (errors) exit(1); + /* + * kind is oring of : + * 1 : directory + * 2 : owner is root + * 4 : group is root + * 8 : group is owner + * 16 : root is designated user/group + * 32 : mask present with no designated user/group + */ + for (kind=0; (kind<10) && (errors<10); kind++) { + isdir = kind & 1; + if (kind & 8) + owner = (const SID*)group_sid; + else + owner = (kind & 2 ? adminsid : (const SID*)owner_sid); + group = (kind & 4 ? adminsid : (const SID*)group_sid); + basictest(kind, isdir, owner, group); + } +#if POSIXACLS + for (k=0; (k= 10) + printf("** too many errors, test aborted\n"); +} +#endif /* SELFTESTS & !USESTUBS */ + +#ifdef WIN32 + +/* + * Get the security descriptor of a file (Windows version) + */ + +unsigned int getfull(char *attr, const char *fullname) +{ + static char part[MAXATTRSZ]; + BIGSID ownsid; + int xowner; + int ownersz; + u16 ownerfl; + ULONG attrsz; + ULONG partsz; + BOOL overflow; + + attrsz = 0; + partsz = 0; + overflow = FALSE; + if (GetFileSecurityW((LPCWSTR)fullname,OWNER_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + xowner = get4l(part,4); + if (xowner) { + ownerfl = get2l(part,2); + ownersz = ntfs_sid_size((SID*)&part[xowner]); + if (ownersz <= (int)sizeof(BIGSID)) + memcpy(ownsid,&part[xowner],ownersz); + else + overflow = TRUE; + } else { + ownerfl = 0; + ownersz = 0; + } + /* + * SACL : just feed in or clean + */ + if (!GetFileSecurityW((LPCWSTR)fullname,SACL_SECURITY_INFORMATION, + (char*)attr,MAXATTRSZ,&attrsz)) { + attrsz = 20; + set4l(attr,0); + attr[0] = SECURITY_DESCRIPTOR_REVISION; + set4l(&attr[12],0); + if (opt_v >= 2) + printf(" No SACL\n"); + } + /* + * append DACL and merge its flags + */ + partsz = 0; + set4l(&attr[16],0); + if (GetFileSecurityW((LPCWSTR)fullname,DACL_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + if ((attrsz + partsz - 20) <= MAXATTRSZ) { + memcpy(&attr[attrsz],&part[20],partsz-20); + set4l(&attr[16],(partsz > 20 ? attrsz : 0)); + set2l(&attr[2],get2l(attr,2) | (get2l(part,2) + & const_le16_to_cpu(SE_DACL_PROTECTED + | SE_DACL_AUTO_INHERITED + | SE_DACL_PRESENT))); + attrsz += partsz - 20; + } else + overflow = TRUE; + } else + if (partsz > MAXATTRSZ) + overflow = TRUE; + else { + if (opt_b) + printf("# No discretionary access control list\n"); + else + printf(" No discretionary access control list\n"); + warnings++; + } + + /* + * append owner and merge its flag + */ + if (xowner && !overflow) { + memcpy(&attr[attrsz],ownsid,ownersz); + set4l(&attr[4],attrsz); + set2l(&attr[2],get2l(attr,2) + | (ownerfl & const_le16_to_cpu(SE_OWNER_DEFAULTED))); + attrsz += ownersz; + } else + set4l(&attr[4],0); + /* + * append group + */ + partsz = 0; + set4l(&attr[8],0); + if (GetFileSecurityW((LPCWSTR)fullname,GROUP_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + if ((attrsz + partsz - 20) <= MAXATTRSZ) { + memcpy(&attr[attrsz],&part[20],partsz-20); + set4l(&attr[8],(partsz > 20 ? attrsz : 0)); + set2l(&attr[2],get2l(attr,2) | (get2l(part,2) + & const_le16_to_cpu(SE_GROUP_DEFAULTED))); + attrsz += partsz - 20; + } else + overflow = TRUE; + } else + if (partsz > MAXATTRSZ) + overflow = TRUE; + else { + printf("** No group SID\n"); + warnings++; + } + set2l(&attr[2],get2l(attr,2) + | const_le16_to_cpu(SE_SELF_RELATIVE)); + if (overflow) { + printf("** Descriptor was too long (> %d)\n",MAXATTRSZ); + warnings++; + attrsz = 0; + } else + if (!ntfs_valid_descr((char*)attr,attrsz)) { + printf("** Descriptor for "); + printname(stdout,fullname); + printf(" is not valid\n"); + errors++; + attrsz = 0; + } + + } else { + printf("** Could not get owner of "); + printname(stdout,fullname); + printf(", partsz %d\n",partsz); + printerror(stdout); + warnings++; + attrsz = 0; + } + return (attrsz); +} + +/* + * Update a security descriptor (Windows version) + */ + +BOOL updatefull(const char *name, DWORD flags, char *attr) +{ + BOOL bad; + + bad = !SetFileSecurityW((LPCWSTR)name, flags, attr); + if (bad + && (flags & OWNER_SECURITY_INFORMATION) + && (GetLastError() == 1307)) { + printf("** Could not set owner of "); + printname(stdout,name); + printf(", retrying with no owner setting\n"); + warnings++; + bad = !SetFileSecurityW((LPCWSTR)name, + flags & ~OWNER_SECURITY_INFORMATION, (char*)attr); + } + if (bad) { + printf("** Could not change attributes of "); + printname(stdout,name); + printf("\n"); + printerror(stdout); + errors++; + } + return (!bad); +} + +#else + +/* + * Get the security descriptor of a file (Linux version) + */ + +unsigned int getfull(char *attr, const char *fullname) +{ + static char part[MAXATTRSZ]; + BIGSID ownsid; + int xowner; + int ownersz; + u16 ownerfl; + u32 attrsz; + u32 partsz; + BOOL overflow; + + attrsz = 0; + partsz = 0; + overflow = FALSE; + if (ntfs_get_file_security(ntfs_context,fullname, + OWNER_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + xowner = get4l(part,4); + if (xowner) { + ownerfl = get2l(part,2); + ownersz = ntfs_sid_size((SID*)&part[xowner]); + if (ownersz <= (int)sizeof(BIGSID)) + memcpy(ownsid,&part[xowner],ownersz); + else + overflow = TRUE; + } else { + ownerfl = 0; + ownersz = 0; + } + /* + * SACL : just feed in or clean + */ + if (!ntfs_get_file_security(ntfs_context,fullname, + SACL_SECURITY_INFORMATION, + (char*)attr,MAXATTRSZ,&attrsz)) { + attrsz = 20; + set4l(attr,0); + attr[0] = SECURITY_DESCRIPTOR_REVISION; + set4l(&attr[12],0); + if (opt_v >= 2) + printf(" No SACL\n"); + } + /* + * append DACL and merge its flags + */ + partsz = 0; + set4l(&attr[16],0); + if (ntfs_get_file_security(ntfs_context,fullname, + DACL_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + if ((attrsz + partsz - 20) <= MAXATTRSZ) { + memcpy(&attr[attrsz],&part[20],partsz-20); + set4l(&attr[16],(partsz > 20 ? attrsz : 0)); + set2l(&attr[2],get2l(attr,2) | (get2l(part,2) + & const_le16_to_cpu(SE_DACL_PROTECTED + | SE_DACL_AUTO_INHERITED + | SE_DACL_PRESENT))); + attrsz += partsz - 20; + } else + overflow = TRUE; + } else + if (partsz > MAXATTRSZ) + overflow = TRUE; + else { + if (opt_b) + printf("# No discretionary access control list\n"); + else + printf(" No discretionary access control list\n"); + warnings++; + } + + /* + * append owner and merge its flag + */ + if (xowner && !overflow) { + memcpy(&attr[attrsz],ownsid,ownersz); + set4l(&attr[4],attrsz); + set2l(&attr[2],get2l(attr,2) + | (ownerfl & const_le16_to_cpu(SE_OWNER_DEFAULTED))); + attrsz += ownersz; + } else + set4l(&attr[4],0); + /* + * append group + */ + partsz = 0; + set4l(&attr[8],0); + if (ntfs_get_file_security(ntfs_context,fullname, + GROUP_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz)) { + if ((attrsz + partsz - 20) <= MAXATTRSZ) { + memcpy(&attr[attrsz],&part[20],partsz-20); + set4l(&attr[8],(partsz > 20 ? attrsz : 0)); + set2l(&attr[2],get2l(attr,2) | (get2l(part,2) + & const_le16_to_cpu(SE_GROUP_DEFAULTED))); + attrsz += partsz - 20; + } else + overflow = TRUE; + } else + if (partsz > MAXATTRSZ) + overflow = TRUE; + else { + printf("** No group SID\n"); + warnings++; + } + if (overflow) { + printf("** Descriptor was too long (> %d)\n",MAXATTRSZ); + warnings++; + attrsz = 0; + } else + if (!ntfs_valid_descr((char*)attr,attrsz)) { + printf("** Descriptor for %s is not valid\n",fullname); + errors++; + attrsz = 0; + } + + } else { + printf("** Could not get owner of %s\n",fullname); + warnings++; + attrsz = 0; + } + return (attrsz); +} + +/* + * Update a security descriptor (Linux version) + */ + +BOOL updatefull(const char *name, DWORD flags, char *attr) +{ + BOOL ok; + + ok = !ntfs_set_file_security(ntfs_context, name, flags, attr); + if (ok) { + printf("** Could not change attributes of %s\n",name); + printerror(stdout); + errors++; + } + return (ok); +} + + +#endif + +#if POSIXACLS + +/* + * Set all the parameters associated to a file + */ + +BOOL setfull_posix(const char *fullname, const struct POSIX_SECURITY *pxdesc, + BOOL isdir) +{ + static char attr[MAXATTRSZ]; + struct POSIX_SECURITY *oldpxdesc; + struct POSIX_SECURITY *newpxdesc; + const SECURITY_DESCRIPTOR_RELATIVE *phead; + char *newattr; + int err; + unsigned int attrsz; + int newattrsz; + const SID *usid; + const SID *gsid; +#if OWNERFROMACL + const SID *osid; +#endif + + printf("%s ",(isdir ? "Directory" : "File")); + printname(stdout,fullname); + if (pxdesc->acccnt) + printf("\n"); + else + printf(" mode 0%03o\n",pxdesc->mode); + + err = FALSE; + attrsz = getfull(attr, fullname); + if (attrsz) { + oldpxdesc = linux_permissions_posix(attr, isdir); + if (opt_v >= 2) { + printf("Posix equivalent of old ACL :\n"); + showposix(oldpxdesc); + } + if (oldpxdesc) { + if (!pxdesc->defcnt + && !(pxdesc->tagsset & + (POSIX_ACL_USER | POSIX_ACL_GROUP | POSIX_ACL_MASK))) { + if (!ntfs_merge_mode_posix(oldpxdesc,pxdesc->mode)) + newpxdesc = oldpxdesc; + else { + newpxdesc = (struct POSIX_SECURITY*)NULL; + free(oldpxdesc); + } + } else { + newpxdesc = ntfs_merge_descr_posix(pxdesc, oldpxdesc); + free(oldpxdesc); + } + if (opt_v) { + printf("New Posix ACL :\n"); + showposix(newpxdesc); + } + } else + newpxdesc = (struct POSIX_SECURITY*)NULL; + if (newpxdesc) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + gsid = (const SID*)&attr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + osid = (const SID*)&attr[le32_to_cpu(phead->owner)]; + usid = ntfs_acl_owner((const char*)attr); + if (!ntfs_same_sid(usid,osid)) + printf("== Windows owner might change\n"); +#else + usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; +#endif + newattr = ntfs_build_descr_posix(context.mapping, + newpxdesc,isdir,usid,gsid); + free(newpxdesc); + } else + newattr = (char*)NULL; + if (newattr) { + newattrsz = ntfs_attr_size(newattr); + if (opt_v) { + printf("New NTFS security descriptor\n"); + hexdump(newattr,newattrsz,4); + } + if (opt_v >= 2) { + printf("Expected hash : 0x%08lx\n", + (unsigned long)hash((le32*)newattr,ntfs_attr_size(newattr))); + showheader(newattr,0); + showusid(newattr,0); + showgsid(newattr,0); + showdacl(newattr,isdir,0); + showsacl(newattr,isdir,0); + } + +#ifdef WIN32 + /* + * avoid getting a set owner error on Windows + * owner should not be changed anyway + */ + if (!updatefull(fullname, + DACL_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | OWNER_SECURITY_INFORMATION, + newattr)) +#else + if (!updatefull(fullname, + DACL_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | OWNER_SECURITY_INFORMATION, + newattr)) +#endif + err = TRUE; +/* +{ +struct POSIX_SECURITY *interp; +printf("Reinterpreted new Posix :\n"); +interp = linux_permissions_posix(newattr,isdir); +showposix(interp); +free(interp); +} +*/ + free(newattr); + } else + err = TRUE; + } else + err = TRUE; + return (!err); +} + +#endif + +BOOL setfull(const char *fullname, int mode, BOOL isdir) +{ + static char attr[MAXATTRSZ]; + const SECURITY_DESCRIPTOR_RELATIVE *phead; + char *newattr; + int err; + unsigned int attrsz; + int newattrsz; + const SID *usid; + const SID *gsid; +#if OWNERFROMACL + const SID *osid; +#endif + + printf("%s ",(isdir ? "Directory" : "File")); + printname(stdout,fullname); + printf(" mode 0%03o\n",mode); + attrsz = getfull(attr, fullname); + if (attrsz) { + phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr; + gsid = (const SID*)&attr[le32_to_cpu(phead->group)]; +#if OWNERFROMACL + osid = (const SID*)&attr[le32_to_cpu(phead->owner)]; + usid = ntfs_acl_owner((const char*)attr); + if (!ntfs_same_sid(usid,osid)) + printf("== Windows owner might change\n"); +#else + usid = (const SID*)&attr[le32_to_cpu(phead->owner)]; +#endif + newattr = ntfs_build_descr(mode,isdir,usid,gsid); + if (newattr) { + newattrsz = ntfs_attr_size(newattr); + if (opt_v) { + printf("Security descriptor\n"); + hexdump(newattr,newattrsz,4); + } + if (opt_v >= 2) { + printf("Expected hash : 0x%08lx\n", + (unsigned long)hash((le32*)newattr,ntfs_attr_size(newattr))); + showheader(newattr,0); + showusid(newattr,0); + showgsid(newattr,0); + showdacl(newattr,isdir,0); + showsacl(newattr,isdir,0); + } + +#ifdef WIN32 + /* + * avoid getting a set owner error on Windows + * owner should not be changed anyway + */ + if (!updatefull(fullname, + DACL_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | OWNER_SECURITY_INFORMATION, + newattr)) +#else + if (!updatefull(fullname, + DACL_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | OWNER_SECURITY_INFORMATION, + newattr)) +#endif + err = TRUE; + free(newattr); + } + + } else + err = TRUE; + return (err); +} + +#ifdef WIN32 + +/* + * Check whether a directory with reparse data is a junction + * or a symbolic link + */ + +BOOL islink(const char *filename) +{ + WIN32_FIND_DATAW found; + HANDLE search; + BOOL link; + + link = FALSE; + search = FindFirstFileW((LPCWSTR)filename, &found); + if (search != INVALID_HANDLE_VALUE) { + link = (found.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) + || (found.dwReserved0 == IO_REPARSE_TAG_SYMLINK); + FindClose(search); + } + return (link); +} + +#if POSIXACLS +BOOL iterate(RECURSE call, const char *fullname, const struct POSIX_SECURITY *pxdesc) +#else +BOOL iterate(RECURSE call, const char *fullname, mode_t mode) +#endif +{ + WIN32_FIND_DATAW found; + HANDLE search; + BOOL err; + unsigned int len; + char *filter; + char *inner; + + err = FALSE; + filter = (char*)malloc(MAXFILENAME); + inner = (char*)malloc(MAXFILENAME); + if (filter && inner) { + len = utf16len(fullname); + memcpy(filter, fullname, 2*len); + makeutf16(&filter[2*len],"\\*.*"); + search = FindFirstFileW((LPCWSTR)filter, &found); + if (search != INVALID_HANDLE_VALUE) { + do { + if (found.cFileName[0] != UNICODE('.')) { + memcpy(inner, fullname, 2*len); + inner[2*len] = '\\'; + inner[2*len+1] = 0; + memcpy(&inner[2*len+2],found.cFileName, + 2*utf16len((char*)found.cFileName)+2); + if (opt_v) + if (opt_b) + printf("#\n#\n"); + else + printf("\n\n"); + switch (call) { + case RECSHOW : + if (recurseshow(inner)) + err = TRUE; + break; +#if POSIXACLS + case RECSETPOSIX : + if (recurseset_posix(inner,pxdesc)) + err = TRUE; + break; +#else + case RECSET : + if (recurseset(inner,mode)) + err = TRUE; + break; +#endif + default : + err = TRUE; + } + } + } while (FindNextFileW(search, &found)); + FindClose(search); + } + free(filter); + free(inner); + } else { + printf("** Cannot process deeper : not enough memory\n"); + errors++; + err = TRUE; + } + return (err); +} + + + +/* + * Display all the parameters associated to a file (Windows version) + */ + +void showfull(const char *fullname, BOOL isdir) +{ + static char attr[MAXATTRSZ]; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + ULONG attrsz; + int mode; + uid_t uid; + gid_t gid; + int attrib; + int level; + + printf("%s ",(isdir ? "Directory" : "File")); + printname(stdout,fullname); + printf("\n"); + + /* get individual parameters, as when trying to get them */ + /* all, and one (typically SACL) is missing, we get none, */ + /* and concatenate them, to be able to compute the hash code */ + + attrsz = getfull(attr, fullname); + if (attrsz) { + if (opt_v || opt_b) { + hexdump(attr,attrsz,8); + printf("Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr,attrsz)); + } + if (opt_v && opt_b) { + printf("# %s ",(isdir ? "Directory" : "File")); + printname(stdout,fullname); + printf(" hash 0x%lx\n", + (unsigned long)hash((le32*)attr,attrsz)); + } + attrib = GetFileAttributesW((LPCWSTR)fullname); + if (attrib == INVALID_FILE_ATTRIBUTES) { + printf("** Could not get file attrib\n"); + errors++; + } else + printf("Windows attrib : 0x%x\n",attrib); + if (ntfs_valid_descr(attr,attrsz)) { +#if POSIXACLS + pxdesc = linux_permissions_posix(attr,isdir); + if (pxdesc) + mode = pxdesc->mode; + else + mode = 0; +#else + mode = linux_permissions(attr,isdir); +#endif + if (opt_v >= 2) { + level = (opt_b ? 4 : 0); + showheader(attr,level); + showusid(attr,level); + showgsid(attr,level); + showdacl(attr,isdir,level); + showsacl(attr,isdir,level); + } + uid = linux_owner(attr); + gid = linux_group(attr); + if (opt_b) { + printf("# Interpreted Unix owner %d, group %d, mode 0%03o\n", + (int)uid,(int)gid,mode); + } else { + printf("Interpreted Unix owner %d, group %d, mode 0%03o\n", + (int)uid,(int)gid,mode); + } +#if POSIXACLS + if (pxdesc) { + if (!opt_b + && (pxdesc->defcnt + || (pxdesc->tagsset + & (POSIX_ACL_USER + | POSIX_ACL_GROUP + | POSIX_ACL_MASK)))) + showposix(pxdesc); + free(pxdesc); + } +#endif + } else + if (opt_b) + printf("# Descriptor fails sanity check\n"); + else + printf("Descriptor fails sanity check\n"); + } +} + +BOOL recurseshow(const char *fullname) +{ + int attrib; + int err; + BOOL isdir; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)fullname); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; + showfull(fullname,isdir); + if (isdir + && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT) + && islink(fullname))) { +#if POSIXACLS + err = iterate(RECSHOW, fullname, (struct POSIX_SECURITY*)NULL); +#else + err = iterate(RECSHOW, fullname, 0); +#endif + } + } else { + printf("** Could not access "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + errors++; + err = TRUE; + } + return (err); +} + + +BOOL singleshow(const char *fullname) +{ + int attrib; + int err; + BOOL isdir; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)fullname); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; + showfull(fullname,isdir); + } else { + printf("** Could not access "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + errors++; + err = TRUE; + } + return (err); +} + +#if POSIXACLS + +BOOL recurseset_posix(const char *fullname, const struct POSIX_SECURITY *pxdesc) +{ + int attrib; + int err; + BOOL isdir; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)fullname); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; + err = !setfull_posix(fullname,pxdesc,isdir); + if (err) { + printf("** Failed to update "); + printname(stdout,fullname); + printf("\n"); + errors++; + } else + if (isdir + && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT) + && islink(fullname))) + iterate(RECSETPOSIX, fullname, pxdesc); + } else { + err = GetLastError(); + printf("** Could not access "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + err = TRUE; + errors++; + } + return (err); +} + +#else + +BOOL recurseset(const char *fullname, int mode) +{ + int attrib; + int err; + BOOL isdir; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)fullname); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; + setfull(fullname,mode,isdir); + if (isdir + && !((attrib & FILE_ATTRIBUTE_REPARSE_POINT) + && islink(fullname))) + iterate(RECSETPOSIX, fullname, mode); + } else { + err = GetLastError(); + printf("** Could not access "); + printname(stdout,fullname); + printf("\n"); + printerror(stdout); + err = TRUE; + errors++; + } + return (err); +} + +#endif + +#if POSIXACLS + +BOOL singleset_posix(const char *path, const struct POSIX_SECURITY *pxdesc) +{ + BOOL isdir; + BOOL err; + int attrib; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)path); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY); + err = !setfull_posix(path,pxdesc,isdir); + if (err) { + printf("** Failed to update "); + printname(stdout,path); + printf("\n"); + errors++; + } + } else { + printf("** Could not access "); + printname(stdout,path); + printf("\n"); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +#endif + +BOOL singleset(const char *path, int mode) +{ + BOOL isdir; + BOOL err; + int attrib; + + err = FALSE; + attrib = GetFileAttributesW((LPCWSTR)path); + if (attrib != INVALID_FILE_ATTRIBUTES) { + isdir = (attrib & FILE_ATTRIBUTE_DIRECTORY); + setfull(path,mode,isdir); + } else { + printf("** Could not access "); + printname(stdout,path); + printf("\n"); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +#else + +/* + * Display all the parameters associated to a file (Linux version) + */ + +void showfull(const char *fullname, BOOL isdir) +{ + static char attr[MAXATTRSZ]; + static char part[MAXATTRSZ]; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + struct SECURITY_DATA *psecurdata; + char *newattr; + int securindex; + int mode; + int level; + int attrib; + u32 attrsz; + u32 partsz; + uid_t uid; + gid_t gid; + + if (opt_v || opt_b) + printf("%s %s\n",(isdir ? "Directory" : "File"),fullname); + + /* get individual parameters, as when trying to get them */ + /* all, and one (typically SACL) is missing, we get none */ + /* and concatenate them, to be able to compute the checksum */ + + partsz = 0; + securindex = ntfs_get_file_security(ntfs_context,fullname, + OWNER_SECURITY_INFORMATION, + (char*)part,MAXATTRSZ,&partsz); + + attrib = ntfs_get_file_attributes(ntfs_context, fullname); + if (attrib == INVALID_FILE_ATTRIBUTES) { + printf("** Could not get file attrib\n"); + errors++; + } + if ((securindex < 0) + || (securindex >= MAXSECURID) + || ((securindex > 0) + && ((!opt_r && !opt_b) + || !securdata[securindex >> SECBLKSZ] + || !securdata[securindex >> SECBLKSZ][securindex & ((1 << SECBLKSZ) - 1)].filecount))) + { + if (opt_v || opt_b) { + if ((securindex < -1) || (securindex >= MAXSECURID)) + printf("Security key : 0x%x out of range\n",securindex); + else + if (securindex == -1) + printf("Security key : none\n"); + else + printf("Security key : 0x%x\n",securindex); + } else { + printf("%s %s",(isdir ? "Directory" : "File"),fullname); + if ((securindex < -1) || (securindex >= MAXSECURID)) + printf(" : key 0x%x out of range\n",securindex); + else + if (securindex == -1) + printf(" : no key\n"); + else + printf(" : key 0x%x\n",securindex); + } + + attrsz = getfull(attr, fullname); + if (attrsz) { + psecurdata = (struct SECURITY_DATA*)NULL; + if ((securindex < MAXSECURID) && (securindex > 0)) { + if (!securdata[securindex >> SECBLKSZ]) + newblock(securindex); + if (securdata[securindex >> SECBLKSZ]) + psecurdata = &securdata[securindex >> SECBLKSZ] + [securindex & ((1 << SECBLKSZ) - 1)]; + } + if (opt_v && (opt_a || opt_b) && psecurdata) { + newattr = (char*)malloc(attrsz); + printf("# %s %s hash 0x%lx\n",(isdir ? "Directory" : "File"), + fullname, + (unsigned long)hash((le32*)attr,attrsz)); + if (newattr) { + memcpy(newattr,attr,attrsz); + psecurdata->attr = newattr; + } + } + if ((opt_v || opt_b) + && ((securindex >= MAXSECURID) + || (securindex <= 0) + || !psecurdata + || (!psecurdata->filecount + && !psecurdata->flags))) { + hexdump(attr,attrsz,8); + printf("Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr,attrsz)); + } + if (ntfs_valid_descr((char*)attr,attrsz)) { +#if POSIXACLS + pxdesc = linux_permissions_posix(attr,isdir); + if (pxdesc) + mode = pxdesc->mode; + else + mode = 0; +#else + mode = linux_permissions(attr,isdir); +#endif + attrib = ntfs_get_file_attributes(ntfs_context,fullname); + if (opt_v >= 2) { + level = (opt_b ? 4 : 0); + showheader(attr,level); + showusid(attr,level); + showgsid(attr,level); + showdacl(attr,isdir,level); + showsacl(attr,isdir,level); + } + if (attrib != INVALID_FILE_ATTRIBUTES) + printf("Windows attrib : 0x%x\n",attrib); + uid = linux_owner(attr); + gid = linux_group(attr); + if (opt_b) { + printf("# Interpreted Unix owner %d, group %d, mode 0%03o\n", + (int)uid,(int)gid,mode); + } else { + printf("Interpreted Unix owner %d, group %d, mode 0%03o\n", + (int)uid,(int)gid,mode); + } +#if POSIXACLS + if (pxdesc) { + if (!opt_b + && (pxdesc->defcnt + || (pxdesc->tagsset + & (POSIX_ACL_USER + | POSIX_ACL_GROUP + | POSIX_ACL_MASK)))) + showposix(pxdesc); + free(pxdesc); + } +#endif + if ((opt_r || opt_b) && (securindex < MAXSECURID) + && (securindex > 0) && psecurdata) { + psecurdata->filecount++; + psecurdata->mode = mode; + } + } else { + printf("** Descriptor fails sanity check\n"); + errors++; + } + } + } else + if (securindex > 0) { + if (securdata[securindex >> SECBLKSZ]) { + psecurdata = &securdata[securindex >> SECBLKSZ] + [securindex & ((1 << SECBLKSZ) - 1)]; + psecurdata->filecount++; + if (opt_b || opt_r) { + if (!opt_b && !opt_v) + printf("%s %s\n",(isdir ? "Directory" : "File"),fullname); + printf("Security key : 0x%x mode %03o (already displayed)\n", + securindex,psecurdata->mode); + if (attrib != INVALID_FILE_ATTRIBUTES) + printf("Windows attrib : 0x%x\n",attrib); + } else { + printf("%s %s",(isdir ? "Directory" : "File"),fullname); + printf(" : key 0x%x\n",securindex); + } + if ((opt_a || opt_b) && opt_v + && psecurdata && psecurdata->attr) { + printf("# %s %s hash 0x%lx\n",(isdir ? "Directory" : "File"), + fullname, + (unsigned long)hash((le32*)psecurdata->attr, + ntfs_attr_size(psecurdata->attr))); + } + } + } else { + if (!opt_v && !opt_b) + printf("%s %s",(isdir ? "Directory" : "File"),fullname); + printf(" (Failed)\n"); + printf("** Could not get security data of %s, partsz %d\n", + fullname,partsz); + printerror(stdout); + errors++; + } +} + +BOOL recurseshow(const char *path) +{ + struct CALLBACK dircontext; + struct LINK *current; + BOOL isdir; + BOOL err; + + err = FALSE; + dircontext.head = (struct LINK*)NULL; + dircontext.dir = path; + isdir = ntfs_read_directory(ntfs_context, path, + callback, &dircontext); + if (isdir) { + showfull(path,TRUE); + if (opt_v) { + if (opt_b) + printf("#\n#\n"); + else + printf("\n\n"); + } + while (dircontext.head) { + current = dircontext.head; + if (recurseshow(current->name)) err = TRUE; + dircontext.head = dircontext.head->next; + free(current); + } + } else + if (errno == ENOTDIR) { + showfull(path,FALSE); + if (opt_v) { + if (opt_b) + printf("#\n#\n"); + else + printf("\n\n"); + } + } else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + + +BOOL singleshow(const char *path) +{ + BOOL isdir; + BOOL err; + + err = FALSE; + isdir = ntfs_read_directory(ntfs_context, path, + callback, (struct CALLBACK*)NULL); + if (isdir || (errno == ENOTDIR)) + showfull(path,isdir); + else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (err); +} + +/* + * Display all the parameters associated to a mounted file + */ + +void showmounted(const char *fullname) +{ +#ifdef HAVE_SETXATTR + + static char attr[MAXATTRSZ]; + struct stat st; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + BOOL mapped; + int attrsz; + int mode; + uid_t uid; + gid_t gid; + u32 attrib; + int level; + BOOL isdir; + + if (!stat(fullname,&st)) { + isdir = S_ISDIR(st.st_mode); + printf("%s ",(isdir ? "Directory" : "File")); + printname(stdout,fullname); + printf("\n"); + + attrsz = getxattr(fullname,"system.ntfs_acl",attr,MAXATTRSZ); + if (attrsz > 0) { + if (opt_v) { + hexdump(attr,attrsz,8); + printf("Computed hash : 0x%08lx\n", + (unsigned long)hash((le32*)attr,attrsz)); + } + if (getxattr(fullname,"system.ntfs_attrib",&attrib,4) != 4) { + printf("** Could not get file attrib\n"); + errors++; + } else + printf("Windows attrib : 0x%x\n",(int)attrib); + if (ntfs_valid_descr(attr,attrsz)) { + mapped = !local_build_mapping(context.mapping,fullname); +#if POSIXACLS + if (mapped) { + pxdesc = linux_permissions_posix(attr,isdir); + if (pxdesc) + mode = pxdesc->mode; + else + mode = 0; + } else { + pxdesc = (struct POSIX_SECURITY*)NULL; + mode = linux_permissions(attr,isdir); + printf("No user mapping : " + "cannot display the Posix ACL\n"); + } +#else + mode = linux_permissions(attr,isdir); +#endif + if (opt_v >= 2) { + level = (opt_b ? 4 : 0); + showheader(attr,level); + showusid(attr,level); + showgsid(attr,level); + showdacl(attr,isdir,level); + showsacl(attr,isdir,level); + } + if (mapped) { + uid = linux_owner(attr); + gid = linux_group(attr); + printf("Interpreted Unix owner %d, group %d, mode 0%03o\n", + (int)uid,(int)gid,mode); + } else { + printf("Interpreted Unix mode 0%03o (owner and group are unmapped)\n", + mode); + } +#if POSIXACLS + if (pxdesc) { + if ((pxdesc->defcnt + || (pxdesc->tagsset + & (POSIX_ACL_USER + | POSIX_ACL_GROUP + | POSIX_ACL_MASK)))) + showposix(pxdesc); +#if USESTUBS + stdfree(pxdesc); /* allocated within library */ +#else + free(pxdesc); +#endif + } + if (mapped) + ntfs_free_mapping(context.mapping); +#endif + } else + printf("Descriptor fails sanity check\n"); + } else { + printf("** Could not get the NTFS ACL, check whether file is on NTFS\n"); + errors++; + } + } else + printf("%s not found\n",fullname); +#endif +} + +#if POSIXACLS + +BOOL recurseset_posix(const char *path, const struct POSIX_SECURITY *pxdesc) +{ + struct CALLBACK dircontext; + struct LINK *current; + BOOL isdir; + BOOL err; + + err = FALSE; + dircontext.head = (struct LINK*)NULL; + dircontext.dir = path; + isdir = ntfs_read_directory(ntfs_context, path, + callback, &dircontext); + if (isdir) { + err = !setfull_posix(path,pxdesc,TRUE); + if (err) { + printf("** Failed to update %s\n",path); + printerror(stdout); + errors++; + } else { + if (opt_b) + printf("#\n#\n"); + else + printf("\n\n"); + while (dircontext.head) { + current = dircontext.head; + recurseset_posix(current->name,pxdesc); + dircontext.head = dircontext.head->next; + free(current); + } + } + } else + if (errno == ENOTDIR) { + err = !setfull_posix(path,pxdesc,FALSE); + if (err) { + printf("** Failed to update %s\n",path); + printerror(stdout); + errors++; + } + } else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +#else + +BOOL recurseset(const char *path, int mode) +{ + struct CALLBACK dircontext; + struct LINK *current; + BOOL isdir; + BOOL err; + + err = FALSE; + dircontext.head = (struct LINK*)NULL; + dircontext.dir = path; + isdir = ntfs_read_directory(ntfs_context, path, + callback, &dircontext); + if (isdir) { + setfull(path,mode,TRUE); + if (opt_b) + printf("#\n#\n"); + else + printf("\n\n"); + while (dircontext.head) { + current = dircontext.head; + recurseset(current->name,mode); + dircontext.head = dircontext.head->next; + free(current); + } + } else + if (errno == ENOTDIR) + setfull(path,mode,FALSE); + else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +#endif + +#if POSIXACLS + +BOOL singleset_posix(const char *path, const struct POSIX_SECURITY *pxdesc) +{ + BOOL isdir; + BOOL err; + + err = FALSE; + isdir = ntfs_read_directory(ntfs_context, path, + callback, (struct CALLBACK*)NULL); + if (isdir || (errno == ENOTDIR)) { + err = !setfull_posix(path,pxdesc,isdir); + if (err) { + printf("** Failed to update %s\n",path); + printerror(stdout); + errors++; + } + } else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +#endif + +BOOL singleset(const char *path, int mode) +{ + BOOL isdir; + BOOL err; + + err = FALSE; + isdir = ntfs_read_directory(ntfs_context, path, + callback, (struct CALLBACK*)NULL); + if (isdir || (errno == ENOTDIR)) + setfull(path,mode,isdir); + else { + printf("** Could not access %s\n",path); + printerror(stdout); + errors++; + err = TRUE; + } + return (!err); +} + +int callback(struct CALLBACK *dircontext, char *ntfsname, + int length, int type, + long long pos __attribute__((unused)), u64 mft_ref __attribute__((unused)), + unsigned int dt_type __attribute__((unused))) +{ + struct LINK *linkage; + char *name; + int newlth; + int size; + + size = utf8size(ntfsname,length); + if (dircontext + && (type != 2) /* 2 : dos name (8+3) */ + && (size > 0) /* chars convertible to utf8 */ + && ((length > 2) + || (ntfsname[0] != '.') + || (ntfsname[1] != '\0') + || ((ntfsname[2] || ntfsname[3]) + && ((ntfsname[2] != '.') || (ntfsname[3] != '\0'))))) { + linkage = (struct LINK*)malloc(sizeof(struct LINK) + + strlen(dircontext->dir) + + size + 2); + if (linkage) { + /* may find ".fuse_hidden*" files */ + /* recommendation is not to hide them, so that */ + /* the user has a clue to delete them */ + strcpy(linkage->name,dircontext->dir); + if (linkage->name[strlen(linkage->name) - 1] != '/') + strcat(linkage->name,"/"); + name = &linkage->name[strlen(linkage->name)]; + newlth = makeutf8(name,ntfsname,length); + name[newlth] = 0; + linkage->next = dircontext->head; + dircontext->head = linkage; + } + } + return (0); +} + +#endif + +#ifdef WIN32 + +/* + * Backup security descriptors in a directory tree (Windows mode) + */ + +BOOL backup(const char *root) +{ + BOOL err; + time_t now; + const char *txtime; + + now = time((time_t*)NULL); + txtime = ctime(&now); + printf("#\n# Recursive ACL collection on %s#\n",txtime); + err = recurseshow(root); + return (err); +} + +#else + +/* + * Backup security descriptors in a directory tree (Linux mode) + */ + +BOOL backup(const char *volume, const char *root) +{ + BOOL err; + int count; + int i,j; + time_t now; + const char *txtime; + + now = time((time_t*)NULL); + txtime = ctime(&now); + if (!getuid() && open_security_api()) { + if (open_volume(volume,MS_RDONLY)) { + printf("#\n# Recursive ACL collection on %s#\n",txtime); + err = recurseshow(root); + count = 0; + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + if (securdata[i]) + for (j=0; j<(1 << SECBLKSZ); j++) + if (securdata[i][j].filecount) { + count++; + } + printf("# %d security keys\n",count); + close_volume(volume); + } else { + fprintf(stderr,"Could not open volume %s\n",volume); + printerror(stdout); + err = TRUE; + } + close_security_api(); + } else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else + fprintf(stderr,"Could not open security API\n"); + err = TRUE; + } + return (err); +} + +#endif + +#ifdef WIN32 + +/* + * List security descriptors in a directory tree (Windows mode) + */ + +BOOL listfiles(const char *root) +{ + BOOL err; + + if (opt_r) { + printf("\nRecursive file check\n"); + err = recurseshow(root); + } else + err = singleshow(root); + return (err); +} + +#else + +/* + * List security descriptors in a directory tree (Linux mode) + */ + +BOOL listfiles(const char *volume, const char *root) +{ + BOOL err; + int i,j; + int count; + + if (!getuid() && open_security_api()) { + if (open_volume(volume,MS_RDONLY)) { + if (opt_r) { + printf("\nRecursive file check\n"); + err = recurseshow(root); + printf("Summary\n"); + count = 0; + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + if (securdata[i]) + for (j=0; j<(1 << SECBLKSZ); j++) + if (securdata[i][j].filecount) { + printf("Key 0x%x : %d files, mode 0%03o\n", + i*(1 << SECBLKSZ)+j,securdata[i][j].filecount, + securdata[i][j].mode); + count++; + } + printf("%d security keys\n",count); + } else + err = singleshow(root); + close_volume(volume); + } else { + fprintf(stderr,"Could not open volume %s\n",volume); + printerror(stdout); + err = TRUE; + } + close_security_api(); + } else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else + fprintf(stderr,"Could not open security API\n"); + err = TRUE; + } + return (err); +} + +#endif + +#ifndef WIN32 + +/* + * Check whether a SDS entry is valid + */ + +BOOL valid_sds(const char *attr, unsigned int offset, + unsigned int entrysz, unsigned int size, u32 prevkey, + BOOL second) +{ + BOOL unsane; + u32 comphash; + u32 key; + + unsane = FALSE; + if (!get4l(attr,0) && !get4l(attr,4)) { + printf("Entry at 0x%lx was deleted\n",(long)offset); + } else { + if ((ntfs_attr_size(&attr[20]) + 20) > entrysz) { + printf("** Entry is truncated (expected size %ld)\n", + (long)ntfs_attr_size(&attr[20] + 20)); + unsane = TRUE; + errors++; + } + if ((ntfs_attr_size(&attr[20]) + 20) < entrysz) { + printf("** Extra data appended to entry (expected size %ld)\n", + (long)ntfs_attr_size(&attr[20]) + 20); + warnings++; + } + if (!unsane && !ntfs_valid_descr((const char*)&attr[20],size)) { + printf("** General sanity check has failed\n"); + unsane = TRUE; + errors++; + } + if (!unsane) { + comphash = hash((const le32*)&attr[20],entrysz-20); + if ((u32)get4l(attr,0) == comphash) { + if (opt_v >= 2) + printf("Hash 0x%08lx (correct)\n", + (unsigned long)comphash); + } else { + printf("** hash 0x%08lx (computed : 0x%08lx)\n", + (unsigned long)get4l(attr,0), + (unsigned long)comphash); + unsane = TRUE; + errors++; + } + } + if (!unsane) { + if ((second ? get8l(attr,8) + 0x40000 : get8l(attr,8)) == offset) { + if (opt_v >= 2) + printf("Offset 0x%lx (correct)\n",(long)offset); + } else { + printf("** offset 0x%llx (expected : 0x%llx)\n", + (long long)get8l(attr,8), + (long long)(second ? get8l(attr,8) - 0x40000 : get8l(attr,8))); +// unsane = TRUE; + errors++; + } + } + if (!unsane) { + key = get4l(attr,4); + if (opt_v >= 2) + printf("Key 0x%x\n",(int)key); + if (key) { + if (key <= prevkey) { + printf("** Unordered key 0x%lx after 0x%lx\n", + (long)key,(long)prevkey); + unsane = TRUE; + errors++; + } + } + } + } + return (!unsane); +} + +/* + * Check whether a SDS entry is consistent with other known data + * and store current data for subsequent checks + */ + +int consist_sds(const char *attr, unsigned int offset, + unsigned int entrysz, BOOL second) +{ + int errcnt; + u32 key; + u32 comphash; + struct SECURITY_DATA *psecurdata; + + errcnt = 0; + key = get4l(attr,4); + if ((key > 0) && (key < MAXSECURID)) { + printf("Valid entry at 0x%lx for key 0x%lx\n", + (long)offset,(long)key); + if (!securdata[key >> SECBLKSZ]) + newblock(key); + if (securdata[key >> SECBLKSZ]) { + psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)]; + comphash = hash((const le32*)&attr[20],entrysz-20); + if (psecurdata->flags & INSDS1) { + if (psecurdata->hash != comphash) { + printf("** Different hash values : $SDS-1 0x%08lx $SDS-2 0x%08lx\n", + (unsigned long)psecurdata->hash, + (unsigned long)comphash); + errcnt++; + errors++; + } + if (psecurdata->offset != get8l(attr,8)) { + printf("** Different offsets : $SDS-1 0x%llx $SDS-2 0x%llx\n", + (long long)psecurdata->offset,(long long)get8l(attr,8)); + errcnt++; + errors++; + } + if (psecurdata->length != get4l(attr,16)) { + printf("** Different lengths : $SDS-1 0x%lx $SDS-2 0x%lx\n", + (long)psecurdata->length,(long)get4l(attr,16)); + errcnt++; + errors++; + } + } else { + if (second) { + printf("** Entry was not present in $SDS-1\n"); + errcnt++; + errors++; + } + psecurdata->hash = comphash; + psecurdata->offset = get8l(attr,8); + psecurdata->length = get4l(attr,16); + } + psecurdata->flags |= (second ? INSDS2 : INSDS1); + } + } else + if (key || get4l(attr,0)) { + printf("** Security_id 0x%x out of bounds\n",key); + warnings++; + } + return (errcnt); +} + + +/* + * Auditing of $SDS (Linux only) + */ + +int audit_sds(BOOL second) +{ + static char attr[MAXATTRSZ + 20]; + BOOL isdir; + BOOL done; + BOOL unsane; + u32 prevkey; + int errcnt; + int size; + unsigned int entrysz; + unsigned int entryalsz; + unsigned int offset; + int count; + int deleted; + int mode; + + if (second) + printf("\nAuditing $SDS-2\n"); + else + printf("\nAuditing $SDS-1\n"); + errcnt = 0; + offset = (second ? 0x40000 : 0); + count = 0; + deleted = 0; + done = FALSE; + prevkey = 0; + + /* get size of first record */ + + size = ntfs_read_sds(ntfs_context,(char*)attr,20,offset); + if (size != 20) { + if ((size < 0) && (errno == ENOTSUP)) + printf("** There is no $SDS-%d in this volume\n", + (second ? 2 : 1)); + else { + printf("** Could not open $SDS-%d, size %d\n", + (second ? 2 : 1),size); + errors++; + errcnt++; + } + } else + do { + entrysz = get4l(attr,16); + entryalsz = ((entrysz - 1) | 15) + 1; + if (entryalsz <= (MAXATTRSZ + 20)) { + /* read next header in anticipation, to get its size */ + size = ntfs_read_sds(ntfs_context, + (char*)&attr[20],entryalsz,offset + 20); + if (opt_v) + printf("\nAt offset 0x%lx got %lu bytes\n",(long)offset,(long)size); + } else { + printf("** Security attribute is too long (%ld bytes) - stopping\n", + (long)entryalsz); + errcnt++; + } + if ((entryalsz > (MAXATTRSZ + 20)) || (size < (int)(entrysz - 20))) + done = TRUE; + else { + if (opt_v) { + printf("Entry size %d bytes\n",entrysz); + hexdump(&attr[20],size,8); + } + + unsane = !valid_sds(attr,offset,entrysz, + size,prevkey,second); + if (!unsane) { + if (!get4l(attr,0) && !get4l(attr,4)) + deleted++; + else + count++; + errcnt += consist_sds(attr,offset, + entrysz, second); + if (opt_v >= 2) { + isdir = guess_dir(&attr[20]); + printf("Assuming %s descriptor\n",(isdir ? "directory" : "file")); + showheader(&attr[20],0); + showusid(&attr[20],0); + showgsid(&attr[20],0); + showdacl(&attr[20],isdir,0); + showsacl(&attr[20],isdir,0); + mode = linux_permissions( + &attr[20],isdir); + printf("Interpreted Unix mode 0%03o\n",mode); + } + prevkey = get4l(attr,4); + } + if (!unsane) { + memcpy(attr,&attr[entryalsz],20); + offset += entryalsz; + if (!get4l(attr,16) + || ((((offset - 1) | 0x3ffff) - offset + 1) < 20)) { + if (second) + offset = ((offset - 1) | 0x7ffff) + 0x40001; + else + offset = ((offset - 1) | 0x7ffff) + 1; + if (opt_v) + printf("Trying next SDS-%d block at offset 0x%lx\n", + (second ? 2 : 1), (long)offset); + size = ntfs_read_sds(ntfs_context, + (char*)attr,20,offset); + if (size != 20) { + if (opt_v) + printf("Assuming end of $SDS, got %d bytes\n",size); + done = TRUE; + } + } + } else { + printf("** Sanity check failed - stopping there\n"); + errcnt++; + errors++; + done = TRUE; + } + } + } while (!done); + if (count || deleted || errcnt) { + printf("%d valid and %d deleted entries in $SDS-%d\n", + count,deleted,(second ? 2 : 1)); + printf("%d errors in $SDS-%c\n",errcnt,(second ? '2' : '1')); + } + return (errcnt); +} + +/* + * Check whether a SII entry is sane + */ + +BOOL valid_sii(const char *entry, u32 prevkey) +{ + BOOL valid; + u32 key; + + valid = TRUE; + key = get4l(entry,16); + if (key <= prevkey) { + printf("** Unordered key 0x%lx after 0x%lx\n", + (long)key,(long)prevkey); + valid = FALSE; + errors++; + } + prevkey = key; + if (get2l(entry,0) != 20) { + printf("** offset %d (instead of 20)\n",(int)get2l(entry,0)); + valid = FALSE; + errors++; + } + if (get2l(entry,2) != 20) { + printf("** size %d (instead of 20)\n",(int)get2l(entry,2)); + valid = FALSE; + errors++; + } + if (get4l(entry,4) != 0) { + printf("** fill1 %d (instead of 0)\n",(int)get4l(entry,4)); + valid = FALSE; + errors++; + } + if (get2l(entry,12) & 1) { + if (get2l(entry,8) != 48) { + printf("** index size %d (instead of 48)\n",(int)get2l(entry,8)); + valid = FALSE; + errors++; + } + } else + if (get2l(entry,8) != 40) { + printf("** index size %d (instead of 40)\n",(int)get2l(entry,8)); + valid = FALSE; + errors++; + } + if (get2l(entry,10) != 4) { + printf("** index key size %d (instead of 4)\n",(int)get2l(entry,10)); + valid = FALSE; + errors++; + } + if ((get2l(entry,12) & ~3) != 0) { + printf("** flags 0x%x (instead of < 4)\n",(int)get2l(entry,12)); + valid = FALSE; + errors++; + } + if (get2l(entry,14) != 0) { + printf("** fill2 %d (instead of 0)\n",(int)get2l(entry,14)); + valid = FALSE; + errors++; + } + if (get4l(entry,24) != key) { + printf("** key 0x%x (instead of 0x%x)\n", + (int)get4l(entry,24),(int)key); + valid = FALSE; + errors++; + } + return (valid); +} + +/* + * Check whether a SII entry is consistent with other known data + */ + +int consist_sii(const char *entry) +{ + int errcnt; + u32 key; + struct SECURITY_DATA *psecurdata; + + errcnt = 0; + key = get4l(entry,16); + if ((key > 0) && (key < MAXSECURID)) { + printf("Valid entry for key 0x%lx\n",(long)key); + if (!securdata[key >> SECBLKSZ]) + newblock(key); + if (securdata[key >> SECBLKSZ]) { + psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)]; + psecurdata->flags |= INSII; + if (psecurdata->flags & (INSDS1 | INSDS2)) { + if ((u32)get4l(entry,20) != psecurdata->hash) { + printf("** hash 0x%x (instead of 0x%x)\n", + (unsigned int)get4l(entry,20), + (unsigned int)psecurdata->hash); + errors++; + } + if (get8l(entry,28) != psecurdata->offset) { + printf("** offset 0x%llx (instead of 0x%llx)\n", + (long long)get8l(entry,28), + (long long)psecurdata->offset); + errors++; + } + if (get4l(entry,36) != psecurdata->length) { + printf("** length 0x%lx (instead of %ld)\n", + (long)get4l(entry,36), + (long)psecurdata->length); + errors++; + } + } else { + printf("** Entry was not present in $SDS\n"); + errors++; + psecurdata->hash = get4l(entry,20); + psecurdata->offset = get8l(entry,28); + psecurdata->length = get4l(entry,36); + if (opt_v) { + printf(" hash 0x%x\n",(unsigned int)psecurdata->hash); + printf(" offset 0x%llx\n",(long long)psecurdata->offset); + printf(" length %ld\n",(long)psecurdata->length); + } + errcnt++; + } + } + } else { + printf("** Security_id 0x%x out of bounds\n",key); + warnings++; + } + return (errcnt); +} + + +/* + * Auditing of $SII (Linux only) + */ + +int audit_sii() +{ + char *entry; + int errcnt; + u32 prevkey; + BOOL valid; + BOOL done; + int count; + + printf("\nAuditing $SII\n"); + errcnt = 0; + count = 0; + entry = (char*)NULL; + prevkey = 0; + done = FALSE; + do { + entry = (char*)ntfs_read_sii(ntfs_context,(void*)entry); + if (entry) { + valid = valid_sii(entry,prevkey); + if (valid) { + count++; + errcnt += consist_sii(entry); + prevkey = get4l(entry,16); + } else + errcnt++; + } else + if ((errno == ENOTSUP) && !prevkey) + printf("** There is no $SII in this volume\n"); + } while (entry && !done); + if (count || errcnt) { + printf("%d valid entries in $SII\n",count); + printf("%d errors in $SII\n",errcnt); + } + return (errcnt); +} + +/* + * Check whether a SII entry is sane + */ + +BOOL valid_sdh(const char *entry, u32 prevkey, u32 prevhash) +{ + BOOL valid; + u32 key; + u32 currhash; + + valid = TRUE; + currhash = get4l(entry,16); + key = get4l(entry,20); + if ((currhash < prevhash) + || ((currhash == prevhash) && (key <= prevkey))) { + printf("** Unordered hash and key 0x%x 0x%x after 0x%x 0x%x\n", + (unsigned int)currhash,(unsigned int)key, + (unsigned int)prevhash,(unsigned int)prevkey); + valid = FALSE; + errors++; + } + if ((opt_v >= 2) && (currhash == prevhash)) + printf("Hash collision (not an error)\n"); + + if (get2l(entry,0) != 24) { + printf("** offset %d (instead of 24)\n",(int)get2l(entry,0)); + valid = FALSE; + errors++; + } + if (get2l(entry,2) != 20) { + printf("** size %d (instead of 20)\n",(int)get2l(entry,2)); + valid = FALSE; + errors++; + } + if (get4l(entry,4) != 0) { + printf("** fill1 %d (instead of 0)\n",(int)get4l(entry,4)); + valid = FALSE; + errors++; + } + if (get2l(entry,12) & 1) { + if (get2l(entry,8) != 56) { + printf("** index size %d (instead of 56)\n",(int)get2l(entry,8)); + valid = FALSE; + errors++; + } + } else + if (get2l(entry,8) != 48) { + printf("** index size %d (instead of 48)\n",(int)get2l(entry,8)); + valid = FALSE; + errors++; + } + if (get2l(entry,10) != 8) { + printf("** index key size %d (instead of 8)\n",(int)get2l(entry,10)); + valid = FALSE; + errors++; + } + if ((get2l(entry,12) & ~3) != 0) { + printf("** flags 0x%x (instead of < 4)\n",(int)get2l(entry,12)); + valid = FALSE; + errors++; + } + if (get2l(entry,14) != 0) { + printf("** fill2 %d (instead of 0)\n",(int)get2l(entry,14)); + valid = FALSE; + errors++; + } + if ((u32)get4l(entry,24) != currhash) { + printf("** hash 0x%x (instead of 0x%x)\n", + (unsigned int)get4l(entry,24),(unsigned int)currhash); + valid = FALSE; + errors++; + } + if (get4l(entry,28) != key) { + printf("** key 0x%x (instead of 0x%x)\n", + (int)get4l(entry,28),(int)key); + valid = FALSE; + errors++; + } + if (get4l(entry,44) + && (get4l(entry,44) != 0x490049)) { + printf("** fill3 0x%lx (instead of 0 or 0x490049)\n", + (long)get4l(entry,44)); + valid = FALSE; + errors++; + } + return (valid); +} + +/* + * Check whether a SDH entry is consistent with other known data + */ + +int consist_sdh(const char *entry) +{ + int errcnt; + u32 key; + struct SECURITY_DATA *psecurdata; + + errcnt = 0; + key = get4l(entry,20); + if ((key > 0) && (key < MAXSECURID)) { + printf("Valid entry for key 0x%lx\n",(long)key); + if (!securdata[key >> SECBLKSZ]) + newblock(key); + if (securdata[key >> SECBLKSZ]) { + psecurdata = &securdata[key >> SECBLKSZ][key & ((1 << SECBLKSZ) - 1)]; + psecurdata->flags |= INSDH; + if (psecurdata->flags & (INSDS1 | INSDS2 | INSII)) { + if ((u32)get4l(entry,24) != psecurdata->hash) { + printf("** hash 0x%x (instead of 0x%x)\n", + (unsigned int)get4l(entry,24), + (unsigned int)psecurdata->hash); + errors++; + } + if (get8l(entry,32) != psecurdata->offset) { + printf("** offset 0x%llx (instead of 0x%llx)\n", + (long long)get8l(entry,32), + (long long)psecurdata->offset); + errors++; + } + if (get4l(entry,40) != psecurdata->length) { + printf("** length %ld (instead of %ld)\n", + (long)get4l(entry,40), + (long)psecurdata->length); + errors++; + } + } else { + printf("** Entry was not present in $SDS nor in $SII\n"); + errors++; + psecurdata->hash = get4l(entry,24); + psecurdata->offset = get8l(entry,32); + psecurdata->length = get4l(entry,40); + if (opt_v) { + printf(" offset 0x%llx\n",(long long)psecurdata->offset); + printf(" length %ld\n",(long)psecurdata->length); + } + errcnt++; + } + } + } else { + printf("** Security_id 0x%x out of bounds\n",key); + warnings++; + } + return (errcnt); +} + +/* + * Auditing of $SDH (Linux only) + */ + +int audit_sdh() +{ + char *entry; + int errcnt; + int count; + u32 prevkey; + u32 prevhash; + BOOL valid; + BOOL done; + + printf("\nAuditing $SDH\n"); + count = 0; + errcnt = 0; + prevkey = 0; + prevhash = 0; + entry = (char*)NULL; + done = FALSE; + do { + entry = (char*)ntfs_read_sdh(ntfs_context,(void*)entry); + if (entry) { + valid = valid_sdh(entry,prevkey,prevhash); + if (valid) { + count++; + errcnt += consist_sdh(entry); + prevhash = get4l(entry,16); + prevkey = get4l(entry,20); + } else + errcnt++; + } else + if ((errno == ENOTSUP) && !prevkey) + printf("** There is no $SDH in this volume\n"); + } while (entry && !done); + if (count || errcnt) { + printf("%d valid entries in $SDH\n",count); + printf("%d errors in $SDH\n",errcnt); + } + return (errcnt); +} + +/* + * Audit summary + */ + +void audit_summary() +{ + int count; + int flags; + int cnt; + int found; + int i,j; + + count = 0; + found = 0; + if (opt_r) printf("Summary of security key use :\n"); + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + if (securdata[i]) + for (j=0; j<(1 << SECBLKSZ); j++) { + flags = securdata[i][j].flags & (INSDS1 + INSDS2 + INSII + INSDH); + if (flags) found++; + if (flags + && (flags != (INSDS1 + INSDS2 + INSII + INSDH))) + { + if (!count && !opt_r) + printf("\n** Keys not present in all files :\n"); + cnt = securdata[i][j].filecount; + if (opt_r) + printf("Key 0x%x used by %d %s, not in", + i*(1 << SECBLKSZ)+j,cnt, + (cnt > 1 ? "files" : "file")); + else + printf("Key 0x%x not in", i*(1 << SECBLKSZ)+j); + if (!(flags & INSDS1)) + printf(" SDS-1"); + if (!(flags & INSDS2)) + printf(" SDS-2"); + if (!(flags & INSII)) + printf(" SII"); + if (!(flags & INSDH)) + printf(" SDH"); + printf("\n"); + count++; + } else { + cnt = securdata[i][j].filecount; + if (opt_r && cnt) + printf("Key 0x%x used by %d %s\n", + i*(1 << SECBLKSZ)+j,cnt, + (cnt > 1 ? "files" : "file")); + } + } + if (found) { + if (count) + printf("%d keys not present in all lists\n",count); + else + printf("All keys are present in all lists\n"); + } +} + +/* + * Auditing (Linux only) + */ + +BOOL audit(const char *volume) +{ + BOOL err; + + err = FALSE; + if (!getuid() && open_security_api()) { + if (open_volume(volume,MS_RDONLY)) { + if (audit_sds(FALSE)) err = TRUE; + if (audit_sds(TRUE)) err = TRUE; + if (audit_sii()) err = TRUE; + if (audit_sdh()) err = TRUE; + if (opt_r) recurseshow("/"); + + audit_summary(); + close_volume(volume); + } + else { + fprintf(stderr,"Could not open volume %s\n",volume); + printerror(stdout); + err = TRUE; + } + close_security_api(); + } + else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else fprintf(stderr,"Could not open security API\n"); + err = TRUE; + } + return (err); +} + +#endif + +#if POSIXACLS + +/* + * Encode a Posix ACL string + * [d:]{ugmo}:uid[:perms],... + */ + +struct POSIX_SECURITY *encode_posix_acl(const char *str) +{ + int acccnt; + int defcnt; + int i,k,l; + int c; + s32 id; + u16 perms; + u16 apermsset; + u16 dpermsset; + u16 tag; + u16 tagsset; + mode_t mode; + BOOL defacl; + BOOL dmask; + BOOL amask; + const char *p; + struct POSIX_ACL *acl; + struct POSIX_SECURITY *pxdesc; + enum { PXBEGIN, PXTAG, PXTAG1, PXID, PXID1, PXID2, + PXPERM, PXPERM1, PXPERM2, PXOCT, PXNEXT, PXEND, PXERR + } state; + + /* raw evaluation of ACE count */ + p = str; + amask = FALSE; + dmask = FALSE; + if (*p == 'd') { + acccnt = 0; + defcnt = 1; + } else { + if ((*p >= '0') && (*p <= '7')) + acccnt = 0; + else + acccnt = 1; + defcnt = 0; + } + while (*p) + if (*p++ == ',') { + if (*p == 'd') { + defcnt++; + if (p[1] && (p[2] == 'm')) + dmask = TRUE; + } else { + acccnt++; + if (*p == 'm') + amask = TRUE; + } + } + /* account for an implicit mask if none defined */ + if (acccnt && !amask) + acccnt++; + if (defcnt && !dmask) + defcnt++; + pxdesc = (struct POSIX_SECURITY*)malloc(sizeof(struct POSIX_SECURITY) + + (acccnt + defcnt)*sizeof(struct POSIX_ACE)); + if (pxdesc) { + pxdesc->acccnt = acccnt; + pxdesc->firstdef = acccnt; + pxdesc->defcnt = defcnt; + acl = &pxdesc->acl; + p = str; + state = PXBEGIN; + id = 0; + defacl = FALSE; + mode = 0; + apermsset = 0; + dpermsset = 0; + tag = 0; + perms = 0; + k = l = 0; + c = *p++; + while ((state != PXEND) && (state != PXERR)) { + switch (state) { + case PXBEGIN : + if (c == 'd') { + defacl = TRUE; + state = PXTAG1; + break; + } else + if ((c >= '0') && (c <= '7')) { + mode = c - '0'; + state = PXOCT; + break; + } + defacl = FALSE; + /* fall through */ + case PXTAG : + switch (c) { + case 'u' : + tag = POSIX_ACL_USER; + state = PXID; + break; + case 'g' : + tag = POSIX_ACL_GROUP; + state = PXID; + break; + case 'o' : + tag = POSIX_ACL_OTHER; + state = PXID; + break; + case 'm' : + tag = POSIX_ACL_MASK; + state = PXID; + break; + default : + state = PXERR; + break; + } + break; + case PXTAG1 : + if (c == ':') + state = PXTAG; + else + state = PXERR; + break; + case PXID : + if (c == ':') { + if ((tag == POSIX_ACL_OTHER) + || (tag == POSIX_ACL_MASK)) + state = PXPERM; + else + state = PXID1; + } else + state = PXERR; + break; + case PXID1 : + if ((c >= '0') && (c <= '9')) { + id = c - '0'; + state = PXID2; + } else + if (c == ':') { + id = -1; + if (tag == POSIX_ACL_USER) + tag = POSIX_ACL_USER_OBJ; + if (tag == POSIX_ACL_GROUP) + tag = POSIX_ACL_GROUP_OBJ; + state = PXPERM1; + } else + state = PXERR; + break; + case PXID2 : + if ((c >= '0') && (c <= '9')) + id = 10*id + c - '0'; + else + if (c == ':') + state = PXPERM1; + else + state = PXERR; + break; + case PXPERM : + if (c == ':') { + id = -1; + state = PXPERM1; + } else + state = PXERR; + break; + case PXPERM1 : + if ((c >= '0') && (c <= '7')) { + perms = c - '0'; + state = PXNEXT; + break; + } + state = PXPERM2; + perms = 0; + /* fall through */ + case PXPERM2 : + switch (c) { + case 'r' : + perms |= POSIX_PERM_R; + break; + case 'w' : + perms |= POSIX_PERM_W; + break; + case 'x' : + perms |= POSIX_PERM_X; + break; + case ',' : + case '\0' : + if (defacl) { + i = acccnt + l++; + dpermsset |= perms; + } else { + i = k++; + apermsset |= perms; + } + acl->ace[i].tag = tag; + acl->ace[i].perms = perms; + acl->ace[i].id = id; + if (c == '\0') + state = PXEND; + else + state = PXBEGIN; + break; + } + break; + case PXNEXT : + if (!c || (c == ',')) { + if (defacl) { + i = acccnt + l++; + dpermsset |= perms; + } else { + i = k++; + apermsset |= perms; + } + acl->ace[i].tag = tag; + acl->ace[i].perms = perms; + acl->ace[i].id = id; + if (c == '\0') + state = PXEND; + else + state = PXBEGIN; + } else + state = PXERR; + break; + case PXOCT : + if ((c >= '0') && (c <= '7')) + mode = (mode << 3) + c - '0'; + else + if (c == '\0') + state = PXEND; + else + state = PXBEGIN; + break; + default : + break; + } + c = *p++; + } + /* insert default mask if none defined */ + if (acccnt && !amask) { + i = k++; + acl->ace[i].tag = POSIX_ACL_MASK; + acl->ace[i].perms = apermsset; + acl->ace[i].id = -1; + } + if (defcnt && !dmask) { + i = acccnt + l++; + acl->ace[i].tag = POSIX_ACL_MASK; + acl->ace[i].perms = dpermsset; + acl->ace[i].id = -1; + } + /* compute the mode and tagsset */ + tagsset = 0; + for (i=0; iace[i].tag; + switch (acl->ace[i].tag) { + case POSIX_ACL_USER_OBJ : + mode |= acl->ace[i].perms << 6; + break; + case POSIX_ACL_GROUP_OBJ : + mode |= acl->ace[i].perms << 3; + break; + case POSIX_ACL_OTHER : + mode |= acl->ace[i].perms; + break; + default : + break; + } + pxdesc->mode = mode; + pxdesc->tagsset = tagsset; + pxdesc->acl.version = POSIX_VERSION; + pxdesc->acl.flags = 0; + pxdesc->acl.filler = 0; + if (state != PXERR) + ntfs_sort_posix(pxdesc); +showposix(pxdesc); + if ((state == PXERR) + || (k != acccnt) + || (l != defcnt) + || !ntfs_valid_posix(pxdesc)) { + if (~pxdesc->tagsset + & (POSIX_ACL_USER_OBJ | POSIX_ACL_GROUP_OBJ | POSIX_ACL_OTHER)) + fprintf(stderr,"User, group or other permissions missing\n"); + else + fprintf(stderr,"Bad ACL description\n"); + free(pxdesc); + pxdesc = (struct POSIX_SECURITY*)NULL; + } else + if (opt_v >= 2) { + printf("Interpreted input description :\n"); + showposix(pxdesc); + } + } else + errno = ENOMEM; + return (pxdesc); +} + +#endif /* POSIXACLS */ + + +int getoptions(int argc, char *argv[]) +{ + int xarg; + int narg; + const char *parg; + BOOL err; + + opt_a = FALSE; + opt_b = FALSE; + opt_e = FALSE; + opt_h = FALSE; +#if FORCEMASK + opt_m = FALSE; +#endif + opt_r = FALSE; + opt_s = FALSE; +#if SELFTESTS & !USESTUBS + opt_t = FALSE; +#endif + opt_v = 0; + xarg = 1; + err = FALSE; + while ((xarg < argc) && (argv[xarg][0] == '-')) { + parg = argv[xarg++]; + while (*++parg) + switch (*parg) + { +#ifndef WIN32 + case 'a' : + opt_a = TRUE; + break; +#endif + case 'b' : + opt_b = TRUE; + break; + case 'e' : + opt_e = TRUE; + break; + case 'h' : + opt_h = TRUE; + break; +#if FORCEMASK + case 'm' : + opt_m = TRUE; + break; +#endif + case 'r' : + case 'R' : + opt_r = TRUE; + break; + case 's' : + opt_s = TRUE; + break; +#if SELFTESTS & !USESTUBS + case 't' : + opt_t = TRUE; + break; +#endif + case 'v' : + opt_v++; + break; + default : + fprintf(stderr,"Invalid option -%c\n",*parg); + err = TRUE; + } + } + narg = argc - xarg; +#ifdef WIN32 + if ( ((opt_h || opt_s) && (narg > 1)) + || ((opt_r || opt_b) && ((narg < 1) || (narg > 2))) +#if SELFTESTS & !USESTUBS + || (opt_t && (narg > 0)) +#endif + || (opt_e && !opt_s) + || (!opt_h && !opt_r && !opt_b && !opt_s +#if SELFTESTS & !USESTUBS + && !opt_t +#endif + && ((narg < 1) || (narg > 2)))) + + err = TRUE; + if (err) { + xarg = 0; + fprintf(stderr,"Usage:\n"); +#if SELFTESTS & !USESTUBS + fprintf(stderr," secaudit -t\n"); + fprintf(stderr," run self-tests\n"); +#endif + fprintf(stderr," secaudit -h [file]\n"); + fprintf(stderr," display security descriptors within file\n"); + fprintf(stderr," secaudit [-v] file\n"); + fprintf(stderr," display the security parameters of file\n"); + fprintf(stderr," secaudit -r[v] directory\n"); + fprintf(stderr," display the security parameters of files in directory\n"); + fprintf(stderr," secaudit -b[v] directory\n"); + fprintf(stderr," backup the security parameters of files in directory\n"); + fprintf(stderr," secaudit -s[ev] [backupfile]\n"); + fprintf(stderr," set the security parameters as indicated in backup file\n"); + fprintf(stderr," with -e also set extra parameters (Windows attrib)\n"); + fprintf(stderr," secaudit perms file\n"); + fprintf(stderr," set the security parameters of file to perms\n"); + fprintf(stderr," secaudit -r[v] perms directory\n"); + fprintf(stderr," set the security parameters of files in directory to perms\n"); +#if POSIXACLS + fprintf(stderr," Note: perms can be an octal mode or a Posix ACL description\n"); +#else + fprintf(stderr," Note: perms is an octal mode\n"); +#endif + fprintf(stderr," -v is for verbose, -vv for very verbose\n"); + } +#else + if ( (opt_h && (narg > 1)) + || (opt_a && (narg != 1)) + || ((opt_r || opt_b || opt_s) && ((narg < 1) || (narg > 3))) +#if SELFTESTS & !USESTUBS + || (opt_t && (narg > 0)) +#endif + || (opt_e && !opt_s) + || (!opt_h && !opt_a && !opt_r && !opt_b && !opt_s +#if SELFTESTS & !USESTUBS + && !opt_t +#endif +#ifdef HAVE_SETXATTR + && ((narg < 1) || (narg > 3)))) +#else + && ((narg < 2) || (narg > 3)))) +#endif + err = TRUE; + if (err) { + xarg = 0; + fprintf(stderr,"Usage:\n"); +#if SELFTESTS & !USESTUBS + fprintf(stderr," secaudit -t\n"); + fprintf(stderr," run self-tests\n"); +#endif + fprintf(stderr," secaudit -h [file]\n"); + fprintf(stderr," display security descriptors within file\n"); + fprintf(stderr," secaudit -a[rv] volume\n"); + fprintf(stderr," audit the volume\n"); + fprintf(stderr," secaudit [-v] volume file\n"); + fprintf(stderr," display the security parameters of file\n"); + fprintf(stderr," secaudit -r[v] volume directory\n"); + fprintf(stderr," display the security parameters of files in directory\n"); + fprintf(stderr," secaudit -b[v] volume directory\n"); + fprintf(stderr," backup the security parameters of files in directory\n"); + fprintf(stderr," secaudit -s[ev] volume [backupfile]\n"); + fprintf(stderr," set the security parameters as indicated in backup file\n"); + fprintf(stderr," with -e also set extra parameters (Windows attrib)\n"); + fprintf(stderr," secaudit volume perms file\n"); + fprintf(stderr," set the security parameters of file to perms\n"); + fprintf(stderr," secaudit -r[v] volume perms directory\n"); + fprintf(stderr," set the security parameters of files in directory to perms\n"); + fprintf(stderr," special case, does not require being root :\n"); + fprintf(stderr," secaudit [-v] mounted-file\n"); + fprintf(stderr," display the security parameters of a mounted file\n"); +#if POSIXACLS + fprintf(stderr," Note: perms can be an octal mode or a Posix ACL description\n"); +#else + fprintf(stderr," Note: perms is an octal mode\n"); +#endif + fprintf(stderr," -v is for verbose, -vv for very verbose\n"); + } +#endif + if ((sizeof(SID) != 12) && !err) { + fprintf(stderr,"Possible alignment problem, check your compiler options\n"); + err = TRUE; + xarg = 0; + } + return (xarg); +} + +/* + * Memory allocation with checks + */ + +#undef malloc +#undef calloc +#undef free +#undef isalloc + +void dumpalloc(const char *txt) +{ + struct CHKALLOC *q; + + if (firstalloc) { + printf("alloc table at %s\n",txt); + for (q=firstalloc; q; q=q->next) + printf("%08lx : %u bytes at %08lx allocated at %s line %d\n", + (long)q,(unsigned int)q->size, + (long)q->alloc,q->file,q->line); + } +} + +void *chkmalloc(size_t size, const char *file, int line) +{ + void *p; + struct CHKALLOC *q; + + p = (void*)malloc(size+1); + if (p) { + ((unsigned char*)p)[size] = 0xaa; + q = (struct CHKALLOC*)malloc(sizeof(struct CHKALLOC)); + if (q) { + q->next = firstalloc; + q->alloc = p; + q->size = size; + q->file = file; + q->line = line; + firstalloc = q; + } + } + return (p); +} + +void *chkcalloc(size_t cnt, size_t size, const char *file, int line) +{ + return (chkmalloc(cnt*size,file,line)); +} + +void chkfree(void *p, const char *file, int line) +{ + struct CHKALLOC *q; + struct CHKALLOC *r; + + if (p) { + if (firstalloc && (firstalloc->alloc == p)) { + r = firstalloc; + firstalloc = firstalloc->next; + } else { + q = firstalloc; + if (q) + while (q->next && (q->next->alloc != p)) + q = q->next; + if (q && q->next) { + r = q->next; + q->next = r->next; + } else { + r = (struct CHKALLOC*)NULL; + printf("** freeing unallocated memory in %s line %d\n",file,line); + if (!isatty(1)) + fprintf(stderr,"** freeing unallocated memory in %s line %d\n",file,line); + } + } + if (r) { + if (((unsigned char*)p)[r->size] != 0xaa) { + printf("** memory corruption, alloc in %s line %d release in %s %d\n", + r->file,r->line,file,line); + if (!isatty(1)) + fprintf(stderr,"** memory corruption, alloc in %s line %d release in %s %d\n", + r->file,r->line,file,line); + } + memset(p,0xaa,r->size); + free(r); + free(p); + } + } +} + +void stdfree(void *p) +{ + free(p); +} + +BOOL chkisalloc(void *p, const char *file, int line) +{ + struct CHKALLOC *q; + + if (p) { + q = firstalloc; + while (q && (q->alloc != p)) + q = q->next; + } else + q = (struct CHKALLOC*)NULL; + if (!p || !q) { + printf("error in %s %d : 0x%lx not allocated\n",file,line,(long)p); + } + return (p && q); +} + + + + +#ifdef WIN32 + +/* + * Windows version + */ + +main(argc,argv) +int argc; +char *argv[]; +{ + FILE *fd; + int xarg; + int mode; + unsigned int size; + BOOL cmderr; + char *filename; + const char *p; + int i; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + + printf("%s\n",BANNER); + cmderr = FALSE; + errors = 0; + warnings = 0; + xarg = getoptions(argc,argv); + if (xarg) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; +#if POSIXACLS + context.mapping[MAPUSERS] = (struct MAPPING*)NULL; + context.mapping[MAPGROUPS] = (struct MAPPING*)NULL; +#endif + firstalloc = (struct CHKALLOC*)NULL; + mappingtype = MAPNONE; + switch (argc - xarg) { + case 0 : + if (opt_h) + showhex(stdin); + else + if (opt_s) + restore(stdin); +#if SELFTESTS & !USESTUBS + if (opt_t) + selftests(); +#endif + break; + case 1 : + if (opt_h || opt_s) { + fd = fopen(argv[xarg],"r"); + if (fd) { + if (opt_h) + showhex(fd); + else + restore(fd); + fclose(fd); + } else { + fprintf(stderr,"Could not open %s\n",argv[xarg]); + cmderr = TRUE; + } + } else { + size = utf16size(argv[xarg]); + if (size) { + filename = (char*)malloc(2*size + 2); + if (filename) { + makeutf16(filename,argv[xarg]); +#if POSIXACLS + if (local_build_mapping(context.mapping,filename)) { + printf("*** Could not get user mapping data\n"); + warnings++; + } +#endif + if (opt_b) + cmderr = backup(filename); + else { + if (opt_r) + cmderr = listfiles(filename); + else + cmderr = singleshow(filename); + } +#if POSIXACLS + ntfs_free_mapping(context.mapping); +#endif + free(filename); + } else { + fprintf(stderr,"No more memory\n"); + cmderr = TRUE; + } + } else { + fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg]); + cmderr = TRUE; + } + } + break; + case 2 : + mode = 0; + p = argv[xarg]; +#if POSIXACLS + pxdesc = encode_posix_acl(p); + if (pxdesc) { + size = utf16size(argv[xarg + 1]); + if (size) { + filename = (char*)malloc(2*size + 2); + if (filename) { + makeutf16(filename,argv[xarg + 1]); + if (local_build_mapping(context.mapping,filename)) { + printf("*** Could not get user mapping data\n"); + warnings++; + } + if (opt_r) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; + recurseset_posix(filename,pxdesc); + } else + singleset_posix(filename,pxdesc); + ntfs_free_mapping(context.mapping); + free(filename); + } else { + fprintf(stderr,"No more memory\n"); + cmderr = TRUE; + } + chkfree(pxdesc,__FILE__,__LINE__); + } else { + fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg + 1]); + cmderr = TRUE; + } + } +#else + while ((*p >= '0') && (*p <= '7')) + mode = (mode << 3) + (*p++) - '0'; + if (*p) { + fprintf(stderr,"New mode should be given in octal\n"); + cmderr = TRUE; + } else { + size = utf16size(argv[xarg + 1]); + if (size) { + filename = (char*)malloc(2*size + 2); + if (filename) { + makeutf16(filename,argv[xarg + 1]); +#if POSIXACLS + if (local_build_mapping(&context,filename)) { + printf("*** Could not get user mapping data\n"); + warnings++; + } +#endif + if (opt_r) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; + recurseset(filename,mode); + } else + singleset(filename,mode); + free(filename); + } else { + fprintf(stderr,"No more memory\n"); + cmderr = TRUE; + } + } else { + fprintf(stderr,"Bad UTF-8 name \"%s\"\n",argv[xarg + 1]); + cmderr = TRUE; + } + } +#endif + break; +#if FORCEMASK + case 3 : + mode = 0; + forcemsk = 0; + p = argv[xarg]; + while (*p) { + if ((*p >= '0') && (*p <= '9')) + forcemsk = (forcemsk << 4) + *p - '0'; + else forcemsk = (forcemsk << 4) + (*p & 7) + 9; + p++; + } + p = argv[xarg + 1]; + while ((*p >= '0') && (*p <= '7')) + mode = (mode << 3) + (*p++) - '0'; + if (*p) { + fprintf(stderr,"New mode should be given in octal\n"); + cmderr = TRUE; + } else { + if (opt_r) { + recurseset(argv[xarg + 2],mode); + } + else singleset(argv[xarg + 2],mode); + } + break; +#endif + } + if (warnings) + printf("** %u %s signalled\n",warnings, + (warnings > 1 ? "warnings were" : "warning was")); + if (errors) + printf("** %u %s found\n",errors, + (errors > 1 ? "errors were" : "error was")); + else + printf("No errors were found\n"); + if (!isatty(1)) { + fflush(stdout); + if (warnings) + fprintf(stderr,"** %u %s signalled\n",warnings, + (warnings > 1 ? "warnings were" : "warning was")); + if (errors) + fprintf(stderr,"** %u %s found\n",errors, + (errors > 1 ? "errors were" : "error was")); + else + fprintf(stderr,"No errors were found\n"); + freeblocks(); + } + } + dumpalloc("termination"); + if (cmderr || errors) + exit(1); + return (0); +} + +#else + +/* + * Linux version + */ + +int main(int argc, char *argv[]) +{ + FILE *fd; + unsigned int mode; + const char *p; + int xarg; + BOOL cmderr; + int i; +#if POSIXACLS + struct POSIX_SECURITY *pxdesc; +#endif + + printf("%s\n",BANNER); + cmderr = FALSE; + errors = 0; + warnings = 0; + xarg = getoptions(argc,argv); + if (xarg) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; +#if POSIXACLS + context.mapping[MAPUSERS] = (struct MAPPING*)NULL; + context.mapping[MAPGROUPS] = (struct MAPPING*)NULL; +#endif + firstalloc = (struct CHKALLOC*)NULL; + mappingtype = MAPNONE; + switch (argc - xarg) { + case 0 : + if (opt_h) + showhex(stdin); +#if SELFTESTS & !USESTUBS + if (opt_t) + selftests(); +#endif + break; + case 1 : + if (opt_a) + cmderr = audit(argv[xarg]); + else + if (opt_h) { + fd = fopen(argv[xarg],"rb"); + if (fd) { + showhex(fd); + fclose(fd); + } else { + fprintf(stderr,"Could not open %s\n",argv[xarg]); + cmderr = TRUE; + } + } else + if (opt_b) + cmderr = backup(argv[xarg],"/"); + else + if (opt_r) + cmderr = listfiles(argv[xarg],"/"); + else + if (opt_s) + cmderr = dorestore(argv[xarg],stdin); + else + showmounted(argv[xarg]); + break; + case 2 : + if (opt_b) + cmderr = backup(argv[xarg],argv[xarg+1]); + else + if (opt_s) { + fd = fopen(argv[xarg+1],"rb"); + if (fd) { + if (!dorestore(argv[xarg],fd)) + cmderr = TRUE; + fclose(fd); + } else { + fprintf(stderr,"Could not open %s\n",argv[xarg]); + cmderr = TRUE; + } + } else + cmderr = listfiles(argv[xarg],argv[xarg+1]); + break; + case 3 : + mode = 0; + p = argv[xarg+1]; +#if POSIXACLS + pxdesc = encode_posix_acl(p); + if (pxdesc) { + if (!getuid() && open_security_api()) { + if (open_volume(argv[xarg],MS_NONE)) { + if (opt_r) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; + recurseset_posix(argv[xarg + 2],pxdesc); + } else + singleset_posix(argv[xarg + 2],pxdesc); + close_volume(argv[xarg]); + } else { + fprintf(stderr,"Could not open volume %s\n",argv[xarg]); + printerror(stderr); + cmderr = TRUE; + } + close_security_api(); + } else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else + fprintf(stderr,"Could not open security API\n"); + cmderr = TRUE; + } + chkfree(pxdesc,__FILE__,__LINE__); + } else + cmderr = TRUE; +#else + while ((*p >= '0') && (*p <= '7')) + mode = (mode << 3) + (*p++) - '0'; + if (*p) { + fprintf(stderr,"New mode should be given in octal\n"); + cmderr = TRUE; + } else + if (!getuid() && open_security_api()) { + if (open_volume(argv[xarg],MS_NONE)) { + if (opt_r) { + for (i=0; i<(MAXSECURID + (1 << SECBLKSZ) - 1)/(1 << SECBLKSZ); i++) + securdata[i] = (struct SECURITY_DATA*)NULL; + recurseset(argv[xarg + 2],mode); + } else + singleset(argv[xarg + 2],mode); + close_volume(argv[xarg]); + } else { + fprintf(stderr,"Could not open volume %s\n",argv[xarg]); + printerror(stderr); + cmderr = TRUE; + } + close_security_api(); + } else { + if (getuid()) + fprintf(stderr,"This is only possible as root\n"); + else + fprintf(stderr,"Could not open security API\n"); + cmderr = TRUE; + } +#endif + break; + } + if (warnings) + printf("** %u %s signalled\n",warnings, + (warnings > 1 ? "warnings were" : "warning was")); + if (errors) + printf("** %u %s found\n",errors, + (errors > 1 ? "errors were" : "error was")); + else + if (!cmderr) + printf("No errors were found\n"); + if (!isatty(1)) { + fflush(stdout); + if (warnings) + fprintf(stderr,"** %u %s signalled\n",warnings, + (warnings > 1 ? "warnings were" : "warning was")); + if (errors) + fprintf(stderr,"** %u %s found\n",errors, + (errors > 1 ? "errors were" : "error was")); + else + if (!cmderr) + fprintf(stderr,"No errors were found\n"); + } + freeblocks(); + } else + cmderr = TRUE; + dumpalloc("termination"); + if (cmderr || errors) + exit(1); + return (0); +} + +#endif diff --git a/release/src/router/ntfs-3g/src/secaudit.h b/release/src/router/ntfs-3g/src/secaudit.h new file mode 100644 index 0000000000..7f0d6da27c --- /dev/null +++ b/release/src/router/ntfs-3g/src/secaudit.h @@ -0,0 +1,731 @@ +/* + * General declarations for secaudit + * + * These declarations are organized to enable code sharing with ntfs-3g + * library, but should only be used to build tools runnable both + * on Linux (dynamic linking) and Windows (static linking) + * + * Copyright (c) 2007-2009 Jean-Pierre Andre + * + */ + +/* + * 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * General parameters which may have to be adapted to needs + */ + +#define SELFTESTS 1 /* include code for self-testing */ +#define POSIXACLS 0 /* include code for processing Posix ACLs */ +#define NOREVBOM 0 /* temporary */ + +#define OWNERFROMACL 1 /* must match option in security.c */ + +#define MAXATTRSZ 65536 /* Max sec attr size (16448 met for WinXP) */ +#define MAXSECURID 262144 +#define SECBLKSZ 8 +#define MAXFILENAME 4096 +#define FORCEMASK 0 /* Special (dangerous) option -m to force a mask */ +#define MAXLINE 80 /* maximum processed size of a line */ +#define BUFSZ 1024 /* buffer size to read mapping file */ +#define LINESZ 120 /* maximum useful size of a mapping line */ + +/* + * Definitions for Linux + * Use explicit or implicit dynamic linking + */ + +#ifdef HAVE_CONFIG_H +#undef POSIXACLS /* override default by configure option */ +#define USESTUBS 1 /* API stubs generated at link time */ +#else +#define USESTUBS 0 /* direct calls to API, based on following definitions */ +#define ENVNTFS3G "NTFS3G" +#define LIBFILE64 "/lib64/libntfs-3g.so.4921" +#define LIBFILE "/lib/libntfs-3g.so.4921" +#endif + +#define MAPDIR ".NTFS-3G" +#define MAPFILE "UserMapping" +#define MAGIC_API 0x09042009 + +#ifndef _NTFS_ENDIANS_H + +typedef char s8; +typedef short s16; +typedef long long s64; +typedef unsigned char u8; +typedef unsigned short le16, be16, u16; +typedef unsigned long long u64; +#ifdef STSC +typedef long s32; +typedef unsigned long le32, be32, u32; +#else +typedef int s32; +typedef unsigned int le32, be32, u32; +#endif + +#ifdef STSC +#define endian_rev16(x) ((((x) & 255L) << 8) + (((x) >> 8) & 255L)) +#define endian_rev32(x) ((((x) & 255L) << 24) + (((x) & 0xff00L) << 8) \ + + (((x) >> 8) & 0xff00L) + (((x) >> 24) & 255L)) +#else +#define endian_rev16(x) ((((x) & 255) << 8) + (((x) >> 8) & 255)) +#define endian_rev32(x) ((((x) & 255) << 24) + (((x) & 0xff00) << 8) \ + + (((x) >> 8) & 0xff00) + (((x) >> 24) & 255)) +#endif +#define endian_rev64(x) ((((x) & 255LL) << 56) + (((x) & 0xff00LL) << 40) \ + + (((x) & 0xff0000LL) << 24) + (((x) & 0xff000000LL) << 8) \ + + (((x) >> 8) & 0xff000000LL) + (((x) >> 24) & 0xff0000LL) \ + + (((x) >> 40) & 0xff00LL) + (((x) >> 56) & 255LL)) + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +#define cpu_to_be16(x) endian_rev16(x) +#define cpu_to_be32(x) endian_rev32(x) +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) +#define cpu_to_le64(x) (x) +#define le16_to_cpu(x) (x) +#define le32_to_cpu(x) (x) +#define le64_to_cpu(x) (x) + +#else + +#define cpu_to_be16(x) (x) +#define cpu_to_be32(x) (x) +#define cpu_to_le16(x) endian_rev16(x) +#define cpu_to_le32(x) endian_rev32(x) +#define cpu_to_le64(x) endian_rev64(x) +#define le16_to_cpu(x) endian_rev16(x) +#define le32_to_cpu(x) endian_rev32(x) +#define le64_to_cpu(x) endian_rev64(x) + +#endif + +#define const_le16_to_cpu(x) le16_to_cpu(x) +#define const_cpu_to_le16(x) cpu_to_le16(x) +#define const_cpu_to_le32(x) cpu_to_le32(x) +#define const_cpu_to_be16(x) cpu_to_be16(x) +#define const_cpu_to_be32(x) cpu_to_be32(x) + +#endif /* _NTFS_ENDIANS_H */ + +#ifndef FALSE +enum { FALSE, TRUE } ; +#endif /* FALSE */ + +#ifdef WIN32 + +typedef unsigned short uid_t; +typedef unsigned short gid_t; + +#define UNICODE(c) ((unsigned short)(c)) + +#define __attribute__(x) + +#else + +#ifndef BOOL +typedef int BOOL; /* Already defined in windows.h */ +#endif /* BOOL */ + +#ifdef STSC + +#define ENOTSUP 95 + +#endif /* STSC */ + +typedef u32 DWORD; /* must be 32 bits whatever the platform */ +typedef DWORD *LPDWORD; + +#define MS_NONE 0 /* no flag for mounting the device */ +#define MS_RDONLY 1 /* flag for mounting the device read-only */ + +#endif /* WIN32 */ + +#if defined(WIN32) | defined(STSC) + +/* + * On non-Linux computers, there is no mount and the user mapping + * if fetched from a real file (or a dummy one for self tests) + */ + +#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf) +#define NTFS_FIND_GSID(map,gid,buf) ntfs_find_gsid(map,gid,buf) +#define NTFS_FIND_USER(map,usid) ntfs_find_user(map,usid) +#define NTFS_FIND_GROUP(map,gsid) ntfs_find_group(map,gsid) + +#else + +/* + * On Linux computers, there is a mount and the user mapping + * if either obtained through the mount process or fetched + * from a dummy file for self-tests + */ + +#define NTFS_FIND_USID(map,uid,buf) (mappingtype != MAPEXTERN ? \ + ntfs_find_usid(map,uid,buf) : relay_find_usid(map,uid,buf)) +#define NTFS_FIND_GSID(map,gid,buf) (mappingtype != MAPEXTERN ? \ + ntfs_find_gsid(map,gid,buf) : relay_find_gsid(map,gid,buf)) +#define NTFS_FIND_USER(map,usid) (mappingtype != MAPEXTERN ? \ + ntfs_find_user(map,usid) : relay_find_user(map,usid)) +#define NTFS_FIND_GROUP(map,gsid) (mappingtype != MAPEXTERN ? \ + ntfs_find_group(map,gsid) : relay_find_group(map,gsid)) + +#endif + +/* + * A few name hijackings or definitions + * needed for using code from ntfs-3g + */ + +#ifdef WIN32 +#define ACL MY_ACL +#define SID MY_SID +#define ACCESS_ALLOWED_ACE MY_ACCESS_ALLOWED_ACE +#define ACCESS_DENIED_ACE MY_ACCESS_DENIED_ACE +#define FILE_ATTRIBUTE_REPARSE_POINT 0x400 +#define IO_REPARSE_TAG_MOUNT_POINT 0xa0000003 +#define IO_REPARSE_TAG_SYMLINK 0xa000000c +#else +#define SE_OWNER_DEFAULTED const_cpu_to_le16(1) +#define SE_GROUP_DEFAULTED const_cpu_to_le16(2) +#define SE_DACL_PRESENT const_cpu_to_le16(4) +#define SE_SACL_PRESENT const_cpu_to_le16(0x10) +#define SE_DACL_DEFAULTED const_cpu_to_le16(8) +#define SE_SELF_RELATIVE const_cpu_to_le16(0x8000) +#define SID_REVISION 1 +#endif /* WIN32 */ +#define SE_DACL_PROTECTED const_cpu_to_le16(0x1000) +#define SE_SACL_PROTECTED const_cpu_to_le16(0x2000) +#define SE_DACL_AUTO_INHERITED const_cpu_to_le16(0x400) +#define SE_SACL_AUTO_INHERITED const_cpu_to_le16(0x800) +#define SE_DACL_AUTO_INHERIT_REQ cpu_to_le16(0x100) +#define SE_SACL_AUTO_INHERIT_REQ cpu_to_le16(0x200) + +typedef le16 ntfschar; + +typedef struct { + le32 a; + le16 b,c; + struct { + le16 m,n,o,p, q,r,s,t; + } ; +} GUID; + +#define ntfs_log_error(args...) do { printf("** " args); if (!isatty(1)) fprintf(stderr,args); } while(0) + +/* + * Struct to hold the input mapping file + * (private to this module) + */ + +struct MAPLIST { + struct MAPLIST *next; + char *uidstr; /* uid text from the same record */ + char *gidstr; /* gid text from the same record */ + char *sidstr; /* sid text from the same record */ + char maptext[LINESZ + 1]; +}; + +/* + * A few dummy declarations needed for using code from security.c + */ + +#define MFT_RECORD_IS_DIRECTORY const_cpu_to_le16(1) + +struct SECURITY_DATA { + u64 offset; + char *attr; + u32 hash; + u32 length; + unsigned int filecount:16; + unsigned int mode:12; + unsigned int flags:4; +} ; + +#define AUTH1 3141592653U +#define AUTH2 589793238 +#define AUTH3 462843383 +#define OWNERID 1016 +#define GROUPID 513 + + +#define INSDS1 1 +#define INSDS2 2 +#define INSII 4 +#define INSDH 8 + +#ifdef WIN32 + +typedef enum { RECSHOW, RECSET, RECSETPOSIX } RECURSE; + +#endif + +/* + * A type large enough to hold any SID + */ + +typedef char BIGSID[40]; + +/* + * Declarations for memory allocation checks + */ + +struct CHKALLOC + { + struct CHKALLOC *next; + void *alloc; + const char *file; + int line; + size_t size; + } ; + +#if defined(WIN32) | defined(STSC) + +#define S_ISVTX 01000 +#define S_ISGID 02000 +#define S_ISUID 04000 +#define S_IXUSR 0100 +#define S_IWUSR 0200 +#define S_IRUSR 0400 +#define S_IXGRP 010 +#define S_IWGRP 020 +#define S_IRGRP 040 +#define S_IXOTH 001 +#define S_IWOTH 002 +#define S_IROTH 004 + +#endif + +#ifdef WIN32 +#else +/* + * + * See http://msdn2.microsoft.com/en-us/library/aa379649.aspx + */ + +typedef enum { + DACL_SECURITY_INFORMATION = 4, // The DACL of the object is being referenced. + SACL_SECURITY_INFORMATION = 8, // The SACL of the object is being referenced. + LABEL_SECURITY_INFORMATION = 8, // The mandatory integrity label is being referenced. + GROUP_SECURITY_INFORMATION = 2, // The primary group identifier of the object is being referenced. + OWNER_SECURITY_INFORMATION = 1, // The owner identifier of the object is being referenced. +} SECURITY_INFORMATION; + +#define STANDARD_RIGHTS_READ cpu_to_le32(0x20000) +#define STANDARD_RIGHTS_WRITE cpu_to_le32(0x20000) +#define STANDARD_RIGHTS_EXECUTE cpu_to_le32(0x20000) +#define STANDARD_RIGHTS_REQUIRED cpu_to_le32(0xf0000) + +#endif + +typedef struct SECHEAD { + s8 revision; + s8 alignment; + le16 control; + le32 owner; + le32 group; + le32 sacl; + le32 dacl; +} SECURITY_DESCRIPTOR_RELATIVE; + +typedef struct ACL { + s8 revision; + s8 alignment1; + le16 size; + le16 ace_count; + le16 alignment2; +} ACL; + +typedef struct { + union { + struct { + unsigned char revision; + unsigned char sub_authority_count; + } ; + struct { + /* evade an alignment problem when a 4 byte field */ + /* in a struct implies alignment of the struct */ + le16 dummy; + be16 high_part; + be32 low_part; + } identifier_authority; + } ; + le32 sub_authority[1]; +} SID; + +typedef u8 ACE_FLAGS; + +typedef struct ACE { + u8 type; + u8 flags; + le16 size; + le32 mask; + SID sid; +} ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE; + + +/* + * item in the mapping list + */ + +struct MAPPING { + struct MAPPING *next; + int xid; /* linux id : uid or gid */ + SID *sid; /* Windows id : usid or gsid */ + int grcnt; /* group count (for users only) */ + gid_t *groups; /* groups which the user is member of */ +}; + +/* + * Posix ACL structures + */ + +struct POSIX_ACE { + u16 tag; + u16 perms; + s32 id; +} ; + +struct POSIX_ACL { + u8 version; + u8 flags; + u16 filler; + struct POSIX_ACE ace[0]; +} ; + +struct POSIX_SECURITY { + mode_t mode; + int acccnt; + int defcnt; + int firstdef; + u16 tagsset; + struct POSIX_ACL acl; +} ; + +/* + * Posix tags, cpu-endian 16 bits + */ + +enum { + POSIX_ACL_USER_OBJ = 1, + POSIX_ACL_USER = 2, + POSIX_ACL_GROUP_OBJ = 4, + POSIX_ACL_GROUP = 8, + POSIX_ACL_MASK = 16, + POSIX_ACL_OTHER = 32, + POSIX_ACL_SPECIAL = 64 /* internal use only */ +} ; + +/* + * Posix permissions, cpu-endian 16 bits + */ + +enum { + POSIX_PERM_X = 1, + POSIX_PERM_W = 2, + POSIX_PERM_R = 4, + POSIX_PERM_DENIAL = 64 /* internal use only */ +} ; + +#define POSIX_VERSION 2 + +/* + * A few definitions adapted from winnt.h + * (Windows version uses actual definitions from winnt.h, which are + * not compatible with code from security.c on a big-endian computer) + */ + +#ifndef WIN32 + +#define DELETE cpu_to_le32(0x00010000L) +#define READ_CONTROL cpu_to_le32(0x00020000L) +#define WRITE_DAC cpu_to_le32(0x00040000L) +#define WRITE_OWNER cpu_to_le32(0x00080000L) +#define SYNCHRONIZE cpu_to_le32(0x00100000L) + + +#define FILE_READ_DATA cpu_to_le32( 0x0001 ) // file & pipe +#define FILE_LIST_DIRECTORY cpu_to_le32( 0x0001 ) // directory + +#define FILE_WRITE_DATA cpu_to_le32( 0x0002 ) // file & pipe +#define FILE_ADD_FILE cpu_to_le32( 0x0002 ) // directory + +#define FILE_APPEND_DATA cpu_to_le32( 0x0004 ) // file +#define FILE_ADD_SUBDIRECTORY cpu_to_le32( 0x0004 ) // directory +#define FILE_CREATE_PIPE_INSTANCE cpu_to_le32( 0x0004 ) // named pipe + + +#define FILE_READ_EA cpu_to_le32( 0x0008 ) // file & directory + +#define FILE_WRITE_EA cpu_to_le32( 0x0010 ) // file & directory + +#define FILE_EXECUTE cpu_to_le32( 0x0020 ) // file +#define FILE_TRAVERSE cpu_to_le32( 0x0020 ) // directory + +#define FILE_DELETE_CHILD cpu_to_le32( 0x0040 ) // directory + +#define FILE_READ_ATTRIBUTES cpu_to_le32( 0x0080 ) // all + +#define FILE_WRITE_ATTRIBUTES cpu_to_le32( 0x0100 ) // all + +#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ + cpu_to_le32(0x1FF)) + +#define FILE_GENERIC_READ (STANDARD_RIGHTS_READ |\ + FILE_READ_DATA |\ + FILE_READ_ATTRIBUTES |\ + FILE_READ_EA |\ + SYNCHRONIZE) + + +#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE |\ + FILE_WRITE_DATA |\ + FILE_WRITE_ATTRIBUTES |\ + FILE_WRITE_EA |\ + FILE_APPEND_DATA |\ + SYNCHRONIZE) + + +#define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE |\ + FILE_READ_ATTRIBUTES |\ + FILE_EXECUTE |\ + SYNCHRONIZE) + +#define GENERIC_READ cpu_to_le32(0x80000000L) +#define GENERIC_WRITE cpu_to_le32(0x40000000L) +#define GENERIC_EXECUTE cpu_to_le32(0x20000000L) +#define GENERIC_ALL cpu_to_le32(0x10000000L) + + +#define OBJECT_INHERIT_ACE (0x1) +#define CONTAINER_INHERIT_ACE (0x2) +#define NO_PROPAGATE_INHERIT_ACE (0x4) +#define INHERIT_ONLY_ACE (0x8) +#define VALID_INHERIT_FLAGS (0xF) + +/* + * Other useful definitions + */ + +#define ACL_REVISION 2 +#define ACCESS_ALLOWED_ACE_TYPE 0 +#define ACCESS_DENIED_ACE_TYPE 1 +#define SECURITY_DESCRIPTOR_REVISION 1 + +#endif /* !WIN32 */ + +#ifndef ACL_REVISION_DS /* not always defined in */ +#define ACL_REVISION_DS 4 +#endif + +/* + * Matching of ntfs permissions to Linux permissions + * these constants are adapted to endianness + * when setting, set them all + * when checking, check one is present + */ + + /* flags which are set to mean exec, write or read */ + +#define FILE_READ (FILE_READ_DATA) +#define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \ + | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) +#define FILE_EXEC (FILE_EXECUTE) +#define DIR_READ FILE_LIST_DIRECTORY +#define DIR_WRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD \ + | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) +#define DIR_EXEC (FILE_TRAVERSE) + + /* flags tested for meaning exec, write or read */ + /* tests for write allow for interpretation of a sticky bit */ + +#define FILE_GREAD (FILE_READ_DATA | GENERIC_READ) +#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE) +#define FILE_GEXEC (FILE_EXECUTE | GENERIC_EXECUTE) +#define DIR_GREAD (FILE_LIST_DIRECTORY | GENERIC_READ) +#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE) +#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE) + + /* standard owner (and administrator) rights */ + +#define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \ + | SYNCHRONIZE \ + | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \ + | FILE_READ_EA | FILE_WRITE_EA) + + /* standard world rights */ + +#define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \ + | SYNCHRONIZE) + + /* inheritance flags for files and directories */ + +#define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE +#define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE) + +/* + * To identify NTFS ACL meaning Posix ACL granted to root + * we use rights always granted to anybody, so they have no impact + * either on Windows or on Linux. + */ + +#define ROOT_OWNER_UNMARK SYNCHRONIZE /* ACL granted to root as owner */ +#define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */ + + +struct SII { /* this is an image of an $SII index entry */ + le16 offs; + le16 size; + le32 fill1; + le16 indexsz; + le16 indexksz; + le16 flags; + le16 fill2; + le32 keysecurid; + + /* did not find official description for the following */ + le32 hash; + le32 securid; + le32 dataoffsl; /* documented as badly aligned */ + le32 dataoffsh; + le32 datasize; +} ; + +struct SDH { /* this is an image of an $SDH index entry */ + le16 offs; + le16 size; + le32 fill1; + le16 indexsz; + le16 indexksz; + le16 flags; + le16 fill2; + le32 keyhash; + le32 keysecurid; + + /* did not find official description for the following */ + le32 hash; + le32 securid; + le32 dataoffsl; + le32 dataoffsh; + le32 datasize; + le32 fill3; + } ; + +#ifndef INVALID_FILE_ATTRIBUTES /* not defined in old windows.h */ +#define INVALID_FILE_ATTRIBUTES (-1) +#endif + +enum { MAPUSERS, MAPGROUPS, MAPCOUNT } ; + +struct SECURITY_CONTEXT { + struct MAPPING *mapping[MAPCOUNT]; +} ; + +typedef enum { MAPNONE, MAPEXTERN, MAPLOCAL, MAPDUMMY } MAPTYPE; + + + +struct passwd { + uid_t pw_uid; +} ; + +struct group { + gid_t gr_gid; +} ; + +typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos); + +/* + * Data defined in secaudit.c + */ + +extern MAPTYPE mappingtype; + +/* + * Functions defined in acls.c + */ + +BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz); +BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc); +BOOL ntfs_valid_pattern(const SID *sid); +BOOL ntfs_same_sid(const SID *first, const SID *second); + + +int ntfs_sid_size(const SID * sid); +unsigned int ntfs_attr_size(const char *attr); + +const SID *ntfs_find_usid(const struct MAPPING *usermapping, + uid_t uid, SID *pdefsid); +const SID *ntfs_find_gsid(const struct MAPPING *groupmapping, + gid_t gid, SID *pdefsid); +uid_t ntfs_find_user(const struct MAPPING *usermapping, const SID *usid); +gid_t ntfs_find_group(const struct MAPPING *groupmapping, const SID * gsid); +const SID *ntfs_acl_owner(const char *secattr); + +void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc); +int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode); + + +struct POSIX_SECURITY *ntfs_build_permissions_posix( + struct MAPPING* const mapping[], + const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir); +int ntfs_build_permissions(const char *securattr, + const SID *usid, const SID *gsid, BOOL isdir); +struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid); +struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem); +struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem); +void ntfs_free_mapping(struct MAPPING *mapping[]); + +struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first, + const struct POSIX_SECURITY *second); +char *ntfs_build_descr_posix(struct MAPPING* const mapping[], + struct POSIX_SECURITY *pxdesc, + int isdir, const SID *usid, const SID *gsid); +char *ntfs_build_descr(mode_t mode, + int isdir, const SID * usid, const SID * gsid); + +/* + * Functions defined in secaudit.c + */ + +void *chkmalloc(size_t, const char*, int); +void *chkcalloc(size_t, size_t, const char *, int); +void chkfree(void*, const char*, int); +BOOL chkisalloc(void*, const char*, int); +void dumpalloc(const char*); + +#define malloc(sz) chkmalloc(sz, __FILE__, __LINE__) +#define calloc(cnt,sz) chkcalloc(cnt, sz, __FILE__, __LINE__) +#define free(ptr) chkfree(ptr, __FILE__, __LINE__) +#define isalloc(ptr) chkisalloc(ptr, __FILE__, __LINE__) +#define ntfs_malloc(sz) chkmalloc(sz, __FILE__, __LINE__) + +struct passwd *getpwnam(const char *user); +struct group *getgrnam(const char *group); + +const SID *relay_find_usid(const struct MAPPING *usermapping, + uid_t uid, SID *pdefsid); +const SID *relay_find_gsid(const struct MAPPING *groupmapping, + gid_t gid, SID *pdefsid); +uid_t relay_find_user(const struct MAPPING *usermapping, const SID *usid); +gid_t relay_find_group(const struct MAPPING *groupmapping, const SID * gsid); + diff --git a/release/src/router/ntfs-3g/src/usermap.c b/release/src/router/ntfs-3g/src/usermap.c new file mode 100644 index 0000000000..847f651040 --- /dev/null +++ b/release/src/router/ntfs-3g/src/usermap.c @@ -0,0 +1,1333 @@ +/* + * Windows to Linux user mapping for ntfs-3g + * + * + * Copyright (c) 2007-2008 Jean-Pierre Andre + * + * A quick'n dirty program scanning owners of files in + * "c:\Documents and Settings" (and "c:\Users") + * and asking user to map them to Linux accounts + * + * History + * + * Sep 2007 + * - first version, limited to Win32 + * + * Oct 2007 + * - ported to Linux (rewritten would be more correct) + * + * Nov 2007 Version 1.0.0 + * - added more defaults + * + * Nov 2007 Version 1.0.1 + * - avoided examining files whose name begin with a '$' + * + * Jan 2008 Version 1.0.2 + * - moved user mapping file to directory .NTFS-3G (hidden for Linux) + * - fixed an error case in Windows version + * + * Nov 2008 Version 1.1.0 + * - fixed recursions for account in Linux version + * - searched owner in c:\Users (standard location for Vista) + * + * May 2009 Version 1.1.1 + * - reordered mapping records to limit usage of same SID for user and group + * - fixed decoding SIDs on 64-bit systems + * - fixed a pointer to dynamic data in mapping tables + * - fixed default mapping on Windows + * - fixed bug for renaming UserMapping on Windows + * + * May 2009 Version 1.1.2 + * - avoided selecting DOS names on Linux + */ + +/* + * 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 (in the main directory of the NTFS-3G + * distribution in the file COPYING); if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * General parameters which may have to be adapted to needs + */ + +#ifdef HAVE_CONFIG_H +#define USESTUBS 1 /* API stubs generated at link time */ +#else +#define USESTUBS 0 /* direct calls to API, based on following definitions */ +#define ENVNTFS3G "NTFS3G" +#define LIBFILE64 "/lib64/libntfs-3g.so.4921" +#define LIBFILE "/lib/libntfs-3g.so.4921" +#endif + +#define GET_FILE_SECURITY "ntfs_get_file_security" +#define SET_FILE_SECURITY "ntfs_set_file_security" +#define READ_DIRECTORY "ntfs_read_directory" +#define INIT_FILE_SECURITY "ntfs_initialize_file_security" +#define LEAVE_FILE_SECURITY "ntfs_leave_file_security" + +#define VERSION "1.1.2" +#define MAPDIR ".NTFS-3G" +#define MAPFILE "UserMapping" +#define MAXATTRSZ 2048 +#define MAXSIDSZ 80 +#define MAXNAMESZ 256 +#define OWNERS1 "Documents and Settings" +#define OWNERS2 "Users" + +/* + * Define WIN32 for a Windows execution + * may have to be adapted to compiler or something else + */ + +#ifndef WIN32 +#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC) +#define WIN32 1 +#endif +#endif + +#ifdef WIN32 +#define BANNER "Generated by usermap for Windows, v " VERSION +#else +#define BANNER "Generated by usermap for Linux, v " VERSION +#endif + + +#include +#include +#include +#include +#include +#include +#include + +/* + * Define the security API according to platform + */ + +#ifdef WIN32 + +#include +#include + +#define STATIC + +typedef enum { false, true } boolean; + +#else + +#include +#include + +typedef enum { false, true } boolean, BOOL; +typedef unsigned int DWORD; /* must be 32 bits whatever the platform */ +typedef DWORD *LPDWORD; + +enum { OWNER_SECURITY_INFORMATION = 1, + GROUP_SECURITY_INFORMATION = 2, + DACL_SECURITY_INFORMATION = 4, + SACL_SECURITY_INFORMATION = 8 +} ; + +struct CALLBACK { + const char *accname; + const char *dir; + int levels; + int docset; +} ; + +typedef int (*dircallback)(struct CALLBACK *context, char *ntfsname, + int length, int type, long long pos, unsigned long long mft_ref, + unsigned int dt_type); + +#if USESTUBS + +#define STATIC static + +BOOL ntfs_get_file_security(void *scapi, + const char *path, DWORD selection, + char *buf, DWORD buflen, LPDWORD psize); +BOOL ntfs_set_file_security(void *scapi, + const char *path, DWORD selection, const char *attr); +BOOL ntfs_read_directory(void *scapi, + const char *path, dircallback callback, void *context); +void *ntfs_initialize_file_security(const char *device, + int flags); +BOOL ntfs_leave_file_security(void *scapi); + +#else + +#define STATIC + +BOOL (*ntfs_get_file_security)(void *scapi, + const char *path, DWORD selection, + char *buf, DWORD buflen, LPDWORD psize); +BOOL (*ntfs_set_file_security)(void *scapi, + const char *path, DWORD selection, const char *attr); +BOOL (*ntfs_read_directory)(void *scapi, + const char *path, dircallback callback, void *context); +void *(*ntfs_initialize_file_security)(const char *device, + int flags); +BOOL (*ntfs_leave_file_security)(void *scapi); + +#endif + +STATIC boolean open_security_api(void); +STATIC boolean close_security_api(void); +STATIC boolean open_volume(const char *volume); +STATIC boolean close_volume(const char *volume); + +#endif + +struct MAPPING { + struct MAPPING *next; + const char *uidstr; + const char *gidstr; + const char *sidstr; + const unsigned char *sid; + const char *login; + boolean defined; +}; + +struct MAPPING *firstmapping; +struct MAPPING *lastmapping; + +#ifdef WIN32 +char *currentwinname; +char *currentdomain; +unsigned char *currentsid; +#endif + +#ifndef WIN32 + +void *ntfs_handle; +void *ntfs_context = (void*)NULL; + +/* + * Open and close the security API (platform dependent) + */ + +STATIC boolean open_security_api(void) +{ +#if USESTUBS + return (true); +#else + char *error; + boolean err; + const char *libfile; + + err = true; + libfile = getenv(ENVNTFS3G); + if (!libfile) + libfile = (sizeof(char*) == 8 ? LIBFILE64 : LIBFILE); + ntfs_handle = dlopen(libfile,RTLD_LAZY); + if (ntfs_handle) { + ntfs_initialize_file_security = + dlsym(ntfs_handle,INIT_FILE_SECURITY); + error = dlerror(); + if (error) + fprintf(stderr," %s\n",error); + else { + ntfs_leave_file_security = + dlsym(ntfs_handle,LEAVE_FILE_SECURITY); + ntfs_get_file_security = + dlsym(ntfs_handle,GET_FILE_SECURITY); + ntfs_set_file_security = + dlsym(ntfs_handle,SET_FILE_SECURITY); + ntfs_read_directory = + dlsym(ntfs_handle,READ_DIRECTORY); + err = !ntfs_initialize_file_security + || !ntfs_leave_file_security + || !ntfs_get_file_security + || !ntfs_set_file_security + || !ntfs_read_directory; + if (error) + fprintf(stderr,"ntfs-3g API not available\n"); + } + } else { + fprintf(stderr,"Could not open ntfs-3g library\n"); + fprintf(stderr,"\nPlease set environment variable \"" ENVNTFS3G "\"\n"); + fprintf(stderr,"to appropriate path and retry\n"); + } + return (!err); +#endif +} + +STATIC boolean close_security_api(void) +{ +#if USESTUBS + return (0); +#else + return (!dlclose(ntfs_handle)); +#endif +} + +/* + * Open and close a volume (platform dependent) + * assuming a single volume needs to be opened at any time + */ + +STATIC boolean open_volume(const char *volume) +{ + boolean ok; + + ok = false; + if (!ntfs_context) { + ntfs_context = ntfs_initialize_file_security(volume,0); + if (ntfs_context) { + fprintf(stderr,"\"%s\" opened\n",volume); + ok = true; + } else { + fprintf(stderr,"Could not open \"%s\"\n",volume); + fprintf(stderr,"Make sure \"%s\" is not mounted\n",volume); + } + } else + fprintf(stderr,"A volume is already open\n"); + return (ok); +} + +STATIC boolean close_volume(const char *volume) +{ + boolean r; + + r = ntfs_leave_file_security(ntfs_context); + if (r) + fprintf(stderr,"\"%s\" closed\n",volume); + else + fprintf(stderr,"Could not close \"%s\"\n",volume); + ntfs_context = (void*)NULL; + return (r); +} + +/* + * A poor man's conversion of Unicode to UTF8 + * We are assuming outputs to terminal expect UTF8 + */ + +STATIC void to_utf8(char *dst, const char *src, unsigned int cnt) +{ + unsigned int ch; + unsigned int i; + + for (i=0; i> 6); + *dst++ = 0x80 + (ch & 63); + } else { + *dst++ = 0xe0 + (ch >> 12); + *dst++ = 0x80 + ((ch >> 6) & 63); + *dst++ = 0x80 + (ch & 63); + } + } + *dst = 0; +} + +STATIC int utf8_size(const char *src, unsigned int cnt) +{ + unsigned int ch; + unsigned int i; + int size; + + size = 0; + for (i=0; isidstr, sidstr)) + mapping = mapping->next; + if (mapping + && (mapping->defined + || !accname + || !strcmp(mapping->login, accname))) + free(sidstr); /* decision already known */ + else { + do { + reject = false; + printf("\n"); + if (accname) + printf("Under Windows login \"%s\"\n", accname); + printf(" file \"%s\" has no mapped %s\n", + filename,(type ? "group" : "owner")); + printf("By which Linux login should this file be owned ?\n"); + printf("Enter %s of login, or just press \"enter\" if this file\n", + (type ? "gid" : "uid")); + printf("does not belong to a user, or you do not known to whom\n"); + printf("\n"); + if (type) + printf("Group : "); + else + printf("User : "); + p = fgets(buf, 80, stdin); + if (p && p[0] && (p[strlen(p) - 1] == '\n')) + p[strlen(p) - 1] = '\0'; + + if (p && p[0] + && ((p[0] == '0') || !strcmp(p, "root"))) { + printf("Please do not map users to root\n"); + printf("Administrators will be mapped automatically\n"); + reject = true; + } + if (reject) + printf("Please retry\n"); + } while (reject); + if (!mapping) { + mapping = + (struct MAPPING *) + malloc(sizeof(struct MAPPING)); + mapping->next = (struct MAPPING *)NULL; + mapping->defined = false; + if (lastmapping) + lastmapping->next = mapping; + else + firstmapping = mapping; + lastmapping = mapping; + } + if (mapping) { + if (p && p[0]) { + idstr = (char *)malloc(strlen(p) + 1); + if (idstr) { + strcpy(idstr, p); + if (type) { + mapping->uidstr = ""; + mapping->gidstr = idstr; + } else { + mapping->uidstr = idstr; + mapping->gidstr = idstr; + } + mapping->defined = true; + } + } + mapping->sidstr = sidstr; + if (accname) { + login = (char*)malloc(strlen(accname) + 1); + if (login) + strcpy(login,accname); + mapping->login = login; + } else + mapping->login = (char*)NULL; + sidsz = 8 + sid[1]*4; + p = (char*)malloc(sidsz); + if (p) { + memcpy(p, sid, sidsz); + } + mapping->sid = (unsigned char*)p; + } + } + } +} + +STATIC void listaclusers(const char *accname, const unsigned char *attr, int off) +{ + int i; + int cnt; + int x; + + cnt = get2l(attr, off + 4); + x = 8; + for (i = 0; i < cnt; i++) { + domapping(accname, (char *)NULL, &attr[off + x + 8], 2); + x += get2l(attr, off + x + 2); + } +} + +#ifdef WIN32 + +STATIC void account(const char *accname, const char *dir, const char *name, int type) +{ + unsigned char attr[MAXATTRSZ]; + unsigned long attrsz; + char *fullname; + int attrib; + + fullname = (char *)malloc(strlen(dir) + strlen(name) + 2); + if (fullname) { + strcpy(fullname, dir); + strcat(fullname, "\\"); + strcat(fullname, name); + attrib = GetFileAttributes(fullname); + if (attrib & 0x10) { /* only directories processed */ + if (GetFileSecurity + (fullname, OWNER_SECURITY_INFORMATION, attr, MAXATTRSZ, + &attrsz)) { + domapping(accname, name, &attr[20], 0); + attrsz = 0; + if (GetFileSecurity + (fullname, GROUP_SECURITY_INFORMATION, attr, + MAXATTRSZ, &attrsz)) + domapping(accname, name, &attr[20], 1); + else + printf(" No group SID\n"); + attrsz = 0; + if (GetFileSecurityA + (fullname, DACL_SECURITY_INFORMATION, attr, + MAXATTRSZ, &attrsz)) { + if (type == 0) + listaclusers(accname, attr, 20); + } else + printf + (" No discretionary access control list\n"); + } + } + free(fullname); + } +} + +#else + +STATIC void account(const char *accname, const char *dir, const char *name, int type) +{ + unsigned char attr[MAXATTRSZ]; + DWORD attrsz; + char *fullname; + + fullname = (char *)malloc(strlen(dir) + strlen(name) + 2); + if (fullname) { + strcpy(fullname, dir); + strcat(fullname, "/"); + strcat(fullname, name); + if (ntfs_get_file_security(ntfs_context, + fullname, OWNER_SECURITY_INFORMATION, + (char*)attr, MAXATTRSZ, &attrsz)) { + domapping(accname, name, &attr[20], 0); + attrsz = 0; + if (ntfs_get_file_security(ntfs_context, + fullname, GROUP_SECURITY_INFORMATION, + (char*)attr, MAXATTRSZ, &attrsz)) + domapping(accname, name, &attr[20], 1); + else + printf(" No group SID\n"); + attrsz = 0; + if (ntfs_get_file_security(ntfs_context, + fullname, DACL_SECURITY_INFORMATION, + (char*)attr, MAXATTRSZ, &attrsz)) { + if (type == 0) + listaclusers(accname, attr, 20); + } else + printf(" No discretionary access control list for %s !\n", + dir); + } + free(fullname); + } +} + +#endif + + +/* + * recursive search of file owners and groups in a directory + */ + +#ifdef WIN32 + +STATIC boolean recurse(const char *accname, const char *dir, int levels) +{ + WIN32_FIND_DATA found; + HANDLE search; + char *filter; + char *fullname; + boolean err; + + err = false; + filter = (char *)malloc(strlen(dir) + 5); + if (filter) { + strcpy(filter, dir); + strcat(filter, "\\*.*"); + search = FindFirstFile(filter, &found); + if (search != INVALID_HANDLE_VALUE) { + do { + if (found.cFileName[0] != '.') { + account(accname, dir, found.cFileName,1); + if (levels > 0) { + fullname = + (char *)malloc(strlen(dir) + + strlen(found.cFileName) + + 2); + if (fullname) { + strcpy(fullname, dir); + strcat(fullname, "\\"); + strcat(fullname, + found.cFileName); + recurse(accname, + fullname, + levels - 1); + free(fullname); + } + } + } + } while (FindNextFile(search, &found)); + FindClose(search); + } + free(filter); + } else { + printf("Directory %s not found\n",dir); + err = true; + } + return (!err); +} + +#else + +STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset); + +STATIC int callback(struct CALLBACK *context, char *ntfsname, + int length, int type, long long pos, unsigned long long mft_ref, + unsigned int dt_type) +{ + char *fullname; + char *accname; + char *name; + + fullname = (char *)malloc(strlen(context->dir) + + utf8_size(ntfsname, length) + 2); + if (fullname) { + if (strcmp(context->dir,"/")) { + strcpy(fullname, context->dir); + strcat(fullname, "/"); + } else + strcpy(fullname,"/"); + /* Unicode to ascii conversion by a lazy man */ + name = &fullname[strlen(fullname)]; + to_utf8(name, ntfsname, length); + /* ignore special files and DOS names */ + if ((type != 2) + && strcmp(name,".") + && strcmp(name,"..") + && (name[0] != '$')) { + switch (context->docset) { + case 2 : + /* + * only "Documents and Settings" + * or "Users" + */ + if (!strcmp(name,OWNERS1) + || !strcmp(name,OWNERS2)) { + recurse((char*)NULL, fullname, 2, 1); + } + break; + /* + * within "Documents and Settings" + * or "Users" + */ + case 1 : + accname = (char*)malloc(strlen(name) + 1); + if (accname) { + strcpy(accname, name); + if (context->levels > 0) + recurse(name, fullname, + context->levels - 1, 0); + } + break; + /* + * not related to "Documents and Settings" + * or "Users" + */ + case 0 : + account(context->accname, context->dir, + name, 1); + if (context->levels > 0) + recurse(context->accname, fullname, + context->levels - 1, 0); + break; + } + } + free(fullname); + } +/* check expected return value */ + return (0); +} + +STATIC boolean recurse(const char *accname, const char *dir, int levels, int docset) +{ + struct CALLBACK context; + boolean err; + + err = false; + context.dir = dir; + context.accname = accname; + context.levels = levels; + context.docset = docset; + ntfs_read_directory(ntfs_context,dir,callback,&context); + return (!err); +} +#endif + +/* + * Search directory "Documents and Settings" for user accounts + */ + +#ifdef WIN32 + +STATIC boolean getusers(const char *dir, int levels) +{ + WIN32_FIND_DATA found; + HANDLE search; + char *filter; + char *fullname; + char *accname; + boolean err; + const char *docset; + + /* first get files from "Documents and Settings" */ + err = false; + if (sizeof(OWNERS1) > sizeof(OWNERS2)) + filter = (char *)malloc(strlen(dir) + strlen(OWNERS1) + 6); + else + filter = (char *)malloc(strlen(dir) + strlen(OWNERS2) + 6); + if (filter) { + docset = OWNERS1; + strcpy(filter, dir); + strcat(filter, "\\"); + strcat(filter, docset); + strcat(filter, "\\*.*"); + search = FindFirstFile(filter, &found); + /* if failed, retry with "Users" */ + if (search == INVALID_HANDLE_VALUE) { + docset = OWNERS2; + strcpy(filter, dir); + strcat(filter, "\\"); + strcat(filter, docset); + strcat(filter, "\\*.*"); + search = FindFirstFile(filter, &found); + } + if (search != INVALID_HANDLE_VALUE) { + do { + if (found.cFileName[0] != '.') { + fullname = + (char *)malloc(strlen(dir) + + strlen(docset) + + strlen(found.cFileName) + 3); + accname = (char *) + malloc(strlen(found.cFileName) + 1); + if (fullname && accname) { + strcpy(accname, + found.cFileName); + + strcpy(fullname, dir); + strcat(fullname, "\\"); + strcat(fullname, docset); + strcat(fullname, "\\"); + strcat(fullname, + found.cFileName); + recurse(accname, fullname, 2); + + free(fullname); + } + } + } while (FindNextFile(search, &found)); + FindClose(search); + } else { + printf("No subdirectory found in %s\\%s\n",dir,docset); + } + /* now search in other directories */ + strcpy(filter, dir); + strcat(filter, "\\*.*"); + search = FindFirstFile(filter, &found); + if (search != INVALID_HANDLE_VALUE) { + do { + if ((found.cFileName[0] != '.') + && strcmp(found.cFileName,OWNERS1) + && strcmp(found.cFileName,OWNERS2)) { + fullname = + (char *)malloc(strlen(dir) + + strlen(found.cFileName) + 2); + if (fullname) { + strcpy(fullname, dir); + strcat(fullname, "\\"); + strcat(fullname, + found.cFileName); + recurse((char*)NULL, fullname, 2); + free(fullname); + } + } + } while (FindNextFile(search, &found)); + FindClose(search); + } else { + printf("No directory found in %s\n",dir); + err = true; + } + } + return (!err); +} + +#else + +STATIC boolean getusers(const char *dir, int levels) +{ + boolean err; + struct CALLBACK context; + + printf("* Search for \"" OWNERS1 "\" and \"" OWNERS2 "\"\n"); + err = false; + context.dir = dir; + context.accname = (const char*)NULL; + context.levels = levels; + context.docset = 2; + ntfs_read_directory(ntfs_context,dir,callback,&context); + printf("* Search for other directories %s\n",dir); + context.docset = 0; + ntfs_read_directory(ntfs_context,dir,callback,&context); + + return (!err); +} + +#endif + +#ifdef WIN32 +/* + * Get the current login name (Win32 only) + */ + +STATIC void loginname(boolean silent) +{ + char *winname; + char *domain; + unsigned char *sid; + unsigned long namesz; + unsigned long sidsz; + unsigned long domainsz; + int nametype; + boolean ok; + int r; + + ok = FALSE; + winname = (char*)malloc(MAXNAMESZ); + domain = (char*)malloc(MAXNAMESZ); + sid = (char*)malloc(MAXSIDSZ); + + namesz = MAXNAMESZ; + domainsz = MAXNAMESZ; + sidsz = MAXSIDSZ; + if (winname + && domain + && sid + && GetUserName(winname,&namesz)) { + winname[namesz] = '\0'; + if (!silent) + printf("Your current user name is %s\n",winname); + nametype = 1; + r = LookupAccountName((char*)NULL,winname,sid,&sidsz, + domain,&domainsz,&nametype); + if (r) { + domain[domainsz] = '\0'; + if (!silent) + printf("Your account domain is %s\n",domain); + ok = true; + } + } + if (ok) { + currentwinname = winname; + currentdomain = domain; + currentsid = sid; + } else { + currentwinname = (char*)NULL; + currentdomain = (char*)NULL; + currentsid = (unsigned char*)NULL; + } +} + +/* + * Minimal output on stdout + */ + +boolean minimal(unsigned char *sid) +{ + const unsigned char *groupsid; + boolean ok; + + ok = false; + if (sid) { + groupsid = makegroupsid(sid); + printf("# %s\n",BANNER); + printf("# For Windows account \"%s\" in domain \"%s\"\n", + currentwinname, currentdomain); + printf("# Replace \"user\" and \"group\" hereafter by matching Linux login\n"); + printf("user::%s\n",decodesid(sid)); + printf(":group:%s\n",decodesid(groupsid)); + ok = true; + } + return (ok); +} + +#endif + +STATIC boolean outputmap(const char *volume, const char *dir) +{ + char buf[256]; + int fn; + char *fullname; + char *backup; + struct MAPPING *mapping; + boolean done; + boolean err; + boolean undecided; +#ifdef WIN32 +#else + struct stat st; + int s; +#endif + + done = false; + fullname = (char *)malloc(strlen(MAPFILE) + 1 + + strlen(volume) + 1 + + (dir ? strlen(dir) + 1 : 0)); + if (fullname) { +#ifdef WIN32 + strcpy(fullname, volume); + if (dir && dir[0]) { + strcat(fullname, "\\"); + strcat(fullname,dir); + } + + /* build directory, if not present */ + if (GetFileAttributes(fullname) & 0x80000000) { + printf("* Creating directory %s\n", fullname); + mkdir(fullname); + } + + strcat(fullname, "\\"); + strcat(fullname, MAPFILE); + printf("\n"); + + if (!(GetFileAttributes(fullname) & 0x80000000)) { + backup = (char*)malloc(strlen(fullname) + 5); + strcpy(backup,fullname); + strcat(backup,".bak"); + unlink(backup); + if (!rename(fullname,backup)) + printf("* Old mapping file moved to %s\n",backup); + } +#else + strcpy(fullname, MAPFILE); + printf("\n"); + + s = stat(fullname,&st); + if (!s) { + backup = (char*)malloc(strlen(fullname + 5)); + strcpy(backup,fullname); + strcat(backup,".bak"); + if (rename(fullname,backup)) + printf("* Old mapping file moved to %s\n",backup); + } +#endif + + printf("* Creating file %s\n", fullname); + err = false; +#ifdef WIN32 + fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY + O_BINARY, + S_IREAD + S_IWRITE); +#else + fn = open(fullname,O_CREAT + O_TRUNC + O_WRONLY, + S_IREAD + S_IWRITE); +#endif + if (fn > 0) { + sprintf(buf,"# %s\n",BANNER); + if (!write(fn,buf,strlen(buf))) + err = true; + printf("%s",buf); + undecided = false; + /* records for owner only or group only */ + for (mapping = firstmapping; mapping && !err; + mapping = mapping->next) + if (mapping->defined + && (!mapping->uidstr[0] || !mapping->gidstr[0])) { + sprintf(buf,"%s:%s:%s\n", + mapping->uidstr, + mapping->gidstr, + mapping->sidstr); + if (!write(fn,buf,strlen(buf))) + err = true; + printf("%s",buf); + } else + undecided = true; + /* records for both owner and group */ + for (mapping = firstmapping; mapping && !err; + mapping = mapping->next) + if (mapping->defined + && mapping->uidstr[0] && mapping->gidstr[0]) { + sprintf(buf,"%s:%s:%s\n", + mapping->uidstr, + mapping->gidstr, + mapping->sidstr); + if (!write(fn,buf,strlen(buf))) + err = true; + printf("%s",buf); + } else + undecided = true; + done = !err; + close(fn); + if (undecided) { + printf("Undecided :\n"); + for (mapping = firstmapping; mapping; + mapping = mapping->next) + if (!mapping->defined) { + printf(" %s\n", mapping->sidstr); + } + } +#ifndef WIN32 + printf("\n* You will have to move the file \"" MAPFILE "\"\n"); + printf(" to directory \"" MAPDIR "\" after mounting\n"); +#endif + } + } + if (!done) + fprintf(stderr, "* Could not create mapping file \"%s\"\n", fullname); + return (done); +} + +STATIC boolean sanitize(void) +{ + char buf[81]; + boolean ok; + int ownercnt; + int groupcnt; + struct MAPPING *mapping; + struct MAPPING *firstowner; + struct MAPPING *genericgroup; + struct MAPPING *group; + char *sidstr; + + /* count owners and groups */ + /* and find first user, and a generic group */ + ownercnt = 0; + groupcnt = 0; + firstowner = (struct MAPPING*)NULL; + genericgroup = (struct MAPPING*)NULL; + for (mapping=firstmapping; mapping; mapping=mapping->next) { + if (mapping->defined && mapping->uidstr[0]) { + if (!ownercnt) + firstowner = mapping; + ownercnt++; + } + if (mapping->defined && mapping->gidstr[0] && !mapping->uidstr[0]) { + groupcnt++; + } + if (!mapping->defined && isgenericgroup(mapping->sidstr)) { + genericgroup = mapping; + } + } +#ifdef WIN32 + /* no user defined, on Windows, suggest a mapping */ + /* based on account currently used */ + if (!ownercnt && currentwinname && currentsid) { + char *owner; + char *p; + + printf("\nYou have defined no file owner,\n"); + printf(" please enter the Linux login which should be mapped\n"); + printf(" to account you are currently using\n"); + printf(" Linux user ? "); + p = fgets(buf, 80, stdin); + if (p && p[0] && (p[strlen(p) - 1] == '\n')) + p[strlen(p) - 1] = '\0'; + if (p && p[0]) { + firstowner = (struct MAPPING*)malloc(sizeof(struct MAPPING)); + owner = (char*)malloc(strlen(p) + 1); + if (firstowner && owner) { + strcpy(owner, p); + firstowner->next = firstmapping; + firstowner->uidstr = owner; + firstowner->gidstr = ""; + firstowner->sidstr = decodesid(currentsid); + firstowner->sid = currentsid; + firstmapping = firstowner; + ownercnt++; + /* prefer a generic group with the same authorities */ + for (mapping=firstmapping; mapping; + mapping=mapping->next) + if (!mapping->defined + && isgenericgroup(mapping->sidstr) + && !memcmp(firstowner->sidstr, + mapping->sidstr, + strlen(mapping->sidstr)-3)) + genericgroup = mapping; + } + } + } +#endif + if (ownercnt) { + /* + * No group was selected, but there were a generic group + * insist in using it, associated to the first user + */ + if (!groupcnt) { + printf("\nYou have defined no group, this can cause problems\n"); + printf("Do you accept defining a standard group ?\n"); + if (!fgets(buf,80,stdin) + || ((buf[0] != 'n') + && (buf[0] != 'N'))) { + if (genericgroup) { + genericgroup->uidstr = ""; + genericgroup->gidstr = firstowner->uidstr; + genericgroup->defined = true; + } else { + group = (struct MAPPING*) + malloc(sizeof(struct MAPPING)); + sidstr = decodesid( + makegroupsid(firstowner->sid)); + if (group && sidstr) { + group->uidstr = ""; + group->gidstr = firstowner-> + uidstr; + group->sidstr = sidstr; + group->defined = true; + group->next = firstmapping; + firstmapping = group; + } + } + } + } + ok = true; + } else { + printf("\nYou have defined no user, no mapping can be built\n"); + ok = false; + } + + return (ok); +} + +STATIC boolean checkoptions(int argc, char *argv[], boolean silent) +{ + boolean err; +#ifdef WIN32 + int xarg; + const char *pvol; + + if (silent) + err = (argc != 1); + else { + err = (argc < 2); + for (xarg=1; (xarg= 'A') && (pvol[0] <= 'Z')) + || ((pvol[0] >= 'a') && (pvol[0] <= 'z'))); + } + } + } + if (err) { + fprintf(stderr, "Usage : usermap [vol1: [vol2: ...]]\n"); + fprintf(stderr, " \"voln\" are the letters of the partition to share with Linux\n"); + fprintf(stderr, " eg C:\n"); + fprintf(stderr, " the Windows system partition should be named first\n"); + } +#else + err = (argc < 2); + if (err) { + fprintf(stderr, "Usage : usermap dev1 [dev2 ...]\n"); + fprintf(stderr, " \"dev.\" are the devices to share with Windows\n"); + fprintf(stderr, " eg /dev/sdb1\n"); + fprintf(stderr, " the devices should not be mounted\n"); + fprintf(stderr, " the Windows system partition should be named first\n"); + } else + if (getuid()) { + fprintf(stderr, "\nSorry, only root can start usermap\n"); + err = true; + } +#endif + return (!err); +} + +STATIC boolean process(int argc, char *argv[]) +{ + boolean ok; + int xarg; + int targ; + + firstmapping = (struct MAPPING *)NULL; + lastmapping = (struct MAPPING *)NULL; + ok = true; +#ifdef WIN32 + for (xarg=1; (xarg 2 ? 2 : 1); + if (!outputmap(argv[targ],MAPDIR)) { + printf("Trying to write file on root directory\n"); + if (outputmap(argv[targ],(const char*)NULL)) { + printf("\nNote : you will have to move the file to directory \"%s\" on Linux\n", + MAPDIR); + } else + ok = false; + } else + ok = false; + } else + ok = false; + return (ok); +} + +int main(int argc, char *argv[]) +{ + boolean ok; + boolean silent; + + silent = !isatty(1); + if (!silent) + welcome(); + if (checkoptions(argc, argv, silent)) { +#ifdef WIN32 + loginname(silent); + if (silent) + ok = minimal(currentsid); + else + ok = process(argc, argv); +#else + if (open_security_api()) { + ok = process(argc,argv); + if (!close_security_api()) ok = false; + } +#endif + } else + ok = false; + if (!ok) + exit(1); + return (0); +} -- 2.11.4.GIT