Переглянути джерело

Support off64_t for Android build

Android NDK R8e does not provide ftruncate64, but bionic has the
assembler code to access kernel function. We borrowed those
ftruncate64.S files from android source code repository.  It turns out
that x86 asm.h in NDK R8e is also broken, so latest asm.h was also
borrowed.
Tatsuhiro Tsujikawa 12 роки тому
батько
коміт
5bc5665c6a

+ 24 - 1
configure.ac

@@ -67,6 +67,7 @@ AC_PROG_CC
 AC_PROG_INSTALL
 AC_PROG_MKDIR_P
 AC_PROG_YACC
+AM_PROG_AS
 
 AC_CHECK_TOOL([AR], [ar], [:])
 if test "x$AR" = "x:"; then
@@ -123,7 +124,14 @@ if test "x$with_libz" = "xyes"; then
   fi
   if test "x$have_zlib" = "xyes"; then
     AC_DEFINE([HAVE_ZLIB], [1], [Define to 1 if you have zlib.])
-    AC_CHECK_FUNCS([gzbuffer gzsetparams])
+    # Android NDK arch-mips contains gzbuffer symbol but it is missing
+    # in zlib.h
+    AC_CHECK_DECL([gzbuffer], [have_decl_gzbuffer=yes], [],
+                  [[#include <zlib.h>]])
+    if test "x$have_decl_gzbuffer" = "xyes"; then
+      AC_CHECK_FUNC([gzbuffer])
+    fi
+    AC_CHECK_FUNCS([gzsetparams])
   fi
 fi
 
@@ -815,11 +823,26 @@ AC_SUBST([bashcompletiondir])
 case "$host" in
   *android*)
     LIBS="$LIBS -lstdc++ -lsupc++"
+    case "$host" in
+      arm-*)
+        android_arm=yes
+        ;;
+      mipsel-*)
+        android_mips=yes
+        ;;
+      i686-*)
+        android_x86=yes
+        ;;
+    esac
     ;;
   *)
     ;;
 esac
 
+AM_CONDITIONAL([ANDROID_ARM], [test "x$android_arm" = "xyes"])
+AM_CONDITIONAL([ANDROID_MIPS], [test "x$android_mips" = "xyes"])
+AM_CONDITIONAL([ANDROID_X86], [test "x$android_x86" = "xyes"])
+
 if test "x$ARIA2_STATIC" = "xyes"; then
   LDFLAGS="$LDFLAGS -all-static -static-libgcc -static-libstdc++"
   dnl For non-MinGW build, we need additional libs for static build.

+ 2 - 2
src/AbstractDiskWriter.cc

@@ -324,7 +324,7 @@ void AbstractDiskWriter::seek(int64_t offset)
   fileLength.QuadPart = offset;
   if(SetFilePointerEx(fd_, fileLength, 0, FILE_BEGIN) == 0)
 #else // !__MINGW32__
