SQLite Forum

SQLITE_FCNTL_WIN32_GET_HANDLE
Login

SQLITE_FCNTL_WIN32_GET_HANDLE

(1) By dubiousjim on 2020-05-20 11:59:41 [source]

This opcode was introduced in sqlite 3.15.1 (2016-11-04). But it's currently only implemented in src/os_win.c. It'd be useful to have a parallel implementation for unix, something like this:

@@ -42334,6 +42334,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       *(int*)pArg = pFile->eFileLock;
       return SQLITE_OK;
     }
+    case SQLITE_FCNTL_WIN32_GET_HANDLE: {
+      *(int*)pArg = pFile->h;
+      return SQLITE_OK;
+    }
     case SQLITE_FCNTL_LAST_ERRNO: {
       *(int*)pArg = pFile->lastErrno;
       return SQLITE_OK;

Of course, if that were added, it might be friendly to create another macro name for the opcode, such as:

 #define SQLITE_FCNTL_WIN32_GET_HANDLE       29
+#define SQLITE_FCNTL_UNIX_GET_FD       29

Here's why I'd find this helpful. I'd like (1) to be able to request the opening of a new database file, with the attempt to fail if there's already a file there. I'd also like (2) if I request the opening of a database file that's allowed to already exist, but with permission to create a new file if needed, I'd like to be given feedback about whether the file was in fact newly created. sqlite3's current API doesn't provide for these things. I can to some extent accomplish them using my OS's filesystem API. Ideally, there would be another variant of sqlite3_open(), which took an open file descriptor or handle as an argument, rather than a pathname. I'd welcome that if it were feasible. But a more minimal approach would be to use the filesystem API to open a file, and use the sqlite3 API to attempt to open the same file, and then verify that the files are the same. Then one could release/close the filesystem-opened file.

(If you just used the filesystem API to check whether any file existed at the desired path, and if not then told sqlite3 to open a file there, allowing creation, that wouldn't be atomic. You couldn't be sure that a file didn't appear between the time you checked the path and saw nothing there, and the time when sqlite3's open interacted with the filesystem.)

So how to verify that a file I opened using my OS filesystem API is the same file that a sqlite3 connection is using?

On Windows, one can extract the underlying file handle using sqlite3_file_control(..., SQLITE_FCNTL_WIN32_GET_HANDLE, ...). On Unix, I hoped to be able to extract the underlying file descriptor in the same way. If the patches above are applied, then one can do this. (Then one can do a stat on the file descriptor and verify that its device and inode correspond to those of the file opened via the filesystem API, and afterwards close/release the filesystem-opened file.)

I expect there's been prior discussion of this, but when I search this forum and the (now-closed) mailing list for the WIN32_GET_HANDLE opcode, I come up empty. I did find this thread.

(2) By dubiousjim on 2020-12-24 17:51:00 in reply to 1 [link] [source]

Hi just bumping this, in case it fell under the developers' radar.

(3) By anonymous on 2020-12-25 06:47:52 in reply to 1 [link] [source]

and afterwards close/release the filesystem-opened file

Probably not a good idea, given how POSIX advisory locks work.