Browse Source

add --newid command-line option

David Mazieres 5 years ago
parent
commit
1b36c60570
5 changed files with 61 additions and 11 deletions
  1. 2
    0
      NEWS
  2. 9
    0
      muchsync.1.md
  3. 34
    5
      muchsync.cc
  4. 13
    6
      sql_db.cc
  5. 3
    0
      sql_db.h

+ 2
- 0
NEWS View File

@@ -2,6 +2,8 @@
2 2
 
3 3
 Added help command to --server mode.
4 4
 
5
+Added --newid command-line option.
6
+
5 7
 * Changes in release 2
6 8
 
7 9
 Work around missing openat because of reports it is missing on some

+ 9
- 0
muchsync.1.md View File

@@ -197,6 +197,15 @@ privacy reasons, you will need to run the following on each replica:
197 197
     is running, particularly if network file systems allow a replica
198 198
     to be accessed from multiple machines.
199 199
 
200
+\--newid
201
+:   Muchsync requires every replica to have a unique 64-bit identifier.
202
+    If you ever copy a notmuch database to another machine, including
203
+    the muchsync state, bad things will happen if both copies use
204
+    muchsync, as they will both have the same identifier.  Hence,
205
+    after making such copy and before running muchsync to synchronize
206
+    mail, run `muchsync --newid` to change the identifier of one of
207
+    the copies.
208
+
200 209
 \--version
201 210
 :   Report on the muchsync version number
202 211
 

+ 34
- 5
muchsync.cc View File

@@ -40,6 +40,8 @@ bool opt_server;
40 40
 bool opt_upbg;
41 41
 bool opt_noup;
42 42
 bool opt_nonew;
43
+bool opt_newid;
44
+i64 opt_newid_value;
43 45
 int opt_verbose;
44 46
 int opt_upbg_fd = -1;
45 47
 string opt_ssh = "ssh -CTaxq";
@@ -124,13 +126,14 @@ Additional options:\n\
124 126
    --noup[load]  Do not upload changes to server\n\
125 127
    --upbg        Download mail in forground, then upload in background\n\
126 128
    --self        Print local replica identifier and exit\n\
129
+   --newid       Change local replica identifier and exit\n\
127 130
    --version     Print version number and exit\n\
128 131
    --help        Print usage\n";
129 132
   exit (code);
130 133
 }
131 134
 
132 135
 static void
133
-print_self()
136
+id_request()
134 137
 {
135 138
   unique_ptr<notmuch_db> nmp;
136 139
   try {
@@ -140,11 +143,21 @@ print_self()
140 143
 
141 144
   string dbpath = nm.maildir + muchsync_dbpath;
142 145
 
143
-  sqlite3 *db = dbopen(dbpath.c_str(), false);
146
+  sqlite3 *db = dbopen(dbpath.c_str(), opt_newid);
144 147
   if (!db)
145 148
     exit(1);
146 149
   cleanup _c (sqlite3_close_v2, db);
147
-  cout << getconfig<i64>(db, "self") << '\n';
150
+  if (!opt_newid)
151
+    cout << getconfig<i64>(db, "self") << '\n';
152
+  else {
153
+    i64 oldid = getconfig<i64>(db, "self");
154
+    if (opt_newid_value <= 0)
155
+      opt_newid_value = create_random_id ();
156
+    if (opt_newid_value <= 0)
157
+      exit(1);
158
+    cout << "changing id from " << oldid << " to " << opt_newid_value << '\n';
159
+    setconfig (db, "self", opt_newid_value);
160
+  }
148 161
 }
149 162
 
150 163
 static void
@@ -355,6 +368,7 @@ enum opttag {
355 368
   OPT_HELP,
356 369
   OPT_NONEW,
357 370
   OPT_SELF,
371
+  OPT_NEWID,
358 372
   OPT_INIT
359 373
 };
360 374
 
@@ -368,6 +382,7 @@ static const struct option muchsync_options[] = {
368 382
   { "nonew", no_argument, nullptr, OPT_NONEW },
369 383
   { "init", required_argument, nullptr, OPT_INIT },
370 384
   { "self", no_argument, nullptr, OPT_SELF },
385
+  { "newid", optional_argument, nullptr, OPT_NEWID },
371 386
   { "config", required_argument, nullptr, 'C' },
372 387
   { "help", no_argument, nullptr, OPT_HELP },
373 388
   { nullptr, 0, nullptr, 0 }
@@ -423,6 +438,9 @@ main(int argc, char **argv)
423 438
     case OPT_SELF:
424 439
       opt_self = true;
425 440
       break;
441
+    case OPT_NEWID:
442
+      opt_newid = true;
443
+      break;
426 444
     case OPT_INIT:
427 445
       opt_init = true;
428 446
       opt_init_dest = optarg;
@@ -433,8 +451,19 @@ main(int argc, char **argv)
433 451
       usage();
434 452
     }
435 453
 
436
-  if (opt_self)
437
-    print_self();
454
+  if (opt_self || opt_newid) {
455
+    if ((opt_self && opt_newid) || optind != argc
456
+	|| opt_init || opt_noup || opt_upbg)
457
+      usage();
458
+    if (opt_newid && optarg) {
459
+      opt_newid_value = std::stoll(optarg, nullptr, 10);
460
+      if (opt_newid_value <= 0) {
461
+	cerr << "invalid id\n";
462
+	exit (1);
463
+      }
464
+    }
465
+    id_request();
466
+  }
438 467
   else if (opt_server) {
439 468
     if (opt_init || opt_noup || opt_upbg || optind != argc)
440 469
       usage();

+ 13
- 6
sql_db.cc View File

@@ -65,16 +65,23 @@ CREATE TABLE xapian_nlinks (
65 65
   PRIMARY KEY (hash_id, dir_docid));
66 66
 )";
67 67
 
68
+i64
69
+create_random_id()
70
+{
71
+  i64 id = 0;
72
+  if (RAND_pseudo_bytes ((unsigned char *) &id, sizeof (id)) == -1 || id == 0) {
73
+    cerr << "RAND_pseudo_bytes failed\n";
74
+    return -1;
75
+  }
76
+  id &= ~(i64 (1) << 63);
77
+}
78
+
68 79
 static sqlite3 *
69 80
 dbcreate (const char *path)
70 81
 {
71
-  i64 self = 0;
72
-  if (RAND_pseudo_bytes ((unsigned char *) &self, sizeof (self)) == -1
73
-      || self == 0) {
74
-    cerr << "RAND_pseudo_bytes failed\n";
82
+  i64 self = create_random_id();
83
+  if (self <= 0)
75 84
     return nullptr;
76
-  }
77
-  self &= ~(i64 (1) << 63);
78 85
 
79 86
   sqlite3 *db = nullptr;
80 87
   int err = sqlite3_open_v2 (path, &db,

+ 3
- 0
sql_db.h View File

@@ -139,4 +139,7 @@ string trashname (const string &maildir, const string &hash);
139 139
 
140 140
 string permissive_percent_encode (const string &raw);
141 141
 
142
+i64 create_random_id ();
143
+
144
+
142 145
 #endif /* !_SQL_DB_H */

Loading…
Cancel
Save