Package: libesd0, esound-clients
Version: 0.2.36-1
Severity: normal
Tags: upstream patch

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Moin,

esddsp fails to esd-ify programs that use the 64-bit file offset
versions of open, fopen and mmap. This is, for instance, the case for
bash:
$ objdump -T /bin/bash | grep -E '(open|fopen|mmap)64'
00000000      DF *UND*  000000bf  GLIBC_2.1   open64
00000000      DF *UND*  00000024  GLIBC_2.1   fopen64
$

As bash calls open64 instead of open (because of a #define in fcntl.h),
libesdds0's open doesn't get called. You can verify this by running:
$ esddsp bash -c 'echo foo > /dev/dsp'
bash: /dev/dsp: Device or resource busy
$

This problem is not only specific to bash:
$ total=0; affected=0; for filename in /bin/* /usr/bin/*; do
  total=$((total+1)); objdump -T "$filename" 2>/dev/null | grep -qE
  '(open|fopen|mmap)64' && affected=$((affected+1)); done; echo "total:
  $total, affected: $affected"
total: 2788, affected: 404
$

A fix is attached.

Greets,
Sebastian

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFDocHivBVic1oTsEgRAnvsAJ963DjkHel7N0voXrYTfCUY419JUACeKpb/
1ytzksE8nq25JNYB8rEbDZw=
=DtU1
-----END PGP SIGNATURE-----
diff -ru esound-0.2.36.old/config.h.in esound-0.2.36/config.h.in
--- esound-0.2.36.old/config.h.in	2005-06-07 03:04:49.000000000 +0200
+++ esound-0.2.36/config.h.in	2005-12-15 19:14:08.270514120 +0100
@@ -81,6 +81,9 @@
 /* Define to 1 if you have the `fchown' function. */
 #undef HAVE_FCHOWN
 
+/* Define to 1 if you have the `fopen64' function. */
+#undef HAVE_FOPEN64
+
 /* Define to 1 if you have the `gethostbyname2' function. */
 #undef HAVE_GETHOSTBYNAME2
 
@@ -129,12 +132,18 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `mmap64' function. */
+#undef HAVE_MMAP64
+
 /* Define to 1 if you have the <mme/mme_api.h> header file. */
 #undef HAVE_MME_MME_API_H
 
 /* Defined if nanosleep() works */
 #undef HAVE_NANOSLEEP
 
+/* Define to 1 if you have the `open64' function. */
+#undef HAVE_OPEN64
+
 /* Define to 1 if you have the `putenv' function. */
 #undef HAVE_PUTENV
 
diff -ru esound-0.2.36.old/configure esound-0.2.36/configure
--- esound-0.2.36.old/configure	2005-06-07 03:04:13.000000000 +0200
+++ esound-0.2.36/configure	2005-12-15 19:14:10.624156312 +0100
@@ -21299,6 +21299,109 @@
 done
 
 
+
+
+for ac_func in open64 fopen64 mmap64
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
 use_inet_pton=no
 echo "$as_me:$LINENO: checking for inet_pton" >&5
 echo $ECHO_N "checking for inet_pton... $ECHO_C" >&6
diff -ru esound-0.2.36.old/configure.ac esound-0.2.36/configure.ac
--- esound-0.2.36.old/configure.ac	2005-06-07 03:03:55.000000000 +0200
+++ esound-0.2.36/configure.ac	2005-12-15 19:11:58.833191584 +0100
@@ -57,6 +57,7 @@
   AC_CHECK_LIB(rt,nanosleep,,[AC_CHECK_LIB(posix4,nanosleep)])])
 AC_CHECK_FUNCS(usleep)
 AC_CHECK_FUNCS(strtok_r)
+AC_CHECK_FUNCS(open64 fopen64 mmap64)
 
 use_inet_pton=no
 AC_CHECK_FUNC(inet_pton,use_inet_pton=yes,[AC_CHECK_LIB(resolv,inet_pton)])
