sqlite3_open - problems checking if a file is a sqlite3 database - c++

I'm working with sqlite3 for the first time, and cannot get it to properly check a file before it opens it. So far, sqlite always returns OK on any file.
Also, the file name is a variable returned from the GTK file chooser. It returns an absolute path, I'm guessing this is not a problem.
Thanks for any help.
This is a snippet of the code:
int rc;
char *filename;
sqlite3 *db;
filename = gtk_file_chooser_get_filename(etc.);
if(SQLITE_OK == rc = sqlite3_open(filename,&db))
{ etc. }

sqlite3_open doesn't actually read the file until the first non-pragma statement is prepared.
sqlite3_open_v2 provides other options.

Does your code compile?
I believe this is an error
if (SQLITE_OK == rc = sqlite3_open(filename,&db)) { /* ... */ }
it's the same as
if ((SQLITE_OK == rc) = sqlite3_open(filename,&db)) { /* ... */ }
and you cannot assign something (the result of the sqlite3_open() call) to (SQLITE_OK == rc).
Try this:
if ((rc = sqlite3_open(filename,&db)) == SQLITE_OK) { /* ... */ }
/* or, if you really want the constant on the left side of the comparison */
if (SQLITE_OK == (rc = sqlite3_open(filename,&db))) { /* ... */ }

Related

How does prepared statements in Sqlite C++ work

I do not know how to implement prepared statements in my Sqlite3 code
#include <iostream>
#include <sqlite3.h>
#include <stdio.h>
static int callback (void* NotUsed, int argc, char** argv, char** azColName) {
int i;
for (i = 0; i < argc; i++) {
std::cout << ("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
std::cout << ("\n");
return 0;
}
int main (int argc, char* argv[]) {
sqlite3* db;
char* zErrMsg = 0;
int rc;
char* sql;
/* Open database */
rc = sqlite3_open ("test.db", &db);
if (rc) {
std::cerr << "Can't open database: \n" << sqlite3_errmsg (db);
return (0);
}
else {
std::cout << "Opened database successfully\n";
}
std::string newName;
std::cin >> newName;
/* Create SQL statement */
sql = "UPDATE company SET name = newName WHERE id = 1";
/* Execute SQL statement */
rc = sqlite3_exec (db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
std::cout << "SQL error: \n" << zErrMsg;
sqlite3_free (zErrMsg);
}
else {
std::cout << "Records created successfully\n";
}
sqlite3_close (db);
return 0;
}
The user has to input newName and this variable should be used to Update a field in the Database. This way it does not work, because the Sql script is searching for a column. In the internet I found, that I had to use a prepared statement, but I do not know how to implement it.
You start with an sql statement that has placeholders for the parameters that you wish to bind later. Here, I use a single question mark for the placeholder, but there are other options described in the documentation.
std::string sql = "UPDATE company SET name = ? WHERE id = 1";
Then you construct a prepared statement (or "compile", as they say it in sqlite documentation). You'll normally use sqlite_prepare_v2 function, but there are others (for when your statement is encoded in something else than utf-8, for example).
sqlite3_stmt* stmt; // will point to prepared stamement object
sqlite3_prepare_v2(
db, // the handle to your (opened and ready) database
sql.c_str(), // the sql statement, utf-8 encoded
sql.length(), // max length of sql statement
&stmt, // this is an "out" parameter, the compiled statement goes here
nullptr); // pointer to the tail end of sql statement (when there are
// multiple statements inside the string; can be null)
Then you bind the parameter(s). There's a whole bunch of avaliable functions. Which one exactly you use depends on the type
of data that you're binding to the parameter. Here, we bind text, so we use sqlite3_bind_text:
std::string newName = /* get name from user */;
sqlite3_bind_text(
stmt, // previously compiled prepared statement object
1, // parameter index, 1-based
newName.c_str(), // the data
newName.length(), // length of data
SQLITE_STATIC); // this parameter is a little tricky - it's a pointer to the callback
// function that frees the data after the call to this function.
// It can be null if the data doesn't need to be freed, or like in this case,
// special value SQLITE_STATIC (the data is managed by the std::string
// object and will be freed automatically).
So, the prepared statement is ready to go. Now you execute it by passing it to sqlite3_step:
sqlite3_step(stmt); // you'll want to check the return value, read on...
Now, when you step through a statement that's supposed to return rows of a result table, this function will keep returning SQLITE_ROW as long as there are result rows to process, and SQLITE_DONE when there are none left. You can use sqlite3_column_* family of functions to get the single columns from a result row. I'll let you figure this out on your own.
For a simple update statements that you have, sqlite3_step will return SQLITE_DONE on the first call. More info and possible error codes are here.
When it's all done, you finish by destructing the prepared statement.
sqlite3_finalize(stmt);
I hope this should get you started.

Is the return value of pycurl.CurlMulti.info_read still usable after call to remove_handle?

I am using pycurl.CurlMulti interface in python3 and I want to use info_read to check for the succeeded and failed connections.
According to the documentation of the c interface curl_multi_info_read of libcurl:
WARNING: The data the returned pointer points to will not survive calling curl_multi_cleanup, curl_multi_remove_handle or curl_easy_cleanup.
However, the documentation of pycurl.CurlMulti does not mention whether the curl error message in the return value of pycurl.CurlMulti.info_read() is valid after a call to curl_multi_remove_handle.
The only way to check this is read the source code of pycurl.
I checked the source code for pycurl.CurlMulti.info_read and it shows that:
/* When an error occurs */
else {
/* Create a result tuple that will get added to err_list. */
PyObject *v = Py_BuildValue("(Ois)", (PyObject *)co, (int)msg->data.result, co->error);
/* Append curl object to list of objects which failed */
if (v == NULL || PyList_Append(err_list, v) != 0) {
Py_XDECREF(v);
goto error;
}
Py_DECREF(v);
}
where co is retrieved from L781:
/* Fetch the curl object that corresponds to the curl handle in the message */
res = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **) &co);
And CURLINFO_PRIVATE and co->error is set at src/easy.c#L52:
/* Set curl error buffer and zero it */
res = curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->error);
if (res != CURLE_OK) {
return (-1);
}
memset(self->error, 0, sizeof(self->error));
/* Set backreference */
res = curl_easy_setopt(self->handle, CURLOPT_PRIVATE, (char *) self);
if (res != CURLE_OK) {
return (-1);
}
which means that given the pycurl.Curl object is not reused for another connection or destroyed, it should be pretty safe to use the curl error message in the return value of pycurl.CurlMulti.info_read().
This answer gives me another interesting fact:
It is not safe to set CURLOPT_PRIVATE on the pycurl.Curl object.

