getlock.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. ** This utility program looks at an SQLite database and determines whether
  3. ** or not it is locked, the kind of lock, and who is holding this lock.
  4. **
  5. ** This only works on unix when the posix advisory locking method is used
  6. ** (which is the default on unix) and when the PENDING_BYTE is in its
  7. ** usual place.
  8. */
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <errno.h>
  17. static void usage(const char *argv0){
  18. fprintf(stderr, "Usage: %s database\n", argv0);
  19. exit(1);
  20. }
  21. /* Check for a conflicting lock. If one is found, print an this
  22. ** on standard output using the format string given and return 1.
  23. ** If there are no conflicting locks, return 0.
  24. */
  25. static int isLocked(
  26. int h, /* File descriptor to check */
  27. int type, /* F_RDLCK or F_WRLCK */
  28. unsigned int iOfst, /* First byte of the lock */
  29. unsigned int iCnt, /* Number of bytes in the lock range */
  30. const char *zType /* Type of lock */
  31. ){
  32. struct flock lk;
  33. memset(&lk, 0, sizeof(lk));
  34. lk.l_type = type;
  35. lk.l_whence = SEEK_SET;
  36. lk.l_start = iOfst;
  37. lk.l_len = iCnt;
  38. if( fcntl(h, F_GETLK, &lk)==(-1) ){
  39. fprintf(stderr, "fcntl(%d) failed: errno=%d\n", h, errno);
  40. exit(1);
  41. }
  42. if( lk.l_type==F_UNLCK ) return 0;
  43. printf("%s lock held by %d\n", zType, (int)lk.l_pid);
  44. return 1;
  45. }
  46. /*
  47. ** Location of locking bytes in the database file
  48. */
  49. #define PENDING_BYTE (0x40000000)
  50. #define RESERVED_BYTE (PENDING_BYTE+1)
  51. #define SHARED_FIRST (PENDING_BYTE+2)
  52. #define SHARED_SIZE 510
  53. /*
  54. ** Lock locations for shared-memory locks used by WAL mode.
  55. */
  56. #define SHM_BASE 120
  57. #define SHM_WRITE SHM_BASE
  58. #define SHM_CHECKPOINT (SHM_BASE+1)
  59. #define SHM_RECOVER (SHM_BASE+2)
  60. #define SHM_READ_FIRST (SHM_BASE+3)
  61. #define SHM_READ_SIZE 5
  62. int main(int argc, char **argv){
  63. int hDb; /* File descriptor for the open database file */
  64. int hShm; /* File descriptor for WAL shared-memory file */
  65. char *zShm; /* Name of the shared-memory file for WAL mode */
  66. ssize_t got; /* Bytes read from header */
  67. int isWal; /* True if in WAL mode */
  68. int nName; /* Length of filename */
  69. unsigned char aHdr[100]; /* Database header */
  70. int nLock = 0; /* Number of locks held */
  71. int i; /* Loop counter */
  72. if( argc!=2 ) usage(argv[0]);
  73. hDb = open(argv[1], O_RDONLY, 0);
  74. if( hDb<0 ){
  75. fprintf(stderr, "cannot open %s\n", argv[1]);
  76. return 1;
  77. }
  78. /* Make sure we are dealing with an database file */
  79. got = read(hDb, aHdr, 100);
  80. if( got!=100 || memcmp(aHdr, "SQLite format 3",16)!=0 ){
  81. fprintf(stderr, "not an SQLite database: %s\n", argv[1]);
  82. exit(1);
  83. }
  84. /* First check for an exclusive lock */
  85. if( isLocked(hDb, F_RDLCK, SHARED_FIRST, SHARED_SIZE, "EXCLUSIVE") ){
  86. return 0;
  87. }
  88. isWal = aHdr[18]==2;
  89. if( isWal==0 ){
  90. /* Rollback mode */
  91. if( isLocked(hDb, F_RDLCK, PENDING_BYTE, 1, "PENDING") ) return 0;
  92. if( isLocked(hDb, F_RDLCK, RESERVED_BYTE, 1, "RESERVED") ) return 0;
  93. if( isLocked(hDb, F_WRLCK, SHARED_FIRST, SHARED_SIZE, "SHARED") ){
  94. return 0;
  95. }
  96. }else{
  97. /* WAL mode */
  98. nName = (int)strlen(argv[1]);
  99. zShm = malloc( nName + 100 );
  100. if( zShm==0 ){
  101. fprintf(stderr, "out of memory\n");
  102. exit(1);
  103. }
  104. memcpy(zShm, argv[1], nName);
  105. memcpy(&zShm[nName], "-shm", 5);
  106. hShm = open(zShm, O_RDONLY, 0);
  107. if( hShm<0 ){
  108. fprintf(stderr, "cannot open %s\n", zShm);
  109. return 1;
  110. }
  111. if( isLocked(hShm, F_RDLCK, SHM_RECOVER, 1, "WAL-RECOVERY") ){
  112. return 0;
  113. }
  114. nLock += isLocked(hShm, F_RDLCK, SHM_CHECKPOINT, 1, "WAL-CHECKPOINT");
  115. nLock += isLocked(hShm, F_RDLCK, SHM_WRITE, 1, "WAL-WRITE");
  116. for(i=0; i<SHM_READ_SIZE; i++){
  117. nLock += isLocked(hShm, F_WRLCK, SHM_READ_FIRST+i, 1, "WAL-READ");
  118. }
  119. }
  120. if( nLock==0 ){
  121. printf("file is not locked\n");
  122. }
  123. return 0;
  124. }