1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include <libwebsockets.h> 26d4afb5ceSopenharmony_ci#include <private-lib-core.h> 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#include <sqlite3.h> 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci/* 31d4afb5ceSopenharmony_ci * we get one of these per matching result from the query 32d4afb5ceSopenharmony_ci */ 33d4afb5ceSopenharmony_ci 34d4afb5ceSopenharmony_cistatic int 35d4afb5ceSopenharmony_cilws_struct_sq3_deser_cb(void *priv, int cols, char **cv, char **cn) 36d4afb5ceSopenharmony_ci{ 37d4afb5ceSopenharmony_ci lws_struct_args_t *a = (lws_struct_args_t *)priv; 38d4afb5ceSopenharmony_ci char *u = lwsac_use_zero(&a->ac, a->dest_len, a->ac_block_size); 39d4afb5ceSopenharmony_ci lws_dll2_owner_t *o = (lws_dll2_owner_t *)a->cb_arg; 40d4afb5ceSopenharmony_ci const lws_struct_map_t *map = a->map_st[0]; 41d4afb5ceSopenharmony_ci int n, mems = (int)(ssize_t)a->map_entries_st[0]; 42d4afb5ceSopenharmony_ci long long li; 43d4afb5ceSopenharmony_ci size_t lim; 44d4afb5ceSopenharmony_ci char **pp; 45d4afb5ceSopenharmony_ci char *s; 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_ci if (!u) { 48d4afb5ceSopenharmony_ci lwsl_err("OOM\n"); 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci return 1; 51d4afb5ceSopenharmony_ci } 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci lws_dll2_add_tail((lws_dll2_t *)((char *)u + a->toplevel_dll2_ofs), o); 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_ci while (mems--) { 56d4afb5ceSopenharmony_ci for (n = 0; n < cols; n++) { 57d4afb5ceSopenharmony_ci if (!cv[n] || strcmp(cn[n], map->colname)) 58d4afb5ceSopenharmony_ci continue; 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci switch (map->type) { 61d4afb5ceSopenharmony_ci case LSMT_SIGNED: 62d4afb5ceSopenharmony_ci if (map->aux == sizeof(signed char)) { 63d4afb5ceSopenharmony_ci signed char *pc; 64d4afb5ceSopenharmony_ci pc = (signed char *)(u + map->ofs); 65d4afb5ceSopenharmony_ci *pc = (signed char)atoi(cv[n]); 66d4afb5ceSopenharmony_ci break; 67d4afb5ceSopenharmony_ci } 68d4afb5ceSopenharmony_ci if (map->aux == sizeof(short)) { 69d4afb5ceSopenharmony_ci short *ps; 70d4afb5ceSopenharmony_ci ps = (short *)(u + map->ofs); 71d4afb5ceSopenharmony_ci *ps = (short)atoi(cv[n]); 72d4afb5ceSopenharmony_ci break; 73d4afb5ceSopenharmony_ci } 74d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 75d4afb5ceSopenharmony_ci int *pi; 76d4afb5ceSopenharmony_ci pi = (int *)(u + map->ofs); 77d4afb5ceSopenharmony_ci *pi = (int)atoll(cv[n]); /* 32-bit OS */ 78d4afb5ceSopenharmony_ci break; 79d4afb5ceSopenharmony_ci } 80d4afb5ceSopenharmony_ci if (map->aux == sizeof(long)) { 81d4afb5ceSopenharmony_ci long *pl; 82d4afb5ceSopenharmony_ci pl = (long *)(u + map->ofs); 83d4afb5ceSopenharmony_ci *pl = (long)atoll(cv[n]); /* 32-bit OS */ 84d4afb5ceSopenharmony_ci break; 85d4afb5ceSopenharmony_ci } 86d4afb5ceSopenharmony_ci { 87d4afb5ceSopenharmony_ci long long *pll; 88d4afb5ceSopenharmony_ci pll = (long long *)(u + map->ofs); 89d4afb5ceSopenharmony_ci *pll = atoll(cv[n]); 90d4afb5ceSopenharmony_ci } 91d4afb5ceSopenharmony_ci break; 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci case LSMT_UNSIGNED: 94d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned char)) { 95d4afb5ceSopenharmony_ci unsigned char *pc; 96d4afb5ceSopenharmony_ci pc = (unsigned char *)(u + map->ofs); 97d4afb5ceSopenharmony_ci *pc = (unsigned char)(unsigned int)atoi(cv[n]); 98d4afb5ceSopenharmony_ci break; 99d4afb5ceSopenharmony_ci } 100d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned short)) { 101d4afb5ceSopenharmony_ci unsigned short *ps; 102d4afb5ceSopenharmony_ci ps = (unsigned short *)(u + map->ofs); 103d4afb5ceSopenharmony_ci *ps = (unsigned short)atoi(cv[n]); 104d4afb5ceSopenharmony_ci break; 105d4afb5ceSopenharmony_ci } 106d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned int)) { 107d4afb5ceSopenharmony_ci unsigned int *pi; 108d4afb5ceSopenharmony_ci pi = (unsigned int *)(u + map->ofs); 109d4afb5ceSopenharmony_ci *pi = (unsigned int)atoi(cv[n]); 110d4afb5ceSopenharmony_ci break; 111d4afb5ceSopenharmony_ci } 112d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned long)) { 113d4afb5ceSopenharmony_ci unsigned long *pl; 114d4afb5ceSopenharmony_ci pl = (unsigned long *)(u + map->ofs); 115d4afb5ceSopenharmony_ci *pl = (unsigned long)atol(cv[n]); 116d4afb5ceSopenharmony_ci break; 117d4afb5ceSopenharmony_ci } 118d4afb5ceSopenharmony_ci { 119d4afb5ceSopenharmony_ci unsigned long long *pll; 120d4afb5ceSopenharmony_ci pll = (unsigned long long *)(u + map->ofs); 121d4afb5ceSopenharmony_ci *pll = (unsigned long long)atoll(cv[n]); 122d4afb5ceSopenharmony_ci } 123d4afb5ceSopenharmony_ci break; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci case LSMT_BOOLEAN: 126d4afb5ceSopenharmony_ci li = 0; 127d4afb5ceSopenharmony_ci if (!strcmp(cv[n], "true") || 128d4afb5ceSopenharmony_ci !strcmp(cv[n], "TRUE") || cv[n][0] == '1') 129d4afb5ceSopenharmony_ci li = 1; 130d4afb5ceSopenharmony_ci if (map->aux == sizeof(char)) { 131d4afb5ceSopenharmony_ci char *pc; 132d4afb5ceSopenharmony_ci pc = (char *)(u + map->ofs); 133d4afb5ceSopenharmony_ci *pc = (char)li; 134d4afb5ceSopenharmony_ci break; 135d4afb5ceSopenharmony_ci } 136d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 137d4afb5ceSopenharmony_ci int *pi; 138d4afb5ceSopenharmony_ci pi = (int *)(u + map->ofs); 139d4afb5ceSopenharmony_ci *pi = (int)li; 140d4afb5ceSopenharmony_ci } else { 141d4afb5ceSopenharmony_ci uint64_t *p64; 142d4afb5ceSopenharmony_ci p64 = (uint64_t *)(u + map->ofs); 143d4afb5ceSopenharmony_ci *p64 = (uint64_t)li; 144d4afb5ceSopenharmony_ci } 145d4afb5ceSopenharmony_ci break; 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 148d4afb5ceSopenharmony_ci s = (char *)(u + map->ofs); 149d4afb5ceSopenharmony_ci lim = map->aux; 150d4afb5ceSopenharmony_ci lws_strncpy(s, cv[n], lim); 151d4afb5ceSopenharmony_ci break; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 154d4afb5ceSopenharmony_ci pp = (char **)(u + map->ofs); 155d4afb5ceSopenharmony_ci lim = strlen(cv[n]); 156d4afb5ceSopenharmony_ci s = lwsac_use(&a->ac, lim + 1, a->ac_block_size); 157d4afb5ceSopenharmony_ci if (!s) 158d4afb5ceSopenharmony_ci return 1; 159d4afb5ceSopenharmony_ci *pp = s; 160d4afb5ceSopenharmony_ci memcpy(s, cv[n], lim); 161d4afb5ceSopenharmony_ci s[lim] = '\0'; 162d4afb5ceSopenharmony_ci break; 163d4afb5ceSopenharmony_ci default: 164d4afb5ceSopenharmony_ci break; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci } 167d4afb5ceSopenharmony_ci map++; 168d4afb5ceSopenharmony_ci } 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci return 0; 171d4afb5ceSopenharmony_ci} 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci/* 174d4afb5ceSopenharmony_ci * Call this with an LSM_SCHEMA map, its colname is the table name and its 175d4afb5ceSopenharmony_ci * type information describes the toplevel type. Schema is dereferenced and 176d4afb5ceSopenharmony_ci * put in args before the actual sq3 query, which is given the child map. 177d4afb5ceSopenharmony_ci */ 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ciint 180d4afb5ceSopenharmony_cilws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order, 181d4afb5ceSopenharmony_ci const lws_struct_map_t *schema, lws_dll2_owner_t *o, 182d4afb5ceSopenharmony_ci struct lwsac **ac, int start, int _limit) 183d4afb5ceSopenharmony_ci{ 184d4afb5ceSopenharmony_ci int limit = _limit < 0 ? -_limit : _limit; 185d4afb5ceSopenharmony_ci char s[768], results[512], where[250]; 186d4afb5ceSopenharmony_ci lws_struct_args_t a; 187d4afb5ceSopenharmony_ci int n, m; 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci if (!order) 190d4afb5ceSopenharmony_ci order = "_lws_idx"; 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci memset(&a, 0, sizeof(a)); 193d4afb5ceSopenharmony_ci a.ac = *ac; 194d4afb5ceSopenharmony_ci a.cb_arg = o; /* lws_dll2_owner tracking query result objects */ 195d4afb5ceSopenharmony_ci a.map_st[0] = schema->child_map; 196d4afb5ceSopenharmony_ci a.map_entries_st[0] = schema->child_map_size; 197d4afb5ceSopenharmony_ci a.dest_len = schema->aux; /* size of toplevel object to allocate */ 198d4afb5ceSopenharmony_ci a.toplevel_dll2_ofs = schema->ofs; 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci lws_dll2_owner_clear(o); 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci /* 203d4afb5ceSopenharmony_ci * Explicitly list the columns instead of use *, so we can skip blobs 204d4afb5ceSopenharmony_ci */ 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci m = 0; 207d4afb5ceSopenharmony_ci for (n = 0; n < (int)schema->child_map_size; n++) 208d4afb5ceSopenharmony_ci m += lws_snprintf(&results[m], sizeof(results) - (unsigned int)n - 1, 209d4afb5ceSopenharmony_ci "%s%c", schema->child_map[n].colname, 210d4afb5ceSopenharmony_ci n + 1 == (int)schema->child_map_size ? ' ' : ','); 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_ci where[0] = '\0'; 213d4afb5ceSopenharmony_ci lws_snprintf(where, sizeof(where), " where _lws_idx >= %llu %s", 214d4afb5ceSopenharmony_ci (unsigned long long)start, filter ? filter : ""); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci lws_snprintf(s, sizeof(s) - 1, "select %s " 217d4afb5ceSopenharmony_ci "from %s %s order by %s %slimit %d;", results, 218d4afb5ceSopenharmony_ci schema->colname, where, order, 219d4afb5ceSopenharmony_ci _limit < 0 ? "desc " : "", limit); 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) { 224d4afb5ceSopenharmony_ci lwsl_err("%s: %s: fail %s\n", __func__, sqlite3_errmsg(pdb), s); 225d4afb5ceSopenharmony_ci lwsac_free(&a.ac); 226d4afb5ceSopenharmony_ci return -1; 227d4afb5ceSopenharmony_ci } 228d4afb5ceSopenharmony_ci 229d4afb5ceSopenharmony_ci *ac = a.ac; 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci return 0; 232d4afb5ceSopenharmony_ci} 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci/* 235d4afb5ceSopenharmony_ci * This takes a struct and turns it into an sqlite3 UPDATE, using the given 236d4afb5ceSopenharmony_ci * schema... which has one LSM_SCHEMA_DLL2 entry wrapping the actual schema 237d4afb5ceSopenharmony_ci */ 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_cistatic int 240d4afb5ceSopenharmony_ci_lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema, 241d4afb5ceSopenharmony_ci uint32_t idx, void *st) 242d4afb5ceSopenharmony_ci{ 243d4afb5ceSopenharmony_ci const lws_struct_map_t *map = schema->child_map; 244d4afb5ceSopenharmony_ci int n, m, pk = 0, nentries = (int)(ssize_t)schema->child_map_size, nef = 0, did; 245d4afb5ceSopenharmony_ci size_t sql_est = 46 + strlen(schema->colname) + 1; 246d4afb5ceSopenharmony_ci /* "insert into (_lws_idx, ) values (00000001,);" ... 247d4afb5ceSopenharmony_ci * plus the table name */ 248d4afb5ceSopenharmony_ci uint8_t *stb = (uint8_t *)st; 249d4afb5ceSopenharmony_ci const char *p; 250d4afb5ceSopenharmony_ci char *sql; 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_ci /* 253d4afb5ceSopenharmony_ci * Figure out effective number of columns, exluding BLOB. 254d4afb5ceSopenharmony_ci * 255d4afb5ceSopenharmony_ci * The first UNSIGNED is a hidden index. Blobs are not handled by 256d4afb5ceSopenharmony_ci * lws_struct except to create the column in the schema. 257d4afb5ceSopenharmony_ci */ 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci pk = 0; 260d4afb5ceSopenharmony_ci nef = 0; 261d4afb5ceSopenharmony_ci for (n = 0; n < nentries; n++) { 262d4afb5ceSopenharmony_ci if (!pk && map[n].type == LSMT_UNSIGNED) { 263d4afb5ceSopenharmony_ci pk = 1; 264d4afb5ceSopenharmony_ci continue; 265d4afb5ceSopenharmony_ci } 266d4afb5ceSopenharmony_ci if (map[n].type == LSMT_BLOB_PTR) 267d4afb5ceSopenharmony_ci continue; 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ci nef++; 270d4afb5ceSopenharmony_ci } 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci /* 273d4afb5ceSopenharmony_ci * Figure out an estimate for the length of the populated sqlite 274d4afb5ceSopenharmony_ci * command, and then malloc it up 275d4afb5ceSopenharmony_ci */ 276d4afb5ceSopenharmony_ci 277d4afb5ceSopenharmony_ci for (n = 0; n < nentries; n++) { 278d4afb5ceSopenharmony_ci sql_est += strlen(map[n].colname) + 2; 279d4afb5ceSopenharmony_ci switch (map[n].type) { 280d4afb5ceSopenharmony_ci case LSMT_SIGNED: 281d4afb5ceSopenharmony_ci case LSMT_UNSIGNED: 282d4afb5ceSopenharmony_ci case LSMT_BOOLEAN: 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci switch (map[n].aux) { 285d4afb5ceSopenharmony_ci case 1: 286d4afb5ceSopenharmony_ci sql_est += 3 + 2; 287d4afb5ceSopenharmony_ci break; 288d4afb5ceSopenharmony_ci case 2: 289d4afb5ceSopenharmony_ci sql_est += 5 + 2; 290d4afb5ceSopenharmony_ci break; 291d4afb5ceSopenharmony_ci case 4: 292d4afb5ceSopenharmony_ci sql_est += 10 + 2; 293d4afb5ceSopenharmony_ci break; 294d4afb5ceSopenharmony_ci case 8: 295d4afb5ceSopenharmony_ci sql_est += 20 + 2; 296d4afb5ceSopenharmony_ci break; 297d4afb5ceSopenharmony_ci } 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_ci if (map[n].type == LSMT_SIGNED) 300d4afb5ceSopenharmony_ci sql_est++; /* minus sign */ 301d4afb5ceSopenharmony_ci 302d4afb5ceSopenharmony_ci break; 303d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 304d4afb5ceSopenharmony_ci sql_est += (unsigned int)lws_sql_purify_len((const char *)st + 305d4afb5ceSopenharmony_ci map[n].ofs) + 2; 306d4afb5ceSopenharmony_ci break; 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 309d4afb5ceSopenharmony_ci p = *((const char * const *)&stb[map[n].ofs]); 310d4afb5ceSopenharmony_ci sql_est += (unsigned int)((p ? lws_sql_purify_len(p) : 0) + 2); 311d4afb5ceSopenharmony_ci break; 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ci case LSMT_BLOB_PTR: 314d4afb5ceSopenharmony_ci /* we don't deal with blobs actually */ 315d4afb5ceSopenharmony_ci sql_est -= strlen(map[n].colname) + 2; 316d4afb5ceSopenharmony_ci break; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci default: 319d4afb5ceSopenharmony_ci lwsl_err("%s: unsupported type\n", __func__); 320d4afb5ceSopenharmony_ci assert(0); 321d4afb5ceSopenharmony_ci break; 322d4afb5ceSopenharmony_ci } 323d4afb5ceSopenharmony_ci } 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci sql = malloc(sql_est); 326d4afb5ceSopenharmony_ci if (!sql) 327d4afb5ceSopenharmony_ci return -1; 328d4afb5ceSopenharmony_ci 329d4afb5ceSopenharmony_ci m = lws_snprintf(sql, sql_est, "insert into %s(_lws_idx, ", 330d4afb5ceSopenharmony_ci schema->colname); 331d4afb5ceSopenharmony_ci 332d4afb5ceSopenharmony_ci /* 333d4afb5ceSopenharmony_ci * First explicit integer type is primary key autoincrement, should 334d4afb5ceSopenharmony_ci * not be specified 335d4afb5ceSopenharmony_ci */ 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci pk = 0; 338d4afb5ceSopenharmony_ci did = 0; 339d4afb5ceSopenharmony_ci for (n = 0; n < nentries; n++) { 340d4afb5ceSopenharmony_ci if (!pk && map[n].type == LSMT_UNSIGNED) { 341d4afb5ceSopenharmony_ci pk = 1; 342d4afb5ceSopenharmony_ci continue; 343d4afb5ceSopenharmony_ci } 344d4afb5ceSopenharmony_ci if (map[n].type == LSMT_BLOB_PTR) 345d4afb5ceSopenharmony_ci continue; 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci did++; 348d4afb5ceSopenharmony_ci m += lws_snprintf(sql + m, sql_est - (unsigned int)m, 349d4afb5ceSopenharmony_ci did == nef ? "%s" : "%s, ", 350d4afb5ceSopenharmony_ci map[n].colname); 351d4afb5ceSopenharmony_ci } 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci m += lws_snprintf(sql + m, sql_est - (unsigned int)m, ") values(%u, ", idx); 354d4afb5ceSopenharmony_ci 355d4afb5ceSopenharmony_ci pk = 0; 356d4afb5ceSopenharmony_ci did = 0; 357d4afb5ceSopenharmony_ci for (n = 0; n < nentries; n++) { 358d4afb5ceSopenharmony_ci uint64_t uu64; 359d4afb5ceSopenharmony_ci size_t q; 360d4afb5ceSopenharmony_ci 361d4afb5ceSopenharmony_ci if (!pk && map[n].type == LSMT_UNSIGNED) { 362d4afb5ceSopenharmony_ci pk = 1; 363d4afb5ceSopenharmony_ci continue; 364d4afb5ceSopenharmony_ci } 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci switch (map[n].type) { 367d4afb5ceSopenharmony_ci case LSMT_SIGNED: 368d4afb5ceSopenharmony_ci case LSMT_UNSIGNED: 369d4afb5ceSopenharmony_ci case LSMT_BOOLEAN: 370d4afb5ceSopenharmony_ci 371d4afb5ceSopenharmony_ci uu64 = 0; 372d4afb5ceSopenharmony_ci for (q = 0; q < map[n].aux; q++) 373d4afb5ceSopenharmony_ci uu64 |= ((uint64_t)stb[map[n].ofs + q] << 374d4afb5ceSopenharmony_ci (q << 3)); 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci if (map[n].type == LSMT_SIGNED) 377d4afb5ceSopenharmony_ci m += lws_snprintf(sql + m, sql_est - (unsigned int)m, "%lld", 378d4afb5ceSopenharmony_ci (long long)(int64_t)uu64); 379d4afb5ceSopenharmony_ci else 380d4afb5ceSopenharmony_ci m += lws_snprintf(sql + m, sql_est - (unsigned int)m, "%llu", 381d4afb5ceSopenharmony_ci (unsigned long long)uu64); 382d4afb5ceSopenharmony_ci break; 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 385d4afb5ceSopenharmony_ci sql[m++] = '\''; 386d4afb5ceSopenharmony_ci lws_sql_purify(sql + m, (const char *)&stb[map[n].ofs], 387d4afb5ceSopenharmony_ci sql_est - (size_t)(ssize_t)m - 4); 388d4afb5ceSopenharmony_ci m += (int)(ssize_t)strlen(sql + m); 389d4afb5ceSopenharmony_ci sql[m++] = '\''; 390d4afb5ceSopenharmony_ci break; 391d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 392d4afb5ceSopenharmony_ci p = *((const char * const *)&stb[map[n].ofs]); 393d4afb5ceSopenharmony_ci sql[m++] = '\''; 394d4afb5ceSopenharmony_ci if (p) { 395d4afb5ceSopenharmony_ci lws_sql_purify(sql + m, p, sql_est - (unsigned int)m - 4); 396d4afb5ceSopenharmony_ci m += (int)(ssize_t)strlen(sql + m); 397d4afb5ceSopenharmony_ci } 398d4afb5ceSopenharmony_ci sql[m++] = '\''; 399d4afb5ceSopenharmony_ci break; 400d4afb5ceSopenharmony_ci 401d4afb5ceSopenharmony_ci case LSMT_BLOB_PTR: 402d4afb5ceSopenharmony_ci continue; 403d4afb5ceSopenharmony_ci 404d4afb5ceSopenharmony_ci default: 405d4afb5ceSopenharmony_ci lwsl_err("%s: unsupported type\n", __func__); 406d4afb5ceSopenharmony_ci assert(0); 407d4afb5ceSopenharmony_ci break; 408d4afb5ceSopenharmony_ci } 409d4afb5ceSopenharmony_ci 410d4afb5ceSopenharmony_ci did++; 411d4afb5ceSopenharmony_ci if (did != nef) { 412d4afb5ceSopenharmony_ci if (sql_est - (unsigned int)m < 6) 413d4afb5ceSopenharmony_ci return -1; 414d4afb5ceSopenharmony_ci sql[m++] = ','; 415d4afb5ceSopenharmony_ci sql[m++] = ' '; 416d4afb5ceSopenharmony_ci } 417d4afb5ceSopenharmony_ci } 418d4afb5ceSopenharmony_ci 419d4afb5ceSopenharmony_ci lws_snprintf(sql + m, sql_est - (unsigned int)m, ");"); 420d4afb5ceSopenharmony_ci 421d4afb5ceSopenharmony_ci n = sqlite3_exec(pdb, sql, NULL, NULL, NULL); 422d4afb5ceSopenharmony_ci if (n != SQLITE_OK) { 423d4afb5ceSopenharmony_ci lwsl_err("%s\n", sql); 424d4afb5ceSopenharmony_ci free(sql); 425d4afb5ceSopenharmony_ci lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); 426d4afb5ceSopenharmony_ci return -1; 427d4afb5ceSopenharmony_ci } 428d4afb5ceSopenharmony_ci free(sql); 429d4afb5ceSopenharmony_ci 430d4afb5ceSopenharmony_ci return 0; 431d4afb5ceSopenharmony_ci} 432d4afb5ceSopenharmony_ci 433d4afb5ceSopenharmony_ciint 434d4afb5ceSopenharmony_cilws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema, 435d4afb5ceSopenharmony_ci lws_dll2_owner_t *owner, uint32_t manual_idx) 436d4afb5ceSopenharmony_ci{ 437d4afb5ceSopenharmony_ci uint32_t idx = manual_idx; 438d4afb5ceSopenharmony_ci 439d4afb5ceSopenharmony_ci lws_start_foreach_dll(struct lws_dll2 *, p, owner->head) { 440d4afb5ceSopenharmony_ci void *item = (void *)((uint8_t *)p - schema->ofs_clist); 441d4afb5ceSopenharmony_ci if (_lws_struct_sq3_ser_one(pdb, schema, idx++, item)) 442d4afb5ceSopenharmony_ci return 1; 443d4afb5ceSopenharmony_ci 444d4afb5ceSopenharmony_ci } lws_end_foreach_dll(p); 445d4afb5ceSopenharmony_ci 446d4afb5ceSopenharmony_ci return 0; 447d4afb5ceSopenharmony_ci} 448d4afb5ceSopenharmony_ci 449d4afb5ceSopenharmony_ciint 450d4afb5ceSopenharmony_cilws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema) 451d4afb5ceSopenharmony_ci{ 452d4afb5ceSopenharmony_ci const lws_struct_map_t *map = schema->child_map; 453d4afb5ceSopenharmony_ci int map_size = (int)(ssize_t)schema->child_map_size, subsequent = 0; 454d4afb5ceSopenharmony_ci char s[2048], *p = s, *end = &s[sizeof(s) - 1], 455d4afb5ceSopenharmony_ci *pri = " primary key autoincrement", *use; 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ci p += lws_snprintf(p, (unsigned int)lws_ptr_diff(end, p), 458d4afb5ceSopenharmony_ci "create table if not exists %s (_lws_idx integer, ", 459d4afb5ceSopenharmony_ci schema->colname); 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci while (map_size--) { 462d4afb5ceSopenharmony_ci if (map->type > LSMT_STRING_PTR && map->type != LSMT_BLOB_PTR) { 463d4afb5ceSopenharmony_ci map++; 464d4afb5ceSopenharmony_ci continue; 465d4afb5ceSopenharmony_ci } 466d4afb5ceSopenharmony_ci if (subsequent && (end - p) > 4) { 467d4afb5ceSopenharmony_ci *p++ = ','; 468d4afb5ceSopenharmony_ci *p++ = ' '; 469d4afb5ceSopenharmony_ci } 470d4afb5ceSopenharmony_ci subsequent = 1; 471d4afb5ceSopenharmony_ci if (map->type == LSMT_BLOB_PTR) { 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci p += lws_snprintf(p, (unsigned int)lws_ptr_diff(end, p), "%s blob", map->colname); 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci } else { 476d4afb5ceSopenharmony_ci if (map->type < LSMT_STRING_CHAR_ARRAY) { 477d4afb5ceSopenharmony_ci use = ""; 478d4afb5ceSopenharmony_ci if (map->colname[0] != '_') /* _lws_idx is not primary key */ 479d4afb5ceSopenharmony_ci use = pri; 480d4afb5ceSopenharmony_ci p += lws_snprintf(p, (unsigned int)lws_ptr_diff(end, p), "%s integer%s", 481d4afb5ceSopenharmony_ci map->colname, use); 482d4afb5ceSopenharmony_ci if (map->colname[0] != '_') 483d4afb5ceSopenharmony_ci pri = ""; 484d4afb5ceSopenharmony_ci } else 485d4afb5ceSopenharmony_ci p += lws_snprintf(p, (unsigned int)lws_ptr_diff(end, p), "%s varchar", 486d4afb5ceSopenharmony_ci map->colname); 487d4afb5ceSopenharmony_ci } 488d4afb5ceSopenharmony_ci 489d4afb5ceSopenharmony_ci map++; 490d4afb5ceSopenharmony_ci } 491d4afb5ceSopenharmony_ci 492d4afb5ceSopenharmony_ci p += lws_snprintf(p, (unsigned int)lws_ptr_diff(end, p), ");"); 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_ci if (sqlite3_exec(pdb, s, NULL, NULL, NULL) != SQLITE_OK) { 495d4afb5ceSopenharmony_ci lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb)); 496d4afb5ceSopenharmony_ci 497d4afb5ceSopenharmony_ci return -1; 498d4afb5ceSopenharmony_ci } 499d4afb5ceSopenharmony_ci 500d4afb5ceSopenharmony_ci return 0; 501d4afb5ceSopenharmony_ci} 502d4afb5ceSopenharmony_ci 503d4afb5ceSopenharmony_ciint 504d4afb5ceSopenharmony_cilws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path, 505d4afb5ceSopenharmony_ci char create_if_missing, sqlite3 **pdb) 506d4afb5ceSopenharmony_ci{ 507d4afb5ceSopenharmony_ci#if !defined(WIN32) 508d4afb5ceSopenharmony_ci uid_t uid = 0; 509d4afb5ceSopenharmony_ci gid_t gid = 0; 510d4afb5ceSopenharmony_ci#endif 511d4afb5ceSopenharmony_ci 512d4afb5ceSopenharmony_ci if (sqlite3_open_v2(sqlite3_path, pdb, 513d4afb5ceSopenharmony_ci SQLITE_OPEN_READWRITE | 514d4afb5ceSopenharmony_ci (create_if_missing ? SQLITE_OPEN_CREATE : 0), 515d4afb5ceSopenharmony_ci NULL) != SQLITE_OK) { 516d4afb5ceSopenharmony_ci lwsl_info("%s: Unable to open db %s: %s\n", 517d4afb5ceSopenharmony_ci __func__, sqlite3_path, sqlite3_errmsg(*pdb)); 518d4afb5ceSopenharmony_ci 519d4afb5ceSopenharmony_ci return 1; 520d4afb5ceSopenharmony_ci } 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci#if !defined(WIN32) 523d4afb5ceSopenharmony_ci lws_get_effective_uid_gid(context, &uid, &gid); 524d4afb5ceSopenharmony_ci if (uid) 525d4afb5ceSopenharmony_ci if (chown(sqlite3_path, uid, gid)) 526d4afb5ceSopenharmony_ci lwsl_err("%s: failed to chown %s\n", __func__, sqlite3_path); 527d4afb5ceSopenharmony_ci chmod(sqlite3_path, 0600); 528d4afb5ceSopenharmony_ci 529d4afb5ceSopenharmony_ci lwsl_debug("%s: created %s owned by %u:%u mode 0600\n", __func__, 530d4afb5ceSopenharmony_ci sqlite3_path, (unsigned int)uid, (unsigned int)gid); 531d4afb5ceSopenharmony_ci#else 532d4afb5ceSopenharmony_ci lwsl_debug("%s: created %s\n", __func__, sqlite3_path); 533d4afb5ceSopenharmony_ci#endif 534d4afb5ceSopenharmony_ci sqlite3_extended_result_codes(*pdb, 1); 535d4afb5ceSopenharmony_ci 536d4afb5ceSopenharmony_ci return 0; 537d4afb5ceSopenharmony_ci} 538d4afb5ceSopenharmony_ci 539d4afb5ceSopenharmony_ciint 540d4afb5ceSopenharmony_cilws_struct_sq3_close(sqlite3 **pdb) 541d4afb5ceSopenharmony_ci{ 542d4afb5ceSopenharmony_ci int n; 543d4afb5ceSopenharmony_ci 544d4afb5ceSopenharmony_ci if (!*pdb) 545d4afb5ceSopenharmony_ci return 0; 546d4afb5ceSopenharmony_ci 547d4afb5ceSopenharmony_ci n = sqlite3_close(*pdb); 548d4afb5ceSopenharmony_ci if (n != SQLITE_OK) { 549d4afb5ceSopenharmony_ci /* 550d4afb5ceSopenharmony_ci * trouble... 551d4afb5ceSopenharmony_ci */ 552d4afb5ceSopenharmony_ci lwsl_err("%s: failed to close: %d\n", __func__, n); 553d4afb5ceSopenharmony_ci return 1; 554d4afb5ceSopenharmony_ci } 555d4afb5ceSopenharmony_ci *pdb = NULL; 556d4afb5ceSopenharmony_ci 557d4afb5ceSopenharmony_ci return 0; 558d4afb5ceSopenharmony_ci} 559