GnuCOBOL  2.0
A free COBOL compiler
fileio.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2012, 2014-2016 Free Software Foundation, Inc.
3  Written by Keisuke Nishida, Roger While, Simon Sobisch, Ron Norman
4 
5  This file is part of GnuCOBOL.
6 
7  The GnuCOBOL runtime library is free software: you can redistribute it
8  and/or modify it under the terms of the GNU Lesser General Public License
9  as published by the Freecob_freetware Foundation, either version 3 of the
10  License, or (at your option) any later version.
11 
12  GnuCOBOL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GnuCOBOL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 
22 #include "config.h"
23 
24 #define _LFS64_LARGEFILE 1
25 #define _LFS64_STDIO 1
26 #define _FILE_OFFSET_BITS 64
27 #define _LARGEFILE64_SOURCE 1
28 #ifdef _AIX
29 #define _LARGE_FILES 1
30 #endif /* _AIX */
31 #if defined(__hpux__) && !defined(__LP64__)
32 #define _APP32_64BIT_OFF_T 1
33 #endif
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stddef.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <errno.h>
42 #include <time.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49 
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
53 
54 #ifdef _WIN32
55 
56 #define WIN32_LEAN_AND_MEAN
57 #include <windows.h>
58 #include <direct.h>
59 #include <io.h>
60 #ifndef __WATCOMC__
61 #define fdcobsync _commit
62 #else
63 #define fdcobsync fsync
64 #endif
65 #if !defined(__BORLANDC__) && !defined(__WATCOMC__)
66 #define getcwd _getcwd
67 #define chdir _chdir
68 #define mkdir _mkdir
69 #define rmdir _rmdir
70 #define open _open
71 #define close _close
72 #define unlink _unlink
73 #define fdopen _fdopen
74 #define lseek _lseeki64
75 #endif
76 #define off_t cob_s64_t
77 
78 #ifndef _O_TEMPORARY
79 #define _O_TEMPORARY 0
80 #endif
81 
82 #else
83 #if defined(HAVE_FDATASYNC)
84 #define fdcobsync fdatasync
85 #else
86 #define fdcobsync fsync
87 #endif
88 
89 #ifndef O_BINARY
90 #define O_BINARY 0
91 #endif
92 
93 #endif
94 
95 /* Force symbol exports */
96 #define COB_LIB_EXPIMP
97 
98 #include "libcob.h"
99 #include "coblocal.h"
100 
101 #ifdef WITH_DB
102 
103 #include <db.h>
104 
105 #elif defined(WITH_CISAM) || defined(WITH_DISAM) || defined(WITH_VBISAM)
106 
107 #define WITH_ANY_ISAM
108 #include <signal.h>
109 
110 #define COB_WITH_STATUS_02
111 
112 #ifdef WITH_CISAM
113 #include <isam.h>
114 #define isfullclose(x) isclose (x)
115 #endif
116 
117 #ifdef WITH_DISAM
118 #include <disam.h>
119 #define isfullclose(x) isclose (x)
120 #endif
121 
122 #ifdef WITH_VBISAM
123 #include <vbisam.h>
124 #if 1 /* RXWRXW - Status 02 */
125 #undef COB_WITH_STATUS_02
126 #endif
127 #endif
128 
129 /* Isam File handler packet */
130 
131 struct indexfile {
132  char *filename; /* ISAM data file name */
133  char *savekey; /* Area to save last primary key read */
134  char *recwrk; /* Record work/save area */
135  size_t nkeys; /* Actual keys in file */
136  int isfd; /* ISAM file number */
137  int recnum; /* Last record number read */
138  int saverecnum; /* isrecnum of next record to process */
139  int saveerrno; /* savefileposition errno */
140  int lmode; /* File lock mode for 'isread' */
141  int curkey; /* Current active index */
142  int startcond; /* Previous 'start' condition value */
143  int readdir; /* Read direction: ISPREV or ISNEXT */
144  int lenkey; /* Length of savekey area */
145  int eofpending; /* End of file pending */
146  int readdone; /* A 'read' has been succesfully done */
147  int startiscur; /* The 'start' record is current */
148  int wrkhasrec; /* 'recwrk' holds the next|prev record */
149  struct keydesc key[1]; /* Table of key information */
150  /* keydesc is defined in (d|c|vb)isam.h */
151 };
152 
153 #endif
154 
155 struct file_list {
156  struct file_list *next;
158 };
159 
160 #ifdef WORDS_BIGENDIAN
161 #define COB_MAYSWAP_16(x) ((unsigned short)(x))
162 #define COB_MAYSWAP_32(x) ((unsigned int)(x))
163 #else
164 #define COB_MAYSWAP_16(x) (COB_BSWAP_16((unsigned short)(x)))
165 #define COB_MAYSWAP_32(x) (COB_BSWAP_32((unsigned int)(x)))
166 #endif
167 
168 /* SORT definitions */
169 
170 #define COBSORTEND 1
171 #define COBSORTABORT 2
172 #define COBSORTFILEERR 3
173 #define COBSORTNOTOPEN 4
174 
175 
176 /* Sort item */
177 struct cobitem {
178  struct cobitem *next;
179  unsigned char end_of_block;
180  unsigned char block_byte;
181  unsigned char unique[sizeof(size_t)];
182  unsigned char item[1];
183 };
184 
185 /* Sort memory chunk */
188  unsigned char *mem_ptr;
189 };
190 
191 /* Sort queue structure */
192 struct queue_struct {
193  struct cobitem *first;
194  struct cobitem *last;
195  size_t count;
196 };
197 
198 /* Sort temporary file structure */
199 struct file_struct {
200  FILE *fp;
201  size_t count; /* Count of blocks in temporary files */
202 };
203 
204 /* Sort base structure */
205 struct cobsort {
206  void *pointer;
207  struct cobitem *empty;
208  void *sort_return;
211  size_t unique;
212  size_t size;
213  size_t alloc_size;
214  size_t mem_size;
215  size_t mem_used;
216  size_t mem_total;
217  size_t chunk_size;
218  size_t r_size;
219  size_t w_size;
221  unsigned int retrieving;
222  unsigned int files_used;
225  struct queue_struct queue[4];
226  struct file_struct file[4];
227 };
228 
229 /* End SORT definitions */
230 
231 
232 /* Local variables */
233 
236 
237 static unsigned int eop_status;
238 static unsigned int check_eop_status;
239 static size_t cob_vsq_len;
240 
241 static struct file_list *file_cache;
242 
243 static char *file_open_env;
244 static char *file_open_name;
245 static char *file_open_buff;
246 
247 static char *runtime_buffer;
248 
249 static const int status_exception[] = {
250  0, /* 0x */
251  COB_EC_I_O_AT_END, /* 1x */
252  COB_EC_I_O_INVALID_KEY, /* 2x */
254  COB_EC_I_O_LOGIC_ERROR, /* 4x */
256  COB_EC_I_O_FILE_SHARING, /* 6x */
257  COB_EC_I_O, /* Unused */
258  COB_EC_I_O, /* Unused */
259  COB_EC_I_O_IMP /* 9x */
260 };
261 
262 static const char * const prefix[] = { "DD_", "dd_", "" };
263 #define NUM_PREFIX sizeof(prefix) / sizeof(char *)
264 
265 static int dummy_delete (cob_file *);
266 static int dummy_rnxt_rewrite (cob_file *, const int);
267 static int dummy_read (cob_file *, cob_field *, const int);
268 static int dummy_start (cob_file *, const int, cob_field *);
269 
270 static int cob_file_open (cob_file *, char *, const int, const int);
271 static int cob_file_close (cob_file *, const int);
272 static int cob_file_write_opt (cob_file *, const int);
273 
274 static int sequential_read (cob_file *, const int);
275 static int sequential_write (cob_file *, const int);
276 static int sequential_rewrite (cob_file *, const int);
277 static int lineseq_read (cob_file *, const int);
278 static int lineseq_write (cob_file *, const int);
279 static int relative_start (cob_file *, const int, cob_field *);
280 static int relative_read (cob_file *, cob_field *, const int);
281 static int relative_read_next (cob_file *, const int);
282 static int relative_write (cob_file *, const int);
283 static int relative_rewrite (cob_file *, const int);
284 static int relative_delete (cob_file *);
285 
286 static int indexed_open (cob_file *, char *, const int, const int);
287 static int indexed_close (cob_file *, const int);
288 static int indexed_start (cob_file *, const int, cob_field *);
289 static int indexed_read (cob_file *, cob_field *, const int);
290 static int indexed_read_next (cob_file *, const int);
291 static int indexed_write (cob_file *, const int);
292 static int indexed_delete (cob_file *);
293 static int indexed_rewrite (cob_file *, const int);
294 
295 static const struct cob_fileio_funcs indexed_funcs = {
296  indexed_open,
299  indexed_read,
304 };
305 
306 static const struct cob_fileio_funcs sequential_funcs = {
309  dummy_start,
310  dummy_read,
315 };
316 
317 static const struct cob_fileio_funcs lineseq_funcs = {
320  dummy_start,
321  dummy_read,
322  lineseq_read,
326 };
327 
328 static const struct cob_fileio_funcs relative_funcs = {
337 };
338 
339 static const struct cob_fileio_funcs *fileio_funcs[COB_ORG_MAX] = {
341  &lineseq_funcs,
343  &indexed_funcs,
344  NULL
345 };
346 
347 #if defined(WITH_INDEX_EXTFH) || defined(WITH_SEQRA_EXTFH)
348 extern void extfh_cob_init_fileio (const struct cob_fileio_funcs *,
349  const struct cob_fileio_funcs *,
350  const struct cob_fileio_funcs *,
351  int (*)(cob_file *, const int));
352 extern void extfh_cob_exit_fileio (void);
353 #endif
354 
355 #ifdef WITH_INDEX_EXTFH
356 extern void extfh_indexed_unlock (cob_file *);
357 extern int extfh_indexed_locate (cob_file *, char *);
358 extern int extfh_indexed_open (cob_file *, char *, const int, const int);
359 extern int extfh_indexed_close (cob_file *, const int);
360 extern int extfh_indexed_start (cob_file *, const int, cob_field *);
361 extern int extfh_indexed_read (cob_file *, cob_field *, const int);
362 extern int extfh_indexed_read_next (cob_file *, const int);
363 extern int extfh_indexed_write (cob_file *, const int);
364 extern int extfh_indexed_delete (cob_file *);
365 extern int extfh_indexed_rewrite (cob_file *, const int);
366 #endif
367 
368 #ifdef WITH_SEQRA_EXTFH
369 extern void extfh_seqra_unlock (cob_file *);
370 extern int extfh_seqra_locate (cob_file *, char *);
371 extern int extfh_cob_file_open (cob_file *, char *, const int, const int);
372 extern int extfh_cob_file_close (cob_file *, const int);
373 extern int extfh_sequential_read (cob_file *, const int);
374 extern int extfh_sequential_write (cob_file *, const int);
375 extern int extfh_sequential_rewrite (cob_file *, const int);
376 extern int extfh_relative_start (cob_file *, const int, cob_field *);
377 extern int extfh_relative_read (cob_file *, cob_field *, const int);
378 extern int extfh_relative_read_next (cob_file *, const int);
379 extern int extfh_relative_write (cob_file *, const int);
380 extern int extfh_relative_rewrite (cob_file *, const int);
381 extern int extfh_relative_delete (cob_file *);
382 #endif
383 
384 #ifdef WITH_DB
385 
386 static DB_ENV *bdb_env;
387 static char *bdb_buff;
388 static const char **bdb_data_dir;
389 static void *record_lock_object;
390 static size_t rlo_size;
391 static unsigned int bdb_lock_id;
392 
393 #define DB_PUT(db,flags) db->put (db, NULL, &p->key, &p->data, flags)
394 #define DB_GET(db,flags) db->get (db, NULL, &p->key, &p->data, flags)
395 #define DB_SEQ(db,flags) db->c_get (db, &p->key, &p->data, flags)
396 #define DB_DEL(db,key,flags) db->del (db, NULL, key, flags)
397 #define DB_CLOSE(db) db->close (db, 0)
398 #define DB_SYNC(db) db->sync (db, 0)
399 #define cob_dbtsize_t u_int32_t
400 
401 #define DBT_SET(key,fld) \
402  key.data = fld->data; \
403  key.size = (cob_dbtsize_t) fld->size
404 
405 struct indexed_file {
406  DB **db; /* Database handlers */
407  DBC **cursor;
408  char *filename; /* Needed for record locks */
409  unsigned char *last_key; /* The last key written */
410  unsigned char *temp_key; /* Used for temporary storage */
411  unsigned char **last_readkey; /* The last key read */
412  unsigned int *last_dupno; /* The last number of duplicates read */
413  int *rewrite_sec_key;
414  DBT key;
415  DBT data;
416  DB_LOCK bdb_file_lock;
417  DB_LOCK bdb_record_lock;
418  size_t key_index;
419  unsigned int bdb_lock_id;
420  int write_cursor_open;
421  int record_locked;
422  int filenamelen;
423 };
424 
425 #endif /* WITH_DB */
426 
427 
428 /* Local functions */
429 
430 static int
432 {
433  COB_UNUSED (f);
434 
436 }
437 
438 static int
439 dummy_rnxt_rewrite (cob_file *f, const int opt)
440 {
441  COB_UNUSED (f);
442  COB_UNUSED (opt);
443 
445 }
446 
447 static int
448 dummy_read (cob_file *f, cob_field *key, const int read_opts)
449 {
450  COB_UNUSED (f);
451  COB_UNUSED (key);
452  COB_UNUSED (read_opts);
453 
455 }
456 
457 static int
458 dummy_start (cob_file *f, const int cond, cob_field *key)
459 {
460  COB_UNUSED (f);
461  COB_UNUSED (cond);
462  COB_UNUSED (key);
463 
465 }
466 
467 static char *
468 cob_chk_file_env (const char *src)
469 {
470  char *p;
471  char *q;
472  char *s;
473  size_t i;
474 
475  if (unlikely(cobsetptr->cob_env_mangle)) {
476  q = cob_strdup (src);
477  s = q;
478  for (i = 0; i < strlen (s); ++i) {
479  if (!isalnum ((int)s[i])) {
480  s[i] = '_';
481  }
482  }
483  } else {
484  q = NULL;
485  s = (char *)src;
486  }
487  p = NULL;
488  for (i = 0; i < NUM_PREFIX; ++i) {
489  snprintf (file_open_env, (size_t)COB_FILE_MAX, "%s%s",
490  prefix[i], s);
492  p = getenv (file_open_env);
493  if (p) {
494  break;
495  }
496  }
497  if (unlikely(q)) {
498  cob_free (q);
499  }
500  return p;
501 }
502 
503 static void
505 {
506  char *p;
507  char *src;
508  char *dst;
509  char *saveptr;
510  char *orig;
511  unsigned int dollar;
512 
513  if (unlikely(!COB_MODULE_PTR->flag_filename_mapping)) {
514  return;
515  }
516 
517  /* Misuse "dollar" here to indicate a separator */
518  dollar = 0;
519  for (p = file_open_name; *p; p++) {
520  if (*p == '/' || *p == '\\') {
521  dollar = 1;
522  break;
523  }
524  }
525 
526  src = file_open_name;
527 
528  /* Simple case - No separators */
529  if (likely(dollar == 0)) {
530  /* Ignore leading dollar */
531  if (*src == '$') {
532  src++;
533  }
534  /* Check for DD_xx, dd_xx, xx environment variables */
535  /* If not found, use as is including the dollar character */
536  if ((p = cob_chk_file_env (src)) != NULL) {
537  strncpy (file_open_name, p, (size_t)COB_FILE_MAX);
538  } else if (cobsetptr->cob_file_path) {
539  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s%c%s",
542  strncpy (file_open_name, file_open_buff,
543  (size_t)COB_FILE_MAX);
544  }
545  return;
546  }
547 
548  /* Complex */
549  /* Isolate first element (everything before the slash) */
550  /* If it starts with a slash, it's absolute, do nothing */
551  /* Else if it starts with a $, mark and skip over the $ */
552  /* Try mapping on resultant string - DD_xx, dd_xx, xx */
553  /* If successful, use the mapping */
554  /* If not, use original element EXCEPT if we started */
555  /* with a $, in which case, we ignore the element AND */
556  /* the following slash */
557 
558  dollar = 0;
559  dst = file_open_buff;
560  *dst = 0;
561 
562  if (*src == '$') {
563  dollar = 1;
564  src++;
565  }
566 
567  orig = cob_strdup (src);
568  saveptr = orig;
569 
570  /* strtok strips leading delimiters */
571  if (*src == '/' || *src == '\\') {
572  strcpy (file_open_buff, SLASH_STR);
573  } else {
575  p = strtok (orig, "/\\");
576  orig = NULL;
577  if ((src = cob_chk_file_env (p)) != NULL) {
578  strncpy (file_open_buff, src, (size_t)COB_FILE_MAX);
579  dollar = 0;
580  } else if (!dollar) {
581  strncpy (file_open_buff, p, (size_t)COB_FILE_MAX);
582  }
583  }
584  /* First element completed, loop through remaining */
585  /* elements delimited by slash */
586  /* Check each for $ mapping */
587  for (; ;) {
588  p = strtok (orig, "/\\");
589  if (!p) {
590  break;
591  }
592  if (!orig) {
593  if (dollar) {
594  dollar = 0;
595  } else {
596  strcat (file_open_buff, SLASH_STR);
597  }
598  } else {
599  orig = NULL;
600  }
601  if (*p == '$' && (src = cob_chk_file_env (p + 1)) != NULL) {
602  strncat (file_open_buff, src, (size_t)COB_FILE_MAX);
603  } else {
604  strncat (file_open_buff, p, (size_t)COB_FILE_MAX);
605  }
606  }
607  strcpy (file_open_name, file_open_buff);
608  cob_free (saveptr);
609 }
610 
611 static void
613 {
614 #ifdef WITH_DB
615  struct indexed_file *p;
616  size_t i;
617 #elif defined(WITH_ANY_ISAM)
618  struct indexfile *fh;
619 #endif
620 
621  if (f->organization == COB_ORG_INDEXED) {
622 #ifdef WITH_DB
623  p = f->file;
624  if (p) {
625  for (i = 0; i < f->nkeys; ++i) {
626  if (p->db[i]) {
627  DB_SYNC (p->db[i]);
628  }
629  }
630  }
631 #elif defined(WITH_ANY_ISAM)
632  fh = f->file;
633  if (fh) {
634  isflush (fh->isfd);
635  }
636 #endif
637  return;
638  }
639  if (f->organization != COB_ORG_SORT) {
641  if (f->file) {
642  fflush ((FILE *)f->file);
643  }
644  }
645  if (f->fd >= 0) {
646  fdcobsync (f->fd);
647  }
648  }
649 }
650 
651 static void
653 {
654  struct file_list *l;
655 
656  for (l = file_cache; l; l = l->next) {
657  if (f == l->file) {
658  return;
659  }
660  }
661  l = cob_malloc (sizeof (struct file_list));
662  l->file = f;
663  l->next = file_cache;
664  file_cache = l;
665 }
666 
667 static void
668 save_status (cob_file *f, cob_field *fnstatus, const int status)
669 {
670  cobglobptr->cob_error_file = f;
671  if (likely(status == 0)) {
672  memset (f->file_status, '0', (size_t)2);
673  if (fnstatus) {
674  memset (fnstatus->data, '0', (size_t)2);
675  }
676  /* EOP is non-fatal therefore 00 status but needs exception */
677  if (unlikely(eop_status)) {
678  eop_status = 0;
680  } else {
681  cob_set_exception (0);
682  }
683  if (unlikely(cobsetptr->cob_do_sync)) {
684  cob_sync (f);
685  }
686  return;
687  }
688  cob_set_exception (status_exception[status / 10]);
689  f->file_status[0] = (unsigned char)COB_I2D (status / 10);
690  f->file_status[1] = (unsigned char)COB_I2D (status % 10);
691  if (fnstatus) {
692  memcpy (fnstatus->data, f->file_status, (size_t)2);
693  }
694 }
695 
696 /* Regular file */
697 
698 static size_t
700 {
701  cob_linage *lingptr;
702 
703  lingptr = f->linorkeyptr;
704  lingptr->lin_lines = cob_get_int (lingptr->linage);
705  if (lingptr->lin_lines < 1) {
706  goto linerr;
707  }
708  if (lingptr->latfoot) {
709  lingptr->lin_foot = cob_get_int (lingptr->latfoot);
710  if (lingptr->lin_foot < 1 ||
711  lingptr->lin_foot > lingptr->lin_lines) {
712  goto linerr;
713  }
714  } else {
715  lingptr->lin_foot = 0;
716  }
717  if (lingptr->lattop) {
718  lingptr->lin_top = cob_get_int (lingptr->lattop);
719  if (lingptr->lin_top < 0) {
720  goto linerr;
721  }
722  } else {
723  lingptr->lin_top = 0;
724  }
725  if (lingptr->latbot) {
726  lingptr->lin_bot = cob_get_int (lingptr->latbot);
727  if (lingptr->lin_bot < 0) {
728  goto linerr;
729  }
730  } else {
731  lingptr->lin_bot = 0;
732  }
733  return 0;
734 linerr:
735  cob_set_int (lingptr->linage_ctr, 0);
736  return 1;
737 }
738 
739 static int
740 cob_linage_write_opt (cob_file *f, const int opt)
741 {
742  cob_linage *lingptr;
743  FILE *fp;
744  int i;
745  int n;
746 
747  fp = (FILE *)f->file;
748  lingptr = f->linorkeyptr;
749  if (unlikely(opt & COB_WRITE_PAGE)) {
750  i = cob_get_int (lingptr->linage_ctr);
751  if (i == 0) {
753  }
754  n = lingptr->lin_lines;
755  for (; i < n; ++i) {
756  putc ('\n', fp);
757  }
758  for (i = 0; i < lingptr->lin_bot; ++i) {
759  putc ('\n', fp);
760  }
761  if (file_linage_check (f)) {
763  }
764  for (i = 0; i < lingptr->lin_top; ++i) {
765  putc ('\n', fp);
766  }
767  cob_set_int (lingptr->linage_ctr, 1);
768  } else if (opt & COB_WRITE_LINES) {
769  n = cob_get_int (lingptr->linage_ctr);
770  if (n == 0) {
772  }
773  cob_add_int (lingptr->linage_ctr, opt & COB_WRITE_MASK, 0);
774  i = cob_get_int (lingptr->linage_ctr);
775  /* Set EOP status if requested */
776  if (check_eop_status && lingptr->lin_foot) {
777  if (i >= lingptr->lin_foot) {
778  eop_status = 1;
779  }
780  }
781  if (i > lingptr->lin_lines) {
782  /* Set EOP status if requested */
783  if (check_eop_status) {
784  eop_status = 1;
785  }
786  for (; n < lingptr->lin_lines; ++n) {
787  putc ('\n', fp);
788  }
789  for (i = 0; i < lingptr->lin_bot; ++i) {
790  putc ('\n', fp);
791  }
792  if (file_linage_check (f)) {
794  }
795  cob_set_int (lingptr->linage_ctr, 1);
796  for (i = 0; i < lingptr->lin_top; ++i) {
797  putc ('\n', fp);
798  }
799  } else {
800  for (i = (opt & COB_WRITE_MASK) - 1; i > 0; --i) {
801  putc ('\n', fp);
802  }
803  }
804  }
805  return 0;
806 }
807 
808 static unsigned int
809 cob_seq_write_opt (cob_file *f, const int opt)
810 {
811  int i;
812 
813  if (opt & COB_WRITE_LINES) {
814  i = opt & COB_WRITE_MASK;
815  if (!i) {
816  /* AFTER/BEFORE 0 */
817  if (write (f->fd, "\r", (size_t)1) != 1) {
818  return 1;
819  }
820  } else {
821  for (i = opt & COB_WRITE_MASK; i > 0; --i) {
822  if (write (f->fd, "\n", (size_t)1) != 1) {
823  return 1;
824  }
825  }
826  }
827  } else if (opt & COB_WRITE_PAGE) {
828  if (write (f->fd, "\f", (size_t)1) != 1) {
829  return 1;
830  }
831  }
832  return 0;
833 }
834 
835 static int
836 cob_file_write_opt (cob_file *f, const int opt)
837 {
838  int i;
839 
841  return cob_linage_write_opt (f, opt);
842  }
843  if (opt & COB_WRITE_LINES) {
844  i = opt & COB_WRITE_MASK;
845  if (!i) {
846  /* AFTER/BEFORE 0 */
847  putc (0x0d, (FILE *)f->file);
848  } else {
849  for (; i > 0; --i) {
850  putc ('\n', (FILE *)f->file);
851  }
852  }
853  } else if (opt & COB_WRITE_PAGE) {
854  putc ('\f', (FILE *)f->file);
855  }
856  return 0;
857 }
858 
859 static int
860 cob_fd_file_open (cob_file *f, char *filename, const int mode, const int sharing)
861 {
862  int fd;
863  int fdmode;
864  int fperms;
865  unsigned int nonexistent;
866 #ifdef HAVE_FCNTL
867  int ret;
868  struct flock lock;
869 #endif
870 
871  /* Note filename points to file_open_name */
872  /* cob_chk_file_mapping manipulates file_open_name directly */
873 
874  COB_UNUSED (sharing);
875 
877 
878  nonexistent = 0;
879  errno = 0;
880  if (access (filename, F_OK) && errno == ENOENT) {
881  if (mode != COB_OPEN_OUTPUT && f->flag_optional == 0) {
883  }
884  nonexistent = 1;
885  }
886 
887  fdmode = O_BINARY;
888  fperms = 0;
889  f->fd = -1;
890  switch (mode) {
891  case COB_OPEN_INPUT:
892  fdmode |= O_RDONLY;
893  break;
894  case COB_OPEN_OUTPUT:
895  nonexistent = 0;
896  fdmode |= O_CREAT | O_TRUNC;
897  if (f->organization == COB_ORG_RELATIVE) {
898  fdmode |= O_RDWR;
899  } else {
900  fdmode |= O_WRONLY;
901  }
902 #ifdef _WIN32
903  fperms = _S_IREAD | _S_IWRITE ;
904 #else
905  fperms = COB_FILE_MODE;
906 #endif
907  break;
908  case COB_OPEN_I_O:
909  if (nonexistent) {
910  fdmode |= O_CREAT | O_RDWR;
911 #ifdef _WIN32
912  fperms = _S_IREAD | _S_IWRITE ;
913 #else
914  fperms = COB_FILE_MODE;
915 #endif
916  } else {
917  fdmode |= O_RDWR;
918  }
919  break;
920  case COB_OPEN_EXTEND:
921  fdmode |= O_CREAT | O_RDWR | O_APPEND;
922 #ifdef _WIN32
923  fperms = _S_IREAD | _S_IWRITE ;
924 #else
925  fperms = COB_FILE_MODE;
926 #endif
927  break;
928  }
929 
930  errno = 0;
931  fd = open (filename, fdmode, fperms);
932 
933  switch (errno) {
934  case 0:
935  if (mode == COB_OPEN_EXTEND && fd >= 0) {
936  lseek (fd, (off_t) 0, SEEK_END);
937  }
938  f->open_mode = mode;
939  break;
940  case ENOENT:
941  if (mode == COB_OPEN_EXTEND || mode == COB_OPEN_OUTPUT) {
943  }
944  if (f->flag_optional) {
945  f->open_mode = mode;
946  f->flag_nonexistent = 1;
947  f->flag_end_of_file = 1;
948  f->flag_begin_of_file = 1;
950  }
952  case EACCES:
953  case EISDIR:
954  case EROFS:
956  case EAGAIN:
958  default:
960  }
961  f->fd = fd;
962 
963 #ifdef HAVE_FCNTL
964  /* Lock the file */
965  if (memcmp (filename, "/dev/", (size_t)5)) {
966  memset ((void *)&lock, 0, sizeof (struct flock));
967  if (mode != COB_OPEN_INPUT) {
968  lock.l_type = F_WRLCK;
969  } else {
970  lock.l_type = F_RDLCK;
971  }
972  lock.l_whence = SEEK_SET;
973  lock.l_start = 0;
974  lock.l_len = 0;
975  errno = 0;
976  if (fcntl (fd, F_SETLK, &lock) < 0) {
977  ret = errno;
978  close (fd);
979  f->fd = -1;
980  switch (ret) {
981  case EACCES:
982  case EAGAIN:
983  case EDEADLK:
985  default:
987  }
988  }
989  }
990 #endif
991  if (f->flag_optional && nonexistent) {
993  }
994  return 0;
995 }
996 
997 static int
998 cob_file_open (cob_file *f, char *filename, const int mode, const int sharing)
999 {
1000  /* Note filename points to file_open_name */
1001  /* cob_chk_file_mapping manipulates file_open_name directly */
1002 
1003 #ifdef WITH_SEQRA_EXTFH
1004  int ret;
1005 
1006  ret = extfh_seqra_locate (f, filename);
1007  switch (ret) {
1008  case COB_NOT_CONFIGURED:
1010  if (access (filename, F_OK) && errno == ENOENT) {
1011  if (mode != COB_OPEN_OUTPUT && f->flag_optional == 0) {
1012  return COB_STATUS_35_NOT_EXISTS;
1013  }
1014  }
1015  break;
1016  case COB_STATUS_00_SUCCESS:
1017  break;
1018  default:
1019  return ret;
1020  }
1021  ret = extfh_cob_file_open (f, filename, mode, sharing);
1022  switch (ret) {
1023  case COB_STATUS_00_SUCCESS:
1024  f->open_mode = mode;
1025  break;
1027  if (f->flag_optional) {
1028  f->open_mode = mode;
1029  f->flag_nonexistent = 1;
1030  f->flag_end_of_file = 1;
1031  f->flag_begin_of_file = 1;
1033  }
1034  break;
1035  }
1036  return ret;
1037 
1038 #else
1039 
1040  FILE *fp;
1041  const char *fmode;
1042  cob_linage *lingptr;
1043 #ifdef HAVE_FCNTL
1044  int ret;
1045  struct flock lock;
1046 #endif
1047  unsigned int nonexistent;
1048 
1050  return cob_fd_file_open (f, filename, mode, sharing);
1051  }
1052 
1054 
1055  nonexistent = 0;
1056  errno = 0;
1057  if (access (filename, F_OK) && errno == ENOENT) {
1058  nonexistent = 1;
1059  if (mode != COB_OPEN_OUTPUT && f->flag_optional == 0) {
1060  return COB_STATUS_35_NOT_EXISTS;
1061  }
1062  }
1063 
1064  fp = NULL;
1065  fmode = NULL;
1066  /* Open the file */
1067  switch (mode) {
1068  case COB_OPEN_INPUT:
1069  if (!cobsetptr->cob_unix_lf) {
1070  fmode = "r";
1071  } else {
1072  fmode = "rb";
1073  }
1074  break;
1075  case COB_OPEN_OUTPUT:
1076  if (!cobsetptr->cob_unix_lf) {
1077  fmode = "w";
1078  } else {
1079  fmode = "wb";
1080  }
1081  break;
1082  case COB_OPEN_I_O:
1084  case COB_OPEN_EXTEND:
1085  /* Problem with VC (tested MSC_VER 15) if file isn't there: */
1086  /* Both modes create the file and return a bad pointer */
1087  /* Mode "a+" sets EINVAL, further actions on the file do work */
1088  /* Mode "ab+" doesn't set errno, but we dont want a binary file */
1089  /* Possible Solutions: */
1090  /* a) Create the file and reopen it with a+ */
1091  /* b) Check this stuff in EINVAL and just go on */
1092  if (!cobsetptr->cob_unix_lf) {
1093  fmode = "a+";
1094  } else {
1095  fmode = "ab+";
1096  }
1097  break;
1098  default:
1100  }
1101 
1102  errno = 0;
1103  fp = fopen (filename, fmode);
1104  switch (errno) {
1105  case 0:
1106  f->open_mode = mode;
1107  break;
1108  case EINVAL:
1109  if (f->flag_optional && nonexistent) {
1110  f->open_mode = mode;
1111  } else {
1113  }
1114  break;
1115  case ENOENT:
1116  if (mode == COB_OPEN_EXTEND || mode == COB_OPEN_OUTPUT) {
1118  }
1119  if (f->flag_optional) {
1120  f->open_mode = mode;
1121  f->flag_nonexistent = 1;
1122  f->flag_end_of_file = 1;
1123  f->flag_begin_of_file = 1;
1125  }
1126  return COB_STATUS_35_NOT_EXISTS;
1127  case EACCES:
1128  case EISDIR:
1129  case EROFS:
1131  case EAGAIN:
1133  default:
1135  }
1136 
1138  if (file_linage_check (f)) {
1139  fclose (fp);
1140  return COB_STATUS_57_I_O_LINAGE;
1141  }
1142  f->flag_needs_top = 1;
1143  lingptr = f->linorkeyptr;
1144  cob_set_int (lingptr->linage_ctr, 1);
1145  }
1146  f->file = fp;
1147  f->fd = fileno (fp);
1148 
1149 #ifdef HAVE_FCNTL
1150  /* Lock the file */
1151  if (memcmp (filename, "/dev/", (size_t)5)) {
1152  memset ((void *)&lock, 0, sizeof (struct flock));
1153  if (mode != COB_OPEN_INPUT) {
1154  lock.l_type = F_WRLCK;
1155  } else {
1156  lock.l_type = F_RDLCK;
1157  }
1158  lock.l_whence = SEEK_SET;
1159  lock.l_start = 0;
1160  lock.l_len = 0;
1161  if (fcntl (fileno (fp), F_SETLK, &lock) < 0) {
1162  ret = errno;
1163  fclose (fp);
1164  switch (ret) {
1165  case EACCES:
1166  case EAGAIN:
1167  case EDEADLK:
1169  default:
1171  }
1172  }
1173  }
1174 #endif
1175  if (f->flag_optional && nonexistent) {
1177  }
1178  return 0;
1179 
1180 #endif
1181 }
1182 
1183 static int
1184 cob_file_close (cob_file *f, const int opt)
1185 {
1186 #ifdef WITH_SEQRA_EXTFH
1187  return extfh_cob_file_close (f, opt);
1188 #else
1189 
1190 #ifdef HAVE_FCNTL
1191  struct flock lock;
1192 #endif
1193 
1194  switch (opt) {
1195  case COB_CLOSE_NORMAL:
1196  case COB_CLOSE_LOCK:
1197  case COB_CLOSE_NO_REWIND:
1199  if (f->flag_needs_nl &&
1201  f->flag_needs_nl = 0;
1202  putc ('\n', (FILE *)f->file);
1203  }
1204  } else if (f->flag_needs_nl) {
1205  f->flag_needs_nl = 0;
1206  if (f->fd >= 0) {
1207  if (write (f->fd, "\n", (size_t)1) != 1) {
1208  }
1209  }
1210  }
1211 #ifdef HAVE_FCNTL
1212  /* Unlock the file */
1213  memset ((void *)&lock, 0, sizeof (struct flock));
1214  lock.l_type = F_UNLCK;
1215  lock.l_whence = SEEK_SET;
1216  lock.l_start = 0;
1217  lock.l_len = 0;
1218  if (f->fd >= 0) {
1219  fcntl (f->fd, F_SETLK, &lock);
1220  }
1221 #endif
1222  /* Close the file */
1224  if (f->file) {
1225  fclose ((FILE *)f->file);
1226  }
1227  } else {
1228  if (f->fd >= 0) {
1229  close (f->fd);
1230  }
1231  }
1232  if (opt == COB_CLOSE_NO_REWIND) {
1235  }
1236  return COB_STATUS_00_SUCCESS;
1237  default:
1238  if (f->fd >= 0 && f->open_mode != COB_OPEN_INPUT) {
1239  fdcobsync (f->fd);
1240  }
1242  }
1243 #endif
1244 }
1245 
1246 /* SEQUENTIAL */
1247 
1248 static int
1249 sequential_read (cob_file *f, const int read_opts)
1250 {
1251  int bytesread;
1252  union {
1253  unsigned char sbuff[4];
1254  unsigned short sshort[2];
1255  unsigned int sint;
1256  } recsize;
1257 
1258 #ifdef WITH_SEQRA_EXTFH
1259  int extfh_ret;
1260 
1261  extfh_ret = extfh_sequential_read (f, read_opts);
1262  if (extfh_ret != COB_NOT_CONFIGURED) {
1263  return extfh_ret;
1264  }
1265 #else
1266  COB_UNUSED (read_opts);
1267 #endif
1268 
1269  if (unlikely(f->flag_operation != 0)) {
1270  f->flag_operation = 0;
1271  lseek (f->fd, (off_t)0, SEEK_CUR);
1272  }
1273 
1274  if (unlikely(f->record_min != f->record_max)) {
1275  /* Read record size */
1276 
1277  bytesread = read (f->fd, recsize.sbuff, cob_vsq_len);
1278  if (unlikely (bytesread != (int)cob_vsq_len)) {
1279  if (bytesread == 0) {
1281  } else {
1283  }
1284  }
1285  switch (cobsetptr->cob_varseq_type) {
1286  case 1:
1287  f->record->size = COB_MAYSWAP_32 (recsize.sint);
1288  break;
1289  case 2:
1290  f->record->size = recsize.sint;
1291  break;
1292  default:
1293  f->record->size = COB_MAYSWAP_16 (recsize.sshort[0]);
1294  break;
1295  }
1296  }
1297 
1298  /* Read record */
1299  bytesread = read (f->fd, f->record->data, f->record->size);
1300  if (unlikely(bytesread != (int)f->record->size)) {
1301  if (bytesread == 0) {
1303  } else if (bytesread < 0) {
1305  } else {
1307  }
1308  }
1309  return COB_STATUS_00_SUCCESS;
1310 }
1311 
1312 static int
1313 sequential_write (cob_file *f, const int opt)
1314 {
1315  union {
1316  unsigned char sbuff[4];
1317  unsigned short sshort[2];
1318  unsigned int sint;
1319  } recsize;
1320 
1321 #ifdef WITH_SEQRA_EXTFH
1322  int extfh_ret;
1323 
1324  extfh_ret = extfh_sequential_write (f, opt);
1325  if (extfh_ret != COB_NOT_CONFIGURED) {
1326  return extfh_ret;
1327  }
1328 #endif
1329 
1330  if (unlikely(f->flag_operation == 0)) {
1331  f->flag_operation = 1;
1332  lseek (f->fd, (off_t)0, SEEK_CUR);
1333  }
1334 
1335  /* WRITE AFTER */
1336  if (unlikely(opt & COB_WRITE_AFTER)) {
1337  if (cob_seq_write_opt (f, opt)) {
1339  }
1340  f->flag_needs_nl = 1;
1341  }
1342 
1343  if (unlikely(f->record_min != f->record_max)) {
1344  /* Write record size */
1345 
1346  switch (cobsetptr->cob_varseq_type) {
1347  case 1:
1348  recsize.sint = COB_MAYSWAP_32 (f->record->size);
1349  break;
1350  case 2:
1351  recsize.sint = f->record->size;
1352  break;
1353  default:
1354  recsize.sint = 0;
1355  recsize.sshort[0] = COB_MAYSWAP_16 (f->record->size);
1356  break;
1357  }
1358 
1359  if (unlikely(write (f->fd, recsize.sbuff, cob_vsq_len) !=
1360  (int)cob_vsq_len)) {
1362  }
1363  }
1364 
1365  /* Write record */
1366  if (unlikely(write (f->fd, f->record->data, f->record->size) !=
1367  (int)f->record->size)) {
1369  }
1370 
1371  /* WRITE BEFORE */
1372  if (unlikely(opt & COB_WRITE_BEFORE)) {
1373  if (cob_seq_write_opt (f, opt)) {
1375  }
1376  f->flag_needs_nl = 0;
1377  }
1378 
1379  return COB_STATUS_00_SUCCESS;
1380 }
1381 
1382 static int
1383 sequential_rewrite (cob_file *f, const int opt)
1384 {
1385 #ifdef WITH_SEQRA_EXTFH
1386  int extfh_ret;
1387 
1388  extfh_ret = extfh_sequential_rewrite (f, opt);
1389  if (extfh_ret != COB_NOT_CONFIGURED) {
1390  return extfh_ret;
1391  }
1392 #else
1393  COB_UNUSED (opt);
1394 #endif
1395  f->flag_operation = 1;
1396  if (lseek (f->fd, -(off_t) f->record->size, SEEK_CUR) == (off_t)-1) {
1398  }
1399  if (write (f->fd, f->record->data, f->record->size) != (int)f->record->size) {
1401  }
1402  return COB_STATUS_00_SUCCESS;
1403 }
1404 
1405 /* LINE SEQUENTIAL */
1406 
1407 static int
1408 lineseq_read (cob_file *f, const int read_opts)
1409 {
1410  unsigned char *dataptr;
1411  size_t i = 0;
1412  int n;
1413 
1414 #ifdef WITH_SEQRA_EXTFH
1415  int extfh_ret;
1416 
1417  extfh_ret = extfh_sequential_read (f, read_opts);
1418  if (extfh_ret != COB_NOT_CONFIGURED) {
1419  return extfh_ret;
1420  }
1421 #else
1422  COB_UNUSED (read_opts);
1423 #endif
1424 
1425  dataptr = f->record->data;
1426  for (; ;) {
1427  n = getc ((FILE *)f->file);
1428  if (unlikely(n == EOF)) {
1429  if (!i) {
1431  } else {
1432  break;
1433  }
1434  }
1435  if (unlikely(n == 0 && cobsetptr->cob_ls_nulls != 0)) {
1436  n = getc ((FILE *)f->file);
1437  if (n == EOF) {
1439  }
1440  } else {
1441  if (n == '\r') {
1442  continue;
1443  }
1444  if (n == '\n') {
1445  break;
1446  }
1447  }
1448  if (likely(i < f->record_max)) {
1449  *dataptr++ = (unsigned char)n;
1450  i++;
1451  }
1452  }
1453  if (i < f->record_max) {
1454  /* Fill the record with spaces */
1455  memset ((unsigned char *)f->record->data + i, ' ',
1456  f->record_max - i);
1457  }
1458  f->record->size = i;
1459  return COB_STATUS_00_SUCCESS;
1460 }
1461 
1462 static int
1463 lineseq_write (cob_file *f, const int opt)
1464 {
1465  unsigned char *p;
1466  cob_linage *lingptr;
1467  size_t size;
1468  int i;
1469  int ret;
1470 
1471 #ifdef WITH_SEQRA_EXTFH
1472  int extfh_ret;
1473 
1474  extfh_ret = extfh_sequential_write (f, opt);
1475  if (extfh_ret != COB_NOT_CONFIGURED) {
1476  return extfh_ret;
1477  }
1478 #endif
1479 
1480  /* Determine the size to be written */
1481  if (unlikely(cobsetptr->cob_ls_fixed != 0)) {
1482  size = f->record->size;
1483  } else {
1484  for (i = (int)f->record->size - 1; i >= 0; --i) {
1485  if (f->record->data[i] != ' ') {
1486  break;
1487  }
1488  }
1489  size = i + 1;
1490  }
1491 
1493  if (f->flag_needs_top) {
1494  f->flag_needs_top = 0;
1495  lingptr = f->linorkeyptr;
1496  for (i = 0; i < lingptr->lin_top; ++i) {
1497  putc ('\n', (FILE *)f->file);
1498  }
1499  }
1500  }
1501  /* WRITE AFTER */
1502  if (opt & COB_WRITE_AFTER) {
1503  ret = cob_file_write_opt (f, opt);
1504  if (ret) {
1505  return ret;
1506  }
1507  f->flag_needs_nl = 1;
1508  }
1509 
1510  /* Write to the file */
1511  if (size) {
1512  if (unlikely(cobsetptr->cob_ls_nulls != 0)) {
1513  p = f->record->data;
1514  for (i = 0; i < (int)size; ++i, ++p) {
1515  if (*p < ' ') {
1516  putc (0, (FILE *)f->file);
1517  }
1518  putc ((int)(*p), (FILE *)f->file);
1519  }
1520  } else {
1521  if (unlikely(fwrite (f->record->data, size, (size_t)1,
1522  (FILE *)f->file) != 1)) {
1524  }
1525  }
1526  }
1527 
1529  putc ('\n', (FILE *)f->file);
1530  } else if (cobsetptr->cob_ls_uses_cr) {
1531  if (opt & COB_WRITE_PAGE) {
1532  putc ('\r', (FILE *)f->file);
1533  } else if ((opt & COB_WRITE_BEFORE) && f->flag_needs_nl) {
1534  putc ('\r', (FILE *)f->file);
1535  }
1536  }
1537 
1538  /* WRITE BEFORE */
1539  if (opt & COB_WRITE_BEFORE) {
1540  ret = cob_file_write_opt (f, opt);
1541  if (ret) {
1542  return ret;
1543  }
1544  f->flag_needs_nl = 0;
1545  }
1546 
1547  return COB_STATUS_00_SUCCESS;
1548 }
1549 
1550 /* RELATIVE */
1551 
1552 static int
1553 relative_start (cob_file *f, const int cond, cob_field *k)
1554 {
1555  off_t off;
1556  size_t relsize;
1557  int kindex;
1558  int ksindex;
1559  int kcond;
1560  struct stat st;
1561 
1562 #ifdef WITH_SEQRA_EXTFH
1563  int extfh_ret;
1564 
1565  extfh_ret = extfh_relative_start (f, cond, k);
1566  if (extfh_ret != COB_NOT_CONFIGURED) {
1567  return extfh_ret;
1568  }
1569 #endif
1570 
1571  if (fstat (f->fd, &st) != 0 || st.st_size == 0) {
1573  }
1574 
1575  relsize = f->record_max + sizeof (f->record->size);
1576 
1577  /* Get the index */
1578  switch (cond) {
1579  case COB_FI:
1580  kcond = COB_GE;
1581  kindex = 0;
1582  break;
1583  case COB_LA:
1584  kcond = COB_LE;
1585  kindex = st.st_size / relsize;
1586  kindex--;
1587  break;
1588  case COB_LT:
1589  case COB_LE:
1590  kcond = cond;
1591  kindex = cob_get_int (k) - 1;
1592  /* Check against current file size */
1593  ksindex = st.st_size / relsize;
1594  ksindex--;
1595  if (kindex > ksindex) {
1596  kindex = ksindex;
1597  if (cond == COB_LT) {
1598  /* Cater for decrement below */
1599  kindex++;
1600  }
1601  }
1602  break;
1603  default:
1604  kcond = cond;
1605  kindex = cob_get_int (k) - 1;
1606  break;
1607  }
1608 
1609  if (kindex < 0) {
1610  /* Only valid ops are GE and GT in this case */
1611  switch (kcond) {
1612  case COB_GE:
1613  kindex = 0;
1614  break;
1615  case COB_GT:
1616  /* Set to cater for increment below */
1617  kindex = -1;
1618  break;
1619  default:
1621  }
1622  }
1623 
1624  if (kcond == COB_LT) {
1625  kindex--;
1626  if (kindex < 0) {
1628  }
1629  } else if (kcond == COB_GT) {
1630  kindex++;
1631  }
1632 
1633  f->flag_operation = 0;
1634 
1635  /* Seek index */
1636  for (;;) {
1637  if (kindex < 0) {
1638  break;
1639  }
1640  off = kindex * relsize;
1641  if (off >= st.st_size) {
1642  break;
1643  }
1644  if (lseek (f->fd, off, SEEK_SET) == (off_t)-1) {
1645  break;
1646  }
1647 
1648  /* Check if a valid record */
1649  if (read (f->fd, &f->record->size, sizeof (f->record->size))
1650  == sizeof (f->record->size) && f->record->size > 0) {
1651 #if 0 /* RXWRXW - Set key - COBOL standards */
1652  cob_set_int (k, kindex + 1);
1653 #endif
1654  lseek (f->fd, off, SEEK_SET);
1655  return COB_STATUS_00_SUCCESS;
1656  }
1657 
1658  switch (kcond) {
1659  case COB_EQ:
1661  case COB_LT:
1662  case COB_LE:
1663  kindex--;
1664  break;
1665  case COB_GT:
1666  case COB_GE:
1667  kindex++;
1668  break;
1669  }
1670  }
1672 }
1673 
1674 static int
1675 relative_read (cob_file *f, cob_field *k, const int read_opts)
1676 {
1677  off_t off;
1678  size_t relsize;
1679  int relnum;
1680 #ifdef WITH_SEQRA_EXTFH
1681  int extfh_ret;
1682 
1683  extfh_ret = extfh_relative_read (f, k, read_opts);
1684  if (extfh_ret != COB_NOT_CONFIGURED) {
1685  return extfh_ret;
1686  }
1687 #else
1688  COB_UNUSED (read_opts);
1689 #endif
1690 
1691  if (unlikely(f->flag_operation != 0)) {
1692  f->flag_operation = 0;
1693  lseek (f->fd, (off_t)0, SEEK_CUR);
1694  }
1695 
1696  relnum = cob_get_int (k) - 1;
1697  if (relnum < 0) {
1699  }
1700  relsize = f->record_max + sizeof (f->record->size);
1701  off = relnum * relsize;
1702  if (lseek (f->fd, off, SEEK_SET) == (off_t)-1 ||
1703  read (f->fd, &f->record->size, sizeof (f->record->size))
1704  != sizeof (f->record->size)) {
1706  }
1707 
1708  if (f->record->size == 0) {
1709  lseek (f->fd, off, SEEK_SET);
1711  }
1712 
1713  if (read (f->fd, f->record->data, f->record_max) != (int)f->record_max) {
1715  }
1716  return COB_STATUS_00_SUCCESS;
1717 }
1718 
1719 static int
1720 relative_read_next (cob_file *f, const int read_opts)
1721 {
1722  off_t curroff;
1723  cob_s64_t relsize;
1724  int relnum;
1725  int bytesread;
1726  cob_u32_t moveback;
1727  struct stat st;
1728 
1729 #ifdef WITH_SEQRA_EXTFH
1730  int extfh_ret;
1731 
1732  extfh_ret = extfh_relative_read_next (f, read_opts);
1733  if (extfh_ret != COB_NOT_CONFIGURED) {
1734  return extfh_ret;
1735  }
1736 #endif
1737 
1738  if (unlikely(f->flag_operation != 0)) {
1739  f->flag_operation = 0;
1740  lseek (f->fd, (off_t)0, SEEK_CUR);
1741  }
1742 
1743  relsize = f->record_max + sizeof (f->record->size);
1744  if (fstat (f->fd, &st) != 0 || st.st_size == 0) {
1746  }
1747  if (st.st_size < relsize) {
1749  }
1750 
1751  curroff = lseek (f->fd, (off_t)0, SEEK_CUR);
1752  moveback = 0;
1753 
1754  switch (read_opts & COB_READ_MASK) {
1755  case COB_READ_FIRST:
1756  curroff = lseek (f->fd, (off_t)0, SEEK_SET);
1757  break;
1758  case COB_READ_LAST:
1759  curroff = st.st_size - relsize;
1760  curroff = lseek (f->fd, curroff, SEEK_SET);
1761  moveback = 1;
1762  break;
1763  case COB_READ_PREVIOUS:
1764  if (f->flag_first_read) {
1765  break;
1766  } else if (curroff > relsize) {
1767  curroff -= (relsize * 2);
1768  curroff = lseek (f->fd, curroff, SEEK_SET);
1769  } else {
1771  }
1772  moveback = 1;
1773  break;
1774  case COB_READ_NEXT:
1775  default:
1776  break;
1777  }
1778 
1779  for (;;) {
1780  bytesread = read (f->fd, &f->record->size, sizeof (f->record->size));
1781  if (bytesread != sizeof (f->record->size)) {
1782  if (bytesread != 0) {
1784  } else {
1785  break;
1786  }
1787  }
1788 
1789  if (f->record->size > 0) {
1790  if (read (f->fd, f->record->data, f->record_max) != (int)f->record_max) {
1792  }
1793  if (f->keys[0].field) {
1794  relnum = (int)((curroff / relsize) + 1);
1795  cob_set_int (f->keys[0].field, 0);
1796  if (cob_add_int (f->keys[0].field, relnum,
1798  lseek (f->fd, curroff, SEEK_SET);
1800  }
1801  }
1802  if (moveback) {
1803  curroff -= relsize;
1804  curroff = lseek (f->fd, curroff, SEEK_SET);
1805  }
1806  return COB_STATUS_00_SUCCESS;
1807  }
1808  if (moveback) {
1809  if (curroff > relsize) {
1810  curroff -= (relsize * 2);
1811  curroff = lseek (f->fd, curroff, SEEK_SET);
1812  } else {
1813  break;
1814  }
1815  } else {
1816  curroff = lseek (f->fd, (off_t) f->record_max, SEEK_CUR);
1817  }
1818  }
1820 }
1821 
1822 static int
1823 relative_write (cob_file *f, const int opt)
1824 {
1825  off_t off;
1826  size_t size;
1827  size_t relsize;
1828  int i;
1829  int kindex;
1830 #ifdef WITH_SEQRA_EXTFH
1831  int extfh_ret;
1832 
1833  extfh_ret = extfh_relative_write (f, opt);
1834  if (extfh_ret != COB_NOT_CONFIGURED) {
1835  return extfh_ret;
1836  }
1837 #else
1838  COB_UNUSED (opt);
1839 #endif
1840 
1841  if (unlikely(f->flag_operation == 0)) {
1842  f->flag_operation = 1;
1843  lseek (f->fd, (off_t)0, SEEK_CUR);
1844  }
1845 
1846  relsize = f->record_max + sizeof (f->record->size);
1847  if (f->access_mode != COB_ACCESS_SEQUENTIAL) {
1848  kindex = cob_get_int (f->keys[0].field) - 1;
1849  if (kindex < 0) {
1851  }
1852  off = (off_t) (relsize * kindex);
1853  if (lseek (f->fd, off, SEEK_SET) == (off_t)-1) {
1855  }
1856  if (read (f->fd, &size, sizeof (size)) > 0) {
1857  if (size > 0) {
1858  return COB_STATUS_22_KEY_EXISTS;
1859  }
1860  }
1861  } else {
1862  off = lseek (f->fd, (off_t)0, SEEK_CUR);
1863  }
1864  lseek (f->fd, off, SEEK_SET);
1865 
1866  if (write (f->fd, &f->record->size, sizeof (f->record->size)) != sizeof (f->record->size)) {
1868  }
1869  if (write (f->fd, f->record->data, f->record_max) != (int)f->record_max) {
1871  }
1872 
1873  /* Update RELATIVE KEY */
1874  if (f->access_mode == COB_ACCESS_SEQUENTIAL) {
1875  if (f->keys[0].field) {
1876  off += relsize;
1877  i = (int)(off / relsize);
1878  cob_set_int (f->keys[0].field, i);
1879  }
1880  }
1881 
1882  return COB_STATUS_00_SUCCESS;
1883 }
1884 
1885 static int
1886 relative_rewrite (cob_file *f, const int opt)
1887 {
1888  off_t off;
1889  size_t relsize;
1890  int relnum;
1891 #ifdef WITH_SEQRA_EXTFH
1892  int extfh_ret;
1893 
1894  extfh_ret = extfh_relative_rewrite (f, opt);
1895  if (extfh_ret != COB_NOT_CONFIGURED) {
1896  return extfh_ret;
1897  }
1898 #else
1899  COB_UNUSED (opt);
1900 #endif
1901 
1902  f->flag_operation = 1;
1903  if (f->access_mode == COB_ACCESS_SEQUENTIAL) {
1904  lseek (f->fd, -(off_t) f->record_max, SEEK_CUR);
1905  } else {
1906  relsize = f->record_max + sizeof (f->record->size);
1907  relnum = cob_get_int (f->keys[0].field) - 1;
1908  if (relnum < 0) {
1910  }
1911  off = relnum * relsize;
1912  if (lseek (f->fd, off, SEEK_SET) == (off_t)-1 ||
1913  read (f->fd, &f->record->size, sizeof (f->record->size))
1914  != sizeof (f->record->size)) {
1916  }
1917  lseek (f->fd, (off_t)0, SEEK_CUR);
1918  }
1919 
1920  if (write (f->fd, f->record->data, f->record_max) != (int)f->record_max) {
1922  }
1923  return COB_STATUS_00_SUCCESS;
1924 }
1925 
1926 static int
1928 {
1929  off_t off;
1930  size_t relsize;
1931  int relnum;
1932 #ifdef WITH_SEQRA_EXTFH
1933  int extfh_ret;
1934 
1935  extfh_ret = extfh_relative_delete (f);
1936  if (extfh_ret != COB_NOT_CONFIGURED) {
1937  return extfh_ret;
1938  }
1939 #endif
1940 
1941  f->flag_operation = 1;
1942  relnum = cob_get_int (f->keys[0].field) - 1;
1943  if (relnum < 0) {
1945  }
1946  relsize = f->record_max + sizeof (f->record->size);
1947  off = relnum * relsize;
1948  if (lseek (f->fd, off, SEEK_SET) == (off_t)-1 ||
1949  read (f->fd, &f->record->size, sizeof (f->record->size))
1950  != sizeof (f->record->size)) {
1952  }
1953  lseek (f->fd, off, SEEK_SET);
1954 
1955  f->record->size = 0;
1956  if (write (f->fd, &f->record->size, sizeof (f->record->size)) != sizeof (f->record->size)) {
1958  }
1959  lseek (f->fd, (off_t) f->record_max, SEEK_CUR);
1960  return COB_STATUS_00_SUCCESS;
1961 }
1962 
1963 /* INDEXED */
1964 
1965 #ifdef WITH_ANY_ISAM
1966 
1967 static int
1968 fisretsts (const int dfltsts)
1969 {
1970  /* Translate ISAM status to COBOL status */
1971  switch (iserrno) {
1972  case 0:
1973  return COB_STATUS_00_SUCCESS;
1974  case ENOREC:
1976  case EENDFILE:
1977  if (dfltsts != COB_STATUS_23_KEY_NOT_EXISTS) {
1979  }
1980  break;
1981  case EDUPL:
1982  case EKEXISTS:
1983  return COB_STATUS_22_KEY_EXISTS;
1984  case EPERM:
1985  case EACCES:
1986  case EISDIR:
1988  case ENOENT:
1989  return COB_STATUS_35_NOT_EXISTS;
1990  case EBADFILE:
1992  case ELOCKED:
1994  case EFLOCKED:
1996  case ENOCURR:
1997  if (dfltsts != COB_STATUS_10_END_OF_FILE) {
1999  }
2000  break;
2001  default:
2002  break;
2003  }
2004  return dfltsts;
2005 }
2006 
2007 /* Free memory for indexfile packet */
2008 
2009 static void
2010 freefh (struct indexfile *fh)
2011 {
2012  if (fh == NULL) {
2013  return;
2014  }
2015  if (fh->filename) {
2016  cob_free ((void *)fh->filename);
2017  }
2018  if (fh->savekey) {
2019  cob_free ((void *)fh->savekey);
2020  }
2021  if (fh->recwrk) {
2022  cob_free ((void *)fh->recwrk);
2023  }
2024  cob_free ((void *)fh);
2025 }
2026 
2027 /* Restore ISAM file positioning */
2028 static void
2029 restorefileposition (cob_file *f)
2030 {
2031  struct indexfile *fh;
2032  struct keydesc k0;
2033 
2034  fh = f->file;
2035  memset ((void *)&k0, 0, sizeof(k0));
2036  if (fh->saverecnum >= 0) {
2037  /* Switch back to index */
2038  isrecnum = fh->saverecnum;
2039  /* Switch to recnum mode */
2040  isstart (fh->isfd, &k0, 0, (void *)fh->recwrk, ISEQUAL);
2041  /* Read by record number */
2042  isread (fh->isfd, (void *)fh->recwrk, ISEQUAL);
2043  isstart (fh->isfd, &fh->key[fh->curkey], 0,
2044  (void *)fh->recwrk, ISEQUAL);
2045  isread (fh->isfd, (void *)fh->recwrk, ISEQUAL);
2046  while (isrecnum != fh->saverecnum) {
2047  /* Read back into position */
2048  if (isread (fh->isfd, (void *)fh->recwrk, fh->readdir)) {
2049  break;
2050  }
2051  }
2052  if (isrecnum == fh->saverecnum) {
2053  if (fh->readdir == ISNEXT) {
2054  /* Back off by one so next read gets this */
2055  isread (fh->isfd, (void *)fh->recwrk, ISPREV);
2056  } else {
2057  isread (fh->isfd, (void *)fh->recwrk, ISNEXT);
2058  }
2059  }
2060  } else if (fh->readdone && fh->curkey == 0) {
2061  memcpy (fh->recwrk + fh->key[0].k_start,
2062  fh->savekey, (size_t)fh->key[0].k_leng);
2063  isstart (fh->isfd, &fh->key[fh->curkey], 0,
2064  (void *)fh->recwrk, ISGTEQ);
2065  }
2066 }
2067 
2068 /* Save ISAM file positioning information for later 'restorefileposition' */
2069 
2070 static void
2071 savefileposition (cob_file *f)
2072 {
2073  struct indexfile *fh;
2074 
2075  fh = f->file;
2076  if (fh->curkey >= 0 && fh->readdir != -1) {
2077  /* Switch back to index */
2078  if (fh->wrkhasrec != fh->readdir) {
2079  fh->eofpending = 0;
2080  fh->wrkhasrec = 0;
2081  /* Read next record in file */
2082  if (isread (fh->isfd, (void *)fh->recwrk, fh->readdir)) {
2083  fh->saverecnum = -1;
2084  fh->saveerrno = iserrno;
2085  if (fh->saveerrno == EENDFILE ||
2086  fh->saveerrno == ENOREC) {
2087  fh->eofpending = fh->readdir;
2088  }
2089  } else {
2090  fh->saverecnum = isrecnum;
2091  fh->saveerrno = 0;
2092  }
2093  /* Restore saved record data */
2094  memcpy (fh->recwrk, f->record->data, f->record_max);
2095  }
2096  } else {
2097  fh->saverecnum = -1;
2098  }
2099 }
2100 #endif /* WITH_ANY_ISAM */
2101 
2102 #ifdef WITH_DB
2103 
2104 #if 0 /* RXWRXW - BDB msg */
2105 static void
2106 bdb_msgcall_set (DB_ENV *dbe, const char *err)
2107 {
2108  COB_UNUSED (dbe);
2109 
2110  cob_runtime_error (_("BDB error: %s"), err);
2111  cob_stop_run (1);
2112 }
2113 
2114 static void
2115 bdb_errcall_set (DB_ENV *dbe, const char *prefix, const char *err)
2116 {
2117  COB_UNUSED (dbe);
2118 
2119  cob_runtime_error (_("BDB error: %s %s"), prefix, err);
2120  cob_stop_run (1);
2121 }
2122 #endif
2123 
2124 static void
2125 join_environment (void)
2126 {
2127  cob_u32_t flags;
2128  int ret;
2129 
2130  if (cobsetptr->bdb_home == NULL) {
2131  return;
2132  }
2133  ret = db_env_create (&bdb_env, 0);
2134  if (ret) {
2135  cob_runtime_error (_("Cannot join BDB environment (%s), error: %d %s"),
2136  "env_create", ret, db_strerror (ret));
2137  cob_stop_run (1);
2138  }
2139 #if 0 /* RXWRXW - BDB msg */
2140  bdb_env->set_errcall (bdb_env, bdb_errcall_set);
2141 #if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR > 2))
2142  bdb_env->set_msgcall (bdb_env, bdb_msgcall_set);
2143 #endif
2144 #else
2145  bdb_env->set_errfile (bdb_env, stderr);
2146 #if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR > 2))
2147  bdb_env->set_msgfile (bdb_env, stderr);
2148 #endif
2149 #endif
2150  bdb_env->set_cachesize (bdb_env, 0, 2*1024*1024, 0);
2151  bdb_env->set_alloc (bdb_env, cob_malloc, realloc, cob_free);
2152  flags = DB_CREATE | DB_INIT_MPOOL | DB_INIT_CDB;
2153  ret = bdb_env->open (bdb_env, cobsetptr->bdb_home, flags, 0);
2154  if (ret) {
2155  cob_runtime_error (_("Cannot join BDB environment (%s), error: %d %s"),
2156  "env->open", ret, db_strerror (ret));
2157  bdb_env->close (bdb_env, 0);
2158  bdb_env = NULL;
2159  cob_stop_run (1);
2160  }
2161 #if (DB_VERSION_MAJOR > 4) || ((DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR > 1))
2162  bdb_env->get_data_dirs (bdb_env, &bdb_data_dir);
2163 #endif
2164  bdb_env->lock_id (bdb_env, &bdb_lock_id);
2165 }
2166 
2167 static int
2168 lock_record (cob_file *f, const char *key, const unsigned int keylen)
2169 {
2170  struct indexed_file *p;
2171  size_t len;
2172  int ret;
2173  DBT dbt;
2174 
2175  p = f->file;
2176  len = keylen + p->filenamelen + 1;
2177  if (len > rlo_size) {
2178  cob_free (record_lock_object);
2179  record_lock_object = cob_malloc (len);
2180  rlo_size = len;
2181  }
2182  memcpy ((char *)record_lock_object, p->filename,
2183  (size_t)(p->filenamelen + 1));
2184  memcpy ((char *)record_lock_object + p->filenamelen + 1, key,
2185  (size_t)keylen);
2186  dbt.size = (cob_dbtsize_t) len;
2187  dbt.data = record_lock_object;
2188  ret = bdb_env->lock_get (bdb_env, p->bdb_lock_id, DB_LOCK_NOWAIT,
2189  &dbt, DB_LOCK_WRITE, &p->bdb_record_lock);
2190  if (!ret) {
2191  p->record_locked = 1;
2192  }
2193  return ret;
2194 }
2195 
2196 static int
2197 test_record_lock (cob_file *f, const char *key, const unsigned int keylen)
2198 {
2199  struct indexed_file *p;
2200  size_t len;
2201  int ret;
2202  DBT dbt;
2203  DB_LOCK test_lock;
2204 
2205  p = f->file;
2206  len = keylen + p->filenamelen + 1;
2207  if (len > rlo_size) {
2208  cob_free (record_lock_object);
2209  record_lock_object = cob_malloc (len);
2210  rlo_size = len;
2211  }
2212  memcpy ((char *)record_lock_object, p->filename,
2213  (size_t)(p->filenamelen + 1));
2214  memcpy ((char *)record_lock_object + p->filenamelen + 1, key,
2215  (size_t)keylen);
2216  dbt.size = (cob_dbtsize_t) len;
2217  dbt.data = record_lock_object;
2218  ret = bdb_env->lock_get (bdb_env, p->bdb_lock_id, DB_LOCK_NOWAIT,
2219  &dbt, DB_LOCK_WRITE, &test_lock);
2220  if (!ret) {
2221  bdb_env->lock_put (bdb_env, &test_lock);
2222  }
2223  return ret;
2224 }
2225 
2226 static int
2227 unlock_record (cob_file *f)
2228 {
2229  struct indexed_file *p;
2230  int ret;
2231 
2232  p = f->file;
2233  if (p->record_locked == 0) {
2234  return 0;
2235  }
2236  ret = bdb_env->lock_put (bdb_env, &p->bdb_record_lock);
2237  p->record_locked = 0;
2238  return ret;
2239 }
2240 
2241 /* Get the next number in a set of duplicates */
2242 static unsigned int
2243 get_dupno (cob_file *f, const cob_u32_t i)
2244 {
2245  struct indexed_file *p;
2246  int ret;
2247  unsigned int dupno;
2248 
2249  p = f->file;
2250  dupno = 0;
2251  DBT_SET (p->key, f->keys[i].field);
2252  memcpy (p->temp_key, p->key.data, (size_t)p->key.size);
2253  p->db[i]->cursor (p->db[i], NULL, &p->cursor[i], 0);
2254  ret = DB_SEQ (p->cursor[i], DB_SET_RANGE);
2255  while (ret == 0 && memcmp (p->key.data, p->temp_key, (size_t)p->key.size) == 0) {
2256  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size,
2257  sizeof(unsigned int));
2258  ret = DB_SEQ (p->cursor[i], DB_NEXT);
2259  }
2260  p->cursor[i]->c_close (p->cursor[i]);
2261  p->cursor[i] = NULL;
2262  return ++dupno;
2263 }
2264 
2265 static int
2266 check_alt_keys (cob_file *f, const int rewrite)
2267 {
2268  struct indexed_file *p;
2269  size_t i;
2270  int ret;
2271 
2272  p = f->file;
2273  for (i = 1; i < f->nkeys; ++i) {
2274  if (!f->keys[i].flag) {
2275  DBT_SET (p->key, f->keys[i].field);
2276  ret = DB_GET (p->db[i], 0);
2277  if (ret == 0) {
2278  if (rewrite) {
2279  if (memcmp (p->data.data, f->keys[0].field->data, f->keys[0].field->size)) {
2280  return 1;
2281  }
2282  } else {
2283  return 1;
2284  }
2285  }
2286  }
2287  }
2288  return 0;
2289 }
2290 
2291 static int
2292 indexed_write_internal (cob_file *f, const int rewrite, const int opt)
2293 {
2294  struct indexed_file *p;
2295  cob_u32_t i;
2296  unsigned int dupno;
2297  cob_u32_t flags;
2298  int close_cursor;
2299 
2300  p = f->file;
2301  if (bdb_env) {
2302  flags = DB_WRITECURSOR;
2303  } else {
2304  flags = 0;
2305  }
2306  if (p->write_cursor_open) {
2307  close_cursor = 0;
2308  } else {
2309  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], flags);
2310  p->write_cursor_open = 1;
2311  close_cursor = 1;
2312  }
2313 
2314  /* Check duplicate alternate keys */
2315  if (f->nkeys > 1 && !rewrite) {
2316  if (check_alt_keys (f, 0)) {
2317  if (close_cursor) {
2318  p->cursor[0]->c_close (p->cursor[0]);
2319  p->cursor[0] = NULL;
2320  p->write_cursor_open = 0;
2321  }
2322  return COB_STATUS_22_KEY_EXISTS;
2323  }
2324  DBT_SET (p->key, f->keys[0].field);
2325  }
2326 
2327  /* Write data */
2328  if (p->cursor[0]->c_get (p->cursor[0], &p->key, &p->data, DB_SET) == 0) {
2329  if (close_cursor) {
2330  p->cursor[0]->c_close (p->cursor[0]);
2331  p->cursor[0] = NULL;
2332  p->write_cursor_open = 0;
2333  }
2334  return COB_STATUS_22_KEY_EXISTS;
2335  }
2336  p->data.data = f->record->data;
2337  p->data.size = (cob_dbtsize_t) f->record->size;
2338  p->cursor[0]->c_put (p->cursor[0], &p->key, &p->data, DB_KEYFIRST);
2339 
2340  /* Write secondary keys */
2341  p->data = p->key;
2342  for (i = 1; i < f->nkeys; ++i) {
2343  if (rewrite && ! p->rewrite_sec_key[i]) {
2344  continue;
2345  }
2346  if (f->keys[i].flag) {
2347  flags = 0;
2348  dupno = get_dupno(f, i);
2349  memcpy (p->temp_key, f->keys[0].field->data,
2350  f->keys[0].field->size);
2351  memcpy (p->temp_key + f->keys[0].field->size, &dupno,
2352  sizeof(unsigned int));
2353  p->data.data = p->temp_key;
2354  p->data.size = f->keys[0].field->size + sizeof(unsigned int);;
2355  } else {
2356  flags = DB_NOOVERWRITE;
2357  }
2358 
2359  DBT_SET (p->key, f->keys[i].field);
2360  if (DB_PUT (p->db[i], flags) != 0) {
2361  if (close_cursor) {
2362  p->cursor[0]->c_close (p->cursor[0]);
2363  p->cursor[0] = NULL;
2364  p->write_cursor_open = 0;
2365  }
2366  return COB_STATUS_22_KEY_EXISTS;
2367  }
2368  }
2369 
2370  if (opt & COB_WRITE_LOCK) {
2371  if (bdb_env != NULL) {
2372  DBT_SET (p->key, f->keys[0].field);
2373  if (lock_record (f, p->key.data, p->key.size)) {
2374  if (close_cursor) {
2375  p->cursor[0]->c_close (p->cursor[0]);
2376  p->cursor[0] = NULL;
2377  p->write_cursor_open = 0;
2378  }
2380  }
2381  }
2382  }
2383  if (close_cursor) {
2384  p->cursor[0]->c_close (p->cursor[0]);
2385  p->cursor[0] = NULL;
2386  p->write_cursor_open = 0;
2387  }
2388  return COB_STATUS_00_SUCCESS;
2389 }
2390 
2391 static int
2392 indexed_start_internal (cob_file *f, const int cond, cob_field *key,
2393  const int read_opts, const int test_lock)
2394 {
2395  struct indexed_file *p;
2396  int ret;
2397  unsigned int dupno;
2398 
2399  dupno = 0;
2400  p = f->file;
2401  /* Look up for the key */
2402  for (p->key_index = 0; p->key_index < f->nkeys; p->key_index++) {
2403  if (f->keys[p->key_index].field->data == key->data) {
2404  break;
2405  }
2406  }
2407 
2408  /* Search */
2409  DBT_SET (p->key, key);
2410  /* The open cursor makes this function atomic */
2411  if (p->key_index != 0) {
2412  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], 0);
2413  }
2414  p->db[p->key_index]->cursor (p->db[p->key_index], NULL, &p->cursor[p->key_index], 0);
2415  if (cond == COB_FI) {
2416  ret = DB_SEQ (p->cursor[p->key_index], DB_FIRST);
2417  } else if (cond == COB_LA) {
2418  ret = DB_SEQ (p->cursor[p->key_index], DB_LAST);
2419  } else {
2420  ret = DB_SEQ (p->cursor[p->key_index], DB_SET_RANGE);
2421  }
2422  switch (cond) {
2423  case COB_EQ:
2424  if (ret == 0) {
2425  ret = memcmp (p->key.data, key->data, key->size);
2426  }
2427  break;
2428  case COB_LT:
2429  if (ret != 0) {
2430  ret = DB_SEQ (p->cursor[p->key_index], DB_LAST);
2431  } else {
2432  ret = DB_SEQ (p->cursor[p->key_index], DB_PREV);
2433  }
2434  break;
2435  case COB_LE:
2436  if (ret != 0) {
2437  ret = DB_SEQ (p->cursor[p->key_index], DB_LAST);
2438  } else if (memcmp (p->key.data, key->data, key->size) != 0) {
2439  ret = DB_SEQ (p->cursor[p->key_index], DB_PREV);
2440  } else if (f->keys[p->key_index].flag) {
2441  ret = DB_SEQ (p->cursor[p->key_index], DB_NEXT_NODUP);
2442  if (ret != 0) {
2443  ret = DB_SEQ (p->cursor[p->key_index], DB_LAST);
2444  } else {
2445  ret = DB_SEQ (p->cursor[p->key_index], DB_PREV);
2446  }
2447  }
2448  break;
2449  case COB_GT:
2450  while (ret == 0 && memcmp (p->key.data, key->data, key->size) == 0) {
2451  ret = DB_SEQ (p->cursor[p->key_index], DB_NEXT);
2452  }
2453  break;
2454  case COB_GE:
2455  /* nothing */
2456  break;
2457  case COB_FI:
2458  /* nothing */
2459  break;
2460  case COB_LA:
2461  /* nothing */
2462  break;
2463  }
2464 
2465  if (ret == 0 && p->key_index > 0) {
2466  /* Temporarily save alternate key */
2467  memcpy (p->temp_key, p->key.data, f->keys[p->key_index].field->size);
2468  if (f->keys[p->key_index].flag) {
2469  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
2470  }
2471  p->key.data = p->data.data;
2472  p->key.size = f->keys[0].field->size;
2473  ret = DB_GET (p->db[0], 0);
2474  }
2475 
2476  if (ret == 0 && test_lock) {
2477  if (!(read_opts & COB_READ_IGNORE_LOCK)) {
2478  ret = test_record_lock (f, p->key.data, p->key.size);
2479  if (ret) {
2480  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
2481  p->cursor[p->key_index] = NULL;
2482  if (p->key_index != 0) {
2483  p->cursor[0]->c_close (p->cursor[0]);
2484  p->cursor[0] = NULL;
2485  }
2487  }
2488  }
2489  if (read_opts & COB_READ_LOCK) {
2490  ret = lock_record (f, p->key.data, p->key.size);
2491  if (ret) {
2492  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
2493  p->cursor[p->key_index] = NULL;
2494  if (p->key_index != 0) {
2495  p->cursor[0]->c_close (p->cursor[0]);
2496  p->cursor[0] = NULL;
2497  }
2499  }
2500  }
2501  }
2502 
2503  if (ret == 0) {
2504  if (p->key_index == 0) {
2505  memcpy (p->last_readkey[0], p->key.data, f->keys[0].field->size);
2506  } else {
2507  memcpy (p->last_readkey[p->key_index],
2508  p->temp_key, f->keys[p->key_index].field->size);
2509  memcpy (p->last_readkey[p->key_index + f->nkeys], p->key.data, f->keys[0].field->size);
2510  if (f->keys[p->key_index].flag) {
2511  p->last_dupno[p->key_index] = dupno;
2512  }
2513  }
2514  }
2515 
2516  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
2517  p->cursor[p->key_index] = NULL;
2518  if (p->key_index != 0) {
2519  p->cursor[0]->c_close (p->cursor[0]);
2520  p->cursor[0] = NULL;
2521  }
2522 
2524 }
2525 
2526 static int
2527 indexed_delete_internal (cob_file *f, const int rewrite)
2528 {
2529  struct indexed_file *p;
2530  size_t i;
2531  size_t offset;
2532  DBT prim_key;
2533  int ret;
2534  cob_u32_t flags;
2535  int close_cursor;
2536 
2537  p = f->file;
2538  if (bdb_env) {
2539  flags = DB_WRITECURSOR;
2540  } else {
2541  flags = 0;
2542  }
2543  if (p->write_cursor_open) {
2544  close_cursor = 0;
2545  } else {
2546  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], flags);
2547  p->write_cursor_open = 1;
2548  close_cursor = 1;
2549  }
2550  if (bdb_env != NULL) {
2551  unlock_record (f);
2552  }
2553  /* Find the primary key */
2554  if (f->access_mode != COB_ACCESS_SEQUENTIAL) {
2555  DBT_SET (p->key, f->keys[0].field);
2556  }
2557  ret = DB_SEQ (p->cursor[0], DB_SET);
2558  if (ret != 0 && f->access_mode != COB_ACCESS_SEQUENTIAL) {
2559  if (close_cursor) {
2560  p->cursor[0]->c_close (p->cursor[0]);
2561  p->cursor[0] = NULL;
2562  p->write_cursor_open = 0;
2563  }
2565  }
2566  if (bdb_env != NULL) {
2567  ret = test_record_lock (f, p->key.data, p->key.size);
2568  if (ret) {
2569  if (close_cursor) {
2570  p->cursor[0]->c_close (p->cursor[0]);
2571  p->cursor[0] = NULL;
2572  p->write_cursor_open = 0;
2573  }
2575  }
2576  }
2577  prim_key = p->key;
2578 
2579  /* Delete the secondary keys */
2580  offset = (char *) p->data.data - (char *) f->record->data;
2581  for (i = 1; i < f->nkeys; ++i) {
2582  DBT_SET (p->key, f->keys[i].field);
2583  p->key.data = (char *)p->key.data + offset;
2584  /* rewrite: no delete if secondary key is unchanged */
2585  if (rewrite) {
2586  p->rewrite_sec_key[i] = memcmp (p->key.data, f->keys[i].field->data, (size_t)p->key.size);
2587  if (!p->rewrite_sec_key[i]) {
2588  continue;
2589  }
2590  }
2591  if (!f->keys[i].flag) {
2592  DB_DEL (p->db[i], &p->key, 0);
2593  } else {
2594  DBT sec_key = p->key;
2595 
2596  p->db[i]->cursor (p->db[i], NULL, &p->cursor[i], flags);
2597  if (DB_SEQ (p->cursor[i], DB_SET_RANGE) == 0) {
2598  while (sec_key.size == p->key.size &&
2599  memcmp (p->key.data, sec_key.data,
2600  (size_t)sec_key.size) == 0) {
2601  if (memcmp (p->data.data, prim_key.data,
2602  (size_t)prim_key.size) == 0) {
2603  p->cursor[i]->c_del (p->cursor[i], 0);
2604  }
2605  if (DB_SEQ (p->cursor[i], DB_NEXT) != 0) {
2606  break;
2607  }
2608  }
2609  }
2610  p->cursor[i]->c_close (p->cursor[i]);
2611  p->cursor[i] = NULL;
2612  }
2613  }
2614 
2615  /* Delete the record */
2616  p->cursor[0]->c_del (p->cursor[0], 0);
2617 
2618  if (close_cursor) {
2619  p->cursor[0]->c_close (p->cursor[0]);
2620  p->cursor[0] = NULL;
2621  p->write_cursor_open = 0;
2622  }
2623  return COB_STATUS_00_SUCCESS;
2624 }
2625 
2626 /* Check if a file exists in bdb data dirs */
2627 
2628 static int
2629 is_absolute (const char *filename)
2630 {
2631 #ifdef _WIN32
2632  if (filename[0] == '/' || filename[0] == '\\') {
2633  return 1;
2634  } else {
2635  if (isalpha (filename[0]) && filename[1] == ':' &&
2636  (filename[2] == '/' || filename[2] == '\\')) {
2637  return 1;
2638  } else {
2639  return 0;
2640  }
2641  }
2642 #else
2643  if (filename[0] == '/') {
2644  return 1;
2645  } else {
2646  return 0;
2647  }
2648 #endif
2649 }
2650 
2651 static int
2652 bdb_nofile (const char *filename)
2653 {
2654  cob_u32_t i;
2655 
2656  if (!bdb_env || is_absolute (filename)) {
2657  errno = 0;
2658  if (access (filename, F_OK) && errno == ENOENT) {
2659  return 1;
2660  }
2661  return 0;
2662  }
2663 
2664  for (i = 0; bdb_data_dir && bdb_data_dir[i]; ++i) {
2665  bdb_buff[COB_SMALL_MAX] = 0;
2666  if (is_absolute (bdb_data_dir[i])) {
2667  snprintf (bdb_buff, (size_t)COB_SMALL_MAX, "%s%c%s",
2668  bdb_data_dir[i], SLASH_CHAR, filename);
2669  } else {
2670  snprintf (bdb_buff, (size_t)COB_SMALL_MAX, "%s%c%s%c%s",
2671  cobsetptr->bdb_home, SLASH_CHAR, bdb_data_dir[i], SLASH_CHAR, filename);
2672  }
2673  errno = 0;
2674  if (access (bdb_buff, F_OK) == 0 || errno != ENOENT) {
2675  return 0;
2676  }
2677  }
2678  if (i == 0) {
2679  bdb_buff[COB_SMALL_MAX] = 0;
2680  snprintf (bdb_buff, (size_t)COB_SMALL_MAX, "%s%c%s",
2681  cobsetptr->bdb_home, SLASH_CHAR, filename);
2682  errno = 0;
2683  if (access (bdb_buff, F_OK) == 0 || errno != ENOENT) {
2684  return 0;
2685  }
2686  }
2687  return 1;
2688 }
2689 
2690 #endif /* WITH_DB */
2691 
2692 /* Delete file */
2693 
2694 static void
2695 indexed_file_delete (cob_file *f, const char *filename)
2696 {
2697 #ifdef WITH_ANY_ISAM
2698  COB_UNUSED (f);
2699 
2700  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s.idx", filename);
2702  unlink (file_open_buff);
2703  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s.dat", filename);
2705  unlink (file_open_buff);
2706 #elif defined(WITH_DB)
2707  size_t i;
2708 
2709  for (i = 0; i < f->nkeys; ++i) {
2710  if (i == 0) {
2711  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s",
2712  filename);
2713  } else {
2714  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s.%d",
2715  filename, (int)i);
2716  }
2718  unlink (file_open_buff);
2719  }
2720 #endif
2721 }
2722 
2723 /* OPEN INDEXED file */
2724 
2725 static int
2726 indexed_open (cob_file *f, char *filename, const int mode, const int sharing)
2727 {
2728  /* Note filename points to file_open_name */
2729  /* cob_chk_file_mapping manipulates file_open_name directly */
2730 
2731 #ifdef WITH_INDEX_EXTFH
2732  int ret;
2733 
2734  ret = extfh_indexed_locate (f, filename);
2735  switch (ret) {
2736  case COB_NOT_CONFIGURED:
2738  if (access (filename, F_OK) && errno == ENOENT) {
2739  if (mode != COB_OPEN_OUTPUT && f->flag_optional == 0) {
2740  return COB_STATUS_35_NOT_EXISTS;
2741  }
2742  }
2743  break;
2744  case COB_STATUS_00_SUCCESS:
2745  break;
2746  default:
2747  return ret;
2748  }
2749  ret = extfh_indexed_open (f, filename, mode, sharing);
2750  switch (ret) {
2751  case COB_STATUS_00_SUCCESS:
2752  f->open_mode = mode;
2753  break;
2755  if (f->flag_optional) {
2756  f->open_mode = mode;
2757  f->flag_nonexistent = 1;
2758  f->flag_end_of_file = 1;
2759  f->flag_begin_of_file = 1;
2761  }
2762  break;
2763  }
2764  return ret;
2765 
2766 #elif defined(WITH_ANY_ISAM)
2767 
2768  struct indexfile *fh;
2769  size_t k;
2770  int ret;
2771  int omode;
2772  int lmode;
2773  int vmode;
2774  int dobld;
2775  int isfd;
2776  int checkvalue;
2777  struct dictinfo di; /* Defined in (c|d|vb)isam.h */
2778 
2779  COB_UNUSED (sharing);
2780 
2782 
2783  if (mode == COB_OPEN_INPUT) {
2784  checkvalue = R_OK;
2785  } else {
2786  checkvalue = R_OK | W_OK;
2787  }
2788 
2789  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s.idx", filename);
2791  errno = 0;
2792  if (access (file_open_buff, checkvalue)) {
2793  if (!(errno == ENOENT &&
2794  (mode == COB_OPEN_OUTPUT || f->flag_optional == 1))) {
2795  switch (errno) {
2796  case ENOENT:
2797  return COB_STATUS_35_NOT_EXISTS;
2798  case EACCES:
2800  default:
2802  }
2803  }
2804  }
2805 
2806  snprintf (file_open_buff, (size_t)COB_FILE_MAX, "%s.dat", filename);
2808  errno = 0;
2809  if (access (file_open_buff, checkvalue)) {
2810  if (!(errno == ENOENT &&
2811  (mode == COB_OPEN_OUTPUT || f->flag_optional == 1))) {
2812  switch (errno) {
2813  case ENOENT:
2814  return COB_STATUS_35_NOT_EXISTS;
2815  case EACCES:
2817  default:
2819  }
2820  }
2821  }
2822 
2823  ret = COB_STATUS_00_SUCCESS;
2824  omode = 0;
2825  lmode = 0;
2826  vmode = 0;
2827  dobld = 0;
2828  isfd = -1;
2829 #ifdef ISVARLEN
2830  if (f->record_min != f->record_max) {
2831  vmode = ISVARLEN;
2832  isreclen = f->record_min;
2833  }
2834 #endif
2835  if (!f->lock_mode) {
2836  if (mode != COB_OPEN_INPUT) {
2837  lmode = ISEXCLLOCK;
2838  } else {
2839  lmode = ISMANULOCK;
2840  }
2841  } else if ((f->lock_mode & COB_FILE_EXCLUSIVE)) {
2842  lmode = ISEXCLLOCK;
2843  } else if ((f->lock_mode & COB_LOCK_AUTOMATIC) && mode != COB_OPEN_INPUT) {
2844  lmode = ISAUTOLOCK;
2845  } else {
2846  lmode = ISMANULOCK;
2847  }
2848  switch (mode) {
2849  case COB_OPEN_INPUT:
2850  omode = ISINPUT;
2851  break;
2852  case COB_OPEN_OUTPUT:
2853  lmode = ISEXCLLOCK;
2854  omode = ISOUTPUT;
2855  iserrno = 0;
2856  isfd = isopen ((void *)filename, ISINPUT | ISEXCLLOCK | vmode);
2857  if (iserrno == EFLOCKED) {
2859  } else {
2860  if (isfd >= 0) {
2861  isfullclose (isfd);
2862  }
2863  iserase ((void *)filename);
2864  }
2865  dobld = 1;
2866  break;
2867  case COB_OPEN_I_O:
2868  omode = ISINOUT;
2869  break;
2870  case COB_OPEN_EXTEND:
2871  lmode = ISEXCLLOCK;
2872  omode = ISINOUT;
2873  break;
2874  }
2875  fh = cob_malloc (sizeof(struct indexfile) +
2876  ((sizeof (struct keydesc)) * (f->nkeys + 1)));
2877  /* Copy index information */
2878  for (k = 0; k < f->nkeys; ++k) {
2879  fh->key[k].k_flags = f->keys[k].flag ? ISDUPS : ISNODUPS;
2880  fh->key[k].k_nparts = 1; /* Single field key */
2881  fh->key[k].k_start = f->keys[k].offset;
2882  fh->key[k].k_leng = f->keys[k].field->size;
2883  if (fh->lenkey < fh->key[k].k_leng) {
2884  fh->lenkey = fh->key[k].k_leng;
2885  }
2886  fh->key[k].k_type = CHARTYPE;
2887  }
2888  iserrno = 0;
2889  fh->lmode = 0;
2890  if (dobld) {
2891 dobuild:
2892  isfd = isbuild ((void *)filename, (int)f->record_max, &fh->key[0],
2893  vmode | ISINOUT | ISEXCLLOCK);
2894  } else {
2895  if (lmode == ISAUTOLOCK) {
2896  fh->lmode = ISLOCK;
2897  lmode = ISMANULOCK;
2898  }
2899  isfd = isopen ((void *)filename, omode | lmode | vmode);
2900  if (isfd < 0) {
2901  if (f->flag_optional) {
2902  if (mode == COB_OPEN_EXTEND ||
2903  mode == COB_OPEN_I_O) {
2904  dobld = 1;
2906  goto dobuild;
2907  }
2908 #if 0 /* RXWRXW - freefh */
2909  fh->isfd = isfd;
2910  fh->filename = cob_strdup (filename);
2911  /* Active index is unknown at this time */
2912  fh->curkey = -1;
2913  f->file = fh;
2914 #endif
2915  freefh (fh);
2916  f->open_mode = mode;
2917  f->flag_end_of_file = 1;
2918  f->flag_begin_of_file = 1;
2919  if (f->flag_nonexistent) {
2920  return COB_STATUS_00_SUCCESS;
2921  }
2922  f->flag_nonexistent = 1;
2924  }
2925  } else {
2926  memset(&di, 0, sizeof(di));
2927  isindexinfo (isfd, (void *)&di, 0);
2928  /* Mask off ISVARLEN */
2929  fh->nkeys = di.di_nkeys & 0x7F;
2930  if (fh->nkeys != f->nkeys) {
2932  }
2933  for (k = 0; k < fh->nkeys && !ret; ++k) {
2934  memset (&fh->key[k], 0, sizeof(struct keydesc));
2935  isindexinfo (isfd, &fh->key[k], (int)(k+1));
2936  if (fh->lenkey < fh->key[k].k_leng) {
2937  fh->lenkey = fh->key[k].k_leng;
2938  }
2939  /* Verify that COBOL keys match real ISAM keys */
2940  if (f->keys[k].flag) {
2941  if (!(fh->key[k].k_flags & ISDUPS)) {
2943  }
2944  } else {
2945  if (fh->key[k].k_flags & ISDUPS) {
2947  }
2948  }
2949  if (fh->key[k].k_nparts != 1 ||
2950  (int)fh->key[k].k_start != (int)f->keys[k].offset ||
2951  (int)fh->key[k].k_leng != (int)f->keys[k].field->size) {
2953  }
2954  }
2955  }
2956  }
2957  if (isfd < 0) {
2958  ret = fisretsts (COB_STATUS_30_PERMANENT_ERROR);
2959  freefh (fh);
2960  return ret;
2961  }
2962  if (ret > 9) {
2963  isfullclose (isfd);
2964  freefh (fh);
2965  return ret;
2966  }
2967  if (dobld) {
2968  for (k = 1; k < f->nkeys; ++k) {
2969  iserrno = 0;
2970  if (isaddindex (isfd, &fh->key[k])) {
2972  }
2973  }
2974  if (ret > 9) {
2975  isfullclose (isfd);
2976  iserase ((void *)filename);
2977  freefh (fh);
2978  return ret;
2979  }
2980  }
2981  f->file = fh;
2982  f->open_mode = mode;
2983  fh->isfd = isfd;
2984  fh->filename = cob_strdup (filename);
2985  fh->savekey = cob_malloc ((size_t)(fh->lenkey + 1));
2986  fh->recwrk = cob_malloc ((size_t)(f->record_max + 1));
2987  /* Active index is unknown at this time */
2988  fh->curkey = -1;
2989  f->flag_nonexistent = 0;
2990  f->flag_end_of_file = 0;
2991  f->flag_begin_of_file = 0;
2992  return ret;
2993 
2994 #elif defined(WITH_DB)
2995 
2996  struct indexed_file *p;
2997  size_t i;
2998  size_t j;
2999  size_t maxsize;
3000  db_lockmode_t lock_mode;
3001  int handle_created;
3002  cob_u32_t flags = 0;
3003  int ret = 0;
3004  int nonexistent;
3005 #if 0 /* RXWRXW - Access check BDB Human */
3006  int checkvalue;
3007 #endif
3008 
3009  COB_UNUSED (sharing);
3010 
3012 
3013 #if 0 /* RXWRXW - Access check BDB Human */
3014  if (mode == COB_OPEN_INPUT) {
3015  checkvalue = R_OK;
3016  } else {
3017  checkvalue = R_OK | W_OK;
3018  }
3019 #endif
3020 
3021  nonexistent = 0;
3022  if (bdb_nofile (filename)) {
3023  nonexistent = 1;
3024  if (mode != COB_OPEN_OUTPUT && f->flag_optional == 0) {
3025  return COB_STATUS_35_NOT_EXISTS;
3026  }
3027  }
3028 
3029  p = cob_malloc (sizeof (struct indexed_file));
3030  if (bdb_env != NULL) {
3031  if (mode == COB_OPEN_OUTPUT || mode == COB_OPEN_EXTEND ||
3032  (f->lock_mode & COB_FILE_EXCLUSIVE) ||
3033  (mode == COB_OPEN_I_O && !f->lock_mode)) {
3034  lock_mode = DB_LOCK_WRITE;
3035  } else {
3036  lock_mode = DB_LOCK_READ;
3037  }
3038  p->key.size = (cob_dbtsize_t) strlen (filename);
3039  p->key.data = filename;
3040  ret = bdb_env->lock_get (bdb_env, bdb_lock_id, DB_LOCK_NOWAIT,
3041  &p->key, lock_mode, &p->bdb_file_lock);
3042  if (ret) {
3043  cob_free (p);
3044  if (ret == DB_LOCK_NOTGRANTED) {
3046  } else {
3048  }
3049  }
3050  }
3051 
3052  switch (mode) {
3053  case COB_OPEN_INPUT:
3054  flags |= DB_RDONLY;
3055  break;
3056  case COB_OPEN_OUTPUT:
3057  flags |= DB_CREATE;
3058  break;
3059  case COB_OPEN_I_O:
3060  case COB_OPEN_EXTEND:
3061  flags |= DB_CREATE;
3062  break;
3063  }
3064 
3065  p->db = cob_malloc (sizeof (DB *) * f->nkeys);
3066  p->cursor = cob_malloc (sizeof (DBC *) * f->nkeys);
3067  p->filenamelen = (int) strlen (filename);
3068  p->last_readkey = cob_malloc (sizeof (unsigned char *) * 2 * f->nkeys);
3069  p->last_dupno = cob_malloc (sizeof (unsigned int) * f->nkeys);
3070  p->rewrite_sec_key = cob_malloc (sizeof (int) * f->nkeys);
3071  maxsize = 0;
3072  for (i = 0; i < f->nkeys; ++i) {
3073  if (f->keys[i].field->size > maxsize) {
3074  maxsize = f->keys[i].field->size;
3075  }
3076  }
3077  for (i = 0; i < f->nkeys; ++i) {
3078  /* File name */
3080  if (i == 0) {
3081  snprintf (runtime_buffer, (size_t)COB_FILE_MAX, "%s",
3082  filename);
3083  } else {
3084  snprintf (runtime_buffer, (size_t)COB_FILE_MAX, "%s.%d",
3085  filename, (int)i);
3086  }
3087 #if 0 /* RXWRXW - Access check BDB Human */
3088  ret = access (runtime_buffer, checkvalue);
3089  if (ret != 0) {
3090  if (errno == ENOENT &&
3091  (mode == COB_OPEN_OUTPUT || f->flag_optional == 1)) {
3092  ret = 0;
3093  /* Check here if the directory exists ? */
3094 #if 0 /* RXWRXW - Check dir */
3095  if (!directory exists) {
3096  ret = ENOENT;
3097  } else {
3098  ret = 0;
3099  }
3100 #endif
3101  } else {
3102  ret = errno;
3103  }
3104  if (ret != 0) {
3105  switch (ret) {
3106  case ENOENT:
3108  break;
3109  case EACCES:
3111  break;
3112  default:
3114  break;
3115  }
3116  /* FIXME: BDB cleanup is missing here */
3117  return ret;
3118  }
3119  }
3120 #endif
3121 
3122  /* btree info */
3123  ret = db_create (&p->db[i], bdb_env, 0);
3124  if (!ret) {
3125  handle_created = 1;
3126  if (mode == COB_OPEN_OUTPUT) {
3127  if (bdb_env) {
3128  bdb_env->dbremove (bdb_env, NULL, runtime_buffer, NULL, 0);
3129  } else {
3130  p->db[i]->remove (p->db[i], runtime_buffer, NULL, 0);
3131  ret = db_create (&p->db[i], bdb_env, 0);
3132  }
3133  }
3134  if (!ret) {
3135  if (f->keys[i].flag) {
3136  p->db[i]->set_flags (p->db[i], DB_DUP);
3137  }
3138  }
3139  } else {
3140  handle_created = 0;
3141  }
3142 
3143  /* Open db */
3144  if (!ret) {
3145  ret = p->db[i]->open (p->db[i], NULL, runtime_buffer, NULL,
3146  DB_BTREE, flags, COB_FILE_MODE);
3147  }
3148  if (ret) {
3149  for (j = 0; j < i; ++j) {
3150  DB_CLOSE (p->db[j]);
3151  }
3152  if (handle_created) {
3153  DB_CLOSE (p->db[i]);
3154  }
3155  cob_free (p->db);
3156  cob_free (p->last_readkey);
3157  cob_free (p->last_dupno);
3158  cob_free (p->cursor);
3159  if (bdb_env != NULL) {
3160  bdb_env->lock_put (bdb_env, &p->bdb_file_lock);
3161  }
3162  cob_free (p);
3163  switch (ret) {
3164  case DB_LOCK_NOTGRANTED:
3166  case ENOENT:
3167  if (mode == COB_OPEN_EXTEND ||
3168  mode == COB_OPEN_OUTPUT) {
3170  }
3171  if (f->flag_optional) {
3172  if (mode == COB_OPEN_I_O) {
3174  }
3175  f->open_mode = mode;
3176  f->flag_nonexistent = 1;
3177  f->flag_end_of_file = 1;
3178  f->flag_begin_of_file = 1;
3179  /* RXWRXW - Check directory exists? */
3181  }
3182  return COB_STATUS_35_NOT_EXISTS;
3183  default:
3185  }
3186 
3187  }
3188 
3189  p->last_readkey[i] = cob_malloc (maxsize);
3190  p->last_readkey[f->nkeys + i] = cob_malloc (maxsize);
3191  }
3192 
3193  p->temp_key = cob_malloc (maxsize + sizeof(unsigned int));
3194  f->file = p;
3195  p->key_index = 0;
3196  p->last_key = NULL;
3197 
3198  memset ((void *)&p->key, 0, sizeof (DBT));
3199  memset ((void *)&p->data, 0, sizeof (DBT));
3200  p->filename = cob_malloc (strlen (filename) + 1);
3201  strcpy (p->filename, filename);
3202  p->write_cursor_open = 0;
3203  p->record_locked = 0;
3204  if (bdb_env != NULL) {
3205  bdb_env->lock_id (bdb_env, &p->bdb_lock_id);
3206  }
3207 
3208  DBT_SET (p->key, f->keys[0].field);
3209  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], 0);
3210  ret = DB_SEQ (p->cursor[0], DB_FIRST);
3211  p->cursor[0]->c_close (p->cursor[0]);
3212  p->cursor[0] = NULL;
3213  if (!ret) {
3214  memcpy (p->last_readkey[0], p->key.data, (size_t)p->key.size);
3215  } else {
3216  p->data.data = NULL;
3217  }
3218 
3219  f->open_mode = mode;
3220  if (f->flag_optional && nonexistent) {
3222  }
3223  return 0;
3224 
3225 #else
3226 
3228 #endif
3229 }
3230 
3231 /* Close the INDEXED file */
3232 
3233 static int
3234 indexed_close (cob_file *f, const int opt)
3235 {
3236 #ifdef WITH_INDEX_EXTFH
3237 
3238  return extfh_indexed_close (f, opt);
3239 
3240 #elif defined(WITH_ANY_ISAM)
3241 
3242  struct indexfile *fh;
3243 
3244  COB_UNUSED (opt);
3245 
3246  fh = f->file;
3247  if (fh == NULL) {
3248  return COB_STATUS_00_SUCCESS;
3249  }
3250  if (fh->isfd >= 0) {
3251  isfullclose (fh->isfd);
3252  }
3253  freefh (fh);
3254  f->file = NULL;
3255  return COB_STATUS_00_SUCCESS;
3256 
3257 #elif defined(WITH_DB)
3258 
3259  struct indexed_file *p;
3260  int i;
3261 
3262  COB_UNUSED (opt);
3263 
3264  p = f->file;
3265  /* Close DB's */
3266  for (i = 0; i < (int)f->nkeys; ++i) {
3267  if (p->cursor[i]) {
3268  p->cursor[i]->c_close (p->cursor[i]);
3269  }
3270  }
3271  for (i = (int)f->nkeys - 1; i >= 0; --i) {
3272  if (p->db[i]) {
3273  DB_CLOSE (p->db[i]);
3274  }
3275  cob_free (p->last_readkey[i]);
3276  cob_free (p->last_readkey[f->nkeys + i]);
3277  }
3278 
3279  if (p->last_key) {
3280  cob_free (p->last_key);
3281  }
3282  cob_free (p->temp_key);
3283  cob_free (p->db);
3284  cob_free (p->last_readkey);
3285  cob_free (p->last_dupno);
3286  cob_free (p->rewrite_sec_key);
3287  cob_free (p->filename);
3288  cob_free (p->cursor);
3289  if (bdb_env != NULL) {
3290  unlock_record (f);
3291  bdb_env->lock_put (bdb_env, &p->bdb_file_lock);
3292  bdb_env->lock_id_free (bdb_env, p->bdb_lock_id);
3293  }
3294  cob_free (p);
3295 
3296  return COB_STATUS_00_SUCCESS;
3297 
3298 #else
3299 
3301 
3302 #endif
3303 }
3304 
3305 
3306 /* START INDEXED file with positioning */
3307 
3308 static int
3309 indexed_start (cob_file *f, const int cond, cob_field *key)
3310 {
3311 #ifdef WITH_INDEX_EXTFH
3312 
3313  return extfh_indexed_start (f, cond, key);
3314 
3315 #elif defined(WITH_ANY_ISAM)
3316 
3317  struct indexfile *fh;
3318  size_t k;
3319  int mode;
3320  int klen;
3321  int savecond;
3322 
3323  fh = f->file;
3324  f->flag_read_done = 0;
3325  f->flag_first_read = 0;
3326  fh->readdone = 0;
3327  fh->eofpending = 0;
3328  fh->startiscur = 0;
3329  fh->wrkhasrec = 0;
3330  if (f->flag_nonexistent) {
3332  }
3333  for (k = 0; k < f->nkeys; ++k) {
3334  if (f->keys[k].field->data == key->data) {
3335  break;
3336  }
3337  }
3338  /* Use size of data field; This may indicate a partial key */
3339  klen = key->size;
3340  if (klen < 1 || klen > fh->key[k].k_leng) {
3341  /* Max key length for this index */
3342  klen = fh->key[k].k_leng;
3343  }
3344  mode = ISGTEQ;
3345  fh->startiscur = 1;
3346  savecond = cond;
3347  switch (cond) {
3348  case COB_EQ:
3349  mode = ISEQUAL;
3350  fh->readdir = ISNEXT;
3351  break;
3352  case COB_GE:
3353  mode = ISGTEQ;
3354  fh->readdir = ISNEXT;
3355  break;
3356  case COB_GT:
3357  mode = ISGREAT;
3358  fh->readdir = ISNEXT;
3359  break;
3360  case COB_LE:
3361  mode = ISGTEQ;
3362  fh->readdir = ISPREV;
3363  break;
3364  case COB_LT:
3365  mode = ISGTEQ;
3366  fh->readdir = ISPREV;
3367  break;
3368  case COB_FI:
3369  mode = ISFIRST;
3370  fh->readdir = ISNEXT;
3371  break;
3372  case COB_LA:
3373  mode = ISLAST;
3374  fh->readdir = ISPREV;
3375  break;
3376  default:
3378  }
3379  if (isstart (fh->isfd, &fh->key[k], klen, (void *)f->record->data, mode)) {
3380  if (cond == COB_LE || cond == COB_LT) {
3381  if (isstart (fh->isfd, &fh->key[k], klen, (void *)f->record->data, ISLAST)) {
3382  fh->curkey = -1;
3383  fh->startcond = -1;
3384  fh->readdir = -1;
3385  fh->startiscur = 0;
3386  return fisretsts (COB_STATUS_23_KEY_NOT_EXISTS);
3387  } else {
3388  savecond = COB_LA;
3389  }
3390  } else {
3391  fh->curkey = -1;
3392  fh->startcond = -1;
3393  fh->readdir = -1;
3394  fh->startiscur = 0;
3395  return fisretsts (COB_STATUS_23_KEY_NOT_EXISTS);
3396  }
3397  }
3398  fh->startcond = savecond;
3399  memcpy (fh->savekey, f->record->data + fh->key[k].k_start,
3400  (size_t)fh->key[k].k_leng);
3401  fh->curkey = k;
3402  f->flag_end_of_file = 0;
3403  f->flag_begin_of_file = 0;
3404  f->flag_first_read = 1;
3405  return COB_STATUS_00_SUCCESS;
3406 
3407 #elif defined(WITH_DB)
3408 
3409  return indexed_start_internal (f, cond, key, 0, 0);
3410 
3411 #else
3412 
3414 #endif
3415 }
3416 
3417 /* Random READ of the INDEXED file */
3418 
3419 static int
3420 indexed_read (cob_file *f, cob_field *key, const int read_opts)
3421 {
3422 #ifdef WITH_INDEX_EXTFH
3423 
3424  return extfh_indexed_read (f, key, read_opts);
3425 
3426 #elif defined(WITH_ANY_ISAM)
3427 
3428  struct indexfile *fh;
3429  size_t k;
3430  int ret;
3431  int lmode;
3432 
3433  fh = f->file;
3434  fh->eofpending = 0;
3435  fh->startiscur = 0;
3436  fh->wrkhasrec = 0;
3437  if (f->flag_nonexistent) {
3439  }
3440  for (k = 0; k < f->nkeys; ++k) {
3441  if (f->keys[k].field->data == key->data) {
3442  break;
3443  }
3444  }
3445  if (fh->curkey != (int)k) {
3446  /* Switch to this index */
3447  isstart (fh->isfd, &fh->key[k], 0,
3448  (void *)f->record->data, ISEQUAL);
3449  fh->curkey = k;
3450  fh->wrkhasrec = 0;
3451  }
3452  fh->startcond = -1;
3453  lmode = 0;
3454  if (read_opts & COB_READ_LOCK) {
3455  lmode = ISLOCK;
3456  } else if (read_opts & COB_READ_WAIT_LOCK) {
3457  lmode = ISLCKW;
3458  } else if ((f->lock_mode & COB_LOCK_AUTOMATIC)) {
3459  if (f->open_mode != COB_OPEN_INPUT) {
3460  if (!(read_opts & COB_READ_IGNORE_LOCK)) {
3461  lmode = ISLOCK;
3462  }
3463  }
3464  }
3465 #ifdef ISSKIPLOCK
3466  if (read_opts & COB_READ_IGNORE_LOCK) {
3467  lmode = ISSKIPLOCK;
3468  }
3469 #endif
3470  if ((fh->lmode & ISLOCK) && !(f->lock_mode & COB_LOCK_MULTIPLE)) {
3471  isrelease (fh->isfd);
3472  }
3473  iserrno = 0;
3474  fh->readdir = -1;
3475  ret = COB_STATUS_00_SUCCESS;
3476  if (isread (fh->isfd, (void *)f->record->data, ISEQUAL | lmode)) {
3477  ret = fisretsts (COB_STATUS_21_KEY_INVALID);
3478  }
3479  if (unlikely(ret != 0)) {
3480  memset (fh->savekey, 0, (size_t)fh->key[0].k_leng);
3481  fh->recnum = 0;
3482  fh->readdone = 0;
3483  return ret;
3484  }
3485  f->flag_first_read = 0;
3486  f->flag_read_done = 1;
3487  fh->readdone = 1;
3488  f->flag_end_of_file = 0;
3489  f->flag_begin_of_file = 0;
3490  memcpy (fh->savekey, f->record->data + fh->key[0].k_start,
3491  (size_t)fh->key[0].k_leng);
3492  fh->recnum = isrecnum;
3493 #ifdef ISVARLEN
3494  if (f->record_min != f->record_max) {
3495  f->record->size = isreclen;
3496  }
3497 #endif
3498  return 0;
3499 
3500 #elif defined(WITH_DB)
3501 
3502  struct indexed_file *p;
3503  int ret;
3504  int bdb_opts;
3505  int test_lock;
3506 
3507  p = f->file;
3508  test_lock = 0;
3509  bdb_opts = read_opts;
3510  if (bdb_env != NULL) {
3511  if (f->open_mode != COB_OPEN_I_O ||
3512  (f->lock_mode & COB_FILE_EXCLUSIVE)) {
3513  bdb_opts &= ~COB_READ_LOCK;
3514  } else if ((f->lock_mode & COB_LOCK_AUTOMATIC) &&
3515  !(bdb_opts & COB_READ_NO_LOCK)) {
3516  bdb_opts |= COB_READ_LOCK;
3517  }
3518  unlock_record (f);
3519  test_lock = 1;
3520  } else {
3521  bdb_opts &= ~COB_READ_LOCK;
3522  }
3523 
3524  ret = indexed_start_internal (f, COB_EQ, key, bdb_opts, test_lock);
3525  if (ret != COB_STATUS_00_SUCCESS) {
3526  return ret;
3527  }
3528 
3529  f->record->size = p->data.size;
3530  memcpy (f->record->data, p->data.data, (size_t)p->data.size);
3531 
3532  return COB_STATUS_00_SUCCESS;
3533 
3534 #else
3535 
3537 #endif
3538 }
3539 
3540 /* Sequential READ of the INDEXED file */
3541 
3542 static int
3543 indexed_read_next (cob_file *f, const int read_opts)
3544 {
3545 #ifdef WITH_INDEX_EXTFH
3546 
3547  return extfh_indexed_read_next (f, read_opts);
3548 
3549 #elif defined(WITH_ANY_ISAM)
3550 
3551  struct indexfile *fh;
3552  int ret;
3553  int lmode;
3554  int domoveback;
3555 
3556  fh = f->file;
3557  ret = COB_STATUS_00_SUCCESS;
3558  lmode = 0;
3559 
3560  if (f->flag_nonexistent) {
3561  if (f->flag_first_read == 0) {
3563  }
3564  f->flag_first_read = 0;
3566  }
3567 
3568  if (fh->curkey == -1) {
3569  /* Switch to primary index */
3570  isstart (fh->isfd, &fh->key[0], 0, NULL, ISFIRST);
3571  fh->curkey = 0;
3572  fh->readdir = ISNEXT;
3573  fh->startcond = -1;
3574  fh->startiscur = 0;
3575  fh->wrkhasrec = 0;
3576  }
3577  if (read_opts & COB_READ_LOCK) {
3578  lmode = ISLOCK;
3579  } else if (read_opts & COB_READ_WAIT_LOCK) {
3580  lmode = ISLCKW;
3581  } else if ((f->lock_mode & COB_LOCK_AUTOMATIC) &&
3582  f->open_mode != COB_OPEN_INPUT) {
3583  if (!(read_opts & COB_READ_IGNORE_LOCK)) {
3584  lmode = ISLOCK;
3585  }
3586  }
3587 #ifdef ISSKIPLOCK
3588  if (read_opts & COB_READ_IGNORE_LOCK) {
3589  lmode |= ISSKIPLOCK;
3590  }
3591 #endif
3592  if ((fh->lmode & ISLOCK) && !(f->lock_mode & COB_LOCK_MULTIPLE)) {
3593  isrelease (fh->isfd);
3594  }
3595  iserrno = 0;
3596  switch (read_opts & COB_READ_MASK) {
3597  case COB_READ_NEXT:
3598  fh->readdir = ISNEXT;
3599  if (fh->eofpending == ISNEXT) {
3600  fh->eofpending = 0;
3601  fh->wrkhasrec = 0;
3603  }
3604  if (fh->startiscur) {
3605  if (fh->startcond == COB_LA) {
3606  if (isread (fh->isfd, (void *)f->record->data, ISLAST | lmode)) {
3607  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3608  }
3609  } else if (fh->startcond == COB_FI) {
3610  if (isread (fh->isfd, (void *)f->record->data, ISFIRST | lmode)) {
3611  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3612  }
3613  } else if (isread (fh->isfd, (void *)f->record->data, ISCURR)) {
3614  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3615  } else {
3616  switch (fh->startcond) {
3617  case COB_GE:
3618  domoveback = 0;
3619  while (iserrno == 0
3620  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) == 0) {
3621  isread (fh->isfd, (void *)f->record->data, ISPREV);
3622  domoveback = 1;
3623  }
3624  if (domoveback) {
3625  isread (fh->isfd, (void *)f->record->data, iserrno == 0 ? ISNEXT : ISFIRST);
3626  }
3627  break;
3628  case COB_LE:
3629  domoveback = 0;
3630  while (iserrno == 0
3631  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) == 0) {
3632  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3633  domoveback = 1;
3634  }
3635  if (domoveback) {
3636  isread (fh->isfd, (void *)f->record->data, iserrno == 0 ? ISPREV : ISLAST);
3637  }
3638  break;
3639  case COB_LT:
3640  while (iserrno == 0
3641  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) >= 0) {
3642  isread (fh->isfd, (void *)f->record->data, ISPREV);
3643  }
3644  break;
3645  case COB_GT:
3646  while (iserrno == 0
3647  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) <= 0) {
3648  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3649  }
3650  break;
3651  }
3652  if (isread (fh->isfd, (void *)f->record->data, ISCURR | lmode)) {
3653  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3654  }
3655  }
3656  fh->startcond = -1;
3657  fh->startiscur = 0;
3658  } else if (fh->wrkhasrec == ISNEXT) {
3659  memcpy (f->record->data, fh->recwrk, f->record_max);
3660  if (fh->lmode & ISLOCK) {
3661  /* Now lock 'peek ahead' record */
3662  if (isread (fh->isfd, (void *)f->record->data,
3663  ISCURR | fh->lmode)) {
3664  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3665  }
3666  }
3667  } else {
3668  if (fh->wrkhasrec == ISPREV) {
3669  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3670  fh->wrkhasrec = 0;
3671  }
3672  if (isread (fh->isfd, (void *)f->record->data, ISNEXT | lmode)) {
3673  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3674  }
3675  }
3676  break;
3677  case COB_READ_PREVIOUS:
3678  fh->readdir = ISPREV;
3679  if (fh->eofpending == ISPREV) {
3680  fh->eofpending = 0;
3681  fh->wrkhasrec = 0;
3683  }
3684  if (fh->startiscur) {
3685  if (fh->startcond == COB_FI) {
3686  if (isread (fh->isfd, (void *)f->record->data, ISFIRST | lmode)) {
3687  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3688  }
3689  } else if (fh->startcond == COB_LA) {
3690  if (isread (fh->isfd, (void *)f->record->data, ISLAST | lmode)) {
3691  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3692  }
3693  } else if (isread (fh->isfd, (void *)f->record->data, ISCURR | lmode)) {
3694  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3695  } else {
3696  switch (fh->startcond) {
3697  case COB_LE:
3698  domoveback = 0;
3699  while (iserrno == 0
3700  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) == 0) {
3701  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3702  domoveback = 1;
3703  }
3704  if (domoveback) {
3705  isread (fh->isfd, (void *)f->record->data, ISPREV);
3706  }
3707  break;
3708  case COB_LT:
3709  while (iserrno == 0
3710  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) >= 0) {
3711  isread (fh->isfd, (void *)f->record->data, ISPREV);
3712  }
3713  break;
3714  case COB_GT:
3715  while (iserrno == 0
3716  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) <= 0) {
3717  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3718  }
3719  break;
3720  case COB_GE:
3721  while (iserrno == 0
3722  && memcmp (f->record->data + fh->key[fh->curkey].k_start, fh->savekey, (size_t)fh->key[fh->curkey].k_leng) < 0) {
3723  isread (fh->isfd, (void *)f->record->data, ISNEXT);
3724  }
3725  break;
3726  }
3727  if (isread (fh->isfd, (void *)f->record->data, ISCURR | lmode)) {
3728  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3729  }
3730  }
3731  fh->startcond = -1;
3732  fh->startiscur = 0;
3733  } else if (fh->wrkhasrec == ISPREV) {
3734  memcpy (f->record->data, fh->recwrk, f->record_max);
3735  if (fh->lmode & ISLOCK) {
3736  /* Now lock 'peek ahead' record */
3737  if (isread (fh->isfd, (void *)f->record->data,
3738  ISCURR | fh->lmode)) {
3739  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3740  }
3741  }
3742  } else {
3743  if (fh->wrkhasrec == ISNEXT) {
3744  isread (fh->isfd, (void *)f->record->data, ISPREV);
3745  fh->wrkhasrec = 0;
3746  }
3747  if (isread (fh->isfd, (void *)f->record->data, ISPREV | lmode)) {
3748  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3749  }
3750  }
3751  break;
3752  case COB_READ_FIRST:
3753  fh->readdir = ISNEXT;
3754  if (isread (fh->isfd, (void *)f->record->data, ISFIRST | lmode)) {
3755  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3756  }
3757  break;
3758  case COB_READ_LAST:
3759  fh->readdir = ISPREV;
3760  if (isread (fh->isfd, (void *)f->record->data, ISLAST | lmode)) {
3761  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3762  }
3763  break;
3764  default:
3765  fh->readdir = ISNEXT;
3766  if (isread (fh->isfd, (void *)f->record->data, ISNEXT | lmode)) {
3767  ret = fisretsts (COB_STATUS_10_END_OF_FILE);
3768  }
3769  break;
3770  }
3771  if (unlikely(ret != 0)) {
3772  memset (fh->savekey, 0, (size_t)fh->key[0].k_leng);
3773  fh->recnum = 0;
3774  fh->readdone = 0;
3775  fh->wrkhasrec = 0;
3776  return ret;
3777  }
3778  fh->eofpending = 0;
3779  f->flag_first_read = 0;
3780  f->flag_read_done = 1;
3781  fh->readdone = 1;
3782  f->flag_end_of_file = 0;
3783  f->flag_begin_of_file = 0;
3784  memcpy (fh->savekey, f->record->data + fh->key[0].k_start,
3785  (size_t)fh->key[0].k_leng);
3786  fh->recnum = isrecnum;
3787 #ifdef ISVARLEN
3788  if (f->record_min != f->record_max) {
3789  f->record->size = isreclen;
3790  }
3791 #endif
3792 
3793 #ifdef COB_WITH_STATUS_02
3794  if((isstat1 == '0') && (isstat2 == '2')) {
3796  }
3797 #endif
3798  return 0;
3799 
3800 #elif defined(WITH_DB)
3801 
3802  struct indexed_file *p;
3803  int ret;
3804  int read_nextprev;
3805  cob_u32_t nextprev;
3806  int file_changed;
3807  int bdb_opts;
3808  unsigned int dupno;
3809 
3810  p = f->file;
3811  nextprev = DB_NEXT;
3812  dupno = 0;
3813  file_changed = 0;
3814 
3815  dupno = 0;
3816 
3817  bdb_opts = read_opts;
3818  if (bdb_env != NULL) {
3819  if (f->open_mode != COB_OPEN_I_O ||
3820  (f->lock_mode & COB_FILE_EXCLUSIVE)) {
3821  bdb_opts &= ~COB_READ_LOCK;
3822  } else if ((f->lock_mode & COB_LOCK_AUTOMATIC) &&
3823  !(bdb_opts & COB_READ_NO_LOCK)) {
3824  bdb_opts |= COB_READ_LOCK;
3825  }
3826  unlock_record (f);
3827  } else {
3828  bdb_opts &= ~COB_READ_LOCK;
3829  }
3830 
3831  if (unlikely(bdb_opts & COB_READ_PREVIOUS)) {
3832  if (f->flag_end_of_file) {
3833  nextprev = DB_LAST;
3834  } else {
3835  nextprev = DB_PREV;
3836  }
3837  } else if (f->flag_begin_of_file) {
3838  nextprev = DB_FIRST;
3839  }
3840  /* The open cursor makes this function atomic */
3841  if (p->key_index != 0) {
3842  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], 0);
3843  }
3844  p->db[p->key_index]->cursor (p->db[p->key_index], NULL, &p->cursor[p->key_index], 0);
3845 
3846  if (f->flag_first_read) {
3847  /* Data is read in indexed_open or indexed_start */
3848  if (p->data.data == NULL || (f->flag_first_read == 2 &&
3849  nextprev == DB_PREV)) {
3850  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3851  p->cursor[p->key_index] = NULL;
3852  if (p->key_index != 0) {
3853  p->cursor[0]->c_close (p->cursor[0]);
3854  p->cursor[0] = NULL;
3855  }
3857  }
3858  /* Check if previously read data still exists */
3859  p->key.size = (cob_dbtsize_t) f->keys[p->key_index].field->size;
3860  p->key.data = p->last_readkey[p->key_index];
3861  ret = DB_SEQ (p->cursor[p->key_index], DB_SET);
3862  if (!ret && p->key_index > 0) {
3863  if (f->keys[p->key_index].flag) {
3864  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
3865  while (ret == 0 &&
3866  memcmp (p->key.data, p->last_readkey[p->key_index], (size_t)p->key.size) == 0 &&
3867  dupno < p->last_dupno[p->key_index]) {
3868  ret = DB_SEQ (p->cursor[p->key_index], DB_NEXT);
3869  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
3870  }
3871  if (ret == 0 &&
3872  memcmp (p->key.data, p->last_readkey[p->key_index], (size_t)p->key.size) == 0 &&
3873  dupno == p->last_dupno[p->key_index]) {
3874  ret = memcmp (p->last_readkey[p->key_index + f->nkeys], p->data.data, f->keys[0].field->size);
3875  } else {
3876  ret = 1;
3877  }
3878  } else {
3879  ret = memcmp (p->last_readkey[p->key_index + f->nkeys], p->data.data, f->keys[0].field->size);
3880  }
3881  if (!ret) {
3882  p->key.size = (cob_dbtsize_t) f->keys[0].field->size;
3883  p->key.data = p->last_readkey[p->key_index + f->nkeys];
3884  ret = DB_GET (p->db[0], 0);
3885  }
3886  }
3887  file_changed = ret;
3888  if (bdb_env != NULL && !file_changed) {
3889  if (!(bdb_opts & COB_READ_IGNORE_LOCK)) {
3890  ret = test_record_lock (f, p->key.data, p->key.size);
3891  if (ret) {
3892  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3893  p->cursor[p->key_index] = NULL;
3894  if (p->key_index != 0) {
3895  p->cursor[0]->c_close (p->cursor[0]);
3896  p->cursor[0] = NULL;
3897  }
3899  }
3900  }
3901  if (bdb_opts & COB_READ_LOCK) {
3902  ret = lock_record (f, p->key.data, p->key.size);
3903  if (ret) {
3904  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3905  p->cursor[p->key_index] = NULL;
3906  if (p->key_index != 0) {
3907  p->cursor[0]->c_close (p->cursor[0]);
3908  p->cursor[0] = NULL;
3909  }
3911  }
3912  }
3913  }
3914  }
3915  if (!f->flag_first_read || file_changed) {
3916  if (nextprev == DB_FIRST || nextprev == DB_LAST) {
3917  read_nextprev = 1;
3918  } else {
3919  p->key.size = (cob_dbtsize_t) f->keys[p->key_index].field->size;
3920  p->key.data = p->last_readkey[p->key_index];
3921  ret = DB_SEQ (p->cursor[p->key_index], DB_SET_RANGE);
3922  /* ret != 0 possible, records may be deleted since last read */
3923  if (ret != 0) {
3924  if (nextprev == DB_PREV) {
3925  nextprev = DB_LAST;
3926  read_nextprev = 1;
3927  } else {
3928  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3929  p->cursor[p->key_index] = NULL;
3930  if (p->key_index != 0) {
3931  p->cursor[0]->c_close (p->cursor[0]);
3932  p->cursor[0] = NULL;
3933  }
3935  }
3936  } else {
3937  if (memcmp (p->key.data, p->last_readkey[p->key_index], (size_t)p->key.size) == 0) {
3938  if (p->key_index > 0 && f->keys[p->key_index].flag) {
3939  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
3940  while (ret == 0 &&
3941  memcmp (p->key.data, p->last_readkey[p->key_index], (size_t)p->key.size) == 0 &&
3942  dupno < p->last_dupno[p->key_index]) {
3943  ret = DB_SEQ (p->cursor[p->key_index], DB_NEXT);
3944  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
3945  }
3946  if (ret != 0) {
3947  if (nextprev == DB_PREV) {
3948  nextprev = DB_LAST;
3949  read_nextprev = 1;
3950  } else {
3951  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3952  p->cursor[p->key_index] = NULL;
3953  if (p->key_index != 0) {
3954  p->cursor[0]->c_close (p->cursor[0]);
3955  p->cursor[0] = NULL;
3956  }
3958  }
3959  } else {
3960  if (memcmp (p->key.data, p->last_readkey[p->key_index], (size_t)p->key.size) == 0 &&
3961  dupno == p->last_dupno[p->key_index]) {
3962  read_nextprev = 1;
3963  } else {
3964  if (nextprev == DB_PREV) {
3965  read_nextprev = 1;
3966  } else {
3967  read_nextprev = 0;
3968  }
3969  }
3970  }
3971  } else {
3972  read_nextprev = 1;
3973  }
3974  } else {
3975  if (nextprev == DB_PREV) {
3976  read_nextprev = 1;
3977  } else {
3978  read_nextprev = 0;
3979  }
3980  }
3981  }
3982  }
3983  if (read_nextprev) {
3984  ret = DB_SEQ (p->cursor[p->key_index], nextprev);
3985  if (ret != 0) {
3986  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
3987  p->cursor[p->key_index] = NULL;
3988  if (p->key_index != 0) {
3989  p->cursor[0]->c_close (p->cursor[0]);
3990  p->cursor[0] = NULL;
3991  }
3993  }
3994  }
3995 
3996  if (p->key_index > 0) {
3997  /* Temporarily save alternate key */
3998  memcpy (p->temp_key, p->key.data, (size_t)p->key.size);
3999  if (f->keys[p->key_index].flag) {
4000  memcpy (&dupno, (cob_u8_ptr)p->data.data + f->keys[0].field->size, sizeof(unsigned int));
4001  }
4002  p->key.data = p->data.data;
4003  p->key.size = f->keys[0].field->size;
4004  if (DB_GET (p->db[0], 0) != 0) {
4005  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
4006  p->cursor[p->key_index] = NULL;
4007  p->cursor[0]->c_close (p->cursor[0]);
4008  p->cursor[0] = NULL;
4010  }
4011  }
4012  if (bdb_env != NULL) {
4013  if (!(bdb_opts & COB_READ_IGNORE_LOCK)) {
4014  ret = test_record_lock (f, p->key.data, p->key.size);
4015  if (ret) {
4016  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
4017  p->cursor[p->key_index] = NULL;
4018  if (p->key_index != 0) {
4019  p->cursor[0]->c_close (p->cursor[0]);
4020  p->cursor[0] = NULL;
4021  }
4023  }
4024  }
4025  if (bdb_opts & COB_READ_LOCK) {
4026  ret = lock_record (f, p->key.data, p->key.size);
4027  if (ret) {
4028  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
4029  p->cursor[p->key_index] = NULL;
4030  if (p->key_index != 0) {
4031  p->cursor[0]->c_close (p->cursor[0]);
4032  p->cursor[0] = NULL;
4033  }
4035  }
4036  }
4037  }
4038  if (p->key_index == 0) {
4039  memcpy (p->last_readkey[0], p->key.data, (size_t)p->key.size);
4040  } else {
4041  memcpy (p->last_readkey[p->key_index], p->temp_key,
4042  f->keys[p->key_index].field->size);
4043  memcpy (p->last_readkey[p->key_index + f->nkeys], p->key.data, f->keys[0].field->size);
4044  if (f->keys[p->key_index].flag) {
4045  p->last_dupno[p->key_index] = dupno;
4046  }
4047  }
4048  }
4049 
4050  p->cursor[p->key_index]->c_close (p->cursor[p->key_index]);
4051  p->cursor[p->key_index] = NULL;
4052  if (p->key_index != 0) {
4053  p->cursor[0]->c_close (p->cursor[0]);
4054  p->cursor[0] = NULL;
4055  }
4056 
4057  f->record->size = p->data.size;
4058  memcpy (f->record->data, p->data.data, (size_t)p->data.size);
4059 
4060  return COB_STATUS_00_SUCCESS;
4061 
4062 #else
4063 
4065 #endif
4066 }
4067 
4068 
4069 /* WRITE to the INDEXED file */
4070 
4071 static int
4072 indexed_write (cob_file *f, const int opt)
4073 {
4074 #ifdef WITH_INDEX_EXTFH
4075 
4076  return extfh_indexed_write (f, opt);
4077 
4078 #elif defined(WITH_ANY_ISAM)
4079 
4080  struct indexfile *fh;
4081 
4082  COB_UNUSED (opt);
4083 
4084  fh = f->file;
4085  if (f->flag_nonexistent) {
4087  }
4088  if (f->access_mode == COB_ACCESS_SEQUENTIAL &&
4089  memcmp (fh->savekey, f->record->data + fh->key[0].k_start,
4090  (size_t)fh->key[0].k_leng) > 0) {
4092  }
4093 
4094 #ifdef ISVARLEN
4095  if (f->record_min != f->record_max) {
4096  isreclen = f->record->size;
4097  }
4098 #endif
4099  if (unlikely(iswrite (fh->isfd, (void *)f->record->data))) {
4100  return fisretsts (COB_STATUS_49_I_O_DENIED);
4101  }
4102  memcpy (fh->savekey, f->record->data + fh->key[0].k_start,
4103  (size_t)fh->key[0].k_leng);
4104 
4105 #ifdef COB_WITH_STATUS_02
4106  if((isstat1 == '0') && (isstat2 == '2')) {
4108  }
4109 #endif
4110  return 0;
4111 
4112 #elif defined(WITH_DB)
4113 
4114  struct indexed_file *p;
4115 
4116  if (f->flag_nonexistent) {
4118  }
4119  p = f->file;
4120  if (bdb_env != NULL) {
4121  unlock_record (f);
4122  }
4123 
4124  /* Check record key */
4125  DBT_SET (p->key, f->keys[0].field);
4126  if (!p->last_key) {
4127  p->last_key = cob_malloc ((size_t)p->key.size);
4128  } else if (f->access_mode == COB_ACCESS_SEQUENTIAL &&
4129  memcmp (p->last_key, p->key.data, (size_t)p->key.size) > 0) {
4131  }
4132  memcpy (p->last_key, p->key.data, (size_t)p->key.size);
4133 
4134  return indexed_write_internal (f, 0, opt);
4135 
4136 #else
4137 
4139 #endif
4140 }
4141 
4142 
4143 /* DELETE record from the INDEXED file */
4144 
4145 static int
4147 {
4148 #ifdef WITH_INDEX_EXTFH
4149 
4150  return extfh_indexed_delete (f);
4151 
4152 #elif defined(WITH_ANY_ISAM)
4153 
4154  struct indexfile *fh;
4155  int ret;
4156 
4157  fh = f->file;
4158  ret = COB_STATUS_00_SUCCESS;
4159  if (f->flag_nonexistent) {
4160  return COB_STATUS_49_I_O_DENIED;
4161  }
4162  if (fh->curkey == -1) {
4163  /* Switch to primary index */
4164  isstart (fh->isfd, &fh->key[0], 0,
4165  (void *)f->record->data, ISEQUAL);
4166  fh->curkey = 0;
4167  fh->readdir = ISNEXT;
4168  } else {
4169  savefileposition (f);
4170  if (fh->curkey != 0) {
4171  /* Switch to primary index */
4172  isstart (fh->isfd, &fh->key[0], 0,
4173  (void *)f->record->data, ISEQUAL);
4174  }
4175  }
4176  if (isread (fh->isfd, (void *)f->record->data, ISEQUAL | ISLOCK)) {
4177  ret = fisretsts (COB_STATUS_21_KEY_INVALID);
4178  } else if (isdelete (fh->isfd, (void *)f->record->data)) {
4179  ret = fisretsts (COB_STATUS_49_I_O_DENIED);
4180  }
4181  restorefileposition (f);
4182  return ret;
4183 
4184 #elif defined(WITH_DB)
4185 
4186  if (f->flag_nonexistent) {
4187  return COB_STATUS_49_I_O_DENIED;
4188  }
4189  return indexed_delete_internal (f, 0);
4190 
4191 #else
4192 
4194 #endif
4195 }
4196 
4197 /* REWRITE record to the INDEXED file */
4198 
4199 static int
4200 indexed_rewrite (cob_file *f, const int opt)
4201 {
4202 #ifdef WITH_INDEX_EXTFH
4203 
4204  return extfh_indexed_rewrite (f, opt);
4205 
4206 #elif defined(WITH_ANY_ISAM)
4207 
4208  struct indexfile *fh;
4209  size_t k;
4210  int ret;
4211 
4212  COB_UNUSED (opt);
4213 
4214  fh = f->file;
4215  ret = COB_STATUS_00_SUCCESS;
4216  if (f->flag_nonexistent) {
4217  return COB_STATUS_49_I_O_DENIED;
4218  }
4219 
4220  if (f->access_mode == COB_ACCESS_SEQUENTIAL &&
4221  memcmp (fh->savekey, f->record->data + fh->key[0].k_start,
4222  (size_t)fh->key[0].k_leng) != 0) {
4224  }
4225  if (fh->curkey >= 0) {
4226  /* Index is active */
4227  /* Save record data */
4228  memcpy (fh->recwrk, f->record->data, f->record_max);
4229 /* RXWRXW - readdir */
4230  fh->readdir = ISNEXT;
4231  savefileposition (f);
4232  memcpy (fh->recwrk, f->record->data, f->record_max);
4233  if (fh->curkey != 0) {
4234  /* Activate primary index */
4235  isstart (fh->isfd, &fh->key[0], 0, (void *)fh->recwrk,
4236  ISEQUAL);
4237  }
4238  /* Verify record exists */
4239  if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL)) {
4240  restorefileposition (f);
4242  }
4243  for (k = 1; k < f->nkeys && ret == COB_STATUS_00_SUCCESS; ++k) {
4244  if (fh->key[k].k_flags & ISDUPS) {
4245  continue;
4246  }
4247  memcpy (fh->recwrk, f->record->data, f->record_max);
4248  isstart (fh->isfd, &fh->key[k], fh->key[k].k_leng,
4249  (void *)fh->recwrk, ISEQUAL);
4250  if (!isread (fh->isfd, (void *)fh->recwrk, ISEQUAL) &&
4251  isrecnum != fh->recnum) {
4253  break;
4254  }
4255  }
4256  if (ret == COB_STATUS_00_SUCCESS) {
4257  memcpy (fh->recwrk, f->record->data, f->record_max);
4258  isstart (fh->isfd, &fh->key[0], 0, (void *)fh->recwrk,
4259  ISEQUAL);
4260  if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL | ISLOCK)) {
4261  ret = fisretsts (COB_STATUS_49_I_O_DENIED);
4262  } else {
4263 #ifdef ISVARLEN
4264  if (f->record_min != f->record_max) {
4265  isreclen = f->record->size;
4266  }
4267 #endif
4268  if (isrewcurr (fh->isfd, (void *)f->record->data)) {
4269  ret = fisretsts (COB_STATUS_49_I_O_DENIED);
4270  }
4271  }
4272  }
4273  restorefileposition (f);
4274 
4275 #ifdef COB_WITH_STATUS_02
4276  if(!ret && (isstat1 == '0') && (isstat2 == '2')) {
4278  }
4279 #endif
4280 
4281  return ret;
4282  }
4283 
4284  memcpy (fh->recwrk, f->record->data, f->record_max);
4285  if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL | ISLOCK)) {
4286  ret = fisretsts (COB_STATUS_49_I_O_DENIED);
4287  } else {
4288 #ifdef ISVARLEN
4289  if (f->record_min != f->record_max) {
4290  isreclen = f->record->size;
4291  }
4292 #endif
4293  if (isrewrite (fh->isfd, (void *)f->record->data)) {
4294  ret = fisretsts (COB_STATUS_49_I_O_DENIED);
4295  }
4296  }
4297  if (!ret) {
4298  if ((f->lock_mode & COB_LOCK_AUTOMATIC) &&
4299  !(f->lock_mode & COB_LOCK_MULTIPLE)) {
4300  isrelease (fh->isfd);
4301  }
4302 #ifdef COB_WITH_STATUS_02
4303  if((isstat1 == '0') && (isstat2 == '2')) {
4305  }
4306 #endif
4307  }
4308  return ret;
4309 
4310 #elif defined(WITH_DB)
4311 
4312  struct indexed_file *p;
4313  int ret;
4314  cob_u32_t flags;
4315 
4316  if (f->flag_nonexistent) {
4317  return COB_STATUS_49_I_O_DENIED;
4318  }
4319  p = f->file;
4320  if (bdb_env) {
4321  flags = DB_WRITECURSOR;
4322  } else {
4323  flags = 0;
4324  }
4325  p->db[0]->cursor (p->db[0], NULL, &p->cursor[0], flags);
4326  p->write_cursor_open = 1;
4327  if (bdb_env != NULL) {
4328  unlock_record (f);
4329  }
4330 
4331  /* Check duplicate alternate keys */
4332  if (check_alt_keys (f, 1)) {
4333  p->cursor[0]->c_close (p->cursor[0]);
4334  p->cursor[0] = NULL;
4335  p->write_cursor_open = 0;
4336  return COB_STATUS_22_KEY_EXISTS;
4337  }
4338 
4339  /* Delete the current record */
4340  ret = indexed_delete_internal (f, 1);
4341 
4342  if (ret != COB_STATUS_00_SUCCESS) {
4343  p->cursor[0]->c_close (p->cursor[0]);
4344  p->cursor[0] = NULL;
4345  p->write_cursor_open = 0;
4346  return ret;
4347  }
4348 
4349  /* Write data */
4350  DBT_SET (p->key, f->keys[0].field);
4351  ret = indexed_write_internal (f, 1, opt);
4352 
4353  p->cursor[0]->c_close (p->cursor[0]);
4354  p->cursor[0] = NULL;
4355  p->write_cursor_open = 0;
4356  return ret;
4357 
4358 #else
4359 
4361 #endif
4362 }
4363 
4364 
4365 static void
4367 {
4368 #ifdef WITH_DB
4369  struct indexed_file *p;
4370 #elif defined(WITH_ANY_ISAM)
4371  struct indexfile *fh;
4372 #endif
4373 
4374 #ifndef WITH_SEQRA_EXTFH
4375 #ifdef HAVE_FCNTL
4376  struct flock lock;
4377 #endif
4378 #endif
4379 
4380  if (COB_FILE_SPECIAL(f)) {
4381  return;
4382  }
4383 
4384  if (f->open_mode != COB_OPEN_CLOSED &&
4385  f->open_mode != COB_OPEN_LOCKED) {
4386  if (f->organization == COB_ORG_SORT) {
4387  return;
4388  }
4389  if (f->organization != COB_ORG_INDEXED) {
4390 #ifndef WITH_SEQRA_EXTFH
4391  if (f->fd >= 0) {
4392  fdcobsync (f->fd);
4393  }
4394 #ifdef HAVE_FCNTL
4395  if (!(f->lock_mode & COB_FILE_EXCLUSIVE)) {
4396  /* Unlock the file */
4397  memset ((void *)&lock, 0, sizeof (struct flock));
4398  lock.l_type = F_UNLCK;
4399  lock.l_whence = SEEK_SET;
4400  lock.l_start = 0;
4401  lock.l_len = 0;
4402  if (f->fd >= 0) {
4403  fcntl (f->fd, F_SETLK, &lock);
4404  }
4405  }
4406 #endif
4407 
4408 #endif
4409  } else {
4410 #ifdef WITH_INDEX_EXTFH
4411  extfh_indexed_unlock (f);
4412 #elif defined(WITH_DB)
4413  p = f->file;
4414  if (bdb_env != NULL && p) {
4415  unlock_record (f);
4416  bdb_env->lock_put (bdb_env, &p->bdb_file_lock);
4417  }
4418 #elif defined(WITH_ANY_ISAM)
4419  fh = f->file;
4420  if (fh) {
4421  isrelease (fh->isfd);
4422  }
4423 #endif
4424  }
4425  }
4426 }
4427 
4428 /* Global functions */
4429 
4430 void
4432 {
4433  cob_file_unlock (f);
4434  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
4435 }
4436 
4437 void
4438 cob_open (cob_file *f, const int mode, const int sharing, cob_field *fnstatus)
4439 {
4440  f->flag_read_done = 0;
4441 
4442  /* File was previously closed with lock */
4443  if (f->open_mode == COB_OPEN_LOCKED) {
4445  return;
4446  }
4447 
4448  /* File is already open */
4449  if (f->open_mode != COB_OPEN_CLOSED) {
4450  save_status (f, fnstatus, COB_STATUS_41_ALREADY_OPEN);
4451  return;
4452  }
4453 
4454  f->last_open_mode = mode;
4455  f->flag_nonexistent = 0;
4456  f->flag_end_of_file = 0;
4457  f->flag_begin_of_file = 0;
4458  f->flag_first_read = 2;
4459  f->flag_operation = 0;
4461  f->lock_mode |= sharing;
4462 
4463  if (unlikely(COB_FILE_STDIN (f))) {
4464  if (mode != COB_OPEN_INPUT) {
4466  return;
4467  }
4468  f->file = stdin;
4469  f->fd = fileno (stdin);
4470  f->open_mode = mode;
4471  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
4472  return;
4473  }
4474  if (unlikely(COB_FILE_STDOUT (f))) {
4475  if (mode != COB_OPEN_OUTPUT) {
4477  return;
4478  }
4479  f->file = stdout;
4480  f->fd = fileno (stdout);
4481  f->open_mode = mode;
4482  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
4483  return;
4484  }
4485 
4486  /* Obtain the file name */
4488 
4489  cob_cache_file (f);
4490 
4491  /* Open the file */
4492  save_status (f, fnstatus,
4493  fileio_funcs[(int)f->organization]->open (f, file_open_name,
4494  mode, sharing));
4495 }
4496 
4497 void
4498 cob_close (cob_file *f, cob_field *fnstatus, const int opt, const int remfil)
4499 {
4500  struct file_list *l;
4501  struct file_list *m;
4502  int ret;
4503 
4504  f->flag_read_done = 0;
4505  f->flag_operation = 0;
4506 
4508 
4509  if (COB_FILE_SPECIAL (f)) {
4511  f->file = NULL;
4512  f->fd = -1;
4513  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
4514  return;
4515  }
4516 
4517  if (unlikely(remfil)) {
4518  /* Remove from cache - Needed for CANCEL */
4519  /* Setting m silences false compiler warning */
4520  m = file_cache;
4521  for (l = file_cache; l; l = l->next) {
4522  if (f == l->file) {
4523  if (l == file_cache) {
4524  file_cache = l->next;
4525  } else {
4526  m->next = l->next;
4527  }
4528  cob_free (l);
4529  break;
4530  }
4531  m = l;
4532  }
4533  }
4534 
4535  if (f->open_mode == COB_OPEN_CLOSED) {
4536  save_status (f, fnstatus, COB_STATUS_42_NOT_OPEN);
4537  return;
4538  }
4539 
4540  if (f->flag_nonexistent) {
4541  ret = COB_STATUS_00_SUCCESS;
4542  } else {
4543  ret = fileio_funcs[(int)f->organization]->close (f, opt);
4544  }
4545 
4546  if (ret == COB_STATUS_00_SUCCESS) {
4547  switch (opt) {
4548  case COB_CLOSE_LOCK:
4550  break;
4551  default:
4553  break;
4554  }
4555  }
4556 
4557  save_status (f, fnstatus, ret);
4558 }
4559 
4560 #if 0 /* RXWRXW - unlock */
4561 void
4562 cob_unlock (cob_file *f)
4563 {
4564  int ret;
4565 
4566  f->flag_read_done = 0;
4567 
4568  if (f->open_mode == COB_OPEN_CLOSED) {
4569  save_status (f, fnstatus, COB_STATUS_42_NOT_OPEN);
4570  return;
4571  }
4572 
4573  if (f->flag_nonexistent) {
4574  ret = COB_STATUS_00_SUCCESS;
4575  } else {
4576  ret = fileio_funcs[(int)f->organization]->close (f, opt);
4577  }
4578 
4579  save_status (f, fnstatus, ret);
4580 }
4581 #endif
4582 
4583 void
4584 cob_start (cob_file *f, const int cond, cob_field *key,
4585  cob_field *keysize, cob_field *fnstatus)
4586 {
4587  int ret;
4588  int size;
4589  cob_field tempkey;
4590 
4591  f->flag_read_done = 0;
4592  f->flag_first_read = 0;
4593 
4594  if (unlikely(f->open_mode != COB_OPEN_I_O &&
4595  f->open_mode != COB_OPEN_INPUT)) {
4596  save_status (f, fnstatus, COB_STATUS_47_INPUT_DENIED);
4597  return;
4598  }
4599 
4600  if (unlikely(f->access_mode == COB_ACCESS_RANDOM)) {
4601  save_status (f, fnstatus, COB_STATUS_47_INPUT_DENIED);
4602  return;
4603  }
4604 
4605  if (f->flag_nonexistent) {
4607  return;
4608  }
4609 
4610  size = 0;
4611  if (unlikely(keysize)) {
4612  size = cob_get_int (keysize);
4613  if (size < 1 || size > (int)key->size) {
4615  return;
4616  }
4617  tempkey = *key;
4618  tempkey.size = (size_t)size;
4619  ret = fileio_funcs[(int)f->organization]->start (f, cond, &tempkey);
4620  } else {
4621  ret = fileio_funcs[(int)f->organization]->start (f, cond, key);
4622  }
4623  if (ret == COB_STATUS_00_SUCCESS) {
4624  f->flag_end_of_file = 0;
4625  f->flag_begin_of_file = 0;
4626  f->flag_first_read = 1;
4627  }
4628 
4629  save_status (f, fnstatus, ret);
4630 }
4631 
4632 void
4633 cob_read (cob_file *f, cob_field *key, cob_field *fnstatus, const int read_opts)
4634 {
4635  int ret;
4636 
4637  f->flag_read_done = 0;
4638 
4639  if (unlikely(f->open_mode != COB_OPEN_INPUT &&
4640  f->open_mode != COB_OPEN_I_O)) {
4641  save_status (f, fnstatus, COB_STATUS_47_INPUT_DENIED);
4642  return;
4643  }
4644 
4645  if (unlikely(f->flag_nonexistent)) {
4646  if (f->flag_first_read == 0) {
4648  return;
4649  }
4650  f->flag_first_read = 0;
4651  save_status (f, fnstatus, COB_STATUS_10_END_OF_FILE);
4652  return;
4653  }
4654 
4655  /* Sequential read at the end of file is an error */
4656  if (key == NULL) {
4657  if (unlikely(f->flag_end_of_file &&
4658  !(read_opts & COB_READ_PREVIOUS))) {
4659  save_status (f, fnstatus, COB_STATUS_46_READ_ERROR);
4660  return;
4661  }
4662  if (unlikely(f->flag_begin_of_file &&
4663  (read_opts & COB_READ_PREVIOUS))) {
4664  save_status (f, fnstatus, COB_STATUS_46_READ_ERROR);
4665  return;
4666  }
4667  ret = fileio_funcs[(int)f->organization]->read_next (f, read_opts);
4668  } else {
4669  ret = fileio_funcs[(int)f->organization]->read (f, key, read_opts);
4670  }
4671 
4672  switch (ret) {
4673  case COB_STATUS_00_SUCCESS:
4675  f->flag_first_read = 0;
4676  f->flag_read_done = 1;
4677  f->flag_end_of_file = 0;
4678  f->flag_begin_of_file = 0;
4679  if (f->variable_record) {
4680  cob_set_int (f->variable_record, (int) f->record->size);
4681  }
4682  break;
4684  if (read_opts & COB_READ_PREVIOUS) {
4685  f->flag_begin_of_file = 1;
4686  } else {
4687  f->flag_end_of_file = 1;
4688  }
4689  break;
4690  }
4691 
4692  save_status (f, fnstatus, ret);
4693 }
4694 
4695 void
4696 cob_read_next (cob_file *f, cob_field *fnstatus, const int read_opts)
4697 {
4698  int ret;
4699 
4700  f->flag_read_done = 0;
4701 
4702  if (unlikely(f->open_mode != COB_OPEN_INPUT &&
4703  f->open_mode != COB_OPEN_I_O)) {
4704  save_status (f, fnstatus, COB_STATUS_47_INPUT_DENIED);
4705  return;
4706  }
4707 
4708  if (unlikely(f->flag_nonexistent)) {
4709  if (f->flag_first_read == 0) {
4711  return;
4712  }
4713  f->flag_first_read = 0;
4714  save_status (f, fnstatus, COB_STATUS_10_END_OF_FILE);
4715  return;
4716  }
4717 
4718  /* Sequential read at the end of file is an error */
4719  if (unlikely(f->flag_end_of_file && !(read_opts & COB_READ_PREVIOUS))) {
4720  save_status (f, fnstatus, COB_STATUS_46_READ_ERROR);
4721  return;
4722  }
4723  if (unlikely(f->flag_begin_of_file && (read_opts & COB_READ_PREVIOUS))) {
4724  save_status (f, fnstatus, COB_STATUS_46_READ_ERROR);
4725  return;
4726  }
4727 
4728  ret = fileio_funcs[(int)f->organization]->read_next (f, read_opts);
4729 
4730  switch (ret) {
4731  case COB_STATUS_00_SUCCESS:
4733  f->flag_first_read = 0;
4734  f->flag_read_done = 1;
4735  f->flag_end_of_file = 0;
4736  f->flag_begin_of_file = 0;
4737  if (f->variable_record) {
4738  cob_set_int (f->variable_record, (int) f->record->size);
4739  }
4740  break;
4742  if (read_opts & COB_READ_PREVIOUS) {
4743  f->flag_begin_of_file = 1;
4744  } else {
4745  f->flag_end_of_file = 1;
4746  }
4747  break;
4748  }
4749 
4750  save_status (f, fnstatus, ret);
4751 }
4752 
4753 void
4754 cob_write (cob_file *f, cob_field *rec, const int opt, cob_field *fnstatus,
4755  const unsigned int check_eop)
4756 {
4757  f->flag_read_done = 0;
4758 
4759  if (f->access_mode == COB_ACCESS_SEQUENTIAL) {
4760  if (unlikely(f->open_mode != COB_OPEN_OUTPUT &&
4761  f->open_mode != COB_OPEN_EXTEND)) {
4763  return;
4764  }
4765  } else {
4766  if (unlikely(f->open_mode != COB_OPEN_OUTPUT &&
4767  f->open_mode != COB_OPEN_I_O)) {
4769  return;
4770  }
4771  }
4772 
4773  if (f->variable_record) {
4774  f->record->size = (size_t)cob_get_int (f->variable_record);
4775  if (unlikely(f->record->size > rec->size)) {
4776  f->record->size = rec->size;
4777  }
4778  } else {
4779  f->record->size = rec->size;
4780  }
4781 
4782  if (f->record->size < f->record_min || f->record_max < f->record->size) {
4784  return;
4785  }
4786 
4787  check_eop_status = check_eop;
4788  save_status (f, fnstatus,
4789  fileio_funcs[(int)f->organization]->write (f, opt));
4790 }
4791 
4792 void
4793 cob_rewrite (cob_file *f, cob_field *rec, const int opt, cob_field *fnstatus)
4794 {
4795  int read_done;
4796 
4797  read_done = f->flag_read_done;
4798  f->flag_read_done = 0;
4799 
4800  if (unlikely(f->open_mode != COB_OPEN_I_O)) {
4801  save_status (f, fnstatus, COB_STATUS_49_I_O_DENIED);
4802  return;
4803  }
4804 
4805  if (f->access_mode == COB_ACCESS_SEQUENTIAL && !read_done) {
4807  return;
4808  }
4809 
4811  if (f->record->size != rec->size) {
4813  return;
4814  }
4815 
4816  if (f->variable_record) {
4817  if (f->record->size != (size_t)cob_get_int (f->variable_record)) {
4819  return;
4820  }
4821  }
4822  }
4823 
4824  save_status (f, fnstatus,
4825  fileio_funcs[(int)f->organization]->rewrite (f, opt));
4826 }
4827 
4828 void
4830 {
4831  int read_done;
4832 
4833  read_done = f->flag_read_done;
4834  f->flag_read_done = 0;
4835 
4836  if (unlikely(f->open_mode != COB_OPEN_I_O)) {
4837  save_status (f, fnstatus, COB_STATUS_49_I_O_DENIED);
4838  return;
4839  }
4840 
4841  if (f->access_mode == COB_ACCESS_SEQUENTIAL && !read_done) {
4843  return;
4844  }
4845 
4846  save_status (f, fnstatus,
4847  fileio_funcs[(int)f->organization]->fdelete (f));
4848 }
4849 
4850 void
4852 {
4853  struct file_list *l;
4854 
4855  for (l = file_cache; l; l = l->next) {
4856  if (l->file) {
4857  cob_file_unlock (l->file);
4858  }
4859  }
4860 }
4861 
4862 void
4864 {
4865  struct file_list *l;
4866 
4867  for (l = file_cache; l; l = l->next) {
4868  if (l->file) {
4869  cob_file_unlock (l->file);
4870  }
4871  }
4872 }
4873 
4874 void
4876 {
4877  if (f->organization == COB_ORG_SORT) {
4879  return;
4880  }
4881 
4882  /* File was previously closed with lock */
4883  if (f->open_mode == COB_OPEN_LOCKED) {
4885  return;
4886  }
4887 
4888  /* File is open */
4889  if (f->open_mode != COB_OPEN_CLOSED) {
4890  save_status (f, fnstatus, COB_STATUS_41_ALREADY_OPEN);
4891  return;
4892  }
4893 
4894  if (unlikely(COB_FILE_STDIN (f))) {
4896  return;
4897  }
4898  if (unlikely(COB_FILE_STDOUT (f))) {
4900  return;
4901  }
4902 
4903  /* Obtain the file name */
4906 
4907  if (f->organization != COB_ORG_INDEXED) {
4908 #ifdef WITH_SEQRA_EXTFH
4910  return;
4911 #else
4912  unlink (file_open_name);
4913 #endif
4914  } else {
4915 #ifdef WITH_INDEX_EXTFH
4917  return;
4918 #else
4920 #endif
4921  }
4922  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
4923 }
4924 
4925 /* System routines */
4926 
4927 static void *
4929 {
4930  void *mptr;
4931  unsigned char *s;
4932  int i;
4933  int n;
4934  int j;
4935 #if 0 /* Quotes in file */
4936  int quote_switch;
4937 
4938  quote_switch = 0;
4939 #endif
4940 
4941  if (!f) {
4942  return cob_malloc ((size_t)1);
4943  }
4944  for (i = (int) f->size - 1; i >= 0; --i) {
4945  if (f->data[i] != ' ' && f->data[i] != 0) {
4946  break;
4947  }
4948  }
4949  i++;
4950  /* i is 0 or > 0 */
4951  mptr = cob_malloc ((size_t)(i + 1));
4952  s = mptr;
4953  j = 0;
4954  for (n = 0; n < i; ++n) {
4955  if (f->data[n] == '"') {
4956  continue;
4957  }
4958  s[j++] = f->data[n];
4959 #if 0 /* Quotes in file */
4960  if (f->data[n] == '"') {
4961  quote_switch = !quote_switch;
4962  continue;
4963  }
4964  s[j] = f->data[n];
4965  if (quote_switch) {
4966  j++;
4967  continue;
4968  }
4969  if (s[j] == ' ' || s[j] == 0) {
4970  s[j] = 0;
4971  break;
4972  }
4973  j++;
4974 #endif
4975  }
4976  return mptr;
4977 }
4978 
4979 static int
4980 open_cbl_file (unsigned char *file_name, unsigned char *file_access,
4981  unsigned char *file_handle, const int file_flags)
4982 {
4983  char *fn;
4984  int flag = O_BINARY;
4985  int fd;
4986 
4987  COB_UNUSED (file_name);
4988 
4989  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
4990  memset (file_handle, -1, (size_t)4);
4991  return -1;
4992  }
4993  flag |= file_flags;
4994  switch (*file_access & 0x3F) {
4995  case 1:
4996  flag |= O_RDONLY;
4997  break;
4998  case 2:
4999  flag |= O_CREAT | O_TRUNC | O_WRONLY;
5000  break;
5001  case 3:
5002  flag |= O_RDWR;
5003  break;
5004  default:
5005  if (cobsetptr->cob_display_warn) {
5006  fprintf (stderr, _("WARNING - Call to CBL_OPEN_FILE with wrong access mode: %d"), *file_access & 0x3F);
5007  putc ('\n', stderr);
5008  fflush (stderr);
5009  }
5010  memset (file_handle, -1, (size_t)4);
5011  return -1;
5012  }
5013  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5014  fd = open (fn, flag, COB_FILE_MODE);
5015  if (fd < 0) {
5016  cob_free (fn);
5017  memset (file_handle, -1, (size_t)4);
5018  return 35;
5019  }
5020  cob_free (fn);
5021  memcpy (file_handle, &fd, (size_t)4);
5022  return 0;
5023 }
5024 
5025 int
5026 cob_sys_open_file (unsigned char *file_name, unsigned char *file_access,
5027  unsigned char *file_lock, unsigned char *file_dev,
5028  unsigned char *file_handle)
5029 {
5030  COB_UNUSED (file_lock);
5031  COB_UNUSED (file_dev);
5032 
5033  COB_CHK_PARMS (CBL_OPEN_FILE, 5);
5034 
5035  return open_cbl_file (file_name, file_access, file_handle, 0);
5036 }
5037 
5038 int
5039 cob_sys_create_file (unsigned char *file_name, unsigned char *file_access,
5040  unsigned char *file_lock, unsigned char *file_dev,
5041  unsigned char *file_handle)
5042 {
5043  /*
5044  * @param: file_access : 1 (read-only), 2 (write-only), 3 (both)
5045  * @param: file_lock : not implemented, set 0
5046  * @param: file_dev : not implemented, set 0
5047  */
5048 
5049  if (*file_lock != 0 && cobsetptr->cob_display_warn) {
5050  fprintf (stderr, _("WARNING - Call to CBL_CREATE_FILE with wrong file_lock: %d"), *file_lock);
5051  putc ('\n', stderr);
5052  fflush (stderr);
5053  }
5054  if (*file_dev != 0 && cobsetptr->cob_display_warn) {
5055  fprintf (stderr, _("WARNING - Call to CBL_CREATE_FILE with wrong file_dev: %d"), *file_dev);
5056  putc ('\n', stderr);
5057  fflush (stderr);
5058  }
5059 
5060  COB_CHK_PARMS (CBL_CREATE_FILE, 5);
5061 
5062  return open_cbl_file (file_name, file_access, file_handle, O_CREAT | O_TRUNC);
5063 }
5064 
5065 int
5066 cob_sys_read_file (unsigned char *file_handle, unsigned char *file_offset,
5067  unsigned char *file_len, unsigned char *flags,
5068  unsigned char *buf)
5069 {
5070  cob_s64_t off;
5071  int fd;
5072  int len;
5073  int rc;
5074  struct stat st;
5075 
5076  COB_CHK_PARMS (CBL_READ_FILE, 5);
5077 
5078  rc = 0;
5079  memcpy (&fd, file_handle, (size_t)4);
5080  memcpy (&off, file_offset, (size_t)8);
5081  memcpy (&len, file_len, (size_t)4);
5082 #ifndef WORDS_BIGENDIAN
5083  off = COB_BSWAP_64 (off);
5084  len = COB_BSWAP_32 (len);
5085 #endif
5086  if (lseek (fd, (off_t)off, SEEK_SET) == (off_t)-1) {
5087  return -1;
5088  }
5089  if (len > 0) {
5090  rc = read (fd, buf, (size_t)len);
5091  if (rc < 0) {
5092  rc = -1;
5093  } else if (rc == 0) {
5094  rc = 10;
5095  } else {
5096  rc = 0;
5097  }
5098  }
5099  if ((*flags & 0x80) != 0) {
5100  if (fstat (fd, &st) < 0) {
5101  return -1;
5102  }
5103  off = st.st_size;
5104 #ifndef WORDS_BIGENDIAN
5105  off = COB_BSWAP_64 (off);
5106 #endif
5107  memcpy (file_offset, &off, (size_t)8);
5108  }
5109  return rc;
5110 }
5111 
5112 int
5113 cob_sys_write_file (unsigned char *file_handle, unsigned char *file_offset,
5114  unsigned char *file_len, unsigned char *flags,
5115  unsigned char *buf)
5116 {
5117  cob_s64_t off;
5118  int fd;
5119  int len;
5120  int rc;
5121 
5122  COB_UNUSED (flags);
5123 
5124  COB_CHK_PARMS (CBL_WRITE_FILE, 5);
5125 
5126  memcpy (&fd, file_handle, (size_t)4);
5127  memcpy (&off, file_offset, (size_t)8);
5128  memcpy (&len, file_len, (size_t)4);
5129 #ifndef WORDS_BIGENDIAN
5130  off = COB_BSWAP_64 (off);
5131  len = COB_BSWAP_32 (len);
5132 #endif
5133  if (lseek (fd, (off_t)off, SEEK_SET) == (off_t)-1) {
5134  return -1;
5135  }
5136  rc = write (fd, buf, (size_t)len);
5137  if (rc < 0) {
5138  return 30;
5139  }
5140  return 0;
5141 }
5142 
5143 int
5144 cob_sys_close_file (unsigned char *file_handle)
5145 {
5146  int fd;
5147 
5148  COB_CHK_PARMS (CBL_CLOSE_FILE, 1);
5149 
5150  memcpy (&fd, file_handle, (size_t)4);
5151  return close (fd);
5152 }
5153 
5154 int
5155 cob_sys_flush_file (unsigned char *file_handle)
5156 {
5157  COB_UNUSED (file_handle);
5158 
5159  COB_CHK_PARMS (CBL_FLUSH_FILE, 1);
5160 
5161  return 0;
5162 }
5163 
5164 int
5165 cob_sys_delete_file (unsigned char *file_name)
5166 {
5167  char *fn;
5168  int ret;
5169 
5170  COB_UNUSED (file_name);
5171 
5172  COB_CHK_PARMS (CBL_DELETE_FILE, 1);
5173 
5174  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5175  return -1;
5176  }
5177  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5178  ret = unlink (fn);
5179  cob_free (fn);
5180  if (ret) {
5181  return 128;
5182  }
5183  return 0;
5184 }
5185 
5186 int
5187 cob_sys_copy_file (unsigned char *fname1, unsigned char *fname2)
5188 {
5189  char *fn1;
5190  char *fn2;
5191  int flag = O_BINARY;
5192  int ret;
5193  int i;
5194  int fd1, fd2;
5195 
5196  COB_UNUSED (fname1);
5197  COB_UNUSED (fname2);
5198 
5199  COB_CHK_PARMS (CBL_COPY_FILE, 2);
5200 
5201  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5202  return -1;
5203  }
5204  if (!COB_MODULE_PTR->cob_procedure_params[1]) {
5205  return -1;
5206  }
5207  fn1 = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5208  flag |= O_RDONLY;
5209  fd1 = open (fn1, flag, 0);
5210  if (fd1 < 0) {
5211  cob_free (fn1);
5212  return -1;
5213  }
5214  cob_free (fn1);
5215  fn2 = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[1]);
5216  flag &= ~O_RDONLY;
5217  flag |= O_CREAT | O_TRUNC | O_WRONLY;
5218  fd2 = open (fn2, flag, COB_FILE_MODE);
5219  if (fd2 < 0) {
5220  close (fd1);
5221  cob_free (fn2);
5222  return -1;
5223  }
5224  cob_free (fn2);
5225 
5226  ret = 0;
5227  while ((i = read (fd1, file_open_buff, COB_FILE_BUFF)) > 0) {
5228  if (write (fd2, file_open_buff, (size_t)i) < 0) {
5229  ret = -1;
5230  break;
5231  }
5232  }
5233  close (fd1);
5234  close (fd2);
5235  return ret;
5236 }
5237 
5238 int
5239 cob_sys_check_file_exist (unsigned char *file_name, unsigned char *file_info)
5240 {
5241  char *fn;
5242  struct tm *tm;
5243  cob_s64_t sz;
5244  struct stat st;
5245  short y;
5246  short d, m, hh, mm, ss;
5247 
5248  COB_UNUSED (file_name);
5249 
5250  COB_CHK_PARMS (CBL_CHECK_FILE_EXIST, 2);
5251 
5252  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5253  return -1;
5254  }
5255  if (!COB_MODULE_PTR->cob_procedure_params[1]) {
5256  return -1;
5257  }
5258  if (COB_MODULE_PTR->cob_procedure_params[1]->size < 16U) {
5259  cob_runtime_error (_("'%s' - File detail area is too short"), "CBL_CHECK_FILE_EXIST");
5260  cob_stop_run (1);
5261  }
5262 
5263  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5264  if (stat (fn, &st) < 0) {
5265  cob_free (fn);
5266  return 35;
5267  }
5268  cob_free (fn);
5269  sz = (cob_s64_t)st.st_size;
5270  tm = localtime (&st.st_mtime);
5271  d = (short)tm->tm_mday;
5272  m = (short)(tm->tm_mon + 1);
5273  y = (short)(tm->tm_year + 1900);
5274  hh = (short)tm->tm_hour;
5275  mm = (short)tm->tm_min;
5276  /* Leap seconds ? */
5277  if (tm->tm_sec >= 60) {
5278  ss = 59;
5279  } else {
5280  ss = (short)tm->tm_sec;
5281  }
5282 
5283 #ifndef WORDS_BIGENDIAN
5284  sz = COB_BSWAP_64 (sz);
5285  y = COB_BSWAP_16 (y);
5286 #endif
5287  memcpy (file_info, &sz, (size_t)8);
5288  file_info[8] = (unsigned char)d;
5289  file_info[9] = (unsigned char)m;
5290  memcpy (file_info+10, &y, (size_t)2);
5291  file_info[12] = (unsigned char)hh;
5292  file_info[13] = (unsigned char)mm;
5293  file_info[14] = (unsigned char)ss;
5294  file_info[15] = 0;
5295  return 0;
5296 }
5297 
5298 int
5299 cob_sys_rename_file (unsigned char *fname1, unsigned char *fname2)
5300 {
5301  char *fn1;
5302  char *fn2;
5303  int ret;
5304 
5305  COB_UNUSED (fname1);
5306  COB_UNUSED (fname2);
5307 
5308  COB_CHK_PARMS (CBL_RENAME_FILE, 2);
5309 
5310  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5311  return -1;
5312  }
5313  if (!COB_MODULE_PTR->cob_procedure_params[1]) {
5314  return -1;
5315  }
5316  fn1 = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5317  fn2 = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[1]);
5318  ret = rename (fn1, fn2);
5319  cob_free (fn1);
5320  cob_free (fn2);
5321  if (ret) {
5322  return 128;
5323  }
5324  return 0;
5325 }
5326 
5327 int
5328 cob_sys_get_current_dir (const int flags, const int dir_length,
5329  unsigned char *dir)
5330 {
5331  char *dirname;
5332  int dir_size;
5333  int has_space;
5334 
5335  COB_CHK_PARMS (CBL_GET_CURRENT_DIR, 3);
5336 
5337  if (dir_length < 1) {
5338  return 128;
5339  }
5340  if (flags) {
5341  return 129;
5342  }
5343  memset (dir, ' ', (size_t)dir_length);
5344  dirname = getcwd (NULL, (size_t)0);
5345  if (dirname == NULL) {
5346  return 128;
5347  }
5348  dir_size = (int) strlen (dirname);
5349  has_space = 0;
5350  if (strchr (dirname, ' ')) {
5351  has_space = 2;
5352  }
5353  if (dir_size + has_space > dir_length) {
5354  cob_free (dirname);
5355  return 128;
5356  }
5357  if (has_space) {
5358  *dir = '"';
5359  memcpy (&dir[1], dirname, (size_t)dir_size);
5360  dir[dir_size + 1] = '"';
5361  } else {
5362  memcpy (dir, dirname, (size_t)dir_size);
5363  }
5364  cob_free (dirname);
5365  return 0;
5366 }
5367 
5368 int
5369 cob_sys_create_dir (unsigned char *dir)
5370 {
5371  char *fn;
5372  int ret;
5373 
5374  COB_UNUSED (dir);
5375 
5376  COB_CHK_PARMS (CBL_CREATE_DIR, 1);
5377 
5378  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5379  return -1;
5380  }
5381  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5382 #ifdef _WIN32
5383  ret = mkdir (fn);
5384 #else
5385  ret = mkdir (fn, 0770);
5386 #endif
5387  cob_free (fn);
5388  if (ret) {
5389  return 128;
5390  }
5391  return 0;
5392 }
5393 
5394 int
5395 cob_sys_change_dir (unsigned char *dir)
5396 {
5397  char *fn;
5398  int ret;
5399 
5400  COB_UNUSED (dir);
5401 
5402  COB_CHK_PARMS (CBL_CHANGE_DIR, 1);
5403 
5404  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5405  return -1;
5406  }
5407  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5408  ret = chdir (fn);
5409  cob_free (fn);
5410  if (ret) {
5411  return 128;
5412  }
5413  return 0;
5414 }
5415 
5416 int
5417 cob_sys_delete_dir (unsigned char *dir)
5418 {
5419  char *fn;
5420  int ret;
5421 
5422  COB_UNUSED (dir);
5423 
5424  COB_CHK_PARMS (CBL_DELETE_DIR, 1);
5425 
5426  if (!COB_MODULE_PTR->cob_procedure_params[0]) {
5427  return -1;
5428  }
5429  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5430  ret = rmdir (fn);
5431  cob_free (fn);
5432  if (ret) {
5433  return 128;
5434  }
5435  return 0;
5436 }
5437 
5438 int
5439 cob_sys_mkdir (unsigned char *dir)
5440 {
5441  int ret;
5442 
5443  COB_CHK_PARMS (C$MAKEDIR, 1);
5444 
5445  ret = cob_sys_create_dir (dir);
5446  if (ret < 0) {
5447  ret = 128;
5448  }
5449  return ret;
5450 }
5451 
5452 int
5453 cob_sys_chdir (unsigned char *dir, unsigned char *status)
5454 {
5455  int ret;
5456 
5457  COB_UNUSED (status);
5458 
5459  COB_CHK_PARMS (C$CHDIR, 2);
5460 
5461  ret = cob_sys_change_dir (dir);
5462  if (ret < 0) {
5463  ret = 128;
5464  }
5465  cob_set_int (COB_MODULE_PTR->cob_procedure_params[1], ret);
5466  return ret;
5467 }
5468 
5469 int
5470 cob_sys_copyfile (unsigned char *fname1, unsigned char *fname2,
5471  unsigned char *file_type)
5472 {
5473  int ret;
5474 
5475  /* RXW - Type is not yet evaluated */
5476  COB_UNUSED (file_type);
5477 
5478  COB_CHK_PARMS (C$COPY, 3);
5479 
5480  if (cobglobptr->cob_call_params < 3) {
5481  return 128;
5482  }
5483  ret = cob_sys_copy_file (fname1, fname2);
5484  if (ret < 0) {
5485  ret = 128;
5486  }
5487  return ret;
5488 }
5489 
5490 int
5491 cob_sys_file_info (unsigned char *file_name, unsigned char *file_info)
5492 {
5493  char *fn;
5494  struct tm *tm;
5495  cob_u64_t sz;
5496  unsigned int dt;
5497  short y;
5498  short d, m, hh, mm, ss;
5499  struct stat st;
5500 
5501  COB_UNUSED (file_name);
5502 
5503  COB_CHK_PARMS (C$FILEINFO, 2);
5504 
5505  if (cobglobptr->cob_call_params < 2 ||
5506  !COB_MODULE_PTR->cob_procedure_params[0]) {
5507  return 128;
5508  }
5509  if (!COB_MODULE_PTR->cob_procedure_params[1]) {
5510  return 128;
5511  }
5512  if (COB_MODULE_PTR->cob_procedure_params[1]->size < 16U) {
5513  cob_runtime_error (_("'%s' - File detail area is too short"), "C$FILEINFO");
5514  cob_stop_run (1);
5515  }
5516 
5517  fn = cob_str_from_fld (COB_MODULE_PTR->cob_procedure_params[0]);
5518  if (stat (fn, &st) < 0) {
5519  cob_free (fn);
5520  return 35;
5521  }
5522  cob_free (fn);
5523  sz = (cob_u64_t)st.st_size;
5524  tm = localtime (&st.st_mtime);
5525  d = (short)tm->tm_mday;
5526  m = (short)(tm->tm_mon + 1);
5527  y = (short)(tm->tm_year + 1900);
5528  hh = (short)tm->tm_hour;
5529  mm = (short)tm->tm_min;
5530  /* Leap seconds ? */
5531  if (tm->tm_sec >= 60) {
5532  ss = 59;
5533  } else {
5534  ss = (short)tm->tm_sec;
5535  }
5536 
5537 #ifndef WORDS_BIGENDIAN
5538  sz = COB_BSWAP_64 (sz);
5539 #endif
5540  memcpy (file_info, &sz, (size_t)8);
5541  dt = (y * 10000) + (m * 100) + d;
5542 #ifndef WORDS_BIGENDIAN
5543  dt = COB_BSWAP_32 (dt);
5544 #endif
5545  memcpy (file_info + 8, &dt, (size_t)4);
5546  dt = (hh * 1000000) + (mm * 10000) + (ss * 100);
5547 #ifndef WORDS_BIGENDIAN
5548  dt = COB_BSWAP_32 (dt);
5549 #endif
5550  memcpy (file_info + 12, &dt, (size_t)4);
5551  return 0;
5552 }
5553 
5554 int
5555 cob_sys_file_delete (unsigned char *file_name, unsigned char *file_type)
5556 {
5557  int ret;
5558 
5559  /* RXW - Type is not yet evaluated */
5560  COB_UNUSED (file_type);
5561 
5562  COB_CHK_PARMS (C$DELETE, 2);
5563 
5564  if (cobglobptr->cob_call_params < 2 ||
5565  !COB_MODULE_PTR->cob_procedure_params[0]) {
5566  return 128;
5567  }
5568  ret = cob_sys_delete_file (file_name);
5569  if (ret < 0) {
5570  ret = 128;
5571  }
5572  return ret;
5573 }
5574 
5575 /* SORT */
5576 
5577 static int
5578 sort_cmps (const unsigned char *s1, const unsigned char *s2, const size_t size,
5579  const unsigned char *col)
5580 {
5581  size_t i;
5582  int ret;
5583 
5584  if (unlikely(col)) {
5585  for (i = 0; i < size; ++i) {
5586  if ((ret = col[s1[i]] - col[s2[i]]) != 0) {
5587  return ret;
5588  }
5589  }
5590  } else {
5591  for (i = 0; i < size; ++i) {
5592  if ((ret = s1[i] - s2[i]) != 0) {
5593  return ret;
5594  }
5595  }
5596  }
5597  return 0;
5598 }
5599 
5600 static COB_INLINE void
5601 unique_copy (unsigned char *s1, const unsigned char *s2)
5602 {
5603  size_t size;
5604 
5605  size = sizeof(size_t);
5606  do {
5607  *s1++ = *s2++;
5608  } while (--size);
5609 }
5610 
5611 static int
5612 cob_file_sort_compare (struct cobitem *k1, struct cobitem *k2, void *pointer)
5613 {
5614  cob_file *f;
5615  size_t i;
5616  size_t u1;
5617  size_t u2;
5618  int cmp;
5619  cob_field f1;
5620  cob_field f2;
5621 
5622  f = pointer;
5623  for (i = 0; i < f->nkeys; ++i) {
5624  f1 = f2 = *(f->keys[i].field);
5625  f1.data = k1->item + f->keys[i].offset;
5626  f2.data = k2->item + f->keys[i].offset;
5627  if (unlikely(COB_FIELD_IS_NUMERIC (&f1))) {
5628  cmp = cob_numeric_cmp (&f1, &f2);
5629  } else {
5630  cmp = sort_cmps (f1.data, f2.data, f1.size,
5631  f->sort_collating);
5632  }
5633  if (cmp != 0) {
5634  return (f->keys[i].flag == COB_ASCENDING) ? cmp : -cmp;
5635  }
5636  }
5637  unique_copy ((unsigned char *)&u1, k1->unique);
5638  unique_copy ((unsigned char *)&u2, k2->unique);
5639  if (u1 < u2) {
5640  return -1;
5641  }
5642  return 1;
5643 }
5644 
5645 static void
5647 {
5648  struct sort_mem_struct *s1;
5649  struct sort_mem_struct *s2;
5650 
5651  s1 = hp->mem_base;
5652  for (; s1;) {
5653  s2 = s1;
5654  s1 = s1->next;
5655  cob_free (s2->mem_ptr);
5656  cob_free (s2);
5657  }
5658 }
5659 
5660 static struct cobitem *
5661 cob_new_item (struct cobsort *hp, const size_t size)
5662 {
5663  struct cobitem *q;
5664  struct sort_mem_struct *s;
5665 
5666  COB_UNUSED (size);
5667 
5668  /* Creation of an empty item */
5669  if (unlikely(hp->empty != NULL)) {
5670  q = hp->empty;
5671  hp->empty = q->next;
5672  q->block_byte = 0;
5673  q->next = NULL;
5674  q->end_of_block = 0;
5675  return (void *)q;
5676  }
5677  if (unlikely((hp->mem_used + hp->alloc_size) > hp->mem_size)) {
5678  s = cob_fast_malloc (sizeof (struct sort_mem_struct));
5679  s->mem_ptr = cob_fast_malloc (hp->chunk_size);
5680  s->next = hp->mem_base;
5681  hp->mem_base = s;
5682  hp->mem_size = hp->chunk_size;
5683  hp->mem_total += hp->chunk_size;
5684  hp->mem_used = 0;
5685  }
5686  q = (struct cobitem *)(hp->mem_base->mem_ptr + hp->mem_used);
5687  hp->mem_used += hp->alloc_size;
5688  if (unlikely(hp->mem_total >= cobsetptr->cob_sort_memory)) {
5689  if ((hp->mem_used + hp->alloc_size) > hp->mem_size) {
5690  hp->switch_to_file = 1;
5691  }
5692  }
5693  q->block_byte = 0;
5694  q->next = NULL;
5695  q->end_of_block = 0;
5696  return q;
5697 }
5698 
5699 static FILE *
5701 {
5702  FILE *fp;
5703  char *filename;
5704  int fd;
5705 
5706  filename = cob_malloc ((size_t)COB_FILE_BUFF);
5707  cob_temp_name(filename, NULL);
5709 #ifdef _WIN32
5710  fd = open (filename,
5711  _O_CREAT | _O_TRUNC | _O_RDWR | _O_BINARY | _O_TEMPORARY,
5712  _S_IREAD | _S_IWRITE);
5713 #else
5714  fd = open (filename, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, COB_FILE_MODE);
5715 #endif
5716  if (fd < 0) {
5717  cob_free (filename);
5718  return NULL;
5719  }
5720  (void)unlink (filename);
5721  fp = fdopen (fd, "w+b");
5722  if (!fp) {
5723  close (fd);
5724  }
5725  cob_free (filename);
5726  return fp;
5727 }
5728 
5729 static int
5730 cob_get_sort_tempfile (struct cobsort *hp, const int n)
5731 {
5732  if (hp->file[n].fp == NULL) {
5733  hp->file[n].fp = cob_srttmpfile ();
5734  if (hp->file[n].fp == NULL) {
5735  cob_runtime_error (_("SORT is unable to acquire temporary file"));
5736  cob_stop_run (1);
5737  }
5738  } else {
5739  rewind (hp->file[n].fp);
5740  }
5741  hp->file[n].count = 0;
5742  return hp->file[n].fp == NULL;
5743 }
5744 
5745 static int
5747 {
5748  struct cobitem *q;
5749  int source;
5750  int destination;
5751  int move;
5752  int n;
5753  int end_of_block[2];
5754 
5755  source = 0;
5756  while (hp->queue[source + 1].count != 0) {
5757  destination = source ^ 2;
5758  hp->queue[destination].first = NULL;
5759  hp->queue[destination].count = 0;
5760  hp->queue[destination + 1].first = NULL;
5761  hp->queue[destination + 1].count = 0;
5762  for (;;) {
5763  end_of_block[0] = hp->queue[source].count == 0;
5764  end_of_block[1] = hp->queue[source + 1].count == 0;
5765  if (end_of_block[0] && end_of_block[1]) {
5766  break;
5767  }
5768  while (!end_of_block[0] || !end_of_block[1]) {
5769  if (end_of_block[0]) {
5770  move = 1;
5771  } else if (end_of_block[1]) {
5772  move = 0;
5773  } else {
5775  (hp->queue[source].first,
5776  hp->queue[source + 1].first,
5777  hp->pointer);
5778  move = n < 0 ? 0 : 1;
5779  }
5780  q = hp->queue[source + move].first;
5781  if (q->end_of_block) {
5782  end_of_block[move] = 1;
5783  }
5784  hp->queue[source + move].first = q->next;
5785  if (hp->queue[destination].first == NULL) {
5786  hp->queue[destination].first = q;
5787  } else {
5788  hp->queue[destination].last->next = q;
5789  }
5790  hp->queue[destination].last = q;
5791  hp->queue[source + move].count--;
5792  hp->queue[destination].count++;
5793  q->next = NULL;
5794  q->end_of_block = 0;
5795  }
5796  hp->queue[destination].last->end_of_block = 1;
5797  destination ^= 1;
5798  }
5799  source = destination & 2;
5800  }
5801  return source;
5802 }
5803 
5804 static int
5805 cob_read_item (struct cobsort *hp, const int n)
5806 {
5807  FILE *fp;
5808 
5809  fp = hp->file[n].fp;
5810  if (getc (fp) != 0) {
5811  hp->queue[n].first->end_of_block = 1;
5812  } else {
5813  hp->queue[n].first->end_of_block = 0;
5814  if (unlikely(fread (hp->queue[n].first->unique, hp->r_size, (size_t)1, fp) != 1)) {
5815  return 1;
5816  }
5817  }
5818  return 0;
5819 }
5820 
5821 static int
5822 cob_write_block (struct cobsort *hp, const int n)
5823 {
5824  struct cobitem *q;
5825  FILE *fp;
5826 
5827  fp = hp->file[hp->destination_file].fp;
5828  for (;;) {
5829  q = hp->queue[n].first;
5830  if (q == NULL) {
5831  break;
5832  }
5833  if (unlikely(fwrite (&(q->block_byte), hp->w_size, (size_t)1, fp) != 1)) {
5834  return 1;
5835  }
5836  hp->queue[n].first = q->next;
5837  q->next = hp->empty;
5838  hp->empty = q;
5839  }
5840  hp->queue[n].count = 0;
5841  hp->file[hp->destination_file].count++;
5842  if (unlikely(putc (1, fp) != 1)) {
5843  return 1;
5844  }
5845  return 0;
5846 }
5847 
5848 static void
5850 {
5851  unsigned char *toptr;
5852  unsigned char *fromptr;
5853  size_t tosize;
5854  size_t fromsize;
5855 
5856  toptr = to->record->data;
5857  fromptr = from->record->data;
5858  tosize = to->record->size;
5859  fromsize = from->record->size;
5860  if (unlikely(tosize > fromsize)) {
5861  memcpy (toptr, fromptr, fromsize);
5862  memset (toptr + fromsize, ' ', tosize - fromsize);
5863  } else {
5864  memcpy (toptr, fromptr, tosize);
5865  }
5866 }
5867 
5868 static int
5870 {
5871  int i;
5872  int source;
5873  int destination;
5874  int n;
5875  int move;
5876  int res;
5877 
5878  hp->retrieving = 1;
5879  n = cob_sort_queues (hp);
5880 #if 0 /* RXWRXW - Cannot be true */
5881  if (unlikely(n < 0)) {
5882  return COBSORTABORT;
5883  }
5884 #endif
5885  if (likely(!hp->files_used)) {
5886  hp->retrieval_queue = n;
5887  return 0;
5888  }
5889  if (unlikely(cob_write_block (hp, n))) {
5890  return COBSORTFILEERR;
5891  }
5892  for (i = 0; i < 4; ++i) {
5893  hp->queue[i].first = hp->empty;
5894  hp->empty = hp->empty->next;
5895  hp->queue[i].first->next = NULL;
5896  }
5897  rewind (hp->file[0].fp);
5898  rewind (hp->file[1].fp);
5899  if (unlikely(cob_get_sort_tempfile (hp, 2))) {
5900  return COBSORTFILEERR;
5901  }
5902  if (unlikely(cob_get_sort_tempfile (hp, 3))) {
5903  return COBSORTFILEERR;
5904  }
5905  source = 0;
5906  while (hp->file[source].count > 1) {
5907  destination = source ^ 2;
5908  hp->file[destination].count = 0;
5909  hp->file[destination + 1].count = 0;
5910  while (hp->file[source].count > 0) {
5911  if (unlikely(cob_read_item (hp, source))) {
5912  return COBSORTFILEERR;
5913  }
5914  if (hp->file[source + 1].count > 0) {
5915  if (unlikely(cob_read_item (hp, source + 1))) {
5916  return COBSORTFILEERR;
5917  }
5918  } else {
5919  hp->queue[source + 1].first->end_of_block = 1;
5920  }
5921  while (!hp->queue[source].first->end_of_block ||
5922  !hp->queue[source + 1].first->end_of_block) {
5923  if (hp->queue[source].first->end_of_block) {
5924  move = 1;
5925  } else if (hp->queue[source + 1].first->end_of_block) {
5926  move = 0;
5927  } else {
5928  res = cob_file_sort_compare
5929  (hp->queue[source].first,
5930  hp->queue[source + 1].first,
5931  hp->pointer);
5932  move = res < 0 ? 0 : 1;
5933  }
5934  if (unlikely(fwrite (
5935  &(hp->queue[source + move].first->block_byte),
5936  hp->w_size, (size_t)1,
5937  hp->file[destination].fp) != 1)) {
5938  return COBSORTFILEERR;
5939  }
5940  if (unlikely(cob_read_item (hp, source + move))) {
5941  return COBSORTFILEERR;
5942  }
5943  }
5944  hp->file[destination].count++;
5945  if (unlikely(putc (1, hp->file[destination].fp) != 1)) {
5946  return COBSORTFILEERR;
5947  }
5948  hp->file[source].count--;
5949  hp->file[source + 1].count--;
5950  destination ^= 1;
5951  }
5952  source = destination & 2;
5953  rewind (hp->file[0].fp);
5954  rewind (hp->file[1].fp);
5955  rewind (hp->file[2].fp);
5956  rewind (hp->file[3].fp);
5957  }
5958  hp->retrieval_queue = source;
5959  if (unlikely(cob_read_item (hp, source))) {
5960  return COBSORTFILEERR;
5961  }
5962  if (unlikely(cob_read_item (hp, source + 1))) {
5963  return COBSORTFILEERR;
5964  }
5965  return 0;
5966 }
5967 
5968 static int
5969 cob_file_sort_submit (cob_file *f, const unsigned char *p)
5970 {
5971  struct cobsort *hp;
5972  struct cobitem *q;
5973  struct queue_struct *z;
5974  int n;
5975 
5976  hp = f->file;
5977  if (unlikely(!hp)) {
5978  return COBSORTNOTOPEN;
5979  }
5980  if (unlikely(hp->retrieving)) {
5981  return COBSORTABORT;
5982  }
5983  if (unlikely(hp->switch_to_file)) {
5984  if (!hp->files_used) {
5985  if (unlikely(cob_get_sort_tempfile (hp, 0))) {
5986  return COBSORTFILEERR;
5987  }
5988  if (unlikely(cob_get_sort_tempfile (hp, 1))) {
5989  return COBSORTFILEERR;
5990  }
5991  hp->files_used = 1;
5992  hp->destination_file = 0;
5993  }
5994  n = cob_sort_queues (hp);
5995 #if 0 /* RXWRXW - Cannot be true */
5996  if (unlikely(n < 0)) {
5997  return COBSORTABORT;
5998  }
5999 #endif
6000  if (unlikely(cob_write_block (hp, n))) {
6001  return COBSORTFILEERR;
6002  }
6003  hp->destination_file ^= 1;
6004  }
6005  q = cob_new_item (hp, sizeof (struct cobitem) + hp->size);
6006  q->end_of_block = 1;
6007  unique_copy (q->unique, (const unsigned char *)&(hp->unique));
6008  hp->unique++;
6009  memcpy (q->item, p, hp->size);
6010  if (hp->queue[0].count <= hp->queue[1].count) {
6011  z = &hp->queue[0];
6012  } else {
6013  z = &hp->queue[1];
6014  }
6015  q->next = z->first;
6016  z->first = q;
6017  z->count++;
6018  return 0;
6019 }
6020 
6021 static int
6022 cob_file_sort_retrieve (cob_file *f, unsigned char *p)
6023 {
6024  struct cobsort *hp;
6025  struct cobitem *next;
6026  struct queue_struct *z;
6027  int move;
6028  int source;
6029  int res;
6030 
6031  hp = f->file;
6032  if (unlikely(!hp)) {
6033  return COBSORTNOTOPEN;
6034  }
6035  if (unlikely(!hp->retrieving)) {
6036  res = cob_file_sort_process (hp);
6037  if (res) {
6038  return res;
6039  }
6040  }
6041  if (unlikely(hp->files_used)) {
6042  source = hp->retrieval_queue;
6043  if (hp->queue[source].first->end_of_block) {
6044  if (hp->queue[source + 1].first->end_of_block) {
6045  return COBSORTEND;
6046  }
6047  move = 1;
6048  } else if (hp->queue[source + 1].first->end_of_block) {
6049  move = 0;
6050  } else {
6051  res = cob_file_sort_compare (hp->queue[source].first,
6052  hp->queue[source + 1].first,
6053  hp->pointer);
6054  move = res < 0 ? 0 : 1;
6055  }
6056  memcpy (p, hp->queue[source + move].first->item, hp->size);
6057  if (unlikely(cob_read_item (hp, source + move))) {
6058  return COBSORTFILEERR;
6059  }
6060  } else {
6061  z = &hp->queue[hp->retrieval_queue];
6062  if (z->first == NULL) {
6063  return COBSORTEND;
6064  }
6065  memcpy (p, z->first->item, hp->size);
6066  next = z->first->next;
6067  z->first->next = hp->empty;
6068  hp->empty = z->first;
6069  z->first = next;
6070  }
6071  return 0;
6072 }
6073 
6074 void
6075 cob_file_sort_using (cob_file *sort_file, cob_file *data_file)
6076 {
6077  int ret;
6078 
6079  cob_open (data_file, COB_OPEN_INPUT, 0, NULL);
6080  for (;;) {
6081  cob_read_next (data_file, NULL, COB_READ_NEXT);
6082  if (data_file->file_status[0] != '0') {
6083  break;
6084  }
6085  cob_copy_check (sort_file, data_file);
6086  ret = cob_file_sort_submit (sort_file, sort_file->record->data);
6087  if (ret) {
6088  break;
6089  }
6090  }
6091  cob_close (data_file, NULL, COB_CLOSE_NORMAL, 0);
6092 }
6093 
6094 void
6095 cob_file_sort_giving (cob_file *sort_file, const size_t varcnt, ...)
6096 {
6097  cob_file **fbase;
6098  struct cobsort *hp;
6099  size_t i;
6100  int ret;
6101  int opt;
6102  va_list args;
6103 
6104  fbase = cob_malloc (varcnt * sizeof(cob_file *));
6105  va_start (args, varcnt);
6106  for (i = 0; i < varcnt; ++i) {
6107  fbase[i] = va_arg (args, cob_file *);
6108  }
6109  va_end (args);
6110  for (i = 0; i < varcnt; ++i) {
6111  cob_open (fbase[i], COB_OPEN_OUTPUT, 0, NULL);
6112  }
6113  for (;;) {
6114  ret = cob_file_sort_retrieve (sort_file, sort_file->record->data);
6115  if (ret) {
6116  if (ret == COBSORTEND) {
6117  sort_file->file_status[0] = '1';
6118  sort_file->file_status[1] = '0';
6119  } else {
6120  hp = sort_file->file;
6121  *(int *)(hp->sort_return) = 16;
6122  sort_file->file_status[0] = '3';
6123  sort_file->file_status[1] = '0';
6124  }
6125  break;
6126  }
6127  for (i = 0; i < varcnt; ++i) {
6128  if (COB_FILE_SPECIAL (fbase[i]) ||
6129  fbase[i]->organization == COB_ORG_LINE_SEQUENTIAL) {
6130  opt = COB_WRITE_BEFORE | COB_WRITE_LINES | 1;
6131  } else {
6132  opt = 0;
6133  }
6134  fbase[i]->record->size = fbase[i]->record_max;
6135  cob_copy_check (fbase[i], sort_file);
6136  cob_write (fbase[i], fbase[i]->record, opt, NULL, 0);
6137  }
6138  }
6139  for (i = 0; i < varcnt; ++i) {
6140  cob_close (fbase[i], NULL, COB_CLOSE_NORMAL, 0);
6141  }
6142  cob_free (fbase);
6143 }
6144 
6145 void
6146 cob_file_sort_init (cob_file *f, const unsigned int nkeys,
6147  const unsigned char *collating_sequence,
6148  void *sort_return, cob_field *fnstatus)
6149 {
6150  struct cobsort *p;
6151  size_t n;
6152 
6153  p = cob_malloc (sizeof (struct cobsort));
6154  p->fnstatus = fnstatus;
6155  p->size = f->record_max;
6156  p->r_size = f->record_max + sizeof(size_t);
6157  p->w_size = f->record_max + sizeof(size_t) + 1;
6158  n = sizeof (struct cobitem) - offsetof (struct cobitem, item);
6159  if (f->record_max <= n) {
6160  p->alloc_size = sizeof (struct cobitem);
6161  } else {
6162  p->alloc_size = offsetof (struct cobitem, item) + f->record_max;
6163  }
6164  if (p->alloc_size % sizeof(void *)) {
6165  p->alloc_size += sizeof(void *) - (p->alloc_size % sizeof(void *));
6166  }
6167  p->chunk_size = cobsetptr->cob_sort_chunk;
6168  if (p->chunk_size % p->alloc_size) {
6169  p->chunk_size += p->alloc_size - (p->chunk_size % p->alloc_size);
6170  }
6171  p->pointer = f;
6172  p->sort_return = sort_return;
6173  *(int *)sort_return = 0;
6174  p->mem_base = cob_fast_malloc (sizeof (struct sort_mem_struct));
6176  p->mem_base->next = NULL;
6177  p->mem_size = p->chunk_size;
6178  p->mem_total = p->chunk_size;
6179  f->file = p;
6180  f->keys = cob_malloc (sizeof (cob_file_key) * nkeys);
6181  f->nkeys = 0;
6182  if (collating_sequence) {
6183  f->sort_collating = collating_sequence;
6184  } else {
6185  f->sort_collating = COB_MODULE_PTR->collating_sequence;
6186  }
6187  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
6188 }
6189 
6190 void
6191 cob_file_sort_init_key (cob_file *f, cob_field *field, const int flag,
6192  const unsigned int offset)
6193 {
6194  f->keys[f->nkeys].field = field;
6195  f->keys[f->nkeys].flag = flag;
6196  f->keys[f->nkeys].offset = offset;
6197  f->nkeys++;
6198 }
6199 
6200 void
6202 {
6203  struct cobsort *hp;
6205  size_t i;
6206 
6207  fnstatus = NULL;
6208  hp = f->file;
6209  if (likely(hp)) {
6210  fnstatus = hp->fnstatus;
6211  cob_free_list (hp);
6212  for (i = 0; i < 4; ++i) {
6213  if (hp->file[i].fp != NULL) {
6214  fclose (hp->file[i].fp);
6215  }
6216  }
6217  cob_free (hp);
6218  }
6219  if (f->keys) {
6220  cob_free (f->keys);
6221  }
6222  f->file = NULL;
6223  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
6224 }
6225 
6226 void
6228 {
6229  struct cobsort *hp;
6231  int ret;
6232 
6233  fnstatus = NULL;
6234  hp = f->file;
6235  if (likely(hp)) {
6236  fnstatus = hp->fnstatus;
6237  }
6238  ret = cob_file_sort_submit (f, f->record->data);
6239  if (!ret) {
6240  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
6241  return;
6242  }
6243  if (likely(hp)) {
6244  *(int *)(hp->sort_return) = 16;
6245  }
6247 }
6248 
6249 void
6251 {
6252  struct cobsort *hp;
6254  int ret;
6255 
6256  fnstatus = NULL;
6257  hp = f->file;
6258  if (likely(hp)) {
6259  fnstatus = hp->fnstatus;
6260  }
6261  ret = cob_file_sort_retrieve (f, f->record->data);
6262  switch (ret) {
6263  case 0:
6264  save_status (f, fnstatus, COB_STATUS_00_SUCCESS);
6265  return;
6266  case COBSORTEND:
6267  save_status (f, fnstatus, COB_STATUS_10_END_OF_FILE);
6268  return;
6269  }
6270  if (likely(hp)) {
6271  *(int *)(hp->sort_return) = 16;
6272  }
6274 }
6275 
6276 /* Initialization/Termination
6277  cobsetpr-values with type ENV_PATH or ENV_STR
6278  like bdb_home and cob_file_path are taken care in cob_exit_common()!
6279 */
6280 
6281 void
6283 {
6284  struct file_list *l;
6285  struct file_list *p;
6286 
6287  for (l = file_cache; l; l = l->next) {
6288  if (l->file && l->file->open_mode != COB_OPEN_CLOSED &&
6289  l->file->open_mode != COB_OPEN_LOCKED &&
6290  !l->file->flag_nonexistent) {
6291  if (COB_FILE_SPECIAL (l->file)) {
6292  continue;
6293  }
6294  cob_close (l->file, NULL, COB_CLOSE_NORMAL, 0);
6295  if (cobsetptr->cob_display_warn) {
6298  (size_t)COB_FILE_MAX);
6299  fprintf (stderr, _("WARNING - Implicit CLOSE of %s ('%s')"),
6301  putc ('\n', stderr);
6302  fflush (stderr);
6303  }
6304  }
6305  }
6306 #ifdef WITH_DB
6307  if (bdb_env) {
6308  bdb_env->lock_id_free (bdb_env, bdb_lock_id);
6309  bdb_env->close (bdb_env, 0);
6310  bdb_env = NULL;
6311  }
6312  if (record_lock_object) {
6313  cob_free (record_lock_object);
6314  record_lock_object = NULL;
6315  }
6316  if (bdb_buff) {
6317  cob_free (bdb_buff);
6318  bdb_buff = NULL;
6319  }
6320 
6321 #elif defined(WITH_ANY_ISAM)
6322 #ifndef WITH_DISAM
6323  (void)iscleanup ();
6324 #endif
6325 #endif
6326 
6327 #if defined(WITH_INDEX_EXTFH) || defined(WITH_SEQRA_EXTFH)
6328  extfh_cob_exit_fileio ();
6329 #endif
6330 
6331  if (runtime_buffer) {
6333  runtime_buffer = NULL;
6334  }
6335 
6336  for (l = file_cache; l;) {
6337  p = l;
6338  l = l->next;
6339  cob_free (p);
6340  }
6341  file_cache = NULL;
6342 }
6343 
6344 void
6346 {
6347 
6348  cobglobptr = lptr;
6349  cobsetptr = sptr;
6350  file_cache = NULL;
6351  eop_status = 0;
6352  check_eop_status = 0;
6353  if (cobsetptr->cob_sort_chunk > (cobsetptr->cob_sort_memory / 2)) {
6354  cobsetptr->cob_sort_chunk = cobsetptr->cob_sort_memory / 2;
6355  }
6356 
6357  if(cobsetptr->cob_varseq_type == 3)
6358  cob_vsq_len = 2;
6359  else
6360  cob_vsq_len = 4;
6361 
6362  runtime_buffer = cob_fast_malloc ((size_t)(4 * COB_FILE_BUFF));
6366 
6367 #ifdef WITH_DB
6368  bdb_env = NULL;
6369  bdb_data_dir = NULL;
6370  join_environment ();
6371  record_lock_object = cob_malloc ((size_t)1024);
6372  bdb_buff = cob_malloc ((size_t)COB_SMALL_BUFF);
6373  rlo_size = 1024;
6374 #endif
6375 
6376 #if defined(WITH_INDEX_EXTFH) || defined(WITH_SEQRA_EXTFH)
6377  extfh_cob_init_fileio (&sequential_funcs, &lineseq_funcs,
6378  &relative_funcs, &cob_file_write_opt);
6379 #endif
6380 }
static unsigned int eop_status
Definition: fileio.c:237
cob_field * record
Definition: common.h:1115
void cob_file_sort_close(cob_file *f)
Definition: fileio.c:6201
#define COB_STATUS_42_NOT_OPEN
Definition: common.h:847
#define COB_WRITE_LINES
Definition: common.h:802
void cob_free(void *mptr)
Definition: common.c:1284
#define COB_STATUS_10_END_OF_FILE
Definition: common.h:833
void cob_delete_file(cob_file *f, cob_field *fnstatus)
Definition: fileio.c:4875
#define COBSORTNOTOPEN
Definition: fileio.c:173
int cob_sys_file_delete(unsigned char *file_name, unsigned char *file_type)
Definition: fileio.c:5555
#define COB_WRITE_MASK
Definition: common.h:800
unsigned int files_used
Definition: fileio.c:222
static int indexed_read_next(cob_file *, const int)
Definition: fileio.c:3543
#define COB_STATUS_41_ALREADY_OPEN
Definition: common.h:846
#define COB_FERROR_CODEGEN
Definition: common.h:693
struct sort_mem_struct * next
Definition: fileio.c:187
unsigned int cob_varseq_type
Definition: coblocal.h:233
static int relative_read(cob_file *, cob_field *, const int)
Definition: fileio.c:1675
struct file_struct file[4]
Definition: fileio.c:226
int lin_foot
Definition: common.h:1157
#define COB_GT
Definition: common.h:729
unsigned int cob_unix_lf
Definition: coblocal.h:228
static int cob_sort_queues(struct cobsort *hp)
Definition: fileio.c:5746
int retrieval_queue
Definition: fileio.c:224
cob_file * cob_error_file
Definition: common.h:1187
#define cob_u32_t
Definition: common.h:31
#define COBSORTABORT
Definition: fileio.c:171
static int sort_cmps(const unsigned char *s1, const unsigned char *s2, const size_t size, const unsigned char *col)
Definition: fileio.c:5578
struct sort_mem_struct * mem_base
Definition: fileio.c:210
static cob_settings * cobsetptr
Definition: fileio.c:235
int cob_add_int(cob_field *, const int, const int)
Definition: numeric.c:2195
int cob_sys_check_file_exist(unsigned char *file_name, unsigned char *file_info)
Definition: fileio.c:5239
cob_field * linage
Definition: common.h:1151
unsigned char organization
Definition: common.h:1127
void cob_write(cob_file *f, cob_field *rec, const int opt, cob_field *fnstatus, const unsigned int check_eop)
Definition: fileio.c:4754
unsigned int offset
Definition: common.h:1105
#define COBSORTFILEERR
Definition: fileio.c:172
int isrewrite(const int ihandle, char *pcrow)
Definition: isrewrite.c:144
#define fdcobsync
Definition: fileio.c:86
static int cob_get_sort_tempfile(struct cobsort *hp, const int n)
Definition: fileio.c:5730
#define COB_READ_NO_LOCK
Definition: common.h:818
static struct file_list * file_cache
Definition: fileio.c:241
int isindexinfo(const int ihandle, void *pskeydesc, const int ikeynumber)
Definition: isopen.c:221
#define COB_FILE_SPECIAL(x)
Definition: common.h:765
#define COB_STATUS_14_OUT_OF_KEY_RANGE
Definition: common.h:834
#define COB_FIELD_IS_NUMERIC(f)
Definition: common.h:674
static void cob_chk_file_mapping(void)
Definition: fileio.c:504
#define COB_STATUS_23_KEY_NOT_EXISTS
Definition: common.h:837
void cob_file_sort_init(cob_file *f, const unsigned int nkeys, const unsigned char *collating_sequence, void *sort_return, cob_field *fnstatus)
Definition: fileio.c:6146
int cob_sys_close_file(unsigned char *file_handle)
Definition: fileio.c:5144
cob_field * assign
Definition: common.h:1114
#define COB_LOCK_AUTOMATIC
Definition: common.h:775
unsigned int cob_display_warn
Definition: coblocal.h:204
static int sequential_write(cob_file *, const int)
Definition: fileio.c:1313
cob_field * lattop
Definition: common.h:1154
char * cob_file_path
Definition: coblocal.h:234
int cob_sys_rename_file(unsigned char *fname1, unsigned char *fname2)
Definition: fileio.c:5299
size_t mem_total
Definition: fileio.c:216
#define SLASH_STR
Definition: common.h:506
size_t size
Definition: fileio.c:212
int cob_sys_chdir(unsigned char *dir, unsigned char *status)
Definition: fileio.c:5453
size_t cob_sort_memory
Definition: coblocal.h:236
int isfullclose(const int ihandle)
Definition: isopen.c:209
#define COB_CHK_PARMS(x, z)
Definition: coblocal.h:167
#define COB_STATUS_61_FILE_SHARING
Definition: common.h:856
#define COB_STATUS_00_SUCCESS
Definition: common.h:828
static int cob_read_item(struct cobsort *hp, const int n)
Definition: fileio.c:5805
static int cob_file_close(cob_file *, const int)
Definition: fileio.c:1184
static const struct cob_fileio_funcs lineseq_funcs
Definition: fileio.c:317
#define COB_MAYSWAP_16(x)
Definition: fileio.c:164
void cob_rollback(void)
Definition: fileio.c:4863
static int cob_write_block(struct cobsort *hp, const int n)
Definition: fileio.c:5822
int(* rewrite)(cob_file *, const int)
Definition: common.h:1230
size_t r_size
Definition: fileio.c:218
#define COB_STATUS_35_NOT_EXISTS
Definition: common.h:842
int cob_sys_write_file(unsigned char *file_handle, unsigned char *file_offset, unsigned char *file_len, unsigned char *flags, unsigned char *buf)
Definition: fileio.c:5113
int(* read)(cob_file *, cob_field *, const int)
Definition: common.h:1227
#define COBSORTEND
Definition: fileio.c:170
void cob_file_sort_init_key(cob_file *f, cob_field *field, const int flag, const unsigned int offset)
Definition: fileio.c:6191
cob_field * field
Definition: common.h:1102
void cob_file_sort_using(cob_file *sort_file, cob_file *data_file)
Definition: fileio.c:6075
cob_field f2
Definition: cobxref.c.l.h:55
int cob_sys_mkdir(unsigned char *dir)
Definition: fileio.c:5439
void cob_exit_fileio(void)
Definition: fileio.c:6282
#define COB_SMALL_BUFF
Definition: common.h:540
int isreclen
Definition: vbmemio.c:29
static unsigned int cob_seq_write_opt(cob_file *f, const int opt)
Definition: fileio.c:809
static int indexed_write(cob_file *, const int)
Definition: fileio.c:4072
#define COB_READ_LAST
Definition: common.h:816
static int open_cbl_file(unsigned char *file_name, unsigned char *file_access, unsigned char *file_handle, const int file_flags)
Definition: fileio.c:4980
#define COB_INLINE
Definition: common.h:354
#define COB_ORG_INDEXED
Definition: common.h:745
#define COB_MAYSWAP_32(x)
Definition: fileio.c:165
static int indexed_start(cob_file *, const int, cob_field *)
Definition: fileio.c:3309
static void * cob_str_from_fld(const cob_field *f)
Definition: fileio.c:4928
static COB_INLINE void unique_copy(unsigned char *s1, const unsigned char *s2)
Definition: fileio.c:5601
int destination_file
Definition: fileio.c:223
cob_field * fnstatus
Definition: fileio.c:209
struct cobitem * next
Definition: fileio.c:178
static int relative_start(cob_file *, const int, cob_field *)
Definition: fileio.c:1553
static const struct cob_fileio_funcs relative_funcs
Definition: fileio.c:328
unsigned int cob_do_sync
Definition: coblocal.h:229
static int relative_delete(cob_file *)
Definition: fileio.c:1927
#define COB_OPEN_CLOSED
Definition: common.h:783
static int cob_file_sort_retrieve(cob_file *f, unsigned char *p)
Definition: fileio.c:6022
#define COB_ORG_MAX
Definition: common.h:747
static int sequential_rewrite(cob_file *, const int)
Definition: fileio.c:1383
static int dummy_read(cob_file *, cob_field *, const int)
Definition: fileio.c:448
size_t mem_size
Definition: fileio.c:214
#define COB_FILE_EXCLUSIVE
Definition: common.h:779
int iserase(char *pcfilename)
Definition: ishelper.c:36
void cob_read_next(cob_file *f, cob_field *fnstatus, const int read_opts)
Definition: fileio.c:4696
#define COB_READ_PREVIOUS
Definition: common.h:814
#define COB_SMALL_MAX
Definition: common.h:546
#define COB_LE
Definition: common.h:728
unsigned char unique[sizeof(size_t)]
Definition: fileio.c:181
unsigned char flag_operation
Definition: common.h:1133
#define COB_FI
Definition: common.h:732
unsigned char * data
Definition: common.h:952
#define COB_GE
Definition: common.h:730
#define COB_STATUS_05_SUCCESS_OPTIONAL
Definition: common.h:831
size_t cob_sort_chunk
Definition: coblocal.h:237
#define COB_SELECT_LINAGE
Definition: common.h:759
#define COB_WRITE_AFTER
Definition: common.h:805
#define cob_s64_t
Definition: common.h:51
static char * file_open_name
Definition: fileio.c:244
#define COB_BSWAP_32(val)
Definition: common.h:257
#define COB_STATUS_44_RECORD_OVERFLOW
Definition: common.h:849
static FILE * cob_srttmpfile(void)
Definition: fileio.c:5700
#define COB_BSWAP_16(val)
Definition: common.h:256
unsigned char flag_optional
Definition: common.h:1131
void cob_unlock_file(cob_file *f, cob_field *fnstatus)
Definition: fileio.c:4431
unsigned int retrieving
Definition: fileio.c:221
void cob_file_return(cob_file *f)
Definition: fileio.c:6250
#define COB_STATUS_07_SUCCESS_NO_UNIT
Definition: common.h:832
unsigned char * file_status
Definition: common.h:1113
#define COB_STATUS_39_CONFLICT_ATTRIBUTE
Definition: common.h:845
static void cob_free_list(struct cobsort *hp)
Definition: fileio.c:5646
int cob_call_params
Definition: common.h:1204
static const struct cob_fileio_funcs sequential_funcs
Definition: fileio.c:306
void * sort_return
Definition: fileio.c:208
static struct cobitem * cob_new_item(struct cobsort *hp, const size_t size)
Definition: fileio.c:5661
size_t unique
Definition: fileio.c:211
int isstart(const int ihandle, struct keydesc *pskeydesc, int ilength, char *pcrow, int imode)
Definition: isread.c:469
unsigned int cob_ls_nulls
Definition: coblocal.h:231
size_t record_min
Definition: common.h:1122
#define COB_READ_FIRST
Definition: common.h:815
#define COB_I2D(x)
Definition: coblocal.h:183
#define COB_STATUS_22_KEY_EXISTS
Definition: common.h:836
#define O_BINARY
Definition: fileio.c:90
static int indexed_rewrite(cob_file *, const int)
Definition: fileio.c:4200
int cob_get_int(cob_field *)
Definition: move.c:1626
int iswrite(const int ihandle, char *pcrow)
Definition: iswrite.c:156
void * linorkeyptr
Definition: common.h:1119
cob_field * latbot
Definition: common.h:1155
unsigned char lock_mode
Definition: common.h:1129
void cob_field_to_string(const cob_field *, void *, const size_t)
Definition: common.c:1492
static char * runtime_buffer
Definition: fileio.c:247
#define COB_READ_WAIT_LOCK
Definition: common.h:820
size_t record_max
Definition: common.h:1123
static int cob_file_sort_compare(struct cobitem *k1, struct cobitem *k2, void *pointer)
Definition: fileio.c:5612
void cob_fatal_error(const int fatal_error)
Definition: common.c:1601
#define COB_READ_MASK
Definition: common.h:823
#define COB_WRITE_PAGE
Definition: common.h:803
void cob_runtime_error(const char *,...) COB_A_FORMAT12
Definition: common.c:1543
int cob_numeric_cmp(cob_field *, cob_field *)
Definition: numeric.c:2348
#define cob_u8_ptr
Definition: common.h:66
#define COB_STATUS_46_READ_ERROR
Definition: common.h:850
#define _(s)
Definition: cobcrun.c:59
#define COB_OPEN_EXTEND
Definition: common.h:787
#define COB_FILE_BUFF
Definition: common.h:542
#define COB_OPEN_INPUT
Definition: common.h:784
static int indexed_open(cob_file *, char *, const int, const int)
Definition: fileio.c:2726
static cob_global * cobglobptr
Definition: fileio.c:234
size_t switch_to_file
Definition: fileio.c:220
#define unlikely(x)
Definition: common.h:437
static const int status_exception[]
Definition: fileio.c:249
int cob_sys_open_file(unsigned char *file_name, unsigned char *file_access, unsigned char *file_lock, unsigned char *file_dev, unsigned char *file_handle)
Definition: fileio.c:5026
#define COB_FILE_STDOUT(x)
Definition: common.h:768
#define COB_STATUS_04_SUCCESS_INCOMPLETE
Definition: common.h:830
#define F_OK
Definition: cobc.h:46
static int dummy_start(cob_file *, const int, cob_field *)
Definition: fileio.c:458
#define COB_STATUS_24_KEY_BOUNDARY
Definition: common.h:838
unsigned char * mem_ptr
Definition: fileio.c:188
static int cob_file_open(cob_file *, char *, const int, const int)
Definition: fileio.c:998
#define NUM_PREFIX
Definition: fileio.c:263
static int cob_file_sort_process(struct cobsort *hp)
Definition: fileio.c:5869
int isopen(const char *pcfilename, int imode)
Definition: isopen.c:270
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
static size_t cob_vsq_len
Definition: fileio.c:239
#define COB_CLOSE_NO_REWIND
Definition: common.h:794
static int indexed_read(cob_file *, cob_field *, const int)
Definition: fileio.c:3420
int cob_sys_flush_file(unsigned char *file_handle)
Definition: fileio.c:5155
#define COB_ORG_SEQUENTIAL
Definition: common.h:742
static const char *const prefix[]
Definition: fileio.c:262
#define COB_STATUS_48_OUTPUT_DENIED
Definition: common.h:852
void cob_start(cob_file *f, const int cond, cob_field *key, cob_field *keysize, cob_field *fnstatus)
Definition: fileio.c:4584
cob_field * linage_ctr
Definition: common.h:1152
struct cobitem * last
Definition: fileio.c:194
#define COB_STATUS_30_PERMANENT_ERROR
Definition: common.h:839
static int relative_read_next(cob_file *, const int)
Definition: fileio.c:1720
void * pointer
Definition: fileio.c:206
cob_field * latfoot
Definition: common.h:1153
size_t count
Definition: fileio.c:195
#define COB_FILE_MODE
Definition: common.h:738
static void save_status(cob_file *f, cob_field *fnstatus, const int status)
Definition: fileio.c:668
cob_field f1
Definition: cobxref.c.l.h:54
#define COB_OPEN_LOCKED
Definition: common.h:788
unsigned char end_of_block
Definition: fileio.c:179
int cob_sys_change_dir(unsigned char *dir)
Definition: fileio.c:5395
#define SLASH_CHAR
Definition: common.h:505
void cob_set_exception(const int id)
Definition: common.c:1212
#define COB_ORG_RELATIVE
Definition: common.h:744
#define COB_CLOSE_LOCK
Definition: common.h:793
int lin_lines
Definition: common.h:1156
unsigned int cob_ls_fixed
Definition: coblocal.h:232
void cob_open(cob_file *f, const int mode, const int sharing, cob_field *fnstatus)
Definition: fileio.c:4438
static unsigned int check_eop_status
Definition: fileio.c:238
int isdelete(const int ihandle, char *pcrow)
Definition: isdelete.c:120
struct cobitem * empty
Definition: fileio.c:207
static void indexed_file_delete(cob_file *f, const char *filename)
Definition: fileio.c:2695
#define COB_FILE_STDIN(x)
Definition: common.h:767
struct queue_struct queue[4]
Definition: fileio.c:225
char * bdb_home
Definition: coblocal.h:235
#define COB_STORE_KEEP_ON_OVERFLOW
Definition: common.h:868
unsigned char flag_first_read
Definition: common.h:1138
int cob_sys_file_info(unsigned char *file_name, unsigned char *file_info)
Definition: fileio.c:5491
unsigned char flag_read_done
Definition: common.h:1139
int isrewcurr(const int ihandle, char *pcrow)
Definition: isrewrite.c:235
cob_file_key * keys
Definition: common.h:1117
size_t mem_used
Definition: fileio.c:215
#define COB_ACCESS_SEQUENTIAL
Definition: common.h:751
static int indexed_delete(cob_file *)
Definition: fileio.c:4146
void cob_set_int(cob_field *, const int)
Definition: move.c:1612
void cob_commit(void)
Definition: fileio.c:4851
#define offsetof(s_name, m_name)
Definition: coblocal.h:173
#define COB_READ_IGNORE_LOCK
Definition: common.h:821
unsigned int cob_ls_uses_cr
Definition: coblocal.h:230
#define COB_MODULE_PTR
Definition: coblocal.h:185
static char * file_open_buff
Definition: fileio.c:245
struct cobitem * first
Definition: fileio.c:193
int(* close)(cob_file *, const int)
Definition: common.h:1225
#define COB_STATUS_21_KEY_INVALID
Definition: common.h:835
static int dummy_rnxt_rewrite(cob_file *, const int)
Definition: fileio.c:439
#define COB_WRITE_BEFORE
Definition: common.h:806
#define COB_STATUS_38_CLOSED_WITH_LOCK
Definition: common.h:844
#define COB_OPEN_I_O
Definition: common.h:786
int iscleanup(void)
Definition: isopen.c:152
#define COB_STATUS_43_READ_NOT_DONE
Definition: common.h:848
size_t w_size
Definition: fileio.c:219
void cob_read(cob_file *f, cob_field *key, cob_field *fnstatus, const int read_opts)
Definition: fileio.c:4633
int(* read_next)(cob_file *, const int)
Definition: common.h:1228
static char * cob_chk_file_env(const char *src)
Definition: fileio.c:468
static int lineseq_write(cob_file *, const int)
Definition: fileio.c:1463
#define COB_EQ
Definition: common.h:726
#define COB_STATUS_49_I_O_DENIED
Definition: common.h:853
unsigned char flag_needs_top
Definition: common.h:1142
int cob_sys_read_file(unsigned char *file_handle, unsigned char *file_offset, unsigned char *file_len, unsigned char *flags, unsigned char *buf)
Definition: fileio.c:5066
int isaddindex(const int ihandle, struct keydesc *pskeydesc)
Definition: isbuild.c:577
static void cob_cache_file(cob_file *f)
Definition: fileio.c:652
#define COB_STATUS_57_I_O_LINAGE
Definition: common.h:855
#define COB_STATUS_51_RECORD_LOCKED
Definition: common.h:854
size_t size
Definition: common.h:951
struct file_list * next
Definition: fileio.c:156
static const struct cob_fileio_funcs * fileio_funcs[COB_ORG_MAX]
Definition: fileio.c:339
static int cob_file_sort_submit(cob_file *f, const unsigned char *p)
Definition: fileio.c:5969
FILE * fp
Definition: fileio.c:200
cob_field * variable_record
Definition: common.h:1116
void cob_incr_temp_iteration(void)
Definition: common.c:3266
int cob_sys_create_dir(unsigned char *dir)
Definition: fileio.c:5369
void cob_close(cob_file *f, cob_field *fnstatus, const int opt, const int remfil)
Definition: fileio.c:4498
int fd
Definition: common.h:1125
unsigned char flag_select_features
Definition: common.h:1140
static void cob_copy_check(cob_file *to, cob_file *from)
Definition: fileio.c:5849
size_t alloc_size
Definition: fileio.c:213
#define COB_LOCK_MULTIPLE
Definition: common.h:776
int(* start)(cob_file *, const int, cob_field *)
Definition: common.h:1226
char * cob_strdup(const char *)
Definition: common.c:1308
int cob_sys_get_current_dir(const int flags, const int dir_length, unsigned char *dir)
Definition: fileio.c:5328
cob_file * file
Definition: fileio.c:157
#define COB_STATUS_47_INPUT_DENIED
Definition: common.h:851
int cob_sys_create_file(unsigned char *file_name, unsigned char *file_access, unsigned char *file_lock, unsigned char *file_dev, unsigned char *file_handle)
Definition: fileio.c:5039
#define COB_ORG_SORT
Definition: common.h:746
#define COB_ACCESS_RANDOM
Definition: common.h:753
void * cob_malloc(const size_t size)
Definition: common.c:1250
unsigned char block_byte
Definition: fileio.c:180
int lin_bot
Definition: common.h:1159
int isbuild(const char *pcfilename, const int imaxrowlength, struct keydesc *pskey, int imode)
Definition: isbuild.c:310
const unsigned char * sort_collating
Definition: common.h:1120
unsigned char last_open_mode
Definition: common.h:1132
static int cob_file_write_opt(cob_file *, const int)
Definition: fileio.c:836
#define COB_ORG_LINE_SEQUENTIAL
Definition: common.h:743
#define COB_LOCK_OPEN_EXCLUSIVE
Definition: common.h:777
size_t chunk_size
Definition: fileio.c:217
unsigned int cob_env_mangle
Definition: coblocal.h:205
void cob_delete(cob_file *f, cob_field *fnstatus)
Definition: fileio.c:4829
int cob_sys_copyfile(unsigned char *fname1, unsigned char *fname2, unsigned char *file_type)
Definition: fileio.c:5470
#define COB_NOT_CONFIGURED
Definition: common.h:861
int(* write)(cob_file *, const int)
Definition: common.h:1229
static size_t file_linage_check(cob_file *f)
Definition: fileio.c:699
size_t count
Definition: fileio.c:201
int isflush(const int ihandle)
Definition: ishelper.c:58
#define W_OK
Definition: cobc.h:54
static char * file_open_env
Definition: fileio.c:243
void * cob_fast_malloc(const size_t size)
Definition: common.c:1296
#define COB_STATUS_02_SUCCESS_DUPLICATE
Definition: common.h:829
static int relative_rewrite(cob_file *, const int)
Definition: fileio.c:1886
#define COB_OPEN_OUTPUT
Definition: common.h:785
static int dummy_delete(cob_file *)
Definition: fileio.c:431
#define COB_LA
Definition: common.h:733
unsigned char flag_begin_of_file
Definition: common.h:1137
static int relative_write(cob_file *, const int)
Definition: fileio.c:1823
static int sequential_read(cob_file *, const int)
Definition: fileio.c:1249
#define R_OK
Definition: cobc.h:58
int cob_sys_delete_dir(unsigned char *dir)
Definition: fileio.c:5417
#define COB_READ_NEXT
Definition: common.h:813
int isread(const int ihandle, char *pcrow, int imode)
Definition: isread.c:250
void cob_file_release(cob_file *f)
Definition: fileio.c:6227
Definition: cobc.h:195
unsigned char open_mode
Definition: common.h:1130
size_t nkeys
Definition: common.h:1124
#define COB_CLOSE_NORMAL
Definition: common.h:792
void * file
Definition: common.h:1118
#define COB_WRITE_LOCK
Definition: common.h:808
#define cob_u64_t
Definition: common.h:52
static int cob_linage_write_opt(cob_file *f, const int opt)
Definition: fileio.c:740
unsigned char access_mode
Definition: common.h:1128
#define COB_UNUSED(z)
Definition: common.h:535
void cob_file_sort_giving(cob_file *sort_file, const size_t varcnt,...)
Definition: fileio.c:6095
#define COB_FILE_MAX
Definition: common.h:548
unsigned char flag_nonexistent
Definition: common.h:1134
unsigned char flag_end_of_file
Definition: common.h:1136
int cob_sys_copy_file(unsigned char *fname1, unsigned char *fname2)
Definition: fileio.c:5187
#define COB_STATUS_91_NOT_AVAILABLE
Definition: common.h:857
#define COB_ASCENDING
Definition: common.h:735
#define COB_LT
Definition: common.h:727
int isrelease(const int ihandle)
Definition: ishelper.c:126
unsigned char flag_needs_nl
Definition: common.h:1141
static const struct cob_fileio_funcs indexed_funcs
Definition: fileio.c:295
const char * select_name
Definition: common.h:1112
#define COB_STATUS_37_PERMISSION_DENIED
Definition: common.h:843
static void cob_sync(cob_file *f)
Definition: fileio.c:612
void cob_rewrite(cob_file *f, cob_field *rec, const int opt, cob_field *fnstatus)
Definition: fileio.c:4793
static int indexed_close(cob_file *, const int)
Definition: fileio.c:3234
#define COB_BSWAP_64(val)
Definition: common.h:258
int cob_sys_delete_file(unsigned char *file_name)
Definition: fileio.c:5165
int(* open)(cob_file *, char *, const int, const int)
Definition: common.h:1224
#define likely(x)
Definition: common.h:436
static void cob_file_unlock(cob_file *f)
Definition: fileio.c:4366
void cob_init_fileio(cob_global *lptr, cob_settings *sptr)
Definition: fileio.c:6345
#define COB_READ_LOCK
Definition: common.h:817
static int cob_fd_file_open(cob_file *f, char *filename, const int mode, const int sharing)
Definition: fileio.c:860
int iserrno
Definition: vbmemio.c:27
int isrecnum
Definition: vbmemio.c:30
unsigned char item[1]
Definition: fileio.c:182
int lin_top
Definition: common.h:1158
void cob_temp_name(char *filename, const char *ext)
Definition: common.c:3253
int(* fdelete)(cob_file *)
Definition: common.h:1231
void cob_stop_run(const int status)
Definition: common.c:1524
static int lineseq_read(cob_file *, const int)
Definition: fileio.c:1408