diff -ru esound-0.2.36.old/esddsp.c esound-0.2.36/esddsp.c
--- esound-0.2.36.old/esddsp.c	2005-12-15 19:10:42.499796024 +0100
+++ esound-0.2.36/esddsp.c	2005-12-15 19:12:03.330507888 +0100
@@ -220,22 +220,22 @@
     }
 }
 
+typedef int (*open_funcptr_t) (const char *, int, mode_t);
+
+/* The wrap_* functions act as wrapper for both the 32-bit versions of
+ * the functions (open/mmap/fopen), as well as for the 64-bit ones
+ * (open64/mmap64/fopen64). Just to avoid massive code duplication.
+ *   -- Sebastian Schmidt <[EMAIL PROTECTED]>, 2005-12-15
+ */
 int
-open (const char *pathname, int flags, ...)
+wrap_open (const char *symname, open_funcptr_t *func, const char *pathname,
+                int flags, mode_t mode)
 {
-  static int (*func) (const char *, int, mode_t) = NULL;
-  va_list args;
-  mode_t mode;
-
-  if (!func) {
-    func = (int (*) (const char *, int, mode_t)) dlsym (REAL_LIBC, "open");
+  if (!*func) {
+    *func = (open_funcptr_t) dlsym (REAL_LIBC, symname);
     dsp_init ();
   }
 
-  va_start (args, flags);
-  mode = va_arg (args, mode_t);
-  va_end (args);
-
   if (!strcmp (pathname, "/dev/dsp"))
     {
 /* We shouldn't need this with Unix domain sockets, plus there
@@ -259,12 +259,47 @@
     }
   else if (use_mixer && !strcmp (pathname, "/dev/mixer"))
     {
-      DPRINTF ("hijacking /dev/mixer open, and taking it to esd...\n");
-      return (mixfd = (*func) (mixer, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
+      DPRINTF ("hijacking /dev/mixer %s, and taking it to esd...\n", symname);
+      return (mixfd = (**func) (mixer, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
     }
   else
-    return (*func) (pathname, flags, mode);
+    return (**func) (pathname, flags, mode);
+}
+
+int
+open (const char *pathname, int flags, ...)
+{
+  static open_funcptr_t func = NULL;
+  mode_t mode = 0;
+  va_list args;
+  
+  if (flags & O_CREAT) {
+    va_start(args, flags);
+    mode = va_arg(args, mode_t);
+    va_end(args);
+  }
+
+  return wrap_open("open", &func, pathname, flags, mode);
+}
+
+#ifdef HAVE_OPEN64
+int
+open64 (const char *pathname, int flags, ...)
+{
+  static open_funcptr_t func = NULL;
+  mode_t mode = 0;
+  va_list args;
+  
+  if (flags & O_CREAT) {
+    va_start(args, flags);
+    mode = va_arg(args, mode_t);
+    va_end(args);
+  }
+
+  return wrap_open("open64", &func, pathname, flags, mode);
 }
+#endif /* HAVE_OPEN64 */
+
 
 static int
 dspctl (int fd, request_t request, void *argp)
@@ -524,20 +559,21 @@
   return (*func) (fd);
 }
 
+typedef void *(*mmap_funcptr_t) (void *, size_t, int, int, int, off_t);
+
 void *
-mmap (void  *start,  size_t length, int prot, int flags, int fd, off_t offset)
+wrap_mmap (const char *symname, mmap_funcptr_t *func, void *start, 
+                size_t length, int prot, int flags, int fd, off_t offset)
 {
-  static void *(*func) (void *, size_t, int, int, int, off_t) = NULL;
-  
-  if (!func)
-    func = (void * (*) (void *, size_t, int, int, int, off_t)) dlsym (REAL_LIBC, "mmap");
+  if (!*func)
+    *func = (mmap_funcptr_t) dlsym (REAL_LIBC, symname);
 
   if(fd != sndfd || sndfd == -1)
-    return (*func)(start,length,prot,flags,fd,offset);
+    return (**func)(start,length,prot,flags,fd,offset);
   else
     {
-      DPRINTF ("esddsp: mmap - start = %x, length = %d, prot = %d\n",
-	       start, length, prot);
+      DPRINTF ("esddsp: %s - start = %x, length = %d, prot = %d\n",
+	       symname, start, length, prot);
       DPRINTF ("      flags = %d, fd = %d, offset = %d\n",flags, fd,offset);
       if(mmapemu)
 	{
@@ -551,6 +587,22 @@
   return (void *)-1;
 }
 
+void *
+mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+  static mmap_funcptr_t func = NULL;
+  return wrap_mmap("mmap", &func, start, length, prot, flags, fd, offset);
+}
+
+#ifdef HAVE_MMAP64
+void *
+mmap64 (void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+  static mmap_funcptr_t func = NULL;
+  return wrap_mmap("mmap64", &func, start, length, prot, flags, fd, offset);
+}
+#endif /* HAVE_MMAP64 */
+
 int
 munmap (void *start, size_t length)
 {
@@ -596,10 +648,10 @@
     return (*func) (filename);
 }
 
-typedef int (*sa_func_t) (int, struct sockaddr *, int);
+typedef int (*sa_funcptr_t) (int, struct sockaddr *, int);
 
 static int
-sockaddr_mangle (sa_func_t func, int fd, struct sockaddr *addr, int len)
+sockaddr_mangle (sa_funcptr_t func, int fd, struct sockaddr *addr, int len)
 {
   const char *num;
 
@@ -627,20 +679,20 @@
 int
 bind (int fd, struct sockaddr *addr, int len)
 {
-  static sa_func_t func = NULL;
+  static sa_funcptr_t func = NULL;
 
   if (!func)
-    func = (sa_func_t) dlsym (REAL_LIBC, "bind");
+    func = (sa_funcptr_t) dlsym (REAL_LIBC, "bind");
   return sockaddr_mangle (func, fd, addr, len);
 }
 
 int
 connect (int fd, struct sockaddr *addr, int len)
 {
-  static sa_func_t func = NULL;
+  static sa_funcptr_t func = NULL;
 
   if (!func)
-    func = (sa_func_t) dlsym (REAL_LIBC, "connect");
+    func = (sa_funcptr_t) dlsym (REAL_LIBC, "connect");
   return sockaddr_mangle (func, fd, addr, len);
 }
 
@@ -652,13 +704,15 @@
  * static inside esddsp to be sure that we don't override application symbols
  */
 #include "stdioemu.c"
+
+typdef FILE *(*fopen_funcptr_t) (const char *, const char *);
+
 FILE *
-fopen (const char *pathname, const char *mode)
+wrap_fopen (const char *symname, fopen_funcptr_t *func, const char *pathname,
+                const char *mode)
 {
-  static FILE *(*func) (const char *, const char *) = NULL;
-
-  if (!func) {
-    func = (FILE *(*) (const char *, const char *)) dlsym (REAL_LIBC, "fopen");
+  if (!*func) {
+    *func = (fopen_funcptr_t) dlsym (REAL_LIBC, symname);
     dsp_init ();
   }
 
@@ -671,9 +725,25 @@
       return fake_fopen(pathname,mode);
     }
   else
-    return (*func) (pathname, mode);
+    return (**func) (pathname, mode);
 }
-#endif
+
+FILE *
+fopen(const char *pathname, const char *mode)
+{
+  static fopen_funcptr_t func;
+  return wrap_fopen("fopen", &func, pathname, mode);
+}
+
+#ifdef HAVE_OPEN64
+FILE *
+fopen64(const char *pathname, const char *mode)
+{
+  static fopen_funcptr_t func;
+  return wrap_fopen("fopen64", &func, pathname, mode);
+}
+#endif /* HAVE_OPEN64 */
+#endif /* ESDDSP_STDIO_EMU */
 
 #else /* __GNUC__ */
 

Reply via email to