[libcxx-commits] [PATCH] D91143: [11/N] [libcxx] Hook up a number of operation functions to their windows counterparts

Martin Storsjö via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Nov 13 03:29:20 PST 2020


mstorsjo marked 3 inline comments as done.
mstorsjo added inline comments.


================
Comment at: libcxx/src/filesystem/operations.cpp:446
+  if (GetLastError() != ERROR_INVALID_PARAMETER)
+    return set_errno();
+  if (CreateSymbolicLinkW(newname, oldname, flags))
----------------
mstorsjo wrote:
> amccarth wrote:
> > Technically, there's nothing wrong here.  It just _feels_ a little sketchy to call `GetLastError()` twice in a row.
> Yeah, it's not ideal, but then again, making a separate version of the `set_errno()` function that takes an error code as input, just for this case, also feels a bit superfluous (as the first call to GetLastError() shouldn't clobber the first one). Or would a default parameter, like `set_errno(int err = GetLastError())` work?
Changed `set_errno()` to take the error code as a parameter, with the parameter set by default to `GetLastError()`.


================
Comment at: libcxx/src/filesystem/operations.cpp:467
+int remove(const wchar_t *path) {
+  detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT);
+  if (!h)
----------------
mstorsjo wrote:
> amccarth wrote:
> > Why not implement this with `::DeleteFile()`?  Does it have to do with waiting until the last handle is closed?
> Haven't considered/tested that, I can try that and run it over the testcases to see if it works.
> 
> The reason I ended up with this, was that I first just called `_wremove()`, followed by a `_wrmdir()` if the first failed and the path is a directory - as that was the most obvious path forward when porting over from the posix remove() function. That worked mostly, but failed in some symlink cases, and then I peeked at how the MS STL (which has the same license as libcxx, fwiw) implemented it, and I did the same.
I tried with this implementation, but this still fails on removing symlinks to directories:
```
int remove(const wchar_t *path) {
  if (DeleteFileW(path))
    return 0;
  int e = GetLastError();
  if (e == ERROR_ACCESS_DENIED) {
    if (is_directory(path)) {
      if (!RemoveDirectoryW(path)) 
        return set_errno();
      return 0;
    }
  }
  return set_errno(e);
}
```



================
Comment at: libcxx/src/filesystem/operations.cpp:489
+  HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+  return truncate_handle(h, length);
+}
----------------
mstorsjo wrote:
> amccarth wrote:
> > I'm mildly concerned about the way files are sometimes manipulated by HANDLE and sometimes by file descriptor.
> > 
> > If `fd` represents a file in text mode, then the caller needs to be very careful to understand that `length` must be the _byte_ offset, not the _char_ offset into the file.
> File descriptors here are only an internal detail, fwiw, they're only used within the `__copy_file` function. But good catch about text vs binary mode; I guess the calls to `FileDescriptor::create_with_status` need to be amended with `O_BINARY`.
Adding `O_BINARY` at the callsites that open file descriptors.


================
Comment at: libcxx/src/filesystem/operations.cpp:501
+  if (!(MoveFileExW(from, to,
+                    MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)))
+    return set_errno();
----------------
mstorsjo wrote:
> amccarth wrote:
> > Consider also `MOVEFILE_WRITE_THROUGH` for the case that it is indeed copied and then (probably) deleted.
> Sounds like a good thing to have, I can add that. These flags were based on what the MS STL use, and I didn't see that flag used there though.
Adding that flag as it sounds beneficial, despite MS STL not using it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91143/new/

https://reviews.llvm.org/D91143



More information about the libcxx-commits mailing list