data.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. #ident "ldclt @(#)data.c 1.8 01/03/23"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * This Program is free software; you can redistribute it and/or modify it under
  4. * the terms of the GNU General Public License as published by the Free Software
  5. * Foundation; version 2 of the License.
  6. *
  7. * This Program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with
  12. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  13. * Place, Suite 330, Boston, MA 02111-1307 USA.
  14. *
  15. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  16. * right to link the code of this Program with code not covered under the GNU
  17. * General Public License ("Non-GPL Code") and to distribute linked combinations
  18. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  19. * permitted under this exception must only link to the code of this Program
  20. * through those well defined interfaces identified in the file named EXCEPTION
  21. * found in the source code files (the "Approved Interfaces"). The files of
  22. * Non-GPL Code may instantiate templates or use macros or inline functions from
  23. * the Approved Interfaces without causing the resulting work to be covered by
  24. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  25. * additions to the list of Approved Interfaces. You must obey the GNU General
  26. * Public License in all respects for all of the Program code and other code used
  27. * in conjunction with the Program except the Non-GPL Code covered by this
  28. * exception. If you modify this file, you may extend this exception to your
  29. * version of the file, but you are not obligated to do so. If you do not wish to
  30. * provide this exception without modification, you must delete this exception
  31. * statement from your version and license this file solely under the GPL without
  32. * exception.
  33. *
  34. *
  35. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  36. * Copyright (C) 2006 Red Hat, Inc.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /*
  43. FILE : data.c
  44. AUTHOR : Jean-Luc SCHWING
  45. VERSION : 1.0
  46. DATE : 11 January 1999
  47. DESCRIPTION :
  48. This file implements the management of the data that
  49. are manipulated by ldclt.
  50. It is targetted to contain all the functions needed for
  51. the images, etc...
  52. LOCAL : None.
  53. HISTORY :
  54. ---------+--------------+------------------------------------------------------
  55. dd/mm/yy | Author | Comments
  56. ---------+--------------+------------------------------------------------------
  57. 11/01/99 | JL Schwing | Creation
  58. ---------+--------------+------------------------------------------------------
  59. 06/03/00 | JL Schwing | 1.2 : Test malloc() return value.
  60. ---------+--------------+------------------------------------------------------
  61. 28/11/00 | JL Schwing | 1.3 : Port on NT 4.
  62. ---------+--------------+------------------------------------------------------
  63. 30/11/00 | JL Schwing | 1.4 : Implement loadImages for NT.
  64. ---------+--------------+------------------------------------------------------
  65. 30/11/00 | JL Schwing | 1.5 : Port on OSF1.
  66. ---------+--------------+------------------------------------------------------
  67. 01/12/00 | JL Schwing | 1.6 : Port on Linux.
  68. ---------+--------------+------------------------------------------------------
  69. 06/03/01 | JL Schwing | 1.7 : Better error messages if images not found.
  70. ---------+--------------+------------------------------------------------------
  71. 23/03/01 | JL Schwing | 1.8 : Implements data file list support in variants.
  72. ---------+--------------+------------------------------------------------------
  73. */
  74. #include <stdio.h> /* printf(), etc... */
  75. #include <stdlib.h> /* realloc(), etc... */
  76. #include <string.h> /* strlen(), etc... */
  77. #include <errno.h> /* errno, etc... */ /*JLS 06-03-00*/
  78. #include <sys/types.h> /* Misc types... */
  79. #include <sys/stat.h> /* stat(), etc... */
  80. #include <fcntl.h> /* open(), etc... */
  81. #include <lber.h> /* ldap C-API BER declarations */
  82. #include <ldap.h> /* ldap C-API declarations */
  83. #ifndef _WIN32 /*JLS 28-11-00*/
  84. #include <unistd.h> /* close(), etc... */
  85. #include <dirent.h> /* opendir(), etc... */
  86. #include <pthread.h> /* pthreads(), etc... */
  87. #include <sys/mman.h> /* mmap(), etc... */
  88. #endif /*JLS 28-11-00*/
  89. #include "port.h" /* Portability definitions */ /*JLS 28-11-00*/
  90. #include "ldclt.h" /* This tool's include file */
  91. /* ****************************************************************************
  92. FUNCTION : getExtend
  93. PURPOSE : Get the extension of the given string, i.e. the part
  94. that is after the last '.'
  95. INPUT : str = string to process
  96. OUTPUT : None.
  97. RETURN : The extension.
  98. DESCRIPTION :
  99. *****************************************************************************/
  100. char *getExtend (
  101. char *str)
  102. {
  103. int i;
  104. for (i=strlen(str)-1; (i>=0) && (str[i]!='.') ; i--);
  105. return (&(str[i+1]));
  106. }
  107. /* ****************************************************************************
  108. FUNCTION : loadImages
  109. PURPOSE : Load the images from the given directory.
  110. INPUT : dirpath = directory where the images are located.
  111. OUTPUT : None.
  112. RETURN : -1 if error, 0 else.
  113. DESCRIPTION :
  114. *****************************************************************************/
  115. int loadImages (
  116. char *dirpath)
  117. {
  118. #ifdef _WIN32
  119. WIN32_FIND_DATA fileData; /* Current file */
  120. HANDLE dirContext; /* Directory context */
  121. char *findPath = NULL; /* To build the find path */
  122. char *pt; /* To read the images */
  123. #else /* _WIN32 */
  124. DIR *dirp = NULL; /* Directory data */
  125. struct dirent *direntp; /* Directory entry */
  126. #endif /* _WIN32 */
  127. char *fileName; /* As read from the system */
  128. char name [1024]; /* To build the full path */
  129. struct stat stat_buf; /* To read the image size */
  130. int fd; /* To open the image */
  131. int ret; /* Return value */
  132. int rc = 0;
  133. /*
  134. * Initialization
  135. */
  136. mctx.images = NULL;
  137. mctx.imagesNb = 0;
  138. mctx.imagesLast = -1;
  139. if ((ret = ldclt_mutex_init(&(mctx.imagesLast_mutex))) != 0)
  140. {
  141. fprintf (stderr, "ldclt: %s\n", strerror (ret));
  142. fprintf (stderr, "Error: cannot initiate imagesLast_mutex\n");
  143. fflush (stderr);
  144. rc = -1;
  145. goto exit;
  146. }
  147. /*
  148. * Open the directory
  149. */
  150. #ifdef _WIN32
  151. findPath = (char *) malloc (strlen (dirpath) + 5);
  152. strcpy (findPath, dirpath);
  153. strcat (findPath, "/*.*");
  154. dirContext = FindFirstFile (findPath, &fileData);
  155. if (dirContext == INVALID_HANDLE_VALUE)
  156. {
  157. fprintf (stderr, "ldlct: cannot load images from %s\n", dirpath);
  158. fprintf (stderr, "ldclt: try using -e imagesdir=path\n"); /*JLS 06-03-01*/
  159. fflush (stderr);
  160. rc = -1;
  161. goto exit;
  162. }
  163. #else /* _WIN32 */
  164. dirp = opendir (dirpath);
  165. if (dirp == NULL)
  166. {
  167. perror (dirpath);
  168. fprintf (stderr, "ldlct: cannot load images from %s\n", dirpath);
  169. fprintf (stderr, "ldclt: try using -e imagesdir=path\n"); /*JLS 06-03-01*/
  170. fflush (stderr);
  171. rc = -1;
  172. goto exit;
  173. }
  174. #endif /* _WIN32 */
  175. /*
  176. * Process the directory.
  177. * We will only accept the .jpg files, as stated by the RFC.
  178. */
  179. #ifdef _WIN32
  180. fileName = fileData.cFileName;
  181. do
  182. {
  183. #else
  184. while ((direntp = readdir (dirp)) != NULL)
  185. {
  186. fileName = direntp->d_name;
  187. #endif
  188. if (!strcmp (getExtend (fileName), "jpg"))
  189. {
  190. /*
  191. * Allocate a new image, and initiates with its name.
  192. */
  193. mctx.imagesNb++;
  194. mctx.images =
  195. (image *) realloc (mctx.images, mctx.imagesNb * sizeof (image));
  196. if (mctx.images == NULL) /*JLS 06-03-00*/
  197. { /*JLS 06-03-00*/
  198. printf ("Error: cannot realloc(mctx.images), error=%d (%s)\n",
  199. errno, strerror (errno)); /*JLS 06-03-00*/
  200. rc = -1;
  201. goto exit;
  202. } /*JLS 06-03-00*/
  203. mctx.images[mctx.imagesNb-1].name =
  204. (char *) malloc (strlen(fileName) + 1);
  205. if (mctx.images[mctx.imagesNb-1].name == NULL) /*JLS 06-03-00*/
  206. { /*JLS 06-03-00*/
  207. printf ("Error: cannot malloc(mctx.images[%d]).name, error=%d (%s)\n",
  208. mctx.imagesNb-1, errno, strerror (errno)); /*JLS 06-03-00*/
  209. rc = -1;
  210. goto exit;
  211. } /*JLS 06-03-00*/
  212. strcpy (mctx.images[mctx.imagesNb-1].name, fileName);
  213. /*
  214. * Read the image size
  215. */
  216. snprintf (name, sizeof(name), "%s/%s", dirpath, fileName);
  217. name[sizeof(name)-1] = '\0';
  218. /*
  219. * Open the image
  220. */
  221. fd = open (name, O_RDONLY);
  222. if (fd < 0)
  223. {
  224. perror (name);
  225. fprintf (stderr, "Cannot open(%s)\n", name);
  226. fflush (stderr);
  227. rc = -1;
  228. goto exit;
  229. }
  230. if (fstat (fd, &stat_buf) < 0)
  231. {
  232. perror (name);
  233. fprintf (stderr, "Cannot stat(%s)\n", name);
  234. fflush (stderr);
  235. rc = -1;
  236. goto exit;
  237. }
  238. mctx.images[mctx.imagesNb-1].length = stat_buf.st_size;
  239. #ifdef _WIN32
  240. /*
  241. * Allocate buffer and read the data :-(
  242. */
  243. mctx.images[mctx.imagesNb-1].data = (char *) malloc (stat_buf.st_size);
  244. if (mctx.images[mctx.imagesNb-1].data == NULL)
  245. {
  246. fprintf (stderr, "Cannot malloc(%d) to load %s\n",
  247. stat_buf.st_size, name);
  248. fflush (stderr);
  249. rc = -1;
  250. goto exit;
  251. }
  252. if (read (fd, mctx.images[mctx.imagesNb-1].data, stat_buf.st_size) < 0)
  253. {
  254. perror (name);
  255. fprintf (stderr, "Cannot read(%s)\n", name);
  256. fflush (stderr);
  257. rc = -1;
  258. goto exit;
  259. }
  260. #else /* _WIN32 */
  261. /*
  262. * mmap() the image
  263. */
  264. mctx.images[mctx.imagesNb-1].data = mmap (0, stat_buf.st_size,
  265. PROT_READ, MAP_SHARED, fd, 0);
  266. if (mctx.images[mctx.imagesNb-1].data == (char *)MAP_FAILED)
  267. {
  268. perror (name);
  269. fprintf (stderr, "Cannot mmap(%s)\n", name);
  270. fflush (stderr);
  271. rc = -1;
  272. goto exit;
  273. }
  274. #endif /* _WIN32 */
  275. /*
  276. * Close the image. The mmap() will remain available, and this
  277. * close() will save file descriptors.
  278. */
  279. if (close (fd) < 0)
  280. {
  281. perror (name);
  282. fprintf (stderr, "Cannot close(%s)\n", name);
  283. fflush (stderr);
  284. rc = -1;
  285. goto exit;
  286. }
  287. }
  288. #ifdef _WIN32
  289. } while (FindNextFile(dirContext, &fileData) == TRUE);
  290. #else
  291. } /* while ((direntp = readdir (dirp)) != NULL) */
  292. #endif
  293. exit:
  294. /*
  295. * Close the directory
  296. */
  297. #ifndef _WIN32
  298. if (dirp && closedir (dirp) < 0)
  299. {
  300. perror (dirpath);
  301. fprintf (stderr, "Cannot closedir(%s)\n", dirpath);
  302. fflush (stderr);
  303. rc = -1;
  304. }
  305. #endif
  306. /*
  307. * Normal end
  308. */
  309. #ifdef _WIN32
  310. if (findPath) free (findPath);
  311. #endif
  312. return rc;
  313. }
  314. /* ****************************************************************************
  315. FUNCTION : getImage
  316. PURPOSE : Add a random image to the given attribute.
  317. INPUT : None.
  318. OUTPUT : attribute = the attribute where the image should
  319. be added.
  320. RETURN : -1 if error, 0 else.
  321. DESCRIPTION :
  322. *****************************************************************************/
  323. int getImage (
  324. LDAPMod *attribute)
  325. {
  326. int imageNumber; /* The image we will select */
  327. int ret; /* Return value */
  328. /*
  329. * Select the next image
  330. */
  331. if ((ret = ldclt_mutex_lock (&(mctx.imagesLast_mutex))) != 0) /*JLS 29-11-00*/
  332. {
  333. fprintf (stderr,
  334. "Cannot mutex_lock(imagesLast_mutex), error=%d (%s)\n",
  335. ret, strerror (ret));
  336. fflush (stderr);
  337. return (-1);
  338. }
  339. mctx.imagesLast++;
  340. if (mctx.imagesLast == mctx.imagesNb)
  341. mctx.imagesLast = 0;
  342. imageNumber = mctx.imagesLast;
  343. if ((ret = ldclt_mutex_unlock (&(mctx.imagesLast_mutex))) != 0)
  344. {
  345. fprintf (stderr,
  346. "Cannot mutex_unlock(imagesLast_mutex), error=%d (%s)\n",
  347. ret, strerror (ret));
  348. fflush (stderr);
  349. return (-1);
  350. }
  351. /*
  352. * Create the data structure required
  353. */
  354. attribute->mod_bvalues = (struct berval **)
  355. malloc (2 * sizeof (struct berval *));
  356. if (attribute->mod_bvalues == NULL) /*JLS 06-03-00*/
  357. { /*JLS 06-03-00*/
  358. printf ("Error: cannot malloc(attribute->mod_bvalues), error=%d (%s)\n",
  359. errno, strerror (errno)); /*JLS 06-03-00*/
  360. return (-1); /*JLS 06-03-00*/
  361. } /*JLS 06-03-00*/
  362. attribute->mod_bvalues[0] = (struct berval *) malloc (sizeof (struct berval));
  363. if (attribute->mod_bvalues[0] == NULL) /*JLS 06-03-00*/
  364. { /*JLS 06-03-00*/
  365. printf ("Error: cannot malloc(attribute->mod_bvalues[0]), error=%d (%s)\n",
  366. errno, strerror (errno)); /*JLS 06-03-00*/
  367. return (-1); /*JLS 06-03-00*/
  368. } /*JLS 06-03-00*/
  369. attribute->mod_bvalues[1] = NULL;
  370. /*
  371. * Fill the bvalue with the image data
  372. */
  373. attribute->mod_bvalues[0]->bv_len = mctx.images[imageNumber].length;
  374. attribute->mod_bvalues[0]->bv_val = mctx.images[imageNumber].data;
  375. /*
  376. * Normal end
  377. */
  378. return (0);
  379. }
  380. /* New */ /*JLS 23-03-01*/
  381. /* ****************************************************************************
  382. FUNCTION : loadDataListFile
  383. PURPOSE : Load the data list file given in argument.
  384. INPUT : dlf->fname = file to process
  385. OUTPUT : dlf = file read
  386. RETURN : -1 if error, 0 else.
  387. DESCRIPTION :
  388. *****************************************************************************/
  389. int
  390. loadDataListFile (
  391. data_list_file *dlf)
  392. {
  393. FILE *ifile; /* Input file */
  394. char line[MAX_FILTER]; /* To read ifile */
  395. /*
  396. * Open the file
  397. */
  398. ifile = fopen (dlf->fname, "r");
  399. if (ifile == NULL)
  400. {
  401. perror (dlf->fname);
  402. fprintf (stderr, "Error: cannot open file \"%s\"\n", dlf->fname);
  403. return (-1);
  404. }
  405. /*
  406. * Count the entries.
  407. * Allocate the array.
  408. * Rewind the file.
  409. */
  410. for (dlf->strNb=0 ; fgets(line, MAX_FILTER, ifile) != NULL ; dlf->strNb++);
  411. dlf->str = (char **) malloc (dlf->strNb * sizeof (char *));
  412. if (fseek (ifile, 0, SEEK_SET) != 0)
  413. {
  414. perror (dlf->fname);
  415. fprintf (stderr, "Error: cannot rewind file \"%s\"\n", dlf->fname);
  416. fclose(ifile);
  417. return (-1);
  418. }
  419. /*
  420. * Read all the entries from this file
  421. */
  422. dlf->strNb=0;
  423. while (fgets(line, MAX_FILTER, ifile) != NULL)
  424. {
  425. if ((strlen (line) > 0) && (line[strlen(line)-1]=='\n'))
  426. line[strlen(line)-1] = '\0';
  427. dlf->str[dlf->strNb] = strdup (line);
  428. dlf->strNb++;
  429. }
  430. /*
  431. * Close the file
  432. */
  433. if (fclose (ifile) != 0)
  434. {
  435. perror (dlf->fname);
  436. fprintf (stderr, "Error: cannot fclose file \"%s\"\n", dlf->fname);
  437. return (-1);
  438. }
  439. return (0);
  440. }
  441. /* New */ /*JLS 23-03-01*/
  442. /* ****************************************************************************
  443. FUNCTION : dataListFile
  444. PURPOSE : Find the given data_list_file either in the list of
  445. files already loaded, either load it.
  446. INPUT : fname = file name.
  447. OUTPUT : None.
  448. RETURN : NULL if error, else the requested file.
  449. DESCRIPTION :
  450. *****************************************************************************/
  451. data_list_file *
  452. dataListFile (
  453. char *fname)
  454. {
  455. data_list_file *dlf; /* To process the request */
  456. /*
  457. * Maybe we already have loaded this file ?
  458. */
  459. for (dlf=mctx.dlf ; dlf != NULL ; dlf=dlf->next)
  460. if (!strcmp (fname, dlf->fname))
  461. return (dlf);
  462. /*
  463. * Well, it looks like we should load a new file ;-)
  464. * Allocate a new data structure, chain it in mctx and load the file.
  465. */
  466. dlf = (data_list_file *) malloc (sizeof (data_list_file));
  467. dlf->next = mctx.dlf;
  468. mctx.dlf = dlf;
  469. dlf->fname = strdup (fname);
  470. if (loadDataListFile (dlf) < 0)
  471. return (NULL);
  472. /*
  473. * Loaded...
  474. */
  475. return (dlf);
  476. }
  477. /* End of file */