From 86227d60b6196aea96ea1692232019dc40d58c54 Mon Sep 17 00:00:00 2001 From: David Declerck Date: Fri, 27 Sep 2024 11:42:12 +0200 Subject: [PATCH] Merge SVN 4981 --- libcob/ChangeLog | 8 ++++ libcob/fextfh.c | 25 +++++++----- libcob/fileio.c | 101 +++++++++++++++++++++++++++++++---------------- 3 files changed, 90 insertions(+), 44 deletions(-) diff --git a/libcob/ChangeLog b/libcob/ChangeLog index faa87cc53..bc4d92c9c 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -125,6 +125,14 @@ warnings * cconv.c (cob_load_collation), common.c, intrinisic.c (cob_intr_random), termio.c: minor adjustments to fix compiler warnings + * fileio.c (copy_fcd_to_file)->fextfh.c: fixed memory issues with + writing to assign and select name + * fileio.c (save_status): don't synch directly after open or close + * fileio.c (cob_file_open), (open_next): include binary in open flags if + cobsetptr->cob_unix_lf is set + * 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 diff --git a/libcob/fextfh.c b/libcob/fextfh.c index fbbd3ceee..3077a8cb6 100644 --- a/libcob/fextfh.c +++ b/libcob/fextfh.c @@ -564,8 +564,9 @@ copy_fcd_to_file (FCD3* fcd, cob_file *f, struct fcd_file *fcd_list_entry) } } else if(fcd->fileOrg == ORG_RELATIVE) { f->organization = COB_ORG_RELATIVE; - if (f->keys == NULL) + if (f->keys == NULL) { f->keys = cob_cache_malloc(sizeof(cob_file_key)); + } if (f->keys[0].field == NULL) { f->keys[0].field = cob_cache_malloc(sizeof(cob_field)); f->keys[0].field->data = cob_cache_malloc (4); @@ -628,25 +629,29 @@ copy_fcd_to_file (FCD3* fcd, cob_file *f, struct fcd_file *fcd_list_entry) /* build select name from assign value, if missing */ if (f->select_name == NULL && f->assign != NULL) { + const int max_size = ((int)f->assign->size > 48) + ? 48 : (int)f->assign->size; char fdname[49]; char *origin = (char*)f->assign->data; /* limit filename to last element after path separator, when specified */ - for (k=(int)f->assign->size - 1; k; k--) { + for (k = max_size - 1; k; k--) { if (f->assign->data[k] == SLASH_CHAR #ifdef _WIN32 || f->assign->data[k] == '/' #endif ) { - origin = (char*)&f->assign->data[k+1]; + origin = (char *)f->assign->data + k + 1; break; } } - /* now copy that until the first space/low-value (max 48) as upper-case */ - for (k=0; origin[k] && origin[k] > ' ' && k < 48; k++) { + /* now copy that until the first space/low-value up to + max_size as upper-case */ + for (k = 0; origin[k] && origin[k] > ' ' && k < max_size; k++) { fdname[k] = (char)toupper((int)origin[k]); } fdname[k] = 0; + k++; /* copy with trailing NUL */ /* we don't necessarily know later if we built the name ourself, so we need to cache the storage */ f->select_name = cob_cache_malloc (k); @@ -1391,7 +1396,7 @@ EXTFH3 (unsigned char *opcode, FCD3 *fcd) int opcd,sts,opts,eop,k; unsigned char fnstatus[2]; /* storage for local file status field */ - unsigned char keywrk[80]; + unsigned char keywrk[80]; /* key data used for IDX, if not passed */ char fname[COB_FILE_MAX]; /* different cob_fields as some ABI functions operate on those */ cob_field fs[1]; @@ -1420,7 +1425,7 @@ EXTFH3 (unsigned char *opcode, FCD3 *fcd) COB_MODULE_PTR = cob_malloc( sizeof(cob_module) ); COB_MODULE_PTR->module_name = "GnuCOBOL-fileio"; COB_MODULE_PTR->module_source = "GnuCOBOL-fileio"; - COB_MODULE_PTR->module_formatted_date = "2021/10/03 12:01:20"; + COB_MODULE_PTR->module_formatted_date = "2023/02/06 12:01:20"; } if (*opcode == 0xFA) { @@ -1482,10 +1487,12 @@ EXTFH3 (unsigned char *opcode, FCD3 *fcd) if (opcd == OP_GETINFO) { if (fcd->fnamePtr) { k = strlen(fcd->fnamePtr); - if (k > LDCOMPX2(fcd->fnameLen)) + if (k > LDCOMPX2(fcd->fnameLen)) { k = LDCOMPX2(fcd->fnameLen); - while (k > 0 && fcd->fnamePtr[k-1] == ' ') + } + while (k > 0 && fcd->fnamePtr[k-1] == ' ') { --k; + } memcpy (fname, fcd->fnamePtr, k); fname[k] = 0; f->flag_auto_type = 1; diff --git a/libcob/fileio.c b/libcob/fileio.c index a942ece3e..d9ab63cc9 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -3428,7 +3428,9 @@ cob_file_save_status (cob_file *f, cob_field *fnstatus, const int status) #endif eop_status = 0; } - if ((f->file_features & COB_FILE_SYNC)) { + if ((f->file_features & COB_FILE_SYNC) + && f->last_operation != COB_LAST_OPEN + && f->open_mode != COB_OPEN_CLOSED) { cob_file_sync (f); } } else if (!skip_exn) { @@ -4240,22 +4242,24 @@ cob_fd_file_open (cob_file *f, char *filename, if ((ret=set_file_lock(f, filename, mode)) != 0) return ret; f->record_off = -1; -#if 0 /* Simon: disabled, this function is expected to not use a file */ +#if 0 /* Simon: disabled, this function is expected to not use a FILE* */ { - const char *fmode; + const char *fopen_flags; if (mode == COB_OPEN_INPUT) { - fmode = "r"; + fopen_flags = "r"; } else if (mode == COB_OPEN_I_O) { if (nonexistent) - fmode = "w+"; + fopen_flags = "w+"; else - fmode = "r+"; + fopen_flags = "r+"; } else if (mode == COB_OPEN_EXTEND) { - fmode = ""; + fopen_flags = ""; } else { - fmode = "w"; + fopen_flags = "w"; } - f->file = (void*)fdopen(f->fd, fmode); + /* note: _if_ this is activated (which likely needs adjustments in + other places) then also handle cobsetptr->cob_unix_lf */ + f->file = (void*)fdopen(f->fd, fopen_flags); } #endif if (f->flag_optional && nonexistent) { @@ -4486,7 +4490,6 @@ cob_file_open (cob_file_api *a, cob_file *f, char *filename, } } - fmode = NULL; /* Open the file */ switch (mode) { case COB_OPEN_INPUT: @@ -4544,6 +4547,7 @@ cob_file_open (cob_file_api *a, cob_file *f, char *filename, break; /* LCOV_EXCL_START */ default: + fmode = NULL; cob_runtime_error (_("invalid internal call of %s"), "cob_file_open"); cob_fatal_error (COB_FERROR_CODEGEN); /* LCOV_EXCL_STOP */ @@ -4688,10 +4692,10 @@ cob_file_close (cob_file_api *a, cob_file *f, const int opt) COB_CHECKED_WRITE (f->fd, "\n", 1); } } -#ifdef HAVE_FCNTL /* Unlock the file */ if (f->fd >= 0 && !f->flag_is_pipe) { +#ifdef HAVE_FCNTL struct flock lock; memset ((void *)&lock, 0, sizeof (struct flock)); lock.l_type = F_UNLCK; @@ -4702,14 +4706,13 @@ cob_file_close (cob_file_api *a, cob_file *f, const int opt) if (fcntl (f->fd, F_SETLK, &lock) == -1) { cob_runtime_warning ("issue during unlock (%s), errno: %d", "cob_file_close", errno); } - } #elif defined _WIN32 - { - HANDLE osHandle = (HANDLE)_get_osfhandle (f->fd); - if (osHandle != INVALID_HANDLE_VALUE) { + { + HANDLE osHandle = (HANDLE)_get_osfhandle (f->fd); /* CHECKME: Should this use UnlockFileEx ? */ - if (!UnlockFile (osHandle, 0, 0, MAXDWORD, MAXDWORD)) { -#if 0 /* CHECKME - What is the correct thing to do here? */ + if (osHandle != INVALID_HANDLE_VALUE + && !UnlockFile (osHandle, 0, 0, MAXDWORD, MAXDWORD)) { +#if 0 /* CHECKME - What is the correct thing to do here? */ const DWORD last_error = GetLastError (); if (last_error != 158) { /* no locked region */ /* not translated as "testing only" */ @@ -4719,8 +4722,8 @@ cob_file_close (cob_file_api *a, cob_file *f, const int opt) #endif } } - } #endif + } /* Close the file */ if (f->organization == COB_ORG_LINE_SEQUENTIAL) { if (f->flag_is_pipe) { @@ -4728,7 +4731,7 @@ cob_file_close (cob_file_api *a, cob_file *f, const int opt) if (f->file) fclose (f->file); if (f->fileout - && f->fileout != f->file) + && f->fileout != f->file) fclose (f->fileout); #if defined (HAVE_UNISTD_H) && !(defined (_WIN32)) { @@ -4765,7 +4768,10 @@ cob_file_close (cob_file_api *a, cob_file *f, const int opt) if (f->file != NULL) { fclose ((FILE *)f->file); f->file = NULL; +#ifdef _WIN32 + /* at least on MSVC that closes the underlying file descriptor, too */ f->fd = -1; +#endif } #endif } else { @@ -4802,37 +4808,57 @@ open_next (cob_file *f) { if (f->flag_is_concat && *f->nxt_filename != 0) { - char *nx = strchr(f->nxt_filename,file_setptr->cob_concat_sep[0]); + char *nx = strchr (f->nxt_filename,file_setptr->cob_concat_sep[0]); + int fmode = O_BINARY; /* without this ftell does not work on some systems */ + +#ifdef _WIN32 /* win32 seems to resolve the file descriptor from the file handler + on fclose - and then aborts because it was closed directly before */ + if (f->file) { + fclose (f->file); + } else { + close (f->fd); + } +#else close (f->fd); if (f->file) { fclose (f->file); } - f->fd = -1; - f->file = NULL; +#endif + if (f->open_mode == COB_OPEN_I_O) { + fmode |= O_RDWR; + } else { + fmode |= O_RDONLY; + } if (nx) { *nx = 0; - if (f->open_mode == COB_OPEN_I_O) - f->fd = open (f->nxt_filename, O_RDWR); - else - f->fd = open (f->nxt_filename, O_RDONLY); + f->fd = open (f->nxt_filename, fmode); f->nxt_filename = nx + 1; } else { - if (f->open_mode == COB_OPEN_I_O) - f->fd = open (f->nxt_filename, O_RDWR); - else - f->fd = open (f->nxt_filename, O_RDONLY); + f->fd = open (f->nxt_filename, fmode); f->flag_is_concat = 0; if (f->org_filename) { cob_free (f->org_filename); f->org_filename = NULL; } } - if (f->fd != -1) { - if (f->open_mode == COB_OPEN_INPUT) { - f->file = (void*)fdopen(f->fd, "r"); + if (f->fd == -1) { + f->file = NULL; + } else { + const char *fopen_flags; + if (cobsetptr->cob_unix_lf) { + if (f->open_mode == COB_OPEN_INPUT) { + fopen_flags = "rb"; + } else { + fopen_flags = "rb+"; + } } else { - f->file = (void*)fdopen(f->fd, "r+"); + if (f->open_mode == COB_OPEN_INPUT) { + fopen_flags = "r"; + } else { + fopen_flags = "r+"; + } } + f->file = (void*)fdopen(f->fd, fopen_flags); return 1; } } @@ -5176,6 +5202,9 @@ lineseq_read (cob_file_api *a, cob_file *f, const int read_opts) if (!f->flag_is_pipe) { f->record_off = ftell (fp); /* Save position at start of line */ } + /* Note: at least on Win32 the offset resolved does only return the right values + when file was opened in binary mode -> cob_unix_lf; as an alternative + we could increment the record_off field on each read/write */ for (; ;) { n = getc (fp); if (n == EOF) { @@ -5550,6 +5579,7 @@ lineseq_rewrite (cob_file_api *a, cob_file *f, const int opt) psize = size; slotlen = curroff - f->record_off - 1; if ((f->file_features & COB_FILE_LS_CRLF)) { + /* CHECKME: likely also needed if not opened with unix-lf */ slotlen--; } if ((f->file_features & COB_FILE_LS_NULLS) @@ -9791,7 +9821,8 @@ cob_init_fileio (cob_global *lptr, cob_settings *sptr) file_open_buff = runtime_buffer + (3 * COB_FILE_BUFF); /* TRANSLATORS: This msgid is concatenated with a filename; - setup translation to allow this to be followed on the right side. */ + setup translation to allow this to be followed on the right side, + if necessary use a colon or hyphen */ implicit_close_of_msgid = _("implicit CLOSE of "); file_api.glbptr = file_globptr = lptr;