int EXP_LVL9 CSdtcomp ( Const char *inpt, Const char *outp, int flags, Const char *elipsoid, int (*err_func)(char *mesg) ) { int st; int test; int demo; int warn; int dummy; int cancel; int err_cnt; int crypt; size_t rdCnt; size_t wrCnt; char *cp; csFILE *inStrm; csFILE *elStrm; csFILE *outStrm; struct cs_DtcmpT_ *tp; struct cs_DtTypeT_ *typPtr; cs_magic_t magic; char err_seg [18]; char buff [128]; char err_msg [128]; char last_name [48]; __ALIGNMENT__2 /* For some versions of Sun compiler. */ struct cs_Dtdef_ dtdef; crypt = ((flags & cs_CMPLR_CRYPT) != 0); demo = ((flags & cs_CMPLR_DEMO) != 0); test = ((flags & cs_CMPLR_TEST) != 0); warn = ((flags & cs_CMPLR_WARN) != 0); /* Open the source file. */ inStrm = CS_fopen (inpt,_STRM_TXTRD); if (inStrm == NULL) { sprintf (err_msg,"Couldn't open %s for input.",inpt); cancel = (*err_func)(err_msg); return (1); } /* Open the output file and write the magic number. BINRW mode creates a new file with read and write access. */ outStrm = CS_fopen (outp,_STRM_BINRW); if (outStrm == NULL) { sprintf (err_msg,"Couldn't open %s for output.",outp); cancel = (*err_func)(err_msg); CS_fclose (inStrm); return (1); } if (demo) magic = cs_DTDEF_MAGIC; else magic = cs_DTDEF_MAGIC; CS_bswap (&magic,"l"); wrCnt = CS_fwrite ((char *)&magic,1,sizeof (magic),outStrm); if (wrCnt != sizeof (magic)) { sprintf (err_msg,"Failure detected during write to %s.",outp); cancel = (*err_func)(err_msg); CS_fclose (outStrm); CS_remove (outp); /*lint !e534 */ CS_fclose (inStrm); return (1); } /* If we have been given an ellipsoid file name, we open it now. */ if (elipsoid != NULL && *elipsoid != '\0') { elStrm = CS_fopen (elipsoid,_STRM_BINRD); if (elStrm == NULL) { sprintf (err_msg,"Couldn't open %s as an Ellipsoid Dictionary.",elipsoid); cancel = (*err_func)(err_msg); CS_fclose (inStrm); return (1); } rdCnt = CS_fread (&magic,1,sizeof (magic),elStrm); CS_bswap (&magic,"l"); if (rdCnt != sizeof (magic) || (demo && magic != cs_ELDEF_MAGIC) || (!demo && magic != cs_ELDEF_MAGIC)) { sprintf (err_msg,"%s is not an Elipsoid Dictionary file.",elipsoid); cancel = (*err_func)(err_msg); CS_fclose (inStrm); CS_fclose (elStrm); return (1); } } else { elStrm = NULL; } /* Process each line in the source file. */ line_nbr = 0; err_cnt = 0; cancel = FALSE; memset (&dtdef,'\0',sizeof (dtdef)); dtdef.delta_X = no_value; dtdef.delta_Y = no_value; dtdef.delta_Z = no_value; dtdef.rot_X = no_value; dtdef.rot_Y = no_value; dtdef.rot_Z = no_value; dtdef.bwscale = no_value; dtdef.to84_via = cs_DTCTYP_NONE; while (CS_fgets (buff,sizeof (buff),inStrm) != NULL) { if (cancel) { CS_fclose (inStrm); CS_fclose (outStrm); if (elStrm != NULL) CS_fclose (elStrm); CS_remove (outp); /*lint !e534 */ return (err_cnt); } line_nbr += 1; /* Ignore comments and blank lines. */ CS_trim (buff); if (buff [0] == '#' || buff [0] == '\0') { continue; } cp = buff; while ((cp = strchr (cp,'#')) != NULL) { if (*(cp + 1) != '#' && *(cp - 1) != '\\') { *cp = '\0'; break; } } /* Run the line through the table parser. We see what type of line we have. */ cp = buff; tp = (struct cs_DtcmpT_ *)CS_tpars (&cp,cs_DtcmpT,sizeof (struct cs_DtcmpT_)); if (tp == NULL) { CS_stncp (err_seg,buff,sizeof (err_seg)); sprintf (err_msg,"Invalid keyword (%s) on line %d.",err_seg,line_nbr); cancel = (*err_func)(err_msg); err_cnt += 1; dtdef.key_nm [0] = '\0'; continue; } /* Here when we have a valid line. Cp points to the first character after the colon. */ CS_trim (cp); switch (tp->type) { case DT_NAME: /* Here each time we encounter a new datum name. We see if there is an existing datum which must be written. */ if (dtdef.key_nm [0] != '\0' && /* Skip 1st one. */ (test || CS_stricmp (dtdef.group,"TEST"))) { st = CSdtdefwr (outStrm,&dtdef,crypt,warn,elStrm,err_func); if (st >= 0) err_cnt += st; else { cancel = TRUE; err_cnt += -st; } } /* Prepare for the next coordinate system. */ memset (&dtdef,'\0',sizeof (dtdef)); dtdef.delta_X = no_value; dtdef.delta_Y = no_value; dtdef.delta_Z = no_value; dtdef.rot_X = no_value; dtdef.rot_Y = no_value; dtdef.rot_Z = no_value; dtdef.bwscale = no_value; dtdef.protect = FALSE; dtdef.to84_via = cs_DTCTYP_NONE; CS_stncp (dtdef.key_nm,cp,sizeof (dtdef.key_nm)); st = CS_nampp (dtdef.key_nm); if (st != 0) { sprintf (err_msg,"%s is not a valid datum key name; line %d.",cp,line_nbr); cancel = (*err_func)(err_msg); err_cnt += 1; } break; case DESC_NM: if (strlen (cp) >= sizeof (dtdef.name) && warn) { sprintf (err_msg,"Warning: Description for %s on line %d is too long.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } CS_stncp (dtdef.name,cp,sizeof (dtdef.name)); break; case ELLP_NM: CS_stncp (dtdef.ell_knm,cp,sizeof (dtdef.ell_knm)); break; case LOCATION: if (strlen (cp) >= sizeof (dtdef.locatn) && warn) { sprintf (err_msg,"Warning: Country list for %s on line %d is too long.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } CS_stncp (dtdef.locatn,cp,sizeof (dtdef.locatn)); break; case COUNTRY: if (strlen (cp) >= sizeof (dtdef.cntry_st) && warn) { sprintf (err_msg,"Warning: Country list for %s on line %d is too long.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } CS_stncp (dtdef.cntry_st,cp,sizeof (dtdef.cntry_st)); break; case SOURCE: if (strlen (cp) >= sizeof (dtdef.source) && warn) { sprintf (err_msg,"Warning: Source for %s on line %d is too long.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } CS_stncp (dtdef.source,cp,sizeof (dtdef.source)); break; case DELTA_X: dtdef.delta_X = atof (cp); if (warn && (fabs (dtdef.delta_X) > 2000.0)) { sprintf (err_msg,"Warning: Delta X value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case DELTA_Y: dtdef.delta_Y = atof (cp); if (warn && (fabs (dtdef.delta_Y) > 2000.0)) { sprintf (err_msg,"Warning: Delta Y value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case DELTA_Z: dtdef.delta_Z = atof (cp); if (warn && (fabs (dtdef.delta_Z) > 2000.0)) { sprintf (err_msg,"Warning: Delta Z value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case ROT_X: dtdef.rot_X = atof (cp); if (warn && (fabs (dtdef.rot_X) >= 60.0)) { sprintf (err_msg,"Warning: X Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case ROT_Y: dtdef.rot_Y = atof (cp); if (warn && (fabs (dtdef.rot_Y) >= 60.0)) { sprintf (err_msg,"Warning: Y Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case ROT_Z: dtdef.rot_Z = atof (cp); if (warn && (fabs (dtdef.rot_Z) >= 60.0)) { sprintf (err_msg,"Warning: Y Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case BWSCALE: dtdef.bwscale = atof (cp); if (warn && (fabs (dtdef.bwscale) >= 25.0)) { sprintf (err_msg,"Warning: Bursa Wolfe scale value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } break; case USE: dtdef.to84_via = cs_DTCTYP_NONE; for (typPtr = cs_DtTypeT;typPtr->type != cs_DTCTYP_NONE;typPtr += 1) { if (!CS_stricmp (cp,typPtr->label)) { dtdef.to84_via = typPtr->type; break; } } if (dtdef.to84_via == cs_DTCTYP_NONE) { sprintf (err_msg,"Invalid 'USE' specification detected on line %d.",line_nbr); cancel = (*err_func)(err_msg); err_cnt += 1; } break; case GROUP: if (strlen (cp) >= sizeof (dtdef.group) && warn) { sprintf (err_msg,"Warning: Group for %s on line %d is too long.",dtdef.key_nm,line_nbr); cancel = (*err_func)(err_msg); } CS_stncp (dtdef.group,cp,sizeof (dtdef.group)); break; case EPSG_NBR: dtdef.epsgNbr = atoi (cp); break; default: sprintf (err_msg,"Software problem detected at line %d in module %s.",__LINE__,__FILE__); (void)(*err_func)(err_msg); cancel = TRUE; break; } /* On to the next input line. */ } CS_fclose (inStrm); /* Write out the last coordinate system if not in error. */ if (dtdef.key_nm [0] != '\0' && (test || CS_stricmp (dtdef.group,"TEST"))) { st = CSdtdefwr (outStrm,&dtdef,crypt,warn,elStrm,err_func); if (st >= 0) err_cnt += st; else { cancel = TRUE; err_cnt += -st; } } if (elStrm != NULL) CS_fclose (elStrm); if (cancel) { CS_fclose (outStrm); CS_remove (outp); /*lint !e534 */ return (err_cnt); } /* Sort the output file. */ CS_fseek (outStrm,(long)sizeof (magic),SEEK_SET); CS_ips (outStrm,sizeof (dtdef),0L,(CMPFUNC_CAST)CS_dtcmp); /*lint !e534 */ /* Verify that there are no duplicates. */ CS_fseek (outStrm,(long)sizeof (magic),0); CS_dtrd (outStrm,&dtdef,&dummy); /*lint !e534 */ CS_stncp (last_name,dtdef.key_nm,sizeof (last_name)); while (!cancel && CS_dtrd (outStrm,&dtdef,&dummy) != 0) { if (!CS_stricmp (dtdef.key_nm,last_name)) { sprintf (err_msg,"Datum key name %s appears more than once.",last_name); cancel = (*err_func)(err_msg); err_cnt += 1; } CS_stncp (last_name,dtdef.key_nm,sizeof (last_name)); } CS_fclose (outStrm); /* Remove the output file if there were errors. */ if (err_cnt != 0) { CS_remove (outp); /*lint !e534 */ } return (err_cnt); }
/* This function creates a binary version of the Jgd2k file if it doesn't exist, or if the date on the binary file is older than or equal to that of the primary text file. Note, that this function uses the path name in the provided object, and modifies it to point to the binary file which is then created if necessary. This function is implemented as records in the ASCII text file may not be of fixed length, there can be a million of them, and there is no guarantee that the records in the text file will be properly sorted. The binary file enables random access to the data file for decent performance without eating up 12MB of RAM. */ int CSmakeBinaryJgd2kFile (struct cs_Japan_* thisPtr) { extern char cs_ExtsepC; extern char csErrnam []; extern double cs_Zero; int st; cs_Time_ aTime, bTime; size_t wrCnt; char *cp1, *cp2; csFILE *aStrm, *bStrm; long32_t tempL; long32_t dblFrmt; ulong32_t meshCode; double lngTmp, latTmp; double mesh_ll [2]; char lineBufr [128]; char binaryPath [MAXPATH]; struct csJgd2kGridRecord_ gridRec; struct csJgd2kGridRecord_ minRec; struct csJgd2kGridRecord_ maxRec; /* We will write two records to the file with bogus mesh codes. These records will carry the minimum (i.e. southwest) longitude and latitude and the maximum (i.e. northeast) longitude and latitude of the data in the file. This is an attempt to make the file format something which does not inherently imply applicability to Japanese geography. The bogus mesh codes were devised such that the min/max will be the first two records in the file, thus easily accessible. For these two special records, the deltaLng and DeltaLat fields carry absolute longitude and latitude in seconds. */ minRec.meshCode = 1UL; minRec.deltaLat = (long32_t)( 90 * 3600); minRec.deltaLng = (long32_t)(180 * 3600); maxRec.meshCode = 2UL; maxRec.deltaLat = (long32_t)( -90 * 3600); maxRec.deltaLng = (long32_t)(-180 * 3600); /* Prepare for an error of some sort. */ aStrm = bStrm = NULL; lngTmp = latTmp = cs_Zero; /* Manufacture the name of the binary file. */ CS_stncp (binaryPath,thisPtr->filePath,sizeof (binaryPath)); cp1 = strrchr (binaryPath,cs_ExtsepC); if (cp1 == NULL) { CS_stncp (csErrnam,thisPtr->filePath,MAXPATH); CS_erpt (cs_DTC_FILE); goto error; } CS_stcpy ((cp1 + 1),"_par"); bTime = CS_fileModTime (binaryPath); /* Build a new binary file only if it doesn't exist yet. */ if (0 == bTime) { /* Determine the last modification time for the two files. Zero time value means the file does not exist. */ aTime = CS_fileModTime (thisPtr->filePath); if (aTime == 0) { /* The indicated source file does not exist, not uncommon among the error conditions possible. */ CS_stncp (csErrnam,thisPtr->filePath,MAXPATH); CS_erpt (cs_DTC_FILE); goto error; } /* Here to create a, possibly new, binary version of the Jgd2k file, typically named "TKY2JGD.par". To follow the general design theme, we assume there can be several files, and there is no fixed name for any of the files. At this particular point, of course, we're only dealing with one file, the file whose name was provided. We write one csJgd2kGridRecord structure for each line of text that we read. Of course, we need to skip the first two lines (usually) in the file as they are of the mets-data variety. */ aStrm = CS_fopen (thisPtr->filePath,_STRM_TXTRD); if (aStrm == NULL) { /* This could happen if the file exists, but for some reason we are denied permission to read the file.*/ CS_stncp (csErrnam,thisPtr->filePath,MAXPATH); CS_erpt (cs_DTC_FILE); goto error; } /* The mode of the following open will truncate any existing file, and create a new binary file if necessary. */ bStrm = CS_fopen (binaryPath,_STRM_BINWR); if (bStrm == NULL) { CS_stncp (csErrnam,thisPtr->filePath,MAXPATH); CS_erpt (cs_FL_OPEN); goto error; } /* If we're still here, we can copy the file, converting it to binary form as we do. While doing so, we'll convert each mesh code to latitude and longitude form and accumulate an estimate of the coverage of the file. */ while (CS_fgets (lineBufr,sizeof (lineBufr),aStrm) != NULL) { /* Parse the information is in a record. */ meshCode = CS_strtoul (lineBufr,&cp1,10); /* The first two lines of the files we've seen contain labels and other data. We use the following to filter these out. This may need to be improved should new versions of the file include some other form of header. */ if (meshCode == 0 || meshCode == 0xffffffffUL) continue; /* Accumulate a bounding box (or minimum and maximum as us old farts used to call it) so we have a rough estimate of the coverage of the file. */ CSjpnMeshCodeToLl (mesh_ll,meshCode); if (mesh_ll [LNG] < -180.0 || mesh_ll [LNG] > 180.0 || mesh_ll [LAT] < -90.0 || mesh_ll [LAT] > 90.0) { /* Bogus mesh code. We could consider this to be meta-data that slipped through the code immediately above, or that the file is invalid. For now, we consider it to be the latter: The file is not a validly formatted data file. */ CS_erpt (cs_INV_FILE); goto error; } tempL = (long32_t)(mesh_ll [LNG] * 3600 + 0.01); if (tempL < minRec.deltaLng) minRec.deltaLng = tempL; if (tempL > maxRec.deltaLng) maxRec.deltaLng = tempL; tempL = (long32_t)(mesh_ll [LAT] * 3600 + 0.01); if (tempL < minRec.deltaLat) minRec.deltaLat = tempL; if (tempL > maxRec.deltaLat) maxRec.deltaLat = tempL; /* Separate the two data values. We avoid strtod as it is locale dependent and the data file is not. */ while (*cp1 == ' ') cp1++; cp2 = strchr (cp1,' '); *cp2++ = '\0'; while (*cp2 == ' ') cp2++; dblFrmt = CSatof (&latTmp,cp1,'.',',',':'); if (dblFrmt >= 0) { dblFrmt = CSatof (&lngTmp,cp2,'.',',',':'); } if (dblFrmt < 0) { CS_erpt (cs_INV_FILE); goto error; } /* Build a new record in the array. */ gridRec.meshCode = meshCode; /* NTO 30 Oct 2008, Trac # 13 The following was necessiatated by Linux. It appears that on the Linux platform (or some of them, anyway), the rounding of doubles (especially negative ones) is different than what you will see on WIN32 platforms. Which one is correct is of no concern to me, only that they are different. */ latTmp *= 100000.0; latTmp += (latTmp >= 0.0) ? 0.1 : -0.1; lngTmp *= 100000.0; lngTmp += (lngTmp >= 0.0) ? 0.1 : -0.1; /* End Linux fix, Trac #13 */ gridRec.deltaLat = (long32_t)(latTmp); gridRec.deltaLng = (long32_t)(lngTmp); wrCnt = CS_fwrite (&gridRec,sizeof (gridRec),1,bStrm); if (wrCnt != 1) { CS_erpt (cs_IOERR); goto error; } } /* If we're still here, we write minRec and maxRec to the file so we have a record of the coverage of the file. */ wrCnt = CS_fwrite (&minRec,sizeof (minRec),1,bStrm); if (wrCnt != 1) { CS_erpt (cs_IOERR); goto error; } wrCnt = CS_fwrite (&maxRec,sizeof (maxRec),1,bStrm); if (wrCnt != 1) { CS_erpt (cs_IOERR); goto error; } /* Close the file streams. We're going to open the binary file back up immediately, but have found this redundant close and open to produce more reliable operation cross platforms. */ CS_fclose (aStrm); aStrm = NULL; st = CS_fclose (bStrm); bStrm = NULL; /* OK, we need to sort the file by mesh codes so we can use a binary search algorithm on it. This should also cause the min/max records to end up being the first two records in the file. This is very convenient. Note that the position of any one record in the file with respect to any other record in the file is immaterial in this file format. Thus, we can reorder the file any way we want to. The original code was written in the Windows 95 era, so the current scheme may look rather dumb. Nevertheless, it works and I have no motivation to fix it. */ bStrm = CS_fopen (binaryPath,_STRM_BINUP); if (bStrm == NULL) { CS_stncp (csErrnam,binaryPath,MAXPATH); CS_erpt (cs_FL_OPEN); goto error; } st = CS_ips (bStrm,sizeof (gridRec),0L,(CMPFUNC_CAST)CScompareJgd2kGridRecord); CS_fclose (bStrm); bStrm = NULL; if (st < 0) goto error; if (st == 1) st = csGRIDI_ST_OK; /* CS_ips returns 1 for success, for historical reasons. */ /* OK, now we're really done. */ } /* If all that was done successfully, we change the name of the file and return success. */ CS_stncp (thisPtr->filePath,binaryPath,sizeof (thisPtr->filePath)); return csGRIDI_ST_OK; error: if (aStrm != NULL) { CS_fclose (aStrm); aStrm = NULL; } if (bStrm != NULL) { CS_fclose (bStrm); bStrm = NULL; } return csGRIDI_ST_SYSTEM; }
int CStest6 (int verbose,int crypt) { int st; int cnt; int flag; int my_crypt; csFILE *csStrm; struct tst_lst_ *tp; char last_name [48]; __ALIGNMENT__1 /* Required by some Sun compilers. */ struct cs_Csdef_ cs_def; printf ("Testing sort and binary search functions.\n"); /* This test sorts the Coordinate System Dictionary, the largest of the three dictionaries, into reverse order. Then does some CS_bins calls. Then resorts back into normal order. This is a resaonable good exercise of the sort function which normally sorts files with a single entry out of order. */ if (verbose) { printf ("Sorting Coordinate System Dictionary into reverse order.\n"); } csStrm = CS_csopn (_STRM_BINUP); if (csStrm == NULL) { printf ("Coordinate System Dictionary open failed. Is it write protected?.\n"); return 1; } /* NOTE: CS_csopn leaves the file positioned after the magic number. CS_ips always starts sorting at the current file position. */ CS_ips (csStrm,sizeof (struct cs_Csdef_),-1L,(CMPFUNC_CAST)CStest6cmp); /* The dictionary should now be in reverse order. We check the order now. CS_ips is supposed to return with the file position where it was when we started. */ if (verbose) { printf ("Checking reverse order of Coordinate System Dictionary.\n"); } cnt = 0; st = CS_csrd (csStrm,&cs_def,&my_crypt); if (st == 0) { printf ("CS_ips hosed the Coordinate System Dictionary.\n"); CS_fclose (csStrm); return (1); } CS_stncp (last_name,cs_def.key_nm,sizeof (last_name)); while (CS_csrd (csStrm,&cs_def,&my_crypt)) { cnt += 1; if (verbose && (cnt % 10) == 0) putchar ('.'); st = CS_stricmp (last_name,cs_def.key_nm); if (st < 0) { printf ("\nSort did not sort entire file correctly!!!\n"); CS_fclose (csStrm); return (1); } else if (st == 0) { printf ("\nSort left duplicate entries when sorting entire file!!!\n"); CS_fclose (csStrm); return (1); } } if (verbose) printf (" OK.\n"); /* If we are still here, the sort worked correctly. Use the sort_tst list as a list of names to binary search on. It includes the normal first and last; which should now be the last and the first. */ tp = sort_tst; while (tp->name [0] != '\0') { if (verbose) { printf ("Searching for %s in reversed CS Dictionary.",tp->name); } CS_stncp (cs_def.key_nm,tp->name,sizeof (cs_def.key_nm)); flag = CS_bins (csStrm,(long32_t)sizeof (cs_magic_t),(long32_t)0,sizeof (cs_def), (char *)&cs_def,(CMPFUNC_CAST)CStest6cmp); if (flag <= 0) { printf ("CS_bins failed on file in reverse order!!!\n"); CS_fclose (csStrm); return (1); } if (verbose) printf (" OK.\n"); tp += 1; } /* OK, return the file back to normal sorted order. */ if (verbose) { printf ("Sorting Coordinate System Dictionary back to normal order.\n"); } CS_fseek (csStrm,(long)sizeof (cs_magic_t),SEEK_SET); CS_ips (csStrm,sizeof (struct cs_Csdef_),-1L,(CMPFUNC_CAST)CS_cscmp); /* One more time, check that the order is correct. */ if (verbose) { printf ("Checking Coordinate System Dictionary normal sorted order.\n"); } cnt = 0; st = CS_csrd (csStrm,&cs_def,&my_crypt); if (st == 0) { printf ("CS_ips hosed the Coordinate System Dictionary.\n"); CS_fclose (csStrm); return (1); } CS_stncp (last_name,cs_def.key_nm,sizeof (last_name)); while (CS_csrd (csStrm,&cs_def,&my_crypt)) { cnt += 1; if (verbose && (cnt % 10) == 0) putchar ('.'); st = CS_stricmp (last_name,cs_def.key_nm); if (st > 0) { printf ("Sort did not sort entire file correctly!!!\n"); CS_fclose (csStrm); return (1); } else if (st == 0) { printf ("Sort left duplicate entries when sorting entire file!!!\n"); CS_fclose (csStrm); return (1); } } if (verbose) printf (" OK.\n"); /* OK, if we are still here, we passed the test. */ CS_csDictCls (csStrm); return (0); }
int EXP_LVL3 CS_dtupd (struct cs_Dtdef_ *dtdef,int crypt) { extern char csErrnam []; extern short cs_Protect; extern char cs_Unique; short cs_time; int st; int flag; int dummy; csFILE *strm; long fpos; char *cp; __ALIGNMENT__1 /* For some versions of Sun compiler. */ struct cs_Dtdef_ my_dtdef; /* Capture the current time. For our purposes here, time is the number of days since (approx) January 1, 1990. If this record does get written, the protect field will indicate that it has changed. */ cs_time = (short)((CS_time ((cs_Time_ *)0) - 630720000L) / 86400L); if (dtdef->protect >= 0) { dtdef->protect = cs_time; } /* Prepare for a possible error. */ strm = NULL; /* Adjust the name and make sure it is all upper case. By convention, datum names are case insensitive. */ st = CS_nampp (dtdef->key_nm); if (st != 0) goto error; /* Open up the Datum Dictionary and verify its magic number. */ strm = CS_dtopn (_STRM_BINUP); if (strm == NULL) { goto error; } /* See if we have a datum with this name already. */ flag = CS_bins (strm,(long)sizeof (cs_magic_t),0L,sizeof (*dtdef), (char *)dtdef,(CMPFUNC_CAST)CS_dtcmp); if (flag < 0) goto error; if (flag) { /* Here when the datum already exists. See if we are allowed to change this definition. */ if (cs_Protect >= 0) { /* Distribution protection is enabled. */ fpos = CS_ftell (strm); if (fpos < 0L) { CS_erpt (cs_IOERR); goto error; } st = CS_dtrd (strm,&my_dtdef,&dummy); if (st == 0) CS_erpt (cs_INV_FILE); if (st <= 0) { goto error; } if (my_dtdef.protect == 1) { CS_stncp (csErrnam,dtdef->key_nm,MAXPATH); CS_erpt (cs_DT_PROT); goto error; } if (cs_Protect > 0 && my_dtdef.protect > 0) { if (my_dtdef.protect < (cs_time - cs_Protect)) /*lint !e644 */ { CS_stncp (csErrnam,dtdef->key_nm,MAXPATH); CS_erpt (cs_DT_UPROT); goto error; } } st = CS_fseek (strm,fpos,SEEK_SET); if (st < 0L) { CS_erpt (cs_IOERR); goto error; } } /* If we're still here, it's OK to update this definition. */ if (CS_dtwr (strm,dtdef,crypt)) { goto error; } } else { /* Here if the datum definition doesn't exist. We have to add it. If cs_Unique is not zero, we require that a cs_Unique character be present in the key name before we'll allow it to be written. */ if (cs_Unique != '\0') { cp = strchr (dtdef->key_nm,cs_Unique); if (cp == NULL) { csErrnam [0] = cs_Unique; csErrnam [1] = '\0'; CS_erpt (cs_UNIQUE); goto error; } } /* Now we can add it. Write to the end of the file, and then sort the file. */ st = CS_fseek (strm,0L,SEEK_END); if (st != 0) { CS_erpt (cs_IOERR); goto error; } if (CS_dtwr (strm,dtdef,crypt)) { goto error; } /* Sort the file into proper order, thereby moving the new datum to its proper place in the dictionary. */ st = CS_fseek (strm,(long)sizeof (cs_magic_t),SEEK_SET); if (st != 0) { CS_erpt (cs_IOERR); goto error; } st = CS_ips (strm,sizeof (*dtdef),0L,(CMPFUNC_CAST)CS_dtcmp); if (st < 0) goto error; } /* The Datum Dictionary has been updated. */ CS_dtDictCls (strm); return (flag); error: if (strm != NULL) CS_dtDictCls (strm); return (-1); }