-  if(a2lseek(fd_, offset, SEEK_SET) == (off_t)-1)
+  if(a2lseek(fd_, offset, SEEK_SET) == (a2_off_t)-1)
 #endif // !__MINGW32__
     {
       int errNum = fileError();
@@ -453,7 +453,7 @@ void AbstractDiskWriter::truncate(int64_t length)
   seek(length);
   if(SetEndOfFile(fd_) == 0)
 #else // !__MINGW32__
-  if(ftruncate(fd_, length) == -1)
+  if(a2ftruncate(fd_, length) == -1)
 #endif // !__MINGW32__
     {
       int errNum = fileError();

+ 1 - 1
src/FtpNegotiationCommand.cc

@@ -493,7 +493,7 @@ bool FtpNegotiationCommand::recvSize() {
     return false;
   }
   if(status == 213) {
-    if(size > std::numeric_limits<off_t>::max()) {
+    if(size > std::numeric_limits<a2_off_t>::max()) {
       throw DL_ABORT_EX2(fmt(EX_TOO_LARGE_FILE, size),
                          error_code::FTP_PROTOCOL_ERROR);
     }

+ 4 - 4
src/HttpHeader.cc

@@ -100,7 +100,7 @@ Range HttpHeader::getRange() const
       if(!util::parseLLIntNoThrow(contentLength, clenStr) ||
          contentLength < 0) {
         throw DL_ABORT_EX("Content-Length must be positive integer");
-      } else if(contentLength > std::numeric_limits<off_t>::max()) {
+      } else if(contentLength > std::numeric_limits<a2_off_t>::max()) {
         throw DOWNLOAD_FAILURE_EXCEPTION
           (fmt(EX_TOO_LARGE_FILE, contentLength));
       } else if(contentLength == 0) {
@@ -146,13 +146,13 @@ Range HttpHeader::getRange() const
      startByte < 0 || endByte < 0 || entityLength < 0) {
     throw DL_ABORT_EX("byte-range-spec must be positive");
   }
-  if(startByte > std::numeric_limits<off_t>::max()) {
+  if(startByte > std::numeric_limits<a2_off_t>::max()) {
     throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, startByte));
   }
-  if(endByte > std::numeric_limits<off_t>::max()) {
+  if(endByte > std::numeric_limits<a2_off_t>::max()) {
     throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, endByte));
   }
-  if(entityLength > std::numeric_limits<off_t>::max()) {
+  if(entityLength > std::numeric_limits<a2_off_t>::max()) {
     throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, entityLength));
   }
   return Range(startByte, endByte, entityLength);

+ 14 - 0
src/Makefile.am

@@ -256,6 +256,20 @@ SRCS =  option_processing.cc\
 	FtpNegotiationConnectChain.h\
 	FtpTunnelRequestConnectChain.h
 
+# Android NDK R8e does not provide ftruncate64. Use assembly code from
+# android source code and link it.
+if ANDROID_ARM
+SRCS += android/arm-ftruncate64.S
+endif # ANDROID_ARM
+
+if ANDROID_MIPS
+SRCS += android/mips-ftruncate64.S
+endif # ANDROID_MIPS
+
+if ANDROID_X86
+SRCS += android/x86-ftruncate64.S android/x86-asm.h
+endif # ANDROID_X86
+
 if MINGW_BUILD
 SRCS += WinConsoleFile.cc WinConsoleFile.h
 endif # MINGW_BUILD

+ 1 - 1
src/MetalinkParserStateV3Impl.cc

@@ -150,7 +150,7 @@ void SizeMetalinkParserState::endElement
   // current metalink specification doesn't require size element.
   int64_t size;
   if(util::parseLLIntNoThrow(size, characters) && size >= 0 &&
-     size <= std::numeric_limits<off_t>::max()) {
+     size <= std::numeric_limits<a2_off_t>::max()) {
     psm->setFileLengthOfEntry(size);
   }
 }

+ 1 - 1
src/MetalinkParserStateV4Impl.cc

