Index: src/contrib/fuse-dfs/test/TestFuseDFS.java =================================================================== --- src/contrib/fuse-dfs/test/TestFuseDFS.java (revision 0) +++ src/contrib/fuse-dfs/test/TestFuseDFS.java (revision 0) @@ -0,0 +1,225 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.hadoop.dfs.*; +import junit.framework.TestCase; +import java.io.*; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.*; +import java.net.*; + +/** + * This class tests that the Fuse module for DFS can mount properly + * and does a few simple commands: + * mkdir + * rmdir + * ls + * cat + * + * cp and touch are purposely not tested because they won't work with the current module + + * + */ +public class TestFuseDFS extends TestCase { + + /** + * mount the fuse file system using assumed fuse module library installed in /usr/local/lib or somewhere else on your + * pre-existing LD_LIBRARY_PATH + * + */ + private void mount(String mountpoint, URI dfs) throws IOException, InterruptedException { + String cp = System.getenv("CLASSPATH"); + String libhdfs = "../../c++/libhdfs/"; + String lp = System.getenv("LD_LIBRARY_PATH") + ":" + "/usr/local/lib:" + libhdfs; + + Runtime r = Runtime.getRuntime(); + String fuse_cmd = "../src/fuse_dfs"; + + String cmd = fuse_cmd; + cmd += " "; + // cmd += dfs.toASCIIString(); + cmd += "dfs://"; + cmd += dfs.getHost(); + cmd += ":" ; + cmd += String.valueOf(dfs.getPort()); + cmd += " "; + cmd += mountpoint; + final String [] envp = { + "CLASSPATH="+ cp, + "LD_LIBRARY_PATH=" + lp + }; + + + // ensure the mount point is not currently mounted + Process p = r.exec("sudo umount -l " + mountpoint); + p.waitFor(); + + // make the mount point if needed + p = r.exec("mkdir -p " + mountpoint); + assertTrue(p.waitFor() == 0); + + System.err.println("cmd=" + cmd); + // mount fuse to the mount point + p = r.exec(cmd, envp); + assertTrue(p.waitFor() == 0); + assertTrue(p.exitValue() == 0); + } + + /** + * unmounts fuse for before shutting down. + */ + private void umount(String mpoint) throws IOException, InterruptedException { + Runtime r= Runtime.getRuntime(); + Process p = r.exec("sudo umount -l " + mpoint); + p.waitFor(); + } + + /** + * Set things up - create mini dfs cluster and mount the fuse filesystem. + */ + public TestFuseDFS() throws IOException,InterruptedException { + Configuration conf = new Configuration(); + this.cluster = new MiniDFSCluster(conf, 1, true, null); + this.fileSys = this.cluster.getFileSystem(); + String mpoint = "/tmp/testfuse"; + this.mount(mpoint, fileSys.getUri()); + this.myPath = new Path("/test/mkdirs"); + } + + private MiniDFSCluster cluster; + private FileSystem fileSys; + private String mpoint = "/tmp/testfuse"; + private Path myPath; + + + /** + * use shell to create a dir and then use filesys to see it exists. + */ + public void testMkdir() throws IOException,InterruptedException { + // First create a new directory with mkdirs + Runtime r = Runtime.getRuntime(); + Process p = r.exec("mkdir -p " + mpoint + "/test/mkdirs"); + assertTrue(p.waitFor() == 0); + assertTrue(p.exitValue() == 0); + + assertTrue(this.fileSys.exists(myPath)); + + + } + + /** + * Test ls for dir already created in testMkdDir also tests bad ls + */ + public void testLs() throws IOException,InterruptedException { + // First create a new directory with mkdirs + Runtime r = Runtime.getRuntime(); + Process p = r.exec("ls " + mpoint + "/test/mkdirs"); + assertTrue(p.waitFor() == 0); + assertTrue(p.exitValue() == 0); + + p = r.exec("ls " + mpoint + "/test/mkdirsNotThere"); + assertFalse(p.waitFor() == 0); + assertFalse(p.exitValue() == 0); + + } + + /** + * Remove a dir using the shell and use filesys to see it no longer exists. + */ + public void testRmdir() throws IOException,InterruptedException { + // First create a new directory with mkdirs + Path myPath = new Path("/test/mkdirs"); + assertTrue(fileSys.exists(myPath)); + + Runtime r = Runtime.getRuntime(); + Process p = r.exec("rmdir " + mpoint + "/test/mkdirs"); + + assertTrue(p.waitFor() == 0); + assertTrue(p.exitValue() == 0); + + assertFalse(fileSys.exists(myPath)); + } + + + /** + * Use filesys to create the hello world! file and then cat it and see its contents are correct. + */ + public void testCat() throws IOException,InterruptedException { + // First create a new directory with mkdirs + + Path myPath = new Path("/test/hello"); + FSDataOutputStream s = fileSys.create(myPath); + String hello = "hello world!"; + + s.write(hello.getBytes()); + s.close(); + + assertTrue(fileSys.exists(myPath)); + + Runtime r = Runtime.getRuntime(); + Process p = r.exec("cat " + mpoint + "/test/hello"); + + assertTrue(p.waitFor() == 0); + assertTrue(p.exitValue() == 0); + InputStream i = p.getInputStream(); + byte b[] = new byte[1024]; + int length = i.read(b); + String s2 = new String(b,0,length); + assertTrue(s2.equals(hello)); + } + + + /** + * Unmount and close + */ + public void finalize() { + try { + this.close(); + } catch(Exception e) { } + } + + /** + * Unmount and close + */ + public void close() throws IOException, InterruptedException { + this.umount(mpoint); + if(this.fileSys != null) { + this.fileSys.close(); + this.fileSys = null; + } + if(this.cluster != null) { + this.cluster.shutdown(); + this.cluster = null; + } + } + + public static void main(String args[]) { + try { + TestFuseDFS d = new TestFuseDFS(); + d.testMkdir(); + d.testLs(); + d.testRmdir(); + d.testCat(); + d.close(); + } catch(Exception e) { + System.err.println("e=" + e.getMessage()); + e.printStackTrace(); + } + + } +} Index: src/contrib/fuse-dfs/configure.ac =================================================================== --- src/contrib/fuse-dfs/configure.ac (revision 0) +++ src/contrib/fuse-dfs/configure.ac (revision 0) @@ -0,0 +1,135 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Autoconf input file +# $Id$ + +# AC - autoconf +# FB - facebook + +######################################################################### +# Section 1: +# DO NOT TOUCH EXCEPT TO CHANGE Product-Name and Rev# IN AC_INIT + +AC_PREREQ(2.52) +AC_INIT([fuse_dfs], [0.1.0]) +#AC_CONFIG_AUX_DIR([/usr/share/automake-1.9]) +# To install locally +AC_CANONICAL_TARGET() +FB_INITIALIZE([localinstall]) +AC_PREFIX_DEFAULT([`pwd`]) + + +#case $target in +#*64*intel) +# OS_ARCH=intel64 ;; +#*64*amd* | *64*unknown*) +# OS_ARCH=amd64 ;; +#$esac +#AC_SUBST(OS_ARCH) + DEFS="" +AC_SUBST([DEFS]) + +############################################################################ +# Section 2: +# User Configurable system defaults. Change With CAUTION! + +# User can include custom makefile rules. Uncomment and update only in PRODUCT_MK. +# Include where appropriate in any Makefile.am as @PRODUCT_MK@ + +# Default path to external Facebook components and shared build tools I.e fb303 etc. +# To point to other locations set environment variable EXTERNAL_PATH. +# DO NOT change default. Changing default value requires changing bootstrap.sh. +FB_WITH_EXTERNAL_PATH([`pwd`]) + +# Pre-defined macro to set optimized build mode. Configure with --disable-opt option to turn off optimization. Default CXXFLAGS set to '-Wall -O3'. In debug mode CXXFLAGS is '-Wall -g' +# FB_ENABLE_DEFAULT_DEBUG_BUILD +FB_ENABLE_DEFAULT_OPT_BUILD + +# Predefined macro to set static library mode. Configure with --disable-static option to turn off static lib mode. +# FB_ENABLE_DEFAULT_SHARED +FB_ENABLE_DEFAULT_STATIC + +########################################################################## +# Section 3: +# User Configurable + +# Personalized FLAG setting macro. Sets FLAG to user specifed value overriding any default. +# $(FLAG) can be used in Makefile.am and global mk's. +# FB_SET_FLAG_VALUE([], []) +# FB_SET_FLAG_VALUE([CXXFLAGS], [-g -O3]) + +# Personalized feature generator. Creates defines/conditionals and --enable --disable command line options. Doesn't enable until configured with --enable- option. +# FB_ENABLE_FEATURE([FEATURE], [feature]) OR FB_ENABLE_FEATURE([FEATURE], [feature], [\"\"]) +# Example: Macro supplies -DFACEBOOK at compile time and "if FACEBOOK endif" capabilities. + +# FB_ENABLE_FEATURE([FACEBOOK], [facebook]) +#FB_ENABLE_FEATURE([HDFS], [hdfs]) + +# Personalized path generator Sets default paths. Provides --with-xx=DIR options. +# FB_WITH_PATH([_home], [path], [] +# Example: sets $(thrift_dir) variable with default path. +#FB_WITH_PATH([HADOOP_HOME], [hadooppath], [/usr/local/share/hadoop/]) +#FB_WITH_PATH([external_home], [externalpath], [${EXTERNAL_PATH}/external]) +#FB_WITH_PATH([FUSE_HOME], [fusehome], [/usr/local]) +#FB_WITH_PATH([JAVA_HOME], [jdkhome], [/usr/local/jdk]) +#FB_WITH_PATH([PROTECTED_PATHS], [protectedpaths], [/,/Trash,/user]) + +# Set default location of "php-config". User can also use "--with-php-config=" to point to another location. +# Run "./configure --help" to see --with options. +# PHPCONFIGLIBS and PHPCONFIGINCS are generated. +# FB_SET_PHP([PHPCONFIGDIR], [/usr/local/bin]) + +# Generates Makefile from Makefile.am. Modify when new subdirs are added. +# Change Makefile.am also to add subdirectly. +AC_CONFIG_FILES(Makefile src/Makefile) + + +############################################################################ +# Section 4: +# DO NOT TOUCH. + +AC_SUBST(PRODUCT_MK) +AC_OUTPUT + +############################################################################# +######### FINISH ############################################################ + +echo "EXTERNAL_PATH $EXTERNAL_PATH" + + +# +# NOTES FOR USER +# Short cut to create conditional flags. +#enable_facebook="yes" +#AM_CONDITIONAL([FACEBOOK], [test "$enable_facebook" = yes]) +#enable_hdfs="yes" +#AM_CONDITIONAL([HDFS], [test "$enable_hdfs" = yes]) + +# Enable options with --enable and --disable configurable. +#AC_MSG_CHECKING([whether to enable FACEBOOK]) +#FACEBOOK="" +#AC_ARG_ENABLE([facebook], +# [ --enable-facebook Enable facebook.], +# [ +# ENABLE_FACEBOOK=$enableval +# ], +# [ +# ENABLE_FACEBOOK="no" +# ] +#) +#AM_CONDITIONAL([FACEBOOK], [test "$ENABLE_FACEBOOK" = yes]) +#AC_MSG_RESULT($ENABLE_FACEBOOK) + Index: src/contrib/fuse-dfs/global_footer.mk =================================================================== --- src/contrib/fuse-dfs/global_footer.mk (revision 0) +++ src/contrib/fuse-dfs/global_footer.mk (revision 0) @@ -0,0 +1,17 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +thriftstyle : $(XBUILT_SOURCES) + Index: src/contrib/fuse-dfs/bootstrap.sh =================================================================== --- src/contrib/fuse-dfs/bootstrap.sh (revision 0) +++ src/contrib/fuse-dfs/bootstrap.sh (revision 0) @@ -0,0 +1,21 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +#!/bin/sh + +aclocal +automake -a +autoconf +./configure Index: src/contrib/fuse-dfs/acinclude.m4 =================================================================== --- src/contrib/fuse-dfs/acinclude.m4 (revision 0) +++ src/contrib/fuse-dfs/acinclude.m4 (revision 0) @@ -0,0 +1,268 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +AC_DEFUN([FB_INITIALIZE], +[ +AM_INIT_AUTOMAKE([ foreign 1.9.5 no-define ]) +if test "x$1" = "xlocalinstall"; then +wdir=`pwd` +# To use $wdir undef quote. +# +########## +AC_PREFIX_DEFAULT([`pwd`/install]) +echo +fi +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB(RANLIB, ranlib) +AC_PATH_PROGS(BASH, bash) +AC_PATH_PROGS(PERL, perl) +AC_PATH_PROGS(PYTHON, python) +AC_PATH_PROGS(AR, ar) +AC_PATH_PROGS(ANT, ant) +PRODUCT_MK="" +]) + +AC_DEFUN([FB_WITH_EXTERNAL_PATH], +[ +cdir=`pwd` +AC_MSG_CHECKING([Checking EXTERNAL_PATH set to]) +AC_ARG_WITH([externalpath], + [ --with-externalpath=DIR User specified path to external facebook components.], + [ + if test "x${EXTERNAL_PATH}" != "x"; then + echo "" + echo "ERROR: You have already set EXTERNAL_PATH in your environment" + echo "Cannot override it using --with-externalpath. Unset EXTERNAL_PATH to use this option" + exit 1 + fi + EXTERNAL_PATH=$withval + ], + [ + if test "x${EXTERNAL_PATH}" = "x"; then + EXTERNAL_PATH=$1 + fi + ] +) +if test "x${EXTERNAL_PATH}" = "x"; then + export EXTERNAL_PATH="$cdir/external" + GLOBAL_HEADER_MK="include ${EXTERNAL_PATH}/global_header.mk" + GLOBAL_FOOTER_MK="include ${EXTERNAL_PATH}/global_footer.mk" +else + export EXTERNAL_PATH + GLOBAL_HEADER_MK="include ${EXTERNAL_PATH}/global_header.mk" + GLOBAL_FOOTER_MK="include ${EXTERNAL_PATH}/global_footer.mk" +fi +AC_MSG_RESULT($EXTERNAL_PATH) +if test ! -d ${EXTERNAL_PATH}; then + echo "" + echo "ERROR: EXTERNAL_PATH set to an nonexistent directory ${EXTERNAL_PATH}" + exit 1 +fi +AC_SUBST(EXTERNAL_PATH) +AC_SUBST(GLOBAL_HEADER_MK) +AC_SUBST(GLOBAL_FOOTER_MK) +]) + +# Set option to enable shared mode. Set DEBUG and OPT for use in Makefile.am. +AC_DEFUN([FB_ENABLE_DEFAULT_OPT_BUILD], +[ +AC_MSG_CHECKING([whether to enable optimized build]) +AC_ARG_ENABLE([opt], + [ --disable-opt Set up debug mode.], + [ + ENABLED_OPT=$enableval + ], + [ + ENABLED_OPT="yes" + ] +) +if test "$ENABLED_OPT" = "yes" +then + CFLAGS="-Wall -O3" + CXXFLAGS="-Wall -O3" +else + CFLAGS="-Wall -g" + CXXFLAGS="-Wall -g" +fi +AC_MSG_RESULT($ENABLED_OPT) +AM_CONDITIONAL([OPT], [test "$ENABLED_OPT" = yes]) +AM_CONDITIONAL([DEBUG], [test "$ENABLED_OPT" = no]) +]) + +# Set option to enable debug mode. Set DEBUG and OPT for use in Makefile.am. +AC_DEFUN([FB_ENABLE_DEFAULT_DEBUG_BUILD], +[ +AC_MSG_CHECKING([whether to enable debug build]) +AC_ARG_ENABLE([debug], + [ --disable-debug Set up opt mode.], + [ + ENABLED_DEBUG=$enableval + ], + [ + ENABLED_DEBUG="yes" + ] +) +if test "$ENABLED_DEBUG" = "yes" +then + CFLAGS="-Wall -g" + CXXFLAGS="-Wall -g" +else + CFLAGS="-Wall -O3" + CXXFLAGS="-Wall -O3" +fi +AC_MSG_RESULT($ENABLED_DEBUG) +AM_CONDITIONAL([DEBUG], [test "$ENABLED_DEBUG" = yes]) +AM_CONDITIONAL([OPT], [test "$ENABLED_DEBUG" = no]) +]) + +# Set option to enable static libs. +AC_DEFUN([FB_ENABLE_DEFAULT_STATIC], +[ +SHARED="" +STATIC="" +AC_MSG_CHECKING([whether to enable static mode]) +AC_ARG_ENABLE([static], + [ --disable-static Set up shared mode.], + [ + ENABLED_STATIC=$enableval + ], + [ + ENABLED_STATIC="yes" + ] +) +if test "$ENABLED_STATIC" = "yes" +then + LTYPE=".a" +else + LTYPE=".so" + SHARED_CXXFLAGS="-fPIC" + SHARED_CFLAGS="-fPIC" + SHARED_LDFLAGS="-shared -fPIC" + AC_SUBST(SHARED_CXXFLAGS) + AC_SUBST(SHARED_CFLAGS) + AC_SUBST(SHARED_LDFLAGS) +fi +AC_MSG_RESULT($ENABLED_STATIC) +AC_SUBST(LTYPE) +AM_CONDITIONAL([STATIC], [test "$ENABLED_STATIC" = yes]) +AM_CONDITIONAL([SHARED], [test "$ENABLED_STATIC" = no]) +]) + +# Set option to enable shared libs. +AC_DEFUN([FB_ENABLE_DEFAULT_SHARED], +[ +SHARED="" +STATIC="" +AC_MSG_CHECKING([whether to enable shared mode]) +AC_ARG_ENABLE([shared], + [ --disable-shared Set up static mode.], + [ + ENABLED_SHARED=$enableval + ], + [ + ENABLED_SHARED="yes" + ] +) +if test "$ENABLED_SHARED" = "yes" +then + LTYPE=".so" + SHARED_CXXFLAGS="-fPIC" + SHARED_CFLAGS="-fPIC" + SHARED_LDFLAGS="-shared -fPIC" + AC_SUBST(SHARED_CXXFLAGS) + AC_SUBST(SHARED_CFLAGS) + AC_SUBST(SHARED_LDFLAGS) +else + LTYPE=".a" +fi +AC_MSG_RESULT($ENABLED_SHARED) +AC_SUBST(LTYPE) +AM_CONDITIONAL([SHARED], [test "$ENABLED_SHARED" = yes]) +AM_CONDITIONAL([STATIC], [test "$ENABLED_SHARED" = no]) +]) + +# Generates define flags and conditionals as specified by user. +# This gets enabled *only* if user selects --enable- otion. +AC_DEFUN([FB_ENABLE_FEATURE], +[ +ENABLE="" +flag="$1" +value="$3" +AC_MSG_CHECKING([whether to enable $1]) +AC_ARG_ENABLE([$2], + [ --enable-$2 Enable $2.], + [ + ENABLE=$enableval + ], + [ + ENABLE="no" + ] +) +AM_CONDITIONAL([$1], [test "$ENABLE" = yes]) +if test "$ENABLE" = "yes" +then + if test "x${value}" = "x" + then + AC_DEFINE([$1]) + else + AC_DEFINE_UNQUOTED([$1], [$value]) + fi +fi +AC_MSG_RESULT($ENABLE) +]) + + +# can also use eval $2=$withval;AC_SUBST($2) +AC_DEFUN([FB_WITH_PATH], +[ +USRFLAG="" +USRFLAG=$1 +AC_MSG_CHECKING([Checking $1 set to]) +AC_ARG_WITH([$2], + [ --with-$2=DIR User specified path.], + [ + LOC=$withval + eval $USRFLAG=$withval + ], + [ + LOC=$3 + eval $USRFLAG=$3 + ] +) +AC_SUBST([$1]) +AC_MSG_RESULT($LOC) +]) + +AC_DEFUN([FB_SET_FLAG_VALUE], +[ +SETFLAG="" +AC_MSG_CHECKING([Checking $1 set to]) +SETFLAG=$1 +eval $SETFLAG=\"$2\" +AC_SUBST([$SETFLAG]) +AC_MSG_RESULT($2) +]) + +# NOTES +# if using if else bourne stmt you must have more than a macro in it. +# EX1 is not correct. EX2 is correct +# EX1: if test "$XX" = "yes"; then +# AC_SUBST(xx) +# fi +# EX2: if test "$XX" = "yes"; then +# xx="foo" +# AC_SUBST(xx) +# fi Index: src/contrib/fuse-dfs/src/fuse_dfs.c =================================================================== --- src/contrib/fuse-dfs/src/fuse_dfs.c (revision 0) +++ src/contrib/fuse-dfs/src/fuse_dfs.c (revision 0) @@ -0,0 +1,1064 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define FUSE_USE_VERSION 26 + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef linux +/* For pread()/pwrite() */ +#define _XOPEN_SOURCE 500 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETXATTR +#include +#endif +#include // for ceil +#include +#include +#include +#include + +#include + +// Constants +// +static const int default_id = 99; // nobody - not configurable since soon uids in dfs, yeah! +static const size_t rd_buf_size = 128 * 1024; +static const int blksize = 512; +static const size_t rd_cache_buf_size = 10*1024*1024;//how much of reads to buffer here + +/** options for fuse_opt.h */ +struct options { + char* server; + int port; + int debug; + int nowrites; + int no_trash; +}options; + + +typedef struct dfs_fh_struct { + hdfsFile hdfsFH; + char *buf; + tSize sizeBuffer; //what is the size of the buffer we have + off_t startOffset; //where the buffer starts in the file +} dfs_fh; + +#include + +/** macro to define options */ +#define DFSFS_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v } + +/** keys for FUSE_OPT_ options */ +static void print_usage(const char *pname) +{ + fprintf(stdout,"USAGE: %s [--debug] [--help] [--version] [--nowrites] [--notrash] --server= --port= [fuse options]\n",pname); + fprintf(stdout,"NOTE: a useful fuse option is -o allow_others and -o default_permissions\n"); + fprintf(stdout,"NOTE: optimizations include -o entry_timeout=500 -o attr_timeout=500\n"); + fprintf(stdout,"NOTE: debugging option for fuse is -debug\n"); +} + + +#define OPTIMIZED_READS 1 + + +enum + { + KEY_VERSION, + KEY_HELP, + }; + +static struct fuse_opt dfs_opts[] = + { + DFSFS_OPT_KEY("--server=%s", server, 0), + DFSFS_OPT_KEY("--port=%d", port, 0), + DFSFS_OPT_KEY("--debug", debug, 1), + DFSFS_OPT_KEY("--nowrites", nowrites, 1), + DFSFS_OPT_KEY("--notrash", no_trash, 1), + + FUSE_OPT_KEY("-v", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_END + }; + +static const char *program; + +int dfs_options(void *data, const char *arg, int key, struct fuse_args *outargs) +{ + + if (key == KEY_VERSION) { + fprintf(stdout,"%s %s\n",program,_FUSE_DFS_VERSION); + exit(0); + } else if (key == KEY_HELP) { + print_usage(program); + exit(0); + } else { + // try and see if the arg is a URI for DFS + int tmp_port; + char tmp_server[1024]; + + if (!sscanf(arg,"dfs://%1024[a-zA-Z0-9_.-]:%d",tmp_server,&tmp_port)) { + printf("didn't recognize %s\n",arg); + fuse_opt_add_arg(outargs,arg); + } else { + options.port = tmp_port; + options.server = strdup(tmp_server); + } + } + return 0; +} + + +// +// Structure to store fuse_dfs specific data +// this will be created and passed to fuse at startup +// and fuse will pass it back to us via the context function +// on every operation. +// +typedef struct dfs_context_struct { + int debug; + char *nn_hostname; + int nn_port; + hdfsFS fs; + int nowrites; + int no_trash; + + // todo: + // total hack city - use this to strip off the dfs url from the filenames + // that the dfs API is now providing in 0.14.5 + // Will do a better job of fixing this once I am back from vacation + // + char dfs_uri[1024]; + int dfs_uri_len; +} dfs_context; + + +// +// Start of read-only functions +// + +static int dfs_getattr(const char *path, struct stat *st) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(dfs); + assert(path); + assert(st); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + // call the dfs API to get the actual information + hdfsFileInfo *info = hdfsGetPathInfo(dfs->fs,path); + + if (NULL == info) { + return -ENOENT; + } + + // initialize the stat structure + memset(st, 0, sizeof(struct stat)); + + // setup hard link info - for a file it is 1 else num entries in a dir + 2 (for . and ..) + if (info[0].mKind == kObjectKindDirectory) { + int numEntries = 0; + hdfsFileInfo *info = hdfsListDirectory(dfs->fs,path,&numEntries); + + if (info) { + hdfsFreeFileInfo(info,numEntries); + } + st->st_nlink = numEntries + 2; + } else { + // not a directory + st->st_nlink = 1; + } + + // set stat metadata + st->st_size = (info[0].mKind == kObjectKindDirectory) ? 4096 : info[0].mSize; + st->st_blksize = blksize; + st->st_blocks = ceil(st->st_size/st->st_blksize); + st->st_mode = (info[0].mKind == kObjectKindDirectory) ? (S_IFDIR | 0777) : (S_IFREG | 0666); + st->st_uid = default_id; + st->st_gid = default_id; + st->st_atime = info[0].mLastMod; + st->st_mtime = info[0].mLastMod; + st->st_ctime = info[0].mLastMod; + + // free the info pointer + hdfsFreeFileInfo(info,1); + + return 0; +} + +static int dfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + (void) offset; + (void) fi; + + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(dfs); + assert(path); + assert(buf); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + int path_len = strlen(path); + + // call dfs to read the dir + int numEntries = 0; + hdfsFileInfo *info = hdfsListDirectory(dfs->fs,path,&numEntries); + + // NULL means either the directory doesn't exist or maybe IO error. + if (NULL == info) { + return -ENOENT; + } + + int i ; + for (i = 0; i < numEntries; i++) { + + // check the info[i] struct + if (NULL == info[i].mName) { + syslog(LOG_ERR,"ERROR: for <%s> info[%d].mName==NULL %s:%d", path, i, __FILE__,__LINE__); + continue; + } + + struct stat st; + memset(&st, 0, sizeof(struct stat)); + + // set to 0 to indicate not supported for directory because we cannot (efficiently) get this info for every subdirectory + st.st_nlink = (info[i].mKind == kObjectKindDirectory) ? 0 : 1; + + // setup stat size and acl meta data + st.st_size = info[i].mSize; + st.st_blksize = 512; + st.st_blocks = ceil(st.st_size/st.st_blksize); + st.st_mode = (info[i].mKind == kObjectKindDirectory) ? (S_IFDIR | 0777) : (S_IFREG | 0666); + st.st_uid = default_id; + st.st_gid = default_id; + st.st_atime = info[i].mLastMod; + st.st_mtime = info[i].mLastMod; + st.st_ctime = info[i].mLastMod; + + // hack city: todo fix the below to something nicer and more maintainable but + // with good performance + // strip off the path but be careful if the path is solely '/' + // NOTE - this API started returning filenames as full dfs uris + const char *const str = info[i].mName + dfs->dfs_uri_len + path_len + ((path_len == 1 && *path == '/') ? 0 : 1); + + // pack this entry into the fuse buffer + int res = 0; + if ((res = filler(buf,str,&st,0)) != 0) { + syslog(LOG_ERR, "ERROR: readdir filling the buffer %d %s:%d\n",res, __FILE__, __LINE__); + } + + } + + // insert '.' and '..' + const char *const dots [] = { ".",".."}; + for (i = 0 ; i < 2 ; i++) + { + struct stat st; + memset(&st, 0, sizeof(struct stat)); + + // set to 0 to indicate not supported for directory because we cannot (efficiently) get this info for every subdirectory + st.st_nlink = 0; + + // setup stat size and acl meta data + st.st_size = 512; + st.st_blksize = 512; + st.st_blocks = 1; + st.st_mode = (S_IFDIR | 0777); + st.st_uid = default_id; + st.st_gid = default_id; + // todo fix below times + st.st_atime = 0; + st.st_mtime = 0; + st.st_ctime = 0; + + const char *const str = dots[i]; + + // flatten the info using fuse's function into a buffer + int res = 0; + if ((res = filler(buf,str,&st,0)) != 0) { + syslog(LOG_ERR, "ERROR: readdir filling the buffer %d %s:%d", res, __FILE__, __LINE__); + } + } + + // free the info pointers + hdfsFreeFileInfo(info,numEntries); + + return 0; +} + +static int dfs_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(dfs); + assert(path); + assert(buf); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + +#ifdef OPTIMIZED_READS + dfs_fh *fh = (dfs_fh*)fi->fh; + //fprintf(stderr, "Cache bounds for %s: %llu -> %llu (%d bytes). Check for offset %llu\n", path, fh->startOffset, fh->startOffset + fh->sizeBuffer, fh->sizeBuffer, offset); + if (fh->sizeBuffer == 0 || offset < fh->startOffset || offset > (fh->startOffset + fh->sizeBuffer) ) + { + // do the actual read + //fprintf (stderr,"Reading %s from HDFS, offset %llu, amount %d\n", path, offset, rd_cache_buf_size); + const tSize num_read = hdfsPread(dfs->fs, fh->hdfsFH, offset, fh->buf, rd_cache_buf_size); + if (num_read < 0) { + syslog(LOG_ERR, "Read error - pread failed for %s with return code %d %s:%d", path, num_read, __FILE__, __LINE__); + hdfsDisconnect(dfs->fs); + dfs->fs = NULL; + return -EIO; + } + fh->sizeBuffer = num_read; + fh->startOffset = offset; + //fprintf (stderr,"Read %d bytes of %s from HDFS\n", num_read, path); + } + + char* local_buf = fh->buf; + const tSize cacheLookupOffset = offset - fh->startOffset; + local_buf += cacheLookupOffset; + //fprintf(stderr,"FUSE requested %d bytes of %s for offset %d in file\n", size, path, offset); + const tSize amount = cacheLookupOffset + size > fh->sizeBuffer + ? fh->sizeBuffer - cacheLookupOffset + : size; + //fprintf(stderr,"Reading %s from cache, %d bytes from position %d\n", path, amount, cacheLookupOffset); + //fprintf(stderr,"Cache status for %s: %d bytes cached from offset %llu\n", path, fh->sizeBuffer, fh->startOffset); + memcpy(buf, local_buf, amount); + //fprintf(stderr,"Read %s from cache, %d bytes from position %d\n", path, amount, cacheLookupOffset); + //fprintf(stderr,"Cache status for %s: %d bytes cached from offset %llu\n", path, fh->sizeBuffer, fh->startOffset); + return amount; + +#else + // NULL means either file doesn't exist or maybe IO error - i.e., the dfs_open must have failed + if (NULL == (void*)fi->fh) { + // should never happen + return -EIO; + } + syslog(LOG_DEBUG,"buffer size=%d\n",(int)size); + + // do the actual read + const tSize num_read = hdfsPread(dfs->fs, (hdfsFile)fi->fh, offset, buf, size); + + // handle errors + if (num_read < 0) { + syslog(LOG_ERR, "Read error - pread failed for %s with return code %d %s:%d", path, num_read, __FILE__, __LINE__); + hdfsDisconnect(dfs->fs); + dfs->fs = NULL; + return -EIO; + } + return num_read; +#endif + +} + +static int dfs_statfs(const char *path, struct statvfs *st) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(st); + assert(dfs); + + // init the stat structure + memset(st,0,sizeof(struct statvfs)); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + const long cap = hdfsGetCapacity(dfs->fs); + const long used = hdfsGetUsed(dfs->fs); + const long bsize = hdfsGetDefaultBlockSize(dfs->fs); + + // fill in the statvfs structure + + /* FOR REFERENCE: + struct statvfs { + unsigned long f_bsize; // file system block size + unsigned long f_frsize; // fragment size + fsblkcnt_t f_blocks; // size of fs in f_frsize units + fsblkcnt_t f_bfree; // # free blocks + fsblkcnt_t f_bavail; // # free blocks for non-root + fsfilcnt_t f_files; // # inodes + fsfilcnt_t f_ffree; // # free inodes + fsfilcnt_t f_favail; // # free inodes for non-root + unsigned long f_fsid; // file system id + unsigned long f_flag; / mount flags + unsigned long f_namemax; // maximum filename length + }; + */ + + st->f_bsize = bsize; + st->f_frsize = st->f_bsize; + st->f_blocks = cap/st->f_bsize; + st->f_bfree = (cap-used)/st->f_bsize; + st->f_bavail = st->f_bfree; + st->f_files = 1000; + st->f_ffree = 500; + st->f_favail = 500; + st->f_fsid = 1023; + st->f_flag = ST_RDONLY | ST_NOSUID; + st->f_namemax = 1023; + + return 0; +} + +static int dfs_access(const char *path, int mask) +{ + // no permissions on dfs, always a success + return 0; +} + +// +// The remainder are write functionality and therefore not implemented right now +// + + +static char **protectedpaths; + + +static int dfs_mkdir(const char *path, mode_t mode) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(dfs); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + assert('/' == *path); + + int i ; + for (i = 0; protectedpaths[i]; i++) { + if (strcmp(path, protectedpaths[i]) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to create the directory: %s", path); + return -EACCES; + } + } + + + if (dfs->nowrites || hdfsCreateDirectory(dfs->fs, path)) { + syslog(LOG_ERR,"ERROR: hdfs trying to create directory %s",path); + return -EIO; + } + + return 0; + +} + +static int dfs_rename(const char *from, const char *to) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(from); + assert(to); + assert(dfs); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + assert('/' == *from); + assert('/' == *to); + + int i ; + for (i = 0; protectedpaths[i] != NULL; i++) { + if (strcmp(from, protectedpaths[i]) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to rename directories %s to %s",from,to); + return -EACCES; + } + if (strcmp(to, protectedpaths[i]) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to rename directories %s to %s",from,to); + return -EACCES; + } + } + + if (dfs->nowrites || hdfsRename(dfs->fs, from, to)) { + syslog(LOG_ERR,"ERROR: hdfs trying to rename %s to %s",from, to); + return -EIO; + } + return 0; + +} + + +static int dfs_rmdir(const char *path) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(dfs); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + assert('/' == *path); + + int i ; + for (i = 0; protectedpaths[i]; i++) { + if (strcmp(path, protectedpaths[i]) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to delete the directory: %s ",path); + return -EACCES; + } + } + + int numEntries = 0; + hdfsFileInfo *info = hdfsListDirectory(dfs->fs,path,&numEntries); + + // free the info pointers + hdfsFreeFileInfo(info,numEntries); + + if (numEntries) { + return -ENOTEMPTY; + } + + + + // since these commands go through the programmatic hadoop API, there is no + // trash feature. So, force it here. + // But make sure the person isn't deleting from Trash itself :) + // NOTE: /Trash is in protectedpaths so they cannot delete all of trash + if (!dfs->no_trash && strncmp(path, "/Trash", strlen("/Trash")) != 0) { + + char target[4096]; + char dir[4096]; + int status; + + { + // find the directory and full targets in Trash + + sprintf(target, "/Trash/Current%s",path); + + // strip off the actual file or directory name from the fullpath + char *name = rindex(path, '/'); + assert(name); + *name = 0; + + // use that path to ensure the directory exists in the Trash dir + // prepend Trash to the directory + sprintf(dir,"/Trash/Current%s/",path); + + // repair the path not used again but in case the caller expects it. + *name = '/'; + } + + // if the directory doesn't already exist in the Trash + // then we go through with the rename + if ( hdfsExists(dfs->fs, target) != 0) { // 0 means it exists. weird + // make the directory to put it in in the Trash + if ((status = dfs_mkdir(dir,0)) != 0) { + return status; + } + + // do the rename + return dfs_rename(path,target); + + } + // if the directory exists in the Trash, then we don't bother doing the rename + // and just delete the existing one by falling though. + } + + if (dfs->nowrites || hdfsDelete(dfs->fs, path)) { + syslog(LOG_ERR,"ERROR: hdfs trying to delete the directory %s",path); + return -EIO; + } + return 0; +} + + +static int dfs_unlink(const char *path) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(dfs); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + assert('/' == *path); + + int i ; + for (i = 0; protectedpaths[i]; i++) { + if (strcmp(path, protectedpaths[i]) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to delete the directory: %s ",path); + return -EACCES; + } + } + + + + // since these commands go through the programmatic hadoop API, there is no + // trash feature. So, force it here. + // But make sure the person isn't deleting from Trash itself :) + // NOTE: /Trash is in protectedpaths so they cannot delete all of trash + if (!dfs->no_trash && strncmp(path, "/Trash", strlen("/Trash")) != 0) { + + char target[4096]; + char dir[4096]; + int status; + + { + // find the directory and full targets in Trash + + sprintf(target, "/Trash/Current%s",path); + + // strip off the actual file or directory name from the fullpath + char *name = rindex(path, '/'); + assert(name); + *name = 0; + + // use that path to ensure the directory exists in the Trash dir + // prepend Trash to the directory + sprintf(dir,"/Trash/Current%s/",path); + + // repair the path not used again but in case the caller expects it. + *name = '/'; + } + + // if this is a file and it's already got a copy in the Trash, to be conservative, we + // don't do the delete. + if (hdfsExists(dfs->fs, target) == 0) { + syslog(LOG_ERR,"ERROR: hdfs trying to delete a file that was already deleted so cannot back it to Trash: %s",target); + return -EIO; + } + + // make the directory to put it in in the Trash + if ((status = dfs_mkdir(dir,0)) != 0) { + return status; + } + + // do the rename + return dfs_rename(path,target); + } + + if (dfs->nowrites || hdfsDelete(dfs->fs, path)) { + syslog(LOG_ERR,"ERROR: hdfs trying to delete the file %s",path); + return -EIO; + } + return 0; + +} + +static int dfs_chmod(const char *path, mode_t mode) +{ + (void)path; + (void)mode; + return -ENOTSUP; +} + +static int dfs_chown(const char *path, uid_t uid, gid_t gid) +{ + (void)path; + (void)uid; + (void)gid; + return -ENOTSUP; +} + +static int dfs_truncate(const char *path, off_t size) +{ + (void)path; + (void)size; + return -ENOTSUP; +} + +long tempfh = 0; + +static int dfs_open(const char *path, struct fuse_file_info *fi) +{ + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert('/' == *path); + assert(dfs); + + int ret = 0; + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + // 0x8000 is always passed in and hadoop doesn't like it, so killing it here + // bugbug figure out what this flag is and report problem to Hadoop JIRA + int flags = (fi->flags & 0x7FFF); + +#ifdef OPTIMIZED_READS + // retrieve dfs specific data + dfs_fh *fh = (dfs_fh*)malloc(sizeof (dfs_fh)); + fi->fh = (uint64_t)fh; + fh->hdfsFH = (hdfsFile)hdfsOpenFile(dfs->fs, path, flags, 0, 3, 0); + fh->buf = (char*)malloc(rd_cache_buf_size*sizeof (char)); + fh->startOffset = 0; + fh->sizeBuffer = 0; + + if (0 == fh->hdfsFH) { + syslog(LOG_ERR, "ERROR: could not open file %s dfs %s:%d\n", path,__FILE__, __LINE__); + ret = -EIO; + } +#else + + // retrieve dfs specific data + fi->fh = (uint64_t)hdfsOpenFile(dfs->fs, path, flags, 0, 3, 0); + + if (0 == fi->fh) { + syslog(LOG_ERR, "ERROR: could not open file %s dfs %s:%d\n", path,__FILE__, __LINE__); + ret = -EIO; + } + +#endif + + return ret; +} + +static int dfs_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(dfs); + assert('/' == *path); + + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } +#ifdef OPTIMIZED_READS + + dfs_fh *fh = (dfs_fh*)fi->fh; + hdfsFile file_handle = (hdfsFile)fh->hdfsFH; + +#else + hdfsFile file_handle = (hdfsFile)fi->fh; + + if (NULL == file_handle) { + syslog(LOG_ERR, "ERROR: fuse problem - no file_handle for %s %s:%d\n",path, __FILE__, __LINE__); + return -EIO; + } +#endif + + // syslog(LOG_DEBUG,"hdfsTell(dfs,%ld)\n",(long)file_handle); +// tOffset cur_offset = hdfsTell(dfs->fs, file_handle); + + // if (cur_offset != offset) { + // syslog(LOG_ERR, "ERROR: user trying to random access write to a file %d!=%d for %s %s:%d\n",(int)cur_offset, (int)offset,path, __FILE__, __LINE__); +// return -EIO; +// } + + + syslog(LOG_DEBUG,"hdfsWrite(dfs,%ld,'%s',%d)\n",(long)file_handle,buf,(int)size); + tSize length = hdfsWrite(dfs->fs, file_handle, buf, size); + + + if (length != size) { + syslog(LOG_ERR, "ERROR: fuse problem - could not write all the bytes for %s %d!=%d%s:%d\n",path,length,(int)size, __FILE__, __LINE__); + return -EIO; + } + return 0; + +} + +int dfs_release (const char *path, struct fuse_file_info *fi) { + + // retrieve dfs specific data + dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data; + + // check params and the context var + assert(path); + assert(dfs); + assert('/' == *path); + // if not connected, try to connect and fail out if we can't. + if (NULL == dfs->fs && NULL == (dfs->fs = hdfsConnect(dfs->nn_hostname,dfs->nn_port))) { + syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__); + return -EIO; + } + + if (NULL == (void*)fi->fh) { + return 0; + } + +#ifdef OPTIMIZED_READS + dfs_fh *fh = (dfs_fh*)fi->fh; + hdfsFile file_handle = (hdfsFile)fh->hdfsFH; + free(fh->buf); + free(fh); + +#else + hdfsFile file_handle = (hdfsFile)fi->fh; +#endif + + if (NULL == file_handle) { + return 0; + } + + if (hdfsCloseFile(dfs->fs, file_handle) != 0) { + syslog(LOG_ERR, "ERROR: dfs problem - could not close file_handle for %s %s:%d\n",path, __FILE__, __LINE__); + return -EIO; + } + + fi->fh = (uint64_t)0; + return 0; +} + +static int dfs_mknod(const char *path, mode_t mode, dev_t rdev) { + syslog(LOG_DEBUG,"in dfs_mknod"); + return 0; +} + +static int dfs_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + syslog(LOG_DEBUG,"in dfs_create"); + fi->flags |= mode; + + return dfs_open(path, fi); +} +int dfs_flush(const char *path, struct fuse_file_info *fi) { + return 0; +} + + +void dfs_setattr(struct stat *attr, int to_set, struct fuse_file_info *fi) +{ + +} + +void dfs_destroy (void *ptr) +{ + dfs_context *dfs = (dfs_context*)ptr; + hdfsDisconnect(dfs->fs); + dfs->fs = NULL; +} + + +// Hacked up function to basically do: +// protectedpaths = split(PROTECTED_PATHS,','); + +static void init_protectedpaths() { + // PROTECTED_PATHS should be a #defined value from autoconf + // set it with configure --with-protectedpaths=/,/user,/user/foo + // note , seped with no other spaces and no quotes around it + char *tmp = PROTECTED_PATHS; + + assert(tmp); + + // handle degenerate case up front. + if (0 == *tmp) { + protectedpaths = (char**)malloc(sizeof(char*)); + protectedpaths[0] = NULL; + return; + } + + int i = 0; + while (tmp && (NULL != (tmp = index(tmp,',')))) { + tmp++; // pass the , + i++; + } + i++; // for the last entry + i++; // for the final NULL + protectedpaths = (char**)malloc(sizeof(char*)*i); + printf("i=%d\n",i); + tmp = PROTECTED_PATHS; + int j = 0; + while (NULL != tmp && j < i) { + int length; + char *eos = index(tmp,','); + if (NULL != eos) { + length = eos - tmp; // length of this value + } else { + length = strlen(tmp); + } + protectedpaths[j] = (char*)malloc(sizeof(char)*length+1); + strncpy(protectedpaths[j], tmp, length); + protectedpaths[j][length] = '\0'; + if (eos) { + tmp = eos + 1; + } else { + tmp = NULL; + } + j++; + } + protectedpaths[j] = NULL; + /* + j = 0; + while (protectedpaths[j]) { + printf("protectedpaths[%d]=%s\n",j,protectedpaths[j]); + fflush(stdout); + j++; + } + exit(1); + */ +} + + + +void *dfs_init() +{ + + // + // Create a private struct of data we will pass to fuse here and which + // will then be accessible on every call. + // + dfs_context *dfs = (dfs_context*)malloc(sizeof (dfs_context)); + + if (NULL == dfs) { + syslog(LOG_ERR, "FATAL: could not malloc fuse dfs context struct - out of memory %s:%d", __FILE__, __LINE__); + exit(1); + } + + // initialize the context + dfs->debug = options.debug; + dfs->nn_hostname = options.server; + dfs->nn_port = options.port; + dfs->fs = NULL; + dfs->nowrites = options.nowrites; + dfs->no_trash = options.no_trash; + + bzero(dfs->dfs_uri,0); + sprintf(dfs->dfs_uri,"dfs://%s:%d/",dfs->nn_hostname,dfs->nn_port); + dfs->dfs_uri_len = strlen(dfs->dfs_uri); + + // use ERR level to ensure it makes it into the log. + syslog(LOG_ERR, "mounting %s", dfs->dfs_uri); + + init_protectedpaths(); + + return (void*)dfs; +} + + +static struct fuse_operations dfs_oper = { + .getattr = dfs_getattr, + .access = dfs_access, + .readdir = dfs_readdir, + .destroy = dfs_destroy, + .init = dfs_init, + .open = dfs_open, + .read = dfs_read, + .statfs = dfs_statfs, + .mkdir = dfs_mkdir, + .rmdir = dfs_rmdir, + .rename = dfs_rename, + .unlink = dfs_unlink, + .release = dfs_release, + // .create = dfs_create, + // .write = dfs_write, + // .flush = dfs_flush, + //.xsetattr = dfs_setattr, + // .mknod = dfs_mknod, + .chmod = dfs_chmod, + .chown = dfs_chown, + // .truncate = dfs_truncate, +}; + + +int main(int argc, char *argv[]) +{ + umask(0); + + program = argv[0]; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + + /* clear structure that holds our options */ + memset(&options, 0, sizeof(struct options)); + + if (fuse_opt_parse(&args, &options, dfs_opts, dfs_options) == -1) + /** error parsing options */ + return -1; + + if (options.server == NULL || options.port == 0) { + print_usage(argv[0]); + exit(0); + } + int ret = fuse_main(args.argc, args.argv, &dfs_oper, NULL); + + if (ret) printf("\n"); + + /** free arguments */ + fuse_opt_free_args(&args); + + return ret; +} Index: src/contrib/fuse-dfs/src/fuse_dfs_wrapper.sh =================================================================== --- src/contrib/fuse-dfs/src/fuse_dfs_wrapper.sh (revision 0) +++ src/contrib/fuse-dfs/src/fuse_dfs_wrapper.sh (revision 0) @@ -0,0 +1,37 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if [ "$HADOOP_HOME" = "" ]; then + HADOOP_HOME=/usr/local/share/hadoop +fi + +for f in ls $HADOOP_HOME/lib/*.jar $HADOOP_HOME/*.jar ; do + CLASSPATH=$CLASSPATH:$f +done + +if [ "$OS_ARCH" = "" ]; then + OS_ARCH=amd64 +fi + +if [ "$LD_LIBRARY_PATH" = "" ]; then + LD_LIBRARY_PATH=/usr/local/java/jre/lib/$OS_ARCH/server:/usr/local/share/hdfs/libhdfs/:/usr/local/lib +fi + +if [ "$JAVA_HOME" = "" ]; then + JAVA_HOME=/usr/local/java +fi + +./fuse_dfs $@ -o-o allow_other Index: src/contrib/fuse-dfs/src/Makefile.am =================================================================== --- src/contrib/fuse-dfs/src/Makefile.am (revision 0) +++ src/contrib/fuse-dfs/src/Makefile.am (revision 0) @@ -0,0 +1,20 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +bin_PROGRAMS = fuse_dfs +fuse_dfs_SOURCES = fuse_dfs.c +AM_CPPFLAGS= -D_FILE_OFFSET_BITS=64 -I$(JAVA_HOME)/include -I$(HADOOP_HOME)/src/c++/libhdfs/ -I$(JAVA_HOME)/include/linux/ -D_FUSE_DFS_VERSION=\"$(PACKAGE_VERSION)\" -DPROTECTED_PATHS=\"$(PROTECTED_PATHS)\" +AM_LDFLAGS= -L$(HADOOP_HOME)/build/libhdfs -lhdfs -L$(FUSE_HOME)/lib -lfuse -L$(JAVA_HOME)/jre/lib/$(OS_ARCH)/server -ljvm + Index: src/contrib/fuse-dfs/Makefile.am =================================================================== --- src/contrib/fuse-dfs/Makefile.am (revision 0) +++ src/contrib/fuse-dfs/Makefile.am (revision 0) @@ -0,0 +1,27 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +@GLOBAL_HEADER_MK@ + +@PRODUCT_MK@ + +SUBDIRS = . src + +clean: + rm -rf autom4te.cache config.guess config.log config.status config.sub configure depcomp src/.deps install-sh Makefile.in src/Makefile.in src/Makefile missing Makefile src/fuse_dfs.o src/fuse_dfs + + +@GLOBAL_FOOTER_MK@ Index: src/contrib/fuse-dfs/README =================================================================== --- src/contrib/fuse-dfs/README (revision 0) +++ src/contrib/fuse-dfs/README (revision 0) @@ -0,0 +1,97 @@ +# Copyright 2005 The Apache Software Foundation Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. You may obtain a copy +# of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless +# required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. + +This is a FUSE module for Hadoop's HDFS. + +It allows one to mount HDFS as a Unix filesystem and optionally export +that mount point to other machines. + +For now, writes are disabled as this requires Hadoop-1700 - file +appends which I guess won't be ready till 0.18 ish ??. + +rmdir, mv, mkdir, rm are all supported. just not cp, touch, ... + +BUILDING: + + +Requirements: + + 1. a Linux kernel > 2.6.9 or a kernel module from FUSE - i.e., you + compile it yourself and then modprobe it. Better off with the + former option if possible. (Note for now if you use the kernel + with fuse included, it doesn't allow you to export this through NFS + so be warned. See the FUSE email list for more about this.) + + 2. FUSE should be installed in /usr/local or FUSE_HOME ant + environment variable + +To build: + + 1. ant compile-contrib-fuse -Dfusedfs=1 in HADOOP_HOME + + +NOTE: for amd64 architecture, libhdfs will not compile unless you edit +the Makefile in src/c++/libhdfs/Makefile and set OS_ARCH=amd64 +(probably the same for others too). + +-------------------------------------------------------------------------------- + +CONFIGURING: + +Look at all the paths in fuse_dfs_wrapper.sh and either correct them +or set them in your environment before running. (note for automount +and mount as root, you probably cannnot control the environment, so +best to set them in the wrapper) + +INSTALLING: + +1. mkdir /mnt/dfs (or wherever you want to mount it) + +2. ./fuse_dfs_wrapper.sh dfs://hadoop_server1.foo.com:9000 /mnt/dfs -d +; and from another terminal, try ls /mnt/dfs + +If 2 works, try again dropping the debug mode, i.e., -d + +(note - common problems are that you don't have libhdfs.so or +libjvm.so or libfuse.so on your LD_LIBRARY_PATH. + +-------------------------------------------------------------------------------- + + +DEPLOYING: + +in a root shell do the following: + +1. add the following to /etc/fstab - + fuse_dfs#dfs://hadoop_server.foo.com:9000 /mnt/dfs fuse + allow_other,rw 0 0 + +2. mount /mnt/dfs Expect problems with not finding fuse_dfs. You will + need to probably add this to /sbin and then problems finding the + above 3 libraries. Add these using ldconfig. + +-------------------------------------------------------------------------------- + + +EXPORTING: + +Add the following to /etc/exports: + + /mnt/hdfs *.foo.com(no_root_squash,rw,fsid=1,sync) + +NOTE - you cannot export this with a FUSE module built into the kernel +- e.g., kernel 2.6.17. For info on this, refer to the FUSE wiki. +-------------------------------------------------------------------------------- + +ADVANCED: + +you may want to ensure certain directories cannot be deleted from the +shell until the FS has permissions. You can set this in the build.xml +file in src/contrib/fuse-dfs/build.xml Index: src/contrib/fuse-dfs/aclocal.m4 =================================================================== --- src/contrib/fuse-dfs/aclocal.m4 (revision 0) +++ src/contrib/fuse-dfs/aclocal.m4 (revision 0) @@ -0,0 +1,851 @@ +# generated automatically by aclocal 1.9.5 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Copyright (C) 2002, 2003, 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# 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"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.9.5])]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 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 7 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +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]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + + +# Copyright (C) 1999, 2000, 2001, 2002, 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 8 + +# 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, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +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], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + 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/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 + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 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 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # 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 + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 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 12 + +# 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. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# 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 +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]) +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# 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"} +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 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 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 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 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 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 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# 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 +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 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. + +# 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.) +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])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 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 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 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 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +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" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 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 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([acinclude.m4]) Index: src/contrib/fuse-dfs/build.xml =================================================================== --- src/contrib/fuse-dfs/build.xml (revision 0) +++ src/contrib/fuse-dfs/build.xml (revision 0) @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/contrib/fuse-dfs/global_header.mk =================================================================== --- src/contrib/fuse-dfs/global_header.mk (revision 0) +++ src/contrib/fuse-dfs/global_header.mk (revision 0) @@ -0,0 +1,50 @@ +# +# Copyright 2005 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +ifneq ($$(XBUILT_SOURCES),) + XBUILT_SOURCES := $$(XBUILT_SOURCES) $$(XTARGET) +else + XBUILT_SOURCES := $$(XTARGET) +endif + +showvars: + @echo BUILD_SOURCES = $(BUILT_SOURCES) + @echo XBUILTSOURCES = $(XBUILT_SOURCES) + @echo DEFS = $(DEFS) + @echo CXXFLAGS = $(CXXFLAGS) + @echo AM_CXXFLAGS = $(AM_CXXFLAGS) + @echo CPPFLAGS = $(CPPFLAGS) + @echo AM_CPPFLAGS = $(AM_CPPFLAGS) + @echo LDFLAGS = $(LDFLAGS) + @echo AM_LDFLAGS = $(AM_LDFLAGS) + @echo LDADD = $(LDADD) + @echo LIBS = $(LIBS) + @echo EXTERNAL_LIBS = $(EXTERNAL_LIBS) + @echo EXTERNAL_PATH = $(EXTERNAL_PATH) + @echo MAKE = $(MAKE) + @echo MAKE_FLAGS = $(MAKE_FLAGS) + @echo AM_MAKEFLAGS = $(AM_MAKEFLAGS) + @echo top_builddir = $(top_builddir) + @echo top_srcdir = $(top_srcdir) + @echo srcdir = $(srcdir) + @echo PHPVAL = $(PHPVAL) + @echo PHPCONFIGDIR = $(PHPCONFIGDIR) + @echo PHPCONFIGINCLUDEDIR = $(PHPCONFIGINCLUDEDIR) + @echo PHPCONFIGINCLUDES = $(PHPCONFIGINCLUDES) + @echo PHPCONFIGLDFLAGS = $(PHPCONFIGLDFLAGS) + @echo PHPCONFIGLIBS = $(PHPCONFIGLIBS) + +clean-common: + rm -rf gen-* Index: build.xml =================================================================== --- build.xml (revision 652674) +++ build.xml (working copy) @@ -367,7 +367,7 @@ depends="clover,compile-core-classes,compile-core-native,compile-c++" description="Compile core only"> - +