dsalib_ldif.c 11 KB

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