** This function does the work for the writefile() UDF. Refer to ** header comments at the top of this file for details. */
| 2460 | ** header comments at the top of this file for details. |
| 2461 | */ |
| 2462 | static int writeFile( |
| 2463 | sqlite3_context *pCtx, /* Context to return bytes written in */ |
| 2464 | const char *zFile, /* File to write */ |
| 2465 | sqlite3_value *pData, /* Data to write */ |
| 2466 | mode_t mode, /* MODE parameter passed to writefile() */ |
| 2467 | sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ |
| 2468 | ){ |
| 2469 | #if !defined(_WIN32) && !defined(WIN32) |
| 2470 | if( S_ISLNK(mode) ){ |
| 2471 | const char *zTo = (const char*)sqlite3_value_text(pData); |
| 2472 | if( symlink(zTo, zFile)<0 ) return 1; |
| 2473 | }else |
| 2474 | #endif |
| 2475 | { |
| 2476 | if( S_ISDIR(mode) ){ |
| 2477 | if( mkdir(zFile, mode) ){ |
| 2478 | /* The mkdir() call to create the directory failed. This might not |
| 2479 | ** be an error though - if there is already a directory at the same |
| 2480 | ** path and either the permissions already match or can be changed |
| 2481 | ** to do so using chmod(), it is not an error. */ |
| 2482 | struct stat sStat; |
| 2483 | if( errno!=EEXIST |
| 2484 | || 0!=fileStat(zFile, &sStat) |
| 2485 | || !S_ISDIR(sStat.st_mode) |
| 2486 | || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777)) |
| 2487 | ){ |
| 2488 | return 1; |
| 2489 | } |
| 2490 | } |
| 2491 | }else{ |
| 2492 | sqlite3_int64 nWrite = 0; |
| 2493 | const char *z; |
| 2494 | int rc = 0; |
| 2495 | FILE *out = fopen(zFile, "wb"); |
| 2496 | if( out==0 ) return 1; |
| 2497 | z = (const char*)sqlite3_value_blob(pData); |
| 2498 | if( z ){ |
| 2499 | sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out); |
| 2500 | nWrite = sqlite3_value_bytes(pData); |
| 2501 | if( nWrite!=n ){ |
| 2502 | rc = 1; |
| 2503 | } |
| 2504 | } |
| 2505 | fclose(out); |
| 2506 | if( rc==0 && mode && chmod(zFile, mode & 0777) ){ |
| 2507 | rc = 1; |
| 2508 | } |
| 2509 | if( rc ) return 2; |
| 2510 | sqlite3_result_int64(pCtx, nWrite); |
| 2511 | } |
| 2512 | } |
| 2513 | |
| 2514 | if( mtime>=0 ){ |
| 2515 | #if defined(_WIN32) |
| 2516 | #if !SQLITE_OS_WINRT |
| 2517 | /* Windows */ |
| 2518 | FILETIME lastAccess; |
| 2519 | FILETIME lastWrite; |
no test coverage detected