How to tell when Microsoft Print to PDF printer driver is finished?

I needed a cheap way for my application to create a PDF file. So I'm using the print functions of the Windows API directly (CreateDC(), StartDoc(), StartPage(), EndPage(), EndDoc(), etc.), and selecting the Microsoft Print to PDF printer driver.
In addition, I found that if I set the lpszOutput member of the DOCINFOstructure to a filename, the driver will write the PDF file to the named file without prompting the user for a name.
So far, so good. But how do I know when the PDF file has been created? There are spooler APIs, but the driver isn't necessarily done just because the spooler is done. Or I could create a loop that looks for the file, but of course it will exist before it is actually done. I also thought about trying to put a lock on the file in my loop, which should fail if the file doesn't exist yet or is still being written to.
But I can't help but wonder if there's a more direct way to know when the PDF file is ready.
If you are using the GDI Print API (wingdi.h), then this link shows the sample code used to query the status of print jobs on a printer.
I'm including the code from the link, but you might want to read the article as well.
#include <Windows.h>
#include <wingdi.h>
BOOL GetJobs(HANDLE hPrinter, /* Handle to the printer. */
JOB_INFO_2 **ppJobInfo, /* Pointer to be filled. */
int *pcJobs, /* Count of jobs filled. */
DWORD *pStatus) /* Print Queue status. */
{
DWORD cByteNeeded,
nReturned,
cByteUsed;
JOB_INFO_2 *pJobStorage = NULL;
PRINTER_INFO_2 *pPrinterInfo = NULL;
/* Get the buffer size needed. */
if (!GetPrinter(hPrinter, 2, NULL, 0, &cByteNeeded)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
}
pPrinterInfo = (PRINTER_INFO_2 *)malloc(cByteNeeded);
if (!(pPrinterInfo))
/* Failure to allocate memory. */
return FALSE;
/* Get the printer information. */
if (!GetPrinter(hPrinter,
2,
(LPSTR)pPrinterInfo,
cByteNeeded,
&cByteUsed)) {
/* Failure to access the printer. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
/* Get job storage space. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
NULL,
0,
(LPDWORD)&cByteNeeded,
(LPDWORD)&nReturned)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
}
pJobStorage = (JOB_INFO_2 *)malloc(cByteNeeded);
if (!pJobStorage) {
/* Failure to allocate Job storage space. */
free(pPrinterInfo);
pPrinterInfo = NULL;
return FALSE;
}
ZeroMemory(pJobStorage, cByteNeeded);
/* Get the list of jobs. */
if (!EnumJobs(hPrinter,
0,
pPrinterInfo->cJobs,
2,
(LPBYTE)pJobStorage,
cByteNeeded,
(LPDWORD)&cByteUsed,
(LPDWORD)&nReturned)) {
free(pPrinterInfo);
free(pJobStorage);
pJobStorage = NULL;
pPrinterInfo = NULL;
return FALSE;
}
/*
* Return the information.
*/
*pcJobs = nReturned;
*pStatus = pPrinterInfo->Status;
*ppJobInfo = pJobStorage;
free(pPrinterInfo);
return TRUE;
}
BOOL IsPrinterError(HANDLE hPrinter) {
JOB_INFO_2 *pJobs;
int cJobs,
i;
DWORD dwPrinterStatus;
/*
* Get the state information for the Printer Queue and
* the jobs in the Printer Queue.
*/
if (!GetJobs(hPrinter, &pJobs, &cJobs, &dwPrinterStatus))
return FALSE;
/*
* If the Printer reports an error, believe it.
*/
if (dwPrinterStatus &
(PRINTER_STATUS_ERROR |
PRINTER_STATUS_PAPER_JAM |
PRINTER_STATUS_PAPER_OUT |
PRINTER_STATUS_PAPER_PROBLEM |
PRINTER_STATUS_OUTPUT_BIN_FULL |
PRINTER_STATUS_NOT_AVAILABLE |
PRINTER_STATUS_NO_TONER |
PRINTER_STATUS_OUT_OF_MEMORY |
PRINTER_STATUS_OFFLINE |
PRINTER_STATUS_DOOR_OPEN)) {
free(pJobs);
return TRUE;
}
/*
* Find the Job in the Queue that is printing.
*/
for (i = 0; i < cJobs; i++) {
if (pJobs[i].Status & JOB_STATUS_PRINTING) {
/*
* If the job is in an error state,
* report an error for the printer.
* Code could be inserted here to
* attempt an interpretation of the
* pStatus member as well.
*/
if (pJobs[i].Status &
(JOB_STATUS_ERROR |
JOB_STATUS_OFFLINE |
JOB_STATUS_PAPEROUT |
JOB_STATUS_BLOCKED_DEVQ)) {
free(pJobs);
return TRUE;
}
}
}
/*
* No error condition.
*/
free(pJobs);
return FALSE;
}

