dsalib_ldif.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #if defined( XP_WIN32 )
  42. #include <windows.h>
  43. #include <process.h>
  44. #include <malloc.h>
  45. #define popen _popen
  46. #define pclose _pclose
  47. #else
  48. #include <unistd.h>
  49. #endif
  50. #include "dsalib.h"
  51. #include <sys/types.h>
  52. #include <sys/stat.h>
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <errno.h>
  57. #include "nspr.h"
  58. #include "plstr.h"
  59. #ifndef XP_WIN32
  60. #define SCRIPT_SUFFIX "" /* shell scripts have no suffix */
  61. #else
  62. #define SCRIPT_SUFFIX ".bat" /* batch file suffix */
  63. #endif
  64. static int
  65. process_and_report( char *line, int line_size, FILE *cmd )
  66. {
  67. int err = 0;
  68. while(fgets(line, line_size, cmd)) {
  69. /* Strip off line feeds */
  70. int ind = strlen( line ) - 1;
  71. #ifdef DEBUG_CGI
  72. fprintf(stderr, "read line=[%s] ind=%d\n", line, ind);
  73. #endif /* DEBUG_CGI */
  74. fprintf( stdout, ": %s", line );
  75. fflush(0);
  76. while ( (ind >= 0) &&
  77. ((line[ind] == '\n') ||
  78. (line[ind] == '\r')) ) {
  79. line[ind] = 0;
  80. ind--;
  81. }
  82. if ( ind < 1 ) {
  83. continue;
  84. }
  85. ds_send_status(line);
  86. if ( (strstr(line, "bad LDIF") != NULL) ) {
  87. #ifdef DEBUG_CGI
  88. fprintf(stderr, "invalid ldif file\n");
  89. #endif /* DEBUG_CGI */
  90. err = DS_INVALID_LDIF_FILE;
  91. } else if ( 0 == err ) {
  92. if ( (strstr(line, "err=") != NULL) ) {
  93. #ifdef DEBUG_CGI
  94. fprintf(stderr, "unknown error\n");
  95. #endif /* DEBUG_CGI */
  96. err = DS_UNKNOWN_ERROR;
  97. }
  98. }
  99. }
  100. #ifdef DEBUG_CGI
  101. fprintf(stderr, "process_and_report finished err=%d\n", err);
  102. #endif /* DEBUG_CGI */
  103. return err;
  104. }
  105. static int exec_and_report( char *startup_line )
  106. {
  107. FILE *cmd = NULL;
  108. char line[BIG_LINE];
  109. int haderror = 0;
  110. PATH_FOR_PLATFORM( startup_line );
  111. alter_startup_line(startup_line);
  112. fflush(stdout);
  113. cmd = popen(startup_line, "r");
  114. if(!cmd) {
  115. printf("could not open pipe [%s]: %d\n",
  116. startup_line, errno);
  117. #ifdef DEBUG_CGI
  118. fprintf(stderr, "could not open pipe [%s]: %d\n",
  119. startup_line, errno);
  120. #endif /* DEBUG_CGI */
  121. return DS_CANNOT_EXEC;
  122. }
  123. haderror = process_and_report( line, sizeof(line), cmd );
  124. pclose(cmd);
  125. return haderror;
  126. }
  127. /*
  128. * Execute a shell command.
  129. * 0: success
  130. * anything else: failure
  131. */
  132. DS_EXPORT_SYMBOL int
  133. ds_exec_and_report( char *startup_line )
  134. {
  135. return exec_and_report( startup_line );
  136. }
  137. /*
  138. * Create a database based on a file name.
  139. * 0: success
  140. * anything else: failure
  141. */
  142. static int
  143. importldif(char *file, int preserve, char *backend, char *subtree)
  144. {
  145. char startup_line[BIG_LINE];
  146. char *root;
  147. int haderror = 0;
  148. int i = 0, error = -1;
  149. int status;
  150. struct stat fstats;
  151. char errbuf[ BIG_LINE ];
  152. char **db_files = NULL, *changelogdir = NULL;
  153. int rc;
  154. errbuf[ 0 ] = '\0';
  155. if ( file == NULL ) {
  156. #ifdef DEBUG_CGI
  157. fprintf(stderr, "importldif: null file\n");
  158. #endif /* DEBUG_CGI */
  159. return DS_NULL_PARAMETER;
  160. }
  161. status = ds_get_updown_status();
  162. if ( status == DS_SERVER_UP ) {
  163. #ifdef DEBUG_CGI
  164. fprintf(stderr, "importldif: server is not down\n");
  165. #endif /* DEBUG_CGI */
  166. return DS_SERVER_MUST_BE_DOWN;
  167. }
  168. if ( (root = ds_get_install_root()) == NULL ) {
  169. #ifdef DEBUG_CGI
  170. fprintf(stderr, "importldif: could not get server root\n");
  171. #endif /* DEBUG_CGI */
  172. return DS_NO_SERVER_ROOT;
  173. }
  174. if ( file[strlen(file) - 1] == '\n' ) /* strip out returns */
  175. file[strlen(file) - 1] = '\0';
  176. /* Make sure the file exists and is not a directory: 34347 */
  177. if( stat( file, &fstats ) == -1 && errno == ENOENT ) {
  178. #ifdef DEBUG_CGI
  179. fprintf(stderr, "importldif: could not open %s\n", file);
  180. #endif /* DEBUG_CGI */
  181. return DS_CANNOT_OPEN_LDIF_FILE;
  182. } else if( fstats.st_mode & S_IFDIR ) {
  183. #ifdef DEBUG_CGI
  184. fprintf(stderr, "importldif: not a file %s\n", file);
  185. #endif /* DEBUG_CGI */
  186. return DS_IS_A_DIRECTORY;
  187. }
  188. if ( preserve ) {
  189. PR_snprintf(startup_line, BIG_LINE, "%s%cldif2db%s -i %s%s%s",
  190. root, FILE_SEP, SCRIPT_SUFFIX,
  191. ENQUOTE, file, ENQUOTE);
  192. } else if (backend) {
  193. PR_snprintf(startup_line, BIG_LINE, "%s%cldif2db%s -n %s%s%s -i %s%s%s",
  194. root, FILE_SEP, SCRIPT_SUFFIX,
  195. ENQUOTE, backend, ENQUOTE,
  196. ENQUOTE, file, ENQUOTE);
  197. } else if (subtree) {
  198. PR_snprintf(startup_line, BIG_LINE, "%s%cldif2db%s -s %s%s%s -i %s%s%s",
  199. root, FILE_SEP, SCRIPT_SUFFIX,
  200. ENQUOTE, subtree, ENQUOTE,
  201. ENQUOTE, file, ENQUOTE);
  202. } else {
  203. PR_snprintf(startup_line, BIG_LINE, "%s%cldif2db%s -i %s%s%s -noconfig",
  204. root, FILE_SEP, SCRIPT_SUFFIX,
  205. ENQUOTE, file, ENQUOTE);
  206. }
  207. alter_startup_line(startup_line);
  208. fflush(stdout);
  209. #ifdef DEBUG_CGI
  210. fprintf(stderr, "importldif: executing %s\n", startup_line);
  211. #endif /* DEBUG_CGI */
  212. error = exec_and_report(startup_line);
  213. /*error = system(startup_line);*/
  214. if ( error != 0 ) {
  215. #ifdef DEBUG_CGI
  216. fprintf(stderr, "importldif: error=%d\n", error);
  217. #endif /* DEBUG_CGI */
  218. return error;
  219. }
  220. /* Remove the changelog database, if present */
  221. changelogdir = ds_get_config_value(0xdeadbeef);
  222. if ( changelogdir != NULL ) {
  223. db_files = ds_get_file_list( changelogdir );
  224. if ( db_files != NULL ) {
  225. ds_send_status("Removing changelog database...");
  226. }
  227. for ( i = 0; db_files != NULL && db_files[ i ] != NULL; i++ ) {
  228. char sbuf[ BIG_LINE ];
  229. char filename[ BIG_LINE ];
  230. if ( strlen( db_files[ i ]) > 0 ) {
  231. PR_snprintf( filename, BIG_LINE, "%s%c%s", changelogdir,
  232. FILE_SEP, db_files[ i ]);
  233. PR_snprintf(sbuf, BIG_LINE, "Removing %s", filename);
  234. ds_send_status( sbuf );
  235. rc = unlink( filename);
  236. if ( rc != 0 ) {
  237. PR_snprintf( errbuf, BIG_LINE, "Warning: some files in %s could not "
  238. "be removed\n", changelogdir );
  239. haderror++;
  240. }
  241. }
  242. }
  243. }
  244. if ( strlen( errbuf ) > 0 ) {
  245. ds_send_error( errbuf, 0 );
  246. }
  247. return error;
  248. }
  249. /*
  250. * Create a database based on a file name.
  251. * 0: success
  252. * anything else: failure
  253. */
  254. DS_EXPORT_SYMBOL int
  255. ds_ldif2db(char *file)
  256. {
  257. return importldif( file, 0, NULL, NULL );
  258. }
  259. /*
  260. * Create a database based on a file name.
  261. * 0: success
  262. * anything else: failure
  263. */
  264. DS_EXPORT_SYMBOL int
  265. ds_ldif2db_preserve(char *file)
  266. {
  267. return importldif( file, 1, NULL, NULL );
  268. }
  269. /*
  270. * import an ldif file into a named backend or subtree
  271. * 0: success
  272. * anything else: failure
  273. */
  274. DS_EXPORT_SYMBOL int
  275. ds_ldif2db_backend_subtree(char *file, char *backend, char *subtree)
  276. {
  277. return importldif( file, 0, backend, subtree );
  278. }
  279. /*
  280. * Create a LDIF file based on a file name.
  281. * 0: success
  282. * anything else: failure
  283. */
  284. DS_EXPORT_SYMBOL int
  285. ds_db2ldif_subtree(char *file, char *subtree)
  286. {
  287. char startup_line[BIG_LINE];
  288. char statfile[PATH_MAX];
  289. char outfile[PATH_MAX];
  290. char scriptfile[PATH_MAX];
  291. char *tmp_dir;
  292. char *root;
  293. int haderror = 0;
  294. int error = -1;
  295. FILE *sf = NULL;
  296. if ( (root = ds_get_install_root()) == NULL ) {
  297. return DS_NO_SERVER_ROOT;
  298. }
  299. if ( (file == NULL) || (strlen(file) == 0) )
  300. file = NULL;
  301. tmp_dir = ds_get_tmp_dir();
  302. PR_snprintf(statfile, PATH_MAX, "%s%cdb2ldif.%d", tmp_dir, FILE_SEP, (int) getpid());
  303. #if defined( XP_WIN32 )
  304. if( file == NULL )
  305. {
  306. time_t ltime;
  307. file = malloc( BIG_LINE );
  308. time( &ltime );
  309. PR_snprintf( file, BIG_LINE, "%s", ctime( &ltime ) );
  310. ds_timetofname( file );
  311. }
  312. #endif
  313. if ( file == NULL )
  314. *outfile = 0;
  315. else
  316. PL_strncpyz( outfile, file, sizeof(outfile) );
  317. PR_snprintf(scriptfile, PATH_MAX, "%s%cdb2ldif", root, FILE_SEP);
  318. PATH_FOR_PLATFORM( outfile );
  319. PATH_FOR_PLATFORM( scriptfile );
  320. if ( subtree == NULL ) {
  321. PR_snprintf(startup_line, sizeof(startup_line),
  322. "%s "
  323. "%s%s%s > "
  324. "%s%s%s 2>&1",
  325. scriptfile,
  326. ENQUOTE, outfile, ENQUOTE,
  327. ENQUOTE, statfile, ENQUOTE);
  328. } else {
  329. PR_snprintf(startup_line, sizeof(startup_line),
  330. "%s "
  331. "%s%s%s "
  332. "-s \"%s\" > "
  333. "%s%s%s 2>&1",
  334. scriptfile,
  335. ENQUOTE, outfile, ENQUOTE,
  336. subtree,
  337. ENQUOTE, statfile, ENQUOTE);
  338. }
  339. fflush(0);
  340. alter_startup_line(startup_line);
  341. error = system(startup_line);
  342. if ( error == -1 ) {
  343. return DS_CANNOT_EXEC;
  344. }
  345. sf = fopen(statfile, "r");
  346. if( sf ) {
  347. while ( fgets(startup_line, BIG_LINE, sf) ) {
  348. /*
  349. The db2ldif process will usually print out a summary at the
  350. end, but that is not an error
  351. */
  352. char *ptr = strstr(startup_line, "Processed");
  353. if (ptr && strstr(ptr, "entries."))
  354. {
  355. ds_show_message(startup_line);
  356. }
  357. else
  358. {
  359. haderror = 1;
  360. ds_send_error(startup_line, 0);
  361. }
  362. }
  363. fclose(sf);
  364. unlink(statfile);
  365. }
  366. if ( haderror )
  367. return DS_UNKNOWN_ERROR;
  368. return 0;
  369. }
  370. /*
  371. * Create a LDIF file based on a file name.
  372. * 0: success
  373. * anything else: failure
  374. */
  375. DS_EXPORT_SYMBOL int
  376. ds_db2ldif(char *file)
  377. {
  378. return ds_db2ldif_subtree(file, NULL);
  379. }