SQLite

Check-in [b64681a644]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improve the shell tool ".ar --list --verbose" command.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sqlar-shell-support
Files: files | file ages | folders
SHA3-256: b64681a644c419bb98d00980a6cb56ef5a0aff5ef5321955631f0b4c88aac283
User & Date: dan 2017-12-27 21:13:21.423
Context
2017-12-29
20:19
Update ext/misc/zipfile.c to support creating and adding entries to existing zip archives. (check-in: 2dec2dec59 user: dan tags: sqlar-shell-support)
2017-12-27
21:13
Improve the shell tool ".ar --list --verbose" command. (check-in: b64681a644 user: dan tags: sqlar-shell-support)
18:54
Have the shell tool ".ar --list" and ".ar --extract" commands support zip files. Currently the "-zip" switch is required. (check-in: a532a0f6fd user: dan tags: sqlar-shell-support)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/zipfile.c.
46
47
48
49
50
51
52



53
54
55
56
57
58
59
  "f HIDDEN   /* Name of zip file */"                              \
");"

#define ZIPFILE_F_COLUMN_IDX 6    /* Index of column "f" in the above */

#define ZIPFILE_BUFFER_SIZE (64*1024)




/*
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/
static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
  char *zMsg = 0;
  va_list ap;







>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  "f HIDDEN   /* Name of zip file */"                              \
");"

#define ZIPFILE_F_COLUMN_IDX 6    /* Index of column "f" in the above */

#define ZIPFILE_BUFFER_SIZE (64*1024)


#define ZIPFILE_EXTRA_TIMESTAMP 0x5455

/*
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/
static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
  char *zMsg = 0;
  va_list ap;
337
338
339
340
341
342
343
344







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
        pCsr->cds.zFile = sqlite3_mprintf("%.*s", (int)pCsr->cds.nFile, aRead);
        pCsr->iNextOff += szFix;
        pCsr->iNextOff += pCsr->cds.nFile;
        pCsr->iNextOff += pCsr->cds.nExtra;
        pCsr->iNextOff += pCsr->cds.nComment;
      }

      /* Scan the "extra" fields */







      if( rc==SQLITE_OK ){
        u8 *p = &aRead[pCsr->cds.nFile];
        u8 *pEnd = &p[pCsr->cds.nExtra];

        while( p<pEnd ){
          u16 id = zipfileRead16(p);
          u16 nByte = zipfileRead16(p);

          switch( id ){
            case 0x5455: {        /* Extended timestamp */
              u8 b = p[0];
              if( b & 0x01 ){     /* 0x01 -> modtime is present */
                pCsr->mTime = zipfileGetU32(&p[1]);
                pCsr->flags |= ZIPFILE_MTIME_VALID;
              }
              break;
            }

            case 0x7875:          /* Info-ZIP Unix (new) */
              break;
          }

          p += nByte;
        }
      }
    }
  }







|
>
>
>
>
>
>
>









|







<
<
<







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371



372
373
374
375
376
377
378
        pCsr->cds.zFile = sqlite3_mprintf("%.*s", (int)pCsr->cds.nFile, aRead);
        pCsr->iNextOff += szFix;
        pCsr->iNextOff += pCsr->cds.nFile;
        pCsr->iNextOff += pCsr->cds.nExtra;
        pCsr->iNextOff += pCsr->cds.nComment;
      }

      /* Scan the cds.nExtra bytes of "extra" fields for any that can
      ** be interpreted. The general format of an extra field is:
      **
      **   Header ID    2 bytes
      **   Data Size    2 bytes
      **   Data         N bytes
      **
      */
      if( rc==SQLITE_OK ){
        u8 *p = &aRead[pCsr->cds.nFile];
        u8 *pEnd = &p[pCsr->cds.nExtra];

        while( p<pEnd ){
          u16 id = zipfileRead16(p);
          u16 nByte = zipfileRead16(p);

          switch( id ){
            case ZIPFILE_EXTRA_TIMESTAMP: {
              u8 b = p[0];
              if( b & 0x01 ){     /* 0x01 -> modtime is present */
                pCsr->mTime = zipfileGetU32(&p[1]);
                pCsr->flags |= ZIPFILE_MTIME_VALID;
              }
              break;
            }



          }

          p += nByte;
        }
      }
    }
  }
Changes to src/shell.c.in.
4572
4573
4574
4575
4576
4577
4578



























4579
4580
4581
4582
4583
4584
4585




4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598










4599

4600
4601
4602
4603
4604
4605
4606
        }
        zSep = " OR ";
      }
    }
  }
  *pzWhere = zWhere;
}




























/*
** Implementation of .ar "lisT" command. 
*/
static int arListCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
  const char *zSql = "SELECT name FROM %s WHERE %s"; 
  const char *zTbl = (pAr->bZip ? "zipfile(?)" : "sqlar");





  char *zWhere = 0;
  sqlite3_stmt *pSql = 0;
  int rc;

  rc = arCheckEntries(db, pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(db, &rc, &pSql, zSql, zTbl, zWhere);
  if( rc==SQLITE_OK && pAr->bZip ){
    sqlite3_bind_text(pSql, 1, pAr->zFile, -1, SQLITE_TRANSIENT);
  }
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){










    raw_printf(p->out, "%s\n", sqlite3_column_text(pSql, 0));

  }

  shellFinalize(&rc, pSql);
  return rc;
}









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|

>
>
>
>








|




>
>
>
>
>
>
>
>
>
>
|
>







4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
        }
        zSep = " OR ";
      }
    }
  }
  *pzWhere = zWhere;
}

/*
** Argument zMode must point to a buffer at least 11 bytes in size. This
** function populates this buffer with the string interpretation of
** the unix file mode passed as the second argument (e.g. "drwxr-xr-x").
*/
static void shellModeToString(char *zMode, int mode){
  int i;

  /* Magic numbers copied from [man 2 stat] */
  if( mode & 0040000 ){
    zMode[0] = 'd';
  }else if( (mode & 0120000)==0120000 ){
    zMode[0] = 'l';
  }else{
    zMode[0] = '-';
  }

  for(i=0; i<3; i++){
    int m = (mode >> ((2-i)*3));
    char *a = &zMode[1 + i*3];
    a[0] = (m & 0x4) ? 'r' : '-';
    a[1] = (m & 0x2) ? 'w' : '-';
    a[2] = (m & 0x1) ? 'x' : '-';
  }
  zMode[10] = '\0';
}

/*
** Implementation of .ar "lisT" command. 
*/
static int arListCommand(ShellState *p, sqlite3 *db, ArCommand *pAr){
  const char *zSql = "SELECT %s FROM %s WHERE %s"; 
  const char *zTbl = (pAr->bZip ? "zipfile(?)" : "sqlar");
  const char *azCols[] = {
    "name",
    "mode, sz, datetime(mtime, 'unixepoch'), name"
  };

  char *zWhere = 0;
  sqlite3_stmt *pSql = 0;
  int rc;

  rc = arCheckEntries(db, pAr);
  arWhereClause(&rc, pAr, &zWhere);

  shellPreparePrintf(db, &rc, &pSql, zSql, azCols[pAr->bVerbose], zTbl, zWhere);
  if( rc==SQLITE_OK && pAr->bZip ){
    sqlite3_bind_text(pSql, 1, pAr->zFile, -1, SQLITE_TRANSIENT);
  }
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
    if( pAr->bVerbose ){
      char zMode[11];
      shellModeToString(zMode, sqlite3_column_int(pSql, 0));

      raw_printf(p->out, "%s % 10d  %s  %s\n", zMode,
          sqlite3_column_int(pSql, 1), 
          sqlite3_column_text(pSql, 2),
          sqlite3_column_text(pSql, 3)
      );
    }else{
      raw_printf(p->out, "%s\n", sqlite3_column_text(pSql, 0));
    }
  }

  shellFinalize(&rc, pSql);
  return rc;
}