From 4d2d5c4ace09a74420b74f1b9fbee04ecf5fa08b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Sep 2002 21:17:18 +0000 Subject: Added Solaris sendfile patch + configure tests from Pierre Belanger . Jeremy. (This used to be commit 9c17faefa5cb0ed450578ae5bbcca44e3058bc9b) --- source3/acconfig.h | 3 + source3/configure | 158 ++++++++++++++++++++++++++++++++++++++++---- source3/configure.in | 66 ++++++++++++++++++ source3/include/config.h.in | 3 + source3/lib/sendfile.c | 87 +++++++++++++++++++++++- 5 files changed, 300 insertions(+), 17 deletions(-) diff --git a/source3/acconfig.h b/source3/acconfig.h index 45d6366935..0d0da44887 100644 --- a/source3/acconfig.h +++ b/source3/acconfig.h @@ -230,3 +230,6 @@ #undef FREEBSD_SENDFILE_API #undef HPUX_SENDFILE_API #undef WITH_ADS +#undef HAVE_SENDFILEV +#undef HAVE_SENDFILEV64 +#undef SOLARIS_SENDFILE_API diff --git a/source3/configure b/source3/configure index 538f44621c..4e7b81d1ca 100755 --- a/source3/configure +++ b/source3/configure @@ -14208,7 +14208,137 @@ EOF else echo "$ac_t""no" 1>&6; fi + ;; + *solaris*) + LIBS="$LIBS -lsendfile" + echo $ac_n "checking for solaris sendfilev64 support""... $ac_c" 1>&6 +echo "configure:14217: checking for solaris sendfilev64 support" >&5 +if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILEV64'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext < +int main() { +\ + int sfvcnt; + size_t xferred; + struct sendfilevec vec[2]; + ssize_t nwritten; + + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = 0; + vec[0].sfv_len = 0; + + vec[1].sfv_fd = 0; + vec[1].sfv_flag = 0; + vec[1].sfv_off = 0; + vec[1].sfv_len = 0; + nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); + +; return 0; } +EOF +if { (eval echo configure:14249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + samba_cv_HAVE_SENDFILEV64=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + samba_cv_HAVE_SENDFILEV64=no +fi +rm -f conftest* +fi + +echo "$ac_t""$samba_cv_HAVE_SENDFILEV64" 1>&6 + + if test x"$samba_cv_HAVE_SENDFILEV64" = x"yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SENDFILEV64 1 +EOF + + cat >> confdefs.h <<\EOF +#define SOLARIS_SENDFILE_API 1 +EOF + + cat >> confdefs.h <<\EOF +#define WITH_SENDFILE 1 +EOF + + else + echo "$ac_t""no" 1>&6; + fi + + echo $ac_n "checking for solaris sendfilev support""... $ac_c" 1>&6 +echo "configure:14281: checking for solaris sendfilev support" >&5 +if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILEV'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext < +int main() { +\ + int sfvcnt; + size_t xferred; + struct sendfilevec vec[2]; + ssize_t nwritten; + + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = 0; + vec[0].sfv_len = 0; + + vec[1].sfv_fd = 0; + vec[1].sfv_flag = 0; + vec[1].sfv_off = 0; + vec[1].sfv_len = 0; + nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); + +; return 0; } +EOF +if { (eval echo configure:14313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + samba_cv_HAVE_SENDFILEV=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + samba_cv_HAVE_SENDFILEV=no +fi +rm -f conftest* +fi + +echo "$ac_t""$samba_cv_HAVE_SENDFILEV" 1>&6 + + if test x"$samba_cv_HAVE_SENDFILEV" = x"yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SENDFILEV 1 +EOF + + cat >> confdefs.h <<\EOF +#define SOLARIS_SENDFILE_API 1 +EOF + + cat >> confdefs.h <<\EOF +#define WITH_SENDFILE 1 +EOF + + else + echo "$ac_t""no" 1>&6; + fi ;; *) @@ -14232,7 +14362,7 @@ fi # (WINBIND_STARGETS) and shared libraries (WINBIND_LTARGETS). echo $ac_n "checking whether to build winbind""... $ac_c" 1>&6 -echo "configure:14236: checking whether to build winbind" >&5 +echo "configure:14366: checking whether to build winbind" >&5 # Initially, the value of $host_os decides whether winbind is supported @@ -14328,20 +14458,20 @@ fi # [#include ]) echo $ac_n "checking whether struct passwd has pw_comment""... $ac_c" 1>&6 -echo "configure:14332: checking whether struct passwd has pw_comment" >&5 +echo "configure:14462: checking whether struct passwd has pw_comment" >&5 if eval "test \"`echo '$''{'samba_cv_passwd_pw_comment'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { struct passwd p; p.pw_comment; ; return 0; } EOF -if { (eval echo configure:14345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14475: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* samba_cv_passwd_pw_comment=yes else @@ -14366,20 +14496,20 @@ fi # [#include ]) echo $ac_n "checking whether struct passwd has pw_age""... $ac_c" 1>&6 -echo "configure:14370: checking whether struct passwd has pw_age" >&5 +echo "configure:14500: checking whether struct passwd has pw_age" >&5 if eval "test \"`echo '$''{'samba_cv_passwd_pw_age'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { struct passwd p; p.pw_age; ; return 0; } EOF -if { (eval echo configure:14383: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14513: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* samba_cv_passwd_pw_age=yes else @@ -14418,7 +14548,7 @@ fi if test x"$INCLUDED_POPT" != x"yes"; then echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6 -echo "configure:14422: checking for poptGetContext in -lpopt" >&5 +echo "configure:14552: checking for poptGetContext in -lpopt" >&5 ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -14426,7 +14556,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpopt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:14571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -14461,7 +14591,7 @@ fi fi echo $ac_n "checking whether to use included popt""... $ac_c" 1>&6 -echo "configure:14465: checking whether to use included popt" >&5 +echo "configure:14595: checking whether to use included popt" >&5 if test x"$INCLUDED_POPT" = x"yes"; then echo "$ac_t""yes" 1>&6 BUILD_POPT='$(POPT_OBJS)' @@ -14507,16 +14637,16 @@ fi # final configure stuff echo $ac_n "checking configure summary""... $ac_c" 1>&6 -echo "configure:14511: checking configure summary" >&5 +echo "configure:14641: checking configure summary" >&5 if test "$cross_compiling" = yes; then echo "configure: warning: cannot run when cross-compiling" 1>&2 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:14650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""yes" 1>&6 else diff --git a/source3/configure.in b/source3/configure.in index 5221b8ec2b..cd9c8ecbaf 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -2855,7 +2855,73 @@ samba_cv_HAVE_SENDFILE=yes,samba_cv_HAVE_SENDFILE=no)]) else AC_MSG_RESULT(no); fi + ;; + + *solaris*) + LIBS="$LIBS -lsendfile" + AC_CACHE_CHECK([for solaris sendfilev64 support],samba_cv_HAVE_SENDFILEV64,[ + AC_TRY_LINK([\ +#include ], +[\ + int sfvcnt; + size_t xferred; + struct sendfilevec vec[2]; + ssize_t nwritten; + + sfvcnt = 2; + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = 0; + vec[0].sfv_len = 0; + + vec[1].sfv_fd = 0; + vec[1].sfv_flag = 0; + vec[1].sfv_off = 0; + vec[1].sfv_len = 0; + nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); +], +samba_cv_HAVE_SENDFILEV64=yes,samba_cv_HAVE_SENDFILEV64=no)]) + + if test x"$samba_cv_HAVE_SENDFILEV64" = x"yes"; then + AC_DEFINE(HAVE_SENDFILEV64) + AC_DEFINE(SOLARIS_SENDFILE_API) + AC_DEFINE(WITH_SENDFILE) + else + AC_MSG_RESULT(no); + fi + + AC_CACHE_CHECK([for solaris sendfilev support],samba_cv_HAVE_SENDFILEV,[ + AC_TRY_LINK([\ +#include ], +[\ + int sfvcnt; + size_t xferred; + struct sendfilevec vec[2]; + ssize_t nwritten; + + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = 0; + vec[0].sfv_len = 0; + + vec[1].sfv_fd = 0; + vec[1].sfv_flag = 0; + vec[1].sfv_off = 0; + vec[1].sfv_len = 0; + nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); +], +samba_cv_HAVE_SENDFILEV=yes,samba_cv_HAVE_SENDFILEV=no)]) + + if test x"$samba_cv_HAVE_SENDFILEV" = x"yes"; then + AC_DEFINE(HAVE_SENDFILEV) + AC_DEFINE(SOLARIS_SENDFILE_API) + AC_DEFINE(WITH_SENDFILE) + else + AC_MSG_RESULT(no); + fi ;; *) diff --git a/source3/include/config.h.in b/source3/include/config.h.in index 770af1a6b5..f1fab36d87 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -296,6 +296,9 @@ #undef FREEBSD_SENDFILE_API #undef HPUX_SENDFILE_API #undef WITH_ADS +#undef HAVE_SENDFILEV +#undef HAVE_SENDFILEV64 +#undef SOLARIS_SENDFILE_API /* The number of bytes in a int. */ #undef SIZEOF_INT diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 5d1cf2f10b..d2ecf3f94a 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -143,11 +143,92 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of #elif defined(SOLARIS_SENDFILE_API) -/* Hmmm. Can't find Solaris sendfile API docs.... Where is it ? */ +/* + * Solaris sendfile code written by Pierre Belanger . + */ + +#include + ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { - errno = ENOSYS; - return -1; + int sfvcnt; + size_t total, xferred; + struct sendfilevec vec[2]; + ssize_t hdr_len = 0; + + if (header) { + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = header->data; + vec[0].sfv_len = header->length; + + vec[1].sfv_fd = fromfd; + vec[1].sfv_flag = 0; + vec[1].sfv_off = offset; + vec[1].sfv_len = count; + + hdr_len = header->length; + } else { + sfvcnt = 1; + + vec[0].sfv_fd = fromfd; + vec[0].sfv_flag = 0; + vec[0].sfv_off = offset; + vec[0].sfv_len = count; + } + + total = count + hdr_len; + + while (total) { + ssize_t nwritten; + + /* + * Although not listed in the API error returns, this is almost certainly + * a slow system call and will be interrupted by a signal with EINTR. JRA. + */ + + xferred = 0; + +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64) + nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); +#else + nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); +#endif + if (nwritten == -1 && errno == EINTR) { + if (xferred == 0) + continue; /* Nothing written yet. */ + else + nwritten = xferred; + } + + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than vec[0].sfv_len bytes. + * We move vec[1].* to vec[0].* and set sfvcnt to 1 + */ + + if (sfvcnt == 2 && nwritten >= vec[0].sfv_len) { + vec[1].sfv_off += nwritten - vec[0].sfv_len; + vec[1].sfv_len -= nwritten - vec[0].sfv_len; + + /* Move vec[1].* to vec[0].* and set sfvcnt to 1 */ + vec[0] = vec[1]; + sfvcnt = 1; + } else { + vec[0].sfv_off += nwritten; + vec[0].sfv_len -= nwritten; + } + total -= nwritten; + } + return count + hdr_len; } #elif defined(HPUX_SENDFILE_API) -- cgit