* fhandler.h (class fhandler_base): Change inheritance of fstat_helper

and fstat_by_...  methods to private.
	(fhandler_base::fstat_helper): Drop all redundant arguments.
	* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call
	to fstat_by_nfs_ea here.  Drop fetching basic file information.
	Drop setting file attributes.  Accommodate change in fstat_helper call.
	(fhandler_base::fstat_by_name): Simplify.  Only fetch directory
	information to get the inode number.  Drop setting file attributes.
	Accommodate change in fstat_helper call.
	(fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS.
	(fhandler_base::fstat_helper): Drop all redundant arguments.  Use
	information already collected in the fhandler.  Move heading comment
	into code and drop dwFileAttributes comment.
	* mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle.
	* mount.cc (fs_info::update): Note that has_buggy_basic_info is unused.
	* path.cc (symlink_info::check_reparse_point): Add comment.
	(symlink_info::check): Fetch FileNetworkOpenInformation rather than
	FileBasicInformation throughout, except on NFS.  Explain why.  Store
	FILE_NETWORK_OPEN_INFORMATION in conv_hdl.  Remove
	FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point
	symlinks.
	* path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION
	member _fnoi.
	(path_conv_handle::fnoi): New accessor method for _fnoi.
	(path_conv::fnoi): New accessor method for cubv_hdl._fnoi.

	* fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method.
This commit is contained in:
Corinna Vinschen 2010-09-13 11:17:36 +00:00
parent f7382efe27
commit c80480bfa0
8 changed files with 144 additions and 178 deletions

View File

@ -1,3 +1,33 @@
2010-09-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_base): Change inheritance of fstat_helper
and fstat_by_... methods to private.
(fhandler_base::fstat_helper): Drop all redundant arguments.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call
to fstat_by_nfs_ea here. Drop fetching basic file information.
Drop setting file attributes. Accommodate change in fstat_helper call.
(fhandler_base::fstat_by_name): Simplify. Only fetch directory
information to get the inode number. Drop setting file attributes.
Accommodate change in fstat_helper call.
(fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS.
(fhandler_base::fstat_helper): Drop all redundant arguments. Use
information already collected in the fhandler. Move heading comment
into code and drop dwFileAttributes comment.
* mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle.
* mount.cc (fs_info::update): Note that has_buggy_basic_info is unused.
* path.cc (symlink_info::check_reparse_point): Add comment.
(symlink_info::check): Fetch FileNetworkOpenInformation rather than
FileBasicInformation throughout, except on NFS. Explain why. Store
FILE_NETWORK_OPEN_INFORMATION in conv_hdl. Remove
FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point
symlinks.
* path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION
member _fnoi.
(path_conv_handle::fnoi): New accessor method for _fnoi.
(path_conv::fnoi): New accessor method for cubv_hdl._fnoi.
* fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method.
2010-09-12 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (acl_worker): Remove.

View File

@ -293,21 +293,14 @@ class fhandler_base
int close_fs () { return fhandler_base::close (); }
virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2)));
private:
int __stdcall fstat_helper (struct __stat64 *buf,
PLARGE_INTEGER ChangeTime,
PLARGE_INTEGER LastAccessTime,
PLARGE_INTEGER LastWriteTime,
PLARGE_INTEGER CreationTime,
DWORD dwVolumeSerialNumber,
ULONGLONG nFileSize,
LONGLONG nAllocSize,
ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
__attribute__ ((regparm (3)));
DWORD nNumberOfLinks)
__attribute__ ((regparm (3)));
int __stdcall fstat_by_nfs_ea (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2)));
public:
virtual int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int utimens_fs (const struct timespec *) __attribute__ ((regparm (2)));
virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));

View File

