dsalib_db.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #if defined( XP_WIN32 )
  39. #include <windows.h>
  40. #include <process.h>
  41. #include <io.h>
  42. #endif
  43. #include "dsalib.h"
  44. #include <sys/types.h>
  45. #include <sys/stat.h>
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #if !defined( XP_WIN32 )
  50. #include <dirent.h>
  51. #include <unistd.h>
  52. #else
  53. #define popen _popen
  54. #define pclose _pclose
  55. #endif
  56. #include "portable.h"
  57. #include "nspr.h"
  58. /*
  59. * Get a listing of backup directories
  60. * Return NULL for errors and a NULL list for an empty list.
  61. */
  62. DS_EXPORT_SYMBOL char **
  63. ds_get_bak_dirs()
  64. {
  65. char format_str[PATH_MAX];
  66. char *root;
  67. int i = 0;
  68. char **bak_dirs = NULL;
  69. char *bakdir = NULL;
  70. if ( (root = ds_get_install_root()) == NULL )
  71. {
  72. ds_send_error("Cannot find server root directory.", 0);
  73. return(bak_dirs);
  74. }
  75. if ( (bakdir = ds_get_bak_dir()) == NULL )
  76. {
  77. ds_send_error("Cannot find backup directory.", 0);
  78. return(bak_dirs);
  79. }
  80. PR_snprintf( format_str, PATH_MAX, "%s", bakdir );
  81. bak_dirs = ds_get_file_list( format_str );
  82. if( bak_dirs )
  83. {
  84. while( bak_dirs[i] != NULL )
  85. {
  86. /* Prepend the filename with the install root */
  87. char filename[PATH_MAX];
  88. PR_snprintf( filename, PATH_MAX, "%s%c%s",
  89. bakdir, FILE_SEP, bak_dirs[i] );
  90. free( bak_dirs[i] );
  91. bak_dirs[i] = strdup( filename );
  92. #if defined( XP_WIN32 )
  93. ds_dostounixpath( bak_dirs[i] );
  94. #endif
  95. i++;
  96. }
  97. }
  98. return(bak_dirs);
  99. }
  100. /*
  101. * Restore a database based on a backup directory name.
  102. * 0: success
  103. * anything else: failure
  104. */
  105. DS_EXPORT_SYMBOL int
  106. ds_bak2db(char *file)
  107. {
  108. char startup_line[BIG_LINE];
  109. char statfile[PATH_MAX];
  110. char *tmp_dir;
  111. char *root;
  112. int haderror = 0;
  113. int error = -1;
  114. int status;
  115. FILE *sf = NULL;
  116. struct stat fstats;
  117. if ( file == NULL ) {
  118. return DS_NULL_PARAMETER;
  119. }
  120. status = ds_get_updown_status();
  121. if ( status == DS_SERVER_UP ) {
  122. return DS_SERVER_MUST_BE_DOWN;
  123. }
  124. if ( (root = ds_get_install_root()) == NULL ) {
  125. return DS_NO_SERVER_ROOT;
  126. }
  127. if ( file[strlen(file) - 1] == '\n' ) /* strip out returns */
  128. file[strlen(file) - 1] = '\0';
  129. if( stat( file, &fstats ) == -1 && errno == ENOENT ) {
  130. return DS_CANNOT_OPEN_BACKUP_FILE;
  131. } else if( !(fstats.st_mode & S_IFDIR) ) {
  132. return DS_NOT_A_DIRECTORY;
  133. }
  134. tmp_dir = ds_get_tmp_dir();
  135. PR_snprintf(statfile, PATH_MAX, "%s%cbak2db.%d", tmp_dir, FILE_SEP, (int)getpid());
  136. PR_snprintf(startup_line, BIG_LINE,
  137. "%s%cbak2db "
  138. "%s%s%s > "
  139. "%s%s%s 2>&1",
  140. root, FILE_SEP,
  141. ENQUOTE, file, ENQUOTE,
  142. ENQUOTE, statfile, ENQUOTE );
  143. alter_startup_line(startup_line);
  144. fflush(0);
  145. error = system(startup_line);
  146. fflush(0);
  147. if ( error == -1 ) {
  148. return DS_CANNOT_EXEC;
  149. }
  150. fflush(0);
  151. if( !(sf = fopen(statfile, "r")) ) {
  152. return DS_CANNOT_OPEN_STAT_FILE;
  153. }
  154. while ( fgets(startup_line, BIG_LINE, sf) ) {
  155. if ((strstr(startup_line, "- Restoring file")) ||
  156. (strstr(startup_line, "- Checkpointing"))) {
  157. ds_show_message(startup_line);
  158. } else {
  159. haderror = 1;
  160. ds_send_error(startup_line, 0);
  161. }
  162. }
  163. fclose(sf);
  164. unlink(statfile);
  165. if ( haderror )
  166. return DS_UNKNOWN_ERROR;
  167. return 0;
  168. }
  169. /*
  170. * Create a backup based on a file name.
  171. * 0: success
  172. * anything else: failure
  173. */
  174. DS_EXPORT_SYMBOL int
  175. ds_db2bak(char *file)
  176. {
  177. char startup_line[BIG_LINE];
  178. char statfile[PATH_MAX];
  179. char *tmp_dir;
  180. char *root;
  181. int haderror = 0;
  182. int error = -1;
  183. FILE *sf = NULL;
  184. int lite = 0;
  185. #ifdef XP_WIN32
  186. time_t ltime;
  187. #endif
  188. if ( (root = ds_get_install_root()) == NULL ) {
  189. return DS_NO_SERVER_ROOT;
  190. }
  191. if ( (file == NULL) || (strlen(file) == 0) )
  192. file = NULL;
  193. tmp_dir = ds_get_tmp_dir();
  194. PR_snprintf(statfile, PATH_MAX, "%s%cdb2bak.%d", tmp_dir, FILE_SEP, (int)getpid());
  195. #if defined( XP_WIN32 )
  196. if( file == NULL )
  197. {
  198. file = malloc( BIG_LINE );
  199. time( &ltime );
  200. PR_snprintf( file, BIG_LINE, "%s", ctime( &ltime ) );
  201. ds_timetofname( file );
  202. }
  203. /* Check if the directory exists or can be created */
  204. if ( !ds_file_exists( file ) ) {
  205. char *errmsg = ds_mkdir_p( file, NEWDIR_MODE );
  206. if( errmsg != NULL ) {
  207. /* ds_send_error(errmsg, 10);
  208. */
  209. return DS_CANNOT_CREATE_DIRECTORY;
  210. }
  211. }
  212. #endif
  213. /* DBDB: note on the following line.
  214. * Originally this had quotes round the directory name.
  215. * I found that this made the script not work becuase
  216. * a path of the form "foo"/bar/"baz" was passed to slapd.
  217. * the c runtime didn't like this. Perhaps there's a simple
  218. * solution, but for now I've modified this line here to
  219. * not quote the directory name. This means that backup
  220. * directories can't have spaces in them.
  221. */
  222. PR_snprintf(startup_line, sizeof(startup_line),
  223. "%s%cdb2bak "
  224. "%s%s%s > "
  225. "%s%s%s 2>&1",
  226. root, FILE_SEP,
  227. ENQUOTE,
  228. (file == NULL) ? "" : file,
  229. ENQUOTE,
  230. ENQUOTE, statfile, ENQUOTE);
  231. PATH_FOR_PLATFORM( startup_line );
  232. alter_startup_line(startup_line);
  233. fflush(0);
  234. error = system(startup_line);
  235. if ( error == -1 ) {
  236. return DS_CANNOT_EXEC;
  237. }
  238. if( !(sf = fopen(statfile, "r")) ) {
  239. return DS_CANNOT_OPEN_STAT_FILE;
  240. }
  241. while ( fgets(startup_line, BIG_LINE, sf) ) {
  242. if (strstr(startup_line, " - Backing up file") ||
  243. strstr(startup_line, " - Checkpointing database")) {
  244. ds_show_message(startup_line);
  245. } else {
  246. haderror = 1;
  247. if (strstr ( startup_line, "restricted mode")) {
  248. lite = 1;
  249. }
  250. ds_send_error(startup_line, 0);
  251. }
  252. }
  253. fclose(sf);
  254. unlink(statfile);
  255. if ( lite && haderror )
  256. return DS_HAS_TOBE_READONLY_MODE;
  257. if ( haderror )
  258. return DS_UNKNOWN_ERROR;
  259. return 0;
  260. }
  261. static void
  262. process_and_report( char *line, int line_size, FILE *cmd )
  263. {
  264. while(fgets(line, line_size, cmd)) {
  265. /* Strip off line feeds */
  266. int ind = strlen( line ) - 1;
  267. while ( (ind >= 0) &&
  268. ((line[ind] == '\n') ||
  269. (line[ind] == '\r')) ) {
  270. line[ind] = 0;
  271. ind--;
  272. }
  273. if ( ind < 1 ) {
  274. continue;
  275. }
  276. ds_send_status(line);
  277. }
  278. }
  279. static int exec_and_report( char *startup_line )
  280. {
  281. FILE *cmd = NULL;
  282. char line[BIG_LINE];
  283. int haderror = 0;
  284. PATH_FOR_PLATFORM( startup_line );
  285. alter_startup_line(startup_line);
  286. /*
  287. fprintf( stdout, "Launching <%s>\n", startup_line );
  288. */
  289. fflush(0);
  290. cmd = popen(startup_line, "r");
  291. if(!cmd) {
  292. return DS_CANNOT_EXEC;
  293. }
  294. process_and_report( line, sizeof(line), cmd );
  295. pclose(cmd);
  296. /*
  297. ** The VLV indexing code prints OK,
  298. ** if the index was successfully created.
  299. */
  300. if (strcmp(line,"OK")==0) {
  301. haderror = 0;
  302. } else {
  303. haderror = DS_UNKNOWN_ERROR;
  304. }
  305. return haderror;
  306. }
  307. /*
  308. * Create a vlv index
  309. * 0: success
  310. * anything else: failure
  311. */
  312. DS_EXPORT_SYMBOL int
  313. ds_vlvindex(char **backendList, char **vlvList)
  314. {
  315. char startup_line[BIG_LINE];
  316. char *root;
  317. char *instroot;
  318. char **vlvc = NULL;
  319. root = ds_get_server_root();
  320. instroot = ds_get_install_root();
  321. if ( (root == NULL) || (instroot == NULL) ) {
  322. return DS_NO_SERVER_ROOT;
  323. }
  324. PR_snprintf(startup_line, sizeof(startup_line), "%s/bin/slapd/server/%s db2index "
  325. "-D %s%s/%s "
  326. "-n %s ",
  327. root, SLAPD_NAME,
  328. ENQUOTE, instroot, ENQUOTE,
  329. backendList[0]);
  330. /* Create vlv TAG */
  331. vlvc=vlvList;
  332. while( *vlvc != NULL ) {
  333. PR_snprintf( startup_line, sizeof(startup_line), "%s -T %s%s%s", startup_line,"\"",*vlvc,"\"" );
  334. vlvc++;
  335. }
  336. return exec_and_report( startup_line );
  337. }
  338. /*
  339. * Create one or more indexes
  340. * 0: success
  341. * anything else: failure
  342. */
  343. DS_EXPORT_SYMBOL int
  344. ds_addindex(char **attrList, char *backendName)
  345. {
  346. char startup_line[BIG_LINE];
  347. char *root;
  348. char *instroot;
  349. root = ds_get_server_root();
  350. instroot = ds_get_install_root();
  351. if ( (root == NULL) || (instroot == NULL) ) {
  352. return DS_NO_SERVER_ROOT;
  353. }
  354. PR_snprintf(startup_line, sizeof(startup_line), "%s/bin/slapd/server/%s db2index "
  355. "-D %s%s%s "
  356. "-n %s",
  357. root, SLAPD_NAME,
  358. ENQUOTE, instroot, ENQUOTE,
  359. backendName);
  360. while( *attrList != NULL ) {
  361. PR_snprintf( startup_line, sizeof(startup_line), "%s -t %s", startup_line, *attrList );
  362. attrList++;
  363. }
  364. return exec_and_report( startup_line );
  365. }