Cygwin: Move O_TMPFILE to bin and allow linkat by handle
Along the same lines as the previous patch: By reopening an O_TMPFILE by handle, we can now move the file to the bin at open time and thus free'ing up the parent dir and *still* open the file as /proc/PID/fd/DESCRIPTOR by linkat(2).
This commit is contained in:
parent
a1a750325e
commit
7dbe307e38
@ -2555,6 +2555,7 @@ class fhandler_process: public fhandler_proc
|
|||||||
int __reg3 readdir (DIR *, dirent *);
|
int __reg3 readdir (DIR *, dirent *);
|
||||||
int open (int flags, mode_t mode = 0);
|
int open (int flags, mode_t mode = 0);
|
||||||
virtual fhandler_base *fd_reopen (int);
|
virtual fhandler_base *fd_reopen (int);
|
||||||
|
int __reg2 link (const char *);
|
||||||
int __reg2 fstat (struct stat *buf);
|
int __reg2 fstat (struct stat *buf);
|
||||||
bool fill_filebuf ();
|
bool fill_filebuf ();
|
||||||
|
|
||||||
|
@ -399,6 +399,88 @@ err_out:
|
|||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_process::link (const char *newpath)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
int fd;
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
path = get_name () + proc_len + 1;
|
||||||
|
pid = atoi (path);
|
||||||
|
while (*path != 0 && !isdirsep (*path))
|
||||||
|
path++;
|
||||||
|
if (*path == 0)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
virt_tab_t *entry;
|
||||||
|
entry = virt_tab_search (path + 1, true, process_tab, PROCESS_LINK_COUNT);
|
||||||
|
if (!entry || entry->fhandler != FH_PROCESSFD)
|
||||||
|
goto err_out;
|
||||||
|
if (path[3] != '/' || path[4] == '\0')
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
fd = strtoul (path + 4, &e, 10);
|
||||||
|
if (fd < 0 || e == path + 4 || (*e != '/' && *e != '\0'))
|
||||||
|
goto err_out;
|
||||||
|
if (pid == myself->pid)
|
||||||
|
{
|
||||||
|
cygheap_fdget cfd (fd);
|
||||||
|
if (cfd < 0)
|
||||||
|
goto err_out;
|
||||||
|
return cfd->link (newpath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HANDLE proc;
|
||||||
|
size_t size;
|
||||||
|
void *buf;
|
||||||
|
path_conv pc;
|
||||||
|
HANDLE hdl;
|
||||||
|
fhandler_base *fh = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
pinfo p (pid);
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
set_errno (ENOENT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
|
||||||
|
goto err_out;
|
||||||
|
buf = p->file_pathconv (fd, size);
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
set_errno (EPERM);
|
||||||
|
goto err_out_close_proc;
|
||||||
|
}
|
||||||
|
hdl = pc.deserialize (buf);
|
||||||
|
if (!DuplicateHandle (proc, hdl, GetCurrentProcess (), &hdl,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
goto err_out_close_proc;
|
||||||
|
}
|
||||||
|
fh = build_fh_pc (pc);
|
||||||
|
if (!fh)
|
||||||
|
goto err_out_close_dup;
|
||||||
|
|
||||||
|
fh->set_io_handle (hdl);
|
||||||
|
ret = fh->link (newpath);
|
||||||
|
delete fh;
|
||||||
|
|
||||||
|
err_out_close_dup:
|
||||||
|
CloseHandle (hdl);
|
||||||
|
err_out_close_proc:
|
||||||
|
CloseHandle (proc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
set_errno (EPERM);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct process_fd_t {
|
struct process_fd_t {
|
||||||
const char *path;
|
const char *path;
|
||||||
_pinfo *p;
|
_pinfo *p;
|
||||||
|
@ -1484,6 +1484,10 @@ open (const char *unix_path, int flags, ...)
|
|||||||
else if ((fh->is_fs_special () && fh->device_access_denied (flags))
|
else if ((fh->is_fs_special () && fh->device_access_denied (flags))
|
||||||
|| !fh->open_with_arch (flags, mode & 07777))
|
|| !fh->open_with_arch (flags, mode & 07777))
|
||||||
__leave; /* errno already set */
|
__leave; /* errno already set */
|
||||||
|
/* Move O_TMPFILEs to the bin to avoid blocking the parent dir. */
|
||||||
|
if ((flags & O_TMPFILE) && !fh->pc.isremote ())
|
||||||
|
try_to_bin (fh->pc, fh->get_handle (), DELETE,
|
||||||
|
FILE_OPEN_FOR_BACKUP_INTENT);
|
||||||
fd = fh;
|
fd = fh;
|
||||||
if (fd <= 2)
|
if (fd <= 2)
|
||||||
set_std_handle (fd);
|
set_std_handle (fd);
|
||||||
@ -4791,7 +4795,9 @@ linkat (int olddirfd, const char *oldpathname,
|
|||||||
__leave;
|
__leave;
|
||||||
if (flags & AT_SYMLINK_FOLLOW)
|
if (flags & AT_SYMLINK_FOLLOW)
|
||||||
{
|
{
|
||||||
path_conv old_name (oldpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
|
path_conv old_name (oldpath,
|
||||||
|
PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_PROCFD | PC_POSIX,
|
||||||
|
stat_suffixes);
|
||||||
if (old_name.error)
|
if (old_name.error)
|
||||||
{
|
{
|
||||||
set_errno (old_name.error);
|
set_errno (old_name.error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user