@@ -255,7 +255,7 @@ void SizeMetalinkParserStateV4::endElement
 {
   int64_t size;
   if(util::parseLLIntNoThrow(size, characters) && size >= 0 &&
-     size <= std::numeric_limits<off_t>::max()) {
+     size <= std::numeric_limits<a2_off_t>::max()) {
     psm->setFileLengthOfEntry(size);
   } else {
     psm->cancelEntryTransaction();

+ 34 - 2
src/a2io.h

@@ -141,7 +141,37 @@
 // For Windows, we share files for reading and writing.
 # define a2open(path, flags, mode) _wsopen(path, flags, _SH_DENYNO, mode)
 # define a2fopen(path, mode) _wfsopen(path, mode, _SH_DENYNO)
-#else // !__MINGW32__
+// # define a2ftruncate(fd, length): We don't use ftruncate in Mingw build
+# define a2_off_t off_t
+#elif defined(__ANDROID__) || defined(ANDROID)
+# define a2lseek(fd, offset, origin) lseek64(fd, offset, origin)
+// # define a2fseek(fp, offset, origin): No fseek64 and not used in aria2
+# define a2fstat(fd, buf) fstat64(fd, buf)
+// # define a2ftell(fd): No ftell64 and not used in aria2
+# define a2_struct_stat struct stat
+# define a2stat(path, buf) stat64(path, buf)
+# define a2mkdir(path, openMode) mkdir(path, openMode)
+# define a2utimbuf utimbuf
+# define a2utime(path, times) ::utime(path, times)
+# define a2unlink(path) unlink(path)
+# define a2rmdir(path) rmdir(path)
+# define a2rename(src, dest) rename(src, dest)
+# define a2open(path, flags, mode) open(path, flags, mode)
+# define a2fopen(path, mode) fopen(path, mode)
+// Android NDK R8e does not provide ftruncate64 prototype, so let's
+// define it here.
+#ifdef  __cplusplus
+extern "C" {
+#endif
+extern int ftruncate64(int fd, off64_t length);
+#ifdef __cplusplus
+}
+#endif
+# define a2ftruncate(fd, length) ftruncate64(fd, length)
+// Use off64_t directly since android does not offer transparent
+// switching between off_t and off64_t.
+# define a2_off_t off64_t
+#else // !__MINGW32__ && !(defined(__ANDROID__) || defined(ANDROID))
 # define a2lseek(fd, offset, origin) lseek(fd, offset, origin)
 # define a2fseek(fp, offset, origin) fseek(fp, offset, origin)
 # define a2fstat(fp, buf) fstat(fp, buf)
@@ -156,7 +186,9 @@
 # define a2rename(src, dest) rename(src, dest)
 # define a2open(path, flags, mode) open(path, flags, mode)
 # define a2fopen(path, mode) fopen(path, mode)
-#endif // !__MINGW32__
+# define a2ftruncate(fd, length) ftruncate(fd, length)
+# define a2_off_t off_t
+#endif
 
 #define OPEN_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
 #define DIR_OPEN_MODE S_IRWXU|S_IRWXG|S_IRWXO

+ 2 - 0
src/android/README.rst

@@ -0,0 +1,2 @@
+The files under this directory tree were copied from android source
+code repository.

+ 15 - 0
src/android/arm-ftruncate64.S

@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(ftruncate64)
+    mov     ip, r7
+    ldr     r7, =__NR_ftruncate64
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(ftruncate64)

+ 22 - 0
src/android/mips-ftruncate64.S

@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+    .text
+    .globl ftruncate64
+    .align 4
+    .ent ftruncate64
+
+ftruncate64:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_ftruncate64
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end ftruncate64

+ 218 - 0
src/android/x86-asm.h

@@ -0,0 +1,218 @@
+/*	$NetBSD: asm.h,v 1.40 2011/06/16 13:16:20 joerg Exp $	*/
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ *	@(#)asm.h	5.5 (Berkeley) 5/7/91
+ */
+
+#ifndef _I386_ASM_H_
+#define _I386_ASM_H_
+
+#ifdef _KERNEL_OPT
+#include "opt_multiprocessor.h"
+#endif
+
+#ifdef PIC
+#define PIC_PROLOGUE	\
+	pushl	%ebx;	\
+	call	1f;	\
+1:			\
+	popl	%ebx;	\
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+#define PIC_EPILOGUE	\
+	popl	%ebx
+#define PIC_PLT(x)	x@PLT
+#define PIC_GOT(x)	x@GOT(%ebx)
+#define PIC_GOTOFF(x)	x@GOTOFF(%ebx)
+#else
+#define PIC_PROLOGUE
+#define PIC_EPILOGUE
+#define PIC_PLT(x)	x
+#define PIC_GOT(x)	x
+#define PIC_GOTOFF(x)	x
+#endif
+
+#ifdef __ELF__
+# define _C_LABEL(x)	x
+#else
+# ifdef __STDC__
+#  define _C_LABEL(x)	_ ## x
+# else
+#  define _C_LABEL(x)	_/**/x
+# endif
+#endif
+#define	_ASM_LABEL(x)	x
+
+#define CVAROFF(x, y)		_C_LABEL(x) + y
+
+#ifdef __STDC__
+# define __CONCAT(x,y)	x ## y
+# define __STRING(x)	#x
+#else
+# define __CONCAT(x,y)	x/**/y
+# define __STRING(x)	"x"
+#endif
+
+/* let kernels and others override entrypoint alignment */
+#if !defined(_ALIGN_TEXT) && !defined(_KERNEL)
+# ifdef _STANDALONE
+#  define _ALIGN_TEXT .align 1
+# elif defined __ELF__
+#  define _ALIGN_TEXT .align 16
+# else
+#  define _ALIGN_TEXT .align 4
+# endif
+#endif
+
+#define _ENTRY(x) \
+	.text; _ALIGN_TEXT; .globl x; .type x,@function; x:
+#define _LABEL(x) \
+	.globl x; x:
+
+#ifdef _KERNEL
+
+#define CPUVAR(off) %fs:__CONCAT(CPU_INFO_,off)
+
+/* XXX Can't use __CONCAT() here, as it would be evaluated incorrectly. */
+#ifdef __ELF__
+#ifdef __STDC__
+#define	IDTVEC(name) \
+	ALIGN_TEXT; .globl X ## name; .type X ## name,@function; X ## name:
+#define	IDTVEC_END(name) \
+	.size X ## name, . - X ## name
+#else 
+#define	IDTVEC(name) \
+	ALIGN_TEXT; .globl X/**/name; .type X/**/name,@function; X/**/name:
+#define	IDTVEC_END(name) \
+	.size X/**/name, . - X/**/name
+#endif /* __STDC__ */ 
+#else 
+#ifdef __STDC__
+#define	IDTVEC(name) \
+	ALIGN_TEXT; .globl _X ## name; .type _X ## name,@function; _X ## name: 
+#define	IDTVEC_END(name) \
+	.size _X ## name, . - _X ## name
+#else
+#define	IDTVEC(name) \
+	ALIGN_TEXT; .globl _X/**/name; .type _X/**/name,@function; _X/**/name:
+#define	IDTVEC_END(name) \
+	.size _X/**/name, . - _X/**/name
+#endif /* __STDC__ */
+#endif /* __ELF__ */
+
+#ifdef _STANDALONE
+#define ALIGN_DATA	.align	4
+#define ALIGN_TEXT	.align	4	/* 4-byte boundaries */
+#define SUPERALIGN_TEXT	.align	16	/* 15-byte boundaries */
+#elif defined __ELF__
+#define ALIGN_DATA	.align	4
+#define ALIGN_TEXT	.align	16	/* 16-byte boundaries */
+#define SUPERALIGN_TEXT	.align	16	/* 16-byte boundaries */
+#else
+#define ALIGN_DATA	.align	2
+#define ALIGN_TEXT	.align	4	/* 16-byte boundaries */
+#define SUPERALIGN_TEXT	.align	4	/* 16-byte boundaries */
+#endif /* __ELF__ */
+
+#define _ALIGN_TEXT ALIGN_TEXT
+
+#ifdef GPROF
+#ifdef __ELF__
+#define	MCOUNT_ASM	call	_C_LABEL(__mcount)
+#else /* __ELF__ */
+#define	MCOUNT_ASM	call	_C_LABEL(mcount)
+#endif /* __ELF__ */
+#else /* GPROF */
+#define	MCOUNT_ASM	/* nothing */
+#endif /* GPROF */
+
+#endif /* _KERNEL */
+
+
+
+#ifdef GPROF
+# ifdef __ELF__
+#  define _PROF_PROLOGUE	\
+	pushl %ebp; movl %esp,%ebp; call PIC_PLT(__mcount); popl %ebp
+# else 
+#  define _PROF_PROLOGUE	\
+	pushl %ebp; movl %esp,%ebp; call PIC_PLT(mcount); popl %ebp
+# endif
+#else
+# define _PROF_PROLOGUE
+#endif
+
+#define	ENTRY(y)	_ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
+#define	NENTRY(y)	_ENTRY(_C_LABEL(y))
+#define	ASENTRY(y)	_ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+#define	LABEL(y)	_LABEL(_C_LABEL(y))
+#define	END(y)		.size y, . - y
+
+#define	ASMSTR		.asciz
+
+#ifdef __ELF__
+#define RCSID(x)	.pushsection ".ident"; .asciz x; .popsection
+#else
+#define RCSID(x)	.text; .asciz x
+#endif
+
+#ifdef NO_KERNEL_RCSIDS
+#define	__KERNEL_RCSID(_n, _s)	/* nothing */
+#else
+#define	__KERNEL_RCSID(_n, _s)	RCSID(_s)
+#endif
+
+#ifdef __ELF__
+#define	WEAK_ALIAS(alias,sym)						\
+	.weak alias;							\
+	alias = sym
+#endif
+/*
+ * STRONG_ALIAS: create a strong alias.
+ */
+#define STRONG_ALIAS(alias,sym)						\
+	.globl alias;							\
+	alias = sym
+
+#ifdef __STDC__
+#define	WARN_REFERENCES(sym,msg)					\
+	.pushsection .gnu.warning. ## sym;				\
+	.ascii msg;							\
+	.popsection
+#else
+#define	WARN_REFERENCES(sym,msg)					\
+	.pushsection .gnu.warning./**/sym;				\
+	.ascii msg;							\
+	.popsection
+#endif /* __STDC__ */
+
+#endif /* !_I386_ASM_H_ */

+ 28 - 0
src/android/x86-ftruncate64.S

@@ -0,0 +1,28 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+/* Android NDK R8e asm.h for x86 is broken. Use latest one from the repo */
+#include "android/x86-asm.h"
+#include <asm/unistd.h>
+
+ENTRY(ftruncate64)
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_ftruncate64, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
+END(ftruncate64)

+ 2 - 2
src/bittorrent_helper.cc

@@ -251,7 +251,7 @@ void extractFileEntries
         throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, length));
       }
       length += fileLengthData->i();
-      if(fileLengthData->i() > std::numeric_limits<off_t>::max()) {
+      if(fileLengthData->i() > std::numeric_limits<a2_off_t>::max()) {
         throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, length));
       }
       std::string pathKey;
@@ -310,7 +310,7 @@ void extractFileEntries
                          error_code::BITTORRENT_PARSE_ERROR);
     }
     int64_t totalLength = lengthData->i();
-    if(totalLength > std::numeric_limits<off_t>::max()) {
+    if(totalLength > std::numeric_limits<a2_off_t>::max()) {
       throw DOWNLOAD_FAILURE_EXCEPTION(fmt(EX_TOO_LARGE_FILE, totalLength));
     }
     // For each uri in urlList, if it ends with '/', then