@ -345,43 +345,17 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf)
int __stdcall
fhandler_base::fstat_by_handle (struct __stat64 *buf)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
if (pc.fs_is_nfs ())
return fstat_by_nfs_ea (buf);
/* Don't use FileAllInformation info class. It returns a pathname rather
than a filename, so it needs a really big buffer for no good reason
since we don't need the name anyway. So we just call the three info
classes necessary to get all information required by stat(2). */
union {
FILE_BASIC_INFORMATION fbi;
FILE_NETWORK_OPEN_INFORMATION fnoi;
} fi;
FILE_STANDARD_INFORMATION fsi;
FILE_INTERNAL_INFORMATION fii;
HANDLE h = get_stat_handle ();
NTSTATUS status = 0;
IO_STATUS_BLOCK io;
if (pc.has_buggy_basic_info ())
{
status = NtQueryInformationFile (h, &io, &fi, sizeof fi,
FileNetworkOpenInformation);
/* The timestamps are in the same relative memory location, only
the DOS attributes have to be moved. */
fi.fbi.FileAttributes = fi.fnoi.FileAttributes;
}
else
status = NtQueryInformationFile (h, &io, &fi.fbi,
sizeof fi.fbi, FileBasicInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile(%S, FileBasicInformation)",
status, pc.get_nt_native_path ());
return -1;
}
status = NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
FileStandardInformation);
if (!NT_SUCCESS (status))
@ -402,26 +376,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
}
ino = fii.FileId.QuadPart;
}
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
/* Only copy attributes if not a device root dir. */
if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
pc.file_attributes (fi.fbi.FileAttributes);
return fstat_helper (buf,
fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime
: &fi.fbi.LastWriteTime,
&fi.fbi.LastAccessTime,
&fi.fbi.LastWriteTime,
&fi.fbi.CreationTime,
get_dev (),
fsi.EndOfFile.QuadPart,
fsi.AllocationSize.QuadPart,
ino,
fsi.NumberOfLinks,
fi.fbi.FileAttributes);
return fstat_helper (buf, fsi.NumberOfLinks);
}
int __stdcall
@ -437,76 +392,35 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
FILE_ID_BOTH_DIR_INFORMATION fdi;
WCHAR buf[NAME_MAX + 1];
} fdi_buf;
LARGE_INTEGER FileId;
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (),
NULL, NULL);
if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE)))
if (!ino && wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ())
{
debug_printf ("%p = NtOpenFile(%S)", status, pc.get_nt_native_path ());
goto too_bad;
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (),
NULL, NULL);
status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE);
if (!NT_SUCCESS (status))
debug_printf ("%p = NtOpenFile(%S)", status,
pc.get_nt_native_path ());
else
{
status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io,
&fdi_buf.fdi, sizeof fdi_buf,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE);
NtClose (dir);
if (!NT_SUCCESS (status))
debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
pc.get_nt_native_path ());
else
ino = fdi_buf.fdi.FileId.QuadPart;
}
}
if (wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ()
&& NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io,
&fdi_buf.fdi, sizeof fdi_buf,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE)))
FileId = fdi_buf.fdi.FileId;
else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL,
&io, &fdi_buf.fdi,
sizeof fdi_buf,
FileBothDirectoryInformation,
TRUE, &basename, TRUE)))
FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
pc.get_nt_native_path ());
NtClose (dir);
goto too_bad;
}
NtClose (dir);
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
/* Only copy attributes if not a device root dir. */
if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
pc.file_attributes (fdi_buf.fdi.FileAttributes);
return fstat_helper (buf,
fdi_buf.fdi.ChangeTime.QuadPart
? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime,
&fdi_buf.fdi.LastAccessTime,
&fdi_buf.fdi.LastWriteTime,
&fdi_buf.fdi.CreationTime,
pc.fs_serial_number (),
fdi_buf.fdi.EndOfFile.QuadPart,
fdi_buf.fdi.AllocationSize.QuadPart,
FileId.QuadPart,
1,
fdi_buf.fdi.FileAttributes);
too_bad:
LARGE_INTEGER ft;
/* Arbitrary value: 2006-12-01 */
RtlSecondsSince1970ToTime (1164931200L, &ft);
return fstat_helper (buf,
&ft,
&ft,
&ft,
&ft,
0,
0ULL,
-1LL,
0ULL,
1,
pc.file_attributes ());
return fstat_helper (buf, 1);
}
int __stdcall
@ -519,7 +433,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
if (get_stat_handle ())
{
if (!nohandle () && !is_fs_special ())
res = fstat_by_handle (buf);
res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf);
if (res)
res = fstat_by_name (buf);
return res;
@ -540,7 +454,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
Since fhandler_base::open only calls CloseHandle if !nohandle,
we have to set it to false before calling close and restore
the state afterwards. */
res = fstat_by_handle (buf);
res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf);
bool no_handle = nohandle ();
nohandle (false);
close_fs ();
@ -553,39 +467,26 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
return res;
}
/* The ChangeTime is taken from the NTFS ChangeTime entry, if reading
the file information using NtQueryInformationFile succeeded. If not,
it's faked using the LastWriteTime entry from GetFileInformationByHandle
or FindFirstFile. We're deliberatly not using the creation time anymore
to simplify interaction with native Windows applications which choke on
creation times >= access or write times.
Note that the dwFileAttributes member of the file information evaluated
in the calling function is used here, not the pc.fileattr member, since
the latter might be old and not reflect the actual state of the file. */
int __stdcall
fhandler_base::fstat_helper (struct __stat64 *buf,
PLARGE_INTEGER ChangeTime,
PLARGE_INTEGER LastAccessTime,
PLARGE_INTEGER LastWriteTime,
PLARGE_INTEGER CreationTime,
DWORD dwVolumeSerialNumber,
ULONGLONG nFileSize,
LONGLONG nAllocSize,
ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
DWORD nNumberOfLinks)
{
IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci;
HANDLE h = get_stat_handle ();
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
ULONG attributes = pc.file_attributes ();
to_timestruc_t ((PFILETIME) LastAccessTime, &buf->st_atim);
to_timestruc_t ((PFILETIME) LastWriteTime, &buf->st_mtim);
to_timestruc_t ((PFILETIME) ChangeTime, &buf->st_ctim);
to_timestruc_t ((PFILETIME) CreationTime, &buf->st_birthtim);
buf->st_rdev = buf->st_dev = dwVolumeSerialNumber;
buf->st_size = (_off64_t) nFileSize;
to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim);
to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim);
/* If the ChangeTime is 0, the underlying FS doesn't support this timestamp
(FAT for instance). If so, it's faked using LastWriteTime. */
to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime
: (PFILETIME) &pfnoi->LastWriteTime,
&buf->st_ctim);
to_timestruc_t ((PFILETIME) &pfnoi->CreationTime, &buf->st_birthtim);
buf->st_rdev = buf->st_dev = get_dev ();
buf->st_size = (_off64_t) pfnoi->EndOfFile.QuadPart;
/* The number of links to a directory includes the number of subdirectories
in the directory, since all those subdirectories point to it. However,
this is painfully slow, so we do without it. */
@ -596,19 +497,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
#endif
/* Enforce namehash as inode number on untrusted file systems. */
if (nFileIndex && pc.isgood_inode (nFileIndex))
buf->st_ino = (__ino64_t) nFileIndex;
if (ino && pc.isgood_inode (ino))
buf->st_ino = (__ino64_t) ino;
else
buf->st_ino = get_ino ();
buf->st_blksize = PREFERRED_IO_BLKSIZE;
if (nAllocSize >= 0LL)
if (pfnoi->AllocationSize.QuadPart >= 0LL)
/* A successful NtQueryInformationFile returns the allocation size
correctly for compressed and sparse files as well. */
buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE;
else if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_COMPRESSED
| FILE_ATTRIBUTE_SPARSE_FILE)
buf->st_blocks = (pfnoi->AllocationSize.QuadPart + S_BLKSIZE - 1)
/ S_BLKSIZE;
else if (::has_attribute (attributes, FILE_ATTRIBUTE_COMPRESSED
| FILE_ATTRIBUTE_SPARSE_FILE)
&& h && !is_fs_special ()
&& !NtQueryInformationFile (h, &st, (PVOID) &fci, sizeof fci,
FileCompressionInformation))
@ -641,7 +543,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
&buf->st_mode, &buf->st_uid, &buf->st_gid))
{
/* If read-only attribute is set, modify ntsec return value */
if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY)
if (::has_attribute (attributes, FILE_ATTRIBUTE_READONLY)
&& !pc.isdir () && !pc.issymlink ())
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
@ -660,7 +562,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
{
buf->st_mode |= STD_RBITS;
if (!::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY))
if (!::has_attribute (attributes, FILE_ATTRIBUTE_READONLY))
buf->st_mode |= STD_WBITS;
/* | S_IWGRP | S_IWOTH; we don't give write to group etc */

