diff --git a/libcob/ChangeLog b/libcob/ChangeLog index fe972dd3b..492b5f6e3 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -1,4 +1,10 @@ +2024-01-19 Simon Sobisch + + * fileio.c (indexed_keylen): signature change to directly take the keydesc + * fileio.c [WITH_ANY_ISAM]: refactored to ease access to keydesc and keypart + * fileio.c (indexed_open) [WITH_ANY_ISAM]: refactored + 2023-12-14 David Declerck * common.c (cob_terminate_routines, cob_call_with_exception_check): @@ -596,7 +602,7 @@ after suggestions by Chuck Haatvedt * fileio.c (open_next): set binary file mode, minor refactoring * fileio.c (cob_file_close) [_WIN32]: don't try to unlock invalid file handles; mark file descriptor as closed when file handle was closed - + 2023-02-06 Simon Sobisch * numeric.c (cob_decimal_get_packed, cob_decimal_get_display): @@ -6239,7 +6245,7 @@ after suggestions by Chuck Haatvedt * call.c, common.c, move.c, Makefile.am: gettextized -Copyright 2002-2023 Free Software Foundation, Inc. +Copyright 2002-2024 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. diff --git a/libcob/fileio.c b/libcob/fileio.c index 4a644e1fe..7272878f7 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2012, 2014-2023 Free Software Foundation, Inc. + Copyright (C) 2002-2012, 2014-2024 Free Software Foundation, Inc. Written by Keisuke Nishida, Roger While, Simon Sobisch, Ron Norman This file is part of GnuCOBOL. @@ -191,12 +191,12 @@ struct indexfile { /* Return total length of the key */ static int -indexed_keylen (struct indexfile *fh, int idx) +indexed_keylen (const struct keydesc *key) { int totlen, part; totlen = 0; - for (part = 0; part < fh->key[idx].k_nparts; part++) { - totlen += fh->key[idx].k_part[part].kp_leng; + for (part = 0; part < key->k_nparts; part++) { + totlen += key->k_part[part].kp_leng; } return totlen; } @@ -206,16 +206,16 @@ indexed_keylen (struct indexfile *fh, int idx) static int indexed_savekey (struct indexfile *fh, unsigned char *data, int idx) { - int totlen, part; - totlen = 0; + const struct keydesc *key = &fh->key[idx]; + int totlen = 0; + int part; if (data == NULL) { data = (unsigned char*)fh->recwrk; } - for (part = 0; part < fh->key[idx].k_nparts; part++) { - memcpy (fh->savekey + totlen, - data + fh->key[idx].k_part[part].kp_start, - fh->key[idx].k_part[part].kp_leng); - totlen += fh->key[idx].k_part[part].kp_leng; + for (part = 0; part < key->k_nparts; part++) { + const struct keypart *k_part = &key->k_part[part]; + memcpy (fh->savekey + totlen, data + k_part->kp_start, k_part->kp_leng); + totlen += k_part->kp_leng; } return totlen; } @@ -225,16 +225,16 @@ indexed_savekey (struct indexfile *fh, unsigned char *data, int idx) static int indexed_restorekey (struct indexfile *fh, unsigned char *data, int idx) { + const struct keydesc *key = &fh->key[idx]; int totlen, part; totlen = 0; if (data == NULL) { data = (unsigned char*)fh->recwrk; } - for (part = 0; part < fh->key[idx].k_nparts; part++) { - memcpy (data + fh->key[idx].k_part[part].kp_start, - fh->savekey + totlen, - fh->key[idx].k_part[part].kp_leng); - totlen += fh->key[idx].k_part[part].kp_leng; + for (part = 0; part < key->k_nparts; part++) { + const struct keypart *k_part = &key->k_part[part]; + memcpy (data + k_part->kp_start, fh->savekey + totlen, k_part->kp_leng); + totlen += k_part->kp_leng; } return totlen; } @@ -244,20 +244,21 @@ indexed_restorekey (struct indexfile *fh, unsigned char *data, int idx) static int indexed_cmpkey (struct indexfile *fh, unsigned char *data, int idx, int partlen) { - int sts, part, totlen,cl; + const struct keydesc *key = &fh->key[idx]; + int sts, part, totlen; totlen = sts = 0; if (partlen <= 0) { - partlen = indexed_keylen(fh, idx); + partlen = indexed_keylen (key); } - for (part = 0; part < fh->key[idx].k_nparts && partlen > 0; part++) { - cl = partlen > fh->key[idx].k_part[part].kp_leng ? fh->key[idx].k_part[part].kp_leng : partlen; - sts = memcmp( data + fh->key[idx].k_part[part].kp_start, - fh->savekey + totlen, cl); + for (part = 0; part < key->k_nparts && partlen > 0; part++) { + const struct keypart *k_part = &key->k_part[part]; + const int cl = partlen > k_part->kp_leng ? k_part->kp_leng : partlen; + sts = memcmp (data + k_part->kp_start, fh->savekey + totlen, cl); if (sts != 0) { return sts; } - totlen += fh->key[idx].k_part[part].kp_leng; - partlen -= fh->key[idx].k_part[part].kp_leng; + totlen += k_part->kp_leng; + partlen -= k_part->kp_leng; } return sts; } @@ -267,7 +268,7 @@ indexed_cmpkey (struct indexfile *fh, unsigned char *data, int idx, int partlen) static int indexed_keydesc (cob_file *f, struct keydesc *kd, cob_file_key *key) { - int keylen,part; + int keylen, part; memset (kd,0,sizeof (struct keydesc)); kd->k_flags = key->tf_duplicates ? ISDUPS : ISNODUPS; if (key->count_components < 1) { @@ -301,14 +302,15 @@ indexed_keydesc (cob_file *f, struct keydesc *kd, cob_file_key *key) /* LCOV_EXCL_STOP */ keylen = 0; for (part=0; part < key->count_components; part++) { - kd->k_part[part].kp_start = key->component[part]->data - f->record->data; - kd->k_part[part].kp_leng = key->component[part]->size; - keylen += kd->k_part[part].kp_leng; - kd->k_part[part].kp_type = CHARTYPE; + struct keypart *k_part = &kd->k_part[part]; + k_part->kp_start = key->component[part]->data - f->record->data; + k_part->kp_leng = key->component[part]->size; + keylen += k_part->kp_leng; + k_part->kp_type = CHARTYPE; if (key->tf_suppress) { #ifdef NULLKEY kd->k_flags |= NULLKEY; - kd->k_part[part].kp_type = CHARTYPE | (key->char_suppress << 8); + k_part->kp_type = CHARTYPE | (key->char_suppress << 8); #else #if 0 /* TODO: SUPPRESS string not merged yet */ f->flag_write_chk_dups = 1; @@ -331,20 +333,16 @@ static int indexed_keycmp (struct keydesc *k1, struct keydesc *k2) { int part; - if (k1->k_flags != k2->k_flags) { + if (k1->k_flags != k2->k_flags + || k1->k_nparts != k2->k_nparts) { return 1; } - if (k1->k_nparts != k2->k_nparts) { - return 1; - } - for (part=0; part < k1->k_nparts; part++) { - if (k1->k_part[part].kp_start != k2->k_part[part].kp_start) { - return 1; - } - if (k1->k_part[part].kp_leng != k2->k_part[part].kp_leng) { - return 1; - } - if (k1->k_part[part].kp_type != k2->k_part[part].kp_type) { + for (part = 0; part < k1->k_nparts; part++) { + const struct keypart *k_part1 = &k1->k_part[part]; + const struct keypart *k_part2 = &k2->k_part[part]; + if (k_part1->kp_start != k_part2->kp_start + || k_part1->kp_leng != k_part2->kp_leng + || k_part1->kp_type != k_part2->kp_type) { return 1; } } @@ -377,7 +375,7 @@ cob_findkey_attr (cob_file *f, cob_field *kf, int *fullkeylen, int *partlen) && key->data == kf->data && key->size == kf->size) || (f->keys[k].component[0]->data == kf->data)) { - for (part=0; part < f->keys[k].count_components; part++) { + for (part = 0; part < f->keys[k].count_components; part++) { *fullkeylen += f->keys[k].component[part]->size; } if (key @@ -1111,7 +1109,7 @@ cob_chk_file_mapping (void) /* Simple case - No separators [note: this is also the ACU and Fujitsu way] */ if (!looks_absolute (src) && !has_directory_separator (src)) { - + /* Drop surrounding quotes, some implementations need those to support filename with embedded spaces (like MF), while others (like GC before 3.2) don't like them */ @@ -2505,7 +2503,7 @@ lineseq_read (cob_file *f, const int read_opts) dataptr = f->record->data; again: fp = (FILE *)f->file; - /* save last position at start of line; needed for REWRITE (I-O only) */ + /* save last position at start of line; needed for REWRITE (I-O only) */ if (f->open_mode == COB_OPEN_I_O) { f->record_off = ftell (fp); /* Note: at least on Win32 the offset resolved does only return the right values @@ -2727,7 +2725,7 @@ lineseq_write (cob_file *f, const int opt) f->flag_needs_nl = 1; } - /* save last position at start of line; needed for REWRITE (I-O only) */ + /* save last position at start of line; needed for REWRITE (I-O only) */ if (f->open_mode == COB_OPEN_I_O) { f->record_off = ftell (fp); /* Note: at least on Win32 the offset resolved does only return the right values @@ -3407,12 +3405,11 @@ freefh (struct indexfile *fh) static void restorefileposition (cob_file *f) { - struct indexfile *fh; - struct keydesc k0; + struct indexfile *fh = f->file; - fh = f->file; - memset ((void *)&k0, 0, sizeof (k0)); if (fh->saverecnum >= 0) { + struct keydesc *key = &fh->key[f->curkey]; + struct keydesc k0 = { 0 }; /* Switch back to index */ ISRECNUM = fh->saverecnum; /* Switch to recnum mode */ @@ -3420,8 +3417,7 @@ restorefileposition (cob_file *f) /* Read by record number */ isread (fh->isfd, (void *)fh->recwrk, ISEQUAL); /* Read by current key value */ - isstart (fh->isfd, &fh->key[f->curkey], 0, - (void *)fh->recwrk, ISGTEQ); + isstart (fh->isfd, key, 0, (void *)fh->recwrk, ISGTEQ); isread (fh->isfd, (void *)fh->recwrk, ISGTEQ); while (ISRECNUM != fh->saverecnum) { /* Read back into position */ @@ -3438,9 +3434,9 @@ restorefileposition (cob_file *f) } } } else if (fh->readdone && f->curkey == 0) { + struct keydesc *key = &fh->key[0]; indexed_restorekey(fh, NULL, 0); - isstart (fh->isfd, &fh->key[f->curkey], 0, - (void *)fh->recwrk, ISGTEQ); + isstart (fh->isfd, key, 0, (void *)fh->recwrk, ISGTEQ); } } @@ -3726,13 +3722,8 @@ static int indexed_write_internal (cob_file *f, const int rewrite, const int opt) { struct indexed_file *p = f->file; - cob_u32_t i, len; - unsigned int dupno; - cob_u32_t flags = 0; - int close_cursor, ret; - - close_cursor = bdb_open_cursor (f, 1); - ret = COB_STATUS_00_SUCCESS; + const int close_cursor = bdb_open_cursor (f, 1); + cob_u32_t i; /* Check duplicate alternate keys */ if (f->nkeys > 1 && !rewrite) { @@ -3761,6 +3752,8 @@ indexed_write_internal (cob_file *f, const int rewrite, const int opt) /* Write secondary keys */ p->data = p->key; for (i = 1; i < f->nkeys; ++i) { + cob_u32_t flags, len; + int ret; if (rewrite && ! p->rewrite_sec_key[i]) { continue; } @@ -3770,8 +3763,8 @@ indexed_write_internal (cob_file *f, const int rewrite, const int opt) bdb_setkey (f, i); memset ((void*)&p->data, 0, sizeof (DBT)); if (f->keys[i].tf_duplicates) { + unsigned int dupno = get_dupno (f, i); flags = 0; - dupno = get_dupno (f, i); if (dupno > 1) { ret = COB_STATUS_02_SUCCESS_DUPLICATE; } @@ -3786,7 +3779,6 @@ indexed_write_internal (cob_file *f, const int rewrite, const int opt) p->data.data = p->temp_key; p->data.size = (cob_dbtsize_t)len; flags = DB_NOOVERWRITE; - dupno = 0; } bdb_setkey (f, i); @@ -3819,7 +3811,7 @@ indexed_write_internal (cob_file *f, const int rewrite, const int opt) return COB_STATUS_51_RECORD_LOCKED; } } - return ret; + return COB_STATUS_00_SUCCESS; } static int @@ -4199,15 +4191,13 @@ indexed_open (cob_file *f, char *filename, struct indexfile *fh; size_t k; - int ret,len; + int ret, len; int omode; int lmode; int vmode; int dobld; int isfd; int checkvalue; - struct keydesc kd; - struct dictinfo di; /* Defined in (c|d|vb)isam.h */ COB_UNUSED (sharing); @@ -4311,17 +4301,17 @@ indexed_open (cob_file *f, char *filename, } fh = cob_malloc (sizeof (struct indexfile) + ((sizeof (struct keydesc)) * (f->nkeys + 1))); - /* Copy index information */ - for (k = 0; k < f->nkeys; ++k) { - len = indexed_keydesc(f, &fh->key[k], &f->keys[k]); - if (fh->lenkey < len) { - fh->lenkey = len; - } - } ISERRNO = 0; fh->lmode = 0; if (dobld) { dobuild: + /* copy index information cob_file_key -> keydesc */ + for (k = 0; k < f->nkeys; ++k) { + len = indexed_keydesc (f, &fh->key[k], &f->keys[k]); + if (fh->lenkey < len) { + fh->lenkey = len; + } + } isfd = isbuild ((void *)filename, (int)f->record_max, &fh->key[0], vmode | ISINOUT | ISEXCLLOCK); #if 0 /* activate on later merge of locking enhancements */ @@ -4346,9 +4336,41 @@ indexed_open (cob_file *f, char *filename, lmode = ISMANULOCK; } isfd = isopen ((void *)filename, omode | lmode | vmode); - if (isfd < 0) { - if (ISERRNO == EFLOCKED) + if (isfd >= 0) { + struct dictinfo di = { 0 }; /* Defined in (c|d|vb)isam.h */ + isindexinfo (isfd, (void *)&di, 0); + /* Mask off ISVARLEN */ + fh->nkeys = di.di_nkeys & 0x7F; + if (fh->nkeys != f->nkeys + || f->record_max != di.di_recsize) { + ret = COB_STATUS_39_CONFLICT_ATTRIBUTE; + } + for (k = 0; k < fh->nkeys && !ret; ++k) { + struct keydesc kd = { 0 }; + /* get key info from ISAM */ + struct keydesc key = { 0 }; /* init to prevent analyzer warning */ + int len_key; + isindexinfo (isfd, &key, (int)(k + 1)); + len = indexed_keylen (&key); + if (fh->lenkey < len) { + fh->lenkey = len; + } + /* get key info from cob_key */ + len_key = indexed_keydesc (f, &kd, &f->keys[k]); + /* verify that COBOL keys match exactly to real ISAM keys */ + if (len_key != len + || indexed_keycmp (&kd, &key) != 0) { + ret = COB_STATUS_39_CONFLICT_ATTRIBUTE; + break; + } + /* store ISAM key definition */ + memcpy (&fh->key[k], &key, sizeof (struct keydesc)); + } + } else { /* opening the file is not possible */ + if (ISERRNO == EFLOCKED) { + freefh (fh); return COB_STATUS_61_FILE_SHARING; + } if (f->flag_optional) { if (mode == COB_OPEN_EXTEND || mode == COB_OPEN_I_O) { @@ -4366,33 +4388,6 @@ indexed_open (cob_file *f, char *filename, f->flag_nonexistent = 1; return COB_STATUS_05_SUCCESS_OPTIONAL; } - } else { - memset(&di, 0, sizeof (di)); - isindexinfo (isfd, (void *)&di, 0); - /* Mask off ISVARLEN */ - fh->nkeys = di.di_nkeys & 0x7F; - if (fh->nkeys != f->nkeys) { - ret = COB_STATUS_39_CONFLICT_ATTRIBUTE; - } - if (f->record_max != di.di_recsize) { - ret = COB_STATUS_39_CONFLICT_ATTRIBUTE; - } - for (k = 0; k < fh->nkeys && !ret; ++k) { - memset (&fh->key[k], 0, sizeof (struct keydesc)); - isindexinfo (isfd, &fh->key[k], (int)(k+1)); - if (fh->lenkey < indexed_keylen(fh, k)) { - fh->lenkey = indexed_keylen(fh, k); - } - /* Verify that COBOL keys match exactly to real ISAM keys */ - len = indexed_keydesc(f, &kd, &f->keys[k]); - if (fh->lenkey < len) { - fh->lenkey = len; - } - if(indexed_keycmp(&kd, &fh->key[k]) != 0) { - ret = COB_STATUS_39_CONFLICT_ATTRIBUTE; - break; - } - } } } if (isfd < 0) { @@ -4831,13 +4826,13 @@ indexed_start (cob_file *f, const int cond, cob_field *key) #elif defined(WITH_ANY_ISAM) - struct indexfile *fh; + struct indexfile *fh = f->file; int k; int mode; int klen,fullkeylen,partlen; int savecond; + struct keydesc *keyd; - fh = f->file; f->flag_read_done = 0; f->flag_first_read = 0; fh->readdone = 0; @@ -4852,6 +4847,7 @@ indexed_start (cob_file *f, const int cond, cob_field *key) return COB_STATUS_23_KEY_NOT_EXISTS; } f->mapkey = k; + keyd = &fh->key[k]; /* Use size of data field; This may indicate a partial key */ klen = partlen; if (klen < 1 || klen > fullkeylen) { @@ -4893,9 +4889,9 @@ indexed_start (cob_file *f, const int cond, cob_field *key) default: return COB_STATUS_21_KEY_INVALID; } - if (isstart (fh->isfd, &fh->key[k], klen, (void *)f->record->data, mode)) { + if (isstart (fh->isfd, keyd, klen, (void *)f->record->data, mode)) { if (cond == COB_LE || cond == COB_LT) { - if (isstart (fh->isfd, &fh->key[k], klen, (void *)f->record->data, ISLAST)) { + if (isstart (fh->isfd, keyd, klen, (void *)f->record->data, ISLAST)) { f->curkey = -1; f->mapkey = -1; fh->startcond = -1; @@ -4915,7 +4911,7 @@ indexed_start (cob_file *f, const int cond, cob_field *key) } } fh->startcond = savecond; - indexed_savekey(fh, f->record->data, k); + indexed_savekey (fh, f->record->data, k); f->curkey = k; f->flag_end_of_file = 0; f->flag_begin_of_file = 0; @@ -5008,7 +5004,7 @@ indexed_read (cob_file *f, cob_field *key, const int read_opts) fh->readdone = 1; f->flag_end_of_file = 0; f->flag_begin_of_file = 0; - indexed_savekey(fh, f->record->data, 0); + indexed_savekey (fh, f->record->data, 0); fh->recnum = ISRECNUM; #ifdef ISVARLEN if (f->record_min != f->record_max) { @@ -5140,7 +5136,7 @@ indexed_read_next (cob_file *f, const int read_opts) case COB_GE: domoveback = 0; while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) == 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) == 0) { isread (fh->isfd, (void *)f->record->data, ISPREV); domoveback = 1; } @@ -5151,7 +5147,7 @@ indexed_read_next (cob_file *f, const int read_opts) case COB_LE: domoveback = 0; while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) == 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) == 0) { isread (fh->isfd, (void *)f->record->data, ISNEXT); domoveback = 1; } @@ -5160,15 +5156,17 @@ indexed_read_next (cob_file *f, const int read_opts) } break; case COB_LT: +#if 0 /* CHECKME, not in GC4 */ isread (fh->isfd, (void *)f->record->data, ISPREV); +#endif while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) >= 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) >= 0) { isread (fh->isfd, (void *)f->record->data, ISPREV); } break; case COB_GT: while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) <= 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) <= 0) { isread (fh->isfd, (void *)f->record->data, ISNEXT); } break; @@ -5218,12 +5216,12 @@ indexed_read_next (cob_file *f, const int read_opts) } else { switch (fh->startcond) { case COB_LE: - if(indexed_cmpkey(fh, f->record->data, f->curkey, 0) > 0) + if (indexed_cmpkey (fh, f->record->data, f->curkey, 0) > 0) domoveback = 1; else domoveback = 0; while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) == 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) == 0) { isread (fh->isfd, (void *)f->record->data, ISNEXT); domoveback = 1; } @@ -5233,19 +5231,19 @@ indexed_read_next (cob_file *f, const int read_opts) break; case COB_LT: while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) >= 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) >= 0) { isread (fh->isfd, (void *)f->record->data, ISPREV); } break; case COB_GT: while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) <= 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) <= 0) { isread (fh->isfd, (void *)f->record->data, ISNEXT); } break; case COB_GE: while (ISERRNO == 0 - && indexed_cmpkey(fh, f->record->data, f->curkey, 0) < 0) { + && indexed_cmpkey (fh, f->record->data, f->curkey, 0) < 0) { isread (fh->isfd, (void *)f->record->data, ISNEXT); } break; @@ -5307,7 +5305,7 @@ indexed_read_next (cob_file *f, const int read_opts) fh->readdone = 1; f->flag_end_of_file = 0; f->flag_begin_of_file = 0; - indexed_savekey(fh, f->record->data, 0); + indexed_savekey (fh, f->record->data, 0); fh->recnum = ISRECNUM; #ifdef ISVARLEN if (f->record_min != f->record_max) { @@ -5316,11 +5314,12 @@ indexed_read_next (cob_file *f, const int read_opts) #endif #ifdef COB_WITH_STATUS_02 - if((isstat1 == '0') && (isstat2 == '2')) { + if (isstat1 == '0' + && isstat2 == '2') { return COB_STATUS_02_SUCCESS_DUPLICATE; } #endif - return 0; + return COB_STATUS_00_SUCCESS; #elif defined(WITH_DB) @@ -5427,7 +5426,7 @@ indexed_read_next (cob_file *f, const int read_opts) if (nextprev == DB_FIRST || nextprev == DB_LAST) { read_nextprev = 1; } else { - p->key.size = (cob_dbtsize_t) bdb_keylen(f,p->key_index); + p->key.size = (cob_dbtsize_t) bdb_keylen (f, p->key_index); p->key.data = p->last_readkey[p->key_index]; ret = DB_SEQ (p->cursor[p->key_index], &p->key, &p->data, DB_SET_RANGE); /* ret != 0 possible, records may be deleted since last read */ @@ -5510,7 +5509,7 @@ indexed_read_next (cob_file *f, const int read_opts) } p->key.data = p->data.data; p->key.size = p->primekeylen; - ret = DB_GET (p->db[0], &p->key, &p->data, 0); + ret = DB_GET (p->db[0], &p->key, &p->data, 0); if (ret != 0) { bdb_close_index (f, p->key_index); bdb_close_cursor (f); @@ -5535,7 +5534,7 @@ indexed_read_next (cob_file *f, const int read_opts) memcpy (p->last_readkey[0], p->key.data, (size_t)p->key.size); } else { memcpy (p->last_readkey[p->key_index], p->temp_key, - bdb_keylen(f,p->key_index)); + bdb_keylen(f,p->key_index)); memcpy (p->last_readkey[p->key_index + f->nkeys], p->key.data, p->primekeylen); if (f->keys[p->key_index].tf_duplicates) { p->last_dupno[p->key_index] = dupno; @@ -5579,16 +5578,15 @@ indexed_write (cob_file *f, const int opt) #elif defined(WITH_ANY_ISAM) - struct indexfile *fh; + struct indexfile *fh = f->file; COB_UNUSED (opt); - fh = f->file; if (f->flag_nonexistent) { return COB_STATUS_48_OUTPUT_DENIED; } if (f->access_mode == COB_ACCESS_SEQUENTIAL - && indexed_cmpkey(fh, f->record->data, 0, 0) <= 0) { + && indexed_cmpkey (fh, f->record->data, 0, 0) <= 0) { return COB_STATUS_21_KEY_INVALID; } @@ -5608,14 +5606,15 @@ indexed_write (cob_file *f, const int opt) } return fisretsts (COB_STATUS_49_I_O_DENIED); } - indexed_savekey(fh, f->record->data, 0); + indexed_savekey (fh, f->record->data, 0); #ifdef COB_WITH_STATUS_02 - if((isstat1 == '0') && (isstat2 == '2')) { + if (isstat1 == '0' + && isstat2 == '2') { return COB_STATUS_02_SUCCESS_DUPLICATE; } #endif - return 0; + return COB_STATUS_00_SUCCESS; #elif defined(WITH_DB) @@ -5731,7 +5730,8 @@ indexed_rewrite (cob_file *f, const int opt) struct indexfile *fh; size_t k; - int ret, retdup; + int ret; + int retdup = 0; COB_UNUSED (opt); @@ -5742,21 +5742,21 @@ indexed_rewrite (cob_file *f, const int opt) } if (f->access_mode == COB_ACCESS_SEQUENTIAL - && indexed_cmpkey(fh, f->record->data, 0, 0) != 0) { + && indexed_cmpkey (fh, f->record->data, 0, 0) != 0) { return COB_STATUS_21_KEY_INVALID; } if (f->curkey >= 0) { /* Index is active */ /* Save record data */ memcpy (fh->recwrk, f->record->data, f->record_max); -/* RXWRXW - readdir */ + /* RXWRXW - readdir */ fh->readdir = ISNEXT; savefileposition (f); memcpy (fh->recwrk, f->record->data, f->record_max); if (f->curkey != 0) { /* Activate primary index */ - isstart (fh->isfd, &fh->key[0], 0, (void *)fh->recwrk, - ISEQUAL); + isstart (fh->isfd, &fh->key[0], fh->key[0].k_len, + (void *)fh->recwrk, ISEQUAL); } /* Verify record exists */ if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL)) { @@ -5764,12 +5764,13 @@ indexed_rewrite (cob_file *f, const int opt) return COB_STATUS_21_KEY_INVALID; } for (k = 1; k < f->nkeys && ret == COB_STATUS_00_SUCCESS; ++k) { - if (fh->key[k].k_flags & ISDUPS) { + struct keydesc *key = &fh->key[k]; + if (key->k_flags & ISDUPS) { continue; } memcpy (fh->recwrk, f->record->data, f->record_max); - isstart (fh->isfd, &fh->key[k], fh->key[k].k_leng, - (void *)fh->recwrk, ISEQUAL); + isstart (fh->isfd, key, key->k_leng, + (void *)fh->recwrk, ISEQUAL); if (!isread (fh->isfd, (void *)fh->recwrk, ISEQUAL) && ISRECNUM != fh->recnum) { ret = COB_STATUS_22_KEY_EXISTS; @@ -5778,8 +5779,8 @@ indexed_rewrite (cob_file *f, const int opt) } if (ret == COB_STATUS_00_SUCCESS) { memcpy (fh->recwrk, f->record->data, f->record_max); - isstart (fh->isfd, &fh->key[0], 0, (void *)fh->recwrk, - ISEQUAL); + isstart (fh->isfd, &fh->key[0], fh->key[0].k_len, + (void *)fh->recwrk, ISEQUAL); if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL | ISLOCK)) { ret = fisretsts (COB_STATUS_49_I_O_DENIED); } else { @@ -5792,16 +5793,16 @@ indexed_rewrite (cob_file *f, const int opt) ret = fisretsts (COB_STATUS_49_I_O_DENIED); } } - } - #ifdef COB_WITH_STATUS_02 - if (!ret && (isstat1 == '0') && (isstat2 == '2')) { - retdup = COB_STATUS_02_SUCCESS_DUPLICATE; - } + if (!ret && (isstat1 == '0') && (isstat2 == '2')) { + retdup = COB_STATUS_02_SUCCESS_DUPLICATE; + } #endif + } + restorefileposition (f); - } else { + } else { /* Index is not active */ memcpy (fh->recwrk, f->record->data, f->record_max); if (isread (fh->isfd, (void *)fh->recwrk, ISEQUAL | ISLOCK)) { @@ -5815,34 +5816,30 @@ indexed_rewrite (cob_file *f, const int opt) if (isrewrite (fh->isfd, (void *)f->record->data)) { ret = fisretsts (COB_STATUS_49_I_O_DENIED); } + } #ifdef COB_WITH_STATUS_02 - if (!ret && (isstat1 == '0') && (isstat2 == '2')) { - retdup = COB_STATUS_02_SUCCESS_DUPLICATE; - } -#endif + if (!ret && (isstat1 == '0') && (isstat2 == '2')) { + retdup = COB_STATUS_02_SUCCESS_DUPLICATE; } +#endif if (!ret) { if ((f->lock_mode & COB_LOCK_AUTOMATIC) && !(f->lock_mode & COB_LOCK_MULTIPLE)) { isrelease (fh->isfd); } -#ifdef COB_WITH_STATUS_02 - if ((isstat1 == '0') && (isstat2 == '2')) { - retdup = COB_STATUS_02_SUCCESS_DUPLICATE; - } -#endif } } + if (retdup) { /* FIXME: use (is_suppressed_key_value) or similar to verify - that the duplicate this is not a SUPPRESSed KEY */ - return retdup; + that the duplicate is not a SUPPRESSed KEY */ + return COB_STATUS_02_SUCCESS_DUPLICATE; } return ret; #elif defined(WITH_DB) - int ret; + int ret; if (f->flag_nonexistent) { return COB_STATUS_49_I_O_DENIED; @@ -5865,8 +5862,9 @@ indexed_rewrite (cob_file *f, const int opt) if (ret != COB_STATUS_00_SUCCESS) { bdb_close_cursor (f); - if (ret == COB_STATUS_23_KEY_NOT_EXISTS) + if (ret == COB_STATUS_23_KEY_NOT_EXISTS) { return COB_STATUS_21_KEY_INVALID; + } return ret; } @@ -8863,7 +8861,7 @@ update_file_to_fcd (cob_file *f, FCD3 *fcd, unsigned char *fnstatus) memcpy (fcd->fileStatus, f->file_status, 2); /* FIXME: use switch here */ if (f->open_mode == COB_OPEN_CLOSED - || f->open_mode == COB_OPEN_LOCKED) + || f->open_mode == COB_OPEN_LOCKED) fcd->openMode = OPEN_NOT_OPEN; else if( f->open_mode == COB_OPEN_INPUT) fcd->openMode = OPEN_INPUT; @@ -10175,7 +10173,7 @@ update_key_from_fcd (cob_file *f, FCD3 *fcd, cob_field *kf) && keylen < kf->size) { kf->size = keylen; } - } else + } else if (fcd->fileOrg == ORG_RELATIVE) { cob_field *rel_key = f->keys[0].field; /* set value in the key field (several functions don't pass this outside of "f") */ diff --git a/tests/testsuite.src/run_file.at b/tests/testsuite.src/run_file.at index 2ce70bc84..2126dec17 100644 --- a/tests/testsuite.src/run_file.at +++ b/tests/testsuite.src/run_file.at @@ -1,4 +1,4 @@ -## Copyright (C) 2003-2012, 2014-2023 Free Software Foundation, Inc. +## Copyright (C) 2003-2012, 2014-2024 Free Software Foundation, Inc. ## Written by Keisuke Nishida, Roger While, Simon Sobisch, Ron Norman, ## Brian Tiffin, Joe Robbins, Edward Hart ## @@ -256,12 +256,12 @@ AT_DATA([prog.cob], [ DATA DIVISION. FILE SECTION. FD TEST-XML00 RECORD VARYING FROM 5 TO 500 CHARACTERS. - 01 E-ENR PIC X(500). + 01 E-ENR PIC X(500). WORKING-STORAGE SECTION. - 01 ST-TEST PIC X(2). - 01 W-TYPE PIC 9(03) VALUE ZERO. + 01 ST-TEST PIC X(2). + 01 W-TYPE PIC 9(03) VALUE ZERO. 01 EOF-TEST-XML PIC 9(03) VALUE ZERO. - 01 COUNT-PASS PIC 9(02) VALUE ZERO. + 01 COUNT-PASS PIC 9(02) VALUE ZERO. PROCEDURE DIVISION. DEBUT. OPEN INPUT TEST-XML00 @@ -1947,8 +1947,9 @@ AT_DATA([prog.cob], [ MOVE ALL "*" TO CM-TAPE. WRITE TSPFL-RECORD. - IF CUST-STAT NOT = "00" - AND CUST-STAT NOT = "02" + * Note: some ISAM implementations do not support status 02 + IF CUST-STAT NOT = "02" + AND CUST-STAT NOT = "00" DISPLAY "Key: " TSPFL-KEY ", Status: " CUST-STAT UPON CONSOLE. @@ -7156,9 +7157,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key1-2 START f KEY = f-key1-1 READ f NEXT - IF (f-status <> "00") OR - (file1-serial <> 4) - DISPLAY "FAILED 1: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 4) + DISPLAY "FAILED 1: status " f-status " - " "serial: " file1-serial END-IF @@ -7166,9 +7167,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key1-2 START f KEY < f-key1-1 READ f PREVIOUS - IF (f-status <> "00") OR - (file1-serial <> 3) - DISPLAY "FAILED 2: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 3) + DISPLAY "FAILED 2: status " f-status " - " "serial: " file1-serial END-IF @@ -7176,9 +7177,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key1-2 START f KEY > f-key1-1 READ f NEXT - IF (f-status <> "00") OR - (file1-serial <> 4) - DISPLAY "FAILED 3: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 4) + DISPLAY "FAILED 3: status " f-status " - " "serial: " file1-serial END-IF @@ -7186,9 +7187,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key2-2 START f KEY = f-key2-1 READ f NEXT - IF (f-status <> "00") OR - (file1-serial <> 4) - DISPLAY "FAILED 4: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 4) + DISPLAY "FAILED 4: status " f-status " - " "serial: " file1-serial END-IF @@ -7196,9 +7197,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key2-2 START f KEY < f-key2-1 READ f PREVIOUS - IF (f-status <> "00") OR - (file1-serial <> 3) - DISPLAY "FAILED 5: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 3) + DISPLAY "FAILED 5: status " f-status " - " "serial: " file1-serial END-IF @@ -7206,9 +7207,9 @@ AT_DATA([prog.cob], [ MOVE "~~~" TO f-key2-2 START f KEY > f-key2-1 READ f NEXT - IF (f-status <> "00") OR - (file1-serial <> 4) - DISPLAY "FAILED 6: status " f-status "-" + IF (f-status <> "00") + OR (file1-serial <> 4) + DISPLAY "FAILED 6: status " f-status " - " "serial: " file1-serial END-IF @@ -7216,12 +7217,12 @@ AT_DATA([prog.cob], [ START f KEY > f-key3-1 READ f NEXT * CHECK: Return file-status "02" if duplicates exist - IF (f-status <> "02" - * Depends on xISAM implementation and the way BDB is used (not yet - * implemented in 3.x) - AND f-status <> "00" - ) OR file1-serial <> 3 - DISPLAY "FAILED 7: status " f-status "-" + * Depends on xISAM implementation and also on the way BDB is used + IF (f-status <> "02" + AND f-status <> "00") + OR (file1-serial <> 3) + DISPLAY "FAILED 7: status " f-status " - " + "serial: " file1-serial END-IF CLOSE f STOP RUN