C++ and OpenSSL Library: How can I set subjectAltName (SAN) from code?

I'm trying to create self-signed request with subjectAltName from c++ code (trying to implement dynamic self-signed certificates like this to actual version of OpenResty, but there is not sollution for subjectAltName).
Please, provide some examples of setting SANs from C++/OpenSSL code. I trying some like this:
X509_EXTENSION *ext;
STACK_OF (X509_EXTENSION) * extlist;
char *ext_name = "subjectAltName";
char *ext_value = "DNS:lohsport.com";
extlist = sk_X509_EXTENSION_new_null ();
ext = X509V3_EXT_conf (NULL, NULL, ext_name, ext_value);
if(ext == NULL)
{
*err = "Error creating subjectAltName extension";
goto failed;
}
sk_X509_EXTENSION_push (extlist, ext);
if (!X509_REQ_add_extensions (x509_req, extlist)){
*err = "Error adding subjectAltName to the request";
goto failed;
}
sk_X509_EXTENSION_pop_free (extlist, X509_EXTENSION_free);
It's compiling successfully but not works.
I would be grateful for any help.
UPDATE
Now i trying to work as in selfsing.c demo of OpenSSL Library:
1) I defined a function for adding extensions to CSR:
int add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, char *value)
{
X509_EXTENSION *ex;
ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
if (!ex)
return 0;
sk_X509_EXTENSION_push(sk, ex);
return 1;
}
2) Add this block to my function which generates CSR:
char Buffer[512];
// Format the value
sprintf (Buffer, "DNS:%s", info->common_name);
xts = sk_X509_EXTENSION_new_null();
add_ext(exts, NID_subject_alt_name, Buffer);
if(X509_REQ_add_extensions(x509_req, exts) != 1) {
*err = "X509_REQ_add_extensions() failed";
goto failed;
}
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
The code again compiles correctly, certificates are generated on the fly, but alternative names still don't work, and I get an error in the browser:
NET :: ERR_CERT_COMMON_NAME_INVALID
and I don’t see the alternative name information in the certificate details.
What other solutions can there be for a SAN problem? I can provide all the code for example on githab if it can help.
Hello I have done something like that (but I am working with X509 object not X509_REQ object like you :
static int cs_cert_set_subject_alt_name(X509 *x509_cert)
{
char *subject_alt_name = "IP: 192.168.1.1";
X509_EXTENSION *extension_san = NULL;
ASN1_OCTET_STRING *subject_alt_name_ASN1 = NULL;
int ret = -1;
subject_alt_name_ASN1 = ASN1_OCTET_STRING_new();
if (!subject_alt_name_ASN1) {
goto err;
}
ASN1_OCTET_STRING_set(subject_alt_name_ASN1, (unsigned char*) subject_alt_name, strlen(subject_alt_name));
if (!X509_EXTENSION_create_by_NID(&extension_san, NID_subject_alt_name, 0, subject_alt_name_ASN1)) {
goto err;
}
ASN1_OCTET_STRING_free(subject_alt_name_ASN1);
ret = X509_add_ext(x509_cert, extension_san, -1);
if (!ret) {
goto err;
}
X509_EXTENSION_free(extension_san);
err:
if (subject_alt_name_ASN1) ASN1_OCTET_STRING_free(subject_alt_name_ASN1);
if (extension_san) X509_EXTENSION_free(extension_san);
return -1;
}
It worked for me for the moment, I still have some trouble when I want to update an already existing certificate with a new subject alt name (because of a new ip address).
To see the result and check if the subject alt name is made :
$ openssl x509 -text -in cert.pem
Instead of X509V3_EXT_conf function try with X509V3_EXT_conf_nid function in which you pass the NID instead of name.
ext = X509V3_EXT_conf (NULL, NULL, ext_name, ext_value);
can be
ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, ext_value);
Your code might not be working because you might not be exactly matching the extension name with the one in OpenSSL code.

