1 |
|
2 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca> |
1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca> |
3 // |
2 // |
4 // This program is free software; you can redistribute it and/or modify |
3 // This program is free software; you can redistribute it and/or modify |
5 // it under the terms of the GNU General Public License as published by |
4 // it under the terms of the GNU General Public License as published by |
6 // the Free Software Foundation; either version 2 of the License, or |
5 // the Free Software Foundation; either version 2 of the License, or |
23 #include "misc/autodelete.h" |
22 #include "misc/autodelete.h" |
24 #include "fdbuf/fdbuf.h" |
23 #include "fdbuf/fdbuf.h" |
25 #include "mystring/mystring.h" |
24 #include "mystring/mystring.h" |
26 #include "misc/maildir.h" |
25 #include "misc/maildir.h" |
27 #include "config/configrc.h" |
26 #include "config/configrc.h" |
28 #include "vpwentry/vpwentry.h" |
|
29 #include "vcommand.h" |
27 #include "vcommand.h" |
30 #include "misc/stat_fns.h" |
28 #include "misc/stat_fns.h" |
31 #include "cli/cli.h" |
29 #include "cli++/cli++.h" |
32 #include "cdb++/cdb++.h" |
|
33 |
30 |
34 const char* cli_program = "vrehash"; |
31 const char* cli_program = "vrehash"; |
35 const char* cli_help_prefix = "Reorganize users directory\n" |
32 const char* cli_help_prefix = "Reorganize users directory\n" |
36 "Renames user directories in a virtual domain to match the current\n" |
33 "Renames user directories in a virtual domain to match the current\n" |
37 "partitioning scheme\n"; |
34 "partitioning scheme\n"; |
72 // an error occurs. |
69 // an error occurs. |
73 // If an error occurs, you will have to check the status of the current |
70 // If an error occurs, you will have to check the status of the current |
74 // directory, the virtual password file, and all the virtual users |
71 // directory, the virtual password file, and all the virtual users |
75 // subdirectories in both C<users> and C<new.users>. |
72 // subdirectories in both C<users> and C<new.users>. |
76 |
73 |
77 static cdb_reader* in = 0; |
74 static vpwtable_reader* in = 0; |
78 static cdb_writer* out = 0; |
75 static vpwtable_writer* out = 0; |
79 static mystring cdbfilename; |
|
80 static mystring tmpfilename; |
|
81 static mystring newuserdir; |
76 static mystring newuserdir; |
82 static mystring backupdir; |
77 static mystring backupdir; |
83 |
78 |
84 mystring lock_dir() |
79 mystring lock_dir() |
85 { |
80 { |
88 return "Error stat'ing the current directory ?!?"; |
83 return "Error stat'ing the current directory ?!?"; |
89 if(buf.st_mode & S_ISVTX) |
84 if(buf.st_mode & S_ISVTX) |
90 return "Directory is already locked"; |
85 return "Directory is already locked"; |
91 if(chmod(".", buf.st_mode | S_ISVTX)) |
86 if(chmod(".", buf.st_mode | S_ISVTX)) |
92 return "Can't lock directory"; |
87 return "Can't lock directory"; |
93 cdbfilename = password_file + ".cdb"; |
88 |
94 tmpfilename = cdbfilename + ".tmp"; |
89 vpwtable* table = domain.table(); |
95 in = new cdb_reader(cdbfilename); |
90 |
|
91 in = table->start_read(); |
96 if(!*in) |
92 if(!*in) |
97 return "Could not open virtual password table"; |
93 return "Could not open virtual password table"; |
98 out = new cdb_writer(tmpfilename, 0600); |
94 |
|
95 out = table->start_write(); |
99 if(!*out) |
96 if(!*out) |
100 return "Could not open temporary table exclusively"; |
97 return "Could not open virtual password table writer"; |
101 return ""; |
98 |
|
99 return 0; |
102 } |
100 } |
103 |
101 |
104 mystring unlock_dir() |
102 mystring unlock_dir() |
105 { |
103 { |
106 struct stat buf; |
104 struct stat buf; |
109 if(!(buf.st_mode & S_ISVTX)) |
107 if(!(buf.st_mode & S_ISVTX)) |
110 return "Directory was not locked"; |
108 return "Directory was not locked"; |
111 if(chmod(".", buf.st_mode & ~S_ISVTX)) |
109 if(chmod(".", buf.st_mode & ~S_ISVTX)) |
112 return "Can't unlock directory"; |
110 return "Can't unlock directory"; |
113 if(out) { |
111 if(out) { |
114 if(out->end(cdbfilename)) { |
112 if(out->end()) { |
115 delete out; |
113 delete out; |
116 return "Error completing the virtual password table"; |
114 return "Error completing the virtual password table"; |
117 } |
115 } |
118 delete out; |
116 delete out; |
119 } |
117 } |
120 delete in; |
118 delete in; |
121 return ""; |
119 return ""; |
122 } |
|
123 |
|
124 bool getvpwent(vpwentry& vpw) |
|
125 { |
|
126 autodelete<datum> d = in->nextrec(); |
|
127 if(!d) |
|
128 return false; |
|
129 vpw.from_record(d->key, d->data); |
|
130 return true; |
|
131 } |
120 } |
132 |
121 |
133 mystring user_dir; |
122 mystring user_dir; |
134 |
123 |
135 mystring translate_one(vpwentry& vpw) |
124 mystring translate_one(vpwentry& vpw) |
139 domain.userdir(vpw.name).right(user_dir.length()); |
128 domain.userdir(vpw.name).right(user_dir.length()); |
140 mystring vpwdir = "./" + domain.userdir(vpw.name); |
129 mystring vpwdir = "./" + domain.userdir(vpw.name); |
141 mystring tmpdir = newdir.left(newdir.find_last('/')); |
130 mystring tmpdir = newdir.left(newdir.find_last('/')); |
142 if(mkdirp(tmpdir.c_str(), 0755)) |
131 if(mkdirp(tmpdir.c_str(), 0755)) |
143 return "Error creating a user subdirectory: " + tmpdir; |
132 return "Error creating a user subdirectory: " + tmpdir; |
144 if(rename(vpw.mailbox.c_str(), newdir.c_str())) |
133 if(rename(vpw.directory.c_str(), newdir.c_str())) |
145 return "Error moving a user subdirectory." + vpw.mailbox; |
134 return "Error moving a user subdirectory." + vpw.directory; |
146 vpw.mailbox = vpwdir; |
135 vpw.directory = vpwdir; |
147 return ""; |
136 return ""; |
148 } |
137 } |
149 |
138 |
150 mystring translate() |
139 mystring translate() |
151 { |
140 { |
152 vpwentry vpw; |
141 vpwentry* vpw; |
153 unsigned errors = 0; |
142 unsigned errors = 0; |
154 while(getvpwent(vpw)) { |
143 while((vpw = in->get()) != 0) { |
155 if(!!vpw.mailbox) { |
144 if(vpw->has_mailbox) { |
156 mystring response = translate_one(vpw); |
145 mystring response = translate_one(*vpw); |
157 if(!!response) { |
146 if(!!response) { |
158 ferr << "vrehash: " << response; |
147 ferr << "vrehash: " << response; |
159 ++errors; |
148 ++errors; |
160 } |
149 } |
161 } |
150 } |
162 if(!out->put(vpw.name, vpw.to_record())) { |
151 if(!out->put(*vpw)) { |
163 return "vrehash: failed to add entry to table"; |
152 return "vrehash: failed to add entry to table"; |
164 ++errors; |
153 ++errors; |
165 } |
154 } |
|
155 delete vpw; |
166 } |
156 } |
167 return ""; |
157 return ""; |
168 } |
158 } |
169 |
159 |
170 mystring renamedirs() |
160 mystring renamedirs() |