sqlite3: Unable to change the default file permission for database file by setting compiler option SQLITE_DEFAULT_FILE_PERMISSIONS to 600 - sqlite

C code:
sql.c
#include <stdio.h>
#include <sqlite3.h>
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("test.db", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
} else {
fprintf(stderr, "Opened database successfully\n");
}
sqlite3_close(db);
}
compile:
gcc sql.c -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 -lsqlite3
File permissions are not changing:
-rw-r--r-- 1 user user2 0 Feb 15 02:17 test.db
Can any one please help me to change default file permission

Related

Using execvp with low level IO and standard input

I am trying to use low level IO (Read) to read in standard input for a command. After getting that command I try to pass it into execvp so that it can carry out the command but it is not working. I think the problem is I am not sure how to pass it into execvp properly. It worked before with command line arguments but I cant get standard input working.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
int r;
char b1[4096];
char command[4096];
r = read(STDIN_FILENO, b1, 4096);
memcpy(command, b1, r);
command[r] = '\0';
//printf("%s\n", command);
char* progname = command;
//char* progname = argv[1];
pid_t pid;
if ((pid = fork()) < 0) perror("fork");
else if (pid == 0) { // child process
if (execvp(progname, argv + 1) == -1) {
perror("execvp");
return EXIT_FAILURE;
} // if
} // if
else {
fprintf(stderr, "Please specify the name of the program to exec as a command line argument\n");
return EXIT_FAILURE;
} // if
} // main

SQLite: How embed the memvfs extension to Amalgamation?

I need to load/save SQLite database in memory buffer. For this, I want embed the memvfs extension into sqlite3 code and compile it wholly as sqlite3.dll.
How do it?
Update1:
I want use the memvfs as temp memory buffer. My program load data from net to buffer, connect to this memory buffer and restore data into empty in-memory db. I thoutgh that inclusion of memvfs to sqlite amalgamation would improve perfomance.
Update2:
If you want to use memvfs extension pay attention to bug in readme comment in source. Use "PRAGMA journal_mode=OFF" instead "journal_mode=NONE"
Update3:
Another bug in memvfs.c - use 'max' instead 'maxsz' for maxsz param in URI.
The sqlite developers carefully set a rakes :(
Test program to demonstrate using memvfs:
#include <fcntl.h>
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
sqlite3 *db;
char *err;
// Open an in-memory database to use as a handle for loading the memvfs extension
if (sqlite3_open(":memory:", &db) != SQLITE_OK) {
fprintf(stderr, "open :memory: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_enable_load_extension(db, 1);
if (sqlite3_load_extension(db, "./memvfs", NULL, &err) != SQLITE_OK) {
fprintf(stderr, "load extension: %s\n", err);
return EXIT_FAILURE;
}
// Done with this database
sqlite3_close(db);
// Read the real database into memory
int fd = open("foo.db", O_RDONLY);
if (fd < 0) {
perror("open");
return EXIT_FAILURE;
}
struct stat s;
if (fstat(fd, &s) < 0) {
perror("fstat");
return EXIT_FAILURE;
}
void *memdb = sqlite3_malloc64(s.st_size);
if (read(fd, memdb, s.st_size) != s.st_size) {
perror("read");
return EXIT_FAILURE;
}
close(fd);
// And open that memory with memvfs now that it holds a valid database
char *memuri = sqlite3_mprintf("file:whatever?ptr=0x%p&sz=%lld&freeonclose=1",
memdb, (long long)s.st_size);
printf("Trying to open '%s'\n", memuri);
if (sqlite3_open_v2(memuri, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
"memvfs") != SQLITE_OK) {
fprintf(stderr, "open memvfs: %s\n", sqlite3_errmsg(db));
return EXIT_FAILURE;
}
sqlite3_free(memuri);
// Try querying the database to show it works.
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, "SELECT b FROM test", -1, &stmt, NULL) !=
SQLITE_OK) {
fprintf(stderr, "prepare: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return EXIT_FAILURE;
}
for (int rc = sqlite3_step(stmt); rc == SQLITE_ROW; rc = sqlite3_step(stmt)) {
printf("%d\n", sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
Usage:
# Create a test database to use with memvfs
$ sqlite3 foo.db
sqlite> CREATE TABLE test(b INTEGER);
sqlite> INSERT INTO test VALUES (1), (2);
sqlite> .quit
# Compile the memvfs module and test program
$ gcc -O -fPIC -shared -o memvfs.so memvfs.c
$ gcc -O -Wall -Wextra testmem.c -lsqlite3
# And run it.
$ ./a.out
Trying to open 'file:whatever?ptr=0x56653FE2B940&sz=8192&freeonclose=1'
1
2
Same workflow if you compile it directly into your program instead of using a loadable module; you just have to call sqlite3_memvfs_init() with the right arguments instead of using sqlite3_load_extension().

Trouble with creating an empty file using C programming language in UNIX environment

I have recently started programming in UNIX environment. I need to write a program which creates an empty file with name and size given in the terminal using this commands
gcc foo.c -o foo.o
./foo.o result.txt 1000
Here result.txt means the name of the newly created file, and 1000 means the size of the file in bytes.
I know for sure that lseek function moves the file offset, but the trouble is that whenever I run the program it creates a file with a given name, however the size of the file is 0.
Here is the code of my small program.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int fd;
char *file_name;
off_t bytes;
mode_t mode;
if (argc < 3)
{
perror("There is not enough command-line arguments.");
//return 1;
}
file_name = argv[1];
bytes = atoi(argv[2]);
mode = S_IWUSR | S_IWGRP | S_IWOTH;
if ((fd = creat(file_name, mode)) < 0)
{
perror("File creation error.");
//return 1;
}
if (lseek(fd, bytes, SEEK_SET) == -1)
{
perror("Lseek function error.");
//return 1;
}
close(fd);
return 0;
}
If you aren't allowed to use any other functions to assist in creating a "blank" text file, why not change your file mode on creat() then loop-and-write:
int fd = creat(file_name, 0666);
for (int i=0; i < bytes; i++) {
int wbytes = write(fd, " ", 1);
if (wbytes < 0) {
perror("write error")
return 1;
}
}
You'll want to have some additional checks here but, that would be the general idea.
I don't know whats acceptable in your situation but, possibly adding just the write() call after lseek() even:
// XXX edit to include write
if ((fd = creat(file_name, 0666)) < 0) {
perror("File creation error");
//return 1;
}
// XXX seek to bytes - 1
if (lseek(fd, bytes - 1, SEEK_SET) == -1) {
perror("lseek() error");
//return 1;
}
// add this call to write a single byte # position set by lseek
if (write(fd, " ", 1) == -1) {
perror("write() error");
//return 1;
}
close(fd);
return 0;

Adding a custom sqlite function to a Qt application

I am trying to add a custom sqlite3 regexp function into my Qt application (as recommended by this answer). But as soon as I call the sqlite3_create_function function, I get the message The program has unexpectedly finished. When I debug, it terminates in a segmentation fault in sqlite3_mutex_enter. There is a MWE below, with apologies for the absolute file paths.
The regexp implementation in my code is from this site; it also fails with the msign function here. The various checks of driver()->handle() are straight from the Qt docs.
Incidentally, I used select sqlite_version(); to determine that Qt 5.5 uses sqlite version 3.8.8.2. I found that version by looking through old commits in the Qt GitHub repository.
MWE.pro
QT += core gui
TARGET = MWE
TEMPLATE = app
QT += sql
SOURCES += main.cpp \
D:\Qt\Qt5.5.0\5.5\Src\3rdparty\sqlite\sqlite3.c
HEADERS += D:\Qt\Qt5.5.0\5.5\Src\3rdparty\sqlite\sqlite3.h
main.cpp
#include <QtSql>
#include "D:/Qt/Qt5.5.0/5.5/Src/3rdparty/sqlite/sqlite3.h"
void qtregexp(sqlite3_context* ctx, int argc, sqlite3_value** argv)
{
QRegExp regex;
QString str1((const char*)sqlite3_value_text(argv[0]));
QString str2((const char*)sqlite3_value_text(argv[1]));
regex.setPattern(str1);
regex.setCaseSensitivity(Qt::CaseInsensitive);
bool b = str2.contains(regex);
if (b)
{
sqlite3_result_int(ctx, 1);
}
else
{
sqlite3_result_int(ctx, 0);
}
}
int main(int argc, char *argv[])
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("my.db");
db.open();
QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) { // check that it is not NULL
// This shows that the database handle is generally valid:
qDebug() << sqlite3_db_filename(db_handle, "main");
sqlite3_create_function(db_handle, "regexp", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL, &qtregexp, NULL, NULL);
qDebug() << "This won't be reached."
QSqlQuery query;
query.prepare("select regexp('p$','tap');");
query.exec();
query.next();
qDebug() << query.value(0).toString();
}
}
db.close();
}
You need to call sqlite3_initialize() after you get the database handle from Qt, according to this forum post.
...
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) { // check that it is not NULL
sqlite3_initialize();
...
This solves the issue.

why vi can modify a file while this file is write locked?

I compile this file and run it in one console.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
/* l_type l_whence l_start l_len l_pid */
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0 };
int fd;
fl.l_pid = getpid();
if (argc > 1)
fl.l_type = F_RDLCK;
if ((fd = open("lockdemo.c", O_RDWR)) == -1) {
perror("open");
exit(1);
}
printf("Press <RETURN> to try to get lock: ");
getchar();
printf("Trying to get lock...");
if (fcntl(fd, F_SETLKW, &fl) == -1) {
perror("fcntl");
exit(1);
}
printf("got lock\n");
printf("Press <RETURN> to release lock: ");
getchar();
fl.l_type = F_UNLCK; /* set to unlock same region */
if (fcntl(fd, F_SETLK, &fl) == -1) {
perror("fcntl");
exit(1);
}
printf("Unlocked.\n");
close(fd);
return 0;
}
It outputs:
ZJ:~/Documents/c$ ./a.out
press <RETURN> to try to get lock:
Trying to get lock...got lock
press <RETURN> to release lock:
I open another console and vi lockdemo.c and had modified lockdemo.c successfully. Why? Isn't this file locked?
While I open another console
ZJ:~/Documents/c$ ./a.out
press <RETURN> to try to get lock:
the a.out was always running getchar(), and cannot even execute printf("Trying to get lock...");
I am totally confused.
You are applying an advisory lock on the lockdemo.c file. vi is free to ignore it by design. You should have used a mandatory lock which AFAIK isn't standardized under Unix to enforce vi not to do it.

Resources