From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LwFBy-0000Jy-4o for qemu-devel@nongnu.org; Tue, 21 Apr 2009 08:35:14 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LwFBw-0000JF-8s for qemu-devel@nongnu.org; Tue, 21 Apr 2009 08:35:13 -0400 Received: from [199.232.76.173] (port=50280 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LwFBw-0000JA-3X for qemu-devel@nongnu.org; Tue, 21 Apr 2009 08:35:12 -0400 Received: from naru.obs2.net ([84.20.150.76]:59819) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LwFBt-00010T-J6 for qemu-devel@nongnu.org; Tue, 21 Apr 2009 08:35:11 -0400 Date: Tue, 21 Apr 2009 15:34:55 +0300 From: Riku Voipio Subject: Re: [Qemu-devel] [PATCH] Fix utimensat (aka unbreak cp -a) Message-ID: <20090421123455.GA15170@kos.to> References: <878wlufm8s.fsf@lechat.rtp-net.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <878wlufm8s.fsf@lechat.rtp-net.org> List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Arnaud Patard Cc: laurent.desnogues@gmail.com, qemu-devel@nongnu.org On Tue, Apr 21, 2009 at 10:24:03AM +0200, Arnaud Patard wrote: > Don't use the glibc function for utimensat because glibc returns -EINVAL > if the path is null which is a different behaviour with the syscall. > path can be null because internally the glibc is using utimensat with > path null (for instance, see __futimes in > sysdeps/unix/sysv/linux/futimes.c in glibc tree). Soo.. glibc uses utimensat to implement futimens, but doesn't allow applications to use utimensat in the same way. What a mess. But if we are to go towards using libc calls, your patch is a step backwards. In case pathname is null, we can use futimens. commit 0f34ff059fb9ad6e8c8fa5161d9d17265286bb62 Author: Riku Voipio Date: Tue Apr 21 15:01:51 2009 +0300 linux-user: fix utimensat when used as futimens The glibc function for utimensat glibc returns -EINVAL when the path is null which is a different behaviour with the syscall. path can be null because internally the glibc is using utimensat with path null when implmenting futimens. If path is null, call futimes instead. diff --git a/configure b/configure index 08df436..fc980a4 100755 --- a/configure +++ b/configure @@ -1208,6 +1208,25 @@ EOF fi fi +# check if utimensat and futimens are supported +utimens=no +cat > $TMPC << EOF +#define _ATFILE_SOURCE +#define _GNU_SOURCE +#include +#include + +int main(void) +{ + utimensat(AT_FDCWD, "foo", NULL, 0); + futimens(0, NULL); + return 0; +} +EOF +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then + utimens=yes +fi + # Check if tools are available to build documentation. if [ -x "`which texi2html 2>/dev/null`" ] && \ [ -x "`which pod2man 2>/dev/null`" ]; then @@ -1604,6 +1623,9 @@ fi if test "$atfile" = "yes" ; then echo "#define CONFIG_ATFILE 1" >> $config_h fi +if test "$utimens" = "yes" ; then + echo "#define CONFIG_UTIMENSAT 1" >> $config_h +fi if test "$inotify" = "yes" ; then echo "#define CONFIG_INOTIFY 1" >> $config_h fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 408ccc6..4dad5c1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -406,13 +406,6 @@ static int sys_unlinkat(int dirfd, const char *pathname, int flags) return (unlinkat(dirfd, pathname, flags)); } #endif -#ifdef TARGET_NR_utimensat -static int sys_utimensat(int dirfd, const char *pathname, - const struct timespec times[2], int flags) -{ - return (utimensat(dirfd, pathname, times, flags)); -} -#endif #else /* !CONFIG_ATFILE */ /* @@ -476,12 +469,24 @@ _syscall3(int,sys_symlinkat,const char *,oldpath, #if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) _syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags) #endif + +#endif /* CONFIG_ATFILE */ + +#ifdef CONFIG_UTIMENSAT +static int sys_utimensat(int dirfd, const char *pathname, + const struct timespec times[2], int flags) +{ + if (pathname == NULL) + return futimens(dirfd, times); + else + return utimensat(dirfd, pathname, times, flags); +} +#else #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, const struct timespec *,tsp,int,flags) #endif - -#endif /* CONFIG_ATFILE */ +#endif /* CONFIG_UTIMENSAT */ #ifdef CONFIG_INOTIFY #include