diff options
Diffstat (limited to 'ext/misc/fileio.c')
-rw-r--r-- | ext/misc/fileio.c | 102 |
1 files changed, 80 insertions, 22 deletions
diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c index 475f3713c..db6935700 100644 --- a/ext/misc/fileio.c +++ b/ext/misc/fileio.c @@ -30,6 +30,17 @@ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <stdio.h> +#include <string.h> +#include <assert.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <dirent.h> +#include <time.h> +#include <utime.h> + #define FSDIR_SCHEMA "CREATE TABLE x(name,mode,mtime,data,dir HIDDEN)" @@ -69,44 +80,91 @@ static void readfileFunc( readFileContents(context, zName); } +static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ + char *zMsg = 0; + va_list ap; + va_start(ap, zFmt); + zMsg = sqlite3_vmprintf(zFmt, ap); + sqlite3_result_error(ctx, zMsg, -1); + sqlite3_free(zMsg); + va_end(ap); +} + /* -** Implementation of the "writefile(X,Y)" SQL function. The argument Y -** is written into file X. The number of bytes written is returned. Or -** NULL is returned if something goes wrong, such as being unable to open -** file X for writing. +** Implementation of the "writefile(W,X[,Y]])" SQL function. +** +** The argument X is written into file W. The number of bytes written is +** returned. Or NULL is returned if something goes wrong, such as being unable +** to open file X for writing. */ static void writefileFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ - FILE *out; - const char *z; - sqlite3_int64 rc; const char *zFile; + mode_t mode = 0; + + if( argc<2 || argc>3 ){ + sqlite3_result_error(context, + "wrong number of arguments to function writefile()", -1 + ); + return; + } - (void)(argc); /* Unused parameter */ zFile = (const char*)sqlite3_value_text(argv[0]); if( zFile==0 ) return; - out = fopen(zFile, "wb"); - if( out==0 ) return; - z = (const char*)sqlite3_value_blob(argv[1]); - if( z==0 ){ - rc = 0; + if( argc>=3 ){ + sqlite3_result_int(context, 0); + mode = sqlite3_value_int(argv[2]); + } + + if( S_ISLNK(mode) ){ + const char *zTo = (const char*)sqlite3_value_text(argv[1]); + if( symlink(zTo, zFile)<0 ){ + ctxErrorMsg(context, "failed to create symlink: %s", zFile); + return; + } }else{ - rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); + if( S_ISDIR(mode) ){ + if( mkdir(zFile, mode) ){ + ctxErrorMsg(context, "failed to create directory: %s", zFile); + return; + } + }else{ + sqlite3_int64 nWrite = 0; + const char *z; + int rc = 0; + FILE *out = fopen(zFile, "wb"); + if( out==0 ){ + if( argc>2 ){ + ctxErrorMsg(context, "failed to open file for writing: %s", zFile); + } + return; + } + z = (const char*)sqlite3_value_blob(argv[1]); + if( z ){ + sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); + nWrite = sqlite3_value_bytes(argv[1]); + if( nWrite!=n ){ + ctxErrorMsg(context, "failed to write file: %s", zFile); + rc = 1; + } + } + fclose(out); + if( rc ) return; + sqlite3_result_int64(context, nWrite); + } + + if( argc>2 && chmod(zFile, mode & 0777) ){ + ctxErrorMsg(context, "failed to chmod file: %s", zFile); + return; + } } - fclose(out); - sqlite3_result_int64(context, rc); } #ifndef SQLITE_OMIT_VIRTUALTABLE -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> - /* */ typedef struct fsdir_cursor fsdir_cursor; @@ -463,7 +521,7 @@ int sqlite3_fileio_init( rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0, + rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0, writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ |