Re: renameat2

2017-08-19 Thread Corinna Vinschen
Hi Ken,

On Aug 18 18:24, Ken Brown wrote:
> Hi Corinna,
> 
> On 8/18/2017 11:15 AM, Corinna Vinschen wrote:
> > On Aug 18 09:21, Ken Brown wrote:
> > But there's light.  NtSetInformationFile(FileRenameInformation) already
> > supports RENAME_NOREPLACE :)
> > 
> > Have a look at line 2494 (prior to your patch):
> > 
> >  pfri->ReplaceIfExists = TRUE;
> > 
> > if you replace this with something like
> > 
> >  pfri->ReplaceIfExists = !(flags & RENAME_NOREPLACE);
> > 
> > it should give us the atomic behaviour of renameat2 on Linux.
> > 
> > Another upside is, the status code returned is STATUS_OBJECT_NAME_COLLISION,
> > which translates to Win32 error ERROR_ALREADY_EXISTS, which in turn is
> > already converted to EEXIST by Cygwin, so there's nothing more to do :)
> > 
> > What do you think?
> 
> Thanks for the improvements!  A revised patch is attached.  As you'll see, I
> still found a few places where I thought I needed to explicitly set the
> errno to EEXIST.  Let me know if any of these could be avoided.

No, you're right.  Just one thing:

> @@ -2410,6 +2433,11 @@ rename (const char *oldpath, const char *newpath)
>unlink_nt returns with STATUS_DIRECTORY_NOT_EMPTY. */
>if (dstpc->isdir ())
>   {
> +   if (noreplace)
> + {
> +   set_errno (EEXIST);
> +   __leave;
> + }
> status = unlink_nt (*dstpc);
> if (!NT_SUCCESS (status))
>   {
> @@ -2423,6 +2451,11 @@ rename (const char *oldpath, const char *newpath)
>due to a mangled suffix. */
>else if (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))
>   {
> +   if (noreplace)
> + {
> +   set_errno (EEXIST);
> +   __leave;
> + }
> status = NtOpenFile (&nfh, FILE_WRITE_ATTRIBUTES,
>  dstpc->get_object_attr (attr, sec_none_nih),
>  &io, FILE_SHARE_VALID_FLAGS,

Both of the above cases are just border cases of one and the same
problem, the destination file already exists.

In retrospect your original patch was more concise:

+  /* Should we replace an existing file? */
+  if ((removepc || dstpc->exists ()) && (flags & RENAME_NOREPLACE))
+   {
+ set_errno (EEXIST);
+ __leave;
+   }

The atomicity considerations are not affected by this test anyway, but
it would avoid starting and stopping a transaction on NTFS for no good
reason.

Maybe it's better to revert to this test and drop the other two again?

> @@ -2491,11 +2524,15 @@ rename (const char *oldpath, const char *newpath)
> __leave;
>   }
>pfri = (PFILE_RENAME_INFORMATION) tp.w_get ();
> -  pfri->ReplaceIfExists = TRUE;
> +  pfri->ReplaceIfExists = !noreplace;
>pfri->RootDirectory = NULL;
>pfri->FileNameLength = dstpc->get_nt_native_path ()->Length;
>memcpy (&pfri->FileName,  dstpc->get_nt_native_path ()->Buffer,
> pfri->FileNameLength);
> +  /* If dstpc points to an existing file and RENAME_NOREPLACE has
> +  been specified, then we should get NT error
> +  STATUS_OBJECT_NAME_COLLISION ==> Win32 error
> +  ERROR_ALREADY_EXISTS ==> Cygwin error EEXIST. */
>status = NtSetInformationFile (fh, &io, pfri,
>sizeof *pfri + pfri->FileNameLength,
>FileRenameInformation);
> @@ -2509,6 +2546,11 @@ rename (const char *oldpath, const char *newpath)
>if (status == STATUS_ACCESS_DENIED && dstpc->exists ()
> && !dstpc->isdir ())
>   {
> +   if (noremove)
> + {
> +   set_errno (EEXIST);
> +   __leave;
> + }

Oh, right, that's a good catch.

The patch is ok as is, just let me know what you think of the above
minor tweak (and send the revised patch if you agree).


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: renameat2

2017-08-19 Thread Ken Brown

Hi Corinna,

On 8/19/2017 5:57 AM, Corinna Vinschen wrote:

Hi Ken,

On Aug 18 18:24, Ken Brown wrote:
Thanks for the improvements!  A revised patch is attached.  As you'll see, I

still found a few places where I thought I needed to explicitly set the
errno to EEXIST.  Let me know if any of these could be avoided.


No, you're right.  Just one thing:


@@ -2410,6 +2433,11 @@ rename (const char *oldpath, const char *newpath)
 unlink_nt returns with STATUS_DIRECTORY_NOT_EMPTY. */
if (dstpc->isdir ())
{
+ if (noreplace)
+   {
+ set_errno (EEXIST);
+ __leave;
+   }
  status = unlink_nt (*dstpc);
  if (!NT_SUCCESS (status))
{
@@ -2423,6 +2451,11 @@ rename (const char *oldpath, const char *newpath)
 due to a mangled suffix. */
else if (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))
{
+ if (noreplace)
+   {
+ set_errno (EEXIST);
+ __leave;
+   }
  status = NtOpenFile (&nfh, FILE_WRITE_ATTRIBUTES,
   dstpc->get_object_attr (attr, sec_none_nih),
   &io, FILE_SHARE_VALID_FLAGS,


Both of the above cases are just border cases of one and the same
problem, the destination file already exists.

In retrospect your original patch was more concise:

+  /* Should we replace an existing file? */
+  if ((removepc || dstpc->exists ()) && (flags & RENAME_NOREPLACE))
+   {
+ set_errno (EEXIST);
+ __leave;
+   }

The atomicity considerations are not affected by this test anyway, but
it would avoid starting and stopping a transaction on NTFS for no good
reason.

Maybe it's better to revert to this test and drop the other two again?


@@ -2491,11 +2524,15 @@ rename (const char *oldpath, const char *newpath)
  __leave;
}
pfri = (PFILE_RENAME_INFORMATION) tp.w_get ();
-  pfri->ReplaceIfExists = TRUE;
+  pfri->ReplaceIfExists = !noreplace;
pfri->RootDirectory = NULL;
pfri->FileNameLength = dstpc->get_nt_native_path ()->Length;
memcpy (&pfri->FileName,  dstpc->get_nt_native_path ()->Buffer,
  pfri->FileNameLength);
+  /* If dstpc points to an existing file and RENAME_NOREPLACE has
+been specified, then we should get NT error
+STATUS_OBJECT_NAME_COLLISION ==> Win32 error
+ERROR_ALREADY_EXISTS ==> Cygwin error EEXIST. */
status = NtSetInformationFile (fh, &io, pfri,
 sizeof *pfri + pfri->FileNameLength,
 FileRenameInformation);
@@ -2509,6 +2546,11 @@ rename (const char *oldpath, const char *newpath)
if (status == STATUS_ACCESS_DENIED && dstpc->exists ()
  && !dstpc->isdir ())
{
+ if (noremove)
+   {
+ set_errno (EEXIST);
+ __leave;
+   }


Oh, right, that's a good catch.

The patch is ok as is, just let me know what you think of the above
minor tweak (and send the revised patch if you agree).


Yes, I agree.  But can't I also drop the third test (where you said 
"good catch") for the same reason?  I've done that in the attached.  If 
I'm wrong and I still need that third test, let me know and I'll put it 
back.


Thanks.

Ken
From bbff16b727172a459a9a052b0b948641c82d80eb Mon Sep 17 00:00:00 2001
From: Ken Brown 
Date: Thu, 17 Aug 2017 09:12:15 -0400
Subject: [PATCH] cygwin: Implement renameat2

Define the RENAME_NOREPLACE flag in  as defined on Linux
in .  The other RENAME_* flags defined on Linux are not
supported.
---
 newlib/libc/include/stdio.h|  3 +++
 winsup/cygwin/common.din   |  1 +
 winsup/cygwin/include/cygwin/fs.h  |  6 +
 winsup/cygwin/include/cygwin/version.h |  3 ++-
 winsup/cygwin/syscalls.cc  | 48 +-
 5 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
index 5d8cb1092..331a1cf07 100644
--- a/newlib/libc/include/stdio.h
+++ b/newlib/libc/include/stdio.h
@@ -384,6 +384,9 @@ int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST)
 #endif
 #if __ATFILE_VISIBLE
 int_EXFUN(renameat, (int, const char *, int, const char *));
+# ifdef __CYGWIN__
+int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned int));
+# endif
 #endif
 
 /*
diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index 8da432b8a..ca6ff3cf9 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -1168,6 +1168,7 @@ remquof NOSIGFE
 remquol NOSIGFE
 rename SIGFE
 renameat SIGFE
+renameat2 SIGFE
 res_close = __res_close SIGFE
 res_init = __res_init SIGFE
 res_mkquery = __res_mkquery SIGFE
diff --git a/winsup/cygwin/include/cygwin/fs.h 
b/winsup/cygwin/include/cygwin/fs.h
index f606ffc39..48b0cca45 100644
--- a/winsup/cygwin/include/cygwin/fs.h
+++

Re: renameat2

2017-08-19 Thread Corinna Vinschen
On Aug 19 10:29, Ken Brown wrote:
> Hi Corinna,
> 
> On 8/19/2017 5:57 AM, Corinna Vinschen wrote:
> > Hi Ken,
> > 
> > On Aug 18 18:24, Ken Brown wrote:
> > The patch is ok as is, just let me know what you think of the above
> > minor tweak (and send the revised patch if you agree).
> 
> Yes, I agree.  But can't I also drop the third test (where you said "good
> catch") for the same reason?  I've done that in the attached.  If I'm wrong
> and I still need that third test, let me know and I'll put it back.

Nope, you're right.  Same rules apply for the third test.  Patch pushed.
Doc changes coming? :)


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: renameat2

2017-08-19 Thread Corinna Vinschen
On Aug 19 18:28, Corinna Vinschen wrote:
> On Aug 19 10:29, Ken Brown wrote:
> > Hi Corinna,
> > 
> > On 8/19/2017 5:57 AM, Corinna Vinschen wrote:
> > > Hi Ken,
> > > 
> > > On Aug 18 18:24, Ken Brown wrote:
> > > The patch is ok as is, just let me know what you think of the above
> > > minor tweak (and send the revised patch if you agree).
> > 
> > Yes, I agree.  But can't I also drop the third test (where you said "good
> > catch") for the same reason?  I've done that in the attached.  If I'm wrong
> > and I still need that third test, let me know and I'll put it back.
> 
> Nope, you're right.  Same rules apply for the third test.  Patch pushed.
> Doc changes coming? :)

Oh, one more thing.  This is a question to Yaakov, too.

diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
index 5d8cb1092..331a1cf07 100644
--- a/newlib/libc/include/stdio.h
+++ b/newlib/libc/include/stdio.h
@@ -384,6 +384,9 @@ int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST)
 #endif
 #if __ATFILE_VISIBLE
 int_EXFUN(renameat, (int, const char *, int, const char *));
+# ifdef __CYGWIN__
+int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned int));
+# endif
 #endif

Does it makes sense to guard the renameat2 prototype more extensively
to cater for standards junkies?  __MISC_VISIBLE, perhaps?


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: renameat2

2017-08-19 Thread Ken Brown
On 8/19/2017 12:37 PM, Corinna Vinschen wrote:
> Oh, one more thing.  This is a question to Yaakov, too.
> 
> diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
> index 5d8cb1092..331a1cf07 100644
> --- a/newlib/libc/include/stdio.h
> +++ b/newlib/libc/include/stdio.h
> @@ -384,6 +384,9 @@ int _EXFUN(vdprintf, (int, const char *__restrict, 
> __VALIST)
>   #endif
>   #if __ATFILE_VISIBLE
>   int_EXFUN(renameat, (int, const char *, int, const char *));
> +# ifdef __CYGWIN__
> +int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned 
> int));
> +# endif
>   #endif
> 
> Does it makes sense to guard the renameat2 prototype more extensively
> to cater for standards junkies?  __MISC_VISIBLE, perhaps?

I'll defer to Yaakov.  But here's a related question.  Is renameat
currently guarded properly?  The Linux man page says:

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

   renameat():
   Since glibc 2.10:
   _POSIX_C_SOURCE >= 200809L
   Before glibc 2.10:
   _ATFILE_SOURCE

This suggests that we should do something like the following:

diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
index 331a1cf07..9eb0964f2 100644
--- a/newlib/libc/include/stdio.h
+++ b/newlib/libc/include/stdio.h
@@ -381,8 +381,6 @@ FILE *  _EXFUN(open_memstream, (char **, size_t *));
 int_EXFUN(vdprintf, (int, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0;
 # endif
-#endif
-#if __ATFILE_VISIBLE
 int_EXFUN(renameat, (int, const char *, int, const char *));
 # ifdef __CYGWIN__
 int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned int));

Ken


Re: renameat2

2017-08-19 Thread Ken Brown

On 8/19/2017 12:28 PM, Corinna Vinschen wrote:

Doc changes coming? :)


Attached.

Ken

From 0704541f1d29e0d9aa0af6e549f8ca0114a44a7c Mon Sep 17 00:00:00 2001
From: Ken Brown 
Date: Sat, 19 Aug 2017 13:15:04 -0400
Subject: [PATCH] Document renameat2

---
 winsup/cygwin/release/2.9.0 | 2 ++
 winsup/doc/new-features.xml | 4 
 winsup/doc/posix.xml| 4 
 3 files changed, 10 insertions(+)

diff --git a/winsup/cygwin/release/2.9.0 b/winsup/cygwin/release/2.9.0
index 421d6f24f..ac4c64949 100644
--- a/winsup/cygwin/release/2.9.0
+++ b/winsup/cygwin/release/2.9.0
@@ -6,6 +6,8 @@ What's new:
 - New APIs: pthread_mutex_timedwait, pthread_rwlock_timedrdlock,
pthread_rwlock_timedwrlock.
 
+- New API: renameat2.
+
 
 What changed:
 -
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 23673d1e0..0aa857730 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -17,6 +17,10 @@ New APIs: pthread_mutex_timedwait, 
pthread_rwlock_timedrdlock,
 pthread_rwlock_timedwrlock.
 
 
+
+New API: renameat2.
+
+
 
 Improved implementation of .
 
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index a2fffeebf..6e96272b7 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -1356,6 +1356,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).
 ptsname_r
 putwc_unlocked
 putwchar_unlocked
+renameat2  (see chapter "Implementation Notes")
 qsort_r(see chapter "Implementation Notes")
 quotactl
 rawmemchr
@@ -1671,6 +1672,9 @@ group quotas, no inode quotas, no time constraints.
 qsort_r is available in both BSD and GNU flavors,
 depending on whether _BSD_SOURCE or _GNU_SOURCE is defined when 
compiling.
 
+The Linux-specific function renameat2 only
+supports the RENAME_NOREPLACE flag.
+
 basename is available in both POSIX and GNU flavors,
 depending on whether libgen.h is included or not.
 
-- 
2.14.1



Re: renameat2

2017-08-19 Thread Corinna Vinschen
On Aug 19 13:13, Ken Brown wrote:
> On 8/19/2017 12:37 PM, Corinna Vinschen wrote:
> > Oh, one more thing.  This is a question to Yaakov, too.
> > 
> > diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
> > index 5d8cb1092..331a1cf07 100644
> > --- a/newlib/libc/include/stdio.h
> > +++ b/newlib/libc/include/stdio.h
> > @@ -384,6 +384,9 @@ int _EXFUN(vdprintf, (int, const char *__restrict, 
> > __VALIST)
> >   #endif
> >   #if __ATFILE_VISIBLE
> >   int_EXFUN(renameat, (int, const char *, int, const char *));
> > +# ifdef __CYGWIN__
> > +int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned 
> > int));
> > +# endif
> >   #endif
> > 
> > Does it makes sense to guard the renameat2 prototype more extensively
> > to cater for standards junkies?  __MISC_VISIBLE, perhaps?
> 
> I'll defer to Yaakov.  But here's a related question.  Is renameat
> currently guarded properly?  The Linux man page says:
> 
> Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
> 
>renameat():
>Since glibc 2.10:
>_POSIX_C_SOURCE >= 200809L
>Before glibc 2.10:
>_ATFILE_SOURCE
> 
> This suggests that we should do something like the following:
> 
> diff --git a/newlib/libc/include/stdio.h b/newlib/libc/include/stdio.h
> index 331a1cf07..9eb0964f2 100644
> --- a/newlib/libc/include/stdio.h
> +++ b/newlib/libc/include/stdio.h
> @@ -381,8 +381,6 @@ FILE *  _EXFUN(open_memstream, (char **, size_t *));
>  int_EXFUN(vdprintf, (int, const char *__restrict, __VALIST)
> _ATTRIBUTE ((__format__ (__printf__, 2, 0;
>  # endif
> -#endif
> -#if __ATFILE_VISIBLE
>  int_EXFUN(renameat, (int, const char *, int, const char *));
>  # ifdef __CYGWIN__
>  int_EXFUN(renameat2, (int, const char *, int, const char *, unsigned 
> int));

No, that's correct.  See sys/features.h:

 * __ATFILE_VISIBLE
 *  "at" functions; enabled by default, with _ATFILE_SOURCE,
 *  _POSIX_C_SOURCE >= 200809L, or _XOPEN_SOURCE >= 700.


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: renameat2

2017-08-19 Thread Corinna Vinschen
On Aug 19 13:24, Ken Brown wrote:
> On 8/19/2017 12:28 PM, Corinna Vinschen wrote:
> > Doc changes coming? :)
> 
> Attached.

Pushed.  I also generated new developer snapshots.


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature