SQLite

Check-in [2bf8c3f99a]
Login

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

Overview
Comment:When extracting links from sqlar archives, clobber any existing file or link, and do not call utimes() to set the timestamp - it looks through the link and operates on the target.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2bf8c3f99ad8b74f707d17272fa12b674bec66082d3e8349ebef3dac42ba0782
User & Date: dan 2024-05-06 20:21:31.369
Context
2024-05-07
13:20
Fix a compilation error in test/lemon-test01.y, reported in forum post f0ad095705. (check-in: 576b68c8b5 user: stephan tags: trunk)
2024-05-06
20:21
When extracting links from sqlar archives, clobber any existing file or link, and do not call utimes() to set the timestamp - it looks through the link and operates on the target. (check-in: 2bf8c3f99a user: dan tags: trunk)
20:18
Omit redundant unary + operators from the AST. (check-in: f81cc149e5 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/fileio.c.
368
369
370
371
372
373
374


375
376
377
378
379
380
381
382
  mode_t mode,                    /* MODE parameter passed to writefile() */
  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
){
  if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
  if( S_ISLNK(mode) ){
    const char *zTo = (const char*)sqlite3_value_text(pData);


    if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
  }else
#endif
  {
    if( S_ISDIR(mode) ){
      if( mkdir(zFile, mode) ){
        /* The mkdir() call to create the directory failed. This might not
        ** be an error though - if there is already a directory at the same







>
>
|







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  mode_t mode,                    /* MODE parameter passed to writefile() */
  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
){
  if( zFile==0 ) return 1;
#if !defined(_WIN32) && !defined(WIN32)
  if( S_ISLNK(mode) ){
    const char *zTo = (const char*)sqlite3_value_text(pData);
    if( zTo==0 ) return 1;
    unlink(zFile);
    if( symlink(zTo, zFile)<0 ) return 1;
  }else
#endif
  {
    if( S_ISDIR(mode) ){
      if( mkdir(zFile, mode) ){
        /* The mkdir() call to create the directory failed. This might not
        ** be an error though - if there is already a directory at the same
454
455
456
457
458
459
460
461





462
463
464
465
466
467

468
469
470
471
472
473
474
    times[0].tv_nsec = times[1].tv_nsec = 0;
    times[0].tv_sec = time(0);
    times[1].tv_sec = mtime;
    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
      return 1;
    }
#else
    /* Legacy unix */





    struct timeval times[2];
    times[0].tv_usec = times[1].tv_usec = 0;
    times[0].tv_sec = time(0);
    times[1].tv_sec = mtime;
    if( utimes(zFile, times) ){
      return 1;

    }
#endif
  }

  return 0;
}








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







456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
    times[0].tv_nsec = times[1].tv_nsec = 0;
    times[0].tv_sec = time(0);
    times[1].tv_sec = mtime;
    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
      return 1;
    }
#else
    /* Legacy unix. 
    **
    ** Do not use utimes() on a symbolic link - it sees through the link and
    ** modifies the timestamps on the target. Or fails if the target does 
    ** not exist.  */
    if( 0==S_ISLNK(mode) ){
      struct timeval times[2];
      times[0].tv_usec = times[1].tv_usec = 0;
      times[0].tv_sec = time(0);
      times[1].tv_sec = mtime;
      if( utimes(zFile, times) ){
        return 1;
      }
    }
#endif
  }

  return 0;
}

Changes to test/shell8.test.
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

  # This is a repeat of test 1.$tn.1, except that there is a 2 second 
  # pause between creating the archive and extracting its contents.
  # This is to test that timestamps are set correctly.
  #
  # Because it is slow, only do this for $tn==1.
  if {$tn==1} {
    do_test 1.$tn.1 {
      catchcmd test_ar.db $c1
      file delete -force ar1
      after 2000
      catchcmd test_ar.db $x1
      dir_to_list ar1
    } $expected
  }







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

  # This is a repeat of test 1.$tn.1, except that there is a 2 second 
  # pause between creating the archive and extracting its contents.
  # This is to test that timestamps are set correctly.
  #
  # Because it is slow, only do this for $tn==1.
  if {$tn==1} {
    do_test 1.$tn.4 {
      catchcmd test_ar.db $c1
      file delete -force ar1
      after 2000
      catchcmd test_ar.db $x1
      dir_to_list ar1
    } $expected
  }
189
190
191
192
193
194
195
196

























197
  catchcmd shell8.db {.ar -c}
  catchcmd shell8.db {.ar -C ar2 -i .}
  catchcmd shell8.db {.ar -r ./file2 ./dir1}
  catchcmd shell8.db {.ar -g -r ./ju*2}
  catchcmd shell8.db {.ar -C ar4 -x .}
  regsub -all {ar4} [dir_content ar4] ar2
} {ar2/file1 ar2/file2 ar2/junk1}


























finish_test








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

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  catchcmd shell8.db {.ar -c}
  catchcmd shell8.db {.ar -C ar2 -i .}
  catchcmd shell8.db {.ar -r ./file2 ./dir1}
  catchcmd shell8.db {.ar -g -r ./ju*2}
  catchcmd shell8.db {.ar -C ar4 -x .}
  regsub -all {ar4} [dir_content ar4] ar2
} {ar2/file1 ar2/file2 ar2/junk1}

# Test symbolic links.
#
if {$tcl_platform(platform)=="unix"} {
  populate_dir ar2 {
    file1 "1234" 
    file2 "3456"
  }
  file link ar2/link1 file1

  forcedelete shell8.db
  forcedelete link1

  do_test 3.1 {
    catchcmd shell8.db {.ar -C ar2 -c file2 link1 }
  } {0 {}}

  do_test 3.2 {
    catchcmd shell8.db {.ar -x} 
  } {0 {}}

  do_test 3.3 {
    catchcmd shell8.db {.ar -x} 
  } {0 {}}
}

finish_test