How to create a file only if it doesn't exist?

I wrote a UNIX daemon (targeting Debian, but it shouldn't matter) and I wanted to provide some way of creating a ".pid" file, (a file which contains the process identifier of the daemon).
I searched for a way of opening a file only if it doesn't exist, but couldn't find one.
Basically, I could do something like:
if (fileexists())
{
//fail...
}
else
{
//create it with fopen() or similar
}
But as it stands, this code does not perform the task in a atomic fashion, and doing so would be dangerous, because another process might create the file during my test, and the file creation.
Do you guys have any idea on how to do that?
Thank you.
P.S: Bonus point for a solution which only involves std::streams.
man 2 open:
O_EXCL Ensure that this call creates the file: if this flag is specified in conjunction with O_CREAT, and pathname already exists, then open()
will fail. The behavior of O_EXCL is undefined if O_CREAT is not specified.
so, you could call fd = open(name, O_CREAT | O_EXCL, 0644); /* Open() is atomic. (for a reason) */
UPDATE: and you should of course OR one of the O_RDONLY, O_WRONLY, or O_RDWR flags into the flags argument.
I learned about proper daemonizing here (back in the day):
http://www.enderunix.org/docs/eng/daemon.php
It is a good read. I have since improved the locking code to eliminate race conditions on platforms that allow advisory file locking with specific regions specified.
Here is a relevant snippet from a project that I was involved in:
static int zfsfuse_do_locking(int in_child)
{
/* Ignores errors since the directory might already exist */
mkdir(LOCKDIR, 0700);
if (!in_child)
{
ASSERT(lock_fd == -1);
/*
* before the fork, we create the file, truncating it, and locking the
* first byte
*/
lock_fd = creat(LOCKFILE, S_IRUSR | S_IWUSR);
if(lock_fd == -1)
return -1;
/*
* only if we /could/ lock all of the file,
* we shall lock just the first byte; this way
* we can let the daemon child process lock the
* remainder of the file after forking
*/
if (0==lockf(lock_fd, F_TEST, 0))
return lockf(lock_fd, F_TLOCK, 1);
else
return -1;
} else
{
ASSERT(lock_fd != -1);
/*
* after the fork, we instead try to lock only the region /after/ the
* first byte; the file /must/ already exist. Only in this way can we
* prevent races with locking before or after the daemonization
*/
lock_fd = open(LOCKFILE, O_WRONLY);
if(lock_fd == -1)
return -1;
ASSERT(-1 == lockf(lock_fd, F_TEST, 0)); /* assert that parent still has the lock on the first byte */
if (-1 == lseek(lock_fd, 1, SEEK_SET))
{
perror("lseek");
return -1;
}
return lockf(lock_fd, F_TLOCK, 0);
}
}
void do_daemon(const char *pidfile)
{
chdir("/");
if (pidfile) {
struct stat dummy;
if (0 == stat(pidfile, &dummy)) {
cmn_err(CE_WARN, "%s already exists; aborting.", pidfile);
exit(1);
}
}
/*
* info gleaned from the web, notably
* http://www.enderunix.org/docs/eng/daemon.php
*
* and
*
* http://sourceware.org/git/?p=glibc.git;a=blob;f=misc/daemon.c;h=7597ce9996d5fde1c4ba622e7881cf6e821a12b4;hb=HEAD
*/
{
int forkres, devnull;
if(getppid()==1)
return; /* already a daemon */
forkres=fork();
if (forkres<0)
{ /* fork error */
cmn_err(CE_WARN, "Cannot fork (%s)", strerror(errno));
exit(1);
}
if (forkres>0)
{
int i;
/* parent */
for (i=getdtablesize();i>=0;--i)
if ((lock_fd!=i) && (ioctl_fd!=i)) /* except for the lockfile and the comm socket */
close(i); /* close all descriptors */
/* allow for airtight lockfile semantics... */
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 200000; /* 0.2 seconds */
select(0, NULL, NULL, NULL, &tv);
VERIFY(0 == close(lock_fd));
lock_fd == -1;
exit(0);
}
/* child (daemon) continues */
setsid(); /* obtain a new process group */
VERIFY(0 == chdir("/")); /* change working directory */
umask(027); /* set newly created file permissions */
devnull=open("/dev/null",O_RDWR); /* handle standard I/O */
ASSERT(-1 != devnull);
dup2(devnull, 0); /* stdin */
dup2(devnull, 1); /* stdout */
dup2(devnull, 2); /* stderr */
if (devnull>2)
close(devnull);
/*
* contrary to recommendation, do _not_ ignore SIGCHLD:
* it will break exec-ing subprocesses, e.g. for kstat mount and
* (presumably) nfs sharing!
*
* this will lead to really bad performance too
*/
signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
}
if (0 != zfsfuse_do_locking(1))
{
cmn_err(CE_WARN, "Unexpected locking conflict (%s: %s)", strerror(errno), LOCKFILE);
exit(1);
}
if (pidfile) {
FILE *f = fopen(pidfile, "w");
if (!f) {
cmn_err(CE_WARN, "Error opening %s.", pidfile);
exit(1);
}
if (fprintf(f, "%d\n", getpid()) < 0) {
unlink(pidfile);
exit(1);
}
if (fclose(f) != 0) {
unlink(pidfile);
exit(1);
}
}
}
See also http://gitweb.zfs-fuse.net/?p=sehe;a=blob;f=src/zfs-fuse/util.c;h=7c9816cc895db4f65b94592eebf96d05cd2c369a;hb=refs/heads/maint
The only way I can think of is to use system level locks. See this: C++ how to check if file is in use - multi-threaded multi-process system
One way to approach this problem is to open the file for appending. If the function succeeds and the position is at 0 then you can be fairly certain this is a new file. Could still be an empty file but that scenario may not be important.
FILE* pFile = fopen(theFilePath, "a+");
if (pFile && gfetpos(pFile) == 0) {
// Either file didn't previously exist or it did and was empty
} else if (pFile) {
fclose(pFile);
}
It would appear that there's no way to do it strictly using streams.
You can, instead, use open (as mentioned above by wildplasser) and if that succeeds, proceed to open the same file as a stream. Of course, if all you're writing to the file is a PID, it is unclear why you wouldn't just write it using C-style write().
O_EXCL only excludes other processes that are attempting to open the same file using O_EXCL. This, of course, means that you never have a perfect guarantee, but if the file name/location is somewhere nobody else is likely to be opening (other than folks you know are using O_EXCL) you should be OK.