View File

@ -717,7 +717,7 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
tty process group leader.
TODO: Investigate how SIGTTIN should be handled with pure-windows
programs. */
tc->pgid = myself->pgid;
tc->setpgid (myself->pgid);
}
if (f != INVALID_HANDLE_VALUE)

View File

@ -1,7 +1,7 @@
/* mmap.cc
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007 Red Hat, Inc.
2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@ -865,7 +865,7 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
goto out;
}
if (fh->fstat_by_handle (&st))
if (fh->fstat_fs (&st))
{
__seterrno ();
goto out;

View File

@ -381,7 +381,8 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
Therefore, for NWFS we have to fallback to the
FileNetworkOpenInformation info class. Unfortunately we can't
use FileNetworkOpenInformation all the time since that fails on
other filesystems like NFS. */
other filesystems like NFS.
UNUSED, but keep in for information purposes. */
has_buggy_basic_info (is_nwfs ());
/* Netapp ans NWFS are too dumb to allow non-DOS filesystems
containing trailing dots and spaces when accessed from Windows

View File

@ -1946,6 +1946,7 @@ symlink_info::check_reparse_point (HANDLE h)
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer,
subst.Length / sizeof (WCHAR));
pflags |= PATH_SYMLINK | PATH_REP;
/* A symlink is never a directory. */
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
return posixify (srcbuf);
}
@ -2238,7 +2239,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs,
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
FILE_BASIC_INFORMATION fbi;
suffix_scan suffix;
const ULONG ci_flag = cygwin_shared->obcaseinsensitive
@ -2409,16 +2409,34 @@ restart:
}
}
FILE_BASIC_INFORMATION fbi;
PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
if (NT_SUCCESS (status)
/* Check file system while we're having the file open anyway.
This speeds up path_conv noticably (~10%). */
&& (fs.inited () || fs.update (&upath, h))
&& NT_SUCCESS (status = fs.has_buggy_basic_info ()
? NtQueryAttributesFile (&attr, &fbi)
: NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation)))
fileattr = fbi.FileAttributes;
else
&& (fs.inited () || fs.update (&upath, h)))
{
if (fs.is_nfs ())
{
/* NFS doesn't handle FileNetworkOpenInformation when called
via NtQueryInformationFile (STATUS_INVALID_PARAMETER).
Since we only need FileAttributes for NFS anyway, we just
fetch the FileBasicInformation. */
status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation);
if (NT_SUCCESS (status))
fileattr = fbi.FileAttributes;
}
else
{
status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
FileNetworkOpenInformation);
if (NT_SUCCESS (status))
fileattr = pfnoi->FileAttributes;
}
}
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile (%S)", status, &upath);
fileattr = INVALID_FILE_ATTRIBUTES;
@ -2504,7 +2522,10 @@ restart:
fileattr = 0;
}
else
fileattr = fdi_buf.fdi.FileAttributes;
{
fileattr = fdi_buf.fdi.FileAttributes;
memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
}
}
ext_tacked_on = !!*ext_here;
goto file_not_symlink;
@ -2590,7 +2611,11 @@ restart:
pflags &= ~PC_KEEP_HANDLE;
}
else if (res)
break;
{
/* A symlink is never a directory. */
pfnoi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
break;
}
}
/* This is the old Cygwin method creating symlinks. A symlink will

View File

@ -89,10 +89,24 @@ enum path_types
PATH_SOCKET = 0x40000000
};
class symlink_info;
struct _FILE_NETWORK_OPEN_INFORMATION;
class path_conv_handle
{
HANDLE hdl;
ACCESS_MASK acc;
/* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in
ntdll.h here, though. */
struct {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER EndOfFile;
ULONG FileAttributes;
} _fnoi;
public:
path_conv_handle () : hdl (NULL), acc (0) {}
inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; }
@ -114,10 +128,10 @@ public:
}
inline HANDLE handle () const { return hdl; }
inline ACCESS_MASK access () const { return acc; }
inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi ()
{ return (struct _FILE_NETWORK_OPEN_INFORMATION *) &_fnoi; }
};
class symlink_info;
class path_conv
{
DWORD fileattr;
@ -287,6 +301,7 @@ class path_conv
HANDLE handle () const { return conv_handle.handle (); }
ACCESS_MASK access () const { return conv_handle.access (); }
struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return conv_handle.fnoi (); }
void reset_conv_handle () { conv_handle.set (NULL, 0); }
void close_conv_handle () { conv_handle.close (); }