From f23be1c26b72fe0400b10ec175784586e798f21e Mon Sep 17 00:00:00 2001 From: Grzegorz Kowalski Date: Mon, 5 Aug 2024 15:58:52 +0200 Subject: [PATCH 1/5] Add .clang-format formatting specification --- .clang-format | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2d0f248 --- /dev/null +++ b/.clang-format @@ -0,0 +1,212 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + From 6f64e5cad1658d94b36b488f5eb1e528636b2397 Mon Sep 17 00:00:00 2001 From: Grzegorz Kowalski Date: Tue, 6 Aug 2024 11:35:21 +0200 Subject: [PATCH 2/5] .clang-format: Apply suggestions, keep it closer to existing style .clang-format: don't reorder includes .clang-format: keep comment formatting .clang-format: set indent width to 4 .clang-format: remove column limit .clang-format: allow short case on single line .clang-format: allow single line if-else .clang-format: allow single line blocks .clang-format: apply Linux style for braces --- .clang-format | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.clang-format b/.clang-format index 2d0f248..4616d3f 100644 --- a/.clang-format +++ b/.clang-format @@ -15,11 +15,11 @@ AllowAllArgumentsOnNextLine: true AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortEnumsOnASingleLine: true -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortIfStatementsOnASingleLine: AllIfsAndElse AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None @@ -50,7 +50,7 @@ BraceWrapping: SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeConceptDeclarations: true -BreakBeforeBraces: Attach +BreakBeforeBraces: Linux BreakBeforeInheritanceComma: false BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true @@ -58,7 +58,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 80 +ColumnLimit: 0 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true @@ -105,7 +105,7 @@ IndentGotoLabels: true IndentPPDirectives: None IndentExternBlock: AfterExternBlock IndentRequires: false -IndentWidth: 2 +IndentWidth: 4 IndentWrappedFunctionNames: false InsertTrailingCommas: None JavaScriptQuotes: Leave @@ -163,9 +163,9 @@ RawStringFormats: CanonicalDelimiter: pb BasedOnStyle: google ReferenceAlignment: Pointer -ReflowComments: true +ReflowComments: false ShortNamespaceLines: 1 -SortIncludes: CaseSensitive +SortIncludes: false SortJavaStaticImport: Before SortUsingDeclarations: true SpaceAfterCStyleCast: false From d655e67fa0e38f3a76a8d2614dd7e92443ab4c4d Mon Sep 17 00:00:00 2001 From: Grzegorz Kowalski Date: Mon, 19 Aug 2024 10:29:53 +0200 Subject: [PATCH 3/5] Fix nfsMount usage message --- asApp/src/os/Linux/osdNfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asApp/src/os/Linux/osdNfs.c b/asApp/src/os/Linux/osdNfs.c index 0766c87..fb3957d 100644 --- a/asApp/src/os/Linux/osdNfs.c +++ b/asApp/src/os/Linux/osdNfs.c @@ -29,7 +29,7 @@ int nfsMount(char *uidhost, char *path, char *mntpoint) /* check inputs */ if (!uidhost || !path || !mntpoint) { - fprintf(stderr,"usage: nfsMount(""[uid.gid@]host"",""path"",""mountpoint"")\n"); + fprintf(stderr,"usage: nfsMount(\"[uid.gid@]host\",\"path\",\"mountpoint\")\n"); return -1; } From 838c3230979e2ae6ba65868f3ee09452c03f7c83 Mon Sep 17 00:00:00 2001 From: Grzegorz Kowalski Date: Mon, 19 Aug 2024 10:51:07 +0200 Subject: [PATCH 4/5] .clang-format: Set column limit to 120 --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 4616d3f..c4ff527 100644 --- a/.clang-format +++ b/.clang-format @@ -58,7 +58,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 0 +ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true From f4518b8ee06b818b9a836a182cd2d90986aef8ef Mon Sep 17 00:00:00 2001 From: Grzegorz Kowalski Date: Mon, 19 Aug 2024 10:52:32 +0200 Subject: [PATCH 5/5] Apply clang-format --- asApp/src/asVerify.c | 181 +- asApp/src/configMenuClient.h | 4 +- asApp/src/configMenuSub.c | 362 +- asApp/src/dbrestore.c | 2965 +++++---- asApp/src/fGetDateStr.c | 13 +- asApp/src/fGetDateStr.h | 3 +- asApp/src/initHooks.c | 100 +- asApp/src/os/Linux/osdNfs.c | 72 +- asApp/src/os/Linux/osdNfs.h | 22 +- asApp/src/os/RTEMS/osdNfs.c | 24 +- asApp/src/os/RTEMS/osdNfs.h | 23 +- asApp/src/os/WIN32/osdNfs.c | 11 +- asApp/src/os/WIN32/osdNfs.h | 8 +- asApp/src/os/cygwin32/osdNfs.c | 11 +- asApp/src/os/cygwin32/osdNfs.h | 8 +- asApp/src/os/default/osdNfs.c | 8 +- asApp/src/os/default/osdNfs.h | 8 +- asApp/src/os/solaris/osdNfs.c | 10 +- asApp/src/os/solaris/osdNfs.h | 18 +- asApp/src/os/vxWorks/osdNfs.c | 36 +- asApp/src/os/vxWorks/osdNfs.h | 18 +- asApp/src/save_restore.c | 6379 +++++++++---------- asApp/src/save_restore.h | 89 +- asApp/src/tr_dirent.h | 380 +- asApp/src/verify.c | 1084 ++-- iocs/autosaveIOC/autosaveApp/src/asMain.cpp | 6 +- 26 files changed, 5773 insertions(+), 6070 deletions(-) diff --git a/asApp/src/asVerify.c b/asApp/src/asVerify.c index 8deaa82..93471b9 100644 --- a/asApp/src/asVerify.c +++ b/asApp/src/asVerify.c @@ -9,108 +9,105 @@ #include #include /* isalpha */ -#include /* fabs */ -#include /* for safeDoubleToFloat() */ +#include /* fabs */ +#include /* for safeDoubleToFloat() */ #include "cadef.h" #include "save_restore.h" #include "autosave_release.h" - - - - -void printUsage(void) { - fprintf(stderr,"usage: asVerify [-vr] \n"); - fprintf(stderr," -v (verbose) causes all PV's to be printed out\n"); - fprintf(stderr," Otherwise, only PV's whose values differ are printed.\n"); - fprintf(stderr," -r (restore_file) causes restore files named\n"); - fprintf(stderr," '.asVerify' and '...B'to be written.\n"); - fprintf(stderr," -d (debug) increment debug level by one.\n"); - fprintf(stderr," -rv (or -vr) does both\n"); - fprintf(stderr,"examples:\n"); - fprintf(stderr," asVerify auto_settings.sav\n"); - fprintf(stderr," (reports only PVs whose values differ from saved values)\n"); - fprintf(stderr," asVerify -v auto_settings.sav\n"); - fprintf(stderr," (reports all PVs, marking differences with '***'.)\n"); - fprintf(stderr," asVerify -vr auto_settings.sav\n"); - fprintf(stderr," (reports all PVs, and writes a restore file.)\n"); - fprintf(stderr," asVerify auto_settings.sav\n"); - fprintf(stderr," caput $?\n"); - fprintf(stderr," (writes number of differences found to a PV.)\n\n"); - fprintf(stderr,"NOTE: For the purpose of writing a restore file, you can specify a .req\n"); - fprintf(stderr,"file (or any file that contains PV names, one per line) instead of a\n"); - fprintf(stderr,".sav file. However, this program will misunderstand any 'file' commands\n"); - fprintf(stderr,"that occur in a .req file. (It will look for a PV named 'file'.)\n"); +void printUsage(void) +{ + fprintf(stderr, "usage: asVerify [-vr] \n"); + fprintf(stderr, " -v (verbose) causes all PV's to be printed out\n"); + fprintf(stderr, " Otherwise, only PV's whose values differ are printed.\n"); + fprintf(stderr, " -r (restore_file) causes restore files named\n"); + fprintf(stderr, " '.asVerify' and '...B'to be written.\n"); + fprintf(stderr, " -d (debug) increment debug level by one.\n"); + fprintf(stderr, " -rv (or -vr) does both\n"); + fprintf(stderr, "examples:\n"); + fprintf(stderr, " asVerify auto_settings.sav\n"); + fprintf(stderr, " (reports only PVs whose values differ from saved values)\n"); + fprintf(stderr, " asVerify -v auto_settings.sav\n"); + fprintf(stderr, " (reports all PVs, marking differences with '***'.)\n"); + fprintf(stderr, " asVerify -vr auto_settings.sav\n"); + fprintf(stderr, " (reports all PVs, and writes a restore file.)\n"); + fprintf(stderr, " asVerify auto_settings.sav\n"); + fprintf(stderr, " caput $?\n"); + fprintf(stderr, " (writes number of differences found to a PV.)\n\n"); + fprintf(stderr, "NOTE: For the purpose of writing a restore file, you can specify a .req\n"); + fprintf(stderr, "file (or any file that contains PV names, one per line) instead of a\n"); + fprintf(stderr, ".sav file. However, this program will misunderstand any 'file' commands\n"); + fprintf(stderr, "that occur in a .req file. (It will look for a PV named 'file'.)\n"); } -void printVersion(void) { - printf("asVerify, built from %s\n", AUTOSAVE_RELEASE); -} +void printVersion(void) { printf("asVerify, built from %s\n", AUTOSAVE_RELEASE); } -int main(int argc,char **argv) +int main(int argc, char **argv) { - FILE *fp=NULL, *ftmp=NULL; - char s[BUF_SIZE], filename[PATH_SIZE], restoreFileName[PATH_SIZE]; - char *tempname; - int n; - int numDifferences; - int status; - int verbose=0, debug=0, write_restore_file=0; - int opt; - - while ((opt = getopt(argc, argv, "Vvrdh")) != -1) { - switch (opt) { - case 'V': printVersion(); exit(0); - case 'v': verbose = 1; break; - case 'r': write_restore_file = 1; break; - case 'd': printf("debug=%d\n", ++debug); break; - case 'h': printUsage(); exit(1); - } - } - - if (argc <= optind) { - printUsage(); - exit(1); - } - - strcpy(filename, argv[optind]); - - status = ca_context_create(ca_disable_preemptive_callback); - if (!(status & CA_M_SUCCESS)) { - printf("Can't create CA context. I quit.\n"); - return(-1); - } - - /* + FILE *fp = NULL, *ftmp = NULL; + char s[BUF_SIZE], filename[PATH_SIZE], restoreFileName[PATH_SIZE]; + char *tempname; + int n; + int numDifferences; + int status; + int verbose = 0, debug = 0, write_restore_file = 0; + int opt; + + while ((opt = getopt(argc, argv, "Vvrdh")) != -1) { + switch (opt) { + case 'V': printVersion(); exit(0); + case 'v': verbose = 1; break; + case 'r': write_restore_file = 1; break; + case 'd': printf("debug=%d\n", ++debug); break; + case 'h': printUsage(); exit(1); + } + } + + if (argc <= optind) { + printUsage(); + exit(1); + } + + strcpy(filename, argv[optind]); + + status = ca_context_create(ca_disable_preemptive_callback); + if (!(status & CA_M_SUCCESS)) { + printf("Can't create CA context. I quit.\n"); + return (-1); + } + + /* * Copy to temporary file. * The .sav file is likely to be overwritten while we're using it. */ - fp = fopen(filename,"r"); - if (fp == NULL) {printf("Can't open %s\n", filename); return(-1);} - tempname = tmpnam(NULL); - ftmp = fopen(tempname,"w"); - if (ftmp == NULL) { - printf("Can't open temp file.\n"); - fclose(fp); - return(-1); - } - while (!feof(fp) && (n=fread(s,1,BUF_SIZE,fp))) { - fwrite(s,1,n,ftmp); - } - fclose(fp); fp = NULL; - fclose(ftmp); ftmp = NULL; - - if (write_restore_file) { - strcpy(restoreFileName, filename); - strcat(restoreFileName, ".asVerify"); - } else { - strcpy(restoreFileName, ""); - } - numDifferences = do_asVerify(tempname, verbose, debug, write_restore_file, restoreFileName); - - remove(tempname); - ca_context_destroy(); - return(numDifferences); + fp = fopen(filename, "r"); + if (fp == NULL) { + printf("Can't open %s\n", filename); + return (-1); + } + tempname = tmpnam(NULL); + ftmp = fopen(tempname, "w"); + if (ftmp == NULL) { + printf("Can't open temp file.\n"); + fclose(fp); + return (-1); + } + while (!feof(fp) && (n = fread(s, 1, BUF_SIZE, fp))) { fwrite(s, 1, n, ftmp); } + fclose(fp); + fp = NULL; + fclose(ftmp); + ftmp = NULL; + + if (write_restore_file) { + strcpy(restoreFileName, filename); + strcat(restoreFileName, ".asVerify"); + } else { + strcpy(restoreFileName, ""); + } + numDifferences = do_asVerify(tempname, verbose, debug, write_restore_file, restoreFileName); + + remove(tempname); + ca_context_destroy(); + return (numDifferences); } - diff --git a/asApp/src/configMenuClient.h b/asApp/src/configMenuClient.h index a3760c7..23a4bd0 100644 --- a/asApp/src/configMenuClient.h +++ b/asApp/src/configMenuClient.h @@ -9,6 +9,6 @@ extern int findConfigFiles(char *config, ELLLIST *configMenuList); struct configFileListItem { ELLNODE node; - char *name; - char *description; + char *name; + char *description; }; diff --git a/asApp/src/configMenuSub.c b/asApp/src/configMenuSub.c index 99f3fd7..09dfa70 100644 --- a/asApp/src/configMenuSub.c +++ b/asApp/src/configMenuSub.c @@ -10,30 +10,28 @@ #include "configMenuClient.h" -#define MAX(a,b) ((a)>(b)?(a):(b)) -#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) -volatile int configMenuDebug=0; +volatile int configMenuDebug = 0; void makeLegal(char *name); /* We need to know when a save or restore operation has completed, so client software * can wait for the operation to complete before acting on the result. */ -void configMenuCallback(int status, void *puserPvt) { - aSubRecord *pasub = (aSubRecord *)puserPvt; - epicsInt32 *d = (epicsInt32 *)pasub->d; - - if (configMenuDebug) - printf("configMenuCallback:status=%d, puserPvt=%p\n", status, puserPvt); - dbScanLock((dbCommon *)pasub); - *d = (epicsInt32)status; - dbScanUnlock((dbCommon *)pasub); - scanOnce((dbCommon *)puserPvt); +void configMenuCallback(int status, void *puserPvt) +{ + aSubRecord *pasub = (aSubRecord *)puserPvt; + epicsInt32 *d = (epicsInt32 *)pasub->d; + + if (configMenuDebug) printf("configMenuCallback:status=%d, puserPvt=%p\n", status, puserPvt); + dbScanLock((dbCommon *)pasub); + *d = (epicsInt32)status; + dbScanUnlock((dbCommon *)pasub); + scanOnce((dbCommon *)puserPvt); } -static long configMenu_init(aSubRecord *pasub) { - return(0); -} +static long configMenu_init(aSubRecord *pasub) { return (0); } /* * a - name of scan configuration to save or restore @@ -47,191 +45,181 @@ static long configMenu_init(aSubRecord *pasub) { * valb - desired state of busy record (used to clear) * valc - status value for output: 0=Success, 1=Error */ -static long configMenu_do(aSubRecord *pasub) { - char *a = (char *)pasub->a; - epicsInt32 *b = (epicsInt32 *)pasub->b; - char *c = (char *)pasub->c; - epicsInt32 *d = (epicsInt32 *)pasub->d; - short *e = (short *)pasub->e; - char *f = (char *)pasub->f; - char *g = (char *)pasub->g; - epicsInt32 *vala = (epicsInt32 *)pasub->vala; - epicsInt32 *valb = (epicsInt32 *)pasub->valb; - epicsInt32 *valc = (epicsInt32 *)pasub->valc; - char *macrostring = NULL; - char filename[100]; - - if (configMenuDebug) printf("configMenu_do:c='%s' (%s)\n", - c, *e?"save":"restore"); - - if (*e==0) { - /* restore */ - if (strcmp(c,"Done") == 0) { - /* start restore operation */ - if (configMenuDebug) - printf("configMenu_do:a='%s', c='%s', pasub=%p\n", a, c, pasub); - if (strlen(a)<1) { - *d = 1; - *valc = 1; - return(0); - } - if (f) { - macrostring = getMacroString(f); - } - makeLegal(a); - epicsSnprintf(filename, 99, "%s_%s.cfg", g, a); - *b = fdbrestoreX(filename, macrostring, configMenuCallback, (void *)pasub); - if (configMenuDebug) printf("configMenu_do:fdbrestore returned %d\n", *b); - *vala = 1; - *valb = 1; - } else { - /* this is a callback from restore operation */ - if (configMenuDebug) - printf("configMenu_do:callback status=%d\n", *valc); - *valc = (*d ? 1 : 0); - *vala = 0; - *valb = 0; - } - } else { - /* save */ - if (strcmp(c,"Done") == 0) { - /* start save operation */ - if (configMenuDebug) - printf("configMenu_do:a='%s', c='%s', pasub=%p\n", a, c, pasub); - if (strlen(a)<1) { - *d = 1; - *valc = 1; - return(0); - } - makeLegal(a); - epicsSnprintf(filename, 99, "%s_%s.cfg", g, a); - *b = (epicsInt32)manual_save(f, filename, configMenuCallback, (void *)pasub); - if (configMenuDebug) printf("configMenu_do:manual_save returned %d\n", *b); - *vala = 1; - *valb = 1; - } else { - /* this is a callback from a save operation */ - if (configMenuDebug) - printf("configMenu_do:save callback status=%d\n", *valc); - *valc = (*d ? 1 : 0); - *vala = 0; - *valb = 0; - } - } - return(0); +static long configMenu_do(aSubRecord *pasub) +{ + char *a = (char *)pasub->a; + epicsInt32 *b = (epicsInt32 *)pasub->b; + char *c = (char *)pasub->c; + epicsInt32 *d = (epicsInt32 *)pasub->d; + short *e = (short *)pasub->e; + char *f = (char *)pasub->f; + char *g = (char *)pasub->g; + epicsInt32 *vala = (epicsInt32 *)pasub->vala; + epicsInt32 *valb = (epicsInt32 *)pasub->valb; + epicsInt32 *valc = (epicsInt32 *)pasub->valc; + char *macrostring = NULL; + char filename[100]; + + if (configMenuDebug) printf("configMenu_do:c='%s' (%s)\n", c, *e ? "save" : "restore"); + + if (*e == 0) { + /* restore */ + if (strcmp(c, "Done") == 0) { + /* start restore operation */ + if (configMenuDebug) printf("configMenu_do:a='%s', c='%s', pasub=%p\n", a, c, pasub); + if (strlen(a) < 1) { + *d = 1; + *valc = 1; + return (0); + } + if (f) { macrostring = getMacroString(f); } + makeLegal(a); + epicsSnprintf(filename, 99, "%s_%s.cfg", g, a); + *b = fdbrestoreX(filename, macrostring, configMenuCallback, (void *)pasub); + if (configMenuDebug) printf("configMenu_do:fdbrestore returned %d\n", *b); + *vala = 1; + *valb = 1; + } else { + /* this is a callback from restore operation */ + if (configMenuDebug) printf("configMenu_do:callback status=%d\n", *valc); + *valc = (*d ? 1 : 0); + *vala = 0; + *valb = 0; + } + } else { + /* save */ + if (strcmp(c, "Done") == 0) { + /* start save operation */ + if (configMenuDebug) printf("configMenu_do:a='%s', c='%s', pasub=%p\n", a, c, pasub); + if (strlen(a) < 1) { + *d = 1; + *valc = 1; + return (0); + } + makeLegal(a); + epicsSnprintf(filename, 99, "%s_%s.cfg", g, a); + *b = (epicsInt32)manual_save(f, filename, configMenuCallback, (void *)pasub); + if (configMenuDebug) printf("configMenu_do:manual_save returned %d\n", *b); + *vala = 1; + *valb = 1; + } else { + /* this is a callback from a save operation */ + if (configMenuDebug) printf("configMenu_do:save callback status=%d\n", *valc); + *valc = (*d ? 1 : 0); + *vala = 0; + *valb = 0; + } + } + return (0); } -void makeLegal(char *name) { - int i; - for (i=0; idpvt = configMenuList; - ellInit(configMenuList); - return(0); +static long configMenuList_init(aSubRecord *pasub) +{ + ELLLIST *configMenuList; + configMenuList = calloc(1, sizeof(ELLLIST)); + pasub->dpvt = configMenuList; + ellInit(configMenuList); + return (0); } #define NUM_ITEMS 10 -static long configMenuList_do(aSubRecord *pasub) { - ELLLIST *configMenuList = (ELLLIST *)pasub->dpvt; - struct configFileListItem *pLI; - char *configName = (char *)pasub->a; - short *page = (short *)pasub->b; - short *findFiles = (short *)pasub->c; - short jStart; - char *f[NUM_ITEMS*2] = {0}; - int i, status=0; - - pLI = (struct configFileListItem *) ellFirst(configMenuList); - if (pLI==NULL) { - *findFiles = 1; - } - if (*findFiles || (pLI->name==NULL) || (pLI->name[0]=='\0')) { - status = findConfigFiles(configName, configMenuList); - if (configMenuDebug || status) printf("configMenuList_do(%s): findConfigFiles returned %d\n", - configName, status); - *findFiles = 0; - } - if (status == 0) { - /* names */ - f[0] = (char *)pasub->vala; - f[1] = (char *)pasub->valb; - f[2] = (char *)pasub->valc; - f[3] = (char *)pasub->vald; - f[4] = (char *)pasub->vale; - f[5] = (char *)pasub->valf; - f[6] = (char *)pasub->valg; - f[7] = (char *)pasub->valh; - f[8] = (char *)pasub->vali; - f[9] = (char *)pasub->valj; - - /* descriptions */ - f[10] = (char *)pasub->valk; - f[11] = (char *)pasub->vall; - f[12] = (char *)pasub->valm; - f[13] = (char *)pasub->valn; - f[14] = (char *)pasub->valo; - f[15] = (char *)pasub->valp; - f[16] = (char *)pasub->valq; - f[17] = (char *)pasub->valr; - f[18] = (char *)pasub->vals; - f[19] = (char *)pasub->valt; - - for (i=0; iname ? pLI->name : "(null)"); - } - pLI = (struct configFileListItem *) ellNext(&(pLI->node)); - } - - for (i=0; iname, 39); - if (pLI->description) { - strncpy(f[i+NUM_ITEMS], pLI->description, 39); - } else { - strncpy(f[i+NUM_ITEMS], "no description", 39); - } - pLI = (struct configFileListItem *) ellNext(&(pLI->node)); - } else { - f[i][0] = '\0'; - f[i+NUM_ITEMS][0] = '\0'; - } - } - } - return(0); +static long configMenuList_do(aSubRecord *pasub) +{ + ELLLIST *configMenuList = (ELLLIST *)pasub->dpvt; + struct configFileListItem *pLI; + char *configName = (char *)pasub->a; + short *page = (short *)pasub->b; + short *findFiles = (short *)pasub->c; + short jStart; + char *f[NUM_ITEMS * 2] = {0}; + int i, status = 0; + + pLI = (struct configFileListItem *)ellFirst(configMenuList); + if (pLI == NULL) { *findFiles = 1; } + if (*findFiles || (pLI->name == NULL) || (pLI->name[0] == '\0')) { + status = findConfigFiles(configName, configMenuList); + if (configMenuDebug || status) + printf("configMenuList_do(%s): findConfigFiles returned %d\n", configName, status); + *findFiles = 0; + } + if (status == 0) { + /* names */ + f[0] = (char *)pasub->vala; + f[1] = (char *)pasub->valb; + f[2] = (char *)pasub->valc; + f[3] = (char *)pasub->vald; + f[4] = (char *)pasub->vale; + f[5] = (char *)pasub->valf; + f[6] = (char *)pasub->valg; + f[7] = (char *)pasub->valh; + f[8] = (char *)pasub->vali; + f[9] = (char *)pasub->valj; + + /* descriptions */ + f[10] = (char *)pasub->valk; + f[11] = (char *)pasub->vall; + f[12] = (char *)pasub->valm; + f[13] = (char *)pasub->valn; + f[14] = (char *)pasub->valo; + f[15] = (char *)pasub->valp; + f[16] = (char *)pasub->valq; + f[17] = (char *)pasub->valr; + f[18] = (char *)pasub->vals; + f[19] = (char *)pasub->valt; + + for (i = 0; i < NUM_ITEMS; i++) { + f[i][0] = '\0'; + f[i + NUM_ITEMS][0] = '\0'; + } + + if (configMenuDebug) printf("configMenuList_do(%s): page %d\n", configName, *page); + jStart = MAX(0, *page * NUM_ITEMS); + + pLI = (struct configFileListItem *)ellFirst(configMenuList); + for (i = 0; i < jStart && pLI; i++) { + if (configMenuDebug) { + printf("configMenuList_do(%s): skipping name '%s'\n", configName, pLI->name ? pLI->name : "(null)"); + } + pLI = (struct configFileListItem *)ellNext(&(pLI->node)); + } + + for (i = 0; i < NUM_ITEMS; i++) { + if (pLI) { + strncpy(f[i], pLI->name, 39); + if (pLI->description) { + strncpy(f[i + NUM_ITEMS], pLI->description, 39); + } else { + strncpy(f[i + NUM_ITEMS], "no description", 39); + } + pLI = (struct configFileListItem *)ellNext(&(pLI->node)); + } else { + f[i][0] = '\0'; + f[i + NUM_ITEMS][0] = '\0'; + } + } + } + return (0); } - #include #include epicsExportAddress(int, configMenuDebug); -static registryFunctionRef configMenuRef[] = { - {"configMenuList_init", (REGISTRYFUNCTION)configMenuList_init}, - {"configMenuList_do", (REGISTRYFUNCTION)configMenuList_do}, - {"configMenu_init", (REGISTRYFUNCTION)configMenu_init}, - {"configMenu_do", (REGISTRYFUNCTION)configMenu_do} -}; +static registryFunctionRef configMenuRef[] = {{"configMenuList_init", (REGISTRYFUNCTION)configMenuList_init}, + {"configMenuList_do", (REGISTRYFUNCTION)configMenuList_do}, + {"configMenu_init", (REGISTRYFUNCTION)configMenu_init}, + {"configMenu_do", (REGISTRYFUNCTION)configMenu_do}}; -static void configMenuRegistrar(void) { - registryFunctionRefAdd(configMenuRef, NELEMENTS(configMenuRef)); -} +static void configMenuRegistrar(void) { registryFunctionRefAdd(configMenuRef, NELEMENTS(configMenuRef)); } epicsExportRegistrar(configMenuRegistrar); diff --git a/asApp/src/dbrestore.c b/asApp/src/dbrestore.c index 2e73822..d098dce 100644 --- a/asApp/src/dbrestore.c +++ b/asApp/src/dbrestore.c @@ -62,35 +62,35 @@ */ #define VERSION "5.1" -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include /* added for 3.14 port */ -#include /* for safeDoubleToFloat() */ -#include /* for safeDoubleToFloat() */ - -#include -#include /* includes dbDefs.h, dbBase.h, dbAddr.h, dbFldTypes.h */ -#include /* rset */ -#include /* dbPutConvertRoutine */ -#include /* dbFastPutConvertRoutine */ -#include -#include -#include -#include -#include "fGetDateStr.h" -#include "save_restore.h" -#include -#include -#include -#include -#include -#include -#include +#include /* for safeDoubleToFloat() */ +#include /* for safeDoubleToFloat() */ + +#include +#include /* includes dbDefs.h, dbBase.h, dbAddr.h, dbFldTypes.h */ +#include /* rset */ +#include /* dbPutConvertRoutine */ +#include /* dbFastPutConvertRoutine */ +#include +#include +#include +#include +#include "fGetDateStr.h" +#include "save_restore.h" +#include +#include +#include +#include +#include +#include +#include #ifndef vxWorks #define OK 0 @@ -98,217 +98,223 @@ #endif /* EPICS base version tests.*/ -#define LT_EPICSBASE(v,r,l) ((EPICS_VERSION<=(v)) && (EPICS_REVISION<=(r)) && (EPICS_MODIFICATION<(l))) -#define GE_EPICSBASE(v,r,l) ((EPICS_VERSION>=(v)) && (EPICS_REVISION>=(r)) && (EPICS_MODIFICATION>=(l))) +#define LT_EPICSBASE(v, r, l) ((EPICS_VERSION <= (v)) && (EPICS_REVISION <= (r)) && (EPICS_MODIFICATION < (l))) +#define GE_EPICSBASE(v, r, l) ((EPICS_VERSION >= (v)) && (EPICS_REVISION >= (r)) && (EPICS_MODIFICATION >= (l))) -int restoreFileListsInitialized=0; +int restoreFileListsInitialized = 0; ELLLIST pass0List; ELLLIST pass1List; -void myPrintErrno(char *s, char *file, int line) { - errlogPrintf("%s(%d): [0x%x]=%s:%s\n", file, line, errno, s, strerror(errno)); +void myPrintErrno(char *s, char *file, int line) +{ + errlogPrintf("%s(%d): [0x%x]=%s:%s\n", file, line, errno, s, strerror(errno)); } float mySafeDoubleToFloat(double d) { - float f; + float f; double abs = fabs(d); - if (d==0.0) { + if (d == 0.0) { f = 0.0; - } else if (abs>=FLT_MAX) { - if (d>0.0) f = FLT_MAX; else f = -FLT_MAX; - } else if (abs<=FLT_MIN) { - if (d>0.0) f = FLT_MIN; else f = -FLT_MIN; + } else if (abs >= FLT_MAX) { + if (d > 0.0) f = FLT_MAX; + else f = -FLT_MAX; + } else if (abs <= FLT_MIN) { + if (d > 0.0) f = FLT_MIN; + else f = -FLT_MIN; } else { f = d; } - return(f); + return (f); } -void maybeInitRestoreFileLists() { - if (!restoreFileListsInitialized) { - ellInit(&pass0List); - ellInit(&pass1List); - restoreFileListsInitialized = 1; - } +void maybeInitRestoreFileLists() +{ + if (!restoreFileListsInitialized) { + ellInit(&pass0List); + ellInit(&pass1List); + restoreFileListsInitialized = 1; + } } void dbrestoreShow(void) { - struct restoreFileListItem *pLI; - - maybeInitRestoreFileLists(); - - printf(" ' filename ' - status - 'message' - 'macro string'\n"); - printf(" pass 0:\n"); - pLI = (struct restoreFileListItem *) ellFirst(&pass0List); - while (pLI) { - printf(" '%s' - %s - '%s' - '%s'\n", pLI->filename, - SR_STATUS_STR[pLI->restoreStatus], pLI->restoreStatusStr, - pLI->macrostring ? pLI->macrostring : "None"); - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - - printf(" pass 1:\n"); - pLI = (struct restoreFileListItem *) ellFirst(&pass1List); - while (pLI) { - printf(" '%s' - %s - '%s'\n", pLI->filename, - SR_STATUS_STR[pLI->restoreStatus], pLI->restoreStatusStr); - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } + struct restoreFileListItem *pLI; + + maybeInitRestoreFileLists(); + + printf(" ' filename ' - status - 'message' - 'macro string'\n"); + printf(" pass 0:\n"); + pLI = (struct restoreFileListItem *)ellFirst(&pass0List); + while (pLI) { + printf(" '%s' - %s - '%s' - '%s'\n", pLI->filename, SR_STATUS_STR[pLI->restoreStatus], pLI->restoreStatusStr, + pLI->macrostring ? pLI->macrostring : "None"); + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + + printf(" pass 1:\n"); + pLI = (struct restoreFileListItem *)ellFirst(&pass1List); + while (pLI) { + printf(" '%s' - %s - '%s'\n", pLI->filename, SR_STATUS_STR[pLI->restoreStatus], pLI->restoreStatusStr); + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } } STATIC int myFileCopy(const char *source, const char *dest) { - FILE *source_fd, *dest_fd; - char buffer[BUF_SIZE], *bp; - struct stat fileStat; - int chars_printed, size=0; - - if (save_restoreDebug >= 5) - errlogPrintf("dbrestore:myFileCopy: copying '%s' to '%s'\n", source, dest); - - if (stat(source, &fileStat) == 0) size = (int)fileStat.st_size; - errno = 0; - if ((source_fd = fopen(source,"rb")) == NULL) { - errlogPrintf("save_restore:myFileCopy: Can't open file '%s'\n", source); - /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ - if (++save_restoreIoErrors > save_restoreRemountThreshold) - save_restoreNFSOK = 0; - return(ERROR); - } - errno = 0; - /* Note: under vxWorks, the following fopen() frequently will set errno + FILE *source_fd, *dest_fd; + char buffer[BUF_SIZE], *bp; + struct stat fileStat; + int chars_printed, size = 0; + + if (save_restoreDebug >= 5) errlogPrintf("dbrestore:myFileCopy: copying '%s' to '%s'\n", source, dest); + + if (stat(source, &fileStat) == 0) size = (int)fileStat.st_size; + errno = 0; + if ((source_fd = fopen(source, "rb")) == NULL) { + errlogPrintf("save_restore:myFileCopy: Can't open file '%s'\n", source); + /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ + if (++save_restoreIoErrors > save_restoreRemountThreshold) save_restoreNFSOK = 0; + return (ERROR); + } + errno = 0; + /* Note: under vxWorks, the following fopen() frequently will set errno * to S_nfsLib_NFSERR_NOENT even though it succeeds. Probably this means * a failed attempt was retried. (System calls never set errno to zero.) */ - if ((dest_fd = fopen(dest,"wb")) == NULL) { - errlogPrintf("save_restore:myFileCopy: Can't open file '%s'\n", dest); - /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ - fclose(source_fd); - return(ERROR); - } - chars_printed = 0; - while ((bp=fgets(buffer, BUF_SIZE, source_fd))) { - errno = 0; - chars_printed += fprintf(dest_fd, "%s", bp); - /* if (errno) {myPrintErrno("myFileCopy", __FILE__, __LINE__); errno = 0;} */ - } - errno = 0; - if (fclose(source_fd) != 0){ - errlogPrintf("save_restore:myFileCopy: Error closing file '%s'\n", source); - /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ - } - errno = 0; - if (fclose(dest_fd) != 0){ - errlogPrintf("save_restore:myFileCopy: Error closing file '%s'\n", dest); - /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ - } - errno = 0; - if (size && (chars_printed != size)) { - errlogPrintf("myFileCopy: size=%d, chars_printed=%d\n", - size, chars_printed); - return(ERROR); - } - return(OK); + if ((dest_fd = fopen(dest, "wb")) == NULL) { + errlogPrintf("save_restore:myFileCopy: Can't open file '%s'\n", dest); + /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ + fclose(source_fd); + return (ERROR); + } + chars_printed = 0; + while ((bp = fgets(buffer, BUF_SIZE, source_fd))) { + errno = 0; + chars_printed += fprintf(dest_fd, "%s", bp); + /* if (errno) {myPrintErrno("myFileCopy", __FILE__, __LINE__); errno = 0;} */ + } + errno = 0; + if (fclose(source_fd) != 0) { + errlogPrintf("save_restore:myFileCopy: Error closing file '%s'\n", source); + /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ + } + errno = 0; + if (fclose(dest_fd) != 0) { + errlogPrintf("save_restore:myFileCopy: Error closing file '%s'\n", dest); + /* if (errno) myPrintErrno("myFileCopy", __FILE__, __LINE__); */ + } + errno = 0; + if (size && (chars_printed != size)) { + errlogPrintf("myFileCopy: size=%d, chars_printed=%d\n", size, chars_printed); + return (ERROR); + } + return (OK); } - STATIC long scalar_restore(int pass, DBENTRY *pdbentry, char *PVname, char *value_string, int is_long_string) { - long n, status = 0; - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - dbfType field_type = pdbentry->pflddes->field_type; - short special = pdbentry->pflddes->special; - /* The buffer holding the string value must be at least one byte longer than + long n, status = 0; + DBADDR dbaddr; + DBADDR *paddr = &dbaddr; + dbfType field_type = pdbentry->pflddes->field_type; + short special = pdbentry->pflddes->special; + /* The buffer holding the string value must be at least one byte longer than the actual value (due to the terminating null byte). */ - size_t value_string_len = strlen(value_string) + 1; + size_t value_string_len = strlen(value_string) + 1; - /* We do know the length of the buffer for sure, because this depends on the + /* We do know the length of the buffer for sure, because this depends on the calling code, so we limit to the actual string size. */ - epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); - - if (save_restoreDebug >= 5) errlogPrintf("dbrestore:scalar_restore:entry:field type '%s'\n", pamapdbfType[field_type].strvalue); - switch (field_type) { - case DBF_STRING: case DBF_ENUM: - case DBF_CHAR: case DBF_UCHAR: - case DBF_SHORT: case DBF_USHORT: - case DBF_LONG: case DBF_ULONG: - #ifdef DBR_INT64 - case DBF_INT64: case DBF_UINT64: - #endif - case DBF_FLOAT: case DBF_DOUBLE: - /* + epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); + + if (save_restoreDebug >= 5) + errlogPrintf("dbrestore:scalar_restore:entry:field type '%s'\n", pamapdbfType[field_type].strvalue); + switch (field_type) { + case DBF_STRING: + case DBF_ENUM: + case DBF_CHAR: + case DBF_UCHAR: + case DBF_SHORT: + case DBF_USHORT: + case DBF_LONG: + case DBF_ULONG: +#ifdef DBR_INT64 + case DBF_INT64: + case DBF_UINT64: +#endif + case DBF_FLOAT: + case DBF_DOUBLE: + /* * check SPC_CALC fields against new (3.13.9) requirement that CALC * fields not be empty. */ - if ((field_type==DBF_STRING) && (special==SPC_CALC)){ - if (*value_string == 0) strcpy(value_string, "0"); - } - - status = dbPutString(pdbentry, value_string); - if (save_restoreDebug >= 15) { - errlogPrintf("dbrestore:scalar_restore: dbPutString() returns %ld:", status); - errMessage(status, " "); - } - - break; - - case DBF_INLINK: case DBF_OUTLINK: case DBF_FWDLINK: - /* Can't restore links in pass 1 */ - if (pass == 0) { - status = dbPutString(pdbentry, value_string); - if (save_restoreDebug >= 15) { - errlogPrintf("dbrestore:scalar_restore: dbPutString() returns %ld:", status); - errMessage(status, " "); - } - } else if (save_restoreDebug > 1) { - errlogPrintf("dbrestore:scalar_restore: Can't restore link field (%s) in pass 1.\n", PVname); - } - break; - - case DBF_MENU: - n = (int)atol(value_string); - status = dbPutMenuIndex(pdbentry, n); - if (save_restoreDebug >= 15) { - errlogPrintf("dbrestore:scalar_restore: dbPutMenuIndex() returns %ld:", status); - errMessage(status, " "); - } - break; - - case DBF_NOACCESS: - if (pass == 1) { - status = dbNameToAddr(PVname, paddr); - if (!status) { - if (is_long_string && paddr->field_type == DBF_CHAR) { - status = dbPut(paddr, DBF_CHAR, value_string, strlen(value_string) + 1); - } else { - status = dbPut(paddr, DBF_STRING, value_string, 1); - } - } - } else if (save_restoreDebug > 1) { - errlogPrintf("dbrestore:scalar_restore: Can't restore DBF_NOACCESS field (%s) in pass 0.\n", PVname); - } - break; - - default: - status = -1; - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:scalar_restore: field_type '%d' not handled\n", field_type); - } - break; - } - if (status) { - errlogPrintf("dbrestore:scalar_restore: restore of '%s' for '%s' failed\n", - value_string, PVname); - errMessage(status," "); - } - if (save_restoreDebug >= 15) { - errlogPrintf("dbrestore:scalar_restore: dbGetString() returns '%s'\n",dbGetString(pdbentry)); - } - return(status); + if ((field_type == DBF_STRING) && (special == SPC_CALC)) { + if (*value_string == 0) strcpy(value_string, "0"); + } + + status = dbPutString(pdbentry, value_string); + if (save_restoreDebug >= 15) { + errlogPrintf("dbrestore:scalar_restore: dbPutString() returns %ld:", status); + errMessage(status, " "); + } + + break; + + case DBF_INLINK: + case DBF_OUTLINK: + case DBF_FWDLINK: + /* Can't restore links in pass 1 */ + if (pass == 0) { + status = dbPutString(pdbentry, value_string); + if (save_restoreDebug >= 15) { + errlogPrintf("dbrestore:scalar_restore: dbPutString() returns %ld:", status); + errMessage(status, " "); + } + } else if (save_restoreDebug > 1) { + errlogPrintf("dbrestore:scalar_restore: Can't restore link field (%s) in pass 1.\n", PVname); + } + break; + + case DBF_MENU: + n = (int)atol(value_string); + status = dbPutMenuIndex(pdbentry, n); + if (save_restoreDebug >= 15) { + errlogPrintf("dbrestore:scalar_restore: dbPutMenuIndex() returns %ld:", status); + errMessage(status, " "); + } + break; + + case DBF_NOACCESS: + if (pass == 1) { + status = dbNameToAddr(PVname, paddr); + if (!status) { + if (is_long_string && paddr->field_type == DBF_CHAR) { + status = dbPut(paddr, DBF_CHAR, value_string, strlen(value_string) + 1); + } else { + status = dbPut(paddr, DBF_STRING, value_string, 1); + } + } + } else if (save_restoreDebug > 1) { + errlogPrintf("dbrestore:scalar_restore: Can't restore DBF_NOACCESS field (%s) in pass 0.\n", PVname); + } + break; + + default: + status = -1; + if (save_restoreDebug >= 1) { + errlogPrintf("dbrestore:scalar_restore: field_type '%d' not handled\n", field_type); + } + break; + } + if (status) { + errlogPrintf("dbrestore:scalar_restore: restore of '%s' for '%s' failed\n", value_string, PVname); + errMessage(status, " "); + } + if (save_restoreDebug >= 15) { + errlogPrintf("dbrestore:scalar_restore: dbGetString() returns '%s'\n", dbGetString(pdbentry)); + } + return (status); } static void *p_data = NULL; @@ -316,44 +322,41 @@ static long p_data_size = 0; long SR_put_array_values(char *PVname, void *p_data, long num_values) { - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - long status, max_elements=0; - STATIC long curr_no_elements=0, offset=0; - rset *prset; - dbfType field_type; - - if ((status = dbNameToAddr(PVname, paddr)) != 0) { - errlogPrintf("save_restore: dbNameToAddr can't find PV '%s'\n", PVname); - return(status); - } - /* restore array values */ - max_elements = paddr->no_elements; - field_type = paddr->field_type; - prset = dbGetRset(paddr); - if (prset && (prset->get_array_info) ) { - status = (*prset->get_array_info)(paddr, &curr_no_elements, &offset); - } else { - offset = 0; - } - if (save_restoreDebug >= 5) { - errlogPrintf("dbrestore:SR_put_array_values: restoring %ld values to %s (max_elements=%ld)\n", num_values, PVname, max_elements); - } - if (VALID_DB_REQ(field_type)) { - status = (*dbPutConvertRoutine[field_type][field_type])(paddr,p_data,num_values,max_elements,offset); - } else { - errlogPrintf("save_restore:SR_put_array_values: PV %s: bad field type '%d'\n", - PVname, (int) field_type); - status = -1; - } - /* update array info */ - if (prset && (prset->put_array_info) && !status) { - status = (*prset->put_array_info)(paddr, num_values); - } - return(status); + DBADDR dbaddr; + DBADDR *paddr = &dbaddr; + long status, max_elements = 0; + STATIC long curr_no_elements = 0, offset = 0; + rset *prset; + dbfType field_type; + + if ((status = dbNameToAddr(PVname, paddr)) != 0) { + errlogPrintf("save_restore: dbNameToAddr can't find PV '%s'\n", PVname); + return (status); + } + /* restore array values */ + max_elements = paddr->no_elements; + field_type = paddr->field_type; + prset = dbGetRset(paddr); + if (prset && (prset->get_array_info)) { + status = (*prset->get_array_info)(paddr, &curr_no_elements, &offset); + } else { + offset = 0; + } + if (save_restoreDebug >= 5) { + errlogPrintf("dbrestore:SR_put_array_values: restoring %ld values to %s (max_elements=%ld)\n", num_values, + PVname, max_elements); + } + if (VALID_DB_REQ(field_type)) { + status = (*dbPutConvertRoutine[field_type][field_type])(paddr, p_data, num_values, max_elements, offset); + } else { + errlogPrintf("save_restore:SR_put_array_values: PV %s: bad field type '%d'\n", PVname, (int)field_type); + status = -1; + } + /* update array info */ + if (prset && (prset->put_array_info) && !status) { status = (*prset->put_array_info)(paddr, num_values); } + return (status); } - /* SR_array_restore() * * Parse file *inp_fd, starting with value_string, to extract array data into *p_data @@ -383,433 +386,345 @@ long SR_put_array_values(char *PVname, void *p_data, long num_values) */ long SR_array_restore(int pass, FILE *inp_fd, char *PVname, char *value_string, int gobble) { - int j, end_mark_found=0, begin_mark_found=0, end_of_file=0, found=0, in_element=0; - long status=0, max_elements=0, num_read=0; - char buffer[BUF_SIZE], *bp = NULL; - char string[MAX_STRING_SIZE]; - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - dbfType field_type = DBF_NOACCESS; - int field_size = 0; - char *p_char = NULL; - short *p_short = NULL; - epicsInt32 *p_long = NULL; - epicsInt64 *p_int64 = NULL; - unsigned char *p_uchar = NULL; - unsigned short *p_ushort = NULL; - epicsUInt32 *p_ulong = NULL; - epicsUInt64 *p_uint64 = NULL; - float *p_float = NULL; - double *p_double = NULL; - - - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore:entry: PV = '%s'\n", PVname); - } - if (!gobble) { - status = dbNameToAddr(PVname, paddr); - if (status != 0) { - errlogPrintf("save_restore: dbNameToAddr can't find PV '%s'\n", PVname); - gobble = 1; - } - } - - if (!gobble) { - /*** set up infrastructure for collecting array elements from file into local array ***/ - max_elements = paddr->no_elements; - field_type = paddr->field_type; - field_size = paddr->field_size; - /* if we've already allocated a big enough memory block, use it */ - if ((p_data == NULL) || ((max_elements * field_size) > p_data_size)) { - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore: p_data = %p, p_data_size = %ld\n", p_data, p_data_size); - } - if (p_data) free(p_data); - p_data = (void *)calloc(max_elements, field_size); - p_data_size = p_data ? max_elements * field_size : 0; - if (save_restoreDebug >= 10) errlogPrintf("dbrestore:SR_array_restore: allocated p_data = %p, p_data_size = %ld\n", p_data, p_data_size); - } else { - memset(p_data, 0, p_data_size); - } - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: Looking for up to %ld elements of field-size %d\n", max_elements, field_size); - errlogPrintf("dbrestore:SR_array_restore: ...field_type is '%s' (%d)\n", pamapdbfType[field_type].strvalue, field_type); - } - - switch (field_type) { - case DBF_STRING: case DBF_CHAR: p_char = (char *)p_data; break; - case DBF_UCHAR: p_uchar = (unsigned char *)p_data; break; - case DBF_ENUM: case DBF_USHORT: case DBF_MENU: p_ushort = (unsigned short *)p_data; break; - case DBF_SHORT: p_short = (short *)p_data; break; - case DBF_ULONG: p_ulong = (epicsUInt32 *)p_data; break; - case DBF_LONG: p_long = (epicsInt32 *)p_data; break; - #ifdef DBR_INT64 - case DBF_INT64: p_int64 = (epicsInt64 *)p_data; break; - case DBF_UINT64: p_uint64 = (epicsUInt64 *)p_data; break; - #endif - case DBF_FLOAT: p_float = (float *)p_data; break; - case DBF_DOUBLE: p_double = (double *)p_data; break; - case DBF_NOACCESS: - break; /* just go through the motions, so we can parse the file */ - default: - errlogPrintf("save_restore: field_type '%s' not handled\n", pamapdbfType[field_type].strvalue); - status = -1; - break; - } - } - - - /** read array values **/ - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: parsing buffer '%s'\n", value_string); - } - - if (value_string==NULL || *value_string=='\0') { - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: value_string is null or empty\n"); - } - /* nothing to write; write zero or "" */ - if (p_data) { - switch (field_type) { - case DBF_STRING: - strcpy(p_char, ""); - break; - case DBF_ENUM: case DBF_USHORT: case DBF_MENU: - p_ushort[num_read++] = (unsigned short)0; - break; - case DBF_UCHAR: - p_uchar[num_read++] = (unsigned char)0; - break; - case DBF_CHAR: - p_char[num_read++] = (char)0; - break; - case DBF_SHORT: - p_short[num_read++] = (short)0; - break; - case DBF_LONG: - p_long[num_read++] = (epicsInt32) 0; - break; - case DBF_ULONG: - p_ulong[num_read++] = (epicsUInt32) 0; - break; - #ifdef DBR_INT64 - case DBF_INT64: - p_int64[num_read++] = (epicsInt64) 0; - break; - case DBF_UINT64: - p_uint64[num_read++] = (epicsUInt64) 0; - break; - #endif - case DBF_FLOAT: - p_float[num_read++] = 0; - break; - case DBF_DOUBLE: - p_double[num_read++] = 0; - break; - case DBF_NOACCESS: - default: - break; - } - } - } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) == NULL) { - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: ARRAY_BEGIN not found\n"); - } - /* doesn't look like array data. just restore what we have */ - if (p_data) { - /* We do know the length of the buffer for sure, because this + int j, end_mark_found = 0, begin_mark_found = 0, end_of_file = 0, found = 0, in_element = 0; + long status = 0, max_elements = 0, num_read = 0; + char buffer[BUF_SIZE], *bp = NULL; + char string[MAX_STRING_SIZE]; + DBADDR dbaddr; + DBADDR *paddr = &dbaddr; + dbfType field_type = DBF_NOACCESS; + int field_size = 0; + char *p_char = NULL; + short *p_short = NULL; + epicsInt32 *p_long = NULL; + epicsInt64 *p_int64 = NULL; + unsigned char *p_uchar = NULL; + unsigned short *p_ushort = NULL; + epicsUInt32 *p_ulong = NULL; + epicsUInt64 *p_uint64 = NULL; + float *p_float = NULL; + double *p_double = NULL; + + if (save_restoreDebug >= 1) { errlogPrintf("dbrestore:SR_array_restore:entry: PV = '%s'\n", PVname); } + if (!gobble) { + status = dbNameToAddr(PVname, paddr); + if (status != 0) { + errlogPrintf("save_restore: dbNameToAddr can't find PV '%s'\n", PVname); + gobble = 1; + } + } + + if (!gobble) { + /*** set up infrastructure for collecting array elements from file into local array ***/ + max_elements = paddr->no_elements; + field_type = paddr->field_type; + field_size = paddr->field_size; + /* if we've already allocated a big enough memory block, use it */ + if ((p_data == NULL) || ((max_elements * field_size) > p_data_size)) { + if (save_restoreDebug >= 1) { + errlogPrintf("dbrestore:SR_array_restore: p_data = %p, p_data_size = %ld\n", p_data, p_data_size); + } + if (p_data) free(p_data); + p_data = (void *)calloc(max_elements, field_size); + p_data_size = p_data ? max_elements * field_size : 0; + if (save_restoreDebug >= 10) + errlogPrintf("dbrestore:SR_array_restore: allocated p_data = %p, p_data_size = %ld\n", p_data, + p_data_size); + } else { + memset(p_data, 0, p_data_size); + } + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:SR_array_restore: Looking for up to %ld elements of field-size %d\n", max_elements, + field_size); + errlogPrintf("dbrestore:SR_array_restore: ...field_type is '%s' (%d)\n", pamapdbfType[field_type].strvalue, + field_type); + } + + switch (field_type) { + case DBF_STRING: + case DBF_CHAR: p_char = (char *)p_data; break; + case DBF_UCHAR: p_uchar = (unsigned char *)p_data; break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: p_ushort = (unsigned short *)p_data; break; + case DBF_SHORT: p_short = (short *)p_data; break; + case DBF_ULONG: p_ulong = (epicsUInt32 *)p_data; break; + case DBF_LONG: p_long = (epicsInt32 *)p_data; break; +#ifdef DBR_INT64 + case DBF_INT64: p_int64 = (epicsInt64 *)p_data; break; + case DBF_UINT64: p_uint64 = (epicsUInt64 *)p_data; break; +#endif + case DBF_FLOAT: p_float = (float *)p_data; break; + case DBF_DOUBLE: p_double = (double *)p_data; break; + case DBF_NOACCESS: break; /* just go through the motions, so we can parse the file */ + default: + errlogPrintf("save_restore: field_type '%s' not handled\n", pamapdbfType[field_type].strvalue); + status = -1; + break; + } + } + + /** read array values **/ + if (save_restoreDebug >= 11) { errlogPrintf("dbrestore:SR_array_restore: parsing buffer '%s'\n", value_string); } + + if (value_string == NULL || *value_string == '\0') { + if (save_restoreDebug >= 11) { errlogPrintf("dbrestore:SR_array_restore: value_string is null or empty\n"); } + /* nothing to write; write zero or "" */ + if (p_data) { + switch (field_type) { + case DBF_STRING: strcpy(p_char, ""); break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: p_ushort[num_read++] = (unsigned short)0; break; + case DBF_UCHAR: p_uchar[num_read++] = (unsigned char)0; break; + case DBF_CHAR: p_char[num_read++] = (char)0; break; + case DBF_SHORT: p_short[num_read++] = (short)0; break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)0; break; + case DBF_ULONG: p_ulong[num_read++] = (epicsUInt32)0; break; +#ifdef DBR_INT64 + case DBF_INT64: p_int64[num_read++] = (epicsInt64)0; break; + case DBF_UINT64: p_uint64[num_read++] = (epicsUInt64)0; break; +#endif + case DBF_FLOAT: p_float[num_read++] = 0; break; + case DBF_DOUBLE: p_double[num_read++] = 0; break; + case DBF_NOACCESS: + default: break; + } + } + } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) == NULL) { + if (save_restoreDebug >= 11) { errlogPrintf("dbrestore:SR_array_restore: ARRAY_BEGIN not found\n"); } + /* doesn't look like array data. just restore what we have */ + if (p_data) { + /* We do know the length of the buffer for sure, because this depends on the calling code, so we limit to the actual string size. The buffer must be one byte longer, due to the terminating null byte. */ - size_t value_string_len = strlen(value_string) + 1; - epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); - switch (field_type) { - case DBF_STRING: - /* future: translate escape sequence */ - strNcpy(&(p_char[(num_read++)*MAX_STRING_SIZE]), value_string, MAX_STRING_SIZE); - break; - case DBF_ENUM: case DBF_USHORT: case DBF_MENU: - p_ushort[num_read++] = (unsigned short)atol(value_string); - break; - case DBF_UCHAR: - p_uchar[num_read++] = (unsigned char)atol(value_string); - break; - case DBF_CHAR: - p_char[num_read++] = (char)atol(value_string); - break; - case DBF_SHORT: - p_short[num_read++] = (short)atol(value_string); - break; - case DBF_LONG: - p_long[num_read++] = (epicsInt32) atol(value_string); - break; - case DBF_ULONG: - p_ulong[num_read++] = (epicsUInt32) strtoul(value_string,NULL,0); - break; - #ifdef DBR_INT64 - case DBF_INT64: - epicsParseInt64(value_string, &p_int64[num_read++], 10, NULL); - break; - case DBF_UINT64: - epicsParseUInt64(value_string, &p_uint64[num_read++], 10, NULL); - break; - #endif - case DBF_FLOAT: - p_float[num_read++] = mySafeDoubleToFloat(atof(value_string)); - break; - case DBF_DOUBLE: - p_double[num_read++] = atof(value_string); - break; - case DBF_NOACCESS: - default: - break; - } - } - } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { - begin_mark_found = 1; - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: parsing array buffer '%s'\n", bp); - } - for (num_read=0; bp && !end_mark_found; ) { - /* Find beginning of array element */ - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: looking for element[%ld] \n", num_read); - } - /* If truncated-file detector (checkFile) fails, test for end of file before + size_t value_string_len = strlen(value_string) + 1; + epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); + switch (field_type) { + case DBF_STRING: + /* future: translate escape sequence */ + strNcpy(&(p_char[(num_read++) * MAX_STRING_SIZE]), value_string, MAX_STRING_SIZE); + break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: p_ushort[num_read++] = (unsigned short)atol(value_string); break; + case DBF_UCHAR: p_uchar[num_read++] = (unsigned char)atol(value_string); break; + case DBF_CHAR: p_char[num_read++] = (char)atol(value_string); break; + case DBF_SHORT: p_short[num_read++] = (short)atol(value_string); break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)atol(value_string); break; + case DBF_ULONG: p_ulong[num_read++] = (epicsUInt32)strtoul(value_string, NULL, 0); break; +#ifdef DBR_INT64 + case DBF_INT64: epicsParseInt64(value_string, &p_int64[num_read++], 10, NULL); break; + case DBF_UINT64: epicsParseUInt64(value_string, &p_uint64[num_read++], 10, NULL); break; +#endif + case DBF_FLOAT: p_float[num_read++] = mySafeDoubleToFloat(atof(value_string)); break; + case DBF_DOUBLE: p_double[num_read++] = atof(value_string); break; + case DBF_NOACCESS: + default: break; + } + } + } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { + begin_mark_found = 1; + if (save_restoreDebug >= 10) { errlogPrintf("dbrestore:SR_array_restore: parsing array buffer '%s'\n", bp); } + for (num_read = 0; bp && !end_mark_found;) { + /* Find beginning of array element */ + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:SR_array_restore: looking for element[%ld] \n", num_read); + } + /* If truncated-file detector (checkFile) fails, test for end of file before * using *bp */ - while (!end_mark_found && !end_of_file && (*bp != ELEMENT_BEGIN)) { - if (save_restoreDebug >= 12) { - errlogPrintf("dbrestore:SR_array_restore: ...buffer contains '%s'\n", bp); - } - switch (*bp) { - case '\0': - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - errlogPrintf("save_restore: *** EOF during array-parse\n"); - end_of_file = 1; - } - break; - case ARRAY_END: - end_mark_found = 1; - break; - default: - ++bp; - break; - } - } - /* + while (!end_mark_found && !end_of_file && (*bp != ELEMENT_BEGIN)) { + if (save_restoreDebug >= 12) { + errlogPrintf("dbrestore:SR_array_restore: ...buffer contains '%s'\n", bp); + } + switch (*bp) { + case '\0': + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + errlogPrintf("save_restore: *** EOF during array-parse\n"); + end_of_file = 1; + } + break; + case ARRAY_END: end_mark_found = 1; break; + default: ++bp; break; + } + } + /* * Read one element: Accumulate characters of element value into string[], * ignoring any nonzero control characters, and append the value to the local array. */ - if (bp && !end_mark_found && !end_of_file) { - /* *bp == ELEMENT_BEGIN */ - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: Found element-begin; buffer contains '%s'\n", bp); - } - for (bp++, j=0; (j < MAX_STRING_SIZE-1) && (*bp != ELEMENT_END); bp++) { - if (save_restoreDebug >= 11) errlogPrintf("dbrestore:SR_array_restore: *bp=%c (%d)\n", *bp, (int)*bp); - if (*bp == '\0') { - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - errlogPrintf("save_restore:array_restore: *** premature EOF.\n"); - end_of_file = 1; - break; - } - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: new buffer: '%s'\n", bp); - } - if (*bp == ELEMENT_END) break; - } else if ((*bp == ESCAPE) && ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { - /* escaped character */ - bp++; - } - if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ - } - string[j] = '\0'; - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: element[%ld] value = '%s'\n", num_read, string); - if (bp) errlogPrintf("dbrestore:SR_array_restore: look for element-end: buffer contains '%s'\n", bp); - } - /* + if (bp && !end_mark_found && !end_of_file) { + /* *bp == ELEMENT_BEGIN */ + if (save_restoreDebug >= 11) { + errlogPrintf("dbrestore:SR_array_restore: Found element-begin; buffer contains '%s'\n", bp); + } + for (bp++, j = 0; (j < MAX_STRING_SIZE - 1) && (*bp != ELEMENT_END); bp++) { + if (save_restoreDebug >= 11) + errlogPrintf("dbrestore:SR_array_restore: *bp=%c (%d)\n", *bp, (int)*bp); + if (*bp == '\0') { + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + errlogPrintf("save_restore:array_restore: *** premature EOF.\n"); + end_of_file = 1; + break; + } + if (save_restoreDebug >= 11) { + errlogPrintf("dbrestore:SR_array_restore: new buffer: '%s'\n", bp); + } + if (*bp == ELEMENT_END) break; + } else if ((*bp == ESCAPE) && + ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { + /* escaped character */ + bp++; + } + if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ + } + string[j] = '\0'; + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:SR_array_restore: element[%ld] value = '%s'\n", num_read, string); + if (bp) + errlogPrintf("dbrestore:SR_array_restore: look for element-end: buffer contains '%s'\n", bp); + } + /* * We've accumulated all the characters, or all we can handle in string[]. * If there are more characters than we can handle, just pretend we read them. */ - /* *bp == ELEMENT_END ,*/ - for (found = 0; (found == 0) && !end_of_file; ) { - while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; - switch (*bp) { - case ELEMENT_END: - found = 1; - bp++; - break; - case ESCAPE: - ++bp; - if (*bp == ELEMENT_END || *bp == ESCAPE) { - ++bp; - } - break; - default: - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - end_of_file = 1; - found = 1; - } - } - } - if ((num_read= 10) && p_data && !gobble) { - errlogPrintf("\nsave_restore: %ld array values:\n", num_read); - for (j=0; j= 10) { - errlogPrintf("dbrestore:SR_array_restore: looking for ARRAY_END\n"); - } - in_element = 0; - while (!end_mark_found && !end_of_file) { - if (save_restoreDebug >= 11) { - errlogPrintf("dbrestore:SR_array_restore: ...buffer contains '%s'\n", bp); - } - switch (*bp) { - case ESCAPE: - if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ - break; - case ARRAY_END: - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: found ARRAY_END. in_element=%d\n", in_element); - } - if (!in_element) end_mark_found = 1; - break; - case '\0': - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - errlogPrintf("dbrestore:SR_array_restore: *** EOF during array-end search\n"); - end_of_file = 1; - } - break; - default: - /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ - if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; - break; - } - if (bp) ++bp; - } - } else { - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_array_restore: ARRAY_BEGIN wasn't found.\n"); - } - } - if (!status && end_of_file) { - status = end_of_file; - errlogPrintf("dbrestore:SR_array_restore: status = end_of_file.\n"); - } - - if (gobble) { - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore: Gobbled unused array data.\n"); - } - } else if (pass == 0) { - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore: No array write in pass 0.\n"); - } - } else { - if (!status && p_data) { - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore: Writing array to database\n"); - } - status = SR_put_array_values(PVname, p_data, num_read); - } else { - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:SR_array_restore: No array write to database attempted because of error condition\n"); - errlogPrintf("dbrestore:SR_array_restore: status=%ld, p_data=%p\n", status, p_data); - } - } - } - if ((p_data == NULL) && !gobble) status = -1; - return(status); + /* *bp == ELEMENT_END ,*/ + for (found = 0; (found == 0) && !end_of_file;) { + while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; + switch (*bp) { + case ELEMENT_END: + found = 1; + bp++; + break; + case ESCAPE: + ++bp; + if (*bp == ELEMENT_END || *bp == ESCAPE) { ++bp; } + break; + default: + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + end_of_file = 1; + found = 1; + } + } + } + if ((num_read < max_elements) && !gobble) { + /* Append value to local array. */ + if (p_data) { + epicsStrnRawFromEscaped(string, MAX_STRING_SIZE, string, MAX_STRING_SIZE); + switch (field_type) { + case DBF_STRING: + strNcpy(&(p_char[(num_read++) * MAX_STRING_SIZE]), string, MAX_STRING_SIZE); + break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: p_ushort[num_read++] = (unsigned short)atol(string); break; + case DBF_UCHAR: p_uchar[num_read++] = (unsigned char)atol(string); break; + case DBF_CHAR: p_char[num_read++] = (char)atol(string); break; + case DBF_SHORT: p_short[num_read++] = (short)atol(string); break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)atol(string); break; + case DBF_ULONG: + /*p_ulong[num_read++] = (epicsUInt32) atol(string);*/ + p_ulong[num_read++] = (epicsUInt32)strtoul(string, NULL, 0); + break; +#ifdef DBR_INT64 + case DBF_INT64: epicsParseInt64(string, &p_int64[num_read++], 10, NULL); break; + case DBF_UINT64: epicsParseUInt64(string, &p_uint64[num_read++], 10, NULL); break; +#endif + case DBF_FLOAT: p_float[num_read++] = mySafeDoubleToFloat(atof(string)); break; + case DBF_DOUBLE: p_double[num_read++] = atof(string); break; + case DBF_NOACCESS: + default: break; + } + } + } + } + } /* for (num_read=0; bp && !end_mark_found; ) */ + + if ((save_restoreDebug >= 10) && p_data && !gobble) { + errlogPrintf("\nsave_restore: %ld array values:\n", num_read); + for (j = 0; j < num_read; j++) { + switch (field_type) { + case DBF_STRING: errlogPrintf(" '%s'\n", &(p_char[j * MAX_STRING_SIZE])); break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: errlogPrintf(" %u\n", p_ushort[j]); break; + case DBF_SHORT: errlogPrintf(" %d\n", p_short[j]); break; + case DBF_UCHAR: errlogPrintf(" '%c' (%u)\n", p_uchar[j], p_uchar[j]); break; + case DBF_CHAR: errlogPrintf(" '%c' (%d)\n", p_char[j], p_char[j]); break; + case DBF_ULONG: errlogPrintf(" %u\n", p_ulong[j]); break; + case DBF_LONG: errlogPrintf(" %d\n", p_long[j]); break; +#ifdef DBR_INT64 + case DBF_UINT64: errlogPrintf(" %llu\n", p_uint64[j]); break; + case DBF_INT64: errlogPrintf(" %lld\n", p_int64[j]); break; +#endif + case DBF_FLOAT: errlogPrintf(" %f\n", p_float[j]); break; + case DBF_DOUBLE: errlogPrintf(" %g\n", p_double[j]); break; + case DBF_NOACCESS: + default: break; + } + } + errlogPrintf("save_restore: end of %ld array values.\n\n", num_read); + epicsThreadSleep(0.5); + } + + } /* if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) */ + + /* leave the file pointer ready for next PV (next fgets() should yield next PV) */ + if (begin_mark_found) { + /* find ARRAY_END (but ARRAY_END inside an element is just another character) */ + if (save_restoreDebug >= 10) { errlogPrintf("dbrestore:SR_array_restore: looking for ARRAY_END\n"); } + in_element = 0; + while (!end_mark_found && !end_of_file) { + if (save_restoreDebug >= 11) { errlogPrintf("dbrestore:SR_array_restore: ...buffer contains '%s'\n", bp); } + switch (*bp) { + case ESCAPE: + if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ + break; + case ARRAY_END: + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:SR_array_restore: found ARRAY_END. in_element=%d\n", in_element); + } + if (!in_element) end_mark_found = 1; + break; + case '\0': + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + errlogPrintf("dbrestore:SR_array_restore: *** EOF during array-end search\n"); + end_of_file = 1; + } + break; + default: + /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ + if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; + break; + } + if (bp) ++bp; + } + } else { + if (save_restoreDebug >= 10) { errlogPrintf("dbrestore:SR_array_restore: ARRAY_BEGIN wasn't found.\n"); } + } + if (!status && end_of_file) { + status = end_of_file; + errlogPrintf("dbrestore:SR_array_restore: status = end_of_file.\n"); + } + + if (gobble) { + if (save_restoreDebug >= 1) { errlogPrintf("dbrestore:SR_array_restore: Gobbled unused array data.\n"); } + } else if (pass == 0) { + if (save_restoreDebug >= 1) { errlogPrintf("dbrestore:SR_array_restore: No array write in pass 0.\n"); } + } else { + if (!status && p_data) { + if (save_restoreDebug >= 1) { errlogPrintf("dbrestore:SR_array_restore: Writing array to database\n"); } + status = SR_put_array_values(PVname, p_data, num_read); + } else { + if (save_restoreDebug >= 1) { + errlogPrintf( + "dbrestore:SR_array_restore: No array write to database attempted because of error condition\n"); + errlogPrintf("dbrestore:SR_array_restore: status=%ld, p_data=%p\n", status, p_data); + } + } + } + if ((p_data == NULL) && !gobble) status = -1; + return (status); } /* @@ -835,121 +750,116 @@ long SR_array_restore(int pass, FILE *inp_fd, char *PVname, char *value_string, */ int reboot_restore(char *filename, initHookState init_state) { - char PVname[PV_NAME_LEN+1]; /* Must be greater than max field width ("%80s") in the sscanf format below */ - char bu_filename[PATH_SIZE+1], fname[PATH_SIZE+1] = ""; - char buffer[BUF_SIZE], *bp; - char ebuffer[EBUF_SIZE]; /* make room for macro expansion */ - char value_string[BUF_SIZE]; - char datetime[32]; - char c; - FILE *inp_fd; - int found_field, pass; - DBENTRY dbentry; - DBENTRY *pdbentry = &dbentry; - long status; - int n, write_backup, num_errors, is_scalar; - long *pStatusVal = 0; - char *statusStr = 0; - char realName[64]; /* name without trailing '$' */ - int is_long_string; - struct restoreFileListItem *pLI; - /* macrostring */ - MAC_HANDLE *handle = NULL; - char **pairs = NULL; - char *macrostring = NULL; - - if (save_restoreDebug) - errlogPrintf("reboot_restore: entry for file '%s'\n", filename); - /* initialize database access routines */ - if (!pdbbase) { - errlogPrintf("reboot_restore: No Database Loaded\n"); - return(OK); - } - dbInitEntry(pdbbase,pdbentry); - - maybeInitRestoreFileLists(); - /* what are we supposed to do here? */ - if (init_state >= initHookAfterInitDatabase) { - pass = 1; - pLI = (struct restoreFileListItem *) ellFirst(&pass1List); - } else { - pass = 0; - pLI = (struct restoreFileListItem *) ellFirst(&pass0List); - } - while (pLI) { - if (pLI->filename && (strcmp(filename, pLI->filename) == 0)) { - pStatusVal = &(pLI->restoreStatus); - statusStr = pLI->restoreStatusStr; - macrostring = pLI->macrostring; - break; - } - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - - if ((pStatusVal == 0) || (statusStr == 0)) { - errlogPrintf("reboot_restore: Can't find filename '%s' in list.\n", - filename); - } else if (save_restoreDebug) { - errlogPrintf("reboot_restore: Found filename '%s' in restoreFileList.\n", - filename); - } - - /* open file */ - if (isAbsolute(filename)) { - strNcpy(fname, filename, PATH_SIZE); - } else { - makeNfsPath(fname, saveRestoreFilePath, filename); - } - if (save_restoreDebug) - errlogPrintf("*** restoring from '%s' at initHookState %d (%s record/device init) ***\n", - fname, (int)init_state, pass ? "after" : "before"); - if ((inp_fd = fopen_and_check(fname, &status)) == NULL) { - errlogPrintf("save_restore: Can't open save file."); - if (pStatusVal) *pStatusVal = SR_STATUS_FAIL; - if (statusStr) strNcpy(statusStr, "Can't open save file.", STATUS_STR_LEN-1); - dbFinishEntry(pdbentry); - return(ERROR); - } - if (status) { - if (pStatusVal) *pStatusVal = SR_STATUS_WARN; - if (statusStr) strNcpy(statusStr, "Bad .sav(B) files; used seq. backup", STATUS_STR_LEN-1); - } - - /* Prepare to use macro substitution */ - if (macrostring && macrostring[0]) { - macCreateHandle(&handle, NULL); - if (handle) { - macParseDefns(handle, macrostring, &pairs); - if (pairs) macInstallMacros(handle, pairs); - if (save_restoreDebug >= 5) { - errlogPrintf("save_restore:reboot_restore: Current macro definitions:\n"); - macReportMacros(handle); - errlogPrintf("save_restore:reboot_restore: --------------------------\n"); - } - } - } - - (void)fgets(buffer, BUF_SIZE, inp_fd); /* discard header line */ - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:reboot_restore: header line '%s'\n", buffer); - } - status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - - /* restore from data file */ - num_errors = 0; - while ((bp=fgets(buffer, BUF_SIZE, inp_fd))) { - if (handle && pairs) { - ebuffer[0] = '\0'; - macExpandString(handle, buffer, ebuffer, EBUF_SIZE); - bp = ebuffer; - if (save_restoreDebug >= 5) { - printf("dbrestore:reboot_restore: buffer='%s'\n", buffer); - printf(" ebuffer='%s'\n", ebuffer); - } - } - - /* + char PVname[PV_NAME_LEN + 1]; /* Must be greater than max field width ("%80s") in the sscanf format below */ + char bu_filename[PATH_SIZE + 1], fname[PATH_SIZE + 1] = ""; + char buffer[BUF_SIZE], *bp; + char ebuffer[EBUF_SIZE]; /* make room for macro expansion */ + char value_string[BUF_SIZE]; + char datetime[32]; + char c; + FILE *inp_fd; + int found_field, pass; + DBENTRY dbentry; + DBENTRY *pdbentry = &dbentry; + long status; + int n, write_backup, num_errors, is_scalar; + long *pStatusVal = 0; + char *statusStr = 0; + char realName[64]; /* name without trailing '$' */ + int is_long_string; + struct restoreFileListItem *pLI; + /* macrostring */ + MAC_HANDLE *handle = NULL; + char **pairs = NULL; + char *macrostring = NULL; + + if (save_restoreDebug) errlogPrintf("reboot_restore: entry for file '%s'\n", filename); + /* initialize database access routines */ + if (!pdbbase) { + errlogPrintf("reboot_restore: No Database Loaded\n"); + return (OK); + } + dbInitEntry(pdbbase, pdbentry); + + maybeInitRestoreFileLists(); + /* what are we supposed to do here? */ + if (init_state >= initHookAfterInitDatabase) { + pass = 1; + pLI = (struct restoreFileListItem *)ellFirst(&pass1List); + } else { + pass = 0; + pLI = (struct restoreFileListItem *)ellFirst(&pass0List); + } + while (pLI) { + if (pLI->filename && (strcmp(filename, pLI->filename) == 0)) { + pStatusVal = &(pLI->restoreStatus); + statusStr = pLI->restoreStatusStr; + macrostring = pLI->macrostring; + break; + } + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + + if ((pStatusVal == 0) || (statusStr == 0)) { + errlogPrintf("reboot_restore: Can't find filename '%s' in list.\n", filename); + } else if (save_restoreDebug) { + errlogPrintf("reboot_restore: Found filename '%s' in restoreFileList.\n", filename); + } + + /* open file */ + if (isAbsolute(filename)) { + strNcpy(fname, filename, PATH_SIZE); + } else { + makeNfsPath(fname, saveRestoreFilePath, filename); + } + if (save_restoreDebug) + errlogPrintf("*** restoring from '%s' at initHookState %d (%s record/device init) ***\n", fname, + (int)init_state, pass ? "after" : "before"); + if ((inp_fd = fopen_and_check(fname, &status)) == NULL) { + errlogPrintf("save_restore: Can't open save file."); + if (pStatusVal) *pStatusVal = SR_STATUS_FAIL; + if (statusStr) strNcpy(statusStr, "Can't open save file.", STATUS_STR_LEN - 1); + dbFinishEntry(pdbentry); + return (ERROR); + } + if (status) { + if (pStatusVal) *pStatusVal = SR_STATUS_WARN; + if (statusStr) strNcpy(statusStr, "Bad .sav(B) files; used seq. backup", STATUS_STR_LEN - 1); + } + + /* Prepare to use macro substitution */ + if (macrostring && macrostring[0]) { + macCreateHandle(&handle, NULL); + if (handle) { + macParseDefns(handle, macrostring, &pairs); + if (pairs) macInstallMacros(handle, pairs); + if (save_restoreDebug >= 5) { + errlogPrintf("save_restore:reboot_restore: Current macro definitions:\n"); + macReportMacros(handle); + errlogPrintf("save_restore:reboot_restore: --------------------------\n"); + } + } + } + + (void)fgets(buffer, BUF_SIZE, inp_fd); /* discard header line */ + if (save_restoreDebug >= 1) { errlogPrintf("dbrestore:reboot_restore: header line '%s'\n", buffer); } + status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + + /* restore from data file */ + num_errors = 0; + while ((bp = fgets(buffer, BUF_SIZE, inp_fd))) { + if (handle && pairs) { + ebuffer[0] = '\0'; + macExpandString(handle, buffer, ebuffer, EBUF_SIZE); + bp = ebuffer; + if (save_restoreDebug >= 5) { + printf("dbrestore:reboot_restore: buffer='%s'\n", buffer); + printf(" ebuffer='%s'\n", ebuffer); + } + } + + /* * get PV_name, one space character, value * (value may be a string with leading whitespace; it may be * entirely whitespace; the number of spaces may be crucial; @@ -961,255 +871,249 @@ int reboot_restore(char *filename, initHookState init_state) * xxx:interp.E 100 * xxx:interp.C @array@ { "1" "0.99" } */ - PVname[0] = '\0'; - value_string[0] = '\0'; - n = sscanf(bp,"%80s%c%[^\n\r]", PVname, &c, value_string); - if (n<3) *value_string = 0; - if ((n<1) || (PVname[0] == '\0')) { - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:reboot_restore: line (fragment) '%s' ignored.\n", bp); - } - continue; - } - if (strncmp(PVname, "", 5) == 0) { - break; - } - if (PVname[0] == '#') { - /* user must have edited the file manually; accept this line as a comment */ - is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); - if (!is_scalar) { - /* Parse and gobble up the whole array. */ - status = SR_array_restore(pass, inp_fd, PVname, value_string, 1); - } - continue; - } - if (strlen(PVname) >= 80) { - /* must be a munged input line */ - errlogPrintf("dbrestore:reboot_restore: '%s' is too long to be a PV name.\n", PVname); - continue; - } - if (isalpha((int)PVname[0]) || isdigit((int)PVname[0])) { - if (strchr(PVname,'.') == 0) strcat(PVname,".VAL"); /* if no field name, add default */ - is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); - if (save_restoreDebug > 9) errlogPrintf("\n"); - if (is_scalar) { - long num_elements, field_size, field_type; - /* check the field itself, because an empty string is saved as no value at all , which would look like a scalar. */ - SR_get_array_info(PVname, &num_elements, &field_size, &field_type); - if (num_elements > 1) { - if (save_restoreDebug >= 5) { - printf("reboot_restore: PV '%s' is scalar in .sav file, but has %ld elements. Treating as array.\n", - PVname, num_elements); - } - is_scalar = 0; - } - } - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:reboot_restore: Attempting to put %s '%s' to '%s'\n", - is_scalar?"scalar":"array", value_string, PVname); - } - - /* dbStatic doesn't know about long-string fields (PV name with appended '$'). */ - is_long_string = 0; - strNcpy(realName, PVname, 63); - if (realName[strlen(realName)-1] == '$') { - realName[strlen(realName)-1] = '\0'; - is_long_string = 1; - /* See if we got the whole line */ - if (bp[strlen(bp)-1] != '\n') { - /* No, we didn't. One more read will certainly accumulate a value string of length BUF_SIZE */ - if (save_restoreDebug > 9) printf("reboot_restore: did not reach end of line for long-string PV\n"); - bp = fgets(buffer, BUF_SIZE, inp_fd); - if (handle && pairs) { - ebuffer[0] = '\0'; - macExpandString(handle, buffer, ebuffer, EBUF_SIZE); - bp = ebuffer; - if (save_restoreDebug >= 1) { - printf("dbrestore:reboot_restore: buffer='%s'\n", buffer); - printf(" ebuffer='%s'\n", ebuffer); - } - } - n = BUF_SIZE-strlen(value_string)-1; - strncat(value_string, bp, n); - /* we don't want that '\n' in the string */ - if (value_string[strlen(value_string)-1] == '\n') value_string[strlen(value_string)-1] = '\0'; - } - /* We aren't prepared to handle more than BUF_SIZE characters. Discard additional characters until end of line */ - while (bp[strlen(bp)-1] != '\n') bp = fgets(buffer, BUF_SIZE, inp_fd); - } - - found_field = 1; - if ((status = dbFindRecord(pdbentry, realName)) != 0) { - errlogPrintf("dbFindRecord for '%s' failed\n", PVname); - num_errors++; found_field = 0; - } else if (dbFoundField(pdbentry) == 0) { - errlogPrintf("dbrestore:reboot_restore: dbFindRecord did not find field '%s'\n", PVname); - num_errors++; found_field = 0; - } - if (found_field) { - if (is_scalar || is_long_string) { - status = scalar_restore(pass, pdbentry, PVname, value_string, is_long_string); - } else { - status = SR_array_restore(pass, inp_fd, PVname, value_string, 0); - } - if (status) { - errlogPrintf("dbrestore:reboot_restore: restore for PV '%s' failed\n", PVname); - num_errors++; - } - } else { - if (!is_scalar) { - /* Parse and gobble up the whole array. We don't have PV to restore to, + PVname[0] = '\0'; + value_string[0] = '\0'; + n = sscanf(bp, "%80s%c%[^\n\r]", PVname, &c, value_string); + if (n < 3) *value_string = 0; + if ((n < 1) || (PVname[0] == '\0')) { + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:reboot_restore: line (fragment) '%s' ignored.\n", bp); + } + continue; + } + if (strncmp(PVname, "", 5) == 0) { break; } + if (PVname[0] == '#') { + /* user must have edited the file manually; accept this line as a comment */ + is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); + if (!is_scalar) { + /* Parse and gobble up the whole array. */ + status = SR_array_restore(pass, inp_fd, PVname, value_string, 1); + } + continue; + } + if (strlen(PVname) >= 80) { + /* must be a munged input line */ + errlogPrintf("dbrestore:reboot_restore: '%s' is too long to be a PV name.\n", PVname); + continue; + } + if (isalpha((int)PVname[0]) || isdigit((int)PVname[0])) { + if (strchr(PVname, '.') == 0) strcat(PVname, ".VAL"); /* if no field name, add default */ + is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); + if (save_restoreDebug > 9) errlogPrintf("\n"); + if (is_scalar) { + long num_elements, field_size, field_type; + /* check the field itself, because an empty string is saved as no value at all , which would look like a scalar. */ + SR_get_array_info(PVname, &num_elements, &field_size, &field_type); + if (num_elements > 1) { + if (save_restoreDebug >= 5) { + printf( + "reboot_restore: PV '%s' is scalar in .sav file, but has %ld elements. Treating as " + "array.\n", + PVname, num_elements); + } + is_scalar = 0; + } + } + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:reboot_restore: Attempting to put %s '%s' to '%s'\n", + is_scalar ? "scalar" : "array", value_string, PVname); + } + + /* dbStatic doesn't know about long-string fields (PV name with appended '$'). */ + is_long_string = 0; + strNcpy(realName, PVname, 63); + if (realName[strlen(realName) - 1] == '$') { + realName[strlen(realName) - 1] = '\0'; + is_long_string = 1; + /* See if we got the whole line */ + if (bp[strlen(bp) - 1] != '\n') { + /* No, we didn't. One more read will certainly accumulate a value string of length BUF_SIZE */ + if (save_restoreDebug > 9) printf("reboot_restore: did not reach end of line for long-string PV\n"); + bp = fgets(buffer, BUF_SIZE, inp_fd); + if (handle && pairs) { + ebuffer[0] = '\0'; + macExpandString(handle, buffer, ebuffer, EBUF_SIZE); + bp = ebuffer; + if (save_restoreDebug >= 1) { + printf("dbrestore:reboot_restore: buffer='%s'\n", buffer); + printf(" ebuffer='%s'\n", ebuffer); + } + } + n = BUF_SIZE - strlen(value_string) - 1; + strncat(value_string, bp, n); + /* we don't want that '\n' in the string */ + if (value_string[strlen(value_string) - 1] == '\n') value_string[strlen(value_string) - 1] = '\0'; + } + /* We aren't prepared to handle more than BUF_SIZE characters. Discard additional characters until end of line */ + while (bp[strlen(bp) - 1] != '\n') bp = fgets(buffer, BUF_SIZE, inp_fd); + } + + found_field = 1; + if ((status = dbFindRecord(pdbentry, realName)) != 0) { + errlogPrintf("dbFindRecord for '%s' failed\n", PVname); + num_errors++; + found_field = 0; + } else if (dbFoundField(pdbentry) == 0) { + errlogPrintf("dbrestore:reboot_restore: dbFindRecord did not find field '%s'\n", PVname); + num_errors++; + found_field = 0; + } + if (found_field) { + if (is_scalar || is_long_string) { + status = scalar_restore(pass, pdbentry, PVname, value_string, is_long_string); + } else { + status = SR_array_restore(pass, inp_fd, PVname, value_string, 0); + } + if (status) { + errlogPrintf("dbrestore:reboot_restore: restore for PV '%s' failed\n", PVname); + num_errors++; + } + } else { + if (!is_scalar) { + /* Parse and gobble up the whole array. We don't have PV to restore to, * but we don't want to trip over the unused array data. */ - status = SR_array_restore(pass, inp_fd, PVname, value_string, 1); - } - } /* if (found_field) {} else {... */ - } else if (PVname[0] == '!') { - /* + status = SR_array_restore(pass, inp_fd, PVname, value_string, 1); + } + } /* if (found_field) {} else {... */ + } else if (PVname[0] == '!') { + /* * string is an error message -- something like: * '! 7 channel(s) not connected - or not all gets were successful' */ - n = (int)atol(&bp[1]); - errlogPrintf("%d %s had no saved value.\n", n, n==1?"PV":"PVs"); - if (pStatusVal) *pStatusVal = SR_STATUS_WARN; - if (statusStr) strNcpy(statusStr, ".sav file contained an error message", STATUS_STR_LEN-1); - if (!save_restoreIncompleteSetsOk) { - errlogPrintf("aborting restore\n"); - fclose(inp_fd); - if (handle) macDeleteHandle(handle); - if (pairs) free(pairs); - dbFinishEntry(pdbentry); - if (pStatusVal) *pStatusVal = SR_STATUS_FAIL; - if (statusStr) strNcpy(statusStr, "restore aborted", STATUS_STR_LEN-1); - return(ERROR); - } - } else if (PVname[0] == '<') { - /* end of file */ - break; - } - } - fclose(inp_fd); - if (handle) macDeleteHandle(handle); - if (pairs) free(pairs); - dbFinishEntry(pdbentry); - - /* If this is the second pass for a restore file, don't write backup file again.*/ - write_backup = 1; - if (init_state >= initHookAfterInitDatabase) { - pLI = (struct restoreFileListItem *) ellFirst(&pass0List); - while (pLI) { - if (strcmp(filename, pLI->filename) == 0) { - write_backup = 0; - break; - } - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - } - - /* For now, don't write boot-time backups for files specified with full path. */ - if (isAbsolute(filename)) write_backup = 0; - - if (write_backup) { - /* write backup file*/ - if (save_restoreDatedBackupFiles && (fGetDateStr(datetime) == 0)) { - strNcpy(bu_filename, fname, sizeof(bu_filename) - 1 - strlen(datetime)); - strcat(bu_filename, "_"); - strcat(bu_filename, datetime); - } else { - strNcpy(bu_filename, fname, sizeof(bu_filename) - 3); - strcat(bu_filename, ".bu"); - } - if (save_restoreDebug >= 1) { - errlogPrintf("dbrestore:reboot_restore: writing boot-backup file '%s'.\n", bu_filename); - } - status = (long)myFileCopy(fname,bu_filename); - if (status) { - errlogPrintf("save_restore: Can't write backup file.\n"); - if (pStatusVal) *pStatusVal = SR_STATUS_WARN; - if (statusStr) strNcpy(statusStr, "Can't write backup file", STATUS_STR_LEN-1); - return(OK); - } - } - - /* Record status */ - if (pStatusVal && statusStr) { - if (*pStatusVal != 0) { - /* Status and message have already been recorded */ - ; - } else if (num_errors != 0) { - epicsSnprintf(statusStr, STATUS_STR_LEN-1, "%d %s", num_errors, num_errors==1?"PV error":"PV errors"); - *pStatusVal = SR_STATUS_WARN; - } else { - strNcpy(statusStr, "No errors", STATUS_STR_LEN-1); - *pStatusVal = SR_STATUS_OK; - } - } - if (p_data) { - free(p_data); - p_data = NULL; - p_data_size = 0; - } - if (save_restoreDebug) - errlogPrintf("reboot_restore: done with file '%s'\n\n", filename); - return(OK); -} + n = (int)atol(&bp[1]); + errlogPrintf("%d %s had no saved value.\n", n, n == 1 ? "PV" : "PVs"); + if (pStatusVal) *pStatusVal = SR_STATUS_WARN; + if (statusStr) strNcpy(statusStr, ".sav file contained an error message", STATUS_STR_LEN - 1); + if (!save_restoreIncompleteSetsOk) { + errlogPrintf("aborting restore\n"); + fclose(inp_fd); + if (handle) macDeleteHandle(handle); + if (pairs) free(pairs); + dbFinishEntry(pdbentry); + if (pStatusVal) *pStatusVal = SR_STATUS_FAIL; + if (statusStr) strNcpy(statusStr, "restore aborted", STATUS_STR_LEN - 1); + return (ERROR); + } + } else if (PVname[0] == '<') { + /* end of file */ + break; + } + } + fclose(inp_fd); + if (handle) macDeleteHandle(handle); + if (pairs) free(pairs); + dbFinishEntry(pdbentry); + + /* If this is the second pass for a restore file, don't write backup file again.*/ + write_backup = 1; + if (init_state >= initHookAfterInitDatabase) { + pLI = (struct restoreFileListItem *)ellFirst(&pass0List); + while (pLI) { + if (strcmp(filename, pLI->filename) == 0) { + write_backup = 0; + break; + } + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + } + /* For now, don't write boot-time backups for files specified with full path. */ + if (isAbsolute(filename)) write_backup = 0; + + if (write_backup) { + /* write backup file*/ + if (save_restoreDatedBackupFiles && (fGetDateStr(datetime) == 0)) { + strNcpy(bu_filename, fname, sizeof(bu_filename) - 1 - strlen(datetime)); + strcat(bu_filename, "_"); + strcat(bu_filename, datetime); + } else { + strNcpy(bu_filename, fname, sizeof(bu_filename) - 3); + strcat(bu_filename, ".bu"); + } + if (save_restoreDebug >= 1) { + errlogPrintf("dbrestore:reboot_restore: writing boot-backup file '%s'.\n", bu_filename); + } + status = (long)myFileCopy(fname, bu_filename); + if (status) { + errlogPrintf("save_restore: Can't write backup file.\n"); + if (pStatusVal) *pStatusVal = SR_STATUS_WARN; + if (statusStr) strNcpy(statusStr, "Can't write backup file", STATUS_STR_LEN - 1); + return (OK); + } + } -static int set_restoreFile(int pass, char *filename, char *macrostring) -{ - struct restoreFileListItem *pLI; - - maybeInitRestoreFileLists(); - - pLI = calloc(1, sizeof(struct restoreFileListItem)); - if (pLI == NULL) { - errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); - return(ERROR); - } - - pLI->filename = (char *)calloc(strlen(filename) + 4,sizeof(char)); - if (pLI->filename == NULL) { - errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); - free(pLI); - return(ERROR); - } - strcpy(pLI->filename, filename); - - pLI->restoreStatusStr = (char *)calloc(STATUS_STR_LEN, 1); - if (pLI->restoreStatusStr == NULL) { - errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); - free(pLI->filename); - free(pLI); - return(ERROR); - } - strNcpy(pLI->restoreStatusStr, "Unknown, probably failed", STATUS_STR_LEN-1); - - if (macrostring && macrostring[0]) { - pLI->macrostring = (char *)calloc(strlen(macrostring)+1,sizeof(char)); - strcpy(pLI->macrostring, macrostring); - } - - - pLI->restoreStatus = SR_STATUS_INIT; - - if (pass==1) { - ellAdd(&pass1List, &(pLI->node)); - } else { - ellAdd(&pass0List, &(pLI->node)); - } - return(OK); + /* Record status */ + if (pStatusVal && statusStr) { + if (*pStatusVal != 0) { + /* Status and message have already been recorded */ + ; + } else if (num_errors != 0) { + epicsSnprintf(statusStr, STATUS_STR_LEN - 1, "%d %s", num_errors, + num_errors == 1 ? "PV error" : "PV errors"); + *pStatusVal = SR_STATUS_WARN; + } else { + strNcpy(statusStr, "No errors", STATUS_STR_LEN - 1); + *pStatusVal = SR_STATUS_OK; + } + } + if (p_data) { + free(p_data); + p_data = NULL; + p_data_size = 0; + } + if (save_restoreDebug) errlogPrintf("reboot_restore: done with file '%s'\n\n", filename); + return (OK); } -int set_pass0_restoreFile(char *filename, char *macrostring) +static int set_restoreFile(int pass, char *filename, char *macrostring) { - return(set_restoreFile(0, filename, macrostring)); -} + struct restoreFileListItem *pLI; -int set_pass1_restoreFile(char *filename, char *macrostring) -{ - return(set_restoreFile(1, filename, macrostring)); + maybeInitRestoreFileLists(); + + pLI = calloc(1, sizeof(struct restoreFileListItem)); + if (pLI == NULL) { + errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); + return (ERROR); + } + + pLI->filename = (char *)calloc(strlen(filename) + 4, sizeof(char)); + if (pLI->filename == NULL) { + errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); + free(pLI); + return (ERROR); + } + strcpy(pLI->filename, filename); + + pLI->restoreStatusStr = (char *)calloc(STATUS_STR_LEN, 1); + if (pLI->restoreStatusStr == NULL) { + errlogPrintf("set_pass%d_restoreFile: calloc failed\n", pass); + free(pLI->filename); + free(pLI); + return (ERROR); + } + strNcpy(pLI->restoreStatusStr, "Unknown, probably failed", STATUS_STR_LEN - 1); + + if (macrostring && macrostring[0]) { + pLI->macrostring = (char *)calloc(strlen(macrostring) + 1, sizeof(char)); + strcpy(pLI->macrostring, macrostring); + } + + pLI->restoreStatus = SR_STATUS_INIT; + + if (pass == 1) { + ellAdd(&pass1List, &(pLI->node)); + } else { + ellAdd(&pass0List, &(pLI->node)); + } + return (OK); } +int set_pass0_restoreFile(char *filename, char *macrostring) { return (set_restoreFile(0, filename, macrostring)); } + +int set_pass1_restoreFile(char *filename, char *macrostring) { return (set_restoreFile(1, filename, macrostring)); } + /* file is ok if it ends in either of the two following ways: * ? * ?? @@ -1217,294 +1121,287 @@ int set_pass1_restoreFile(char *filename, char *macrostring) */ FILE *checkFile(const char *file) { - FILE *inp_fd = NULL; - char tmpstr[PATH_SIZE+50], *versionstr; - double version; - char datetime[32]; - int status; - - if (save_restoreDebug >= 2) printf("checkFile: entry\n"); - - if ((inp_fd = fopen(file, "r")) == NULL) { - errlogPrintf("save_restore: Can't open file '%s'.\n", file); - return(0); - } - - /* Get the version number of the code that wrote the file */ - fgets(tmpstr, 29, inp_fd); - versionstr = strchr(tmpstr,(int)'R'); - if (!versionstr) versionstr = strchr(tmpstr,(int)'V'); - if (!versionstr) { - /* file has no version number */ - status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - return(inp_fd); /* Assume file is ok */ - } - if (isdigit((int)versionstr[1])) - version = atof(versionstr+1); - else - version = 0; - if (save_restoreDebug >= 2) printf("checkFile: version=%f\n", version); - - /* check started in v1.8 */ - if (version < 1.8) { - status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - return(inp_fd); /* Assume file is ok. */ - } - /* check out "successfully written" marker */ - status = fseek(inp_fd, -6, SEEK_END); - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - fgets(tmpstr, 6, inp_fd); - if (save_restoreDebug >= 5) printf("checkFile: files ends with '%s'\n", tmpstr); - if (strncmp(tmpstr, "", 5) == 0) { - status = fseek(inp_fd, 0, SEEK_SET); /* file is ok. go to beginning */ - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - return(inp_fd); - } - - status = fseek(inp_fd, -7, SEEK_END); - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - fgets(tmpstr, 7, inp_fd); - if (save_restoreDebug >= 5) printf("checkFile: files ends with '%s'\n", tmpstr); - if (strncmp(tmpstr, "", 5) == 0) { - status = fseek(inp_fd, 0, SEEK_SET); /* file is ok. go to beginning */ - if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); - return(inp_fd); - } - - /* file is bad */ - fclose(inp_fd); - errlogPrintf("save_restore: File '%s' is not trusted.\n", file); - strNcpy(tmpstr, file, PATH_SIZE+49); - strncat(tmpstr, "_RBAD_", PATH_SIZE+49-strlen(tmpstr)); - if (save_restoreDatedBackupFiles) { - fGetDateStr(datetime); - strncat(tmpstr, datetime, PATH_SIZE+49-strlen(tmpstr)); - } - (void)myFileCopy(file, tmpstr); - return(0); -} + FILE *inp_fd = NULL; + char tmpstr[PATH_SIZE + 50], *versionstr; + double version; + char datetime[32]; + int status; + if (save_restoreDebug >= 2) printf("checkFile: entry\n"); + + if ((inp_fd = fopen(file, "r")) == NULL) { + errlogPrintf("save_restore: Can't open file '%s'.\n", file); + return (0); + } + + /* Get the version number of the code that wrote the file */ + fgets(tmpstr, 29, inp_fd); + versionstr = strchr(tmpstr, (int)'R'); + if (!versionstr) versionstr = strchr(tmpstr, (int)'V'); + if (!versionstr) { + /* file has no version number */ + status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + return (inp_fd); /* Assume file is ok */ + } + if (isdigit((int)versionstr[1])) version = atof(versionstr + 1); + else version = 0; + if (save_restoreDebug >= 2) printf("checkFile: version=%f\n", version); + + /* check started in v1.8 */ + if (version < 1.8) { + status = fseek(inp_fd, 0, SEEK_SET); /* go to beginning */ + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + return (inp_fd); /* Assume file is ok. */ + } + /* check out "successfully written" marker */ + status = fseek(inp_fd, -6, SEEK_END); + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + fgets(tmpstr, 6, inp_fd); + if (save_restoreDebug >= 5) printf("checkFile: files ends with '%s'\n", tmpstr); + if (strncmp(tmpstr, "", 5) == 0) { + status = fseek(inp_fd, 0, SEEK_SET); /* file is ok. go to beginning */ + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + return (inp_fd); + } + + status = fseek(inp_fd, -7, SEEK_END); + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + fgets(tmpstr, 7, inp_fd); + if (save_restoreDebug >= 5) printf("checkFile: files ends with '%s'\n", tmpstr); + if (strncmp(tmpstr, "", 5) == 0) { + status = fseek(inp_fd, 0, SEEK_SET); /* file is ok. go to beginning */ + if (status) myPrintErrno("checkFile: fseek error ", __FILE__, __LINE__); + return (inp_fd); + } + + /* file is bad */ + fclose(inp_fd); + errlogPrintf("save_restore: File '%s' is not trusted.\n", file); + strNcpy(tmpstr, file, PATH_SIZE + 49); + strncat(tmpstr, "_RBAD_", PATH_SIZE + 49 - strlen(tmpstr)); + if (save_restoreDatedBackupFiles) { + fGetDateStr(datetime); + strncat(tmpstr, datetime, PATH_SIZE + 49 - strlen(tmpstr)); + } + (void)myFileCopy(file, tmpstr); + return (0); +} FILE *fopen_and_check(const char *fname, long *status) { - FILE *inp_fd = NULL; - char file[PATH_SIZE+1]; - int i, backup_sequence_num; - struct stat fileStat; - char *p; - time_t currTime; - double dTime, min_dTime; - - *status = 0; /* presume success */ - strNcpy(file, fname, PATH_SIZE); - inp_fd = checkFile(file); - if (save_restoreDebug >=1) printf("fopen_and_check: checkFile returned %p\n", inp_fd); - if (inp_fd) return(inp_fd); - - /* Still here? Try the backup file. */ - strncat(file, "B", PATH_SIZE - strlen(file)); - errlogPrintf("save_restore: Trying backup file '%s'\n", file); - inp_fd = checkFile(file); - if (inp_fd) return(inp_fd); - - /*** Still haven't found a good file? Try the sequenced backups ***/ - /* Find the most recent one. */ - *status = 1; - strNcpy(file, fname, PATH_SIZE); - backup_sequence_num = -1; - p = &file[strlen(file)]; - currTime = time(NULL); - min_dTime = 1.e9; - for (i=0; i= 1) printf("fopen_and_check: checkFile returned %p\n", inp_fd); + if (inp_fd) return (inp_fd); + + /* Still here? Try the backup file. */ + strncat(file, "B", PATH_SIZE - strlen(file)); + errlogPrintf("save_restore: Trying backup file '%s'\n", file); + inp_fd = checkFile(file); + if (inp_fd) return (inp_fd); + + /*** Still haven't found a good file? Try the sequenced backups ***/ + /* Find the most recent one. */ + *status = 1; + strNcpy(file, fname, PATH_SIZE); + backup_sequence_num = -1; + p = &file[strlen(file)]; + currTime = time(NULL); + min_dTime = 1.e9; + for (i = 0; i < save_restoreNumSeqFiles; i++) { + epicsSnprintf(p, PATH_SIZE - strlen(file), "%1d", i); + + if (stat(file, &fileStat) == 0) { + /* * Clocks might be unsynchronized, so it's possible * the most recent file has a time in the future. * For now, just choose the file whose date/time is * closest to the current date/time. */ - dTime = fabs(difftime(currTime, fileStat.st_mtime)); - if (save_restoreDebug >= 5) { - errlogPrintf("'%s' modified at %s\n", file, - ctime(&fileStat.st_mtime)); - errlogPrintf("'%s' is %f seconds old\n", file, dTime); - } - if (dTime < min_dTime) { - min_dTime = dTime; - backup_sequence_num = i; - } - } - } - - if (backup_sequence_num == -1) { - /* Clock are way messed up. Just try backup 0. */ - backup_sequence_num = 0; - epicsSnprintf(p, PATH_SIZE-strlen(file), "%1d", backup_sequence_num); - errlogPrintf("save_restore: Can't figure out which seq file is most recent,\n"); - errlogPrintf("save_restore: so I'm just going to start with '%s'.\n", file); - } - - /* Try the sequenced backup files. */ - for (i=0; i= save_restoreNumSeqFiles) - backup_sequence_num = 0; - } - - errlogPrintf("save_restore: Can't find a file to restore from..."); - errlogPrintf("save_restore: ...last tried '%s'. I give up.\n", file); - printf("save_restore: **********************************\n\n"); - return(0); -} + dTime = fabs(difftime(currTime, fileStat.st_mtime)); + if (save_restoreDebug >= 5) { + errlogPrintf("'%s' modified at %s\n", file, ctime(&fileStat.st_mtime)); + errlogPrintf("'%s' is %f seconds old\n", file, dTime); + } + if (dTime < min_dTime) { + min_dTime = dTime; + backup_sequence_num = i; + } + } + } + + if (backup_sequence_num == -1) { + /* Clock are way messed up. Just try backup 0. */ + backup_sequence_num = 0; + epicsSnprintf(p, PATH_SIZE - strlen(file), "%1d", backup_sequence_num); + errlogPrintf("save_restore: Can't figure out which seq file is most recent,\n"); + errlogPrintf("save_restore: so I'm just going to start with '%s'.\n", file); + } + /* Try the sequenced backup files. */ + for (i = 0; i < save_restoreNumSeqFiles; i++) { + epicsSnprintf(p, PATH_SIZE - strlen(file), "%1d", backup_sequence_num); + errlogPrintf("save_restore: Trying backup file '%s'\n", file); + inp_fd = checkFile(file); + if (inp_fd) return (inp_fd); + + /* Next. Order might be, e.g., "1,2,0", if 1 is most recent of 3 files */ + if (++backup_sequence_num >= save_restoreNumSeqFiles) backup_sequence_num = 0; + } + + errlogPrintf("save_restore: Can't find a file to restore from..."); + errlogPrintf("save_restore: ...last tried '%s'. I give up.\n", file); + printf("save_restore: **********************************\n\n"); + return (0); +} /* * These functions really belong to save_restore.c, but they use * database access, which is incompatible with cadef.h included in * save_restore.c. */ - + long SR_get_array_info(char *name, long *num_elements, long *field_size, long *field_type) { - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - long status; - - *num_elements = 0; - *field_size = 0; - *field_type = 0; - status = dbNameToAddr(name, paddr); - if (status) return(status); - *num_elements = paddr->no_elements; - *field_size = paddr->field_size; - *field_type = paddr->field_type; - return(0); + DBADDR dbaddr; + DBADDR *paddr = &dbaddr; + long status; + + *num_elements = 0; + *field_size = 0; + *field_type = 0; + status = dbNameToAddr(name, paddr); + if (status) return (status); + *num_elements = paddr->no_elements; + *field_size = paddr->field_size; + *field_type = paddr->field_type; + return (0); } - long SR_get_array(char *PVname, void *pArray, long *pnum_elements) { - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - long status; - dbfType request_field_type; - - status = dbNameToAddr(PVname, paddr); - if (status) return(status); - dbScanLock((dbCommon *)paddr->precord); - request_field_type = paddr->field_type; - /* + DBADDR dbaddr; + DBADDR *paddr = &dbaddr; + long status; + dbfType request_field_type; + + status = dbNameToAddr(PVname, paddr); + if (status) return (status); + dbScanLock((dbCommon *)paddr->precord); + request_field_type = paddr->field_type; + /* * Not clear what we should do if someone has an array of enums * or menu items. For now, just do something that will work * in the simplest case. */ - if ((request_field_type == DBF_ENUM) || (request_field_type == DBF_MENU)) { - errlogPrintf("save_restore:SR_get_array: field_type %s array read as DBF_USHORT\n", - pamapdbfType[request_field_type].strvalue); - request_field_type = DBF_USHORT; - } - status = dbGet(paddr, request_field_type, pArray, NULL, pnum_elements, NULL); - if (save_restoreDebug >= 10) { - errlogPrintf("dbrestore:SR_get_array: '%s' currently has %ld elements\n", PVname, *pnum_elements); - } - dbScanUnlock((dbCommon *)paddr->precord); - return(status); + if ((request_field_type == DBF_ENUM) || (request_field_type == DBF_MENU)) { + errlogPrintf("save_restore:SR_get_array: field_type %s array read as DBF_USHORT\n", + pamapdbfType[request_field_type].strvalue); + request_field_type = DBF_USHORT; + } + status = dbGet(paddr, request_field_type, pArray, NULL, pnum_elements, NULL); + if (save_restoreDebug >= 10) { + errlogPrintf("dbrestore:SR_get_array: '%s' currently has %ld elements\n", PVname, *pnum_elements); + } + dbScanUnlock((dbCommon *)paddr->precord); + return (status); } long SR_write_array_data(FILE *out_fd, char *name, void *pArray, long num_elements) { - DBADDR dbaddr; - DBADDR *paddr = &dbaddr; - long status; - dbfType field_type; - long i, j, n; - char *p_char = NULL, *pc; - short *p_short = NULL; - epicsInt32 *p_long = NULL; - unsigned char *p_uchar = NULL; - unsigned short *p_ushort = NULL; - epicsUInt32 *p_ulong = NULL; - float *p_float = NULL; - double *p_double = NULL; - - status = dbNameToAddr(name, paddr); - if (status) return(0); - field_type = paddr->field_type; - - n = fprintf(out_fd, "%-s %1c ", ARRAY_MARKER, ARRAY_BEGIN); - for (i=0; ifield_type; + + n = fprintf(out_fd, "%-s %1c ", ARRAY_MARKER, ARRAY_BEGIN); + for (i = 0; i < num_elements; i++) { + switch (field_type) { + case DBF_STRING: + p_char = (char *)pArray; + pc = &p_char[i * MAX_STRING_SIZE]; + n += fprintf(out_fd, "%1c", ELEMENT_BEGIN); + for (j = 0; j < MAX_STRING_SIZE - 1 && *pc; j++, pc++) { + if ((*pc == ELEMENT_BEGIN) || (*pc == ELEMENT_END) || (*pc == ESCAPE)) { + n += fprintf(out_fd, "%1c", ESCAPE); + j++; + } + if (*pc == '\n') { + n += fprintf(out_fd, "%1cn", ESCAPE); + } else if (*pc == '\r') { + n += fprintf(out_fd, "%1cr", ESCAPE); + } else { + n += fprintf(out_fd, "%1c", *pc); + } + } + n += fprintf(out_fd, "%1c ", ELEMENT_END); + break; + case DBF_CHAR: + p_char = (char *)pArray; + n += fprintf(out_fd, "%1c%d%1c ", ELEMENT_BEGIN, p_char[i], ELEMENT_END); + break; + case DBF_UCHAR: + p_uchar = (unsigned char *)pArray; + n += fprintf(out_fd, "%1c%u%1c ", ELEMENT_BEGIN, p_uchar[i], ELEMENT_END); + break; + case DBF_SHORT: + p_short = (short *)pArray; + n += fprintf(out_fd, "%1c%d%1c ", ELEMENT_BEGIN, p_short[i], ELEMENT_END); + break; + case DBF_ENUM: + case DBF_USHORT: + case DBF_MENU: + p_ushort = (unsigned short *)pArray; + n += fprintf(out_fd, "%1c%u%1c ", ELEMENT_BEGIN, p_ushort[i], ELEMENT_END); + break; + case DBF_LONG: + p_long = (epicsInt32 *)pArray; + n += fprintf(out_fd, "%1c%d%1c ", ELEMENT_BEGIN, p_long[i], ELEMENT_END); + break; + case DBF_ULONG: + p_ulong = (epicsUInt32 *)pArray; + n += fprintf(out_fd, "%1c%u%1c ", ELEMENT_BEGIN, p_ulong[i], ELEMENT_END); + break; + case DBF_FLOAT: + p_float = (float *)pArray; + n += fprintf(out_fd, "%1c", ELEMENT_BEGIN); + n += fprintf(out_fd, FLOAT_FMT, p_float[i]); + n += fprintf(out_fd, "%1c ", ELEMENT_END); + break; + case DBF_DOUBLE: + p_double = (double *)pArray; + n += fprintf(out_fd, "%1c", ELEMENT_BEGIN); + n += fprintf(out_fd, DOUBLE_FMT, p_double[i]); + n += fprintf(out_fd, "%1c ", ELEMENT_END); + break; + default: errlogPrintf("save_restore: field_type %d not handled.\n", (int)field_type); break; + } + } + n += fprintf(out_fd, "%1c\n", ARRAY_END); + return (n); } /* Surely this is enough... */ @@ -1517,354 +1414,336 @@ long SR_write_array_data(FILE *out_fd, char *name, void *pArray, long num_elemen */ void makeAutosaveFileFromDbInfo(char *fileBaseName, char *info_name) { - DBENTRY dbentry; - DBENTRY *pdbentry = &dbentry; - const char *info_value, *pbegin, *pend; - char *fname, *falloc=NULL, field[MAX_FIELD_SIZE], realfield[MAX_FIELD_SIZE]; - FILE *out_fd; - int searchRecord, flen; - - if (!pdbbase) { - errlogPrintf("autosave:makeAutosaveFileFromDbInfo: No Database Loaded\n"); - return; - } - if (strstr(fileBaseName, ".req")) { - fname=fileBaseName; - } else { - fname=falloc=malloc(strlen(fileBaseName)+sizeof(".req")+1); - if (!fname) { - errlogPrintf("save_restore:makeAutosaveFileFromDbInfo - allocation failed\n"); - return; - } - epicsSnprintf(fname, strlen(fileBaseName)+sizeof(".req"), "%s.req", fileBaseName); - } - if ((out_fd = fopen(fname,"w")) == NULL) { - errlogPrintf("save_restore:makeAutosaveFileFromDbInfo - unable to open file '%s'\n", fname); - free(falloc); - return; - } - free(falloc); - - dbInitEntry(pdbbase,pdbentry); - /* loop over all record types */ - dbFirstRecordType(pdbentry); - do { - /* loop over all records of current type*/ - dbFirstRecord(pdbentry); -#if GE_EPICSBASE(3,14,11) - searchRecord = dbIsAlias(pdbentry) ? 0 : 1; + DBENTRY dbentry; + DBENTRY *pdbentry = &dbentry; + const char *info_value, *pbegin, *pend; + char *fname, *falloc = NULL, field[MAX_FIELD_SIZE], realfield[MAX_FIELD_SIZE]; + FILE *out_fd; + int searchRecord, flen; + + if (!pdbbase) { + errlogPrintf("autosave:makeAutosaveFileFromDbInfo: No Database Loaded\n"); + return; + } + if (strstr(fileBaseName, ".req")) { + fname = fileBaseName; + } else { + fname = falloc = malloc(strlen(fileBaseName) + sizeof(".req") + 1); + if (!fname) { + errlogPrintf("save_restore:makeAutosaveFileFromDbInfo - allocation failed\n"); + return; + } + epicsSnprintf(fname, strlen(fileBaseName) + sizeof(".req"), "%s.req", fileBaseName); + } + if ((out_fd = fopen(fname, "w")) == NULL) { + errlogPrintf("save_restore:makeAutosaveFileFromDbInfo - unable to open file '%s'\n", fname); + free(falloc); + return; + } + free(falloc); + + dbInitEntry(pdbbase, pdbentry); + /* loop over all record types */ + dbFirstRecordType(pdbentry); + do { + /* loop over all records of current type*/ + dbFirstRecord(pdbentry); +#if GE_EPICSBASE(3, 14, 11) + searchRecord = dbIsAlias(pdbentry) ? 0 : 1; #else - searchRecord = 1; + searchRecord = 1; #endif - do { - if (searchRecord) { - info_value = dbGetInfo(pdbentry, info_name); - if (info_value) { - /* printf("record %s.autosave = '%s'\n", dbGetRecordName(pdbentry), info_value); */ - - for (pbegin=info_value; *pbegin && isspace((int)*pbegin); pbegin++) {} /* skip leading whitespace */ - - while (pbegin && *pbegin && !isspace((int)*pbegin)) { - /* find end of field */ - for (pend=pbegin; *pend && !isspace((int)*pend); pend++) {} - /* pend points to whitespace or \0 */ - - flen = pend-pbegin; - if (flen >= sizeof(field)-1) flen = sizeof(field)-1; - memcpy(field, pbegin, flen); - field[flen]='\0'; - strNcpy(realfield, field, MAX_FIELD_SIZE-1); - if (realfield[strlen(realfield)-1] == '$') realfield[strlen(realfield)-1] = '\0'; - - if (dbFindField(pdbentry, realfield) == 0) { - fprintf(out_fd, "%s.%s\n", dbGetRecordName(pdbentry), field); - } else { - printf("makeAutosaveFileFromDbInfo: %s.%s not found\n", dbGetRecordName(pdbentry), field); - } - - for (pbegin=pend; *pbegin && isspace((int)*pbegin); pbegin++) {} /* skip leading whitespace */ - } - } - } - } while (dbNextRecord(pdbentry) == 0); - } while (dbNextRecordType(pdbentry) == 0); - dbFinishEntry(pdbentry); - fclose(out_fd); - return; + do { + if (searchRecord) { + info_value = dbGetInfo(pdbentry, info_name); + if (info_value) { + /* printf("record %s.autosave = '%s'\n", dbGetRecordName(pdbentry), info_value); */ + + for (pbegin = info_value; *pbegin && isspace((int)*pbegin); pbegin++) { + } /* skip leading whitespace */ + + while (pbegin && *pbegin && !isspace((int)*pbegin)) { + /* find end of field */ + for (pend = pbegin; *pend && !isspace((int)*pend); pend++) {} + /* pend points to whitespace or \0 */ + + flen = pend - pbegin; + if (flen >= sizeof(field) - 1) flen = sizeof(field) - 1; + memcpy(field, pbegin, flen); + field[flen] = '\0'; + strNcpy(realfield, field, MAX_FIELD_SIZE - 1); + if (realfield[strlen(realfield) - 1] == '$') realfield[strlen(realfield) - 1] = '\0'; + + if (dbFindField(pdbentry, realfield) == 0) { + fprintf(out_fd, "%s.%s\n", dbGetRecordName(pdbentry), field); + } else { + printf("makeAutosaveFileFromDbInfo: %s.%s not found\n", dbGetRecordName(pdbentry), field); + } + + for (pbegin = pend; *pbegin && isspace((int)*pbegin); pbegin++) {} /* skip leading whitespace */ + } + } + } + } while (dbNextRecord(pdbentry) == 0); + } while (dbNextRecordType(pdbentry) == 0); + dbFinishEntry(pdbentry); + fclose(out_fd); + return; } /**************************************************************************/ /* support for building autosave-request files automatically from dbLoadRecords, dbLoadTemplate */ -int eraseFile(const char *filename) { - FILE *fd; - char *fname; - - fname = macEnvExpand(filename); - if (fname == NULL) { - printf("save_restore:eraseFile: macEnvExpand('%s') returned NULL\n", filename); - return(ERROR); - } - if ((fd = fopen(fname, "w")) != NULL) { - fclose(fd); - } - free(fname); - return(0); +int eraseFile(const char *filename) +{ + FILE *fd; + char *fname; + + fname = macEnvExpand(filename); + if (fname == NULL) { + printf("save_restore:eraseFile: macEnvExpand('%s') returned NULL\n", filename); + return (ERROR); + } + if ((fd = fopen(fname, "w")) != NULL) { fclose(fd); } + free(fname); + return (0); } -int appendToFile(const char *filename, const char *line) { - FILE *fd; - char *fname; - int status=0; - - fname = macEnvExpand(filename); - if (fname == NULL) { - printf("save_restore:appendToFile: macEnvExpand('%s') returned NULL\n", filename); - return(ERROR); - } - if ((fd = fopen(fname, "a")) != NULL) { - fprintf(fd, "%s\n", line); - fclose(fd); - } else { - errlogPrintf("save_restore:appendToFile: Can't open file '%s'\n", fname); - status = -1; - } - free(fname); - return(status); +int appendToFile(const char *filename, const char *line) +{ + FILE *fd; + char *fname; + int status = 0; + + fname = macEnvExpand(filename); + if (fname == NULL) { + printf("save_restore:appendToFile: macEnvExpand('%s') returned NULL\n", filename); + return (ERROR); + } + if ((fd = fopen(fname, "a")) != NULL) { + fprintf(fd, "%s\n", line); + fclose(fd); + } else { + errlogPrintf("save_restore:appendToFile: Can't open file '%s'\n", fname); + status = -1; + } + free(fname); + return (status); } #ifdef DBLOADRECORDSHOOKREGISTER -static DB_LOAD_RECORDS_HOOK_ROUTINE previousHook=NULL; +static DB_LOAD_RECORDS_HOOK_ROUTINE previousHook = NULL; #endif static ELLLIST buildInfoList = ELLLIST_INIT; struct buildInfoItem { - ELLNODE node; - char *filename; - char *suffix; - int enabled; + ELLNODE node; + char *filename; + char *suffix; + int enabled; }; -static int autosaveBuildInitialized=0; +static int autosaveBuildInitialized = 0; static char requestFileCmd[MAXSTRING]; static char requestFileBase[MAXSTRING]; static char requestFileName[MAXSTRING]; static char macroString[MAXSTRING], emacroString[MAXSTRING]; -static void myDbLoadRecordsHook(const char* fname, const char* macro) { - struct buildInfoItem *pitem; - char *p, *dbFileName; - int n; - MAC_HANDLE *handle = NULL; - char **pairs = NULL; +static void myDbLoadRecordsHook(const char *fname, const char *macro) +{ + struct buildInfoItem *pitem; + char *p, *dbFileName; + int n; + MAC_HANDLE *handle = NULL; + char **pairs = NULL; - dbFileName = macEnvExpand(fname); + dbFileName = macEnvExpand(fname); - if (save_restoreDebug >= 5) { - printf("myDbLoadRecordsHook: dbFileName='%s'; subs='%s'\n", dbFileName, macroString); - } + if (save_restoreDebug >= 5) { + printf("myDbLoadRecordsHook: dbFileName='%s'; subs='%s'\n", dbFileName, macroString); + } #ifdef DBLOADRECORDSHOOKREGISTER - if (previousHook) previousHook(dbFileName, macro); + if (previousHook) previousHook(dbFileName, macro); #endif - /* Should probably call basename(), but is it available on Windows? */ - p = strrchr(dbFileName, (int)'/'); - if (p==NULL) p = strrchr(dbFileName, (int)'\\'); - if (p) { - strNcpy(requestFileBase, p+1, MAXSTRING-strlen(requestFileBase)-1); - } else { - strNcpy(requestFileBase, dbFileName, MAXSTRING-strlen(requestFileBase)-1); - } - p = strstr(requestFileBase, ".db"); - if (p == NULL) p = strstr(requestFileBase, ".vdb"); - if (p == NULL) p = strstr(requestFileBase, ".template"); - if (p == NULL) { - printf("myDbLoadRecordsHook: Can't make request-file name from '%s'\n", dbFileName); - free(dbFileName); - return; - } - *p = '\0'; - - pitem = (struct buildInfoItem *)ellFirst(&buildInfoList); - for (; pitem; pitem = (struct buildInfoItem *)ellNext(&(pitem->node)) ) { - if (pitem->enabled) { - n = epicsSnprintf(requestFileName, MAXSTRING, "%s%s", requestFileBase, pitem->suffix); - if ((n < MAXSTRING) && (openReqFile(requestFileName, NULL))) { - if (save_restoreDebug >= 5) { - printf("myDbLoadRecordsHook: found '%s'\n", requestFileName); - } - /* Expand any internal macros in macroString e.g., "N=1,M=m$(N)" */ - macCreateHandle(&handle, NULL); - macSuppressWarning(handle, 1); - strNcpy(macroString, macro, MAXSTRING-1); - if (handle) { - macParseDefns(handle, macroString, &pairs); - if (pairs) { - macInstallMacros(handle, pairs); - emacroString[0] = '\0'; - macExpandString(handle, macroString, emacroString, MAXSTRING-1); - strNcpy(macroString, emacroString, MAXSTRING-1); - } - } - n = epicsSnprintf(requestFileCmd, MAXSTRING, "file %s %s", requestFileName, macroString); - if (n < MAXSTRING) { - appendToFile(pitem->filename, requestFileCmd); - } else { - printf("myDbLoadRecordsHook: Can't include %s; requestFileCmd is too long (n = %i, MAXSTRING = %i)\n", - requestFileName, n, MAXSTRING); - } - } - } - } - free(dbFileName); + /* Should probably call basename(), but is it available on Windows? */ + p = strrchr(dbFileName, (int)'/'); + if (p == NULL) p = strrchr(dbFileName, (int)'\\'); + if (p) { + strNcpy(requestFileBase, p + 1, MAXSTRING - strlen(requestFileBase) - 1); + } else { + strNcpy(requestFileBase, dbFileName, MAXSTRING - strlen(requestFileBase) - 1); + } + p = strstr(requestFileBase, ".db"); + if (p == NULL) p = strstr(requestFileBase, ".vdb"); + if (p == NULL) p = strstr(requestFileBase, ".template"); + if (p == NULL) { + printf("myDbLoadRecordsHook: Can't make request-file name from '%s'\n", dbFileName); + free(dbFileName); + return; + } + *p = '\0'; + + pitem = (struct buildInfoItem *)ellFirst(&buildInfoList); + for (; pitem; pitem = (struct buildInfoItem *)ellNext(&(pitem->node))) { + if (pitem->enabled) { + n = epicsSnprintf(requestFileName, MAXSTRING, "%s%s", requestFileBase, pitem->suffix); + if ((n < MAXSTRING) && (openReqFile(requestFileName, NULL))) { + if (save_restoreDebug >= 5) { printf("myDbLoadRecordsHook: found '%s'\n", requestFileName); } + /* Expand any internal macros in macroString e.g., "N=1,M=m$(N)" */ + macCreateHandle(&handle, NULL); + macSuppressWarning(handle, 1); + strNcpy(macroString, macro, MAXSTRING - 1); + if (handle) { + macParseDefns(handle, macroString, &pairs); + if (pairs) { + macInstallMacros(handle, pairs); + emacroString[0] = '\0'; + macExpandString(handle, macroString, emacroString, MAXSTRING - 1); + strNcpy(macroString, emacroString, MAXSTRING - 1); + } + } + n = epicsSnprintf(requestFileCmd, MAXSTRING, "file %s %s", requestFileName, macroString); + if (n < MAXSTRING) { + appendToFile(pitem->filename, requestFileCmd); + } else { + printf( + "myDbLoadRecordsHook: Can't include %s; requestFileCmd is too long (n = %i, MAXSTRING = %i)\n", + requestFileName, n, MAXSTRING); + } + } + } + } + free(dbFileName); } -int autosaveBuild(char *filename, char *reqFileSuffix, int on) { - - struct buildInfoItem *pitem; - int fileFound = 0, itemFound = 0; +int autosaveBuild(char *filename, char *reqFileSuffix, int on) +{ + struct buildInfoItem *pitem; + int fileFound = 0, itemFound = 0; - if (!autosaveBuildInitialized) { - autosaveBuildInitialized = 1; + if (!autosaveBuildInitialized) { + autosaveBuildInitialized = 1; #ifdef DBLOADRECORDSHOOKREGISTER previousHook = dbLoadRecordsHook; dbLoadRecordsHook = myDbLoadRecordsHook; #else - printf("pretending to register a dbLoadRecords hook\n"); + printf("pretending to register a dbLoadRecords hook\n"); #endif - } - if (!filename || filename[0]==0) { - printf("autosaveBuild: bad filename\n"); - return(-1); - } - - pitem = (struct buildInfoItem *)ellFirst(&buildInfoList); - for (; pitem; pitem = (struct buildInfoItem *)ellNext(&(pitem->node)) ) { - if ((pitem->filename && strcmp(pitem->filename, filename)==0)) { - fileFound = 1; - if ((pitem->suffix && (reqFileSuffix==NULL || reqFileSuffix[0]=='*' || - strcmp(pitem->suffix, reqFileSuffix)==0))) { - /* item exists */ - if (save_restoreDebug) { - printf("autosaveBuild: %s filename '%s' and suffix '%s'.\n", - on ? "enabled" : "disabled", filename, pitem->suffix); - } - pitem->enabled = on; - itemFound = 1; - } - } - if (itemFound) return(0); - } - - if (!reqFileSuffix || reqFileSuffix[0]==0) { - printf("autosaveBuild: bad suffix\n"); - return(-1); - } - - /* If this is the first mention of filename, erase the file */ - if (!fileFound) eraseFile(filename); - pitem = (struct buildInfoItem *)calloc(1, sizeof(struct buildInfoItem)); - ellAdd(&buildInfoList, &(pitem->node)); - pitem->filename = epicsStrDup(filename); - pitem->suffix = epicsStrDup(reqFileSuffix); - pitem->enabled = on; - if (save_restoreDebug) { - printf("autosaveBuild: initialized and %s filename '%s' and suffix '%s'.\n", - pitem->enabled ? "enabled" : "disabled", pitem->filename, pitem->suffix); - } - return(0); + } + if (!filename || filename[0] == 0) { + printf("autosaveBuild: bad filename\n"); + return (-1); + } + + pitem = (struct buildInfoItem *)ellFirst(&buildInfoList); + for (; pitem; pitem = (struct buildInfoItem *)ellNext(&(pitem->node))) { + if ((pitem->filename && strcmp(pitem->filename, filename) == 0)) { + fileFound = 1; + if ((pitem->suffix && + (reqFileSuffix == NULL || reqFileSuffix[0] == '*' || strcmp(pitem->suffix, reqFileSuffix) == 0))) { + /* item exists */ + if (save_restoreDebug) { + printf("autosaveBuild: %s filename '%s' and suffix '%s'.\n", on ? "enabled" : "disabled", filename, + pitem->suffix); + } + pitem->enabled = on; + itemFound = 1; + } + } + if (itemFound) return (0); + } + + if (!reqFileSuffix || reqFileSuffix[0] == 0) { + printf("autosaveBuild: bad suffix\n"); + return (-1); + } + + /* If this is the first mention of filename, erase the file */ + if (!fileFound) eraseFile(filename); + pitem = (struct buildInfoItem *)calloc(1, sizeof(struct buildInfoItem)); + ellAdd(&buildInfoList, &(pitem->node)); + pitem->filename = epicsStrDup(filename); + pitem->suffix = epicsStrDup(reqFileSuffix); + pitem->enabled = on; + if (save_restoreDebug) { + printf("autosaveBuild: initialized and %s filename '%s' and suffix '%s'.\n", + pitem->enabled ? "enabled" : "disabled", pitem->filename, pitem->suffix); + } + return (0); } /**************************************************************************/ -void makeAutosaveFiles() { +void makeAutosaveFiles() +{ makeAutosaveFileFromDbInfo("info_settings.req", "autosaveFields"); makeAutosaveFileFromDbInfo("info_positions.req", "autosaveFields_pass0"); } /* set_pass0_restoreFile() */ -STATIC const iocshArg set_passN_Arg1 = {"file",iocshArgString}; -STATIC const iocshArg set_passN_Arg2 = {"macrostring",iocshArgString}; -STATIC const iocshArg * const set_passN_Args[2] = {&set_passN_Arg1, &set_passN_Arg2}; -STATIC const iocshFuncDef set_pass0_FuncDef = {"set_pass0_restoreFile",2,set_passN_Args}; -STATIC void set_pass0_CallFunc(const iocshArgBuf *args) -{ - set_pass0_restoreFile(args[0].sval, args[1].sval); -} +STATIC const iocshArg set_passN_Arg1 = {"file", iocshArgString}; +STATIC const iocshArg set_passN_Arg2 = {"macrostring", iocshArgString}; +STATIC const iocshArg *const set_passN_Args[2] = {&set_passN_Arg1, &set_passN_Arg2}; +STATIC const iocshFuncDef set_pass0_FuncDef = {"set_pass0_restoreFile", 2, set_passN_Args}; +STATIC void set_pass0_CallFunc(const iocshArgBuf *args) { set_pass0_restoreFile(args[0].sval, args[1].sval); } /* set_pass1_restoreFile() */ -STATIC const iocshFuncDef set_pass1_FuncDef = {"set_pass1_restoreFile",2,set_passN_Args}; -STATIC void set_pass1_CallFunc(const iocshArgBuf *args) -{ - set_pass1_restoreFile(args[0].sval, args[1].sval); -} +STATIC const iocshFuncDef set_pass1_FuncDef = {"set_pass1_restoreFile", 2, set_passN_Args}; +STATIC void set_pass1_CallFunc(const iocshArgBuf *args) { set_pass1_restoreFile(args[0].sval, args[1].sval); } /* void dbrestoreShow(void) */ -STATIC const iocshFuncDef dbrestoreShow_FuncDef = {"dbrestoreShow",0,NULL}; -STATIC void dbrestoreShow_CallFunc(const iocshArgBuf *args) -{ - dbrestoreShow(); -} +STATIC const iocshFuncDef dbrestoreShow_FuncDef = {"dbrestoreShow", 0, NULL}; +STATIC void dbrestoreShow_CallFunc(const iocshArgBuf *args) { dbrestoreShow(); } /* void makeAutosaveFileFromDbInfo(char *filename, char *info_name) */ -STATIC const iocshArg makeAutosaveFileFromDbInfo_Arg0 = {"filename",iocshArgString}; -STATIC const iocshArg makeAutosaveFileFromDbInfo_Arg1 = {"info_name",iocshArgString}; -STATIC const iocshArg * const makeAutosaveFileFromDbInfo_Args[2] = {&makeAutosaveFileFromDbInfo_Arg0, &makeAutosaveFileFromDbInfo_Arg1}; -STATIC const iocshFuncDef makeAutosaveFileFromDbInfo_FuncDef = {"makeAutosaveFileFromDbInfo",2,makeAutosaveFileFromDbInfo_Args}; +STATIC const iocshArg makeAutosaveFileFromDbInfo_Arg0 = {"filename", iocshArgString}; +STATIC const iocshArg makeAutosaveFileFromDbInfo_Arg1 = {"info_name", iocshArgString}; +STATIC const iocshArg *const makeAutosaveFileFromDbInfo_Args[2] = {&makeAutosaveFileFromDbInfo_Arg0, + &makeAutosaveFileFromDbInfo_Arg1}; +STATIC const iocshFuncDef makeAutosaveFileFromDbInfo_FuncDef = {"makeAutosaveFileFromDbInfo", 2, + makeAutosaveFileFromDbInfo_Args}; STATIC void makeAutosaveFileFromDbInfo_CallFunc(const iocshArgBuf *args) { makeAutosaveFileFromDbInfo(args[0].sval, args[1].sval); } /* void makeAutosaveFiles(void) */ -STATIC const iocshFuncDef makeAutosaveFiles_FuncDef = {"makeAutosaveFiles",0,NULL}; -STATIC void makeAutosaveFiles_CallFunc(const iocshArgBuf *args) -{ - makeAutosaveFiles(); -} +STATIC const iocshFuncDef makeAutosaveFiles_FuncDef = {"makeAutosaveFiles", 0, NULL}; +STATIC void makeAutosaveFiles_CallFunc(const iocshArgBuf *args) { makeAutosaveFiles(); } /* int eraseFile(char *filename) */ -STATIC const iocshArg eraseFile_Arg0 = {"filename",iocshArgString}; -STATIC const iocshArg * const eraseFile_Args[1] = {&eraseFile_Arg0}; -STATIC const iocshFuncDef eraseFile_FuncDef = {"eraseFile",1,eraseFile_Args}; -STATIC void eraseFile_CallFunc(const iocshArgBuf *args) -{ - eraseFile(args[0].sval); -} +STATIC const iocshArg eraseFile_Arg0 = {"filename", iocshArgString}; +STATIC const iocshArg *const eraseFile_Args[1] = {&eraseFile_Arg0}; +STATIC const iocshFuncDef eraseFile_FuncDef = {"eraseFile", 1, eraseFile_Args}; +STATIC void eraseFile_CallFunc(const iocshArgBuf *args) { eraseFile(args[0].sval); } /* int appendToFile(char *filename, char *line) */ -STATIC const iocshArg appendToFile_Arg0 = {"filename",iocshArgString}; -STATIC const iocshArg appendToFile_Arg1 = {"line",iocshArgString}; -STATIC const iocshArg * const appendToFile_Args[2] = {&appendToFile_Arg0, &appendToFile_Arg1}; -STATIC const iocshFuncDef appendToFile_FuncDef = {"appendToFile",2,appendToFile_Args}; -STATIC void appendToFile_CallFunc(const iocshArgBuf *args) -{ - appendToFile(args[0].sval, args[1].sval); -} +STATIC const iocshArg appendToFile_Arg0 = {"filename", iocshArgString}; +STATIC const iocshArg appendToFile_Arg1 = {"line", iocshArgString}; +STATIC const iocshArg *const appendToFile_Args[2] = {&appendToFile_Arg0, &appendToFile_Arg1}; +STATIC const iocshFuncDef appendToFile_FuncDef = {"appendToFile", 2, appendToFile_Args}; +STATIC void appendToFile_CallFunc(const iocshArgBuf *args) { appendToFile(args[0].sval, args[1].sval); } /* int autosaveBuild(char *filename, char *reqFileSuffix, int on) */ -STATIC const iocshArg autosaveBuild_Arg0 = {"filename",iocshArgString}; -STATIC const iocshArg autosaveBuild_Arg1 = {"reqFileSuffix",iocshArgString}; -STATIC const iocshArg autosaveBuild_Arg2 = {"on",iocshArgInt}; -STATIC const iocshArg * const autosaveBuild_Args[3] = {&autosaveBuild_Arg0, &autosaveBuild_Arg1, &autosaveBuild_Arg2}; -STATIC const iocshFuncDef autosaveBuild_FuncDef = {"autosaveBuild",3,autosaveBuild_Args}; -STATIC void autosaveBuild_CallFunc(const iocshArgBuf *args) -{ - autosaveBuild(args[0].sval, args[1].sval, args[2].ival); -} - +STATIC const iocshArg autosaveBuild_Arg0 = {"filename", iocshArgString}; +STATIC const iocshArg autosaveBuild_Arg1 = {"reqFileSuffix", iocshArgString}; +STATIC const iocshArg autosaveBuild_Arg2 = {"on", iocshArgInt}; +STATIC const iocshArg *const autosaveBuild_Args[3] = {&autosaveBuild_Arg0, &autosaveBuild_Arg1, &autosaveBuild_Arg2}; +STATIC const iocshFuncDef autosaveBuild_FuncDef = {"autosaveBuild", 3, autosaveBuild_Args}; +STATIC void autosaveBuild_CallFunc(const iocshArgBuf *args) { autosaveBuild(args[0].sval, args[1].sval, args[2].ival); } void dbrestoreRegister(void) { iocshRegister(&set_pass0_FuncDef, set_pass0_CallFunc); iocshRegister(&set_pass1_FuncDef, set_pass1_CallFunc); - iocshRegister(&dbrestoreShow_FuncDef, dbrestoreShow_CallFunc); - iocshRegister(&makeAutosaveFileFromDbInfo_FuncDef, makeAutosaveFileFromDbInfo_CallFunc); - iocshRegister(&makeAutosaveFiles_FuncDef, makeAutosaveFiles_CallFunc); - iocshRegister(&eraseFile_FuncDef, eraseFile_CallFunc); - iocshRegister(&appendToFile_FuncDef, appendToFile_CallFunc); - iocshRegister(&autosaveBuild_FuncDef, autosaveBuild_CallFunc); + iocshRegister(&dbrestoreShow_FuncDef, dbrestoreShow_CallFunc); + iocshRegister(&makeAutosaveFileFromDbInfo_FuncDef, makeAutosaveFileFromDbInfo_CallFunc); + iocshRegister(&makeAutosaveFiles_FuncDef, makeAutosaveFiles_CallFunc); + iocshRegister(&eraseFile_FuncDef, eraseFile_CallFunc); + iocshRegister(&appendToFile_FuncDef, appendToFile_CallFunc); + iocshRegister(&autosaveBuild_FuncDef, autosaveBuild_CallFunc); } epicsExportRegistrar(dbrestoreRegister); diff --git a/asApp/src/fGetDateStr.c b/asApp/src/fGetDateStr.c index 5d449f4..b334ef8 100644 --- a/asApp/src/fGetDateStr.c +++ b/asApp/src/fGetDateStr.c @@ -71,12 +71,11 @@ DEVELOPMENT CENTER AT ARGONNE NATIONAL LABORATORY (708-252-2000). #include /* get date,time as yymmdd-HHMMSS */ -int fGetDateStr( char datetime[]) -{ - epicsTimeStamp now; +int fGetDateStr(char datetime[]) +{ + epicsTimeStamp now; - epicsTimeGetCurrent(&now); - epicsTimeToStrftime(datetime, 28, "%y%m%d-%H%M%S", &now); - return(0); + epicsTimeGetCurrent(&now); + epicsTimeToStrftime(datetime, 28, "%y%m%d-%H%M%S", &now); + return (0); } - diff --git a/asApp/src/fGetDateStr.h b/asApp/src/fGetDateStr.h index c522341..8eb349e 100644 --- a/asApp/src/fGetDateStr.h +++ b/asApp/src/fGetDateStr.h @@ -1,2 +1 @@ -int fGetDateStr( char datetime[]); - +int fGetDateStr(char datetime[]); diff --git a/asApp/src/initHooks.c b/asApp/src/initHooks.c index 097bdfa..30b6449 100644 --- a/asApp/src/initHooks.c +++ b/asApp/src/initHooks.c @@ -1,4 +1,4 @@ -/* initHooks.c ioc initialization hooks */ +/* initHooks.c ioc initialization hooks */ /* * Author: Marty Kraimer * Date: 06-01-91 @@ -32,15 +32,13 @@ * .04 09-10-92 rcz bug - moved call to setMasterTimeToSelf later * */ - - -#include -#include -#include -#include "save_restore.h" -#include -#include +#include +#include +#include +#include "save_restore.h" +#include +#include /* * INITHOOKS @@ -53,61 +51,47 @@ * at certain defined points during IOC initialization */ static void asInitHooks(initHookState state) { - struct restoreFileListItem *pLI; + struct restoreFileListItem *pLI; - switch (state) { - case initHookAtBeginning : - break; - case initHookAfterCallbackInit : - break; - case initHookAfterCaLinkInit : - break; - case initHookAfterInitDrvSup : - break; - case initHookAfterInitRecSup : - break; - case initHookAfterInitDevSup : + switch (state) { + case initHookAtBeginning: break; + case initHookAfterCallbackInit: break; + case initHookAfterCaLinkInit: break; + case initHookAfterInitDrvSup: break; + case initHookAfterInitRecSup: break; + case initHookAfterInitDevSup: - /* restore fields needed in init_record() */ - maybeInitRestoreFileLists(); - pLI = (struct restoreFileListItem *) ellFirst(&pass0List); - while (pLI) { - reboot_restore(pLI->filename, state); - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - break; + /* restore fields needed in init_record() */ + maybeInitRestoreFileLists(); + pLI = (struct restoreFileListItem *)ellFirst(&pass0List); + while (pLI) { + reboot_restore(pLI->filename, state); + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + break; - case initHookAfterInitDatabase : - /* + case initHookAfterInitDatabase: + /* * restore fields that init_record() would have overwritten with * info from the dol (desired output location). - */ - maybeInitRestoreFileLists(); - pLI = (struct restoreFileListItem *) ellFirst(&pass1List); - while (pLI) { - reboot_restore(pLI->filename, state); - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - break; - case initHookAfterFinishDevSup : - break; - case initHookAfterScanInit : - break; - case initHookAfterInitialProcess : - break; - case initHookAfterInterruptAccept : - break; - case initHookAtEnd : - break; - default: - break; - } - return; + */ + maybeInitRestoreFileLists(); + pLI = (struct restoreFileListItem *)ellFirst(&pass1List); + while (pLI) { + reboot_restore(pLI->filename, state); + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + break; + case initHookAfterFinishDevSup: break; + case initHookAfterScanInit: break; + case initHookAfterInitialProcess: break; + case initHookAfterInterruptAccept: break; + case initHookAtEnd: break; + default: break; + } + return; } -void asInitHooksRegister(void) -{ - initHookRegister(asInitHooks); -} +void asInitHooksRegister(void) { initHookRegister(asInitHooks); } epicsExportRegistrar(asInitHooksRegister); diff --git a/asApp/src/os/Linux/osdNfs.c b/asApp/src/os/Linux/osdNfs.c index fb3957d..c72090a 100644 --- a/asApp/src/os/Linux/osdNfs.c +++ b/asApp/src/os/Linux/osdNfs.c @@ -12,8 +12,9 @@ /** * Global variables */ -int save_restoreNFSOK = 1; /* for Linux, NFS has been mounted before autosave starts */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 1; /* for Linux, NFS has been mounted before autosave starts */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; /** @@ -22,20 +23,20 @@ extern volatile int save_restoreDebug; int nfsMount(char *uidhost, char *path, char *mntpoint) { struct stat st; - int devl; - char *host; /* host string */ - int rval = -1; /* return value */ - char *dev = 0; /* buffer for the full source path */ + int devl; + char *host; /* host string */ + int rval = -1; /* return value */ + char *dev = 0; /* buffer for the full source path */ /* check inputs */ if (!uidhost || !path || !mntpoint) { - fprintf(stderr,"usage: nfsMount(\"[uid.gid@]host\",\"path\",\"mountpoint\")\n"); + fprintf(stderr, "usage: nfsMount(\"[uid.gid@]host\",\"path\",\"mountpoint\")\n"); return -1; } /* allocate buffer for the whole source */ - if ( !(dev = malloc((devl=strlen(uidhost) + 20 + strlen(path)+1))) ) { - fprintf(stderr,"nfsMount: out of memory\n"); + if (!(dev = malloc((devl = strlen(uidhost) + 20 + strlen(path) + 1)))) { + fprintf(stderr, "nfsMount: out of memory\n"); return -1; } @@ -44,14 +45,14 @@ int nfsMount(char *uidhost, char *path, char *mntpoint) if (ENOENT != errno) { perror("nfsMount trying to create mount point - stat failed"); goto cleanup; - } else if (mkdir(mntpoint,0777)) { + } else if (mkdir(mntpoint, 0777)) { perror("nfsMount trying to create mount point"); goto cleanup; } } /* get the host name or IP address string */ - if ( !(host=strchr(uidhost,UIDSEP)) ) { + if (!(host = strchr(uidhost, UIDSEP))) { host = uidhost; } else { host++; @@ -60,7 +61,7 @@ int nfsMount(char *uidhost, char *path, char *mntpoint) /* get the full source path */ if (isdigit(*host)) { /* avoid using gethostbyname (for IP address) */ - sprintf(dev,"%s:%s",uidhost,path); + sprintf(dev, "%s:%s", uidhost, path); } else { struct hostent *h; @@ -68,27 +69,24 @@ int nfsMount(char *uidhost, char *path, char *mntpoint) * overwritten) */ strcpy(dev, uidhost); - /* for string host name, get the IP address */ + /* for string host name, get the IP address */ h = gethostbyname(host); - if ( !h || - !inet_ntop( AF_INET, - (struct in_addr*)h->h_addr_list[0], - dev + (host - uidhost), - devl - (host - uidhost))) { - fprintf(stderr,"nfsMount: host '%s' not found\n",host); + if (!h || + !inet_ntop(AF_INET, (struct in_addr *)h->h_addr_list[0], dev + (host - uidhost), devl - (host - uidhost))) { + fprintf(stderr, "nfsMount: host '%s' not found\n", host); goto cleanup; } /* append ':' */ - strcat(dev,":"); - strcat(dev,path); + strcat(dev, ":"); + strcat(dev, path); } /* mount the NFS */ - printf("Trying to mount %s on %s\n",dev,mntpoint); + printf("Trying to mount %s on %s\n", dev, mntpoint); - if(mount(dev, mntpoint, "nfs", MS_SYNCHRONOUS, "rsize=8192,wsize=8192")) { + if (mount(dev, mntpoint, "nfs", MS_SYNCHRONOUS, "rsize=8192,wsize=8192")) { perror("nfsMount - mount"); goto cleanup; } @@ -96,8 +94,8 @@ int nfsMount(char *uidhost, char *path, char *mntpoint) rval = 0; cleanup: - free(dev); - return rval; + free(dev); + return rval; } #define MANAGE_MOUNT 0 @@ -105,13 +103,13 @@ int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { #if MANAGE_MOUNT /* check the input parameters */ - if (!uidhost || !uidhost[0]) return NFS_INVALID_HOST; - if (!path || !path[0]) return NFS_INVALID_PATH; + if (!uidhost || !uidhost[0]) return NFS_INVALID_HOST; + if (!path || !path[0]) return NFS_INVALID_PATH; if (!mntpoint || !mntpoint[0]) return NFS_INVALID_MNTPOINT; /* mount the file system */ - if (nfsMount(uidhost, path, mntpoint) == OK) { /* 0 - succeed; -1 - failed */ - save_restoreNFSOK = 1; - save_restoreIoErrors = 0; /* clean the counter */ + if (nfsMount(uidhost, path, mntpoint) == OK) { /* 0 - succeed; -1 - failed */ + save_restoreNFSOK = 1; + save_restoreIoErrors = 0; /* clean the counter */ return OK; } else { save_restoreNFSOK = 0; @@ -119,7 +117,7 @@ int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) } #else printf("Autosave is not configured to manage the file-system mount point.\n"); - return(OK); + return (OK); #endif } @@ -132,16 +130,16 @@ int dismountFileSystem(char *mntpoint) /* unmount the file system */ save_restoreNFSOK = 0; - if (umount(mntpoint) == 0) { - return(OK); - } else { - return(ERROR); - } + if (umount(mntpoint) == 0) { + return (OK); + } else { + return (ERROR); + } #else printf("Autosave is not configured to manage the file-system mount point.\n"); - return(OK); + return (OK); #endif } diff --git a/asApp/src/os/Linux/osdNfs.h b/asApp/src/os/Linux/osdNfs.h index d9bb9cc..170f7ca 100644 --- a/asApp/src/os/Linux/osdNfs.h +++ b/asApp/src/os/Linux/osdNfs.h @@ -23,27 +23,27 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* definition except for vxWorks */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf /* NFS operation error codes */ -#define NFS_SUCCESS 0 /* succeed */ -#define NFS_FAILURE -1 /* failure with unknown reasons */ -#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ -#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ -#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ +#define NFS_SUCCESS 0 /* succeed */ +#define NFS_FAILURE -1 /* failure with unknown reasons */ +#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ +#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ +#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ /* NFS operation definitions */ -#define UIDSEP '@' +#define UIDSEP '@' /* routines for NFS operation */ -int nfsMount(char *uidhost, char *path, char *mntpoint); /* mount the NFS (details) */ +int nfsMount(char *uidhost, char *path, char *mntpoint); /* mount the NFS (details) */ -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/RTEMS/osdNfs.c b/asApp/src/os/RTEMS/osdNfs.c index 3976d46..d2aeccd 100644 --- a/asApp/src/os/RTEMS/osdNfs.c +++ b/asApp/src/os/RTEMS/osdNfs.c @@ -12,8 +12,9 @@ /** * Global variables */ -int save_restoreNFSOK = 1; /* for RTEMS, NFS has been mounted before autosave starts */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 1; /* for RTEMS, NFS has been mounted before autosave starts */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; /** @@ -37,14 +38,14 @@ extern volatile int save_restoreDebug; int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { /* check the input parameters */ - if (!uidhost || !uidhost[0]) return NFS_INVALID_HOST; - if (!path || !path[0]) return NFS_INVALID_PATH; + if (!uidhost || !uidhost[0]) return NFS_INVALID_HOST; + if (!path || !path[0]) return NFS_INVALID_PATH; if (!mntpoint || !mntpoint[0]) return NFS_INVALID_MNTPOINT; /* mount the file system */ - if (nfsMount(uidhost, path, mntpoint) == OK) { /* 0 - succeed; -1 - failed */ - save_restoreNFSOK = 1; - save_restoreIoErrors = 0; /* clean the counter */ + if (nfsMount(uidhost, path, mntpoint) == OK) { /* 0 - succeed; -1 - failed */ + save_restoreNFSOK = 1; + save_restoreIoErrors = 0; /* clean the counter */ return NFS_SUCCESS; } else { save_restoreNFSOK = 0; @@ -60,20 +61,17 @@ int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) * * Output: * See the definition of NFS operation error codes - */ + */ int dismountFileSystem(char *mntpoint) { /* check the input parameters */ if (!mntpoint || !mntpoint[0]) return NFS_INVALID_MNTPOINT; /* unmount the file system */ - if (unmount(mntpoint) == OK) { /* 0 - succeed; -1 - failed */ - save_restoreNFSOK = 0; + if (unmount(mntpoint) == OK) { /* 0 - succeed; -1 - failed */ + save_restoreNFSOK = 0; return NFS_SUCCESS; } else { return NFS_FAILURE; } } - - - diff --git a/asApp/src/os/RTEMS/osdNfs.h b/asApp/src/os/RTEMS/osdNfs.h index ff56214..47b2505 100644 --- a/asApp/src/os/RTEMS/osdNfs.h +++ b/asApp/src/os/RTEMS/osdNfs.h @@ -15,29 +15,28 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* definition except for vxWorks */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf /* NFS operation error codes */ -#define NFS_SUCCESS 0 /* succeed */ -#define NFS_FAILURE -1 /* failure with unknown reasons */ -#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ -#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ -#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ +#define NFS_SUCCESS 0 /* succeed */ +#define NFS_FAILURE -1 /* failure with unknown reasons */ +#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ +#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ +#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ -#if __RTEMS_MAJOR__>4 || \ - (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || \ - (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99) +#if __RTEMS_MAJOR__ > 4 || (__RTEMS_MAJOR__ == 4 && __RTEMS_MINOR__ > 9) || \ + (__RTEMS_MAJOR__ == 4 && __RTEMS_MINOR__ == 9 && __RTEMS_REVISION__ == 99) /* Dropped from librtemsNfs.h in RTEMS 4.10, now defined in EPICS */ int nfsMount(char *uidhost, char *path, char *mntpoint); #endif /* routines for NFS operation */ -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/WIN32/osdNfs.c b/asApp/src/os/WIN32/osdNfs.c index b0e1cf0..cca1d57 100644 --- a/asApp/src/os/WIN32/osdNfs.c +++ b/asApp/src/os/WIN32/osdNfs.c @@ -9,18 +9,19 @@ /** * Global variables */ -int save_restoreNFSOK = 0; /* Don't support NFS on this OS */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 0; /* Don't support NFS on this OS */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { printf("mountFileSytem not supported on this OS\n"); - return(0); + return (0); } int dismountFileSystem(char *mntpoint) { - printf("dismountFileSytem not supported on this OS\n"); - return(0); + printf("dismountFileSytem not supported on this OS\n"); + return (0); } diff --git a/asApp/src/os/WIN32/osdNfs.h b/asApp/src/os/WIN32/osdNfs.h index b87d001..64dde8f 100644 --- a/asApp/src/os/WIN32/osdNfs.h +++ b/asApp/src/os/WIN32/osdNfs.h @@ -11,14 +11,14 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* definition except for vxWorks */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/cygwin32/osdNfs.c b/asApp/src/os/cygwin32/osdNfs.c index b0e1cf0..cca1d57 100644 --- a/asApp/src/os/cygwin32/osdNfs.c +++ b/asApp/src/os/cygwin32/osdNfs.c @@ -9,18 +9,19 @@ /** * Global variables */ -int save_restoreNFSOK = 0; /* Don't support NFS on this OS */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 0; /* Don't support NFS on this OS */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { printf("mountFileSytem not supported on this OS\n"); - return(0); + return (0); } int dismountFileSystem(char *mntpoint) { - printf("dismountFileSytem not supported on this OS\n"); - return(0); + printf("dismountFileSytem not supported on this OS\n"); + return (0); } diff --git a/asApp/src/os/cygwin32/osdNfs.h b/asApp/src/os/cygwin32/osdNfs.h index b87d001..64dde8f 100644 --- a/asApp/src/os/cygwin32/osdNfs.h +++ b/asApp/src/os/cygwin32/osdNfs.h @@ -11,14 +11,14 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* definition except for vxWorks */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/default/osdNfs.c b/asApp/src/os/default/osdNfs.c index ee01a58..7c12509 100644 --- a/asApp/src/os/default/osdNfs.c +++ b/asApp/src/os/default/osdNfs.c @@ -7,18 +7,18 @@ #include "osdNfs.h" /* Global variables */ -int save_restoreNFSOK = 1; +int save_restoreNFSOK = 1; int save_restoreIoErrors = 0; extern volatile int save_restoreDebug; int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { printf("mountFileSytem not supported on this OS\n"); - return(0); + return (0); } int dismountFileSystem(char *mntpoint) { - printf("dismountFileSytem not supported on this OS\n"); - return(0); + printf("dismountFileSytem not supported on this OS\n"); + return (0); } diff --git a/asApp/src/os/default/osdNfs.h b/asApp/src/os/default/osdNfs.h index b88725f..65fb863 100644 --- a/asApp/src/os/default/osdNfs.h +++ b/asApp/src/os/default/osdNfs.h @@ -11,13 +11,13 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/solaris/osdNfs.c b/asApp/src/os/solaris/osdNfs.c index c504283..26e766c 100644 --- a/asApp/src/os/solaris/osdNfs.c +++ b/asApp/src/os/solaris/osdNfs.c @@ -12,21 +12,21 @@ /** * Global variables */ -int save_restoreNFSOK = 1; /* for Linux, NFS has been mounted before autosave starts */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 1; /* for Linux, NFS has been mounted before autosave starts */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; - /* Note: file system mounting is managed by Linux */ int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { printf("NFS mounting for solaris is managed by OS\n"); - return(OK); + return (OK); } /* Note: file system mounting is managed by Linux */ int dismountFileSystem(char *mntpoint) { printf("Not allowed to dismount for solaris\n"); - return(OK); + return (OK); } diff --git a/asApp/src/os/solaris/osdNfs.h b/asApp/src/os/solaris/osdNfs.h index 1b5469d..38081be 100644 --- a/asApp/src/os/solaris/osdNfs.h +++ b/asApp/src/os/solaris/osdNfs.h @@ -22,25 +22,25 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* definition except for vxWorks */ -#define OK 0 +#define OK 0 #define ERROR -1 #define logMsg errlogPrintf /* NFS operation error codes */ -#define NFS_SUCCESS 0 /* succeed */ -#define NFS_FAILURE -1 /* failure with unknown reasons */ -#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ -#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ -#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ +#define NFS_SUCCESS 0 /* succeed */ +#define NFS_FAILURE -1 /* failure with unknown reasons */ +#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ +#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ +#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ /* NFS operation definitions */ /* routines for NFS operation */ -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/os/vxWorks/osdNfs.c b/asApp/src/os/vxWorks/osdNfs.c index bf0552f..20c3143 100644 --- a/asApp/src/os/vxWorks/osdNfs.c +++ b/asApp/src/os/vxWorks/osdNfs.c @@ -8,13 +8,14 @@ * Description: Realize the basic function for NFS mount and dismount ***********************************************/ #include "osdNfs.h" -extern char saveRestoreFilePath[]; /* path to save files */ +extern char saveRestoreFilePath[]; /* path to save files */ /** * Global variables */ -int save_restoreNFSOK = 0; /* for vxWorks, NFS has not been mounted before autosave starts */ -int save_restoreIoErrors = 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ +int save_restoreNFSOK = 0; /* for vxWorks, NFS has not been mounted before autosave starts */ +int save_restoreIoErrors = + 0; /* for accumulate the IO error numbers, when the number larger than threshold, remount NFS */ extern volatile int save_restoreDebug; /** @@ -32,15 +33,15 @@ extern volatile int save_restoreDebug; int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) { /* check the input parameters */ - if (!uidhost || !uidhost[0]) return ERROR; - if (!path || !path[0]) return ERROR; + if (!uidhost || !uidhost[0]) return ERROR; + if (!path || !path[0]) return ERROR; if (!mntpoint || !mntpoint[0]) return ERROR; /* mount the file system */ if (hostGetByName(uidhost) == ERROR) (void)hostAdd(uidhost, addr); if (nfsMount(uidhost, path, mntpoint) == OK) { - save_restoreNFSOK = 1; - save_restoreIoErrors = 0; /* clean the counter */ + save_restoreNFSOK = 1; + save_restoreIoErrors = 0; /* clean the counter */ return OK; } else { save_restoreNFSOK = 0; @@ -56,21 +57,21 @@ int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint) * * Output: * See the definition of NFS operation error codes - */ + */ int dismountFileSystem(char *mntpoint) { /* check the input parameters */ if (!mntpoint || !mntpoint[0]) { - if (saveRestoreFilePath && saveRestoreFilePath[0]) { - strncpy(mntpoint, saveRestoreFilePath, (NFS_PATH_LEN-1)); - if (save_restoreDebug) printf("save_restore:dismountFileSystem, setting mntpoint tp '%s'\n", mntpoint); - } else { - return ERROR; - } - } + if (saveRestoreFilePath && saveRestoreFilePath[0]) { + strncpy(mntpoint, saveRestoreFilePath, (NFS_PATH_LEN - 1)); + if (save_restoreDebug) printf("save_restore:dismountFileSystem, setting mntpoint tp '%s'\n", mntpoint); + } else { + return ERROR; + } + } /* unmount the file system */ - + if (nfsUnmount(mntpoint) == OK) { save_restoreNFSOK = 0; return OK; @@ -78,6 +79,3 @@ int dismountFileSystem(char *mntpoint) return ERROR; } } - - - diff --git a/asApp/src/os/vxWorks/osdNfs.h b/asApp/src/os/vxWorks/osdNfs.h index 01e1739..6b419c4 100644 --- a/asApp/src/os/vxWorks/osdNfs.h +++ b/asApp/src/os/vxWorks/osdNfs.h @@ -17,23 +17,23 @@ #include #include -#define NFS_PATH_LEN 255 /* string length for NFS related path */ +#define NFS_PATH_LEN 255 /* string length for NFS related path */ /* nfsDrv.h was renamed nfsDriver.h in Tornado 2.2.2 */ /* #include */ extern STATUS nfsMount(char *host, char *fileSystem, char *localName); extern STATUS nfsUnmount(char *localName); -extern int logMsg(char *fmt, ...); +extern int logMsg(char *fmt, ...); /* NFS operation error codes */ -#define NFS_SUCCESS 0 /* succeed */ -#define NFS_FAILURE -1 /* failure with unknown reasons */ -#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ -#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ -#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ +#define NFS_SUCCESS 0 /* succeed */ +#define NFS_FAILURE -1 /* failure with unknown reasons */ +#define NFS_INVALID_HOST 1 /* uid_gid_host parameter is invalid */ +#define NFS_INVALID_PATH 2 /* path on the NFS server is invalid */ +#define NFS_INVALID_MNTPOINT 3 /* mount point in invalid */ /* routines for NFS operation */ -int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ -int dismountFileSystem(char *mntpoint); /* dismount the NFS */ +int mountFileSystem(char *uidhost, char *addr, char *path, char *mntpoint); /* mount the NFS */ +int dismountFileSystem(char *mntpoint); /* dismount the NFS */ #endif diff --git a/asApp/src/save_restore.c b/asApp/src/save_restore.c index 35c6a31..60738b5 100644 --- a/asApp/src/save_restore.c +++ b/asApp/src/save_restore.c @@ -129,61 +129,61 @@ * Report failed connections to PV's at connect time. * Allow embedded '.' in save-file name. */ -#define SRVERSION "autosave R5.3" +#define SRVERSION "autosave R5.3" -#include -#include -#include +#include +#include +#include #ifndef _WIN32 -#include -#include /* for dirList */ +#include +#include /* for dirList */ #else -#include -#include "tr_dirent.h" /* for dirList */ +#include +#include "tr_dirent.h" /* for dirList */ #endif -#include -#include -#include -#include -#include /* for dirList */ +#include +#include +#include +#include +#include /* for dirList */ #ifdef vxWorks - #include /* for VxWorks VERSION */ +#include /* for VxWorks VERSION */ #endif -#include -#include /* includes dbAddr.h */ -#include -#include -#include +#include +#include /* includes dbAddr.h */ +#include +#include +#include /* not in 3.15.0.1 #include */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "save_restore.h" -#include "fGetDateStr.h" -#include "osdNfs.h" /* qiao: routine of os dependent code, for NFS */ -#include "configMenuClient.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "save_restore.h" +#include "fGetDateStr.h" +#include "osdNfs.h" /* qiao: routine of os dependent code, for NFS */ +#include "configMenuClient.h" #define SET_FILE_PERMISSIONS 1 #ifdef _WIN32 - #define SET_FILE_PERMISSIONS 0 +#define SET_FILE_PERMISSIONS 0 #endif #ifdef vxWorks - #if defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR >= 6) && (_WRS_VXWORKS_MINOR >= 6)) - #define SET_FILE_PERMISSIONS 1 - #else - #define SET_FILE_PERMISSIONS 0 - #endif +#if defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR >= 6) && (_WRS_VXWORKS_MINOR >= 6)) +#define SET_FILE_PERMISSIONS 1 +#else +#define SET_FILE_PERMISSIONS 0 +#endif #endif #if SET_FILE_PERMISSIONS @@ -193,85 +193,85 @@ mode_t file_permissions = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); #endif -#define BACKWARDS_LIST 0 /* old list order was backwards */ +#define BACKWARDS_LIST 0 /* old list order was backwards */ /*** data structure definitions ***/ /* save_methods - used to determine when a file should be deleted */ -#define PERIODIC 0x01 /* set when timer goes off */ -#define TRIGGERED 0x02 /* set when trigger channel goes off */ -#define TIMER 0x04 -#define CHANGE 0x08 -#define MONITORED (TIMER|CHANGE) /* set when timer expires and channel changes */ -#define MANUAL 0x10 /* set on request */ -#define SINGLE_EVENTS (PERIODIC|TRIGGERED|MANUAL) - -#define TIMEFMT "%a %b %d %H:%M:%S %Y\n" /* e.g. 'Fri Sep 13 00:00:00 1986\n' */ -#define TIMEFMT_noY "%a %b %d %H:%M:%S" /* e.g. 'Fri Sep 13 00:00:00' */ - -struct chlist { /* save set list element */ - struct chlist *pnext; /* next list */ - struct channel *pchan_list; /* channel list head */ - struct channel *plast_chan; /* channel list tail */ - char reqFile[FN_LEN]; /* request file name */ - char *macrostring; /* copy of the macrostring with which list was created */ - char saveFile[NFS_PATH_LEN+1]; /* full save file name */ - char last_save_file[FN_LEN]; /* file name last used for save */ - char save_file[FN_LEN]; /* file name to use on next save */ - int save_method; /* bit for each save method requested */ - int enabled_method; /* bit for each save method enabled */ - short save_ok; /* !=0 -> last save ok */ - int save_state; /* state of this save set */ - int period; /* time (s) between saves (max for on change) */ - int monitor_period; /* time (s) between saves (max for on change) */ - char trigger_channel[PV_NAME_LEN]; /* db channel to trigger save */ - CALLBACK periodicCb; - CALLBACK monitorCb; - int not_connected; /* # bad channels not saved/connected */ - int backup_sequence_num; /* appended to backup files */ - epicsTimeStamp backup_time; - epicsTimeStamp save_attempt_time; - epicsTimeStamp save_time; - int statusPvIndex; /* identify this list's status reporting variables */ - char name_PV[PV_NAME_LEN]; /* future: write save-set name to generic PV */ - chid name_chid; - long status; - char status_PV[PV_NAME_LEN]; - chid status_chid; - char save_state_PV[PV_NAME_LEN]; - chid save_state_chid; - char statusStr[STATUS_STR_LEN]; - char statusStr_PV[PV_NAME_LEN]; - chid statusStr_chid; - char timeStr[STRING_LEN]; - char time_PV[PV_NAME_LEN]; - chid time_chid; - char savePathPV[PV_NAME_LEN], saveNamePV[PV_NAME_LEN]; - char config[PV_NAME_LEN]; - chid savePathPV_chid, saveNamePV_chid; - int do_backups; - epicsTimeStamp callback_time; /* qiao: call back time of this list */ - epicsTimeStamp reconnect_check_time; /* qiao: for ca reconnection for the not-connected channels */ +#define PERIODIC 0x01 /* set when timer goes off */ +#define TRIGGERED 0x02 /* set when trigger channel goes off */ +#define TIMER 0x04 +#define CHANGE 0x08 +#define MONITORED (TIMER | CHANGE) /* set when timer expires and channel changes */ +#define MANUAL 0x10 /* set on request */ +#define SINGLE_EVENTS (PERIODIC | TRIGGERED | MANUAL) + +#define TIMEFMT "%a %b %d %H:%M:%S %Y\n" /* e.g. 'Fri Sep 13 00:00:00 1986\n' */ +#define TIMEFMT_noY "%a %b %d %H:%M:%S" /* e.g. 'Fri Sep 13 00:00:00' */ + +struct chlist { /* save set list element */ + struct chlist *pnext; /* next list */ + struct channel *pchan_list; /* channel list head */ + struct channel *plast_chan; /* channel list tail */ + char reqFile[FN_LEN]; /* request file name */ + char *macrostring; /* copy of the macrostring with which list was created */ + char saveFile[NFS_PATH_LEN + 1]; /* full save file name */ + char last_save_file[FN_LEN]; /* file name last used for save */ + char save_file[FN_LEN]; /* file name to use on next save */ + int save_method; /* bit for each save method requested */ + int enabled_method; /* bit for each save method enabled */ + short save_ok; /* !=0 -> last save ok */ + int save_state; /* state of this save set */ + int period; /* time (s) between saves (max for on change) */ + int monitor_period; /* time (s) between saves (max for on change) */ + char trigger_channel[PV_NAME_LEN]; /* db channel to trigger save */ + CALLBACK periodicCb; + CALLBACK monitorCb; + int not_connected; /* # bad channels not saved/connected */ + int backup_sequence_num; /* appended to backup files */ + epicsTimeStamp backup_time; + epicsTimeStamp save_attempt_time; + epicsTimeStamp save_time; + int statusPvIndex; /* identify this list's status reporting variables */ + char name_PV[PV_NAME_LEN]; /* future: write save-set name to generic PV */ + chid name_chid; + long status; + char status_PV[PV_NAME_LEN]; + chid status_chid; + char save_state_PV[PV_NAME_LEN]; + chid save_state_chid; + char statusStr[STATUS_STR_LEN]; + char statusStr_PV[PV_NAME_LEN]; + chid statusStr_chid; + char timeStr[STRING_LEN]; + char time_PV[PV_NAME_LEN]; + chid time_chid; + char savePathPV[PV_NAME_LEN], saveNamePV[PV_NAME_LEN]; + char config[PV_NAME_LEN]; + chid savePathPV_chid, saveNamePV_chid; + int do_backups; + epicsTimeStamp callback_time; /* qiao: call back time of this list */ + epicsTimeStamp reconnect_check_time; /* qiao: for ca reconnection for the not-connected channels */ }; -struct channel { /* database channel list element */ - struct channel *pnext; /* next channel */ - char name[64]; /* channel name */ - chid chid; /* channel access id */ - char value[64]; /* value string */ - short enum_val; /* short value of an enumerated field */ - short valid; /* we think we got valid data for this channel */ - long max_elements; /* number of elements, initially from ca, but then from dbAddr */ - long curr_elements; /* number of elements from dbGet */ - long field_type; /* field type from dbAddr */ - void *pArray; - int channel_connected; /* qiao: show if the channel is successfully connected. 0 - failed; 1 - successfully */ - int just_created; /* qiao: 1 means the channel is just created, need to be handled */ +struct channel { /* database channel list element */ + struct channel *pnext; /* next channel */ + char name[64]; /* channel name */ + chid chid; /* channel access id */ + char value[64]; /* value string */ + short enum_val; /* short value of an enumerated field */ + short valid; /* we think we got valid data for this channel */ + long max_elements; /* number of elements, initially from ca, but then from dbAddr */ + long curr_elements; /* number of elements from dbGet */ + long field_type; /* field type from dbAddr */ + void *pArray; + int channel_connected; /* qiao: show if the channel is successfully connected. 0 - failed; 1 - successfully */ + int just_created; /* qiao: 1 means the channel is just created, need to be handled */ }; struct pathListElement { - struct pathListElement *pnext; - char path[NFS_PATH_LEN+1]; + struct pathListElement *pnext; + char path[NFS_PATH_LEN + 1]; }; /*** module global variables ***/ @@ -279,12 +279,12 @@ struct pathListElement { volatile int save_restoreDebug = 0; epicsExportAddress(int, save_restoreDebug); -STATIC struct chlist *lptr = NULL; /* save-set listhead */ -STATIC int listLock = 0; /* replaces long-term holding of sr_mutex */ +STATIC struct chlist *lptr = NULL; /* save-set listhead */ +STATIC int listLock = 0; /* replaces long-term holding of sr_mutex */ #define NUM_STATUS_PV_SETS 8 STATIC int statusPvsInUse[NUM_STATUS_PV_SETS] = {0}; -STATIC epicsMutexId sr_mutex = NULL; /* mut(ual) ex(clusion) for list of save sets */ -int mustSetPermissions = 0; /* use fchmod() only if save_restoreSet_FilePermissions is used */ +STATIC epicsMutexId sr_mutex = NULL; /* mut(ual) ex(clusion) for list of save sets */ +int mustSetPermissions = 0; /* use fchmod() only if save_restoreSet_FilePermissions is used */ /* Support for manual and programmed operations */ @@ -296,109 +296,106 @@ int mustSetPermissions = 0; /* use fchmod() o #define OP_MSG_MACRO_SIZE 100 #define OP_MSG_TRIGGER_SIZE PV_NAME_LEN typedef enum { - op_RestoreFromSaveFile, - op_RestoreFromAsciiFile, - op_Remove, - op_ReloadPeriodicSet, - op_ReloadTriggeredSet, - op_ReloadMonitorSet, - op_ReloadManualSet, - op_SaveFile, - op_asVerify + op_RestoreFromSaveFile, + op_RestoreFromAsciiFile, + op_Remove, + op_ReloadPeriodicSet, + op_ReloadTriggeredSet, + op_ReloadMonitorSet, + op_ReloadManualSet, + op_SaveFile, + op_asVerify } op_type; typedef struct op_msg { - op_type operation; - char filename[OP_MSG_FILENAME_SIZE]; - char requestfilename[OP_MSG_FILENAME_SIZE]; - char macrostring[OP_MSG_MACRO_SIZE]; - char trigger_channel[OP_MSG_TRIGGER_SIZE]; - int period; - callbackFunc callbackFunction; - void *puserPvt; - /* for asVerify from ioc console */ - int verbose; - char restoreFileName[OP_MSG_FILENAME_SIZE]; + op_type operation; + char filename[OP_MSG_FILENAME_SIZE]; + char requestfilename[OP_MSG_FILENAME_SIZE]; + char macrostring[OP_MSG_MACRO_SIZE]; + char trigger_channel[OP_MSG_TRIGGER_SIZE]; + int period; + callbackFunc callbackFunction; + void *puserPvt; + /* for asVerify from ioc console */ + int verbose; + char restoreFileName[OP_MSG_FILENAME_SIZE]; } op_msg; #define OP_MSG_SIZE sizeof(op_msg) -STATIC epicsMessageQueueId opMsgQueue = NULL; /* message queue for manual/programmed save/restore operations */ +STATIC epicsMessageQueueId opMsgQueue = NULL; /* message queue for manual/programmed save/restore operations */ -STATIC short save_restore_init = 0; -STATIC short save_restore_shutdown = 0; +STATIC short save_restore_init = 0; +STATIC short save_restore_shutdown = 0; STATIC epicsEventId shutdownEvent; -STATIC char *SRversion = SRVERSION; -STATIC struct pathListElement - *reqFilePathList = NULL; -char saveRestoreFilePath[NFS_PATH_LEN] = ""; /* path to save files, also used by dbrestore.c */ -STATIC unsigned int - taskPriority = 20; /* epicsThreadPriorityCAServerLow -- initial task priority */ +STATIC char *SRversion = SRVERSION; +STATIC struct pathListElement *reqFilePathList = NULL; +char saveRestoreFilePath[NFS_PATH_LEN] = ""; /* path to save files, also used by dbrestore.c */ +STATIC unsigned int taskPriority = 20; /* epicsThreadPriorityCAServerLow -- initial task priority */ -STATIC epicsThreadId - taskID = 0; /* save_restore task ID */ +STATIC epicsThreadId taskID = 0; /* save_restore task ID */ /* identifies the file type for a manual restore */ #define FROM_SAVE_FILE 1 #define FROM_ASCII_FILE 2 /*** stuff for reporting status to EPICS client ***/ -STATIC char status_prefix[30] = ""; +STATIC char status_prefix[30] = ""; -STATIC long SR_status = SR_STATUS_INIT; +STATIC long SR_status = SR_STATUS_INIT; STATIC unsigned short SR_heartbeat = 0; -STATIC char SR_statusStr[STATUS_STR_LEN] = "", SR_recentlyStr[STATUS_STR_LEN] = ""; -STATIC char SR_status_PV[PV_NAME_LEN] = "", SR_heartbeat_PV[PV_NAME_LEN] = ""; -STATIC char SR_statusStr_PV[PV_NAME_LEN] = "", SR_recentlyStr_PV[PV_NAME_LEN] = ""; -STATIC chid SR_status_chid, SR_heartbeat_chid, - SR_statusStr_chid, SR_recentlyStr_chid; - -STATIC long SR_rebootStatus; -STATIC char SR_rebootStatusStr[STATUS_STR_LEN] = ""; -STATIC char SR_rebootStatus_PV[PV_NAME_LEN] = "", SR_rebootStatusStr_PV[PV_NAME_LEN] = ""; -STATIC chid SR_rebootStatus_chid, SR_rebootStatusStr_chid; -STATIC char SR_rebootTime_PV[PV_NAME_LEN] = ""; -STATIC char SR_rebootTimeStr[STRING_LEN] = ""; -STATIC chid SR_rebootTime_chid; +STATIC char SR_statusStr[STATUS_STR_LEN] = "", SR_recentlyStr[STATUS_STR_LEN] = ""; +STATIC char SR_status_PV[PV_NAME_LEN] = "", SR_heartbeat_PV[PV_NAME_LEN] = ""; +STATIC char SR_statusStr_PV[PV_NAME_LEN] = "", SR_recentlyStr_PV[PV_NAME_LEN] = ""; +STATIC chid SR_status_chid, SR_heartbeat_chid, SR_statusStr_chid, SR_recentlyStr_chid; + +STATIC long SR_rebootStatus; +STATIC char SR_rebootStatusStr[STATUS_STR_LEN] = ""; +STATIC char SR_rebootStatus_PV[PV_NAME_LEN] = "", SR_rebootStatusStr_PV[PV_NAME_LEN] = ""; +STATIC chid SR_rebootStatus_chid, SR_rebootStatusStr_chid; +STATIC char SR_rebootTime_PV[PV_NAME_LEN] = ""; +STATIC char SR_rebootTimeStr[STRING_LEN] = ""; +STATIC chid SR_rebootTime_chid; /* disable support */ -STATIC char SR_disable_PV[PV_NAME_LEN] = ""; -STATIC int SR_disable = 0; -STATIC chid SR_disable_chid; -STATIC char SR_disableMaxSecs_PV[PV_NAME_LEN] = ""; -STATIC int SR_disableMaxSecs = 0; -STATIC chid SR_disableMaxSecs_chid; +STATIC char SR_disable_PV[PV_NAME_LEN] = ""; +STATIC int SR_disable = 0; +STATIC chid SR_disable_chid; +STATIC char SR_disableMaxSecs_PV[PV_NAME_LEN] = ""; +STATIC int SR_disableMaxSecs = 0; +STATIC chid SR_disableMaxSecs_chid; static epicsTimeStamp disableStart; static epicsTimeStamp nullTimeStamp = {0}; -volatile int save_restoreNumSeqFiles = 3; /* number of sequence files to maintain */ -volatile int save_restoreSeqPeriodInSeconds = 60; /* period between sequence-file writes */ -volatile int save_restoreIncompleteSetsOk = 1; /* will save/restore incomplete sets? */ -volatile int save_restoreDatedBackupFiles = 1; /* save backups as .bu or _YYMMDD-HHMMSS */ -volatile int save_restoreRetrySeconds = 60; /* Time before retrying write after a failure. */ -volatile int save_restoreUseStatusPVs = 1; /* use PVs for status etc. */ +volatile int save_restoreNumSeqFiles = 3; /* number of sequence files to maintain */ +volatile int save_restoreSeqPeriodInSeconds = 60; /* period between sequence-file writes */ +volatile int save_restoreIncompleteSetsOk = 1; /* will save/restore incomplete sets? */ +volatile int save_restoreDatedBackupFiles = 1; /* save backups as .bu or _YYMMDD-HHMMSS */ +volatile int save_restoreRetrySeconds = 60; /* Time before retrying write after a failure. */ +volatile int save_restoreUseStatusPVs = 1; /* use PVs for status etc. */ #define CA_RECONNECT_TIME_SECONDS 60 -volatile int save_restoreCAReconnect = 0; /* qiao: if there are channels not connected, reconnect them */ -volatile int save_restoreCallbackTimeout = 600; /* qiao: if the call back does not work than this time, force to save the data */ +volatile int save_restoreCAReconnect = 0; /* qiao: if there are channels not connected, reconnect them */ +volatile int save_restoreCallbackTimeout = + 600; /* qiao: if the call back does not work than this time, force to save the data */ epicsExportAddress(int, save_restoreNumSeqFiles); epicsExportAddress(int, save_restoreSeqPeriodInSeconds); epicsExportAddress(int, save_restoreIncompleteSetsOk); epicsExportAddress(int, save_restoreDatedBackupFiles); epicsExportAddress(int, save_restoreUseStatusPVs); -epicsExportAddress(int, save_restoreCAReconnect); /* qiao: export the new variables */ -epicsExportAddress(int, save_restoreCallbackTimeout); /* qiao: export the new variables */ +epicsExportAddress(int, save_restoreCAReconnect); /* qiao: export the new variables */ +epicsExportAddress(int, save_restoreCallbackTimeout); /* qiao: export the new variables */ /* variables for managing NFS mount */ #define REMOUNT_CHECK_INTERVAL_SECONDS 60 char save_restoreNFSHostName[NFS_PATH_LEN] = ""; char save_restoreNFSHostAddr[NFS_PATH_LEN] = ""; -char save_restoreNFSMntPoint[NFS_PATH_LEN] = ""; +char save_restoreNFSMntPoint[NFS_PATH_LEN] = ""; int saveRestoreFilePathIsMountPoint = 1; -volatile int save_restoreRemountThreshold=10; +volatile int save_restoreRemountThreshold = 10; epicsExportAddress(int, save_restoreRemountThreshold); /* configuration parameters */ -STATIC int MIN_PERIOD = 4; /* save no more frequently than every 4 seconds */ -STATIC int MIN_DELAY = 1; /* check need to save every 1 second */ - /* worst case wait can be MIN_PERIOD + MIN_DELAY */ +STATIC int MIN_PERIOD = 4; /* save no more frequently than every 4 seconds */ +STATIC int MIN_DELAY = 1; /* check need to save every 1 second */ +/* worst case wait can be MIN_PERIOD + MIN_DELAY */ /*** private functions ***/ STATIC void periodic_save(CALLBACK *pcallback); @@ -412,15 +409,17 @@ STATIC int get_channel_values(struct chlist *plist); STATIC int write_it(char *filename, struct chlist *plist); STATIC int write_save_file(struct chlist *plist, const char *configName, char *retSaveFile); STATIC void do_seq(struct chlist *plist); -STATIC int create_data_set(char *filename, int save_method, int period, - char *trigger_channel, int mon_period, char *macrostring); +STATIC int create_data_set(char *filename, int save_method, int period, char *trigger_channel, int mon_period, + char *macrostring); STATIC int do_manual_restore(char *filename, int file_type, char *macrostring); STATIC int readReqFile(const char *file, struct chlist *plist, char *macrostring); STATIC int do_remove_data_set(char *filename); -STATIC int request_manual_restore(char *filename, int file_type, char *macrostring, callbackFunc callbackFunction, void *puserPvt); +STATIC int request_manual_restore(char *filename, int file_type, char *macrostring, callbackFunc callbackFunction, + void *puserPvt); -STATIC void ca_connection_callback(struct connection_handler_args args); /* qiao: call back function for ca connection of the dataset channels */ -STATIC void ca_disconnect(); /* qiao: disconnect all existing CA channels */ +STATIC void ca_connection_callback( + struct connection_handler_args args); /* qiao: call back function for ca connection of the dataset channels */ +STATIC void ca_disconnect(); /* qiao: disconnect all existing CA channels */ STATIC void defaultCallback(int status, void *puserPvt); STATIC void doPeriodicDatedBackup(struct chlist *plist); @@ -439,8 +438,8 @@ int set_saveTask_priority(int priority); int remove_data_set(char *filename); int reload_periodic_set(char *filename, int period, char *macrostring); int reload_triggered_set(char *filename, char *trigger_channel, char *macrostring); -int reload_monitor_set(char * filename, int period, char *macrostring); -int reload_manual_set(char * filename, char *macrostring); +int reload_monitor_set(char *filename, int period, char *macrostring); +int reload_manual_set(char *filename, char *macrostring); /* callable from a client */ int findConfigFiles(char *config, ELLLIST *configMenuList); @@ -453,98 +452,94 @@ int manual_save(char *request_file, char *save_file, callbackFunc callbackFuncti char *getMacroString(char *request_file); /* functions to set save_restore parameters */ -void save_restoreSet_Debug(int level) {save_restoreDebug = level;} -void save_restoreSet_NumSeqFiles(int numSeqFiles) {save_restoreNumSeqFiles = numSeqFiles;} -void save_restoreSet_SeqPeriodInSeconds(int period) {save_restoreSeqPeriodInSeconds = MAX(10, period);} -void save_restoreSet_IncompleteSetsOk(int ok) {save_restoreIncompleteSetsOk = ok;} -void save_restoreSet_DatedBackupFiles(int ok) {save_restoreDatedBackupFiles = ok;} -static int save_restorePeriodicDatedBackups=0; +void save_restoreSet_Debug(int level) { save_restoreDebug = level; } +void save_restoreSet_NumSeqFiles(int numSeqFiles) { save_restoreNumSeqFiles = numSeqFiles; } +void save_restoreSet_SeqPeriodInSeconds(int period) { save_restoreSeqPeriodInSeconds = MAX(10, period); } +void save_restoreSet_IncompleteSetsOk(int ok) { save_restoreIncompleteSetsOk = ok; } +void save_restoreSet_DatedBackupFiles(int ok) { save_restoreDatedBackupFiles = ok; } +static int save_restorePeriodicDatedBackups = 0; static int save_restoreDatedBackupPeriod; -void save_restoreSet_periodicDatedBackups(int periodInMinutes) { - if (periodInMinutes>0) { - save_restorePeriodicDatedBackups = 1; - save_restoreDatedBackupPeriod = periodInMinutes*60; - } else { - save_restorePeriodicDatedBackups = 0; - } +void save_restoreSet_periodicDatedBackups(int periodInMinutes) +{ + if (periodInMinutes > 0) { + save_restorePeriodicDatedBackups = 1; + save_restoreDatedBackupPeriod = periodInMinutes * 60; + } else { + save_restorePeriodicDatedBackups = 0; + } } -void save_restoreSet_status_prefix(char *prefix) {strNcpy(status_prefix, prefix, 30);} +void save_restoreSet_status_prefix(char *prefix) { strNcpy(status_prefix, prefix, 30); } #if SET_FILE_PERMISSIONS -void save_restoreSet_FilePermissions(int permissions) { - file_permissions = (mode_t)permissions; - mustSetPermissions = 1; - printf("save_restore: File permissions set to 0%o\n", (unsigned int)file_permissions); +void save_restoreSet_FilePermissions(int permissions) +{ + file_permissions = (mode_t)permissions; + mustSetPermissions = 1; + printf("save_restore: File permissions set to 0%o\n", (unsigned int)file_permissions); } #endif -void save_restoreSet_RetrySeconds(int seconds) { - if (seconds >= 0) save_restoreRetrySeconds = seconds; +void save_restoreSet_RetrySeconds(int seconds) +{ + if (seconds >= 0) save_restoreRetrySeconds = seconds; } -void save_restoreSet_UseStatusPVs(int ok) {save_restoreUseStatusPVs = ok;} -void save_restoreSet_CAReconnect(int ok) {save_restoreCAReconnect = ok;} -void save_restoreSet_CallbackTimeout(int t) { - if ((t<0) || (t>=MIN_PERIOD)) { - save_restoreCallbackTimeout = t; - } else { - printf("save_restoreCallbackTimeout must be either negative (forever) or >= %d seconds\n", MIN_PERIOD); - } +void save_restoreSet_UseStatusPVs(int ok) { save_restoreUseStatusPVs = ok; } +void save_restoreSet_CAReconnect(int ok) { save_restoreCAReconnect = ok; } +void save_restoreSet_CallbackTimeout(int t) +{ + if ((t < 0) || (t >= MIN_PERIOD)) { + save_restoreCallbackTimeout = t; + } else { + printf("save_restoreCallbackTimeout must be either negative (forever) or >= %d seconds\n", MIN_PERIOD); + } } /********************************* code *********************************/ int isValid1stPVChar(char chr) { - return isalpha((int)chr) || isdigit((int)chr) || chr == '_' || chr == '-' - || chr == '+' || chr == ':' || chr == '[' || chr == ']' || chr == '<' - || chr == '>' || chr == ';'; + return isalpha((int)chr) || isdigit((int)chr) || chr == '_' || chr == '-' || chr == '+' || chr == ':' || + chr == '[' || chr == ']' || chr == '<' || chr == '>' || chr == ';'; } - -int isAbsolute(const char* filename) +int isAbsolute(const char *filename) { - if ( '/' == filename[0] ) - { - return 1; - } + if ('/' == filename[0]) { return 1; } #ifdef _WIN32 - /* windows x:/ absolute style path - for completeness also check for x:\ */ - if ( (strlen(filename) > 2) && (':' == filename[1]) && (('/' == filename[2]) || ('\\' == filename[2])) ) - { - return 1; - } - if ( '\\' == filename[0] ) - { - return 1; - } + /* windows x:/ absolute style path - for completeness also check for x:\ */ + if ((strlen(filename) > 2) && (':' == filename[1]) && (('/' == filename[2]) || ('\\' == filename[2]))) { return 1; } + if ('\\' == filename[0]) { return 1; } #endif /* _WIN32 */ - return 0; + return 0; } /*** access to list *lptr ***/ -STATIC int lockList() { - int caller_owns_lock = 0; - epicsMutexLock(sr_mutex); - if (!listLock) listLock = caller_owns_lock = 1; - epicsMutexUnlock(sr_mutex); - if (save_restoreDebug >= 15) printf("lockList: listLock=%d\n", listLock); - return(caller_owns_lock); +STATIC int lockList() +{ + int caller_owns_lock = 0; + epicsMutexLock(sr_mutex); + if (!listLock) listLock = caller_owns_lock = 1; + epicsMutexUnlock(sr_mutex); + if (save_restoreDebug >= 15) printf("lockList: listLock=%d\n", listLock); + return (caller_owns_lock); } -STATIC void unlockList() { - epicsMutexLock(sr_mutex); - listLock = 0; - epicsMutexUnlock(sr_mutex); - if (save_restoreDebug >= 15) printf("unlockList: listLock=%d\n", listLock); +STATIC void unlockList() +{ + epicsMutexLock(sr_mutex); + listLock = 0; + epicsMutexUnlock(sr_mutex); + if (save_restoreDebug >= 15) printf("unlockList: listLock=%d\n", listLock); } -STATIC int waitForListLock(double secondsToWait) { - double secondsWaited = 0., waitIncrement = 1; - while (lockList() == 0) { - if (secondsWaited >= secondsToWait) return(0); - epicsThreadSleep(waitIncrement); - secondsWaited += waitIncrement; - } - return(1); +STATIC int waitForListLock(double secondsToWait) +{ + double secondsWaited = 0., waitIncrement = 1; + while (lockList() == 0) { + if (secondsWaited >= secondsToWait) return (0); + epicsThreadSleep(waitIncrement); + secondsWaited += waitIncrement; + } + return (1); } /*** callbacks ***/ @@ -560,62 +555,57 @@ STATIC int waitForListLock(double secondsToWait) { /* method PERIODIC - timer has elapsed */ STATIC void periodic_save(CALLBACK *pcallback) { - void *userArg; - struct chlist *plist; - - callbackGetUser(userArg, pcallback); - plist = (struct chlist *)userArg; - if (plist) { - plist->save_state |= PERIODIC; - } else { - logMsg("Periodic saving failure"); - } -} + void *userArg; + struct chlist *plist; + callbackGetUser(userArg, pcallback); + plist = (struct chlist *)userArg; + if (plist) { + plist->save_state |= PERIODIC; + } else { + logMsg("Periodic saving failure"); + } +} /* method TRIGGERED - ca_monitor received for trigger PV */ STATIC void triggered_save(struct event_handler_args event) { - struct chlist *plist = (struct chlist *) event.usr; - - if (event.dbr) { - if (plist) { - plist->save_state |= TRIGGERED; - } else { - logMsg("Failed to activate triggered saving!"); - } - } -} + struct chlist *plist = (struct chlist *)event.usr; + if (event.dbr) { + if (plist) { + plist->save_state |= TRIGGERED; + } else { + logMsg("Failed to activate triggered saving!"); + } + } +} /* method MONITORED - timer has elapsed */ STATIC void on_change_timer(CALLBACK *pcallback) { - void *userArg; - struct chlist *plist; + void *userArg; + struct chlist *plist; - callbackGetUser(userArg, pcallback); - plist = (struct chlist *)userArg; + callbackGetUser(userArg, pcallback); + plist = (struct chlist *)userArg; - if (save_restoreDebug >= 10) logMsg("on_change_timer for %s (period is %d seconds)\n", - plist->reqFile, plist->monitor_period); + if (save_restoreDebug >= 10) + logMsg("on_change_timer for %s (period is %d seconds)\n", plist->reqFile, plist->monitor_period); - if (plist) { - plist->save_state |= TIMER; - } else { - logMsg("Failed to activate saving with timer!"); - } + if (plist) { + plist->save_state |= TIMER; + } else { + logMsg("Failed to activate saving with timer!"); + } } - /* method MONITORED - ca_monitor received for a PV */ STATIC void on_change_save(struct event_handler_args event) { struct chlist *plist; - if (save_restoreDebug >= 10) { - logMsg("on_change_save: event.usr=0x%lx\n", (unsigned long)event.usr); - } - plist = (struct chlist *) event.usr; + if (save_restoreDebug >= 10) { logMsg("on_change_save: event.usr=0x%lx\n", (unsigned long)event.usr); } + plist = (struct chlist *)event.usr; if (plist) { plist->save_state |= CHANGE; @@ -624,232 +614,233 @@ STATIC void on_change_save(struct event_handler_args event) } } +int findConfigFiles(char *config, ELLLIST *configMenuList) +{ + int found; + DIR *pdir = 0; + FILE *fd; + struct dirent *pdirent = 0; + char thisname[FN_LEN], filename[FN_LEN], *pchar, fullpath[NFS_PATH_LEN]; + char buffer[BUF_SIZE], *bp, *bp1, config_underscore[FN_LEN]; + struct configFileListItem *pLI, *pLInext; + + /* clear old list */ + pLI = (struct configFileListItem *)ellFirst(configMenuList); + while (pLI) { + free(pLI->name); + free(pLI->description); + pLInext = (struct configFileListItem *)ellNext(&(pLI->node)); + ellDelete(configMenuList, &(pLI->node)); + pLI = pLInext; + } -int findConfigFiles(char *config, ELLLIST *configMenuList) { - int found; - DIR *pdir=0; - FILE *fd; - struct dirent *pdirent=0; - char thisname[FN_LEN], filename[FN_LEN], *pchar, fullpath[NFS_PATH_LEN]; - char buffer[BUF_SIZE], *bp, *bp1, config_underscore[FN_LEN]; - struct configFileListItem *pLI, *pLInext; - - /* clear old list */ - pLI = (struct configFileListItem *) ellFirst(configMenuList); - while (pLI) { - free(pLI->name); - free(pLI->description); - pLInext = (struct configFileListItem *) ellNext(&(pLI->node)); - ellDelete(configMenuList, &(pLI->node)); - pLI = pLInext; - } - - strNcpy(config_underscore, config, FN_LEN-1); - strcat(config_underscore, "_"); - if (save_restoreDebug) printf("findConfigFiles: config='%s', config_underscore=%s\n", - config, config_underscore); - - pdir = opendir(saveRestoreFilePath); - if (pdir) { - if (save_restoreDebug) printf("findConfigFiles: opendir('%s') succeeded.\n", saveRestoreFilePath); - while ((pdirent=readdir(pdir))) { - if (save_restoreDebug>1) printf("findConfigFiles: checking '%s'.\n", pdirent->d_name); - if (strncmp(config_underscore, pdirent->d_name, strlen(config_underscore)) == 0) { - strNcpy(filename, pdirent->d_name, FN_LEN); - if (save_restoreDebug) printf("findConfigFiles: found '%s'\n", filename); - strNcpy(thisname, &(filename[strlen(config_underscore)]), FN_LEN); - if (save_restoreDebug) printf("findConfigFiles: searching '%s' for .cfg\n", thisname); - /* require that file end with ".cfg" */ - pchar = strstr(&thisname[strlen(thisname)-strlen(".cfg")], ".cfg"); - if (pchar) { - *pchar = '\0'; - pLI = calloc(1, sizeof(struct configFileListItem)); - ellAdd(configMenuList, &(pLI->node)); - pLI->name = (char *)calloc(strlen(thisname)+1, sizeof(char)); - strNcpy(pLI->name, thisname, strlen(thisname)+1); - if (save_restoreDebug) printf("findConfigFiles: found config file '%s'\n", pLI->name); - makeNfsPath(fullpath, saveRestoreFilePath, filename); - if ((fd = fopen(fullpath, "r"))) { - if (save_restoreDebug) printf("findConfigFiles: searching '%s' for description\n", fullpath); - found = 0; - while (!found && (bp=fgets(buffer, BUF_SIZE, fd))) { - bp1 = strstr(bp, "Menu:currDesc"); - if (bp1 != 0) { - found = 1; - bp1 += strlen("Menu:currDesc")+1; - pLI->description = (char *)calloc(strlen(bp1)+1, sizeof(char)); - strNcpy(pLI->description, bp1, strlen(bp1)+1); - if (( pchar = strchr(pLI->description, '\n') )) *pchar = '\0'; - if (( pchar = strchr(pLI->description, '\r') )) *pchar = '\0'; - } - } - if (fd) { - fclose(fd); - fd = NULL; - } - } else { - if (save_restoreDebug) printf("findConfigFiles: can't open '%s'\n", filename); - } - } - } - } - if (save_restoreDebug) { - pLI = (struct configFileListItem *) ellFirst(configMenuList); - printf("findConfigFiles: \n"); - while (pLI) { - printf(" name='%s'; desc='%s'\n", pLI->name, pLI->description); - pLI = (struct configFileListItem *) ellNext(&(pLI->node)); - } - } - closedir(pdir); - return(0); - } - if (save_restoreDebug) printf("findConfigFiles: opendir('%s') failed.\n", saveRestoreFilePath); + strNcpy(config_underscore, config, FN_LEN - 1); + strcat(config_underscore, "_"); + if (save_restoreDebug) printf("findConfigFiles: config='%s', config_underscore=%s\n", config, config_underscore); + + pdir = opendir(saveRestoreFilePath); + if (pdir) { + if (save_restoreDebug) printf("findConfigFiles: opendir('%s') succeeded.\n", saveRestoreFilePath); + while ((pdirent = readdir(pdir))) { + if (save_restoreDebug > 1) printf("findConfigFiles: checking '%s'.\n", pdirent->d_name); + if (strncmp(config_underscore, pdirent->d_name, strlen(config_underscore)) == 0) { + strNcpy(filename, pdirent->d_name, FN_LEN); + if (save_restoreDebug) printf("findConfigFiles: found '%s'\n", filename); + strNcpy(thisname, &(filename[strlen(config_underscore)]), FN_LEN); + if (save_restoreDebug) printf("findConfigFiles: searching '%s' for .cfg\n", thisname); + /* require that file end with ".cfg" */ + pchar = strstr(&thisname[strlen(thisname) - strlen(".cfg")], ".cfg"); + if (pchar) { + *pchar = '\0'; + pLI = calloc(1, sizeof(struct configFileListItem)); + ellAdd(configMenuList, &(pLI->node)); + pLI->name = (char *)calloc(strlen(thisname) + 1, sizeof(char)); + strNcpy(pLI->name, thisname, strlen(thisname) + 1); + if (save_restoreDebug) printf("findConfigFiles: found config file '%s'\n", pLI->name); + makeNfsPath(fullpath, saveRestoreFilePath, filename); + if ((fd = fopen(fullpath, "r"))) { + if (save_restoreDebug) printf("findConfigFiles: searching '%s' for description\n", fullpath); + found = 0; + while (!found && (bp = fgets(buffer, BUF_SIZE, fd))) { + bp1 = strstr(bp, "Menu:currDesc"); + if (bp1 != 0) { + found = 1; + bp1 += strlen("Menu:currDesc") + 1; + pLI->description = (char *)calloc(strlen(bp1) + 1, sizeof(char)); + strNcpy(pLI->description, bp1, strlen(bp1) + 1); + if ((pchar = strchr(pLI->description, '\n'))) *pchar = '\0'; + if ((pchar = strchr(pLI->description, '\r'))) *pchar = '\0'; + } + } + if (fd) { + fclose(fd); + fd = NULL; + } + } else { + if (save_restoreDebug) printf("findConfigFiles: can't open '%s'\n", filename); + } + } + } + } + if (save_restoreDebug) { + pLI = (struct configFileListItem *)ellFirst(configMenuList); + printf("findConfigFiles: \n"); + while (pLI) { + printf(" name='%s'; desc='%s'\n", pLI->name, pLI->description); + pLI = (struct configFileListItem *)ellNext(&(pLI->node)); + } + } + closedir(pdir); + return (0); + } + if (save_restoreDebug) printf("findConfigFiles: opendir('%s') failed.\n", saveRestoreFilePath); - return(-1); + return (-1); } int manual_save(char *request_file, char *save_file, callbackFunc callbackFunction, void *puserPvt) { - op_msg msg; - - if (save_restoreDebug) printf("manual_save: request_file='%s', save_file='%s', callbackFunction=%p, puserPvt=%p\n", - request_file, save_file, callbackFunction, puserPvt); - - msg.operation = op_SaveFile; - strNcpy(msg.requestfilename, request_file, OP_MSG_FILENAME_SIZE); - msg.filename[0] = '\0'; - if (save_file) strNcpy(msg.filename, save_file, OP_MSG_FILENAME_SIZE); - if (callbackFunction==NULL) { - callbackFunction = defaultCallback; - puserPvt = NULL; - } - msg.puserPvt = puserPvt; - msg.callbackFunction = callbackFunction; - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + op_msg msg; + + if (save_restoreDebug) + printf("manual_save: request_file='%s', save_file='%s', callbackFunction=%p, puserPvt=%p\n", request_file, + save_file, callbackFunction, puserPvt); + + msg.operation = op_SaveFile; + strNcpy(msg.requestfilename, request_file, OP_MSG_FILENAME_SIZE); + msg.filename[0] = '\0'; + if (save_file) strNcpy(msg.filename, save_file, OP_MSG_FILENAME_SIZE); + if (callbackFunction == NULL) { + callbackFunction = defaultCallback; + puserPvt = NULL; + } + msg.puserPvt = puserPvt; + msg.callbackFunction = callbackFunction; + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } - STATIC void ca_connection_callback(struct connection_handler_args args) { - struct channel *pchannel = ca_puser(args.chid); + struct channel *pchannel = ca_puser(args.chid); - if (!pchannel) return; + if (!pchannel) return; - if (args.op == CA_OP_CONN_UP) { - pchannel->channel_connected = 1; - } else { - pchannel->channel_connected = 0; - ca_clear_channel(args.chid); - pchannel->chid = NULL; - } + if (args.op == CA_OP_CONN_UP) { + pchannel->channel_connected = 1; + } else { + pchannel->channel_connected = 0; + ca_clear_channel(args.chid); + pchannel->chid = NULL; + } } /*** functions to manage NFS mount ***/ -STATIC void do_mount() { - if (save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]) { - if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, save_restoreNFSMntPoint, save_restoreNFSMntPoint) == OK) { - printf("save_restore:mountFileSystem:successfully mounted '%s'\n", save_restoreNFSMntPoint); - strNcpy(SR_recentlyStr, "mountFileSystem succeeded", STATUS_STR_LEN); - save_restoreIoErrors = 0; - save_restoreNFSOK = 1; - } - else { - printf("save_restore: Can't mount '%s'\n", save_restoreNFSMntPoint); - } - } else { - save_restoreNFSOK = 1; - } +STATIC void do_mount() +{ + if (save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]) { + if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, save_restoreNFSMntPoint, + save_restoreNFSMntPoint) == OK) { + printf("save_restore:mountFileSystem:successfully mounted '%s'\n", save_restoreNFSMntPoint); + strNcpy(SR_recentlyStr, "mountFileSystem succeeded", STATUS_STR_LEN); + save_restoreIoErrors = 0; + save_restoreNFSOK = 1; + } else { + printf("save_restore: Can't mount '%s'\n", save_restoreNFSMntPoint); + } + } else { + save_restoreNFSOK = 1; + } } /* Concatenate s1 and s2, making sure there is a directory separator between them, * and copy the result to dest. Make local copies of s1 and s2 to defend against * calls in which one of them is specified also as dest, e.g. makeNfsPath(a,b,a). */ -void makeNfsPath(char *dest, const char *s1, const char *s2) { - char tmp1[NFS_PATH_LEN], tmp2[NFS_PATH_LEN]; - if (dest == NULL) return; - tmp1[0] = '\0'; - if (s1 && *s1) strNcpy(tmp1, s1, NFS_PATH_LEN); - tmp2[0] = '\0'; - if (s2 && *s2) strNcpy(tmp2, s2, NFS_PATH_LEN); - - if (*tmp1) strNcpy(dest, tmp1, NFS_PATH_LEN); - if (*tmp2 && (*tmp2 != '/') && (strlen(dest) !=0 ) && (dest[strlen(dest)-1] != '/')) - strncat(dest,"/", MAX(NFS_PATH_LEN-1 - strlen(dest),0)); - - if ((*tmp2 == '/') && (strlen(dest) !=0 ) && (dest[strlen(dest)-1] == '/')) { - strncat(dest, &(tmp2[1]), MAX(NFS_PATH_LEN-1 - strlen(dest),0)); - } else { - strncat(dest, tmp2, MAX(NFS_PATH_LEN-1 - strlen(dest),0)); - } - if (save_restoreDebug > 2) { - printf("save_restore:makeNfsPath: dest='%s'\n", dest); - } +void makeNfsPath(char *dest, const char *s1, const char *s2) +{ + char tmp1[NFS_PATH_LEN], tmp2[NFS_PATH_LEN]; + if (dest == NULL) return; + tmp1[0] = '\0'; + if (s1 && *s1) strNcpy(tmp1, s1, NFS_PATH_LEN); + tmp2[0] = '\0'; + if (s2 && *s2) strNcpy(tmp2, s2, NFS_PATH_LEN); + + if (*tmp1) strNcpy(dest, tmp1, NFS_PATH_LEN); + if (*tmp2 && (*tmp2 != '/') && (strlen(dest) != 0) && (dest[strlen(dest) - 1] != '/')) + strncat(dest, "/", MAX(NFS_PATH_LEN - 1 - strlen(dest), 0)); + + if ((*tmp2 == '/') && (strlen(dest) != 0) && (dest[strlen(dest) - 1] == '/')) { + strncat(dest, &(tmp2[1]), MAX(NFS_PATH_LEN - 1 - strlen(dest), 0)); + } else { + strncat(dest, tmp2, MAX(NFS_PATH_LEN - 1 - strlen(dest), 0)); + } + if (save_restoreDebug > 2) { printf("save_restore:makeNfsPath: dest='%s'\n", dest); } } -int testMakeNfsPath() { - char dest[NFS_PATH_LEN]; +int testMakeNfsPath() +{ + char dest[NFS_PATH_LEN]; - dest[0] = '\0'; - makeNfsPath(dest,"",""); - printf("makeNfsPath(dest,\"\",\"\") yields '%s'\n", dest); + dest[0] = '\0'; + makeNfsPath(dest, "", ""); + printf("makeNfsPath(dest,\"\",\"\") yields '%s'\n", dest); - dest[0] = '\0'; - makeNfsPath(dest,"abc",""); - printf("makeNfsPath(dest,\"abc\",\"\") yields '%s'\n", dest); + dest[0] = '\0'; + makeNfsPath(dest, "abc", ""); + printf("makeNfsPath(dest,\"abc\",\"\") yields '%s'\n", dest); - dest[0] = '\0'; - makeNfsPath(dest,"","def"); - printf("makeNfsPath(dest,\"\",\"def\") yields '%s'\n", dest); + dest[0] = '\0'; + makeNfsPath(dest, "", "def"); + printf("makeNfsPath(dest,\"\",\"def\") yields '%s'\n", dest); - dest[0] = '\0'; - makeNfsPath(dest,"","/def"); - printf("makeNfsPath(dest,\"\",\"/def\") yields '%s'\n", dest); + dest[0] = '\0'; + makeNfsPath(dest, "", "/def"); + printf("makeNfsPath(dest,\"\",\"/def\") yields '%s'\n", dest); - dest[0] = '\0'; - makeNfsPath(dest,"abc/","def"); - printf("makeNfsPath(dest,\"abc/\",\"def\") yields '%s'\n", dest); + dest[0] = '\0'; + makeNfsPath(dest, "abc/", "def"); + printf("makeNfsPath(dest,\"abc/\",\"def\") yields '%s'\n", dest); - dest[0] = '\0'; - makeNfsPath(dest,"abc/","/def"); - printf("makeNfsPath(dest,\"abc/\",\"/def\") yields '%s'\n", dest); - return(0); + dest[0] = '\0'; + makeNfsPath(dest, "abc/", "/def"); + printf("makeNfsPath(dest,\"abc/\",\"/def\") yields '%s'\n", dest); + return (0); } void save_restoreSet_NFSHost(char *hostname, char *address, char *mntpoint) { - /* If file system is mounted (save_restoreNFSOK) and we mounted it (save_restoreNFSMntPoint[0]), + /* If file system is mounted (save_restoreNFSOK) and we mounted it (save_restoreNFSMntPoint[0]), * then dismount, presuming that caller wants us to remount from new information. If we didn't * mount it, presume that caller did, and that caller wants us to manage the mount point. */ - if (save_restoreNFSOK && save_restoreNFSMntPoint[0]) dismountFileSystem(save_restoreNFSMntPoint); + if (save_restoreNFSOK && save_restoreNFSMntPoint[0]) dismountFileSystem(save_restoreNFSMntPoint); - /* get the settings */ - strNcpy(save_restoreNFSHostName, hostname, NFS_PATH_LEN); - strNcpy(save_restoreNFSHostAddr, address, NFS_PATH_LEN); + /* get the settings */ + strNcpy(save_restoreNFSHostName, hostname, NFS_PATH_LEN); + strNcpy(save_restoreNFSHostAddr, address, NFS_PATH_LEN); if (mntpoint && mntpoint[0]) { - saveRestoreFilePathIsMountPoint = 0; - strNcpy(save_restoreNFSMntPoint, mntpoint, NFS_PATH_LEN); - if (saveRestoreFilePath[0]) { - /* If we already have a file path, make sure it begins with the mount point. */ - if (strstr(saveRestoreFilePath, save_restoreNFSMntPoint) != saveRestoreFilePath) { - makeNfsPath(saveRestoreFilePath, save_restoreNFSMntPoint, saveRestoreFilePath); - } - } - } else if (saveRestoreFilePath[0]) { - strNcpy(save_restoreNFSMntPoint, saveRestoreFilePath, NFS_PATH_LEN); - saveRestoreFilePathIsMountPoint = 1; - } + saveRestoreFilePathIsMountPoint = 0; + strNcpy(save_restoreNFSMntPoint, mntpoint, NFS_PATH_LEN); + if (saveRestoreFilePath[0]) { + /* If we already have a file path, make sure it begins with the mount point. */ + if (strstr(saveRestoreFilePath, save_restoreNFSMntPoint) != saveRestoreFilePath) { + makeNfsPath(saveRestoreFilePath, save_restoreNFSMntPoint, saveRestoreFilePath); + } + } + } else if (saveRestoreFilePath[0]) { + strNcpy(save_restoreNFSMntPoint, saveRestoreFilePath, NFS_PATH_LEN); + saveRestoreFilePathIsMountPoint = 1; + } - /* mount the file system */ - do_mount(); + /* mount the file system */ + do_mount(); } -static void save_restoreShutdown(void *arg) { - save_restore_shutdown = 1; - epicsEventWait(shutdownEvent); +static void save_restoreShutdown(void *arg) +{ + save_restore_shutdown = 1; + epicsEventWait(shutdownEvent); } /*** save_restore task ***/ @@ -860,202 +851,197 @@ static void save_restoreShutdown(void *arg) { */ STATIC int save_restore(void) { - struct chlist *plist = NULL; - char *cp, nameString[FN_LEN]; - int i, do_seq_check, just_remounted, n, saveNeeded=0; - epicsTimeStamp currTime, last_seq_check, remount_check_time, delayStart; - epicsTimeStamp lastPeriodicDatedBackup; - char datetime[32]; - double timeDiff; - int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]; - op_msg msg; - struct restoreFileListItem *pLI; - - if (save_restoreDebug > 1) - printf("save_restore:save_restore: entry; status_prefix='%s'\n", status_prefix); - - epicsTimeGetCurrent(&currTime); - last_seq_check = remount_check_time = currTime; /* struct copy */ - lastPeriodicDatedBackup = currTime; - - ca_context_create(ca_enable_preemptive_callback); - - if ((save_restoreNFSOK == 0) && NFS_managed) do_mount(); - - /* Build names for save_restore general status PV's with status_prefix */ - if (save_restoreUseStatusPVs && *status_prefix && (*SR_status_PV == '\0')) { - strNcpy(SR_status_PV, status_prefix, PV_NAME_LEN); - strncat(SR_status_PV, "SR_status", PV_NAME_LEN-1-strlen(SR_status_PV)); - strNcpy(SR_heartbeat_PV, status_prefix, PV_NAME_LEN); - strncat(SR_heartbeat_PV, "SR_heartbeat", PV_NAME_LEN-1-strlen(SR_heartbeat_PV)); - strNcpy(SR_statusStr_PV, status_prefix, PV_NAME_LEN); - strncat(SR_statusStr_PV, "SR_statusStr", PV_NAME_LEN-1-strlen(SR_statusStr_PV)); - strNcpy(SR_recentlyStr_PV, status_prefix, PV_NAME_LEN); - strncat(SR_recentlyStr_PV, "SR_recentlyStr", PV_NAME_LEN-1-strlen(SR_recentlyStr_PV)); - TATTLE(ca_search(SR_status_PV, &SR_status_chid), "save_restore: ca_search(%s) returned %s", SR_status_PV); - TATTLE(ca_search(SR_heartbeat_PV, &SR_heartbeat_chid), "save_restore: ca_search(%s) returned %s", SR_heartbeat_PV); - TATTLE(ca_search(SR_statusStr_PV, &SR_statusStr_chid), "save_restore: ca_search(%s) returned %s", SR_statusStr_PV); - TATTLE(ca_search(SR_recentlyStr_PV, &SR_recentlyStr_chid), "save_restore: ca_search(%s) returned %s", SR_recentlyStr_PV); - - strNcpy(SR_rebootStatus_PV, status_prefix, PV_NAME_LEN); - strncat(SR_rebootStatus_PV, "SR_rebootStatus", PV_NAME_LEN-1-strlen(SR_rebootStatus_PV)); - strNcpy(SR_rebootStatusStr_PV, status_prefix, PV_NAME_LEN); - strncat(SR_rebootStatusStr_PV, "SR_rebootStatusStr", PV_NAME_LEN-1-strlen(SR_rebootStatusStr_PV)); - strNcpy(SR_rebootTime_PV, status_prefix, PV_NAME_LEN); - strncat(SR_rebootTime_PV, "SR_rebootTime", PV_NAME_LEN-1-strlen(SR_rebootTime_PV)); - TATTLE(ca_search(SR_rebootStatus_PV, &SR_rebootStatus_chid), "save_restore: ca_search(%s) returned %s", SR_rebootStatus_PV); - TATTLE(ca_search(SR_rebootStatusStr_PV, &SR_rebootStatusStr_chid), "save_restore: ca_search(%s) returned %s", SR_rebootStatusStr_PV); - TATTLE(ca_search(SR_rebootTime_PV, &SR_rebootTime_chid), "save_restore: ca_search(%s) returned %s", SR_rebootTime_PV); - - /* disable support */ - strNcpy(SR_disable_PV, status_prefix, PV_NAME_LEN); - strncat(SR_disable_PV, "SR_disable", PV_NAME_LEN-1-strlen(SR_disable_PV)); - TATTLE(ca_search(SR_disable_PV, &SR_disable_chid), "save_restore: ca_search(%s) returned %s", SR_disable_PV); - - strNcpy(SR_disableMaxSecs_PV, status_prefix, PV_NAME_LEN); - strncat(SR_disableMaxSecs_PV, "SR_disableMaxSecs", PV_NAME_LEN-1-strlen(SR_disableMaxSecs_PV)); - TATTLE(ca_search(SR_disableMaxSecs_PV, &SR_disableMaxSecs_chid), "save_restore: ca_search(%s) returned %s", SR_disableMaxSecs_PV); - - - if (ca_pend_io(0.5)!=ECA_NORMAL) { - printf("save_restore: Can't connect to all status PV(s)\n"); - } - /* Show reboot status */ - SR_rebootStatus = SR_STATUS_OK; - strcpy(SR_rebootStatusStr, "Ok"); - maybeInitRestoreFileLists(); - - for (i=0; i<2; i++) { - if (i==0) { - pLI = (struct restoreFileListItem *) ellFirst(&pass0List); - } else { - pLI = (struct restoreFileListItem *) ellFirst(&pass1List); - } - while (pLI) { - if (pLI->restoreStatus < SR_rebootStatus) { - SR_rebootStatus = pLI->restoreStatus; - strNcpy(SR_rebootStatusStr, pLI->restoreStatusStr, STATUS_STR_LEN); - } - pLI = (struct restoreFileListItem *) ellNext(&(pLI->node)); - } - } - - TRY_TO_PUT(DBR_LONG, SR_rebootStatus_chid, &SR_rebootStatus); - TRY_TO_PUT(DBR_STRING, SR_rebootStatusStr_chid, &SR_rebootStatusStr); - epicsTimeGetCurrent(&currTime); - epicsTimeToStrftime(SR_rebootTimeStr, sizeof(SR_rebootTimeStr), - TIMEFMT_noY, &currTime); - TRY_TO_PUT(DBR_STRING, SR_rebootTime_chid, &SR_rebootTimeStr); - } + struct chlist *plist = NULL; + char *cp, nameString[FN_LEN]; + int i, do_seq_check, just_remounted, n, saveNeeded = 0; + epicsTimeStamp currTime, last_seq_check, remount_check_time, delayStart; + epicsTimeStamp lastPeriodicDatedBackup; + char datetime[32]; + double timeDiff; + int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]; + op_msg msg; + struct restoreFileListItem *pLI; + + if (save_restoreDebug > 1) printf("save_restore:save_restore: entry; status_prefix='%s'\n", status_prefix); + + epicsTimeGetCurrent(&currTime); + last_seq_check = remount_check_time = currTime; /* struct copy */ + lastPeriodicDatedBackup = currTime; + + ca_context_create(ca_enable_preemptive_callback); + + if ((save_restoreNFSOK == 0) && NFS_managed) do_mount(); + + /* Build names for save_restore general status PV's with status_prefix */ + if (save_restoreUseStatusPVs && *status_prefix && (*SR_status_PV == '\0')) { + strNcpy(SR_status_PV, status_prefix, PV_NAME_LEN); + strncat(SR_status_PV, "SR_status", PV_NAME_LEN - 1 - strlen(SR_status_PV)); + strNcpy(SR_heartbeat_PV, status_prefix, PV_NAME_LEN); + strncat(SR_heartbeat_PV, "SR_heartbeat", PV_NAME_LEN - 1 - strlen(SR_heartbeat_PV)); + strNcpy(SR_statusStr_PV, status_prefix, PV_NAME_LEN); + strncat(SR_statusStr_PV, "SR_statusStr", PV_NAME_LEN - 1 - strlen(SR_statusStr_PV)); + strNcpy(SR_recentlyStr_PV, status_prefix, PV_NAME_LEN); + strncat(SR_recentlyStr_PV, "SR_recentlyStr", PV_NAME_LEN - 1 - strlen(SR_recentlyStr_PV)); + TATTLE(ca_search(SR_status_PV, &SR_status_chid), "save_restore: ca_search(%s) returned %s", SR_status_PV); + TATTLE(ca_search(SR_heartbeat_PV, &SR_heartbeat_chid), "save_restore: ca_search(%s) returned %s", + SR_heartbeat_PV); + TATTLE(ca_search(SR_statusStr_PV, &SR_statusStr_chid), "save_restore: ca_search(%s) returned %s", + SR_statusStr_PV); + TATTLE(ca_search(SR_recentlyStr_PV, &SR_recentlyStr_chid), "save_restore: ca_search(%s) returned %s", + SR_recentlyStr_PV); + + strNcpy(SR_rebootStatus_PV, status_prefix, PV_NAME_LEN); + strncat(SR_rebootStatus_PV, "SR_rebootStatus", PV_NAME_LEN - 1 - strlen(SR_rebootStatus_PV)); + strNcpy(SR_rebootStatusStr_PV, status_prefix, PV_NAME_LEN); + strncat(SR_rebootStatusStr_PV, "SR_rebootStatusStr", PV_NAME_LEN - 1 - strlen(SR_rebootStatusStr_PV)); + strNcpy(SR_rebootTime_PV, status_prefix, PV_NAME_LEN); + strncat(SR_rebootTime_PV, "SR_rebootTime", PV_NAME_LEN - 1 - strlen(SR_rebootTime_PV)); + TATTLE(ca_search(SR_rebootStatus_PV, &SR_rebootStatus_chid), "save_restore: ca_search(%s) returned %s", + SR_rebootStatus_PV); + TATTLE(ca_search(SR_rebootStatusStr_PV, &SR_rebootStatusStr_chid), "save_restore: ca_search(%s) returned %s", + SR_rebootStatusStr_PV); + TATTLE(ca_search(SR_rebootTime_PV, &SR_rebootTime_chid), "save_restore: ca_search(%s) returned %s", + SR_rebootTime_PV); + + /* disable support */ + strNcpy(SR_disable_PV, status_prefix, PV_NAME_LEN); + strncat(SR_disable_PV, "SR_disable", PV_NAME_LEN - 1 - strlen(SR_disable_PV)); + TATTLE(ca_search(SR_disable_PV, &SR_disable_chid), "save_restore: ca_search(%s) returned %s", SR_disable_PV); + + strNcpy(SR_disableMaxSecs_PV, status_prefix, PV_NAME_LEN); + strncat(SR_disableMaxSecs_PV, "SR_disableMaxSecs", PV_NAME_LEN - 1 - strlen(SR_disableMaxSecs_PV)); + TATTLE(ca_search(SR_disableMaxSecs_PV, &SR_disableMaxSecs_chid), "save_restore: ca_search(%s) returned %s", + SR_disableMaxSecs_PV); + + if (ca_pend_io(0.5) != ECA_NORMAL) { printf("save_restore: Can't connect to all status PV(s)\n"); } + /* Show reboot status */ + SR_rebootStatus = SR_STATUS_OK; + strcpy(SR_rebootStatusStr, "Ok"); + maybeInitRestoreFileLists(); + + for (i = 0; i < 2; i++) { + if (i == 0) { + pLI = (struct restoreFileListItem *)ellFirst(&pass0List); + } else { + pLI = (struct restoreFileListItem *)ellFirst(&pass1List); + } + while (pLI) { + if (pLI->restoreStatus < SR_rebootStatus) { + SR_rebootStatus = pLI->restoreStatus; + strNcpy(SR_rebootStatusStr, pLI->restoreStatusStr, STATUS_STR_LEN); + } + pLI = (struct restoreFileListItem *)ellNext(&(pLI->node)); + } + } + + TRY_TO_PUT(DBR_LONG, SR_rebootStatus_chid, &SR_rebootStatus); + TRY_TO_PUT(DBR_STRING, SR_rebootStatusStr_chid, &SR_rebootStatusStr); + epicsTimeGetCurrent(&currTime); + epicsTimeToStrftime(SR_rebootTimeStr, sizeof(SR_rebootTimeStr), TIMEFMT_noY, &currTime); + TRY_TO_PUT(DBR_STRING, SR_rebootTime_chid, &SR_rebootTimeStr); + } + + while (1) { + if (save_restore_shutdown) goto shutdown; + + /* disable support */ + if (CONNECTED(SR_disable_chid)) { ca_get(DBR_LONG, SR_disable_chid, &SR_disable); } + if (CONNECTED(SR_disableMaxSecs_chid)) { ca_get(DBR_LONG, SR_disableMaxSecs_chid, &SR_disableMaxSecs); } + if (ca_pend_io(0.5) == ECA_NORMAL) { + if (SR_disable) { + if (disableStart.secPastEpoch == nullTimeStamp.secPastEpoch) { + epicsTimeGetCurrent(&disableStart); + } else { + epicsTimeGetCurrent(&currTime); + if (epicsTimeDiffInSeconds(&currTime, &disableStart) > SR_disableMaxSecs) { + SR_disable = 0; + ca_put(DBR_LONG, SR_disable_chid, &SR_disable); + disableStart = nullTimeStamp; + } + } + } + } + if (SR_disable) { goto disable; } + + SR_status = SR_STATUS_OK; + strcpy(SR_statusStr, "Ok"); + save_restoreSeqPeriodInSeconds = MAX(10, save_restoreSeqPeriodInSeconds); + save_restoreNumSeqFiles = MIN(10, MAX(0, save_restoreNumSeqFiles)); + epicsTimeGetCurrent(&currTime); + do_seq_check = (epicsTimeDiffInSeconds(&currTime, &last_seq_check) > save_restoreSeqPeriodInSeconds / 2); + if (do_seq_check) last_seq_check = currTime; /* struct copy */ - while(1) { - - if (save_restore_shutdown) goto shutdown; - - /* disable support */ - if (CONNECTED(SR_disable_chid)) { - ca_get(DBR_LONG, SR_disable_chid, &SR_disable); - } - if (CONNECTED(SR_disableMaxSecs_chid)) { - ca_get(DBR_LONG, SR_disableMaxSecs_chid, &SR_disableMaxSecs); - } - if (ca_pend_io(0.5) == ECA_NORMAL) { - if (SR_disable) { - if (disableStart.secPastEpoch==nullTimeStamp.secPastEpoch) { - epicsTimeGetCurrent(&disableStart); - } else { - epicsTimeGetCurrent(&currTime); - if (epicsTimeDiffInSeconds(&currTime, &disableStart) > SR_disableMaxSecs) { - SR_disable = 0; - ca_put(DBR_LONG, SR_disable_chid, &SR_disable); - disableStart = nullTimeStamp; - } - } - } - } - if (SR_disable) { - goto disable; - } - - SR_status = SR_STATUS_OK; - strcpy(SR_statusStr, "Ok"); - save_restoreSeqPeriodInSeconds = MAX(10, save_restoreSeqPeriodInSeconds); - save_restoreNumSeqFiles = MIN(10, MAX(0, save_restoreNumSeqFiles)); - epicsTimeGetCurrent(&currTime); - do_seq_check = (epicsTimeDiffInSeconds(&currTime, &last_seq_check) > - save_restoreSeqPeriodInSeconds/2); - if (do_seq_check) last_seq_check = currTime; /* struct copy */ - - just_remounted = 0; - - /* remount NFS if necessary. If the file written failure happens more times than defined threshold, + just_remounted = 0; + + /* remount NFS if necessary. If the file written failure happens more times than defined threshold, * we will assume the NFS need to be remounted */ - if ((save_restoreNFSOK == 0) && NFS_managed) { - /* NFS problem, and we're managing the mount: Try every 60 seconds to remount. */ - timeDiff = epicsTimeDiffInSeconds(&currTime, &remount_check_time); - /* printf("save_restore: save_restoreNFSOK==0 for %f seconds\n", timeDiff); */ - if (timeDiff > REMOUNT_CHECK_INTERVAL_SECONDS) { - remount_check_time = currTime; /* struct copy */ - printf("save_restore: attempting to remount filesystem\n"); - dismountFileSystem(save_restoreNFSMntPoint); /* first dismount it */ - /* We don't care if dismountFileSystem fails. + if ((save_restoreNFSOK == 0) && NFS_managed) { + /* NFS problem, and we're managing the mount: Try every 60 seconds to remount. */ + timeDiff = epicsTimeDiffInSeconds(&currTime, &remount_check_time); + /* printf("save_restore: save_restoreNFSOK==0 for %f seconds\n", timeDiff); */ + if (timeDiff > REMOUNT_CHECK_INTERVAL_SECONDS) { + remount_check_time = currTime; /* struct copy */ + printf("save_restore: attempting to remount filesystem\n"); + dismountFileSystem(save_restoreNFSMntPoint); /* first dismount it */ + /* We don't care if dismountFileSystem fails. * It could fail simply because an earlier dismount, succeeded. */ - if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, - save_restoreNFSMntPoint, save_restoreNFSMntPoint) == OK) { - just_remounted = 1; - printf("save_restore: remounted '%s'\n", save_restoreNFSMntPoint); - SR_status = SR_STATUS_OK; - strcpy(SR_statusStr, "NFS remounted"); - } else { - printf("save_restore: failed to remount '%s' \n", save_restoreNFSMntPoint); - SR_status = SR_STATUS_FAIL; - strcpy(SR_statusStr, "NFS failed!"); - } - } - } - - /* look at each list */ - while (waitForListLock(5) == 0) { - if (save_restoreDebug > 1) - printf("save_restore: '%s' waiting for listLock()\n", lptr ? lptr->reqFile : ""); - } - plist = lptr; - while (plist != 0) { - if (save_restoreDebug >= 30) - printf("save_restore: '%s' save_state = 0x%x\n", plist->reqFile, plist->save_state); - - /* connect the channels on the first instance of this set */ - if (plist->enabled_method == 0) { - /* qiao: first, Connect to savePathPV and saveNamePV, if they are defined (this is moved from the connect_list() routine */ - if (plist->savePathPV[0] || plist->saveNamePV[0]) { - if (plist->savePathPV[0]) { - TATTLE(ca_search(plist->savePathPV,&plist->savePathPV_chid), "save_restore: ca_search(%s) returned %s", plist->savePathPV); - } - if (plist->saveNamePV[0]) { - TATTLE(ca_search(plist->saveNamePV,&plist->saveNamePV_chid), "save_restore: ca_search(%s) returned %s", plist->saveNamePV); - } - if (ca_pend_io(0.5)!=ECA_NORMAL) { - printf("save_restore: Can't connect to list-specific path/name PV(s)\n"); - - plist->status = SR_STATUS_WARN; - strNcpy(plist->statusStr, "List path/name PVs connection failed", STATUS_STR_LEN); - } - } - - /* qiao: second, connect the list */ - plist->not_connected = connect_list(plist, 1); - plist->reconnect_check_time = currTime; - - } else if (save_restoreCAReconnect && - plist->not_connected > 0 && - epicsTimeDiffInSeconds(&currTime, &plist->reconnect_check_time) > CA_RECONNECT_TIME_SECONDS) { - /* Try to connect to disconnected channels every CA_RECONNECT_TIME_SECONDS */ - plist->reconnect_check_time = currTime; - plist->not_connected = connect_list(plist, 0); - } - - /* + if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, save_restoreNFSMntPoint, + save_restoreNFSMntPoint) == OK) { + just_remounted = 1; + printf("save_restore: remounted '%s'\n", save_restoreNFSMntPoint); + SR_status = SR_STATUS_OK; + strcpy(SR_statusStr, "NFS remounted"); + } else { + printf("save_restore: failed to remount '%s' \n", save_restoreNFSMntPoint); + SR_status = SR_STATUS_FAIL; + strcpy(SR_statusStr, "NFS failed!"); + } + } + } + + /* look at each list */ + while (waitForListLock(5) == 0) { + if (save_restoreDebug > 1) + printf("save_restore: '%s' waiting for listLock()\n", lptr ? lptr->reqFile : ""); + } + plist = lptr; + while (plist != 0) { + if (save_restoreDebug >= 30) + printf("save_restore: '%s' save_state = 0x%x\n", plist->reqFile, plist->save_state); + + /* connect the channels on the first instance of this set */ + if (plist->enabled_method == 0) { + /* qiao: first, Connect to savePathPV and saveNamePV, if they are defined (this is moved from the connect_list() routine */ + if (plist->savePathPV[0] || plist->saveNamePV[0]) { + if (plist->savePathPV[0]) { + TATTLE(ca_search(plist->savePathPV, &plist->savePathPV_chid), + "save_restore: ca_search(%s) returned %s", plist->savePathPV); + } + if (plist->saveNamePV[0]) { + TATTLE(ca_search(plist->saveNamePV, &plist->saveNamePV_chid), + "save_restore: ca_search(%s) returned %s", plist->saveNamePV); + } + if (ca_pend_io(0.5) != ECA_NORMAL) { + printf("save_restore: Can't connect to list-specific path/name PV(s)\n"); + + plist->status = SR_STATUS_WARN; + strNcpy(plist->statusStr, "List path/name PVs connection failed", STATUS_STR_LEN); + } + } + + /* qiao: second, connect the list */ + plist->not_connected = connect_list(plist, 1); + plist->reconnect_check_time = currTime; + + } else if (save_restoreCAReconnect && plist->not_connected > 0 && + epicsTimeDiffInSeconds(&currTime, &plist->reconnect_check_time) > CA_RECONNECT_TIME_SECONDS) { + /* Try to connect to disconnected channels every CA_RECONNECT_TIME_SECONDS */ + plist->reconnect_check_time = currTime; + plist->not_connected = connect_list(plist, 0); + } + + /* * We used to call enable_list() from create_data_set(), if the * list already existed and was just getting a new method. In that * case, we'd only enable new lists (those with enabled_method==0) here. @@ -1063,304 +1049,302 @@ STATIC int save_restore(void) * setting up CA monitors that we're going to have to manage, so we * make all the calls to enable_list(). */ - if (plist->enabled_method != plist->save_method) enable_list(plist); + if (plist->enabled_method != plist->save_method) enable_list(plist); - /* qiao: check the call back timeout if the save method is periodic or monitored */ - if ((plist->save_method & PERIODIC) || (plist->save_method & MONITORED) == MONITORED) { - if ((save_restoreCallbackTimeout > MIN_PERIOD) && - (epicsTimeDiffInSeconds(&currTime, &plist->callback_time) > save_restoreCallbackTimeout)) { - plist->save_state = plist->save_method; + /* qiao: check the call back timeout if the save method is periodic or monitored */ + if ((plist->save_method & PERIODIC) || (plist->save_method & MONITORED) == MONITORED) { + if ((save_restoreCallbackTimeout > MIN_PERIOD) && + (epicsTimeDiffInSeconds(&currTime, &plist->callback_time) > save_restoreCallbackTimeout)) { + plist->save_state = plist->save_method; - if (save_restoreDebug > 1) - printf("save_restore: Callback time out of %s, force to save!\n", plist->reqFile); - } - } + if (save_restoreDebug > 1) + printf("save_restore: Callback time out of %s, force to save!\n", plist->reqFile); + } + } - /* + /* * Save lists that have triggered. Save lists that are in failure, if we've just remounted, * or if RETRY_SECS have elapsed since the last save attempt. */ - saveNeeded = FALSE; - if (plist->save_state & SINGLE_EVENTS) - saveNeeded = TRUE; - else if ((plist->save_state & MONITORED) == MONITORED) - saveNeeded = TRUE; - else if (plist->status <= SR_STATUS_FAIL) { - if (just_remounted) - saveNeeded = TRUE; - else if (epicsTimeDiffInSeconds(&currTime, &plist->save_attempt_time) > save_restoreRetrySeconds) - saveNeeded = TRUE; - } - - if (saveNeeded) { - - /* fetch values all of the channels */ - plist->not_connected = get_channel_values(plist); - - /* write the data to disk */ - if ((plist->not_connected == 0) || (save_restoreIncompleteSetsOk)) - write_save_file(plist, NULL, NULL); - } - - /*** Periodically make sequenced backup of most recent saved file ***/ - if (do_seq_check && plist->do_backups && (plist->status > SR_STATUS_FAIL)) { - if (save_restoreNumSeqFiles && plist->last_save_file[0] && - (epicsTimeDiffInSeconds(&currTime, &plist->backup_time) > - save_restoreSeqPeriodInSeconds)) { - do_seq(plist); - } - } - - /*** periodicated backups ***/ - if (save_restorePeriodicDatedBackups) { - if (epicsTimeDiffInSeconds(&currTime, &lastPeriodicDatedBackup) > - save_restoreDatedBackupPeriod) { - if (plist->do_backups) { - doPeriodicDatedBackup(plist); - lastPeriodicDatedBackup = currTime; - } - } - } - - /*** restart timers and reset save requests ***/ - if (plist->save_state & PERIODIC) { - callbackRequestDelayed(&plist->periodicCb, (double)plist->period); - plist->callback_time = currTime; /* qiao: rememter the time starting callback */ - fGetDateStr(datetime); - } - if (plist->save_state & SINGLE_EVENTS) { - /* Note that this clears PERIODIC, TRIGGERED, and MANUAL bits */ - plist->save_state = plist->save_state & ~SINGLE_EVENTS; - } - if ((plist->save_state & MONITORED) == MONITORED) { - callbackRequestDelayed(&plist->monitorCb, (double)plist->monitor_period); - plist->save_state = plist->save_state & ~MONITORED; - plist->callback_time = currTime; /* qiao: rememter the time starting callback */ - fGetDateStr(datetime); - } - - /* find and record worst status */ - if (plist->status <= SR_status ) { - SR_status = plist->status; - strNcpy(SR_statusStr, plist->statusStr, STATUS_STR_LEN); - } - /*if (SR_rebootStatus < SR_status) { + saveNeeded = FALSE; + if (plist->save_state & SINGLE_EVENTS) saveNeeded = TRUE; + else if ((plist->save_state & MONITORED) == MONITORED) saveNeeded = TRUE; + else if (plist->status <= SR_STATUS_FAIL) { + if (just_remounted) saveNeeded = TRUE; + else if (epicsTimeDiffInSeconds(&currTime, &plist->save_attempt_time) > save_restoreRetrySeconds) + saveNeeded = TRUE; + } + + if (saveNeeded) { + /* fetch values all of the channels */ + plist->not_connected = get_channel_values(plist); + + /* write the data to disk */ + if ((plist->not_connected == 0) || (save_restoreIncompleteSetsOk)) write_save_file(plist, NULL, NULL); + } + + /*** Periodically make sequenced backup of most recent saved file ***/ + if (do_seq_check && plist->do_backups && (plist->status > SR_STATUS_FAIL)) { + if (save_restoreNumSeqFiles && plist->last_save_file[0] && + (epicsTimeDiffInSeconds(&currTime, &plist->backup_time) > save_restoreSeqPeriodInSeconds)) { + do_seq(plist); + } + } + + /*** periodicated backups ***/ + if (save_restorePeriodicDatedBackups) { + if (epicsTimeDiffInSeconds(&currTime, &lastPeriodicDatedBackup) > save_restoreDatedBackupPeriod) { + if (plist->do_backups) { + doPeriodicDatedBackup(plist); + lastPeriodicDatedBackup = currTime; + } + } + } + + /*** restart timers and reset save requests ***/ + if (plist->save_state & PERIODIC) { + callbackRequestDelayed(&plist->periodicCb, (double)plist->period); + plist->callback_time = currTime; /* qiao: rememter the time starting callback */ + fGetDateStr(datetime); + } + if (plist->save_state & SINGLE_EVENTS) { + /* Note that this clears PERIODIC, TRIGGERED, and MANUAL bits */ + plist->save_state = plist->save_state & ~SINGLE_EVENTS; + } + if ((plist->save_state & MONITORED) == MONITORED) { + callbackRequestDelayed(&plist->monitorCb, (double)plist->monitor_period); + plist->save_state = plist->save_state & ~MONITORED; + plist->callback_time = currTime; /* qiao: rememter the time starting callback */ + fGetDateStr(datetime); + } + + /* find and record worst status */ + if (plist->status <= SR_status) { + SR_status = plist->status; + strNcpy(SR_statusStr, plist->statusStr, STATUS_STR_LEN); + } + /*if (SR_rebootStatus < SR_status) { SR_status = SR_rebootStatus; strNcpy(SR_statusStr, SR_rebootStatusStr, STATUS_STR_LEN); }*/ /* qiao: disable this part, because sometimes the system recovers during runtime though some errors during reboot */ - /* next list */ - plist = plist->pnext; - } - - /* release the list */ - unlockList(); - - /* report status */ - SR_heartbeat = (SR_heartbeat+1) % 2; - TRY_TO_PUT(DBR_LONG, SR_status_chid, &SR_status); - TRY_TO_PUT(DBR_SHORT, SR_heartbeat_chid, &SR_heartbeat); - TRY_TO_PUT(DBR_STRING, SR_statusStr_chid, &SR_statusStr); - SR_recentlyStr[(STATUS_STR_LEN-1)] = '\0'; - TRY_TO_PUT(DBR_STRING, SR_recentlyStr_chid, &SR_recentlyStr); - - if (save_restoreUseStatusPVs) { - /*** set up list-specific status PV's for any new lists ***/ - while (waitForListLock(5) == 0) { - if (save_restoreDebug > 1) printf("save_restore: waiting for listLock()\n"); - } - for (plist = lptr; plist; plist = plist->pnext) { - /* + /* next list */ + plist = plist->pnext; + } + + /* release the list */ + unlockList(); + + /* report status */ + SR_heartbeat = (SR_heartbeat + 1) % 2; + TRY_TO_PUT(DBR_LONG, SR_status_chid, &SR_status); + TRY_TO_PUT(DBR_SHORT, SR_heartbeat_chid, &SR_heartbeat); + TRY_TO_PUT(DBR_STRING, SR_statusStr_chid, &SR_statusStr); + SR_recentlyStr[(STATUS_STR_LEN - 1)] = '\0'; + TRY_TO_PUT(DBR_STRING, SR_recentlyStr_chid, &SR_recentlyStr); + + if (save_restoreUseStatusPVs) { + /*** set up list-specific status PV's for any new lists ***/ + while (waitForListLock(5) == 0) { + if (save_restoreDebug > 1) printf("save_restore: waiting for listLock()\n"); + } + for (plist = lptr; plist; plist = plist->pnext) { + /* * If this is the first time for a list, and user has defined a status prefix, * connect to the list's status PV's */ - if (*status_prefix && (plist->status_PV[0] == '\0') && (plist->statusPvIndex < NUM_STATUS_PV_SETS)) { - /*** Build PV names ***/ - /* make common portion of PVname strings */ - n = (PV_NAME_LEN-1) - epicsSnprintf(plist->status_PV, PV_NAME_LEN-1, "%sSR_%1d_", status_prefix, plist->statusPvIndex); - strNcpy(plist->name_PV, plist->status_PV, PV_NAME_LEN); - strNcpy(plist->save_state_PV, plist->status_PV, PV_NAME_LEN); - strNcpy(plist->statusStr_PV, plist->status_PV, PV_NAME_LEN); - strNcpy(plist->time_PV, plist->status_PV, PV_NAME_LEN); - /* make all PVname strings */ - strncat(plist->status_PV, "Status", n); - strncat(plist->name_PV, "Name", n); - strncat(plist->save_state_PV, "State", n); - strncat(plist->statusStr_PV, "StatusStr", n); - strncat(plist->time_PV, "Time", n); - /* connect with PV's */ - TATTLE(ca_search(plist->status_PV, &plist->status_chid), "save_restore: ca_search(%s) returned %s", plist->status_PV); - TATTLE(ca_search(plist->name_PV, &plist->name_chid), "save_restore: ca_search(%s) returned %s", plist->name_PV); - TATTLE(ca_search(plist->save_state_PV, &plist->save_state_chid), "save_restore: ca_search(%s) returned %s", plist->save_state_PV); - TATTLE(ca_search(plist->statusStr_PV, &plist->statusStr_chid), "save_restore: ca_search(%s) returned %s", plist->statusStr_PV); - TATTLE(ca_search(plist->time_PV, &plist->time_chid), "save_restore: ca_search(%s) returned %s", plist->time_PV); - if (ca_pend_io(0.5)!=ECA_NORMAL) { - printf("save_restore: Can't connect to status PV(s) for list '%s'\n", plist->save_file); - } - } - - if (plist->statusPvIndex < NUM_STATUS_PV_SETS) { - TRY_TO_PUT(DBR_LONG, plist->status_chid, &plist->status); - if (CONNECTED(plist->name_chid)) { - strNcpy(nameString, plist->save_file, STRING_LEN); - cp = strrchr(nameString, (int)'.'); - if (cp) *cp = 0; - ca_put(DBR_STRING, plist->name_chid, &nameString); - } - TRY_TO_PUT(DBR_LONG, plist->save_state_chid, &plist->save_state); - TRY_TO_PUT(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - if ((plist->status >= SR_STATUS_WARN) && (plist->save_time.secPastEpoch != 0)) { - epicsTimeToStrftime(plist->timeStr, sizeof(plist->timeStr), - TIMEFMT_noY, &plist->save_time); - TRY_TO_PUT(DBR_STRING, plist->time_chid, &plist->timeStr); - } - } - } - unlockList(); - } - - /*** service client commands and/or sleep for MIN_DELAY ***/ - -disable: - epicsTimeGetCurrent(&delayStart); - while (epicsMessageQueueReceiveWithTimeout(opMsgQueue, (void*) &msg, OP_MSG_SIZE, (double)MIN_DELAY) >= 0) { - int status=0; - int num_errs; - char fullPath[NFS_PATH_LEN+1] = ""; - - switch (msg.operation) { - - case op_RestoreFromSaveFile: - if (save_restoreDebug) printf("save_restore task: calling do_manual_restore('%s')\n", msg.filename); - status = do_manual_restore(msg.filename, FROM_SAVE_FILE, NULL); - if (save_restoreDebug>1) printf("save_restore: manual restore status=%d (0==success)\n", status); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Restore of '%s' %s", msg.filename, status?"Failed":"Succeeded"); - break; - - case op_RestoreFromAsciiFile: - if (save_restoreDebug) printf("save_restore task: calling do_manual_restore('%s')\n", msg.filename); - status = do_manual_restore(msg.filename, FROM_ASCII_FILE, msg.macrostring); - if (save_restoreDebug>1) printf("save_restore: manual restore status=%d (0==success)\n", status); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Restore of '%s' %s", msg.filename, status?"Failed":"Succeeded"); - if (status == 0) { - if (!isAbsolute(msg.filename)) { - makeNfsPath(fullPath, saveRestoreFilePath, msg.filename); - } else { - strNcpy(fullPath, msg.filename, NFS_PATH_LEN); - } - status = do_asVerify(fullPath, -1, save_restoreDebug, 0, ""); - } - if (msg.callbackFunction) (msg.callbackFunction)(status, msg.puserPvt); - break; - - case op_Remove: - if (save_restoreDebug) printf("save_restore task: calling do_remove_data_set('%s')\n", msg.filename); - status = do_remove_data_set(msg.filename); - if (save_restoreDebug>1) printf("save_restore: remove status=%d (0==success)\n", status); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Remove '%s' %s", msg.filename, status?"Failed":"Succeeded"); - break; - - case op_ReloadPeriodicSet: - case op_ReloadTriggeredSet: - case op_ReloadMonitorSet: - case op_ReloadManualSet: - if (save_restoreDebug) printf("save_restore task: calling do_remove_data_set('%s')\n", msg.filename); - status = do_remove_data_set(msg.filename); - if (save_restoreDebug>1) printf("save_restore: remove status=%d (0==success)\n", status); - if (status == 0) { - switch (msg.operation) { - case op_ReloadPeriodicSet: - status = create_periodic_set(msg.filename, msg.period, msg.macrostring); - break; - case op_ReloadTriggeredSet: - status = create_triggered_set(msg.filename, msg.trigger_channel, msg.macrostring); - break; - case op_ReloadMonitorSet: - status = create_monitor_set(msg.filename, msg.period, msg.macrostring); - break; - case op_ReloadManualSet: - status = create_manual_set(msg.filename, msg.macrostring); - break; - /* These can't occur, but are included anyway just to shut the compiler up. */ - case op_RestoreFromSaveFile: case op_RestoreFromAsciiFile: case op_Remove: - default: - break; - } - } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Reload '%s' %s", msg.filename, status?"Failed":"Succeeded"); - break; - - - case op_SaveFile: - if (save_restoreDebug) printf("save_restore task: manual save('%s')\n", msg.filename); - num_errs = 0; - while (waitForListLock(5) == 0) { - if (save_restoreDebug > 1) printf("save_restore: waiting for listLock()\n"); - } - status = -1; - fullPath[0] = '\0'; - plist = lptr; - while (plist != 0) { - if (strcmp(plist->reqFile, msg.requestfilename) == 0) break; - plist = plist->pnext; - } - if (plist) { - /* fetch values all of the channels */ - plist->not_connected = get_channel_values(plist); - num_errs += plist->not_connected; - - /* write the data to disk */ - if ((plist->not_connected == 0) || (save_restoreIncompleteSetsOk)) - status = write_save_file(plist, msg.filename, fullPath); - if (save_restoreDebug>1) printf("save_restore: op_SaveFile: write_save_file() returned %d\n", status); - } - unlockList(); - if (status == 0) { - status = do_asVerify(fullPath, -1, save_restoreDebug, 0, ""); - } - - if (save_restoreDebug>1) printf("save_restore: manual save status=%d (0==success)\n", status); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Save of '%s' %s", - status ? msg.filename : (plist ? plist->save_file : ""), - status ? "Failed" : "Succeeded"); - if (!status && num_errs) status = num_errs; - if (msg.callbackFunction) (msg.callbackFunction)(status, msg.puserPvt); - break; - - case op_asVerify: - if (save_restoreDebug) printf("save_restore task: calling do_asVerify('%s')\n", msg.filename); - if (!isAbsolute(msg.filename)) { - makeNfsPath(fullPath, saveRestoreFilePath, msg.filename); - } else { - strNcpy(fullPath, msg.filename, NFS_PATH_LEN); - } - status = do_asVerify(fullPath, msg.verbose, save_restoreDebug, - (int)(msg.restoreFileName[0]!='\0'), msg.restoreFileName); - break; - - default: - break; - } - ca_pend_event(0.001); - } - - /* Make sure MIN_DELAY has elapsed before we make next pass through the list */ - epicsTimeGetCurrent(&currTime); - timeDiff = epicsTimeDiffInSeconds(&currTime, &delayStart); - if (timeDiff < MIN_DELAY) ca_pend_event(timeDiff - MIN_DELAY); + if (*status_prefix && (plist->status_PV[0] == '\0') && (plist->statusPvIndex < NUM_STATUS_PV_SETS)) { + /*** Build PV names ***/ + /* make common portion of PVname strings */ + n = (PV_NAME_LEN - 1) - epicsSnprintf(plist->status_PV, PV_NAME_LEN - 1, "%sSR_%1d_", status_prefix, + plist->statusPvIndex); + strNcpy(plist->name_PV, plist->status_PV, PV_NAME_LEN); + strNcpy(plist->save_state_PV, plist->status_PV, PV_NAME_LEN); + strNcpy(plist->statusStr_PV, plist->status_PV, PV_NAME_LEN); + strNcpy(plist->time_PV, plist->status_PV, PV_NAME_LEN); + /* make all PVname strings */ + strncat(plist->status_PV, "Status", n); + strncat(plist->name_PV, "Name", n); + strncat(plist->save_state_PV, "State", n); + strncat(plist->statusStr_PV, "StatusStr", n); + strncat(plist->time_PV, "Time", n); + /* connect with PV's */ + TATTLE(ca_search(plist->status_PV, &plist->status_chid), "save_restore: ca_search(%s) returned %s", + plist->status_PV); + TATTLE(ca_search(plist->name_PV, &plist->name_chid), "save_restore: ca_search(%s) returned %s", + plist->name_PV); + TATTLE(ca_search(plist->save_state_PV, &plist->save_state_chid), + "save_restore: ca_search(%s) returned %s", plist->save_state_PV); + TATTLE(ca_search(plist->statusStr_PV, &plist->statusStr_chid), + "save_restore: ca_search(%s) returned %s", plist->statusStr_PV); + TATTLE(ca_search(plist->time_PV, &plist->time_chid), "save_restore: ca_search(%s) returned %s", + plist->time_PV); + if (ca_pend_io(0.5) != ECA_NORMAL) { + printf("save_restore: Can't connect to status PV(s) for list '%s'\n", plist->save_file); + } + } + + if (plist->statusPvIndex < NUM_STATUS_PV_SETS) { + TRY_TO_PUT(DBR_LONG, plist->status_chid, &plist->status); + if (CONNECTED(plist->name_chid)) { + strNcpy(nameString, plist->save_file, STRING_LEN); + cp = strrchr(nameString, (int)'.'); + if (cp) *cp = 0; + ca_put(DBR_STRING, plist->name_chid, &nameString); + } + TRY_TO_PUT(DBR_LONG, plist->save_state_chid, &plist->save_state); + TRY_TO_PUT(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + if ((plist->status >= SR_STATUS_WARN) && (plist->save_time.secPastEpoch != 0)) { + epicsTimeToStrftime(plist->timeStr, sizeof(plist->timeStr), TIMEFMT_noY, &plist->save_time); + TRY_TO_PUT(DBR_STRING, plist->time_chid, &plist->timeStr); + } + } + } + unlockList(); + } + + /*** service client commands and/or sleep for MIN_DELAY ***/ + + disable: + epicsTimeGetCurrent(&delayStart); + while (epicsMessageQueueReceiveWithTimeout(opMsgQueue, (void *)&msg, OP_MSG_SIZE, (double)MIN_DELAY) >= 0) { + int status = 0; + int num_errs; + char fullPath[NFS_PATH_LEN + 1] = ""; + + switch (msg.operation) { + case op_RestoreFromSaveFile: + if (save_restoreDebug) printf("save_restore task: calling do_manual_restore('%s')\n", msg.filename); + status = do_manual_restore(msg.filename, FROM_SAVE_FILE, NULL); + if (save_restoreDebug > 1) printf("save_restore: manual restore status=%d (0==success)\n", status); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Restore of '%s' %s", msg.filename, + status ? "Failed" : "Succeeded"); + break; + + case op_RestoreFromAsciiFile: + if (save_restoreDebug) printf("save_restore task: calling do_manual_restore('%s')\n", msg.filename); + status = do_manual_restore(msg.filename, FROM_ASCII_FILE, msg.macrostring); + if (save_restoreDebug > 1) printf("save_restore: manual restore status=%d (0==success)\n", status); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Restore of '%s' %s", msg.filename, + status ? "Failed" : "Succeeded"); + if (status == 0) { + if (!isAbsolute(msg.filename)) { + makeNfsPath(fullPath, saveRestoreFilePath, msg.filename); + } else { + strNcpy(fullPath, msg.filename, NFS_PATH_LEN); + } + status = do_asVerify(fullPath, -1, save_restoreDebug, 0, ""); + } + if (msg.callbackFunction) (msg.callbackFunction)(status, msg.puserPvt); + break; + + case op_Remove: + if (save_restoreDebug) + printf("save_restore task: calling do_remove_data_set('%s')\n", msg.filename); + status = do_remove_data_set(msg.filename); + if (save_restoreDebug > 1) printf("save_restore: remove status=%d (0==success)\n", status); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Remove '%s' %s", msg.filename, + status ? "Failed" : "Succeeded"); + break; + + case op_ReloadPeriodicSet: + case op_ReloadTriggeredSet: + case op_ReloadMonitorSet: + case op_ReloadManualSet: + if (save_restoreDebug) + printf("save_restore task: calling do_remove_data_set('%s')\n", msg.filename); + status = do_remove_data_set(msg.filename); + if (save_restoreDebug > 1) printf("save_restore: remove status=%d (0==success)\n", status); + if (status == 0) { + switch (msg.operation) { + case op_ReloadPeriodicSet: + status = create_periodic_set(msg.filename, msg.period, msg.macrostring); + break; + case op_ReloadTriggeredSet: + status = create_triggered_set(msg.filename, msg.trigger_channel, msg.macrostring); + break; + case op_ReloadMonitorSet: + status = create_monitor_set(msg.filename, msg.period, msg.macrostring); + break; + case op_ReloadManualSet: status = create_manual_set(msg.filename, msg.macrostring); break; + /* These can't occur, but are included anyway just to shut the compiler up. */ + case op_RestoreFromSaveFile: + case op_RestoreFromAsciiFile: + case op_Remove: + default: break; + } + } + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Reload '%s' %s", msg.filename, + status ? "Failed" : "Succeeded"); + break; + + case op_SaveFile: + if (save_restoreDebug) printf("save_restore task: manual save('%s')\n", msg.filename); + num_errs = 0; + while (waitForListLock(5) == 0) { + if (save_restoreDebug > 1) printf("save_restore: waiting for listLock()\n"); + } + status = -1; + fullPath[0] = '\0'; + plist = lptr; + while (plist != 0) { + if (strcmp(plist->reqFile, msg.requestfilename) == 0) break; + plist = plist->pnext; + } + if (plist) { + /* fetch values all of the channels */ + plist->not_connected = get_channel_values(plist); + num_errs += plist->not_connected; + + /* write the data to disk */ + if ((plist->not_connected == 0) || (save_restoreIncompleteSetsOk)) + status = write_save_file(plist, msg.filename, fullPath); + if (save_restoreDebug > 1) + printf("save_restore: op_SaveFile: write_save_file() returned %d\n", status); + } + unlockList(); + if (status == 0) { status = do_asVerify(fullPath, -1, save_restoreDebug, 0, ""); } + + if (save_restoreDebug > 1) printf("save_restore: manual save status=%d (0==success)\n", status); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Save of '%s' %s", + status ? msg.filename : (plist ? plist->save_file : ""), + status ? "Failed" : "Succeeded"); + if (!status && num_errs) status = num_errs; + if (msg.callbackFunction) (msg.callbackFunction)(status, msg.puserPvt); + break; + + case op_asVerify: + if (save_restoreDebug) printf("save_restore task: calling do_asVerify('%s')\n", msg.filename); + if (!isAbsolute(msg.filename)) { + makeNfsPath(fullPath, saveRestoreFilePath, msg.filename); + } else { + strNcpy(fullPath, msg.filename, NFS_PATH_LEN); + } + status = do_asVerify(fullPath, msg.verbose, save_restoreDebug, + (int)(msg.restoreFileName[0] != '\0'), msg.restoreFileName); + break; + + default: break; + } + ca_pend_event(0.001); + } + + /* Make sure MIN_DELAY has elapsed before we make next pass through the list */ + epicsTimeGetCurrent(&currTime); + timeDiff = epicsTimeDiffInSeconds(&currTime, &delayStart); + if (timeDiff < MIN_DELAY) ca_pend_event(timeDiff - MIN_DELAY); } - /* before exit, clear all CA channels */ + /* before exit, clear all CA channels */ shutdown: - ca_disconnect(); - if (save_restoreDebug) { - save_restoreShow(1); - printf("save_restore: exiting\n"); - } - epicsEventSignal(shutdownEvent); - return(OK); + ca_disconnect(); + if (save_restoreDebug) { + save_restoreShow(1); + printf("save_restore: exiting\n"); + } + epicsEventSignal(shutdownEvent); + return (OK); } - /* * connect all of the channels in a save set * @@ -1368,84 +1352,79 @@ STATIC int save_restore(void) */ STATIC int connect_list(struct chlist *plist, int verbose) { - struct channel *pchannel; - int n, m; - long status, field_size; - - strNcpy(plist->statusStr,"Connecting PVs...", STATUS_STR_LEN); - - /* connect all channels in the list */ - for (pchannel = plist->pchan_list, n=0; pchannel != 0; pchannel = pchannel->pnext) { - if (save_restoreDebug >= 10) - printf("save_restore:connect_list: channel '%s'\n", pchannel->name); - - if (!(pchannel->channel_connected)) { - /* printf("The chid of %s is %p\n", pchannel->name, pchannel->chid); */ - if (pchannel->chid) ca_clear_channel(pchannel->chid); /* qiao: release the channel, avoid duplicate resource allocation */ - if (ca_create_channel(pchannel->name, ca_connection_callback, (void *)pchannel, - CA_PRIORITY_DEFAULT, &pchannel->chid) == ECA_NORMAL) { - strNcpy(pchannel->value,"Search Issued", STRING_LEN); - pchannel->just_created = 1; - n++; - } else { - strNcpy(pchannel->value,"Search Failed", STRING_LEN); - } - } - } - if (ca_pend_io(MAX(5.0, n * 0.01)) == ECA_TIMEOUT) { - printf("save_restore:connect_list: not all searches successful\n"); - } + struct channel *pchannel; + int n, m; + long status, field_size; + + strNcpy(plist->statusStr, "Connecting PVs...", STATUS_STR_LEN); + + /* connect all channels in the list */ + for (pchannel = plist->pchan_list, n = 0; pchannel != 0; pchannel = pchannel->pnext) { + if (save_restoreDebug >= 10) printf("save_restore:connect_list: channel '%s'\n", pchannel->name); + + if (!(pchannel->channel_connected)) { + /* printf("The chid of %s is %p\n", pchannel->name, pchannel->chid); */ + if (pchannel->chid) + ca_clear_channel(pchannel->chid); /* qiao: release the channel, avoid duplicate resource allocation */ + if (ca_create_channel(pchannel->name, ca_connection_callback, (void *)pchannel, CA_PRIORITY_DEFAULT, + &pchannel->chid) == ECA_NORMAL) { + strNcpy(pchannel->value, "Search Issued", STRING_LEN); + pchannel->just_created = 1; + n++; + } else { + strNcpy(pchannel->value, "Search Failed", STRING_LEN); + } + } + } + if (ca_pend_io(MAX(5.0, n * 0.01)) == ECA_TIMEOUT) { + printf("save_restore:connect_list: not all searches successful\n"); + } - for (pchannel = plist->pchan_list, n=m=0; pchannel != 0; pchannel = pchannel->pnext) { - if (!(pchannel->just_created)) - continue; - - /* check newly created channels */ - pchannel->just_created = 0; - m++; /* number of newly created channels */ - - if (pchannel->chid) { - if (ca_state(pchannel->chid) == cs_conn) { - strNcpy(pchannel->value,"Connected", STRING_LEN); - n++; - } else { - if (verbose) { - printf("save_restore: connect failed for channel '%s'\n", pchannel->name); - } - } - } - - pchannel->max_elements = ca_element_count(pchannel->chid); /* just to see if it's an array */ - pchannel->curr_elements = pchannel->max_elements; /* begin with this assumption */ - if (save_restoreDebug >= 10) - printf("save_restore:connect_list: '%s' has, at most, %ld elements\n", - pchannel->name, pchannel->max_elements); - if (pchannel->max_elements > 1) { - /* We use database access for arrays, so get that info */ - status = SR_get_array_info(pchannel->name, &pchannel->max_elements, &field_size, &pchannel->field_type); - if (status) { - pchannel->curr_elements = pchannel->max_elements = -1; - printf("save_restore:connect_list: array PV '%s' is not local.\n", pchannel->name); - } else { - /* info resulting from dbNameToAddr() might be different, but it's still not the actual element count */ - pchannel->curr_elements = pchannel->max_elements; - if (save_restoreDebug >= 10) - printf("save_restore:connect_list:(after SR_get_array_info) '%s' has, at most, %ld elements\n", - pchannel->name, pchannel->max_elements); - pchannel->pArray = calloc(pchannel->max_elements, field_size); - if (pchannel->pArray == NULL) { - printf("save_restore:connect_list: can't alloc array for '%s'\n", pchannel->name); - pchannel->curr_elements = pchannel->max_elements = -1; - } - } - } - } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "%s: %d of %d PV's connected", plist->save_file, n, m); - if (verbose) { - printf("%s\n", SR_recentlyStr); - } + for (pchannel = plist->pchan_list, n = m = 0; pchannel != 0; pchannel = pchannel->pnext) { + if (!(pchannel->just_created)) continue; + + /* check newly created channels */ + pchannel->just_created = 0; + m++; /* number of newly created channels */ + + if (pchannel->chid) { + if (ca_state(pchannel->chid) == cs_conn) { + strNcpy(pchannel->value, "Connected", STRING_LEN); + n++; + } else { + if (verbose) { printf("save_restore: connect failed for channel '%s'\n", pchannel->name); } + } + } + + pchannel->max_elements = ca_element_count(pchannel->chid); /* just to see if it's an array */ + pchannel->curr_elements = pchannel->max_elements; /* begin with this assumption */ + if (save_restoreDebug >= 10) + printf("save_restore:connect_list: '%s' has, at most, %ld elements\n", pchannel->name, + pchannel->max_elements); + if (pchannel->max_elements > 1) { + /* We use database access for arrays, so get that info */ + status = SR_get_array_info(pchannel->name, &pchannel->max_elements, &field_size, &pchannel->field_type); + if (status) { + pchannel->curr_elements = pchannel->max_elements = -1; + printf("save_restore:connect_list: array PV '%s' is not local.\n", pchannel->name); + } else { + /* info resulting from dbNameToAddr() might be different, but it's still not the actual element count */ + pchannel->curr_elements = pchannel->max_elements; + if (save_restoreDebug >= 10) + printf("save_restore:connect_list:(after SR_get_array_info) '%s' has, at most, %ld elements\n", + pchannel->name, pchannel->max_elements); + pchannel->pArray = calloc(pchannel->max_elements, field_size); + if (pchannel->pArray == NULL) { + printf("save_restore:connect_list: can't alloc array for '%s'\n", pchannel->name); + pchannel->curr_elements = pchannel->max_elements = -1; + } + } + } + } + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "%s: %d of %d PV's connected", plist->save_file, n, m); + if (verbose) { printf("%s\n", SR_recentlyStr); } - return(get_channel_values(plist)); + return (get_channel_values(plist)); } /** @@ -1453,42 +1432,41 @@ STATIC int connect_list(struct chlist *plist, int verbose) */ STATIC void ca_disconnect() { - struct chlist *plist = NULL; - struct channel *pchannel = NULL; + struct chlist *plist = NULL; + struct channel *pchannel = NULL; - /* disconnect all channels in the data set */ - plist = lptr; + /* disconnect all channels in the data set */ + plist = lptr; - while (plist != 0) { - /* disconnect all channels in the data list */ - for (pchannel = plist -> pchan_list; pchannel != 0; pchannel = pchannel -> pnext) - if (pchannel->chid) ca_clear_channel(pchannel->chid); + while (plist != 0) { + /* disconnect all channels in the data list */ + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) + if (pchannel->chid) ca_clear_channel(pchannel->chid); - /* disconnect the data list specific PVs */ - if(plist->savePathPV_chid) ca_clear_channel(plist->savePathPV_chid); - if(plist->saveNamePV_chid) ca_clear_channel(plist->saveNamePV_chid); + /* disconnect the data list specific PVs */ + if (plist->savePathPV_chid) ca_clear_channel(plist->savePathPV_chid); + if (plist->saveNamePV_chid) ca_clear_channel(plist->saveNamePV_chid); - if(plist->status_chid) ca_clear_channel(plist->status_chid); - if(plist->name_chid) ca_clear_channel(plist->name_chid); - if(plist->save_state_chid) ca_clear_channel(plist->save_state_chid); - if(plist->statusStr_chid) ca_clear_channel(plist->statusStr_chid); - if(plist->time_chid) ca_clear_channel(plist->time_chid); + if (plist->status_chid) ca_clear_channel(plist->status_chid); + if (plist->name_chid) ca_clear_channel(plist->name_chid); + if (plist->save_state_chid) ca_clear_channel(plist->save_state_chid); + if (plist->statusStr_chid) ca_clear_channel(plist->statusStr_chid); + if (plist->time_chid) ca_clear_channel(plist->time_chid); - /* next list */ - plist = plist->pnext; - } + /* next list */ + plist = plist->pnext; + } - /* disconnect the global level channels */ - if(SR_heartbeat_chid) ca_clear_channel(SR_heartbeat_chid); - if(SR_recentlyStr_chid) ca_clear_channel(SR_recentlyStr_chid); - if(SR_status_chid) ca_clear_channel(SR_status_chid); - if(SR_statusStr_chid) ca_clear_channel(SR_statusStr_chid); - if(SR_rebootStatus_chid) ca_clear_channel(SR_rebootStatus_chid); - if(SR_rebootStatusStr_chid) ca_clear_channel(SR_rebootStatusStr_chid); - if(SR_rebootTime_chid) ca_clear_channel(SR_rebootTime_chid); + /* disconnect the global level channels */ + if (SR_heartbeat_chid) ca_clear_channel(SR_heartbeat_chid); + if (SR_recentlyStr_chid) ca_clear_channel(SR_recentlyStr_chid); + if (SR_status_chid) ca_clear_channel(SR_status_chid); + if (SR_statusStr_chid) ca_clear_channel(SR_statusStr_chid); + if (SR_rebootStatus_chid) ca_clear_channel(SR_rebootStatus_chid); + if (SR_rebootStatusStr_chid) ca_clear_channel(SR_rebootStatusStr_chid); + if (SR_rebootTime_chid) ca_clear_channel(SR_rebootTime_chid); } - /* * enable new save methods * @@ -1496,74 +1474,69 @@ STATIC void ca_disconnect() */ STATIC int enable_list(struct chlist *plist) { - struct channel *pchannel; - chid chid; /* channel access id */ + struct channel *pchannel; + chid chid; /* channel access id */ - if (save_restoreDebug >= 4) printf("save_restore:enable_list: entry\n"); - strNcpy(plist->statusStr,"Enabling list...", STATUS_STR_LEN); + if (save_restoreDebug >= 4) printf("save_restore:enable_list: entry\n"); + strNcpy(plist->statusStr, "Enabling list...", STATUS_STR_LEN); - /* enable a periodic set */ - if ((plist->save_method & PERIODIC) && !(plist->enabled_method & PERIODIC)) { - callbackRequestDelayed(&plist->periodicCb, (double)plist->period); - plist->enabled_method |= PERIODIC; - epicsTimeGetCurrent(&plist->callback_time); - } + /* enable a periodic set */ + if ((plist->save_method & PERIODIC) && !(plist->enabled_method & PERIODIC)) { + callbackRequestDelayed(&plist->periodicCb, (double)plist->period); + plist->enabled_method |= PERIODIC; + epicsTimeGetCurrent(&plist->callback_time); + } - /* enable a triggered set */ - if ((plist->save_method & TRIGGERED) && !(plist->enabled_method & TRIGGERED)) { - if (ca_search(plist->trigger_channel, &chid) != ECA_NORMAL) { - printf("save_restore:enable_list: trigger %s search failed\n", plist->trigger_channel); - } else if (ca_pend_io(2.0) != ECA_NORMAL) { - printf("save_restore:enable_list: timeout on search of %s\n", plist->trigger_channel); - } else if (chid == NULL) { - printf("save_restore:enable_list: no CHID for trigger channel '%s'\n", plist->trigger_channel); - } else if (ca_state(chid) != cs_conn) { - printf("save_restore:enable_list: trigger %s search not connected\n", plist->trigger_channel); - } else if (ca_add_event(DBR_FLOAT, chid, triggered_save, (void *)plist, 0) !=ECA_NORMAL) { - printf("save_restore:enable_list: trigger event for %s failed\n", plist->trigger_channel); - } else{ - plist->enabled_method |= TRIGGERED; - } - } + /* enable a triggered set */ + if ((plist->save_method & TRIGGERED) && !(plist->enabled_method & TRIGGERED)) { + if (ca_search(plist->trigger_channel, &chid) != ECA_NORMAL) { + printf("save_restore:enable_list: trigger %s search failed\n", plist->trigger_channel); + } else if (ca_pend_io(2.0) != ECA_NORMAL) { + printf("save_restore:enable_list: timeout on search of %s\n", plist->trigger_channel); + } else if (chid == NULL) { + printf("save_restore:enable_list: no CHID for trigger channel '%s'\n", plist->trigger_channel); + } else if (ca_state(chid) != cs_conn) { + printf("save_restore:enable_list: trigger %s search not connected\n", plist->trigger_channel); + } else if (ca_add_event(DBR_FLOAT, chid, triggered_save, (void *)plist, 0) != ECA_NORMAL) { + printf("save_restore:enable_list: trigger event for %s failed\n", plist->trigger_channel); + } else { + plist->enabled_method |= TRIGGERED; + } + } - /* enable a monitored set */ - if ((plist->save_method & MONITORED) && !(plist->enabled_method & MONITORED)) { - for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { - if (save_restoreDebug >= 10) { - printf("save_restore:enable_list: calling ca_add_event for '%s'\n", pchannel->name); - printf("save_restore:enable_list: arg = %p\n", (void *)plist); - } - /* + /* enable a monitored set */ + if ((plist->save_method & MONITORED) && !(plist->enabled_method & MONITORED)) { + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + if (save_restoreDebug >= 10) { + printf("save_restore:enable_list: calling ca_add_event for '%s'\n", pchannel->name); + printf("save_restore:enable_list: arg = %p\n", (void *)plist); + } + /* * Work around obscure problem affecting USHORTS by making DBR type different * from any possible field type. This avoids tickling a bug that causes dbGet * to overwrite the source field with its own value converted to LONG. * (Changed DBR_LONG to DBR_TIME_LONG.) */ - if (ca_add_event(DBR_TIME_LONG, pchannel->chid, on_change_save, - (void *)plist, 0) != ECA_NORMAL) { - printf("save_restore:enable_list: could not add event for %s in %s\n", - pchannel->name,plist->reqFile); - } - } - if (save_restoreDebug >= 4) printf("save_restore:enable_list: done calling ca_add_event for list channels\n"); - if (ca_pend_io(5.0) != ECA_NORMAL) { - printf("save_restore:enable_list: timeout on monitored set: %s to monitored scan\n",plist->reqFile); - } - callbackRequestDelayed(&plist->monitorCb, (double)plist->monitor_period); - plist->enabled_method |= MONITORED; - epicsTimeGetCurrent(&plist -> callback_time); - } + if (ca_add_event(DBR_TIME_LONG, pchannel->chid, on_change_save, (void *)plist, 0) != ECA_NORMAL) { + printf("save_restore:enable_list: could not add event for %s in %s\n", pchannel->name, plist->reqFile); + } + } + if (save_restoreDebug >= 4) printf("save_restore:enable_list: done calling ca_add_event for list channels\n"); + if (ca_pend_io(5.0) != ECA_NORMAL) { + printf("save_restore:enable_list: timeout on monitored set: %s to monitored scan\n", plist->reqFile); + } + callbackRequestDelayed(&plist->monitorCb, (double)plist->monitor_period); + plist->enabled_method |= MONITORED; + epicsTimeGetCurrent(&plist->callback_time); + } - /* enable a manual request set */ - if ((plist->save_method & MANUAL) && !(plist->enabled_method & MANUAL)) { - plist->enabled_method |= MANUAL; - } + /* enable a manual request set */ + if ((plist->save_method & MANUAL) && !(plist->enabled_method & MANUAL)) { plist->enabled_method |= MANUAL; } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "list '%s' enabled", plist->save_file); - return(OK); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "list '%s' enabled", plist->save_file); + return (OK); } - /* * fetch values for all channels in the save set * @@ -1572,162 +1545,165 @@ STATIC int enable_list(struct chlist *plist) #define INIT_STRING "!@#$%^&*()" STATIC int get_channel_values(struct chlist *plist) { + struct channel *pchannel; + int not_connected = 0; + unsigned short num_channels = 0; + short field_type; + long status, field_size; + float *pf; + double *pd; + + /* attempt to fetch all channels that are connected */ + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + pchannel->valid = 0; + + /* Handle channels whose element count has not yet been determined. */ + if (pchannel->chid && (ca_state(pchannel->chid) == cs_conn) && (pchannel->max_elements == 0)) { + /* Channel probably wasn't connected when connect_list() was called */ + pchannel->max_elements = pchannel->curr_elements = ca_element_count(pchannel->chid); + if (pchannel->max_elements > 1) { + status = SR_get_array_info(pchannel->name, &pchannel->max_elements, &field_size, &pchannel->field_type); + if (status) { + pchannel->curr_elements = pchannel->max_elements = -1; /* Mark channel so we ignore it forever. */ + printf("save_restore:get_channel_values: array PV '%s' is not local.\n", pchannel->name); + } else { + /* info resulting from dbNameToAddr() might be different, but it's still not the actual element count */ + pchannel->curr_elements = pchannel->max_elements; + if (save_restoreDebug >= 10) + printf( + "save_restore:get_channel_values:(after SR_get_array_info) '%s' has, at most, %ld " + "elements\n", + pchannel->name, pchannel->max_elements); + pchannel->pArray = calloc(pchannel->max_elements, field_size); + if (pchannel->pArray == NULL) { + printf("save_restore:get_channel_values: can't alloc array for '%s'\n", pchannel->name); + pchannel->curr_elements = pchannel->max_elements = + -1; /* Mark channel so we ignore it forever. */ + } + } + } + } - struct channel *pchannel; - int not_connected = 0; - unsigned short num_channels = 0; - short field_type; - long status, field_size; - float *pf; - double *pd; - - /* attempt to fetch all channels that are connected */ - for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { - pchannel->valid = 0; - - /* Handle channels whose element count has not yet been determined. */ - if (pchannel->chid && (ca_state(pchannel->chid) == cs_conn) && (pchannel->max_elements == 0)) { - /* Channel probably wasn't connected when connect_list() was called */ - pchannel->max_elements = pchannel->curr_elements = ca_element_count(pchannel->chid); - if (pchannel->max_elements > 1) { - status = SR_get_array_info(pchannel->name, &pchannel->max_elements, &field_size, &pchannel->field_type); - if (status) { - pchannel->curr_elements = pchannel->max_elements = -1; /* Mark channel so we ignore it forever. */ - printf("save_restore:get_channel_values: array PV '%s' is not local.\n", pchannel->name); - } else { - /* info resulting from dbNameToAddr() might be different, but it's still not the actual element count */ - pchannel->curr_elements = pchannel->max_elements; - if (save_restoreDebug >= 10) - printf("save_restore:get_channel_values:(after SR_get_array_info) '%s' has, at most, %ld elements\n", - pchannel->name, pchannel->max_elements); - pchannel->pArray = calloc(pchannel->max_elements, field_size); - if (pchannel->pArray == NULL) { - printf("save_restore:get_channel_values: can't alloc array for '%s'\n", pchannel->name); - pchannel->curr_elements = pchannel->max_elements = -1; /* Mark channel so we ignore it forever. */ - } - } - } - } - - if (pchannel->chid && (ca_state(pchannel->chid) == cs_conn) && (pchannel->max_elements >= 1)) { - field_type = ca_field_type(pchannel->chid); - strNcpy(pchannel->value, INIT_STRING, STRING_LEN); - if (field_type == DBF_FLOAT) { - ca_array_get(DBR_FLOAT,1,pchannel->chid,(float *)pchannel->value); - } else if (field_type == DBF_DOUBLE) { - ca_array_get(DBR_DOUBLE,1,pchannel->chid,(double *)pchannel->value); - } else { - ca_array_get(DBR_STRING,1,pchannel->chid,pchannel->value); - } - if (field_type == DBF_ENUM) { - ca_array_get(DBR_SHORT,1,pchannel->chid,&pchannel->enum_val); - num_channels++; - } - num_channels++; - pchannel->valid = 1; - if (pchannel->max_elements > 1) { - pchannel->curr_elements = pchannel->max_elements; - (void)SR_get_array(pchannel->name, pchannel->pArray, &pchannel->curr_elements); - } - if (save_restoreDebug >= 15) { - printf("save_restore:get_channel_values: '%s' currently has %ld elements\n", - pchannel->name, pchannel->curr_elements); - } - } else { - not_connected++; - if (pchannel->chid == NULL) { - if (save_restoreDebug > 1) printf("save_restore:get_channel_values: no CHID for '%s'\n", pchannel->name); - } else if (ca_state(pchannel->chid) != cs_conn) { - if (save_restoreDebug > 1) printf("save_restore:get_channel_values: %s not connected\n", pchannel->name); - } else if (pchannel->max_elements == 0) { - if (save_restoreDebug > 1) printf("save_restore:get_channel_values: %s has an undetermined # elements\n", - pchannel->name); - } else if (pchannel->max_elements == -1) { - if (save_restoreDebug > 1) printf("save_restore:get_channel_values: %s has a serious problem\n", - pchannel->name); - } - - } - } - if (ca_pend_io(MIN(10.0, .1*num_channels)) != ECA_NORMAL) { - printf("save_restore:get_channel_values: not all gets completed"); - not_connected++; - } + if (pchannel->chid && (ca_state(pchannel->chid) == cs_conn) && (pchannel->max_elements >= 1)) { + field_type = ca_field_type(pchannel->chid); + strNcpy(pchannel->value, INIT_STRING, STRING_LEN); + if (field_type == DBF_FLOAT) { + ca_array_get(DBR_FLOAT, 1, pchannel->chid, (float *)pchannel->value); + } else if (field_type == DBF_DOUBLE) { + ca_array_get(DBR_DOUBLE, 1, pchannel->chid, (double *)pchannel->value); + } else { + ca_array_get(DBR_STRING, 1, pchannel->chid, pchannel->value); + } + if (field_type == DBF_ENUM) { + ca_array_get(DBR_SHORT, 1, pchannel->chid, &pchannel->enum_val); + num_channels++; + } + num_channels++; + pchannel->valid = 1; + if (pchannel->max_elements > 1) { + pchannel->curr_elements = pchannel->max_elements; + (void)SR_get_array(pchannel->name, pchannel->pArray, &pchannel->curr_elements); + } + if (save_restoreDebug >= 15) { + printf("save_restore:get_channel_values: '%s' currently has %ld elements\n", pchannel->name, + pchannel->curr_elements); + } + } else { + not_connected++; + if (pchannel->chid == NULL) { + if (save_restoreDebug > 1) + printf("save_restore:get_channel_values: no CHID for '%s'\n", pchannel->name); + } else if (ca_state(pchannel->chid) != cs_conn) { + if (save_restoreDebug > 1) + printf("save_restore:get_channel_values: %s not connected\n", pchannel->name); + } else if (pchannel->max_elements == 0) { + if (save_restoreDebug > 1) + printf("save_restore:get_channel_values: %s has an undetermined # elements\n", pchannel->name); + } else if (pchannel->max_elements == -1) { + if (save_restoreDebug > 1) + printf("save_restore:get_channel_values: %s has a serious problem\n", pchannel->name); + } + } + } + if (ca_pend_io(MIN(10.0, .1 * num_channels)) != ECA_NORMAL) { + printf("save_restore:get_channel_values: not all gets completed"); + not_connected++; + } - /* convert floats and doubles, check to see which get's completed */ - for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { - if (pchannel->valid) { - if (ca_field_type(pchannel->chid) == DBF_FLOAT) { - pf = (float *)pchannel->value; - epicsSnprintf(pchannel->value, 63, FLOAT_FMT, *pf); - } else if (ca_field_type(pchannel->chid) == DBF_DOUBLE) { - pd = (double *)pchannel->value; - epicsSnprintf(pchannel->value, 63, DOUBLE_FMT, *pd); - } - /* then we at least had a CA connection. Did it produce? */ - pchannel->valid = strcmp(pchannel->value, INIT_STRING); - } else { - if (save_restoreDebug > 1) printf("save_restore:get_channel_values: invalid channel %s\n", pchannel->name); - } - } + /* convert floats and doubles, check to see which get's completed */ + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + if (pchannel->valid) { + if (ca_field_type(pchannel->chid) == DBF_FLOAT) { + pf = (float *)pchannel->value; + epicsSnprintf(pchannel->value, 63, FLOAT_FMT, *pf); + } else if (ca_field_type(pchannel->chid) == DBF_DOUBLE) { + pd = (double *)pchannel->value; + epicsSnprintf(pchannel->value, 63, DOUBLE_FMT, *pd); + } + /* then we at least had a CA connection. Did it produce? */ + pchannel->valid = strcmp(pchannel->value, INIT_STRING); + } else { + if (save_restoreDebug > 1) printf("save_restore:get_channel_values: invalid channel %s\n", pchannel->name); + } + } - return(not_connected); + return (not_connected); } /* state of a backup restore file */ -#define BS_NONE 0 /* Couldn't open the file */ -#define BS_BAD 1 /* File exists but looks corrupted */ -#define BS_OK 2 /* File is good */ -#define BS_NEW 3 /* Just wrote the file */ +#define BS_NONE 0 /* Couldn't open the file */ +#define BS_BAD 1 /* File exists but looks corrupted */ +#define BS_OK 2 /* File is good */ +#define BS_NEW 3 /* Just wrote the file */ STATIC int check_file(char *file) { - FILE *fd; - char tmpstr[20]; - int file_state = BS_NONE; - - if ((fd = fopen(file, "r")) != NULL) { - if (fseek(fd, -7, SEEK_END)) { - printf("save_restore:check_file: seek failed\n"); - file_state = BS_BAD; - fclose(fd); - return(file_state); - } - if (fgets(tmpstr, 7, fd) == 0) { - printf("save_restore:check_file: fgets failed\n"); - file_state = BS_BAD; - fclose(fd); - return(file_state); - } - if (save_restoreDebug >= 5) printf("save_restore:check_file: tmpstr='%s'\n", tmpstr); - if (strncmp(tmpstr, "", 5) == 0) { - file_state = BS_OK; - fclose(fd); - return(file_state); - } - - if (fseek(fd, -6, SEEK_END)) { - printf("save_restore:check_file: seek failed\n"); - file_state = BS_BAD; - fclose(fd); - return(file_state); - } - if (fgets(tmpstr, 6, fd) == 0) { - printf("save_restore:check_file: fgets failed\n"); - file_state = BS_BAD; - fclose(fd); - return(file_state); - } - if (save_restoreDebug >= 5) printf("save_restore:check_file: tmpstr='%s'\n", tmpstr); - if (strncmp(tmpstr, "", 5) == 0) { - file_state = BS_OK; - fclose(fd); - return(file_state); - } - file_state = BS_BAD; - fclose(fd); - } - return(file_state); + FILE *fd; + char tmpstr[20]; + int file_state = BS_NONE; + + if ((fd = fopen(file, "r")) != NULL) { + if (fseek(fd, -7, SEEK_END)) { + printf("save_restore:check_file: seek failed\n"); + file_state = BS_BAD; + fclose(fd); + return (file_state); + } + if (fgets(tmpstr, 7, fd) == 0) { + printf("save_restore:check_file: fgets failed\n"); + file_state = BS_BAD; + fclose(fd); + return (file_state); + } + if (save_restoreDebug >= 5) printf("save_restore:check_file: tmpstr='%s'\n", tmpstr); + if (strncmp(tmpstr, "", 5) == 0) { + file_state = BS_OK; + fclose(fd); + return (file_state); + } + + if (fseek(fd, -6, SEEK_END)) { + printf("save_restore:check_file: seek failed\n"); + file_state = BS_BAD; + fclose(fd); + return (file_state); + } + if (fgets(tmpstr, 6, fd) == 0) { + printf("save_restore:check_file: fgets failed\n"); + file_state = BS_BAD; + fclose(fd); + return (file_state); + } + if (save_restoreDebug >= 5) printf("save_restore:check_file: tmpstr='%s'\n", tmpstr); + if (strncmp(tmpstr, "", 5) == 0) { + file_state = BS_OK; + fclose(fd); + return (file_state); + } + file_state = BS_BAD; + fclose(fd); + } + return (file_state); } /* @@ -1736,180 +1712,177 @@ STATIC int check_file(char *file) */ void print_chmod_error(int errNumber) { - char shortMessage[100]; - char longMessage[3000]; - - switch (errNumber) { - case EBADF: - strcpy(shortMessage, "EBADF: Descriptor is not valid."); - strcpy(longMessage, "A file descriptor argument was out of range, referred to a file that was not open, or a read or write request was made to a file that is not open for that operation."); - break; - - case EPERM: - strcpy(shortMessage, "EPERM: The operation is not permitted."); - strcpy(longMessage, "You must have appropriate privileges or be the owner of the object or other resource to do the requested operation."); - break; - - case EROFS: - strcpy(shortMessage, "EROFS: Read-only file system."); - strcpy(longMessage, "You have attempted an update operation in a file system that only supports read operations."); - break; - - case EINTR: - strcpy(shortMessage, "EINTR: Interrupted function call."); - strcpy(longMessage, "The function was interrupted by a signal."); - break; - - case EINVAL: - strcpy(shortMessage, "EINVAL: The value specified for the argument is not correct."); - strcpy(longMessage, "A function was passed incorrect argument values, or an operation was attempted on an object and the operation specified is not supported for that type of object."); - } + char shortMessage[100]; + char longMessage[3000]; + + switch (errNumber) { + case EBADF: + strcpy(shortMessage, "EBADF: Descriptor is not valid."); + strcpy(longMessage, + "A file descriptor argument was out of range, referred to a file that was not open, or a read or " + "write request was made to a file that is not open for that operation."); + break; + + case EPERM: + strcpy(shortMessage, "EPERM: The operation is not permitted."); + strcpy(longMessage, + "You must have appropriate privileges or be the owner of the object or other resource to do the " + "requested operation."); + break; + + case EROFS: + strcpy(shortMessage, "EROFS: Read-only file system."); + strcpy(longMessage, + "You have attempted an update operation in a file system that only supports read operations."); + break; + + case EINTR: + strcpy(shortMessage, "EINTR: Interrupted function call."); + strcpy(longMessage, "The function was interrupted by a signal."); + break; + + case EINVAL: + strcpy(shortMessage, "EINVAL: The value specified for the argument is not correct."); + strcpy(longMessage, + "A function was passed incorrect argument values, or an operation was attempted on an object and " + "the operation specified is not supported for that type of object."); + } - printf("Error %d - %s\n%s\n", errNumber, shortMessage, longMessage); + printf("Error %d - %s\n%s\n", errNumber, shortMessage, longMessage); } - /* * Actually write the file * * NOTE: Assumes sr_mutex is locked * */ -#define FPRINTF_FAILED 1 -#define CLOSE_FAILED 2 +#define FPRINTF_FAILED 1 +#define CLOSE_FAILED 2 STATIC int write_it(char *filename, struct chlist *plist) { - FILE *out_fd; - int filedes = -1; - struct channel *pchannel; - int n, problem = 0; - char datetime[32]; - int file_check; - double delta_time; - struct stat fileStat; /* qiao: file state */ - char realName[PV_NAME_LEN]; /* name without trailing '$' */ - int is_long_string; - char value_string[BUF_SIZE]; - - fGetDateStr(datetime); - - /* open the file */ - errno = 0; + FILE *out_fd; + int filedes = -1; + struct channel *pchannel; + int n, problem = 0; + char datetime[32]; + int file_check; + double delta_time; + struct stat fileStat; /* qiao: file state */ + char realName[PV_NAME_LEN]; /* name without trailing '$' */ + int is_long_string; + char value_string[BUF_SIZE]; + + fGetDateStr(datetime); + + /* open the file */ + errno = 0; #if SET_FILE_PERMISSIONS - /* Note: must truncate, else file retains old characters when its used length decreases. */ - filedes = open(filename, O_RDWR | O_CREAT | O_TRUNC, file_permissions); - if (filedes < 0) { - printf("save_restore:write_it - unable to open file '%s' [%s]\n", - filename, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - if (++save_restoreIoErrors > save_restoreRemountThreshold) { - save_restoreNFSOK = 0; - strNcpy(SR_recentlyStr, "Too many I/O errors",STATUS_STR_LEN); - } - return(ERROR); - } else { - if (mustSetPermissions) { - int status; - /* open() doesn't seem to set file permissions anymore */ - status = fchmod (filedes, (mode_t) file_permissions); - if (status) { - int err = errno; - printf("write_it - when changing %s file permission:\n", filename); - print_chmod_error(err); - } - } - out_fd = fdopen(filedes, "w"); - } + /* Note: must truncate, else file retains old characters when its used length decreases. */ + filedes = open(filename, O_RDWR | O_CREAT | O_TRUNC, file_permissions); + if (filedes < 0) { + printf("save_restore:write_it - unable to open file '%s' [%s]\n", filename, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + if (++save_restoreIoErrors > save_restoreRemountThreshold) { + save_restoreNFSOK = 0; + strNcpy(SR_recentlyStr, "Too many I/O errors", STATUS_STR_LEN); + } + return (ERROR); + } else { + if (mustSetPermissions) { + int status; + /* open() doesn't seem to set file permissions anymore */ + status = fchmod(filedes, (mode_t)file_permissions); + if (status) { + int err = errno; + printf("write_it - when changing %s file permission:\n", filename); + print_chmod_error(err); + } + } + out_fd = fdopen(filedes, "w"); + } #else - if ((out_fd = fopen(filename,"w")) == NULL) { - printf("save_restore:write_it - unable to open file '%s' [%s]\n", - filename, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - if (++save_restoreIoErrors > save_restoreRemountThreshold) { - save_restoreNFSOK = 0; - strNcpy(SR_recentlyStr, "Too many I/O errors",STATUS_STR_LEN); - } - return(ERROR); - } + if ((out_fd = fopen(filename, "w")) == NULL) { + printf("save_restore:write_it - unable to open file '%s' [%s]\n", filename, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + if (++save_restoreIoErrors > save_restoreRemountThreshold) { + save_restoreNFSOK = 0; + strNcpy(SR_recentlyStr, "Too many I/O errors", STATUS_STR_LEN); + } + return (ERROR); + } #endif + /* write header info */ + errno = 0; + n = fprintf(out_fd, "# %s\tAutomatically generated - DO NOT MODIFY - %s\n", SRversion, datetime); + if (n <= 0) { + printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= FPRINTF_FAILED; + goto trouble; + } - /* write header info */ - errno = 0; - n = fprintf(out_fd,"# %s\tAutomatically generated - DO NOT MODIFY - %s\n", - SRversion, datetime); - if (n <= 0) { - printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= FPRINTF_FAILED; - goto trouble; - } + if (plist->not_connected) { + errno = 0; + n = fprintf(out_fd, "! %d channel(s) not connected - or not all gets were successful\n", plist->not_connected); + if (n <= 0) { + printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= FPRINTF_FAILED; + goto trouble; + } + } - if (plist->not_connected) { - errno = 0; - n = fprintf(out_fd,"! %d channel(s) not connected - or not all gets were successful\n", - plist->not_connected); - if (n <= 0) { - printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= FPRINTF_FAILED; - goto trouble; - } - } + /* write PV names and values */ + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + errno = 0; + is_long_string = 0; + strNcpy(realName, pchannel->name, PV_NAME_LEN); + if (realName[strlen(realName) - 1] == '$') { + realName[strlen(realName) - 1] = '\0'; + is_long_string = 1; + } + if (pchannel->valid) { + n = fprintf(out_fd, "%s ", pchannel->name); + } else { + n = fprintf(out_fd, "#%s ", pchannel->name); + } + if (n <= 0) { + printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= FPRINTF_FAILED; + goto trouble; + } - /* write PV names and values */ - for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { - errno = 0; - is_long_string = 0; - strNcpy(realName, pchannel->name, PV_NAME_LEN); - if (realName[strlen(realName)-1] == '$') { - realName[strlen(realName)-1] = '\0'; - is_long_string = 1; - } - if (pchannel->valid) { - n = fprintf(out_fd, "%s ", pchannel->name); - } else { - n = fprintf(out_fd, "#%s ", pchannel->name); - } - if (n <= 0) { - printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= FPRINTF_FAILED; - goto trouble; - } - - errno = 0; - if (is_long_string) { - /* write first BUF-SIZE-1 characters of long string, so dbrestore doesn't choke. */ - strNcpy(value_string, pchannel->pArray, BUF_SIZE); - value_string[BUF_SIZE-1] = '\0'; - n = epicsStrPrintEscaped(out_fd, value_string, strlen(value_string)); - if (n > 0 || !strlen(value_string)) { - n = fprintf(out_fd, "\n"); - } - } else if (pchannel->curr_elements <= 1) { - /* treat as scalar */ - if (pchannel->enum_val >= 0) { - n = fprintf(out_fd, "%d\n",pchannel->enum_val); - } else { - n = epicsStrPrintEscaped(out_fd, pchannel->value, strlen(pchannel->value)); - if (n > 0 || !strlen(pchannel->value)) { - n = fprintf(out_fd, "\n"); - } - } - } else { - /* treat as array */ - n = SR_write_array_data(out_fd, pchannel->name, (void *)pchannel->pArray, pchannel->curr_elements); - } - if (n <= 0) { - printf("save_restore:write_it: fprintf returned %d [%s].\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= FPRINTF_FAILED; - goto trouble; - } - } + errno = 0; + if (is_long_string) { + /* write first BUF-SIZE-1 characters of long string, so dbrestore doesn't choke. */ + strNcpy(value_string, pchannel->pArray, BUF_SIZE); + value_string[BUF_SIZE - 1] = '\0'; + n = epicsStrPrintEscaped(out_fd, value_string, strlen(value_string)); + if (n > 0 || !strlen(value_string)) { n = fprintf(out_fd, "\n"); } + } else if (pchannel->curr_elements <= 1) { + /* treat as scalar */ + if (pchannel->enum_val >= 0) { + n = fprintf(out_fd, "%d\n", pchannel->enum_val); + } else { + n = epicsStrPrintEscaped(out_fd, pchannel->value, strlen(pchannel->value)); + if (n > 0 || !strlen(pchannel->value)) { n = fprintf(out_fd, "\n"); } + } + } else { + /* treat as array */ + n = SR_write_array_data(out_fd, pchannel->name, (void *)pchannel->pArray, pchannel->curr_elements); + } + if (n <= 0) { + printf("save_restore:write_it: fprintf returned %d [%s].\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= FPRINTF_FAILED; + goto trouble; + } + } - /* debug: simulate task crash */ + /* debug: simulate task crash */ #if 0 if (save_restoreDebug == 999) { printf("save_restore: simulating task crash. Bye, bye!\n"); @@ -1917,107 +1890,108 @@ STATIC int write_it(char *filename, struct chlist *plist) } #endif - /* write file-is-ok marker */ - errno = 0; - n = fprintf(out_fd, "\n"); - if (n <= 0) { - printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= FPRINTF_FAILED; - goto trouble; - } - - /* flush everything to disk */ - errno = 0; - n = fflush(out_fd); - if (n) { - printf("save_restore:write_it: fflush returned %d [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - } + /* write file-is-ok marker */ + errno = 0; + n = fprintf(out_fd, "\n"); + if (n <= 0) { + printf("save_restore:write_it: fprintf returned %d. [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= FPRINTF_FAILED; + goto trouble; + } + /* flush everything to disk */ + errno = 0; + n = fflush(out_fd); + if (n) { + printf("save_restore:write_it: fflush returned %d [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + } - errno = 0; + errno = 0; #if defined(vxWorks) - n = ioctl(fileno(out_fd),FIOSYNC,0); /* NFS flush to disk */ - if (n == ERROR) { - printf("save_restore:write_it: ioctl(,FIOSYNC,) returned %d [%s]\n", - n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - } + n = ioctl(fileno(out_fd), FIOSYNC, 0); /* NFS flush to disk */ + if (n == ERROR) { + printf("save_restore:write_it: ioctl(,FIOSYNC,) returned %d [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + } #elif defined(_WIN32) - /* WIN32 has no real equivalent to fsync? */ + /* WIN32 has no real equivalent to fsync? */ #else - n = fsync(fileno(out_fd)); - if (n && (errno == ENOTSUP)) { n = 0; errno = 0; } + n = fsync(fileno(out_fd)); + if (n && (errno == ENOTSUP)) { + n = 0; + errno = 0; + } #ifdef __rtems__ - if (n && ((errno == EINVAL) || (errno == EROFS)) ) { n = 0; errno = 0; } + if (n && ((errno == EINVAL) || (errno == EROFS))) { + n = 0; + errno = 0; + } #endif - if (n) { - printf("save_restore:write_it: fsync returned %d [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - } + if (n) { + printf("save_restore:write_it: fsync returned %d [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + } #endif - /* close the file */ - errno = 0; - n = fclose(out_fd); - out_fd = NULL; - if (n) { - printf("save_restore:write_it: fclose returned %d [%s]\n", n, datetime); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - problem |= CLOSE_FAILED; - goto trouble; - } + /* close the file */ + errno = 0; + n = fclose(out_fd); + out_fd = NULL; + if (n) { + printf("save_restore:write_it: fclose returned %d [%s]\n", n, datetime); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + problem |= CLOSE_FAILED; + goto trouble; + } - /* qiao: check the file state: the file contents, file size and the save time of the file */ + /* qiao: check the file state: the file contents, file size and the save time of the file */ file_check = check_file(filename); - if (file_check != BS_OK) { - printf("save_restore:write_it: file-check failure [%s], check_file=%d\n", - datetime, file_check); - return(ERROR); - } + if (file_check != BS_OK) { + printf("save_restore:write_it: file-check failure [%s], check_file=%d\n", datetime, file_check); + return (ERROR); + } - stat(filename, &fileStat); - if (fileStat.st_size <= 0) { - printf("save_restore:write_it: unphysical file size [%s], size=%lld\n", - datetime, (long long)fileStat.st_size); - return(ERROR); - } + stat(filename, &fileStat); + if (fileStat.st_size <= 0) { + printf("save_restore:write_it: unphysical file size [%s], size=%lld\n", datetime, (long long)fileStat.st_size); + return (ERROR); + } delta_time = difftime(time(NULL), fileStat.st_mtime); - if (delta_time > 10.0) { - printf("save_restore:write_it: file time is different from IOC time [%s], difference=%fs\n", - datetime, delta_time); - return(ERROR); - } + if (delta_time > 10.0) { + printf("save_restore:write_it: file time is different from IOC time [%s], difference=%fs\n", datetime, + delta_time); + return (ERROR); + } - /* qiao: up to now, the file is successfully saved, which means the NFS is OK. So here clean up + /* qiao: up to now, the file is successfully saved, which means the NFS is OK. So here clean up the error flag for NFS, corresponding to the auto-recover of NFS */ - save_restoreNFSOK = 1; - save_restoreIoErrors = 0; + save_restoreNFSOK = 1; + save_restoreIoErrors = 0; - return(OK); + return (OK); trouble: - /* close the file */ - errno = 0; - if (out_fd) { - n = fclose(out_fd); - out_fd = NULL; - if (n) { - printf("save_restore:write_it: fclose('%s') returned %d\n", plist->save_file, n); - if (errno) myPrintErrno("write_it", __FILE__, __LINE__); - } else { - problem &= ~CLOSE_FAILED; - } - } - if (problem) { - fGetDateStr(datetime); - printf("save_restore:write_it: Giving up on this attempt to write '%s'. [%s]\n", - plist->save_file, datetime); - } + /* close the file */ + errno = 0; + if (out_fd) { + n = fclose(out_fd); + out_fd = NULL; + if (n) { + printf("save_restore:write_it: fclose('%s') returned %d\n", plist->save_file, n); + if (errno) myPrintErrno("write_it", __FILE__, __LINE__); + } else { + problem &= ~CLOSE_FAILED; + } + } + if (problem) { + fGetDateStr(datetime); + printf("save_restore:write_it: Giving up on this attempt to write '%s'. [%s]\n", plist->save_file, datetime); + } - return(problem ? ERROR : OK); + return (problem ? ERROR : OK); } /* @@ -2028,148 +2002,139 @@ STATIC int write_it(char *filename, struct chlist *plist) * NOTE: Assumes sr_mutex is locked * */ -#define TMPSTRLEN NFS_PATH_LEN+50 +#define TMPSTRLEN NFS_PATH_LEN + 50 STATIC int write_save_file(struct chlist *plist, const char *configName, char *retSaveFile) { - char save_file[NFS_PATH_LEN+3] = "", backup_file[NFS_PATH_LEN+3] = ""; - char tmpstr[TMPSTRLEN]; - int backup_state = BS_OK; - char datetime[32]; - - fGetDateStr(datetime); - plist->status = SR_STATUS_OK; - strcpy(plist->statusStr, "Ok"); - epicsTimeGetCurrent(&plist->save_attempt_time); - if (NULL != retSaveFile) { - retSaveFile[0] = '\0'; - } - - /* Make full file names */ - if (plist->savePathPV_chid) { - /* This list's path name comes from a PV */ - ca_array_get(DBR_STRING,1,plist->savePathPV_chid,tmpstr); - ca_pend_io(1.0); - if (tmpstr[0] == '\0') return(OK); - strNcpy(save_file, tmpstr, sizeof(save_file)); - if (!isAbsolute(save_file)) { - makeNfsPath(save_file, saveRestoreFilePath, save_file); - } - } else { - /* Use standard path name. */ - strNcpy(save_file, saveRestoreFilePath, sizeof(save_file)); - } - if (configName && configName[0]) { - makeNfsPath(save_file, save_file, configName); - } else if (plist->saveNamePV_chid) { - /* This list's file name comes from a PV */ - ca_array_get(DBR_STRING,1,plist->saveNamePV_chid,tmpstr); - ca_pend_io(1.0); - if (tmpstr[0] == '\0') return(OK); - makeNfsPath(save_file, save_file, tmpstr); - } else { - /* Use file name constructed from the request file name. */ - makeNfsPath(save_file, save_file, plist->save_file); - } + char save_file[NFS_PATH_LEN + 3] = "", backup_file[NFS_PATH_LEN + 3] = ""; + char tmpstr[TMPSTRLEN]; + int backup_state = BS_OK; + char datetime[32]; + + fGetDateStr(datetime); + plist->status = SR_STATUS_OK; + strcpy(plist->statusStr, "Ok"); + epicsTimeGetCurrent(&plist->save_attempt_time); + if (NULL != retSaveFile) { retSaveFile[0] = '\0'; } + + /* Make full file names */ + if (plist->savePathPV_chid) { + /* This list's path name comes from a PV */ + ca_array_get(DBR_STRING, 1, plist->savePathPV_chid, tmpstr); + ca_pend_io(1.0); + if (tmpstr[0] == '\0') return (OK); + strNcpy(save_file, tmpstr, sizeof(save_file)); + if (!isAbsolute(save_file)) { makeNfsPath(save_file, saveRestoreFilePath, save_file); } + } else { + /* Use standard path name. */ + strNcpy(save_file, saveRestoreFilePath, sizeof(save_file)); + } + if (configName && configName[0]) { + makeNfsPath(save_file, save_file, configName); + } else if (plist->saveNamePV_chid) { + /* This list's file name comes from a PV */ + ca_array_get(DBR_STRING, 1, plist->saveNamePV_chid, tmpstr); + ca_pend_io(1.0); + if (tmpstr[0] == '\0') return (OK); + makeNfsPath(save_file, save_file, tmpstr); + } else { + /* Use file name constructed from the request file name. */ + makeNfsPath(save_file, save_file, plist->save_file); + } - /* Currently, all lists do backups, unless their file path or file name comes from a PV, or the configName argument. */ - if (plist->do_backups && (configName==NULL)) { - strNcpy(backup_file, save_file, NFS_PATH_LEN); - strncat(backup_file, "B", NFS_PATH_LEN + 2 - strlen(backup_file)); - - /* Ensure that backup is ok before we overwrite .sav file. */ - backup_state = check_file(backup_file); - if (backup_state != BS_OK) { - printf("save_restore:write_save_file: Backup file (%s) bad or not found. Writing a new one. [%s]\n", - backup_file, datetime); - if (backup_state == BS_BAD) { - /* make a backup copy of the corrupted file */ - strNcpy(tmpstr, backup_file, TMPSTRLEN); - strncat(tmpstr, "_SBAD_", TMPSTRLEN-1-strlen(tmpstr)); - if (save_restoreDatedBackupFiles) { - strncat(tmpstr, datetime, TMPSTRLEN-1-strlen(tmpstr)); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Bad file: '%sB'", plist->save_file); - } - (void)myFileCopy(backup_file, tmpstr); - } - if (write_it(backup_file, plist) == ERROR) { - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - printf("save_restore:write_save_file: Can't write new backup file. [%s]\n", datetime); - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - plist->status = SR_STATUS_FAIL; - strNcpy(plist->statusStr, "Can't write .savB file", STATUS_STR_LEN); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - return(ERROR); - } - plist->status = SR_STATUS_WARN; - strNcpy(plist->statusStr, ".savB file was bad", STATUS_STR_LEN); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - backup_state = BS_NEW; - } - } + /* Currently, all lists do backups, unless their file path or file name comes from a PV, or the configName argument. */ + if (plist->do_backups && (configName == NULL)) { + strNcpy(backup_file, save_file, NFS_PATH_LEN); + strncat(backup_file, "B", NFS_PATH_LEN + 2 - strlen(backup_file)); + + /* Ensure that backup is ok before we overwrite .sav file. */ + backup_state = check_file(backup_file); + if (backup_state != BS_OK) { + printf("save_restore:write_save_file: Backup file (%s) bad or not found. Writing a new one. [%s]\n", + backup_file, datetime); + if (backup_state == BS_BAD) { + /* make a backup copy of the corrupted file */ + strNcpy(tmpstr, backup_file, TMPSTRLEN); + strncat(tmpstr, "_SBAD_", TMPSTRLEN - 1 - strlen(tmpstr)); + if (save_restoreDatedBackupFiles) { + strncat(tmpstr, datetime, TMPSTRLEN - 1 - strlen(tmpstr)); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Bad file: '%sB'", plist->save_file); + } + (void)myFileCopy(backup_file, tmpstr); + } + if (write_it(backup_file, plist) == ERROR) { + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + printf("save_restore:write_save_file: Can't write new backup file. [%s]\n", datetime); + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + plist->status = SR_STATUS_FAIL; + strNcpy(plist->statusStr, "Can't write .savB file", STATUS_STR_LEN); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + return (ERROR); + } + plist->status = SR_STATUS_WARN; + strNcpy(plist->statusStr, ".savB file was bad", STATUS_STR_LEN); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + backup_state = BS_NEW; + } + } - if (configName!=NULL) { - char datetime[32]; - FILE *test_fd; - - if ((test_fd = fopen(save_file,"rb")) != NULL) { - fclose(test_fd); - fGetDateStr(datetime); - strNcpy(backup_file, save_file, NFS_PATH_LEN); - strncat(backup_file, "_", NFS_PATH_LEN-strlen(backup_file)); - strncat(backup_file, datetime, NFS_PATH_LEN-strlen(backup_file)); - myFileCopy(save_file,backup_file); - } - } + if (configName != NULL) { + char datetime[32]; + FILE *test_fd; + + if ((test_fd = fopen(save_file, "rb")) != NULL) { + fclose(test_fd); + fGetDateStr(datetime); + strNcpy(backup_file, save_file, NFS_PATH_LEN); + strncat(backup_file, "_", NFS_PATH_LEN - strlen(backup_file)); + strncat(backup_file, datetime, NFS_PATH_LEN - strlen(backup_file)); + myFileCopy(save_file, backup_file); + } + } - /*** Write the save file ***/ - if (save_restoreDebug > 2) printf("write_save_file: saving to %s\n", save_file); - if (write_it(save_file, plist) == ERROR) { - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - printf("save_restore:write_save_file: Can't write save file. [%s]\n", datetime); - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - plist->status = SR_STATUS_FAIL; - strNcpy(plist->statusStr, "Can't write .sav file", STATUS_STR_LEN); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Can't write '%s'", plist->save_file); - return(ERROR); - } + /*** Write the save file ***/ + if (save_restoreDebug > 2) printf("write_save_file: saving to %s\n", save_file); + if (write_it(save_file, plist) == ERROR) { + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + printf("save_restore:write_save_file: Can't write save file. [%s]\n", datetime); + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + plist->status = SR_STATUS_FAIL; + strNcpy(plist->statusStr, "Can't write .sav file", STATUS_STR_LEN); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Can't write '%s'", plist->save_file); + return (ERROR); + } - /* keep the name and time of the last saved file */ - epicsTimeGetCurrent(&plist->save_time); - strNcpy(plist->last_save_file, plist->save_file, FN_LEN); - - if (plist->do_backups) { - /*** Write a backup copy of the save file ***/ - if (backup_state != BS_NEW) { - /* make a backup copy */ - if (myFileCopy(save_file, backup_file) != OK) { - printf("save_restore:write_save_file - Couldn't make backup '%s' [%s]\n", - backup_file, datetime); - plist->status = SR_STATUS_WARN; - strNcpy(plist->statusStr, "Can't copy .sav to .savB file", STATUS_STR_LEN); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Can't write '%sB'", plist->save_file); - return(ERROR); - } - } - } + /* keep the name and time of the last saved file */ + epicsTimeGetCurrent(&plist->save_time); + strNcpy(plist->last_save_file, plist->save_file, FN_LEN); + + if (plist->do_backups) { + /*** Write a backup copy of the save file ***/ + if (backup_state != BS_NEW) { + /* make a backup copy */ + if (myFileCopy(save_file, backup_file) != OK) { + printf("save_restore:write_save_file - Couldn't make backup '%s' [%s]\n", backup_file, datetime); + plist->status = SR_STATUS_WARN; + strNcpy(plist->statusStr, "Can't copy .sav to .savB file", STATUS_STR_LEN); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Can't write '%sB'", plist->save_file); + return (ERROR); + } + } + } - /* Update status PV */ - if (plist->not_connected) { - plist->status = SR_STATUS_WARN; - epicsSnprintf(plist->statusStr, STATUS_STR_LEN-1,"%d %s not saved", plist->not_connected, - plist->not_connected==1?"value":"values"); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Wrote '%s'", plist->save_file); - if (NULL != retSaveFile) - { - strNcpy(retSaveFile, save_file, NFS_PATH_LEN); - } - return(OK); + /* Update status PV */ + if (plist->not_connected) { + plist->status = SR_STATUS_WARN; + epicsSnprintf(plist->statusStr, STATUS_STR_LEN - 1, "%d %s not saved", plist->not_connected, + plist->not_connected == 1 ? "value" : "values"); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + } + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Wrote '%s'", plist->save_file); + if (NULL != retSaveFile) { strNcpy(retSaveFile, save_file, NFS_PATH_LEN); } + return (OK); } - /* * do_seq - copy .sav file to .savX, where X is in * [0..save_restoreNumSeqFiles]. If .sav file can't be opened, @@ -2179,352 +2144,331 @@ STATIC int write_save_file(struct chlist *plist, const char *configName, char *r */ STATIC void do_seq(struct chlist *plist) { - char *p, save_file[NFS_PATH_LEN+3] = "", backup_file[NFS_PATH_LEN+3] = ""; - int i; - struct stat fileStat; - char datetime[32]; - - fGetDateStr(datetime); - - /* Make full file names */ - makeNfsPath(save_file, saveRestoreFilePath, plist->save_file); - strNcpy(backup_file, save_file, NFS_PATH_LEN); - p = &backup_file[strlen(backup_file)]; - - /* If first time for this list, determine which existing file is oldest. */ - if (plist->backup_sequence_num == -1) { - double dTime, max_dTime = -1.e9; - - plist->backup_sequence_num = 0; - for (i=0; ibackup_sequence_num = i; - break; - } - dTime = difftime(time(NULL), fileStat.st_mtime); - if (dTime > max_dTime) { - max_dTime = dTime; - plist->backup_sequence_num = i; - } - } - } + char *p, save_file[NFS_PATH_LEN + 3] = "", backup_file[NFS_PATH_LEN + 3] = ""; + int i; + struct stat fileStat; + char datetime[32]; + + fGetDateStr(datetime); + + /* Make full file names */ + makeNfsPath(save_file, saveRestoreFilePath, plist->save_file); + strNcpy(backup_file, save_file, NFS_PATH_LEN); + p = &backup_file[strlen(backup_file)]; + + /* If first time for this list, determine which existing file is oldest. */ + if (plist->backup_sequence_num == -1) { + double dTime, max_dTime = -1.e9; + + plist->backup_sequence_num = 0; + for (i = 0; i < save_restoreNumSeqFiles; i++) { + epicsSnprintf(p, NFS_PATH_LEN - 1 - strlen(backup_file), "%1d", i); /* (over)write sequence number */ + if (stat(backup_file, &fileStat)) { + /* can't check date; just assume this file is oldest */ + plist->backup_sequence_num = i; + break; + } + dTime = difftime(time(NULL), fileStat.st_mtime); + if (dTime > max_dTime) { + max_dTime = dTime; + plist->backup_sequence_num = i; + } + } + } - if (check_file(save_file) == BS_NONE) { - printf("save_restore:do_seq - '%s' not found. Writing a new one. [%s]\n", - save_file, datetime); - (void) write_save_file(plist, NULL, NULL); - } - epicsSnprintf(p, NFS_PATH_LEN-1-strlen(backup_file), "%1d", plist->backup_sequence_num); - if (myFileCopy(save_file, backup_file) != OK) { - printf("save_restore:do_seq - Can't copy save file to '%s' [%s]\n", - backup_file, datetime); - if (write_it(backup_file, plist) == ERROR) { - printf("save_restore:do_seq - Can't write seq. file from PV list. [%s]\n", datetime); - if (plist->status >= SR_STATUS_WARN) { - plist->status = SR_STATUS_SEQ_WARN; - strNcpy(plist->statusStr, "Can't write sequence file", STATUS_STR_LEN); - } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Can't write '%s%1d'", - plist->save_file, plist->backup_sequence_num); - return; - } else { - printf("save_restore:do_seq: Wrote seq. file from PV list. [%s]\n", datetime); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Wrote '%s%1d'", - plist->save_file, plist->backup_sequence_num); - } - } else { - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Wrote '%s%1d'", - plist->save_file, plist->backup_sequence_num); - } + if (check_file(save_file) == BS_NONE) { + printf("save_restore:do_seq - '%s' not found. Writing a new one. [%s]\n", save_file, datetime); + (void)write_save_file(plist, NULL, NULL); + } + epicsSnprintf(p, NFS_PATH_LEN - 1 - strlen(backup_file), "%1d", plist->backup_sequence_num); + if (myFileCopy(save_file, backup_file) != OK) { + printf("save_restore:do_seq - Can't copy save file to '%s' [%s]\n", backup_file, datetime); + if (write_it(backup_file, plist) == ERROR) { + printf("save_restore:do_seq - Can't write seq. file from PV list. [%s]\n", datetime); + if (plist->status >= SR_STATUS_WARN) { + plist->status = SR_STATUS_SEQ_WARN; + strNcpy(plist->statusStr, "Can't write sequence file", STATUS_STR_LEN); + } + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Can't write '%s%1d'", plist->save_file, + plist->backup_sequence_num); + return; + } else { + printf("save_restore:do_seq: Wrote seq. file from PV list. [%s]\n", datetime); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Wrote '%s%1d'", plist->save_file, + plist->backup_sequence_num); + } + } else { + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Wrote '%s%1d'", plist->save_file, + plist->backup_sequence_num); + } - epicsTimeGetCurrent(&plist->backup_time); - if (++(plist->backup_sequence_num) >= save_restoreNumSeqFiles) - plist->backup_sequence_num = 0; + epicsTimeGetCurrent(&plist->backup_time); + if (++(plist->backup_sequence_num) >= save_restoreNumSeqFiles) plist->backup_sequence_num = 0; } -STATIC void doPeriodicDatedBackup(struct chlist *plist) { - char save_file[NFS_PATH_LEN+3] = ""; - char tmpstr[TMPSTRLEN]; - char datetime[32]; - - if (save_restoreDebug > 1) { - printf("save_restore:doPeriodicDatedBackup: entry\n"); - } - - fGetDateStr(datetime); - /* Make full file names */ - if (plist->savePathPV_chid) { - /* This list's path name comes from a PV */ - ca_array_get(DBR_STRING,1,plist->savePathPV_chid,tmpstr); - ca_pend_io(1.0); - if (tmpstr[0] == '\0') return; - strNcpy(save_file, tmpstr, sizeof(save_file)); - if (!isAbsolute(save_file)) { - makeNfsPath(save_file, saveRestoreFilePath, save_file); - } - } else { - /* Use standard path name. */ - strNcpy(save_file, saveRestoreFilePath, sizeof(save_file)); - } +STATIC void doPeriodicDatedBackup(struct chlist *plist) +{ + char save_file[NFS_PATH_LEN + 3] = ""; + char tmpstr[TMPSTRLEN]; + char datetime[32]; + + if (save_restoreDebug > 1) { printf("save_restore:doPeriodicDatedBackup: entry\n"); } + + fGetDateStr(datetime); + /* Make full file names */ + if (plist->savePathPV_chid) { + /* This list's path name comes from a PV */ + ca_array_get(DBR_STRING, 1, plist->savePathPV_chid, tmpstr); + ca_pend_io(1.0); + if (tmpstr[0] == '\0') return; + strNcpy(save_file, tmpstr, sizeof(save_file)); + if (!isAbsolute(save_file)) { makeNfsPath(save_file, saveRestoreFilePath, save_file); } + } else { + /* Use standard path name. */ + strNcpy(save_file, saveRestoreFilePath, sizeof(save_file)); + } - if (plist->saveNamePV_chid) { - /* This list's file name comes from a PV */ - ca_array_get(DBR_STRING,1,plist->saveNamePV_chid,tmpstr); - ca_pend_io(1.0); - if (tmpstr[0] == '\0') return; - makeNfsPath(save_file, save_file, tmpstr); - } else { - /* Use file name constructed from the request file name. */ - makeNfsPath(save_file, save_file, plist->save_file); - } + if (plist->saveNamePV_chid) { + /* This list's file name comes from a PV */ + ca_array_get(DBR_STRING, 1, plist->saveNamePV_chid, tmpstr); + ca_pend_io(1.0); + if (tmpstr[0] == '\0') return; + makeNfsPath(save_file, save_file, tmpstr); + } else { + /* Use file name constructed from the request file name. */ + makeNfsPath(save_file, save_file, plist->save_file); + } - strncat(save_file, "_b_", sizeof(save_file)-strlen(save_file)-1); - strncat(save_file, datetime, sizeof(save_file)-strlen(save_file)-1); - if (save_restoreDebug > 1) { - printf("save_restore:doPeriodicDatedBackup: filename is '%s'\n", save_file); - } - if (write_it(save_file, plist) == ERROR) { - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - printf("save_restore:doPeriodicDatedBackup: Can't write file. [%s]\n", save_file); - printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); - } + strncat(save_file, "_b_", sizeof(save_file) - strlen(save_file) - 1); + strncat(save_file, datetime, sizeof(save_file) - strlen(save_file) - 1); + if (save_restoreDebug > 1) { printf("save_restore:doPeriodicDatedBackup: filename is '%s'\n", save_file); } + if (write_it(save_file, plist) == ERROR) { + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + printf("save_restore:doPeriodicDatedBackup: Can't write file. [%s]\n", save_file); + printf("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); + } } /* Called only by the user */ int set_savefile_name(char *filename, char *save_filename) { - struct chlist *plist; + struct chlist *plist; - if (waitForListLock(5) == 0) { - printf("set_savefile_name:failed to lock resource. Try later.\n"); - return(ERROR); - } - plist = lptr; - while (plist != 0) { - if (!strcmp(plist->reqFile,filename)) { - strNcpy(plist->save_file,save_filename, FN_LEN); - unlockList(); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "New save file: '%s'", save_filename); - return(OK); - } - plist = plist->pnext; - } - printf("save_restore:set_savefile_name: No save set enabled for %s\n",filename); - unlockList(); - return(ERROR); + if (waitForListLock(5) == 0) { + printf("set_savefile_name:failed to lock resource. Try later.\n"); + return (ERROR); + } + plist = lptr; + while (plist != 0) { + if (!strcmp(plist->reqFile, filename)) { + strNcpy(plist->save_file, save_filename, FN_LEN); + unlockList(); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "New save file: '%s'", save_filename); + return (OK); + } + plist = plist->pnext; + } + printf("save_restore:set_savefile_name: No save set enabled for %s\n", filename); + unlockList(); + return (ERROR); } - int create_periodic_set(char *filename, int period, char *macrostring) { - return(create_data_set(filename, PERIODIC, period, 0, 0, macrostring)); + return (create_data_set(filename, PERIODIC, period, 0, 0, macrostring)); } - int create_triggered_set(char *filename, char *trigger_channel, char *macrostring) { - if (trigger_channel && isValid1stPVChar((int)trigger_channel[0])) { - return(create_data_set(filename, TRIGGERED, 0, trigger_channel, 0, macrostring)); - } - else { - printf("save_restore:create_triggered_set: Error: trigger-channel name is required.\n"); - return(ERROR); - } + if (trigger_channel && isValid1stPVChar((int)trigger_channel[0])) { + return (create_data_set(filename, TRIGGERED, 0, trigger_channel, 0, macrostring)); + } else { + printf("save_restore:create_triggered_set: Error: trigger-channel name is required.\n"); + return (ERROR); + } } - int create_monitor_set(char *filename, int period, char *macrostring) { - return(create_data_set(filename, MONITORED, 0, 0, period, macrostring)); + return (create_data_set(filename, MONITORED, 0, 0, period, macrostring)); } - int create_manual_set(char *filename, char *macrostring) { - return(create_data_set(filename, MANUAL, 0, 0, 0, macrostring)); + return (create_data_set(filename, MANUAL, 0, 0, 0, macrostring)); } - /* * create a data set */ -STATIC int create_data_set( - char *filename, /* save set request file */ - int save_method, - int period, /* maximum time between saves */ - char *trigger_channel, /* db channel to trigger save */ - int mon_period, /* minimum time between saves */ - char *macrostring -) +STATIC int create_data_set(char *filename, /* save set request file */ + int save_method, int period, /* maximum time between saves */ + char *trigger_channel, /* db channel to trigger save */ + int mon_period, /* minimum time between saves */ + char *macrostring) { - struct chlist *plist; - int inx; /* i/o status */ - int i; + struct chlist *plist; + int inx; /* i/o status */ + int i; - if (save_restoreDebug > 1) { - printf("save_restore:create_data_set: file '%s', method %x, period %d, trig_chan '%s', mon_period %d\n", - filename, save_method, period, trigger_channel ? trigger_channel : "NONE", mon_period); - } + if (save_restoreDebug > 1) { + printf("save_restore:create_data_set: file '%s', method %x, period %d, trig_chan '%s', mon_period %d\n", + filename, save_method, period, trigger_channel ? trigger_channel : "NONE", mon_period); + } - /* initialize save_restore routines */ - if (!save_restore_init) { - if ((sr_mutex = epicsMutexCreate()) == 0) { - printf("save_restore:create_data_set: could not create list header mutex"); - return(ERROR); - } - opMsgQueue = epicsMessageQueueCreate(OP_MSG_QUEUE_SIZE, OP_MSG_SIZE); - if (opMsgQueue == NULL) { - printf("save_restore:create_data_set: could not create message queue"); - return(ERROR); - } - taskID = epicsThreadCreate("save_restore", taskPriority, - epicsThreadGetStackSize(epicsThreadStackBig), - (EPICSTHREADFUNC)save_restore, 0); - if (taskID == NULL) { - printf("save_restore:create_data_set: could not create save_restore task"); - return(ERROR); - } - save_restore_init = 1; - - shutdownEvent = epicsEventMustCreate(epicsEventEmpty); - epicsAtExit(save_restoreShutdown, NULL); - } + /* initialize save_restore routines */ + if (!save_restore_init) { + if ((sr_mutex = epicsMutexCreate()) == 0) { + printf("save_restore:create_data_set: could not create list header mutex"); + return (ERROR); + } + opMsgQueue = epicsMessageQueueCreate(OP_MSG_QUEUE_SIZE, OP_MSG_SIZE); + if (opMsgQueue == NULL) { + printf("save_restore:create_data_set: could not create message queue"); + return (ERROR); + } + taskID = epicsThreadCreate("save_restore", taskPriority, epicsThreadGetStackSize(epicsThreadStackBig), + (EPICSTHREADFUNC)save_restore, 0); + if (taskID == NULL) { + printf("save_restore:create_data_set: could not create save_restore task"); + return (ERROR); + } + save_restore_init = 1; + + shutdownEvent = epicsEventMustCreate(epicsEventEmpty); + epicsAtExit(save_restoreShutdown, NULL); + } - if (filename==NULL || filename[0] == '\0') { - /* User probably wanted to start the save_restore task without creating + if (filename == NULL || filename[0] == '\0') { + /* User probably wanted to start the save_restore task without creating * a save set. This is ok. */ - return(0); - } + return (0); + } - /* is save set defined - add new save mode if necessary */ - while (waitForListLock(5) == 0) { - if (save_restoreDebug > 1) printf("create_data_set: '%s' waiting for listLock()\n", filename); - } - plist = lptr; - while (plist != 0) { - if (!strcmp(plist->reqFile,filename)) { - if (plist->save_method & save_method) { - printf("save_restore:create_data_set: '%s' already in %x mode",filename,save_method); - unlockList(); - return(ERROR); - } else { - /* Add a new method to an existing list */ - if (save_method == TRIGGERED) { - if (trigger_channel) { - strNcpy(plist->trigger_channel,trigger_channel, PV_NAME_LEN); - } else { - printf("save_restore:create_data_set: no trigger channel"); - unlockList(); - return(ERROR); - } - } else if (save_method == PERIODIC) { - plist->period = period; - } else if (save_method == MONITORED) { - plist->monitor_period = mon_period; - } - plist->save_method |= save_method; - /* + /* is save set defined - add new save mode if necessary */ + while (waitForListLock(5) == 0) { + if (save_restoreDebug > 1) printf("create_data_set: '%s' waiting for listLock()\n", filename); + } + plist = lptr; + while (plist != 0) { + if (!strcmp(plist->reqFile, filename)) { + if (plist->save_method & save_method) { + printf("save_restore:create_data_set: '%s' already in %x mode", filename, save_method); + unlockList(); + return (ERROR); + } else { + /* Add a new method to an existing list */ + if (save_method == TRIGGERED) { + if (trigger_channel) { + strNcpy(plist->trigger_channel, trigger_channel, PV_NAME_LEN); + } else { + printf("save_restore:create_data_set: no trigger channel"); + unlockList(); + return (ERROR); + } + } else if (save_method == PERIODIC) { + plist->period = period; + } else if (save_method == MONITORED) { + plist->monitor_period = mon_period; + } + plist->save_method |= save_method; + /* * We used to call enable_list() from here, but it starts CA * monitors that will be handled by the save_restore task. * Now, we let the save_restore task do all of its own CA stuff. */ - /* enable_list(plist); */ + /* enable_list(plist); */ - unlockList(); - return(OK); - } - } - plist = plist->pnext; - } - unlockList(); + unlockList(); + return (OK); + } + } + plist = plist->pnext; + } + unlockList(); - /* create a new channel list */ - if ((plist = (struct chlist *)calloc(1,sizeof (struct chlist))) == (struct chlist *)0) { - printf("save_restore:create_data_set: channel list calloc failed"); - return(ERROR); - } - if (macrostring && (strlen(macrostring)>0)) { - plist->macrostring = malloc(1+strlen(macrostring)); - strcpy(plist->macrostring, macrostring); - } - plist->do_backups = 1; /* Do backups and sequences backups, unless we're told not to. */ - callbackSetCallback(periodic_save, &plist->periodicCb); - callbackSetUser(plist, &plist->periodicCb); - callbackSetCallback(on_change_timer, &plist->monitorCb); - callbackSetUser(plist, &plist->monitorCb); - strNcpy(plist->reqFile, filename, sizeof(plist->reqFile)); - plist->pchan_list = (struct channel *)0; - plist->period = MAX(period, MIN_PERIOD); - if (trigger_channel) { - strNcpy(plist->trigger_channel, trigger_channel, sizeof(plist->trigger_channel)); - } else { - plist->trigger_channel[0]=0; - } - plist->last_save_file[0] = 0; - plist->save_method = save_method; - plist->enabled_method = 0; - plist->save_state = 0; - plist->save_ok = 0; - plist->monitor_period = MAX(mon_period, MIN_PERIOD); - /* init times */ - epicsTimeGetCurrent(&plist->backup_time); - epicsTimeGetCurrent(&plist->save_attempt_time); - epicsTimeGetCurrent(&plist->save_time); - plist->backup_sequence_num = -1; - plist->save_ok = 0; - plist->not_connected = -1; - plist->status = SR_STATUS_INIT; - strNcpy(plist->statusStr,"Initializing list", STATUS_STR_LEN); - - /** construct the save_file name **/ - strNcpy(plist->save_file, plist->reqFile, FN_LEN); + /* create a new channel list */ + if ((plist = (struct chlist *)calloc(1, sizeof(struct chlist))) == (struct chlist *)0) { + printf("save_restore:create_data_set: channel list calloc failed"); + return (ERROR); + } + if (macrostring && (strlen(macrostring) > 0)) { + plist->macrostring = malloc(1 + strlen(macrostring)); + strcpy(plist->macrostring, macrostring); + } + plist->do_backups = 1; /* Do backups and sequences backups, unless we're told not to. */ + callbackSetCallback(periodic_save, &plist->periodicCb); + callbackSetUser(plist, &plist->periodicCb); + callbackSetCallback(on_change_timer, &plist->monitorCb); + callbackSetUser(plist, &plist->monitorCb); + strNcpy(plist->reqFile, filename, sizeof(plist->reqFile)); + plist->pchan_list = (struct channel *)0; + plist->period = MAX(period, MIN_PERIOD); + if (trigger_channel) { + strNcpy(plist->trigger_channel, trigger_channel, sizeof(plist->trigger_channel)); + } else { + plist->trigger_channel[0] = 0; + } + plist->last_save_file[0] = 0; + plist->save_method = save_method; + plist->enabled_method = 0; + plist->save_state = 0; + plist->save_ok = 0; + plist->monitor_period = MAX(mon_period, MIN_PERIOD); + /* init times */ + epicsTimeGetCurrent(&plist->backup_time); + epicsTimeGetCurrent(&plist->save_attempt_time); + epicsTimeGetCurrent(&plist->save_time); + plist->backup_sequence_num = -1; + plist->save_ok = 0; + plist->not_connected = -1; + plist->status = SR_STATUS_INIT; + strNcpy(plist->statusStr, "Initializing list", STATUS_STR_LEN); + + /** construct the save_file name **/ + strNcpy(plist->save_file, plist->reqFile, FN_LEN); #if 0 inx = 0; while ((plist->save_file[inx] != 0) && (plist->save_file[inx] != '.') && (inx < (FN_LEN-6))) inx++; #else - /* fix bfr 2007-10-01: need to search for last '.', not first */ - inx = strlen(plist->save_file)-1; - while (inx > 0 && plist->save_file[inx] != '.') inx--; + /* fix bfr 2007-10-01: need to search for last '.', not first */ + inx = strlen(plist->save_file) - 1; + while (inx > 0 && plist->save_file[inx] != '.') inx--; #endif - plist->save_file[inx] = 0; /* truncate if necessary to leave room for ".sav" + null */ - strcat(plist->save_file,".sav"); - /* make full name, including file path */ - makeNfsPath(plist->saveFile, saveRestoreFilePath, plist->save_file); - - /* read the request file and populate plist with the PV names */ - if (readReqFile(plist->reqFile, plist, macrostring) == ERROR) { - free(plist); - return(ERROR); - } + plist->save_file[inx] = 0; /* truncate if necessary to leave room for ".sav" + null */ + strcat(plist->save_file, ".sav"); + /* make full name, including file path */ + makeNfsPath(plist->saveFile, saveRestoreFilePath, plist->save_file); + + /* read the request file and populate plist with the PV names */ + if (readReqFile(plist->reqFile, plist, macrostring) == ERROR) { + free(plist); + return (ERROR); + } - /* associate the list with a set of status PV's */ - for (i=0; istatusPvIndex = i; - if (i < NUM_STATUS_PV_SETS) statusPvsInUse[i] = 1; + /* associate the list with a set of status PV's */ + for (i = 0; i < NUM_STATUS_PV_SETS; i++) { + if (!statusPvsInUse[i]) break; + } + plist->statusPvIndex = i; + if (i < NUM_STATUS_PV_SETS) statusPvsInUse[i] = 1; - /* qiao: init the call back time of this list */ - epicsTimeGetCurrent(&plist->callback_time); + /* qiao: init the call back time of this list */ + epicsTimeGetCurrent(&plist->callback_time); - /* link it to the save set list */ - while (waitForListLock(5) == 0) { - if (save_restoreDebug > 1) printf("create_data_set: '%s' waiting for listLock()\n", filename); - } - plist->pnext = lptr; - lptr = plist; - strNcpy(plist->statusStr,"Ready to connect...", STATUS_STR_LEN); - unlockList(); + /* link it to the save set list */ + while (waitForListLock(5) == 0) { + if (save_restoreDebug > 1) printf("create_data_set: '%s' waiting for listLock()\n", filename); + } + plist->pnext = lptr; + lptr = plist; + strNcpy(plist->statusStr, "Ready to connect...", STATUS_STR_LEN); + unlockList(); - return(OK); + return (OK); } - - - /* * save_restoreShow - Show state of save_restore; optionally, list save sets * @@ -2532,446 +2476,433 @@ STATIC int create_data_set( static char ca_state_string[4][10] = {"Never", "Prev", "Conn", "Closed"}; void save_restoreShow(int verbose) { - struct chlist *plist; - struct channel *pchannel; - struct pathListElement *p = reqFilePathList; - char tmpstr[50]; - char datetime[32]; - int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && - save_restoreNFSMntPoint[0]; - - fGetDateStr(datetime); - printf("BEGIN save_restoreShow\n"); - printf(" Current date-time (yymmdd-hhmmss): [%s] \n", datetime); - printf(" Status: '%s' - '%s'\n", SR_STATUS_STR[SR_status], SR_statusStr); - printf(" Debug level: %d\n", save_restoreDebug); + struct chlist *plist; + struct channel *pchannel; + struct pathListElement *p = reqFilePathList; + char tmpstr[50]; + char datetime[32]; + int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]; + + fGetDateStr(datetime); + printf("BEGIN save_restoreShow\n"); + printf(" Current date-time (yymmdd-hhmmss): [%s] \n", datetime); + printf(" Status: '%s' - '%s'\n", SR_STATUS_STR[SR_status], SR_statusStr); + printf(" Debug level: %d\n", save_restoreDebug); #if SET_FILE_PERMISSIONS - printf(" File permissions: 0%o\n", (unsigned int)file_permissions); + printf(" File permissions: 0%o\n", (unsigned int)file_permissions); #endif - printf(" Save/restore incomplete save sets? %s\n", save_restoreIncompleteSetsOk?"YES":"NO"); - printf(" Write dated backup files? %s\n", save_restoreDatedBackupFiles?"YES":"NO"); - printf(" Number of sequence files to maintain: %d\n", save_restoreNumSeqFiles); - printf(" Time interval between sequence files: %d seconds\n", save_restoreSeqPeriodInSeconds); - printf(" Time interval between .sav-file write failure and retry: %d seconds\n", save_restoreRetrySeconds); - printf(" NFS host: '%s'; address:'%s'\n", save_restoreNFSHostName, save_restoreNFSHostAddr); - printf(" NFS mount point:\n '%s'\n", save_restoreNFSMntPoint); - printf(" NFS mount status: %s\n", - NFS_managed ? (save_restoreNFSOK?"Ok":"Failed") : "not managed by save_restore"); - printf(" I/O errors: %d\n", save_restoreIoErrors); - printf(" request file path list:\n"); - while (p) { - printf(" '%s'\n", p->path); - p = p->pnext; - } - printf(" save file path:\n '%s'\n", saveRestoreFilePath); - if (sr_mutex && (waitForListLock(5) == 1)) { - for (plist = lptr; plist != 0; plist = plist->pnext) { - printf(" %s: \n",plist->reqFile); - printf(" macro string: '%s'\n", plist->macrostring ? plist->macrostring : ""); - printf(" Status PV: %s\n", plist->status_PV); - printf(" Status: '%s' - '%s'\n", SR_STATUS_STR[plist->status], plist->statusStr); - epicsTimeToStrftime(tmpstr, sizeof(tmpstr), TIMEFMT, &plist->save_time); - printf(" Last save time :%s", tmpstr); - epicsTimeToStrftime(tmpstr, sizeof(tmpstr), TIMEFMT, &plist->backup_time); - printf(" Last backup time:%s", tmpstr); - strcpy(tmpstr, "[ "); - if (plist->save_method & PERIODIC) strcat(tmpstr, "PERIODIC "); - if (plist->save_method & TRIGGERED) strcat(tmpstr, "TRIGGERED "); - if ((plist->save_method & MONITORED)==MONITORED) strcat(tmpstr, "TIMER+CHANGE "); - if (plist->save_method & MANUAL) strcat(tmpstr, "MANUAL "); - strcat(tmpstr, "]"); - printf(" methods: %s\n", tmpstr); - strcpy(tmpstr, "[ "); - if (plist->save_state & PERIODIC) strcat(tmpstr, "PERIOD "); - if (plist->save_state & TRIGGERED) strcat(tmpstr, "TRIGGER "); - if (plist->save_state & TIMER) strcat(tmpstr, "TIMER "); - if (plist->save_state & CHANGE) strcat(tmpstr, "CHANGE "); - if (plist->save_state & MANUAL) strcat(tmpstr, "MANUAL "); - strcat(tmpstr, "]"); - printf(" path PV: %s\n", plist->savePathPV[0]?plist->savePathPV:"None"); - if (plist->savePathPV[0]) { - ca_array_get(DBR_STRING, 1, plist->savePathPV_chid, tmpstr); - printf(" path: '%s'\n", tmpstr); - } - printf(" name PV: %s\n", plist->saveNamePV[0]?plist->saveNamePV:"None"); - if (plist->saveNamePV[0]) { - ca_array_get(DBR_STRING, 1, plist->saveNamePV_chid, tmpstr); - printf(" name: '%s'\n", tmpstr); - } - printf(" backups: %s\n", plist->do_backups?"YES":"NO"); - printf(" save_state = 0x%x\n", plist->save_state); - printf(" period: %d; trigger chan: '%s'; monitor period: %d\n", - plist->period,plist->trigger_channel,plist->monitor_period); - printf(" last saved file - %s\n",plist->last_save_file); - printf(" %d channel%c not connected (or ca_get failed)\n",plist->not_connected, - (plist->not_connected == 1) ? ' ' : 's'); - if (verbose && !save_restore_shutdown) { - for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { - printf("\t%s chid:%p state:%s (max:%ld curr:%ld elements)\t%s", pchannel->name, - pchannel->chid, pchannel->chid?ca_state_string[ca_state(pchannel->chid)]:"noChid", - pchannel->max_elements, pchannel->curr_elements, pchannel->value); - printf(" channel_connected = %d", pchannel->channel_connected); - if (pchannel->enum_val >= 0) printf("\t%d\n",pchannel->enum_val); - else printf("\n"); - } - } - } - unlockList(); - } else { - if (!sr_mutex) - printf(" The save_restore task apparently is not running.\n"); - else - printf(" Can't lock sr_mutex.\n"); - } - printf("reboot-restore status:\n"); - dbrestoreShow(); - printf("END save_restoreShow\n"); + printf(" Save/restore incomplete save sets? %s\n", save_restoreIncompleteSetsOk ? "YES" : "NO"); + printf(" Write dated backup files? %s\n", save_restoreDatedBackupFiles ? "YES" : "NO"); + printf(" Number of sequence files to maintain: %d\n", save_restoreNumSeqFiles); + printf(" Time interval between sequence files: %d seconds\n", save_restoreSeqPeriodInSeconds); + printf(" Time interval between .sav-file write failure and retry: %d seconds\n", save_restoreRetrySeconds); + printf(" NFS host: '%s'; address:'%s'\n", save_restoreNFSHostName, save_restoreNFSHostAddr); + printf(" NFS mount point:\n '%s'\n", save_restoreNFSMntPoint); + printf(" NFS mount status: %s\n", + NFS_managed ? (save_restoreNFSOK ? "Ok" : "Failed") : "not managed by save_restore"); + printf(" I/O errors: %d\n", save_restoreIoErrors); + printf(" request file path list:\n"); + while (p) { + printf(" '%s'\n", p->path); + p = p->pnext; + } + printf(" save file path:\n '%s'\n", saveRestoreFilePath); + if (sr_mutex && (waitForListLock(5) == 1)) { + for (plist = lptr; plist != 0; plist = plist->pnext) { + printf(" %s: \n", plist->reqFile); + printf(" macro string: '%s'\n", plist->macrostring ? plist->macrostring : ""); + printf(" Status PV: %s\n", plist->status_PV); + printf(" Status: '%s' - '%s'\n", SR_STATUS_STR[plist->status], plist->statusStr); + epicsTimeToStrftime(tmpstr, sizeof(tmpstr), TIMEFMT, &plist->save_time); + printf(" Last save time :%s", tmpstr); + epicsTimeToStrftime(tmpstr, sizeof(tmpstr), TIMEFMT, &plist->backup_time); + printf(" Last backup time:%s", tmpstr); + strcpy(tmpstr, "[ "); + if (plist->save_method & PERIODIC) strcat(tmpstr, "PERIODIC "); + if (plist->save_method & TRIGGERED) strcat(tmpstr, "TRIGGERED "); + if ((plist->save_method & MONITORED) == MONITORED) strcat(tmpstr, "TIMER+CHANGE "); + if (plist->save_method & MANUAL) strcat(tmpstr, "MANUAL "); + strcat(tmpstr, "]"); + printf(" methods: %s\n", tmpstr); + strcpy(tmpstr, "[ "); + if (plist->save_state & PERIODIC) strcat(tmpstr, "PERIOD "); + if (plist->save_state & TRIGGERED) strcat(tmpstr, "TRIGGER "); + if (plist->save_state & TIMER) strcat(tmpstr, "TIMER "); + if (plist->save_state & CHANGE) strcat(tmpstr, "CHANGE "); + if (plist->save_state & MANUAL) strcat(tmpstr, "MANUAL "); + strcat(tmpstr, "]"); + printf(" path PV: %s\n", plist->savePathPV[0] ? plist->savePathPV : "None"); + if (plist->savePathPV[0]) { + ca_array_get(DBR_STRING, 1, plist->savePathPV_chid, tmpstr); + printf(" path: '%s'\n", tmpstr); + } + printf(" name PV: %s\n", plist->saveNamePV[0] ? plist->saveNamePV : "None"); + if (plist->saveNamePV[0]) { + ca_array_get(DBR_STRING, 1, plist->saveNamePV_chid, tmpstr); + printf(" name: '%s'\n", tmpstr); + } + printf(" backups: %s\n", plist->do_backups ? "YES" : "NO"); + printf(" save_state = 0x%x\n", plist->save_state); + printf(" period: %d; trigger chan: '%s'; monitor period: %d\n", plist->period, plist->trigger_channel, + plist->monitor_period); + printf(" last saved file - %s\n", plist->last_save_file); + printf(" %d channel%c not connected (or ca_get failed)\n", plist->not_connected, + (plist->not_connected == 1) ? ' ' : 's'); + if (verbose && !save_restore_shutdown) { + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + printf("\t%s chid:%p state:%s (max:%ld curr:%ld elements)\t%s", pchannel->name, pchannel->chid, + pchannel->chid ? ca_state_string[ca_state(pchannel->chid)] : "noChid", + pchannel->max_elements, pchannel->curr_elements, pchannel->value); + printf(" channel_connected = %d", pchannel->channel_connected); + if (pchannel->enum_val >= 0) printf("\t%d\n", pchannel->enum_val); + else printf("\n"); + } + } + } + unlockList(); + } else { + if (!sr_mutex) printf(" The save_restore task apparently is not running.\n"); + else printf(" Can't lock sr_mutex.\n"); + } + printf("reboot-restore status:\n"); + dbrestoreShow(); + printf("END save_restoreShow\n"); } - int set_requestfile_path(char *path, char *pathsub) { - struct pathListElement *p, *pnew; - char fullpath[NFS_PATH_LEN+1] = ""; - int path_len=0, pathsub_len=0; - - if (path && *path) path_len = strlen(path); - if (pathsub && *pathsub) pathsub_len = strlen(pathsub); - if (path_len + pathsub_len > (NFS_PATH_LEN-1)) { /* may have to add '/' */ - printf("save_restore:set_requestfile_path: 'path'+'pathsub' is too long\n"); - return(ERROR); - } + struct pathListElement *p, *pnew; + char fullpath[NFS_PATH_LEN + 1] = ""; + int path_len = 0, pathsub_len = 0; + + if (path && *path) path_len = strlen(path); + if (pathsub && *pathsub) pathsub_len = strlen(pathsub); + if (path_len + pathsub_len > (NFS_PATH_LEN - 1)) { /* may have to add '/' */ + printf("save_restore:set_requestfile_path: 'path'+'pathsub' is too long\n"); + return (ERROR); + } - makeNfsPath(fullpath, path, pathsub); - - if (*fullpath) { - /* return(set_requestfile_path(fullpath)); */ - pnew = (struct pathListElement *)calloc(1, sizeof(struct pathListElement)); - if (pnew == NULL) { - printf("save_restore:set_requestfile_path: calloc failed\n"); - return(ERROR); - } - - strNcpy(pnew->path, fullpath, NFS_PATH_LEN); - if (pnew->path[strlen(pnew->path)-1] != '/') { - strncat(pnew->path, "/", NFS_PATH_LEN-strlen(pnew->path)); - } - - if (reqFilePathList == NULL) { - reqFilePathList = pnew; - } else { - for (p = reqFilePathList; p->pnext; p = p->pnext) - ; - p->pnext = pnew; - } - return(OK); - } else { - return(ERROR); - } + makeNfsPath(fullpath, path, pathsub); + + if (*fullpath) { + /* return(set_requestfile_path(fullpath)); */ + pnew = (struct pathListElement *)calloc(1, sizeof(struct pathListElement)); + if (pnew == NULL) { + printf("save_restore:set_requestfile_path: calloc failed\n"); + return (ERROR); + } + + strNcpy(pnew->path, fullpath, NFS_PATH_LEN); + if (pnew->path[strlen(pnew->path) - 1] != '/') { strncat(pnew->path, "/", NFS_PATH_LEN - strlen(pnew->path)); } + + if (reqFilePathList == NULL) { + reqFilePathList = pnew; + } else { + for (p = reqFilePathList; p->pnext; p = p->pnext) + ; + p->pnext = pnew; + } + return (OK); + } else { + return (ERROR); + } } int set_savefile_path(char *path, char *pathsub) { - char fullpath[NFS_PATH_LEN] = ""; - int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]; - - if (save_restoreNFSOK && NFS_managed) dismountFileSystem(save_restoreNFSMntPoint); - - makeNfsPath(fullpath, path, pathsub); - - if (*fullpath) { - if (saveRestoreFilePathIsMountPoint) { - strNcpy(saveRestoreFilePath, fullpath, NFS_PATH_LEN); - strNcpy(save_restoreNFSMntPoint, fullpath, NFS_PATH_LEN); - } else { - makeNfsPath(saveRestoreFilePath, save_restoreNFSMntPoint, fullpath); - } - if (save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]) { - if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, save_restoreNFSMntPoint, save_restoreNFSMntPoint) == OK) { - printf("save_restore:mountFileSystem:successfully mounted '%s'\n", save_restoreNFSMntPoint); - strNcpy(SR_recentlyStr, "mountFileSystem succeeded", STATUS_STR_LEN); - } - else { - printf("save_restore: Can't mount '%s'\n", save_restoreNFSMntPoint); - } - } - return(OK); - } else { - return(ERROR); - } + char fullpath[NFS_PATH_LEN] = ""; + int NFS_managed = save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]; + + if (save_restoreNFSOK && NFS_managed) dismountFileSystem(save_restoreNFSMntPoint); + + makeNfsPath(fullpath, path, pathsub); + + if (*fullpath) { + if (saveRestoreFilePathIsMountPoint) { + strNcpy(saveRestoreFilePath, fullpath, NFS_PATH_LEN); + strNcpy(save_restoreNFSMntPoint, fullpath, NFS_PATH_LEN); + } else { + makeNfsPath(saveRestoreFilePath, save_restoreNFSMntPoint, fullpath); + } + if (save_restoreNFSHostName[0] && save_restoreNFSHostAddr[0] && save_restoreNFSMntPoint[0]) { + if (mountFileSystem(save_restoreNFSHostName, save_restoreNFSHostAddr, save_restoreNFSMntPoint, + save_restoreNFSMntPoint) == OK) { + printf("save_restore:mountFileSystem:successfully mounted '%s'\n", save_restoreNFSMntPoint); + strNcpy(SR_recentlyStr, "mountFileSystem succeeded", STATUS_STR_LEN); + } else { + printf("save_restore: Can't mount '%s'\n", save_restoreNFSMntPoint); + } + } + return (OK); + } else { + return (ERROR); + } } int set_saveTask_priority(int priority) { - if ((priority < epicsThreadPriorityMin) || (priority > epicsThreadPriorityMax)) { - epicsPrintf("save_restore - priority must be >= %d and <= %d\n", - epicsThreadPriorityMin, epicsThreadPriorityMax); - return(ERROR); - } - taskPriority = priority; - if (taskID != NULL) { - epicsThreadSetPriority(taskID, priority); - } - return(OK); + if ((priority < epicsThreadPriorityMin) || (priority > epicsThreadPriorityMax)) { + epicsPrintf("save_restore - priority must be >= %d and <= %d\n", epicsThreadPriorityMin, + epicsThreadPriorityMax); + return (ERROR); + } + taskPriority = priority; + if (taskID != NULL) { epicsThreadSetPriority(taskID, priority); } + return (OK); } STATIC int remove_data_set(char *filename) { - op_msg msg; + op_msg msg; - msg.operation = op_Remove; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("remove_data_set: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + msg.operation = op_Remove; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("remove_data_set: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } /*** remove a data set from the list ***/ STATIC int do_remove_data_set(char *filename) { - int found = 0; - int numchannels = 0; - struct chlist *plist, *previous; - struct channel *pchannel, *pchannelt; - - /* find the data set */ - if (waitForListLock(5) == 0) { - printf("do_remove_data_set:failed to lock resource. Try later.\n"); - return(ERROR); - } - plist = lptr; - previous = 0; - while(plist) { - if (!strcmp(plist->reqFile, filename)) { - found = 1; - break; - } - previous = plist; - plist = plist->pnext; - } - unlockList(); - - if (found) { - if (waitForListLock(5) == 0) { - printf("do_remove_data_set:failed to lock resource. Try later.\n"); - return(ERROR); - } - if (plist->macrostring) free(plist->macrostring); - statusPvsInUse[plist->statusPvIndex] = 0; /* say we're not using these status PVs anymore */ - pchannel = plist->pchan_list; - while (pchannel) { - if (ca_clear_channel(pchannel->chid) != ECA_NORMAL) { - printf("save_restore:do_remove_data_set: couldn't remove ca connection for %s\n", pchannel->name); - } - pchannel = pchannel->pnext; - numchannels++; - } - if (ca_pend_io(MIN(10.0, numchannels*0.1)) != ECA_NORMAL) { - printf("save_restore:do_remove_data_set: ca_pend_io() timed out\n"); - } - pchannel = plist->pchan_list; - while (pchannel) { - pchannelt = pchannel->pnext; - if (pchannel->pArray) free(pchannel->pArray); - free(pchannel); - pchannel = pchannelt; - } - if (previous == 0) { - lptr = plist->pnext; - } else { - previous->pnext = plist->pnext; - } - free(plist); - - unlockList(); - - } else { - printf("save_restore:do_remove_data_set: Couldn't find '%s'\n", filename); - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Can't remove data set '%s'", filename); - return(ERROR); - } - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "Removed data set '%s'", filename); - return(OK); + int found = 0; + int numchannels = 0; + struct chlist *plist, *previous; + struct channel *pchannel, *pchannelt; + + /* find the data set */ + if (waitForListLock(5) == 0) { + printf("do_remove_data_set:failed to lock resource. Try later.\n"); + return (ERROR); + } + plist = lptr; + previous = 0; + while (plist) { + if (!strcmp(plist->reqFile, filename)) { + found = 1; + break; + } + previous = plist; + plist = plist->pnext; + } + unlockList(); + + if (found) { + if (waitForListLock(5) == 0) { + printf("do_remove_data_set:failed to lock resource. Try later.\n"); + return (ERROR); + } + if (plist->macrostring) free(plist->macrostring); + statusPvsInUse[plist->statusPvIndex] = 0; /* say we're not using these status PVs anymore */ + pchannel = plist->pchan_list; + while (pchannel) { + if (ca_clear_channel(pchannel->chid) != ECA_NORMAL) { + printf("save_restore:do_remove_data_set: couldn't remove ca connection for %s\n", pchannel->name); + } + pchannel = pchannel->pnext; + numchannels++; + } + if (ca_pend_io(MIN(10.0, numchannels * 0.1)) != ECA_NORMAL) { + printf("save_restore:do_remove_data_set: ca_pend_io() timed out\n"); + } + pchannel = plist->pchan_list; + while (pchannel) { + pchannelt = pchannel->pnext; + if (pchannel->pArray) free(pchannel->pArray); + free(pchannel); + pchannel = pchannelt; + } + if (previous == 0) { + lptr = plist->pnext; + } else { + previous->pnext = plist->pnext; + } + free(plist); + + unlockList(); + + } else { + printf("save_restore:do_remove_data_set: Couldn't find '%s'\n", filename); + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Can't remove data set '%s'", filename); + return (ERROR); + } + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "Removed data set '%s'", filename); + return (OK); } int reload_periodic_set(char *filename, int period, char *macrostring) { - op_msg msg; + op_msg msg; - msg.operation = op_ReloadPeriodicSet; - msg.period = period; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("reload_periodic_set: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - if (strlen(macrostring) > (OP_MSG_MACRO_SIZE-1)) { - printf("macro string '%s' is too long for message queue\n", macrostring); - return(-1); - } - strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + msg.operation = op_ReloadPeriodicSet; + msg.period = period; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("reload_periodic_set: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + if (strlen(macrostring) > (OP_MSG_MACRO_SIZE - 1)) { + printf("macro string '%s' is too long for message queue\n", macrostring); + return (-1); + } + strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } int reload_triggered_set(char *filename, char *trigger_channel, char *macrostring) { - op_msg msg; + op_msg msg; - msg.operation = op_ReloadTriggeredSet; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("reload_triggered_set: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - if (strlen(macrostring) > (OP_MSG_MACRO_SIZE-1)) { - printf("macro string '%s' is too long for message queue\n", macrostring); - return(-1); - } - strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); - strNcpy(msg.trigger_channel, trigger_channel, OP_MSG_TRIGGER_SIZE); - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + msg.operation = op_ReloadTriggeredSet; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("reload_triggered_set: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + if (strlen(macrostring) > (OP_MSG_MACRO_SIZE - 1)) { + printf("macro string '%s' is too long for message queue\n", macrostring); + return (-1); + } + strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); + strNcpy(msg.trigger_channel, trigger_channel, OP_MSG_TRIGGER_SIZE); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } - -int reload_monitor_set(char * filename, int period, char *macrostring) +int reload_monitor_set(char *filename, int period, char *macrostring) { - op_msg msg; + op_msg msg; - msg.operation = op_ReloadMonitorSet; - msg.period = period; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("reload_monitor_set: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - if (strlen(macrostring) > (OP_MSG_MACRO_SIZE-1)) { - printf("macro string '%s' is too long for message queue\n", macrostring); - return(-1); - } - strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + msg.operation = op_ReloadMonitorSet; + msg.period = period; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("reload_monitor_set: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + if (strlen(macrostring) > (OP_MSG_MACRO_SIZE - 1)) { + printf("macro string '%s' is too long for message queue\n", macrostring); + return (-1); + } + strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } -int reload_manual_set(char * filename, char *macrostring) +int reload_manual_set(char *filename, char *macrostring) { - op_msg msg; - - msg.operation = op_ReloadManualSet; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("reload_manual_set: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - if (strlen(macrostring) > (OP_MSG_MACRO_SIZE-1)) { - printf("macro string '%s' is too long for message queue\n", macrostring); - return(-1); - } - strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + op_msg msg; + + msg.operation = op_ReloadManualSet; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("reload_manual_set: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + if (strlen(macrostring) > (OP_MSG_MACRO_SIZE - 1)) { + printf("macro string '%s' is too long for message queue\n", macrostring); + return (-1); + } + strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } int fdbrestore(char *filename) { - printf("save_restore:fdbrestore:entry\n"); - return(request_manual_restore(filename, FROM_SAVE_FILE, NULL, NULL, NULL)); + printf("save_restore:fdbrestore:entry\n"); + return (request_manual_restore(filename, FROM_SAVE_FILE, NULL, NULL, NULL)); } int fdbrestoreX(char *filename, char *macrostring, callbackFunc callbackFunction, void *puserPvt) { - return(request_manual_restore(filename, FROM_ASCII_FILE, macrostring, callbackFunction, puserPvt)); + return (request_manual_restore(filename, FROM_ASCII_FILE, macrostring, callbackFunction, puserPvt)); } -STATIC void defaultCallback(int status, void *puserPvt) { - printf("save_restore:defaultCallback:status=%d\n", status); -} +STATIC void defaultCallback(int status, void *puserPvt) { printf("save_restore:defaultCallback:status=%d\n", status); } -STATIC int request_manual_restore(char *filename, int file_type, char *macrostring, callbackFunc callbackFunction, void *puserPvt) +STATIC int request_manual_restore(char *filename, int file_type, char *macrostring, callbackFunc callbackFunction, + void *puserPvt) { - op_msg msg; + op_msg msg; - if (save_restoreDebug >= 5) { - printf("save_restore:request_manual_restore: entry\n"); - } - msg.operation = (file_type==FROM_SAVE_FILE) ? op_RestoreFromSaveFile : op_RestoreFromAsciiFile; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("request_manual_restore: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - if ((macrostring) && (strlen(macrostring) > (OP_MSG_MACRO_SIZE-1))) { - printf("request_manual_restore: macro string '%s' is too long for message queue\n", macrostring); - return(-1); - } - if ((macrostring) && (strlen(macrostring)>0)) { - strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); - } else { - msg.macrostring[0] = '\0'; - } - if (callbackFunction==NULL) { - callbackFunction = defaultCallback; - puserPvt = NULL; - } - msg.puserPvt = puserPvt; - msg.callbackFunction = callbackFunction; - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + if (save_restoreDebug >= 5) { printf("save_restore:request_manual_restore: entry\n"); } + msg.operation = (file_type == FROM_SAVE_FILE) ? op_RestoreFromSaveFile : op_RestoreFromAsciiFile; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("request_manual_restore: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + if ((macrostring) && (strlen(macrostring) > (OP_MSG_MACRO_SIZE - 1))) { + printf("request_manual_restore: macro string '%s' is too long for message queue\n", macrostring); + return (-1); + } + if ((macrostring) && (strlen(macrostring) > 0)) { + strNcpy(msg.macrostring, macrostring, OP_MSG_MACRO_SIZE); + } else { + msg.macrostring[0] = '\0'; + } + if (callbackFunction == NULL) { + callbackFunction = defaultCallback; + puserPvt = NULL; + } + msg.puserPvt = puserPvt; + msg.callbackFunction = callbackFunction; + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } STATIC int request_asVerify(char *filename, int verbose, char *restoreFileName) { - op_msg msg; + op_msg msg; - if (save_restoreDebug >= 5) { - printf("save_restore:request_asVerify: entry\n"); - } - msg.operation = op_asVerify; - if ((filename == NULL) || (strlen(filename)<1) || (strlen(filename)>=OP_MSG_FILENAME_SIZE-1)) { - printf("request_asVerify: bad filename\n"); - return(-1); - } - strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); - msg.macrostring[0] = '\0'; - msg.puserPvt = 0; - msg.callbackFunction = NULL; - msg.verbose = verbose; - if (restoreFileName && restoreFileName[0]) { - strNcpy(msg.restoreFileName, restoreFileName, OP_MSG_FILENAME_SIZE); - } else { - msg.restoreFileName[0] = '\0'; - } + if (save_restoreDebug >= 5) { printf("save_restore:request_asVerify: entry\n"); } + msg.operation = op_asVerify; + if ((filename == NULL) || (strlen(filename) < 1) || (strlen(filename) >= OP_MSG_FILENAME_SIZE - 1)) { + printf("request_asVerify: bad filename\n"); + return (-1); + } + strNcpy(msg.filename, filename, OP_MSG_FILENAME_SIZE); + msg.macrostring[0] = '\0'; + msg.puserPvt = 0; + msg.callbackFunction = NULL; + msg.verbose = verbose; + if (restoreFileName && restoreFileName[0]) { + strNcpy(msg.restoreFileName, restoreFileName, OP_MSG_FILENAME_SIZE); + } else { + msg.restoreFileName[0] = '\0'; + } - epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); - return(0); + epicsMessageQueueSend(opMsgQueue, (void *)&msg, OP_MSG_SIZE); + return (0); } -int asVerify(char *filename, int verbose, char *restoreFileName) { - request_asVerify(filename, verbose, restoreFileName); - return(0); +int asVerify(char *filename, int verbose, char *restoreFileName) +{ + request_asVerify(filename, verbose, restoreFileName); + return (0); } char *getMacroString(char *request_file) { - struct chlist *plist; - int found; - - for (plist=lptr, found=0; plist && !found; ) { - if (strcmp(plist->reqFile, request_file) == 0) { - found = 1; - } else { - plist = plist->pnext; - } - } - if (found) { - return(plist->macrostring); - } else { - return(NULL); - } + struct chlist *plist; + int found; + + for (plist = lptr, found = 0; plist && !found;) { + if (strcmp(plist->reqFile, request_file) == 0) { + found = 1; + } else { + plist = plist->pnext; + } + } + if (found) { + return (plist->macrostring); + } else { + return (NULL); + } } /* @@ -2984,613 +2915,550 @@ char *getMacroString(char *request_file) static void *p_data = NULL; static long p_data_size = 0; -STATIC int manual_array_restore(FILE *inp_fd, char *PVname, chid chanid, char *value_string, int gobble) { - - int j, end_mark_found=0, begin_mark_found=0, end_of_file=0, found=0, in_element=0; - long status=0, max_elements=0, num_read=0; - char buffer[BUF_SIZE], *bp = NULL; - char string[MAX_STRING_SIZE]; - short field_type = 0; - int field_size; - char *p_char = NULL; - short *p_short = NULL; - unsigned short *p_ushort = NULL; - epicsInt32 *p_long = NULL; - float *p_float = NULL; - double *p_double = NULL; - - - if (save_restoreDebug >= 1) { - printf("save_restore:manual_array_restore:entry: PV = '%s'\n", PVname); - } - - if (!gobble) { - /*** set up infrastructure for collecting array elements from file into local array ***/ - max_elements = ca_element_count(chanid); - field_type = ca_field_type(chanid); - field_size = dbr_size[field_type]; - /* if we've already allocated a big enough memory block, use it */ - if ((p_data == NULL) || ((max_elements * field_size) > p_data_size)) { - if (save_restoreDebug >= 1) { - printf("save_restore:manual_array_restore: p_data = %p, p_data_size = %ld\n", p_data, p_data_size); - } - if (p_data) free(p_data); - p_data = (void *)calloc(max_elements, field_size); - p_data_size = p_data ? max_elements * field_size : 0; - if (save_restoreDebug >= 10) printf("save_restore:manual_array_restore: allocated p_data = %p, p_data_size = %ld\n", p_data, p_data_size); - } else { - memset(p_data, 0, p_data_size); - } - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: Looking for up to %ld elements of field-size %d\n", max_elements, field_size); - printf("save_restore:manual_array_restore: ...field_type is (%d)\n", field_type); - } - - switch (field_type) { - case DBF_STRING: - case DBF_CHAR: p_char = (char *)p_data; break; - case DBF_ENUM: p_ushort = (unsigned short *)p_data; break; - case DBF_SHORT: p_short = (short *)p_data; break; - case DBF_LONG: p_long = (epicsInt32 *)p_data; break; - case DBF_FLOAT: p_float = (float *)p_data; break; - case DBF_DOUBLE: p_double = (double *)p_data; break; - default: - printf("save_restore:manual_array_restore: field_type '%d' not handled\n", field_type); - status = -1; - break; - } - } - +STATIC int manual_array_restore(FILE *inp_fd, char *PVname, chid chanid, char *value_string, int gobble) +{ + int j, end_mark_found = 0, begin_mark_found = 0, end_of_file = 0, found = 0, in_element = 0; + long status = 0, max_elements = 0, num_read = 0; + char buffer[BUF_SIZE], *bp = NULL; + char string[MAX_STRING_SIZE]; + short field_type = 0; + int field_size; + char *p_char = NULL; + short *p_short = NULL; + unsigned short *p_ushort = NULL; + epicsInt32 *p_long = NULL; + float *p_float = NULL; + double *p_double = NULL; + + if (save_restoreDebug >= 1) { printf("save_restore:manual_array_restore:entry: PV = '%s'\n", PVname); } + + if (!gobble) { + /*** set up infrastructure for collecting array elements from file into local array ***/ + max_elements = ca_element_count(chanid); + field_type = ca_field_type(chanid); + field_size = dbr_size[field_type]; + /* if we've already allocated a big enough memory block, use it */ + if ((p_data == NULL) || ((max_elements * field_size) > p_data_size)) { + if (save_restoreDebug >= 1) { + printf("save_restore:manual_array_restore: p_data = %p, p_data_size = %ld\n", p_data, p_data_size); + } + if (p_data) free(p_data); + p_data = (void *)calloc(max_elements, field_size); + p_data_size = p_data ? max_elements * field_size : 0; + if (save_restoreDebug >= 10) + printf("save_restore:manual_array_restore: allocated p_data = %p, p_data_size = %ld\n", p_data, + p_data_size); + } else { + memset(p_data, 0, p_data_size); + } + if (save_restoreDebug >= 10) { + printf("save_restore:manual_array_restore: Looking for up to %ld elements of field-size %d\n", max_elements, + field_size); + printf("save_restore:manual_array_restore: ...field_type is (%d)\n", field_type); + } - /** read array values **/ - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: parsing buffer '%s'\n", value_string); - } + switch (field_type) { + case DBF_STRING: + case DBF_CHAR: p_char = (char *)p_data; break; + case DBF_ENUM: p_ushort = (unsigned short *)p_data; break; + case DBF_SHORT: p_short = (short *)p_data; break; + case DBF_LONG: p_long = (epicsInt32 *)p_data; break; + case DBF_FLOAT: p_float = (float *)p_data; break; + case DBF_DOUBLE: p_double = (double *)p_data; break; + default: + printf("save_restore:manual_array_restore: field_type '%d' not handled\n", field_type); + status = -1; + break; + } + } - if (value_string==NULL || *value_string=='\0') { - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: value_string is null or empty\n"); - } - /* nothing to write; write zero or "" */ - if (p_data && !gobble) { - switch (field_type) { - case DBF_STRING: strcpy(p_char, ""); break; - case DBF_ENUM: p_ushort[num_read++] = (unsigned short)0; break; - case DBF_CHAR: p_char[num_read++] = (char)0; break; - case DBF_SHORT: p_short[num_read++] = (short)0; break; - case DBF_LONG: p_long[num_read++] = (epicsInt32) 0; break; - case DBF_FLOAT: p_float[num_read++] = 0; break; - case DBF_DOUBLE: p_double[num_read++] = 0; break; - default: - break; - } - } - } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) == NULL) { - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: ARRAY_BEGIN not found\n"); - } - /* doesn't look like array data. just restore what we have */ - if (p_data && !gobble) { - /* We do know the length of the buffer for sure, because this + /** read array values **/ + if (save_restoreDebug >= 11) { printf("save_restore:manual_array_restore: parsing buffer '%s'\n", value_string); } + + if (value_string == NULL || *value_string == '\0') { + if (save_restoreDebug >= 11) { printf("save_restore:manual_array_restore: value_string is null or empty\n"); } + /* nothing to write; write zero or "" */ + if (p_data && !gobble) { + switch (field_type) { + case DBF_STRING: strcpy(p_char, ""); break; + case DBF_ENUM: p_ushort[num_read++] = (unsigned short)0; break; + case DBF_CHAR: p_char[num_read++] = (char)0; break; + case DBF_SHORT: p_short[num_read++] = (short)0; break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)0; break; + case DBF_FLOAT: p_float[num_read++] = 0; break; + case DBF_DOUBLE: p_double[num_read++] = 0; break; + default: break; + } + } + } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) == NULL) { + if (save_restoreDebug >= 11) { printf("save_restore:manual_array_restore: ARRAY_BEGIN not found\n"); } + /* doesn't look like array data. just restore what we have */ + if (p_data && !gobble) { + /* We do know the length of the buffer for sure, because this depends on the calling code, so we limit to the actual string size. The buffer must be one byte longer due to the terminating null byte. */ - size_t value_string_len = strlen(value_string) + 1; - epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); - switch (field_type) { - case DBF_STRING: - /* future: translate escape sequence */ - strNcpy(&(p_char[(num_read++)*MAX_STRING_SIZE]), value_string, MAX_STRING_SIZE); - break; - case DBF_ENUM: - p_ushort[num_read++] = (unsigned short)atol(value_string); - break; - case DBF_CHAR: - p_char[num_read++] = (char)atol(value_string); - break; - case DBF_SHORT: - p_short[num_read++] = (short)atol(value_string); - break; - case DBF_LONG: - p_long[num_read++] = (epicsInt32) atol(value_string); - break; - case DBF_FLOAT: - p_float[num_read++] = mySafeDoubleToFloat(atof(value_string)); - break; - case DBF_DOUBLE: - p_double[num_read++] = atof(value_string); - break; - default: - break; - } - } - } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { - begin_mark_found = 1; - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: parsing array buffer '%s'\n", bp); - } - for (num_read=0; bp && !end_mark_found; ) { - /* Find beginning of array element */ - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: looking for element[%ld] \n", num_read); - } - /* If truncated-file detector (checkFile) fails, test for end of file before + size_t value_string_len = strlen(value_string) + 1; + epicsStrnRawFromEscaped(value_string, value_string_len, value_string, value_string_len); + switch (field_type) { + case DBF_STRING: + /* future: translate escape sequence */ + strNcpy(&(p_char[(num_read++) * MAX_STRING_SIZE]), value_string, MAX_STRING_SIZE); + break; + case DBF_ENUM: p_ushort[num_read++] = (unsigned short)atol(value_string); break; + case DBF_CHAR: p_char[num_read++] = (char)atol(value_string); break; + case DBF_SHORT: p_short[num_read++] = (short)atol(value_string); break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)atol(value_string); break; + case DBF_FLOAT: p_float[num_read++] = mySafeDoubleToFloat(atof(value_string)); break; + case DBF_DOUBLE: p_double[num_read++] = atof(value_string); break; + default: break; + } + } + } else if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { + begin_mark_found = 1; + if (save_restoreDebug >= 10) { printf("save_restore:manual_array_restore: parsing array buffer '%s'\n", bp); } + for (num_read = 0; bp && !end_mark_found;) { + /* Find beginning of array element */ + if (save_restoreDebug >= 10) { + printf("save_restore:manual_array_restore: looking for element[%ld] \n", num_read); + } + /* If truncated-file detector (checkFile) fails, test for end of file before * using *bp */ - while (!end_mark_found && !end_of_file && (*bp != ELEMENT_BEGIN)) { - if (save_restoreDebug >= 12) { - printf("save_restore:manual_array_restore: ...buffer contains '%s'\n", bp); - } - switch (*bp) { - case '\0': - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - printf("save_restore: *** EOF during array-parse\n"); - end_of_file = 1; - } - break; - case ARRAY_END: - end_mark_found = 1; - break; - default: - ++bp; - break; - } - } - /* + while (!end_mark_found && !end_of_file && (*bp != ELEMENT_BEGIN)) { + if (save_restoreDebug >= 12) { + printf("save_restore:manual_array_restore: ...buffer contains '%s'\n", bp); + } + switch (*bp) { + case '\0': + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + printf("save_restore: *** EOF during array-parse\n"); + end_of_file = 1; + } + break; + case ARRAY_END: end_mark_found = 1; break; + default: ++bp; break; + } + } + /* * Read one element: Accumulate characters of element value into string[], * ignoring any nonzero control characters, and append the value to the local array. */ - if (bp && !end_mark_found && !end_of_file) { - /* *bp == ELEMENT_BEGIN */ - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: Found element-begin; buffer contains '%s'\n", bp); - } - for (bp++, j=0; (j < MAX_STRING_SIZE-1) && (*bp != ELEMENT_END); bp++) { - if (save_restoreDebug >= 11) printf("save_restore:manual_array_restore: *bp=%c (%d)\n", *bp, (int)*bp); - if (*bp == '\0') { - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - printf("save_restore:array_restore: *** premature EOF.\n"); - end_of_file = 1; - break; - } - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: new buffer: '%s'\n", bp); - } - if (*bp == ELEMENT_END) break; - } else if ((*bp == ESCAPE) && ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { - /* escaped character */ - bp++; - } - if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ - } - string[j] = '\0'; - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: element[%ld] value = '%s'\n", num_read, string); - if (bp) printf("save_restore:manual_array_restore: look for element-end: buffer contains '%s'\n", bp); - } - /* + if (bp && !end_mark_found && !end_of_file) { + /* *bp == ELEMENT_BEGIN */ + if (save_restoreDebug >= 11) { + printf("save_restore:manual_array_restore: Found element-begin; buffer contains '%s'\n", bp); + } + for (bp++, j = 0; (j < MAX_STRING_SIZE - 1) && (*bp != ELEMENT_END); bp++) { + if (save_restoreDebug >= 11) + printf("save_restore:manual_array_restore: *bp=%c (%d)\n", *bp, (int)*bp); + if (*bp == '\0') { + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + printf("save_restore:array_restore: *** premature EOF.\n"); + end_of_file = 1; + break; + } + if (save_restoreDebug >= 11) { + printf("save_restore:manual_array_restore: new buffer: '%s'\n", bp); + } + if (*bp == ELEMENT_END) break; + } else if ((*bp == ESCAPE) && + ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { + /* escaped character */ + bp++; + } + if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ + } + string[j] = '\0'; + if (save_restoreDebug >= 10) { + printf("save_restore:manual_array_restore: element[%ld] value = '%s'\n", num_read, string); + if (bp) + printf("save_restore:manual_array_restore: look for element-end: buffer contains '%s'\n", bp); + } + /* * We've accumulated all the characters, or all we can handle in string[]. * If there are more characters than we can handle, just pretend we read them. */ - /* *bp == ELEMENT_END ,*/ - for (found = 0; (found == 0) && !end_of_file; ) { - while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; - switch (*bp) { - case ELEMENT_END: - found = 1; - bp++; - break; - case ESCAPE: - ++bp; - if (*bp == ELEMENT_END || *bp == ESCAPE) { - ++bp; - } - break; - default: - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - end_of_file = 1; - found = 1; - } - } - } - if (!gobble && (num_read= 10) && p_data && !gobble) { - printf("\nsave_restore: %ld array values:\n", num_read); - for (j=0; j= 10) { - printf("save_restore:manual_array_restore: looking for ARRAY_END\n"); - } - in_element = 0; - while (!end_mark_found && !end_of_file) { - if (save_restoreDebug >= 11) { - printf("save_restore:manual_array_restore: ...buffer contains '%s'\n", bp); - } - switch (*bp) { - case ESCAPE: - if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ - break; - case ARRAY_END: - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: found ARRAY_END. in_element=%d\n", in_element); - } - if (!in_element) end_mark_found = 1; - break; - case '\0': - if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { - printf("save_restore:manual_array_restore: *** EOF during array-end search\n"); - end_of_file = 1; - } - break; - default: - /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ - if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; - break; - } - if (bp) ++bp; - } - } else { - if (save_restoreDebug >= 10) { - printf("save_restore:manual_array_restore: ARRAY_BEGIN wasn't found.\n"); - } - } - if (!status && end_of_file) { - status = end_of_file; - printf("save_restore:manual_array_restore: status = end_of_file.\n"); - } - - if (gobble) { - if (save_restoreDebug >= 1) { - printf("save_restore:manual_array_restore: Gobbled unused array data.\n"); - } - } else { - if (!status && p_data) { - if (save_restoreDebug >= 1) { - printf("save_restore:manual_array_restore: Writing array to database\n"); - } - if (ca_array_put(field_type, num_read, chanid, p_data) != ECA_NORMAL) { - printf("save_restore:manual_array_restore: ca_array_put to '%s' failed\n",PVname); - return (-1); - } - } else { - if (save_restoreDebug >= 1) { - printf("save_restore:manual_array_restore: No array write to database attempted because of error condition\n"); - printf("save_restore:manual_array_restore: status=%ld, p_data=%p\n", status, p_data); - } - } - } - if ((p_data == NULL) && !gobble) status = -1; - return(status); -} + /* *bp == ELEMENT_END ,*/ + for (found = 0; (found == 0) && !end_of_file;) { + while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; + switch (*bp) { + case ELEMENT_END: + found = 1; + bp++; + break; + case ESCAPE: + ++bp; + if (*bp == ELEMENT_END || *bp == ESCAPE) { ++bp; } + break; + default: + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + end_of_file = 1; + found = 1; + } + } + } + if (!gobble && (num_read < max_elements)) { + /* Append value to local array. */ + if (p_data) { + epicsStrnRawFromEscaped(string, MAX_STRING_SIZE, string, MAX_STRING_SIZE); + switch (field_type) { + case DBF_STRING: + strNcpy(&(p_char[(num_read++) * MAX_STRING_SIZE]), string, MAX_STRING_SIZE); + break; + case DBF_ENUM: p_ushort[num_read++] = (unsigned short)atol(string); break; + case DBF_CHAR: p_char[num_read++] = (char)atol(string); break; + case DBF_SHORT: p_short[num_read++] = (short)atol(string); break; + case DBF_LONG: p_long[num_read++] = (epicsInt32)atol(string); break; + case DBF_FLOAT: p_float[num_read++] = mySafeDoubleToFloat(atof(string)); break; + case DBF_DOUBLE: p_double[num_read++] = atof(string); break; + default: break; + } + } + } + } + } /* for (num_read=0; bp && !end_mark_found; ) */ + + if ((save_restoreDebug >= 10) && p_data && !gobble) { + printf("\nsave_restore: %ld array values:\n", num_read); + for (j = 0; j < num_read; j++) { + switch (field_type) { + case DBF_STRING: printf(" '%s'\n", &(p_char[j * MAX_STRING_SIZE])); break; + case DBF_ENUM: printf(" %u\n", p_ushort[j]); break; + case DBF_SHORT: printf(" %d\n", p_short[j]); break; + case DBF_CHAR: printf(" '%c' (%d)\n", p_char[j], p_char[j]); break; + case DBF_LONG: printf(" %d\n", p_long[j]); break; + case DBF_FLOAT: printf(" %f\n", p_float[j]); break; + case DBF_DOUBLE: printf(" %g\n", p_double[j]); break; + default: break; + } + } + printf("save_restore: end of %ld array values.\n\n", num_read); + epicsThreadSleep(0.5); + } + } /* if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) */ + + /* leave the file pointer ready for next PV (next fgets() should yield next PV) */ + if (begin_mark_found) { + /* find ARRAY_END (but ARRAY_END inside an element is just another character) */ + if (save_restoreDebug >= 10) { printf("save_restore:manual_array_restore: looking for ARRAY_END\n"); } + in_element = 0; + while (!end_mark_found && !end_of_file) { + if (save_restoreDebug >= 11) { printf("save_restore:manual_array_restore: ...buffer contains '%s'\n", bp); } + switch (*bp) { + case ESCAPE: + if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ + break; + case ARRAY_END: + if (save_restoreDebug >= 10) { + printf("save_restore:manual_array_restore: found ARRAY_END. in_element=%d\n", in_element); + } + if (!in_element) end_mark_found = 1; + break; + case '\0': + if ((bp = fgets(buffer, BUF_SIZE, inp_fd)) == NULL) { + printf("save_restore:manual_array_restore: *** EOF during array-end search\n"); + end_of_file = 1; + } + break; + default: + /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ + if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; + break; + } + if (bp) ++bp; + } + } else { + if (save_restoreDebug >= 10) { printf("save_restore:manual_array_restore: ARRAY_BEGIN wasn't found.\n"); } + } + if (!status && end_of_file) { + status = end_of_file; + printf("save_restore:manual_array_restore: status = end_of_file.\n"); + } + if (gobble) { + if (save_restoreDebug >= 1) { printf("save_restore:manual_array_restore: Gobbled unused array data.\n"); } + } else { + if (!status && p_data) { + if (save_restoreDebug >= 1) { printf("save_restore:manual_array_restore: Writing array to database\n"); } + if (ca_array_put(field_type, num_read, chanid, p_data) != ECA_NORMAL) { + printf("save_restore:manual_array_restore: ca_array_put to '%s' failed\n", PVname); + return (-1); + } + } else { + if (save_restoreDebug >= 1) { + printf( + "save_restore:manual_array_restore: No array write to database attempted because of error " + "condition\n"); + printf("save_restore:manual_array_restore: status=%ld, p_data=%p\n", status, p_data); + } + } + } + if ((p_data == NULL) && !gobble) status = -1; + return (status); +} STATIC int do_manual_restore(char *filename, int file_type, char *macrostring) { - struct channel *pchannel; - struct chlist *plist; - int found, is_scalar; - char PVname[80]; - char restoreFile[NFS_PATH_LEN+1] = ""; - char bu_filename[NFS_PATH_LEN+1] = ""; - char buffer[BUF_SIZE], *bp, c; - char ebuffer[EBUF_SIZE]; - char value_string[BUF_SIZE]; - int n; - long status, num_errs=0; - FILE *inp_fd; - chid chanid = 0; - char realName[PV_NAME_LEN]; /* name without trailing '$' */ - int is_long_string; - MAC_HANDLE *handle = NULL; - char **pairs = NULL; - - if (save_restoreDebug >= 5) { - printf("save_restore:do_manual_restore: entry for file '%s'\n", filename); - } - if (file_type == FROM_SAVE_FILE) { - /* if this is the current file name for a save set - restore from there */ - if (waitForListLock(5) == 0) { - printf("do_manual_restore:failed to lock resource. Try later.\n"); - return(ERROR); - } - for (plist=lptr, found=0; plist && !found; ) { - if (strcmp(plist->last_save_file,filename) == 0) { - found = 1; - } else { - plist = plist->pnext; - } - } - if (found) { - /* verify quality of the save set */ - if (plist->not_connected > 0) { - printf("save_restore:do_manual_restore: %d channel(s) not connected or fetched\n", - plist->not_connected); - if (!save_restoreIncompleteSetsOk) { - printf("save_restore:do_manual_restore: aborting restore\n"); - unlockList(); - strNcpy(SR_recentlyStr, "Manual restore failed",STATUS_STR_LEN); - printf("do_manual_restore:failed because some PVs not connected\n"); - return(ERROR); - } - } - - for (pchannel = plist->pchan_list; pchannel !=0; pchannel = pchannel->pnext) { - if (pchannel->curr_elements <= 1) { - status = ca_put(DBR_STRING, pchannel->chid, pchannel->value); - if (status!=ECA_NORMAL) - printf("do_manual_restore:ca_put() to '%s' failed with %lu.\n", - pchannel->name, status); - } else { - status = SR_put_array_values(pchannel->name, pchannel->pArray, pchannel->curr_elements); - if (status!=ECA_NORMAL) - printf("do_manual_restore:SR_put_array_values() to '%s' failed with %lu.\n", - pchannel->name, status); - } - if (status!=ECA_NORMAL) num_errs++; - } - if (ca_pend_io(1.0) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: not all channels restored\n"); - } - unlockList(); - if (num_errs == 0) { - strNcpy(SR_recentlyStr, "Manual restore succeeded",STATUS_STR_LEN); - } else { - epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN-1, "%ld errors during manual restore", num_errs); - } - return(num_errs); - } - unlockList(); - } + struct channel *pchannel; + struct chlist *plist; + int found, is_scalar; + char PVname[80]; + char restoreFile[NFS_PATH_LEN + 1] = ""; + char bu_filename[NFS_PATH_LEN + 1] = ""; + char buffer[BUF_SIZE], *bp, c; + char ebuffer[EBUF_SIZE]; + char value_string[BUF_SIZE]; + int n; + long status, num_errs = 0; + FILE *inp_fd; + chid chanid = 0; + char realName[PV_NAME_LEN]; /* name without trailing '$' */ + int is_long_string; + MAC_HANDLE *handle = NULL; + char **pairs = NULL; + + if (save_restoreDebug >= 5) { printf("save_restore:do_manual_restore: entry for file '%s'\n", filename); } + if (file_type == FROM_SAVE_FILE) { + /* if this is the current file name for a save set - restore from there */ + if (waitForListLock(5) == 0) { + printf("do_manual_restore:failed to lock resource. Try later.\n"); + return (ERROR); + } + for (plist = lptr, found = 0; plist && !found;) { + if (strcmp(plist->last_save_file, filename) == 0) { + found = 1; + } else { + plist = plist->pnext; + } + } + if (found) { + /* verify quality of the save set */ + if (plist->not_connected > 0) { + printf("save_restore:do_manual_restore: %d channel(s) not connected or fetched\n", + plist->not_connected); + if (!save_restoreIncompleteSetsOk) { + printf("save_restore:do_manual_restore: aborting restore\n"); + unlockList(); + strNcpy(SR_recentlyStr, "Manual restore failed", STATUS_STR_LEN); + printf("do_manual_restore:failed because some PVs not connected\n"); + return (ERROR); + } + } + + for (pchannel = plist->pchan_list; pchannel != 0; pchannel = pchannel->pnext) { + if (pchannel->curr_elements <= 1) { + status = ca_put(DBR_STRING, pchannel->chid, pchannel->value); + if (status != ECA_NORMAL) + printf("do_manual_restore:ca_put() to '%s' failed with %lu.\n", pchannel->name, status); + } else { + status = SR_put_array_values(pchannel->name, pchannel->pArray, pchannel->curr_elements); + if (status != ECA_NORMAL) + printf("do_manual_restore:SR_put_array_values() to '%s' failed with %lu.\n", pchannel->name, + status); + } + if (status != ECA_NORMAL) num_errs++; + } + if (ca_pend_io(1.0) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: not all channels restored\n"); + } + unlockList(); + if (num_errs == 0) { + strNcpy(SR_recentlyStr, "Manual restore succeeded", STATUS_STR_LEN); + } else { + epicsSnprintf(SR_recentlyStr, STATUS_STR_LEN - 1, "%ld errors during manual restore", num_errs); + } + return (num_errs); + } + unlockList(); + } - /* open file */ - if (isAbsolute(filename)) { - strNcpy(restoreFile, filename, NFS_PATH_LEN); - } else { - makeNfsPath(restoreFile, saveRestoreFilePath, filename); - } + /* open file */ + if (isAbsolute(filename)) { + strNcpy(restoreFile, filename, NFS_PATH_LEN); + } else { + makeNfsPath(restoreFile, saveRestoreFilePath, filename); + } - if (file_type == FROM_SAVE_FILE) { - inp_fd = fopen_and_check(restoreFile, &status); - } else { - inp_fd = fopen(restoreFile, "r"); - } - if (inp_fd == NULL) { - printf("save_restore:do_manual_restore: Can't open save file."); - strNcpy(SR_recentlyStr, "Manual restore failed",STATUS_STR_LEN); - return(ERROR); - } + if (file_type == FROM_SAVE_FILE) { + inp_fd = fopen_and_check(restoreFile, &status); + } else { + inp_fd = fopen(restoreFile, "r"); + } + if (inp_fd == NULL) { + printf("save_restore:do_manual_restore: Can't open save file."); + strNcpy(SR_recentlyStr, "Manual restore failed", STATUS_STR_LEN); + return (ERROR); + } - if (file_type == FROM_SAVE_FILE) { - (void)fgets(buffer, BUF_SIZE, inp_fd); /* discard header line */ - } + if (file_type == FROM_SAVE_FILE) { (void)fgets(buffer, BUF_SIZE, inp_fd); /* discard header line */ } + + /* Prepare to use macro substitution */ + if (macrostring && macrostring[0]) { + macCreateHandle(&handle, NULL); + if (handle) { + macParseDefns(handle, macrostring, &pairs); + if (pairs) macInstallMacros(handle, pairs); + if (save_restoreDebug >= 5) { + printf("save_restore:do_manual_restore: Current macro definitions:\n"); + macReportMacros(handle); + printf("save_restore:do_manual_restore: --------------------------\n"); + } + } + } - /* Prepare to use macro substitution */ - if (macrostring && macrostring[0]) { - macCreateHandle(&handle, NULL); - if (handle) { - macParseDefns(handle, macrostring, &pairs); - if (pairs) macInstallMacros(handle, pairs); - if (save_restoreDebug >= 5) { - printf("save_restore:do_manual_restore: Current macro definitions:\n"); - macReportMacros(handle); - printf("save_restore:do_manual_restore: --------------------------\n"); - } - } - } + /* restore from data file */ + while ((bp = fgets(buffer, BUF_SIZE, inp_fd))) { + if (handle && pairs) { + ebuffer[0] = '\0'; + macExpandString(handle, buffer, ebuffer, EBUF_SIZE); + bp = ebuffer; + } - /* restore from data file */ - while ((bp=fgets(buffer, BUF_SIZE, inp_fd))) { - if (handle && pairs) { - ebuffer[0] = '\0'; - macExpandString(handle, buffer, ebuffer, EBUF_SIZE); - bp = ebuffer; - } - - /* get PV_name, one space character, value */ - /* (value may be a string with leading whitespace; it may be */ - /* entirely whitespace; the number of spaces may be crucial; */ - /* it might also consist of zero characters) */ - n = sscanf(bp,"%s%c%[^\n]", PVname, &c, value_string); - if (n < 3) *value_string = 0; - if (strncmp(PVname, "", 5) == 0) { - break; - } - if (save_restoreDebug >= 5) { - printf("save_restore:do_manual_restore: PVname='%s'\n", PVname); - } - if (isValid1stPVChar((int)PVname[0])) { - /* handle long string name */ - strNcpy(realName, PVname, PV_NAME_LEN); - is_long_string = 0; - if (realName[strlen(realName)-1] == '$') { - realName[strlen(realName)-1] = '\0'; - is_long_string = 1; - } - is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); - if (is_scalar) { - long num_elements, field_size, field_type; - /* check the field itself, because an empty string is saved as no value at all , which would look like a scalar. */ - SR_get_array_info(PVname, &num_elements, &field_size, &field_type); - if (num_elements > 1) { - if (save_restoreDebug >= 5) { - printf("save_restore:do_manual_restore: PV '%s' is scalar in .sav file, but has %ld elements. Treating as array.\n", - PVname, num_elements); - } - is_scalar = 0; - } - } - if (is_scalar || is_long_string) { - if (!is_long_string) { - /* Discard additional characters until end of line */ - while (bp[strlen(bp)-1] != '\n') fgets(buffer, BUF_SIZE, inp_fd); - epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); - value_string[40] = '\0'; - if (ca_search(realName, &chanid) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_search for %s failed\n", realName); - num_errs++; - } else if (ca_pend_io(0.5) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_search for %s timeout\n", realName); - num_errs++; - } else if (ca_put(DBR_STRING, chanid, value_string) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_put of %s to %s failed\n", value_string,realName); - num_errs++; - } - } else { - if (save_restoreDebug >= 5) { - printf("save_restore:do_manual_restore: PV '%s' is long string; value='%s'.\n", PVname, value_string); - } - /* See if we got the whole line */ - if (bp[strlen(bp)-1] != '\n') { - /* No, we didn't. One more read will certainly accumulate a value string of length BUF_SIZE */ - bp = fgets(buffer, BUF_SIZE, inp_fd); - n = BUF_SIZE-strlen(value_string)-1; - strncat(value_string, bp, n); - if (value_string[strlen(value_string)-1] == '\n') value_string[strlen(value_string)-1] = '\0'; - } - /* Discard additional characters until end of line */ - while (bp[strlen(bp)-1] != '\n') bp = fgets(buffer, BUF_SIZE, inp_fd); - epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); - if (ca_search(PVname, &chanid) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_search for %s failed\n", PVname); - num_errs++; - } else if (ca_pend_io(0.5) != ECA_NORMAL) { - num_errs++; - /* Don't forget trailing null character: "strlen(value_string)+1" below */ - } else if (ca_array_put(DBR_CHAR, strlen(value_string)+1, chanid, value_string) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_array_put of '%s' to '%s' failed\n", value_string,PVname); - num_errs++; - } - } - } else { - /* array restore */ - int gobble = 0; - - if (ca_search(PVname, &chanid) != ECA_NORMAL) { - printf("save_restore:do_manual_restore: ca_search for %s failed\n", PVname); - num_errs++; - gobble = 1; - } else if (ca_pend_io(0.5) != ECA_NORMAL) { - num_errs++; - gobble = 1; - } - status = manual_array_restore(inp_fd, PVname, chanid, value_string, gobble); - - if (status) { - num_errs++; - printf("save_restore:do_manual_restore: manual_array_restore() returned %ld\n", status); - } - } - if (chanid) { - ca_clear_channel(chanid); - chanid = 0; - } - } else if (PVname[0] == '!') { - n = atoi(value_string); /* value_string actually contains 2nd word of error msg */ - num_errs += n; - printf("save_restore:do_manual_restore: %d PV%c had no saved value\n", - n, (n==1) ? ' ':'s'); - if (!save_restoreIncompleteSetsOk) { - printf("save_restore:do_manual_restore: aborting restore\n"); - fclose(inp_fd); - if (handle) macDeleteHandle(handle); - if (pairs) free(pairs); - strNcpy(SR_recentlyStr, "Manual restore failed",STATUS_STR_LEN); - if (p_data) { - free(p_data); - p_data = NULL; - p_data_size = 0; - } - return(ERROR); - } - } else if (PVname[0] == '#') { - /* comment line */ - is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); - if (!is_scalar) { - /* Parse and gobble up the whole array, without restoring anything. */ - status = SR_array_restore(1, inp_fd, PVname, value_string, 1); - } - } - } - fclose(inp_fd); - if (handle) macDeleteHandle(handle); - if (pairs) free(pairs); - - if (file_type == FROM_SAVE_FILE) { - /* make backup */ - strNcpy(bu_filename,restoreFile, NFS_PATH_LEN); - strncat(bu_filename,".bu", NFS_PATH_LEN-1-strlen(bu_filename)); - (void)myFileCopy(restoreFile,bu_filename); - } - strNcpy(SR_recentlyStr, "Manual restore succeeded",STATUS_STR_LEN); + /* get PV_name, one space character, value */ + /* (value may be a string with leading whitespace; it may be */ + /* entirely whitespace; the number of spaces may be crucial; */ + /* it might also consist of zero characters) */ + n = sscanf(bp, "%s%c%[^\n]", PVname, &c, value_string); + if (n < 3) *value_string = 0; + if (strncmp(PVname, "", 5) == 0) { break; } + if (save_restoreDebug >= 5) { printf("save_restore:do_manual_restore: PVname='%s'\n", PVname); } + if (isValid1stPVChar((int)PVname[0])) { + /* handle long string name */ + strNcpy(realName, PVname, PV_NAME_LEN); + is_long_string = 0; + if (realName[strlen(realName) - 1] == '$') { + realName[strlen(realName) - 1] = '\0'; + is_long_string = 1; + } + is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); + if (is_scalar) { + long num_elements, field_size, field_type; + /* check the field itself, because an empty string is saved as no value at all , which would look like a scalar. */ + SR_get_array_info(PVname, &num_elements, &field_size, &field_type); + if (num_elements > 1) { + if (save_restoreDebug >= 5) { + printf( + "save_restore:do_manual_restore: PV '%s' is scalar in .sav file, but has %ld elements. " + "Treating as array.\n", + PVname, num_elements); + } + is_scalar = 0; + } + } + if (is_scalar || is_long_string) { + if (!is_long_string) { + /* Discard additional characters until end of line */ + while (bp[strlen(bp) - 1] != '\n') fgets(buffer, BUF_SIZE, inp_fd); + epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); + value_string[40] = '\0'; + if (ca_search(realName, &chanid) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_search for %s failed\n", realName); + num_errs++; + } else if (ca_pend_io(0.5) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_search for %s timeout\n", realName); + num_errs++; + } else if (ca_put(DBR_STRING, chanid, value_string) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_put of %s to %s failed\n", value_string, realName); + num_errs++; + } + } else { + if (save_restoreDebug >= 5) { + printf("save_restore:do_manual_restore: PV '%s' is long string; value='%s'.\n", PVname, + value_string); + } + /* See if we got the whole line */ + if (bp[strlen(bp) - 1] != '\n') { + /* No, we didn't. One more read will certainly accumulate a value string of length BUF_SIZE */ + bp = fgets(buffer, BUF_SIZE, inp_fd); + n = BUF_SIZE - strlen(value_string) - 1; + strncat(value_string, bp, n); + if (value_string[strlen(value_string) - 1] == '\n') + value_string[strlen(value_string) - 1] = '\0'; + } + /* Discard additional characters until end of line */ + while (bp[strlen(bp) - 1] != '\n') bp = fgets(buffer, BUF_SIZE, inp_fd); + epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); + if (ca_search(PVname, &chanid) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_search for %s failed\n", PVname); + num_errs++; + } else if (ca_pend_io(0.5) != ECA_NORMAL) { + num_errs++; + /* Don't forget trailing null character: "strlen(value_string)+1" below */ + } else if (ca_array_put(DBR_CHAR, strlen(value_string) + 1, chanid, value_string) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_array_put of '%s' to '%s' failed\n", value_string, + PVname); + num_errs++; + } + } + } else { + /* array restore */ + int gobble = 0; + + if (ca_search(PVname, &chanid) != ECA_NORMAL) { + printf("save_restore:do_manual_restore: ca_search for %s failed\n", PVname); + num_errs++; + gobble = 1; + } else if (ca_pend_io(0.5) != ECA_NORMAL) { + num_errs++; + gobble = 1; + } + status = manual_array_restore(inp_fd, PVname, chanid, value_string, gobble); + + if (status) { + num_errs++; + printf("save_restore:do_manual_restore: manual_array_restore() returned %ld\n", status); + } + } + if (chanid) { + ca_clear_channel(chanid); + chanid = 0; + } + } else if (PVname[0] == '!') { + n = atoi(value_string); /* value_string actually contains 2nd word of error msg */ + num_errs += n; + printf("save_restore:do_manual_restore: %d PV%c had no saved value\n", n, (n == 1) ? ' ' : 's'); + if (!save_restoreIncompleteSetsOk) { + printf("save_restore:do_manual_restore: aborting restore\n"); + fclose(inp_fd); + if (handle) macDeleteHandle(handle); + if (pairs) free(pairs); + strNcpy(SR_recentlyStr, "Manual restore failed", STATUS_STR_LEN); + if (p_data) { + free(p_data); + p_data = NULL; + p_data_size = 0; + } + return (ERROR); + } + } else if (PVname[0] == '#') { + /* comment line */ + is_scalar = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN); + if (!is_scalar) { + /* Parse and gobble up the whole array, without restoring anything. */ + status = SR_array_restore(1, inp_fd, PVname, value_string, 1); + } + } + } + fclose(inp_fd); + if (handle) macDeleteHandle(handle); + if (pairs) free(pairs); + + if (file_type == FROM_SAVE_FILE) { + /* make backup */ + strNcpy(bu_filename, restoreFile, NFS_PATH_LEN); + strncat(bu_filename, ".bu", NFS_PATH_LEN - 1 - strlen(bu_filename)); + (void)myFileCopy(restoreFile, bu_filename); + } + strNcpy(SR_recentlyStr, "Manual restore succeeded", STATUS_STR_LEN); - if (p_data) { - free(p_data); - p_data = NULL; - p_data_size = 0; - } + if (p_data) { + free(p_data); + p_data = NULL; + p_data_size = 0; + } - return(num_errs); + return (num_errs); } /* Try to open reqFile, using reqFilePathList. If successful, return 1, else 0. @@ -3600,475 +3468,528 @@ STATIC int do_manual_restore(char *filename, int file_type, char *macrostring) #define RECENTCHARS 100 int openReqFile(const char *reqFile, FILE **fpp) { - struct pathListElement *p; - char tmpfile[NFS_PATH_LEN+1] = ""; - FILE *trial_fd = NULL; - static char recentlyFound[NUMRECENT][RECENTCHARS] = {""}; - static char recentlyNotFound[NUMRECENT][RECENTCHARS] = {""}; - int i; - - /* if fpp==NULL, caller only wants to know if file exists. In that case, save time + struct pathListElement *p; + char tmpfile[NFS_PATH_LEN + 1] = ""; + FILE *trial_fd = NULL; + static char recentlyFound[NUMRECENT][RECENTCHARS] = {""}; + static char recentlyNotFound[NUMRECENT][RECENTCHARS] = {""}; + int i; + + /* if fpp==NULL, caller only wants to know if file exists. In that case, save time * by checking to see if we just found, or failed to find, the file on last call. */ - if (fpp == NULL) { - for (i=0; i 5) printf("openReqFile: using cached found value for '%s'\n", reqFile); - return(1); - } - if (recentlyNotFound[i][0] && (strncmp(reqFile, recentlyNotFound[i], RECENTCHARS-1)==0)) { - if (save_restoreDebug > 5) printf("openReqFile: using cached not-found value for '%s'\n", reqFile); - return(0); - } - } - } + if (fpp == NULL) { + for (i = 0; i < NUMRECENT; i++) { + if (recentlyFound[i][0] && (strncmp(reqFile, recentlyFound[i], RECENTCHARS - 1) == 0)) { + if (save_restoreDebug > 5) printf("openReqFile: using cached found value for '%s'\n", reqFile); + return (1); + } + if (recentlyNotFound[i][0] && (strncmp(reqFile, recentlyNotFound[i], RECENTCHARS - 1) == 0)) { + if (save_restoreDebug > 5) printf("openReqFile: using cached not-found value for '%s'\n", reqFile); + return (0); + } + } + } - if (fpp) *fpp = NULL; - if (save_restoreDebug > 5) { - printf("save_restore:openReqFile: entry: reqFile='%s', fpp=%p\n", reqFile, fpp); - } + if (fpp) *fpp = NULL; + if (save_restoreDebug > 5) { printf("save_restore:openReqFile: entry: reqFile='%s', fpp=%p\n", reqFile, fpp); } - /* open request file */ - if (reqFilePathList) { - /* try to find reqFile in every directory specified in reqFilePathList */ - for (p = reqFilePathList; p; p = p->pnext) { - makeNfsPath(tmpfile, p->path, reqFile); - trial_fd = fopen(tmpfile, "r"); - if (trial_fd) break; - } - } else { - /* try to find reqFile only in current working directory */ - trial_fd = fopen(reqFile, "r"); - } - if (fpp) *fpp = trial_fd; - if (trial_fd) { - if (fpp == NULL) fclose(trial_fd); - if (save_restoreDebug > 5) printf("openReqFile: found '%s' by searching\n", reqFile); - for (i=0; i 5) printf("openReqFile: didn't find '%s' by searching\n", reqFile); - return(0); - } + /* open request file */ + if (reqFilePathList) { + /* try to find reqFile in every directory specified in reqFilePathList */ + for (p = reqFilePathList; p; p = p->pnext) { + makeNfsPath(tmpfile, p->path, reqFile); + trial_fd = fopen(tmpfile, "r"); + if (trial_fd) break; + } + } else { + /* try to find reqFile only in current working directory */ + trial_fd = fopen(reqFile, "r"); + } + if (fpp) *fpp = trial_fd; + if (trial_fd) { + if (fpp == NULL) fclose(trial_fd); + if (save_restoreDebug > 5) printf("openReqFile: found '%s' by searching\n", reqFile); + for (i = 0; i < NUMRECENT - 1; i++) { strncpy(recentlyFound[i], recentlyFound[i + 1], RECENTCHARS - 1); } + strncpy(recentlyFound[i], reqFile, RECENTCHARS - 1); + return (1); + } else { + for (i = 0; i < NUMRECENT - 1; i++) { strncpy(recentlyNotFound[i], recentlyNotFound[i + 1], RECENTCHARS - 1); } + strncpy(recentlyNotFound[0], reqFile, RECENTCHARS - 1); + if (save_restoreDebug > 5) printf("openReqFile: didn't find '%s' by searching\n", reqFile); + return (0); + } } STATIC int readReqFile(const char *reqFile, struct chlist *plist, char *macrostring) { - struct channel *pchannel = NULL; - FILE *inp_fd = NULL; - char name[80] = "", *t=NULL, line[BUF_SIZE]="", eline[EBUF_SIZE]=""; - char templatefile[NFS_PATH_LEN+1] = ""; - char new_macro[BUF_SIZE] = ""; - int i=0; - MAC_HANDLE *handle = NULL; - char **pairs = NULL; - char *c; - - if (save_restoreDebug > 1) { - printf("save_restore:readReqFile: entry: reqFile='%s', plist=%p, macrostring='%s'\n", - reqFile, (void *)plist, macrostring?macrostring:"NULL"); - } + struct channel *pchannel = NULL; + FILE *inp_fd = NULL; + char name[80] = "", *t = NULL, line[BUF_SIZE] = "", eline[EBUF_SIZE] = ""; + char templatefile[NFS_PATH_LEN + 1] = ""; + char new_macro[BUF_SIZE] = ""; + int i = 0; + MAC_HANDLE *handle = NULL; + char **pairs = NULL; + char *c; + + if (save_restoreDebug > 1) { + printf("save_restore:readReqFile: entry: reqFile='%s', plist=%p, macrostring='%s'\n", reqFile, (void *)plist, + macrostring ? macrostring : "NULL"); + } - (void)openReqFile(reqFile, &inp_fd); - if (!inp_fd) { - plist->status = SR_STATUS_FAIL; - strNcpy(plist->statusStr, "Can't open .req file", STATUS_STR_LEN); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - printf("save_restore:readReqFile: unable to open file %s. Exiting.\n", reqFile); - return(ERROR); - } + (void)openReqFile(reqFile, &inp_fd); + if (!inp_fd) { + plist->status = SR_STATUS_FAIL; + strNcpy(plist->statusStr, "Can't open .req file", STATUS_STR_LEN); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + printf("save_restore:readReqFile: unable to open file %s. Exiting.\n", reqFile); + return (ERROR); + } - if (macrostring && macrostring[0]) { - macCreateHandle(&handle, NULL); - if (handle) { - macParseDefns(handle, macrostring, &pairs); - if (pairs) macInstallMacros(handle, pairs); - if (save_restoreDebug >= 5) { - printf("save_restore:readReqFile: Current macro definitions:\n"); - macReportMacros(handle); - printf("save_restore:readReqFile: --------------------------\n"); - } - } - } + if (macrostring && macrostring[0]) { + macCreateHandle(&handle, NULL); + if (handle) { + macParseDefns(handle, macrostring, &pairs); + if (pairs) macInstallMacros(handle, pairs); + if (save_restoreDebug >= 5) { + printf("save_restore:readReqFile: Current macro definitions:\n"); + macReportMacros(handle); + printf("save_restore:readReqFile: --------------------------\n"); + } + } + } + + /* place all of the channels in the group */ + while (fgets(line, BUF_SIZE, inp_fd)) { + /* If we didn't read the whole line, read/discard until we find newline or EOF */ + if ((strlen(line) > 0) && (line[strlen(line) - 1] != '\n')) { + strNcpy(eline, line, EBUF_SIZE); + while ((strlen(eline) > 0) && (eline[strlen(eline) - 1] != '\n')) { + if (save_restoreDebug) printf("save_restore:readReqFile: didn't reach newline:\n\t'%s'\n", eline); + if (fgets(eline, BUF_SIZE, inp_fd) == NULL) break; + if (save_restoreDebug) printf("save_restore:readReqFile: discard:\n\t'%s'\n", eline); + } + /* Also, we should make sure the line does not end in the middle of a macro definition */ + c = line + strlen(line) - 1; + while (c > line && *c != ',' && !isspace((int)*c)) c--; + *c = '\0'; + if (save_restoreDebug) printf("save_restore:readReqFile: line='%s'\n", line); + } - /* place all of the channels in the group */ - while (fgets(line, BUF_SIZE, inp_fd)) { - /* If we didn't read the whole line, read/discard until we find newline or EOF */ - if ((strlen(line)>0) && (line[strlen(line)-1] != '\n')) { - strNcpy(eline, line, EBUF_SIZE); - while ((strlen(eline)>0) && (eline[strlen(eline)-1] != '\n')) { - if (save_restoreDebug) printf("save_restore:readReqFile: didn't reach newline:\n\t'%s'\n", eline); - if (fgets(eline, BUF_SIZE, inp_fd) == NULL) break; - if (save_restoreDebug) printf("save_restore:readReqFile: discard:\n\t'%s'\n", eline); - } - /* Also, we should make sure the line does not end in the middle of a macro definition */ - c = line + strlen(line) - 1; - while (c>line && *c != ',' && !isspace((int)*c)) c--; - *c = '\0'; - if (save_restoreDebug) printf("save_restore:readReqFile: line='%s'\n", line); - } - - /* Expand input line. */ - name[0] = '\0'; - eline[0] = '\0'; - if (handle && pairs) { - if (save_restoreDebug > 5) { - printf("save_restore:readReqFile:handle=%p\n", handle); - printf("save_restore:readReqFile:pairs[0]='%s'\n", pairs[0]); - if (pairs[1]) printf("save_restore:readReqFile:pairs[1]='%s'\n", pairs[1]); - } - macExpandString(handle, line, eline, EBUF_SIZE); - } else { - strNcpy(eline, line, EBUF_SIZE); - } - sscanf(eline, "%s", name); - if (save_restoreDebug >= 2) printf("save_restore:readReqFile: line='%s', eline='%s', name='%s'\n", line, eline, name); - if (name[0] == '#') { - /* take the line as a comment */ - } else if (strncmp(eline, "file", 4) == 0) { - /* handle include file */ - if (save_restoreDebug >= 2) printf("save_restore:readReqFile: preparing to include file: eline='%s'\n", eline); - - /* parse template-file name and fix obvious problems */ - templatefile[0] = '\0'; - t = &(eline[4]); - while (isspace((int)(*t))) t++; /* delete leading whitespace */ - if (*t == '"') t++; /* delete leading quote */ - while (isspace((int)(*t))) t++; /* delete any additional whitespace */ - /* copy to filename; terminate at null char or whitespace or quote or comment */ - for ( i = 0; - i=3 && (new_macro[i-1] != ',')) - new_macro[i++] = ','; - } else if (*t != '"') { - new_macro[i++] = *t; - } - - if (i>=BUF_SIZE-3) { - /* Make sure the macro does not end in the middle of a macro definition */ - c = line + strlen(line) - 1; - while (i>0 && new_macro[i] != ',' && !isspace((int)new_macro[i])) i--; - new_macro[i] = '\0'; - } - } - new_macro[i] = 0; - if (i && new_macro[i-1] == ',') new_macro[--i] = 0; - if (i < 3) new_macro[0] = 0; /* if macro has less than 3 chars, punt */ - if (save_restoreDebug >= 2) printf("save_restore:readReqFile: calling readReqFile('%s', %p,'%s')\n", - templatefile, plist, new_macro); - readReqFile(templatefile, plist, new_macro); - } else if (isValid1stPVChar(name[0]) || name[0] == '$') { - pchannel = (struct channel *)calloc(1,sizeof (struct channel)); - if (pchannel == (struct channel *)0) { - plist->status = SR_STATUS_WARN; - strNcpy(plist->statusStr, "Can't alloc channel memory", EBUF_SIZE); - TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); - printf("save_restore:readReqFile: channel calloc failed"); - } else { - /* add new element to the list */ + /* Expand input line. */ + name[0] = '\0'; + eline[0] = '\0'; + if (handle && pairs) { + if (save_restoreDebug > 5) { + printf("save_restore:readReqFile:handle=%p\n", handle); + printf("save_restore:readReqFile:pairs[0]='%s'\n", pairs[0]); + if (pairs[1]) printf("save_restore:readReqFile:pairs[1]='%s'\n", pairs[1]); + } + macExpandString(handle, line, eline, EBUF_SIZE); + } else { + strNcpy(eline, line, EBUF_SIZE); + } + sscanf(eline, "%s", name); + if (save_restoreDebug >= 2) + printf("save_restore:readReqFile: line='%s', eline='%s', name='%s'\n", line, eline, name); + if (name[0] == '#') { + /* take the line as a comment */ + } else if (strncmp(eline, "file", 4) == 0) { + /* handle include file */ + if (save_restoreDebug >= 2) + printf("save_restore:readReqFile: preparing to include file: eline='%s'\n", eline); + + /* parse template-file name and fix obvious problems */ + templatefile[0] = '\0'; + t = &(eline[4]); + while (isspace((int)(*t))) t++; /* delete leading whitespace */ + if (*t == '"') t++; /* delete leading quote */ + while (isspace((int)(*t))) t++; /* delete any additional whitespace */ + /* copy to filename; terminate at null char or whitespace or quote or comment */ + for (i = 0; i < NFS_PATH_LEN && *t && !(isspace((int)(*t))) && (*t != '"') && (*t != '#'); t++, i++) { + templatefile[i] = *t; + } + templatefile[i] = 0; + + /* parse new macro string and fix obvious problems */ + /* for (i=0; *t && *t != '#'; t++) { */ + for (i = 0; *t && i < BUF_SIZE - 3; t++) { + if (isspace((int)(*t)) || *t == ',') { + if (i >= 3 && (new_macro[i - 1] != ',')) new_macro[i++] = ','; + } else if (*t != '"') { + new_macro[i++] = *t; + } + + if (i >= BUF_SIZE - 3) { + /* Make sure the macro does not end in the middle of a macro definition */ + c = line + strlen(line) - 1; + while (i > 0 && new_macro[i] != ',' && !isspace((int)new_macro[i])) i--; + new_macro[i] = '\0'; + } + } + new_macro[i] = 0; + if (i && new_macro[i - 1] == ',') new_macro[--i] = 0; + if (i < 3) new_macro[0] = 0; /* if macro has less than 3 chars, punt */ + if (save_restoreDebug >= 2) + printf("save_restore:readReqFile: calling readReqFile('%s', %p,'%s')\n", templatefile, plist, + new_macro); + readReqFile(templatefile, plist, new_macro); + } else if (isValid1stPVChar(name[0]) || name[0] == '$') { + pchannel = (struct channel *)calloc(1, sizeof(struct channel)); + if (pchannel == (struct channel *)0) { + plist->status = SR_STATUS_WARN; + strNcpy(plist->statusStr, "Can't alloc channel memory", EBUF_SIZE); + TRY_TO_PUT_AND_FLUSH(DBR_STRING, plist->statusStr_chid, &plist->statusStr); + printf("save_restore:readReqFile: channel calloc failed"); + } else { + /* add new element to the list */ #if BACKWARDS_LIST - pchannel->pnext = plist->pchan_list; - if (plist->pchan_list==NULL) plist->plast_chan = pchannel; - plist->pchan_list = pchannel; + pchannel->pnext = plist->pchan_list; + if (plist->pchan_list == NULL) plist->plast_chan = pchannel; + plist->pchan_list = pchannel; #else - if (plist->plast_chan) { - plist->plast_chan->pnext = pchannel; - } else { - plist->pchan_list = pchannel; - } - plist->plast_chan = pchannel; + if (plist->plast_chan) { + plist->plast_chan->pnext = pchannel; + } else { + plist->pchan_list = pchannel; + } + plist->plast_chan = pchannel; #endif - strNcpy(pchannel->name, name, 64); - strNcpy(pchannel->value,"Not Connected", 64); - pchannel->enum_val = -1; - pchannel->max_elements = 0; - pchannel->curr_elements = 0; - pchannel->channel_connected=0; /* qiao: init the channel connection flag 0 */ - pchannel->just_created=0; /* qiao: init the just created flag 0 */ - } - } - } - /* close file */ - fclose(inp_fd); + strNcpy(pchannel->name, name, 64); + strNcpy(pchannel->value, "Not Connected", 64); + pchannel->enum_val = -1; + pchannel->max_elements = 0; + pchannel->curr_elements = 0; + pchannel->channel_connected = 0; /* qiao: init the channel connection flag 0 */ + pchannel->just_created = 0; /* qiao: init the just created flag 0 */ + } + } + } + /* close file */ + fclose(inp_fd); - /* + /* * Allow macro string supplied to create_xxx_set() to specify a PV from which the * path and/or file name will be read when it's time to write the file. Currently, * this can only be done when the list is defined. */ - if (handle) { - if (macGetValue(handle, "SAVEPATHPV", name, 80) > 0) { - plist->do_backups = 0; - strNcpy(plist->savePathPV, name, PV_NAME_LEN); - } - if (macGetValue(handle, "SAVENAMEPV", name, 80) > 0) { - plist->do_backups = 0; - strNcpy(plist->saveNamePV, name, PV_NAME_LEN); - } - if (macGetValue(handle, "CONFIG", name, 80) > 0) { - strNcpy(plist->config, name, PV_NAME_LEN); - } - if (macGetValue(handle, "CONFIGMENU", name, 80) > 0) { - plist->do_backups = 0; - } - macDeleteHandle(handle); - if (pairs) free(pairs); - } + if (handle) { + if (macGetValue(handle, "SAVEPATHPV", name, 80) > 0) { + plist->do_backups = 0; + strNcpy(plist->savePathPV, name, PV_NAME_LEN); + } + if (macGetValue(handle, "SAVENAMEPV", name, 80) > 0) { + plist->do_backups = 0; + strNcpy(plist->saveNamePV, name, PV_NAME_LEN); + } + if (macGetValue(handle, "CONFIG", name, 80) > 0) { strNcpy(plist->config, name, PV_NAME_LEN); } + if (macGetValue(handle, "CONFIGMENU", name, 80) > 0) { plist->do_backups = 0; } + macDeleteHandle(handle); + if (pairs) free(pairs); + } - if (save_restoreDebug > 1) - printf("save_restore:readReqFile: exit: reqFile='%s'.\n", reqFile); - return(OK); + if (save_restoreDebug > 1) printf("save_restore:readReqFile: exit: reqFile='%s'.\n", reqFile); + return (OK); } /* Caller has a config name, and wants to know which PVlist has that config name */ -int findConfigList(char *configName, char *requestFileName) { - struct chlist *plist = lptr; - - while (plist != 0) { - if (strcmp(plist->config, configName) == 0) { - strcpy(requestFileName, plist->reqFile); - return(0); - } - plist = plist->pnext; - } - return(-1); +int findConfigList(char *configName, char *requestFileName) +{ + struct chlist *plist = lptr; + + while (plist != 0) { + if (strcmp(plist->config, configName) == 0) { + strcpy(requestFileName, plist->reqFile); + return (0); + } + plist = plist->pnext; + } + return (-1); } /*-------------------------------------------------------------------------------*/ /*** ioc-shell command registration (sheesh!) ***/ -#define IOCSH_ARG static const iocshArg -#define IOCSH_ARG_ARRAY static const iocshArg * const -#define IOCSH_FUNCDEF static const iocshFuncDef +#define IOCSH_ARG static const iocshArg +#define IOCSH_ARG_ARRAY static const iocshArg *const +#define IOCSH_FUNCDEF static const iocshFuncDef /* int fdbrestore(char *filename); */ -IOCSH_ARG fdbrestore_Arg0 = {"filename",iocshArgString}; +IOCSH_ARG fdbrestore_Arg0 = {"filename", iocshArgString}; IOCSH_ARG_ARRAY fdbrestore_Args[1] = {&fdbrestore_Arg0}; -IOCSH_FUNCDEF fdbrestore_FuncDef = {"fdbrestore",1,fdbrestore_Args}; -static void fdbrestore_CallFunc(const iocshArgBuf *args) {fdbrestore(args[0].sval);} +IOCSH_FUNCDEF fdbrestore_FuncDef = {"fdbrestore", 1, fdbrestore_Args}; +static void fdbrestore_CallFunc(const iocshArgBuf *args) { fdbrestore(args[0].sval); } /* int fdbrestoreX(char *filename, char *macrostring); */ -IOCSH_ARG fdbrestoreX_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG fdbrestoreX_Arg1 = {"macrostring",iocshArgString}; +IOCSH_ARG fdbrestoreX_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG fdbrestoreX_Arg1 = {"macrostring", iocshArgString}; IOCSH_ARG_ARRAY fdbrestoreX_Args[2] = {&fdbrestoreX_Arg0, &fdbrestoreX_Arg1}; -IOCSH_FUNCDEF fdbrestoreX_FuncDef = {"fdbrestoreX",2,fdbrestoreX_Args}; -static void fdbrestoreX_CallFunc(const iocshArgBuf *args) {fdbrestoreX(args[0].sval, args[1].sval, NULL, NULL);} +IOCSH_FUNCDEF fdbrestoreX_FuncDef = {"fdbrestoreX", 2, fdbrestoreX_Args}; +static void fdbrestoreX_CallFunc(const iocshArgBuf *args) { fdbrestoreX(args[0].sval, args[1].sval, NULL, NULL); } /* int manual_save(char *request_file); */ -IOCSH_ARG manual_save_Arg0 = {"request file",iocshArgString}; +IOCSH_ARG manual_save_Arg0 = {"request file", iocshArgString}; IOCSH_ARG_ARRAY manual_save_Args[1] = {&manual_save_Arg0}; -IOCSH_FUNCDEF manual_save_FuncDef = {"manual_save",1,manual_save_Args}; -static void manual_save_CallFunc(const iocshArgBuf *args) {manual_save(args[0].sval, NULL, NULL, NULL);} +IOCSH_FUNCDEF manual_save_FuncDef = {"manual_save", 1, manual_save_Args}; +static void manual_save_CallFunc(const iocshArgBuf *args) { manual_save(args[0].sval, NULL, NULL, NULL); } /* int set_savefile_name(char *filename, char *save_filename); */ -IOCSH_ARG set_savefile_name_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG set_savefile_name_Arg1 = {"save_filename",iocshArgString}; -IOCSH_ARG_ARRAY set_savefile_name_Args[2] = {&set_savefile_name_Arg0,&set_savefile_name_Arg1}; -IOCSH_FUNCDEF set_savefile_name_FuncDef = {"set_savefile_name",2,set_savefile_name_Args}; -static void set_savefile_name_CallFunc(const iocshArgBuf *args) {set_savefile_name(args[0].sval,args[1].sval);} +IOCSH_ARG set_savefile_name_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG set_savefile_name_Arg1 = {"save_filename", iocshArgString}; +IOCSH_ARG_ARRAY set_savefile_name_Args[2] = {&set_savefile_name_Arg0, &set_savefile_name_Arg1}; +IOCSH_FUNCDEF set_savefile_name_FuncDef = {"set_savefile_name", 2, set_savefile_name_Args}; +static void set_savefile_name_CallFunc(const iocshArgBuf *args) { set_savefile_name(args[0].sval, args[1].sval); } /* int create_periodic_set(char *filename, int period, char *macrostring); */ -IOCSH_ARG create_periodic_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG create_periodic_set_Arg1 = {"period",iocshArgInt}; -IOCSH_ARG create_periodic_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY create_periodic_set_Args[3] = {&create_periodic_set_Arg0,&create_periodic_set_Arg1,&create_periodic_set_Arg2}; -IOCSH_FUNCDEF create_periodic_set_FuncDef = {"create_periodic_set",3,create_periodic_set_Args}; -static void create_periodic_set_CallFunc(const iocshArgBuf *args) {create_periodic_set(args[0].sval,args[1].ival,args[2].sval);} +IOCSH_ARG create_periodic_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG create_periodic_set_Arg1 = {"period", iocshArgInt}; +IOCSH_ARG create_periodic_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY create_periodic_set_Args[3] = {&create_periodic_set_Arg0, &create_periodic_set_Arg1, + &create_periodic_set_Arg2}; +IOCSH_FUNCDEF create_periodic_set_FuncDef = {"create_periodic_set", 3, create_periodic_set_Args}; +static void create_periodic_set_CallFunc(const iocshArgBuf *args) +{ + create_periodic_set(args[0].sval, args[1].ival, args[2].sval); +} /* int create_triggered_set(char *filename, char *trigger_channel, char *macrostring); */ -IOCSH_ARG create_triggered_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG create_triggered_set_Arg1 = {"trigger_channel",iocshArgString}; -IOCSH_ARG create_triggered_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY create_triggered_set_Args[3] = {&create_triggered_set_Arg0,&create_triggered_set_Arg1,&create_triggered_set_Arg2}; -IOCSH_FUNCDEF create_triggered_set_FuncDef = {"create_triggered_set",3,create_triggered_set_Args}; -static void create_triggered_set_CallFunc(const iocshArgBuf *args) {create_triggered_set(args[0].sval,args[1].sval,args[2].sval);} +IOCSH_ARG create_triggered_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG create_triggered_set_Arg1 = {"trigger_channel", iocshArgString}; +IOCSH_ARG create_triggered_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY create_triggered_set_Args[3] = {&create_triggered_set_Arg0, &create_triggered_set_Arg1, + &create_triggered_set_Arg2}; +IOCSH_FUNCDEF create_triggered_set_FuncDef = {"create_triggered_set", 3, create_triggered_set_Args}; +static void create_triggered_set_CallFunc(const iocshArgBuf *args) +{ + create_triggered_set(args[0].sval, args[1].sval, args[2].sval); +} /* int create_monitor_set(char *filename, int period, char *macrostring); */ -IOCSH_ARG create_monitor_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG create_monitor_set_Arg1 = {"period",iocshArgInt}; -IOCSH_ARG create_monitor_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY create_monitor_set_Args[3] = {&create_monitor_set_Arg0,&create_monitor_set_Arg1,&create_monitor_set_Arg2}; -IOCSH_FUNCDEF create_monitor_set_FuncDef = {"create_monitor_set",3,create_monitor_set_Args}; -static void create_monitor_set_CallFunc(const iocshArgBuf *args) {create_monitor_set(args[0].sval,args[1].ival,args[2].sval);} +IOCSH_ARG create_monitor_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG create_monitor_set_Arg1 = {"period", iocshArgInt}; +IOCSH_ARG create_monitor_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY create_monitor_set_Args[3] = {&create_monitor_set_Arg0, &create_monitor_set_Arg1, + &create_monitor_set_Arg2}; +IOCSH_FUNCDEF create_monitor_set_FuncDef = {"create_monitor_set", 3, create_monitor_set_Args}; +static void create_monitor_set_CallFunc(const iocshArgBuf *args) +{ + create_monitor_set(args[0].sval, args[1].ival, args[2].sval); +} /* int create_manual_set(char *filename, char *macrostring); */ -IOCSH_ARG create_manual_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG create_manual_set_Arg1 = {"macrostring",iocshArgString}; -IOCSH_ARG_ARRAY create_manual_set_Args[2] = {&create_manual_set_Arg0,&create_manual_set_Arg1}; -IOCSH_FUNCDEF create_manual_set_FuncDef = {"create_manual_set",2,create_manual_set_Args}; -static void create_manual_set_CallFunc(const iocshArgBuf *args) {create_manual_set(args[0].sval,args[1].sval);} +IOCSH_ARG create_manual_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG create_manual_set_Arg1 = {"macrostring", iocshArgString}; +IOCSH_ARG_ARRAY create_manual_set_Args[2] = {&create_manual_set_Arg0, &create_manual_set_Arg1}; +IOCSH_FUNCDEF create_manual_set_FuncDef = {"create_manual_set", 2, create_manual_set_Args}; +static void create_manual_set_CallFunc(const iocshArgBuf *args) { create_manual_set(args[0].sval, args[1].sval); } /* void save_restoreShow(int verbose); */ -IOCSH_ARG save_restoreShow_Arg0 = {"verbose",iocshArgInt}; +IOCSH_ARG save_restoreShow_Arg0 = {"verbose", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreShow_Args[1] = {&save_restoreShow_Arg0}; -IOCSH_FUNCDEF save_restoreShow_FuncDef = {"save_restoreShow",1,save_restoreShow_Args}; -static void save_restoreShow_CallFunc(const iocshArgBuf *args) {save_restoreShow(args[0].ival);} +IOCSH_FUNCDEF save_restoreShow_FuncDef = {"save_restoreShow", 1, save_restoreShow_Args}; +static void save_restoreShow_CallFunc(const iocshArgBuf *args) { save_restoreShow(args[0].ival); } /* int set_requestfile_path(char *path, char *pathsub); */ -IOCSH_ARG set_requestfile_path_Arg0 = {"path",iocshArgString}; -IOCSH_ARG set_requestfile_path_Arg1 = {"subpath",iocshArgString}; -IOCSH_ARG_ARRAY set_requestfile_path_Args[2] = {&set_requestfile_path_Arg0,&set_requestfile_path_Arg1}; -IOCSH_FUNCDEF set_requestfile_path_FuncDef = {"set_requestfile_path",2,set_requestfile_path_Args}; -static void set_requestfile_path_CallFunc(const iocshArgBuf *args) {set_requestfile_path(args[0].sval,args[1].sval);} +IOCSH_ARG set_requestfile_path_Arg0 = {"path", iocshArgString}; +IOCSH_ARG set_requestfile_path_Arg1 = {"subpath", iocshArgString}; +IOCSH_ARG_ARRAY set_requestfile_path_Args[2] = {&set_requestfile_path_Arg0, &set_requestfile_path_Arg1}; +IOCSH_FUNCDEF set_requestfile_path_FuncDef = {"set_requestfile_path", 2, set_requestfile_path_Args}; +static void set_requestfile_path_CallFunc(const iocshArgBuf *args) { set_requestfile_path(args[0].sval, args[1].sval); } /* int set_savefile_path(char *path, char *pathsub); */ -IOCSH_ARG set_savefile_path_Arg0 = {"path",iocshArgString}; -IOCSH_ARG set_savefile_path_Arg1 = {"subpath",iocshArgString}; -IOCSH_ARG_ARRAY set_savefile_path_Args[2] = {&set_savefile_path_Arg0,&set_savefile_path_Arg1}; -IOCSH_FUNCDEF set_savefile_path_FuncDef = {"set_savefile_path",2,set_savefile_path_Args}; -static void set_savefile_path_CallFunc(const iocshArgBuf *args) {set_savefile_path(args[0].sval,args[1].sval);} +IOCSH_ARG set_savefile_path_Arg0 = {"path", iocshArgString}; +IOCSH_ARG set_savefile_path_Arg1 = {"subpath", iocshArgString}; +IOCSH_ARG_ARRAY set_savefile_path_Args[2] = {&set_savefile_path_Arg0, &set_savefile_path_Arg1}; +IOCSH_FUNCDEF set_savefile_path_FuncDef = {"set_savefile_path", 2, set_savefile_path_Args}; +static void set_savefile_path_CallFunc(const iocshArgBuf *args) { set_savefile_path(args[0].sval, args[1].sval); } /* int set_saveTask_priority(int priority); */ -IOCSH_ARG set_saveTask_priority_Arg0 = {"priority",iocshArgInt}; +IOCSH_ARG set_saveTask_priority_Arg0 = {"priority", iocshArgInt}; IOCSH_ARG_ARRAY set_saveTask_priority_Args[1] = {&set_saveTask_priority_Arg0}; -IOCSH_FUNCDEF set_saveTask_priority_FuncDef = {"set_saveTask_priority",1,set_saveTask_priority_Args}; -static void set_saveTask_priority_CallFunc(const iocshArgBuf *args) {set_saveTask_priority(args[0].ival);} +IOCSH_FUNCDEF set_saveTask_priority_FuncDef = {"set_saveTask_priority", 1, set_saveTask_priority_Args}; +static void set_saveTask_priority_CallFunc(const iocshArgBuf *args) { set_saveTask_priority(args[0].ival); } /* aqiao: void save_restoreSet_NFSHost(char *hostname, char *address, char *mntpoint); */ -IOCSH_ARG save_restoreSet_NFSHost_Arg0 = {"hostname",iocshArgString}; -IOCSH_ARG save_restoreSet_NFSHost_Arg1 = {"address", iocshArgString}; -IOCSH_ARG save_restoreSet_NFSHost_Arg2 = {"mntpoint",iocshArgString}; -IOCSH_ARG_ARRAY save_restoreSet_NFSHost_Args[3] = {&save_restoreSet_NFSHost_Arg0, - &save_restoreSet_NFSHost_Arg1, +IOCSH_ARG save_restoreSet_NFSHost_Arg0 = {"hostname", iocshArgString}; +IOCSH_ARG save_restoreSet_NFSHost_Arg1 = {"address", iocshArgString}; +IOCSH_ARG save_restoreSet_NFSHost_Arg2 = {"mntpoint", iocshArgString}; +IOCSH_ARG_ARRAY save_restoreSet_NFSHost_Args[3] = {&save_restoreSet_NFSHost_Arg0, &save_restoreSet_NFSHost_Arg1, &save_restoreSet_NFSHost_Arg2}; -IOCSH_FUNCDEF save_restoreSet_NFSHost_FuncDef = {"save_restoreSet_NFSHost",3,save_restoreSet_NFSHost_Args}; -static void save_restoreSet_NFSHost_CallFunc(const iocshArgBuf *args) {save_restoreSet_NFSHost(args[0].sval,args[1].sval,args[2].sval);} +IOCSH_FUNCDEF save_restoreSet_NFSHost_FuncDef = {"save_restoreSet_NFSHost", 3, save_restoreSet_NFSHost_Args}; +static void save_restoreSet_NFSHost_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_NFSHost(args[0].sval, args[1].sval, args[2].sval); +} /* int remove_data_set(char *filename); */ -IOCSH_ARG remove_data_set_Arg0 = {"filename",iocshArgString}; +IOCSH_ARG remove_data_set_Arg0 = {"filename", iocshArgString}; IOCSH_ARG_ARRAY remove_data_set_Args[1] = {&remove_data_set_Arg0}; -IOCSH_FUNCDEF remove_data_set_FuncDef = {"remove_data_set",1,remove_data_set_Args}; -static void remove_data_set_CallFunc(const iocshArgBuf *args) {remove_data_set(args[0].sval);} +IOCSH_FUNCDEF remove_data_set_FuncDef = {"remove_data_set", 1, remove_data_set_Args}; +static void remove_data_set_CallFunc(const iocshArgBuf *args) { remove_data_set(args[0].sval); } /* int reload_periodic_set(char *filename, int period, char *macrostring); */ -IOCSH_ARG reload_periodic_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG reload_periodic_set_Arg1 = {"period",iocshArgInt}; -IOCSH_ARG reload_periodic_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY reload_periodic_set_Args[3] = {&reload_periodic_set_Arg0, &reload_periodic_set_Arg1,&reload_periodic_set_Arg2}; -IOCSH_FUNCDEF reload_periodic_set_FuncDef = {"reload_periodic_set",3,reload_periodic_set_Args}; -static void reload_periodic_set_CallFunc(const iocshArgBuf *args) {reload_periodic_set(args[0].sval,args[1].ival,args[2].sval);} +IOCSH_ARG reload_periodic_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG reload_periodic_set_Arg1 = {"period", iocshArgInt}; +IOCSH_ARG reload_periodic_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY reload_periodic_set_Args[3] = {&reload_periodic_set_Arg0, &reload_periodic_set_Arg1, + &reload_periodic_set_Arg2}; +IOCSH_FUNCDEF reload_periodic_set_FuncDef = {"reload_periodic_set", 3, reload_periodic_set_Args}; +static void reload_periodic_set_CallFunc(const iocshArgBuf *args) +{ + reload_periodic_set(args[0].sval, args[1].ival, args[2].sval); +} /* int reload_triggered_set(char *filename, char *trigger_channel, char *macrostring); */ -IOCSH_ARG reload_triggered_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG reload_triggered_set_Arg1 = {"trigger_channel",iocshArgString}; -IOCSH_ARG reload_triggered_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY reload_triggered_set_Args[3] = {&reload_triggered_set_Arg0, &reload_triggered_set_Arg1,&reload_triggered_set_Arg2}; -IOCSH_FUNCDEF reload_triggered_set_FuncDef = {"reload_triggered_set",3,reload_triggered_set_Args}; -static void reload_triggered_set_CallFunc(const iocshArgBuf *args) {reload_triggered_set(args[0].sval,args[1].sval,args[2].sval);} +IOCSH_ARG reload_triggered_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG reload_triggered_set_Arg1 = {"trigger_channel", iocshArgString}; +IOCSH_ARG reload_triggered_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY reload_triggered_set_Args[3] = {&reload_triggered_set_Arg0, &reload_triggered_set_Arg1, + &reload_triggered_set_Arg2}; +IOCSH_FUNCDEF reload_triggered_set_FuncDef = {"reload_triggered_set", 3, reload_triggered_set_Args}; +static void reload_triggered_set_CallFunc(const iocshArgBuf *args) +{ + reload_triggered_set(args[0].sval, args[1].sval, args[2].sval); +} /* int reload_monitor_set(char *filename, int period, char *macrostring); */ -IOCSH_ARG reload_monitor_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG reload_monitor_set_Arg1 = {"period",iocshArgInt}; -IOCSH_ARG reload_monitor_set_Arg2 = {"macro string",iocshArgString}; -IOCSH_ARG_ARRAY reload_monitor_set_Args[3] = {&reload_monitor_set_Arg0, &reload_monitor_set_Arg1,&reload_monitor_set_Arg2}; -IOCSH_FUNCDEF reload_monitor_set_FuncDef = {"reload_monitor_set",3,reload_monitor_set_Args}; -static void reload_monitor_set_CallFunc(const iocshArgBuf *args) {reload_monitor_set(args[0].sval,args[1].ival,args[2].sval);} +IOCSH_ARG reload_monitor_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG reload_monitor_set_Arg1 = {"period", iocshArgInt}; +IOCSH_ARG reload_monitor_set_Arg2 = {"macro string", iocshArgString}; +IOCSH_ARG_ARRAY reload_monitor_set_Args[3] = {&reload_monitor_set_Arg0, &reload_monitor_set_Arg1, + &reload_monitor_set_Arg2}; +IOCSH_FUNCDEF reload_monitor_set_FuncDef = {"reload_monitor_set", 3, reload_monitor_set_Args}; +static void reload_monitor_set_CallFunc(const iocshArgBuf *args) +{ + reload_monitor_set(args[0].sval, args[1].ival, args[2].sval); +} /* int reload_manual_set(char *filename, char *macrostring); */ -IOCSH_ARG reload_manual_set_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG reload_manual_set_Arg1 = {"macrostring",iocshArgString}; -IOCSH_ARG_ARRAY reload_manual_set_Args[2] = {&reload_manual_set_Arg0,&reload_manual_set_Arg1}; -IOCSH_FUNCDEF reload_manual_set_FuncDef = {"reload_manual_set",2,reload_manual_set_Args}; -static void reload_manual_set_CallFunc(const iocshArgBuf *args) {reload_manual_set(args[0].sval,args[1].sval);} +IOCSH_ARG reload_manual_set_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG reload_manual_set_Arg1 = {"macrostring", iocshArgString}; +IOCSH_ARG_ARRAY reload_manual_set_Args[2] = {&reload_manual_set_Arg0, &reload_manual_set_Arg1}; +IOCSH_FUNCDEF reload_manual_set_FuncDef = {"reload_manual_set", 2, reload_manual_set_Args}; +static void reload_manual_set_CallFunc(const iocshArgBuf *args) { reload_manual_set(args[0].sval, args[1].sval); } /* void save_restoreSet_Debug(int level); */ -IOCSH_ARG save_restoreSet_Debug_Arg0 = {"level",iocshArgInt}; +IOCSH_ARG save_restoreSet_Debug_Arg0 = {"level", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_Debug_Args[1] = {&save_restoreSet_Debug_Arg0}; -IOCSH_FUNCDEF save_restoreSet_Debug_FuncDef = {"save_restoreSet_Debug",1,save_restoreSet_Debug_Args}; -static void save_restoreSet_Debug_CallFunc(const iocshArgBuf *args) {save_restoreSet_Debug(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_Debug_FuncDef = {"save_restoreSet_Debug", 1, save_restoreSet_Debug_Args}; +static void save_restoreSet_Debug_CallFunc(const iocshArgBuf *args) { save_restoreSet_Debug(args[0].ival); } /* void save_restoreSet_NumSeqFiles(int numSeqFiles); */ -IOCSH_ARG save_restoreSet_NumSeqFiles_Arg0 = {"numSeqFiles",iocshArgInt}; +IOCSH_ARG save_restoreSet_NumSeqFiles_Arg0 = {"numSeqFiles", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_NumSeqFiles_Args[1] = {&save_restoreSet_NumSeqFiles_Arg0}; -IOCSH_FUNCDEF save_restoreSet_NumSeqFiles_FuncDef = {"save_restoreSet_NumSeqFiles",1,save_restoreSet_NumSeqFiles_Args}; -static void save_restoreSet_NumSeqFiles_CallFunc(const iocshArgBuf *args) {save_restoreSet_NumSeqFiles(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_NumSeqFiles_FuncDef = {"save_restoreSet_NumSeqFiles", 1, + save_restoreSet_NumSeqFiles_Args}; +static void save_restoreSet_NumSeqFiles_CallFunc(const iocshArgBuf *args) { save_restoreSet_NumSeqFiles(args[0].ival); } /* void save_restoreSet_SeqPeriodInSeconds(int period); */ -IOCSH_ARG save_restoreSet_SeqPeriodInSeconds_Arg0 = {"period",iocshArgInt}; +IOCSH_ARG save_restoreSet_SeqPeriodInSeconds_Arg0 = {"period", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_SeqPeriodInSeconds_Args[1] = {&save_restoreSet_SeqPeriodInSeconds_Arg0}; -IOCSH_FUNCDEF save_restoreSet_SeqPeriodInSeconds_FuncDef = {"save_restoreSet_SeqPeriodInSeconds",1,save_restoreSet_SeqPeriodInSeconds_Args}; -static void save_restoreSet_SeqPeriodInSeconds_CallFunc(const iocshArgBuf *args) {save_restoreSet_SeqPeriodInSeconds(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_SeqPeriodInSeconds_FuncDef = {"save_restoreSet_SeqPeriodInSeconds", 1, + save_restoreSet_SeqPeriodInSeconds_Args}; +static void save_restoreSet_SeqPeriodInSeconds_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_SeqPeriodInSeconds(args[0].ival); +} /* void save_restoreSet_IncompleteSetsOk(int ok); */ -IOCSH_ARG save_restoreSet_IncompleteSetsOk_Arg0 = {"ok",iocshArgInt}; +IOCSH_ARG save_restoreSet_IncompleteSetsOk_Arg0 = {"ok", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_IncompleteSetsOk_Args[1] = {&save_restoreSet_IncompleteSetsOk_Arg0}; -IOCSH_FUNCDEF save_restoreSet_IncompleteSetsOk_FuncDef = {"save_restoreSet_IncompleteSetsOk",1,save_restoreSet_IncompleteSetsOk_Args}; -static void save_restoreSet_IncompleteSetsOk_CallFunc(const iocshArgBuf *args) {save_restoreSet_IncompleteSetsOk(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_IncompleteSetsOk_FuncDef = {"save_restoreSet_IncompleteSetsOk", 1, + save_restoreSet_IncompleteSetsOk_Args}; +static void save_restoreSet_IncompleteSetsOk_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_IncompleteSetsOk(args[0].ival); +} /* void save_restoreSet_DatedBackupFiles(int ok); */ -IOCSH_ARG save_restoreSet_DatedBackupFiles_Arg0 = {"ok",iocshArgInt}; +IOCSH_ARG save_restoreSet_DatedBackupFiles_Arg0 = {"ok", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_DatedBackupFiles_Args[1] = {&save_restoreSet_DatedBackupFiles_Arg0}; -IOCSH_FUNCDEF save_restoreSet_DatedBackupFiles_FuncDef = {"save_restoreSet_DatedBackupFiles",1,save_restoreSet_DatedBackupFiles_Args}; -static void save_restoreSet_DatedBackupFiles_CallFunc(const iocshArgBuf *args) {save_restoreSet_DatedBackupFiles(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_DatedBackupFiles_FuncDef = {"save_restoreSet_DatedBackupFiles", 1, + save_restoreSet_DatedBackupFiles_Args}; +static void save_restoreSet_DatedBackupFiles_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_DatedBackupFiles(args[0].ival); +} /* void save_restoreSet_status_prefix(char *prefix); */ -IOCSH_ARG save_restoreSet_status_prefix_Arg0 = {"prefix",iocshArgString}; +IOCSH_ARG save_restoreSet_status_prefix_Arg0 = {"prefix", iocshArgString}; IOCSH_ARG_ARRAY save_restoreSet_status_prefix_Args[1] = {&save_restoreSet_status_prefix_Arg0}; -IOCSH_FUNCDEF save_restoreSet_status_prefix_FuncDef = {"save_restoreSet_status_prefix",1,save_restoreSet_status_prefix_Args}; -static void save_restoreSet_status_prefix_CallFunc(const iocshArgBuf *args) {save_restoreSet_status_prefix(args[0].sval);} +IOCSH_FUNCDEF save_restoreSet_status_prefix_FuncDef = {"save_restoreSet_status_prefix", 1, + save_restoreSet_status_prefix_Args}; +static void save_restoreSet_status_prefix_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_status_prefix(args[0].sval); +} #if SET_FILE_PERMISSIONS /* void save_restoreSet_FilePermissions(int permissions); */ -IOCSH_ARG save_restoreSet_FilePermissions_Arg0 = {"permissions",iocshArgInt}; +IOCSH_ARG save_restoreSet_FilePermissions_Arg0 = {"permissions", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_FilePermissions_Args[1] = {&save_restoreSet_FilePermissions_Arg0}; -IOCSH_FUNCDEF save_restoreSet_FilePermissions_FuncDef = {"save_restoreSet_FilePermissions",1,save_restoreSet_FilePermissions_Args}; -static void save_restoreSet_FilePermissions_CallFunc(const iocshArgBuf *args) {save_restoreSet_FilePermissions(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_FilePermissions_FuncDef = {"save_restoreSet_FilePermissions", 1, + save_restoreSet_FilePermissions_Args}; +static void save_restoreSet_FilePermissions_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_FilePermissions(args[0].ival); +} #endif /* void save_restoreSet_RetrySeconds(int seconds); */ -IOCSH_ARG save_restoreSet_RetrySeconds_Arg0 = {"seconds",iocshArgInt}; +IOCSH_ARG save_restoreSet_RetrySeconds_Arg0 = {"seconds", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_RetrySeconds_Args[1] = {&save_restoreSet_RetrySeconds_Arg0}; -IOCSH_FUNCDEF save_restoreSet_RetrySeconds_FuncDef = {"save_restoreSet_RetrySeconds",1,save_restoreSet_RetrySeconds_Args}; -static void save_restoreSet_RetrySeconds_CallFunc(const iocshArgBuf *args) {save_restoreSet_RetrySeconds(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_RetrySeconds_FuncDef = {"save_restoreSet_RetrySeconds", 1, + save_restoreSet_RetrySeconds_Args}; +static void save_restoreSet_RetrySeconds_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_RetrySeconds(args[0].ival); +} /* void save_restoreSet_UseStatusPVs(int ok); */ -IOCSH_ARG save_restoreSet_UseStatusPVs_Arg0 = {"ok",iocshArgInt}; +IOCSH_ARG save_restoreSet_UseStatusPVs_Arg0 = {"ok", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_UseStatusPVs_Args[1] = {&save_restoreSet_UseStatusPVs_Arg0}; -IOCSH_FUNCDEF save_restoreSet_UseStatusPVs_FuncDef = {"save_restoreSet_UseStatusPVs",1,save_restoreSet_UseStatusPVs_Args}; -static void save_restoreSet_UseStatusPVs_CallFunc(const iocshArgBuf *args) {save_restoreSet_UseStatusPVs(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_UseStatusPVs_FuncDef = {"save_restoreSet_UseStatusPVs", 1, + save_restoreSet_UseStatusPVs_Args}; +static void save_restoreSet_UseStatusPVs_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_UseStatusPVs(args[0].ival); +} /* qiao: void save_restoreSet_CAReconnect(int ok); */ -IOCSH_ARG save_restoreSet_CAReconnect_Arg0 = {"ok",iocshArgInt}; +IOCSH_ARG save_restoreSet_CAReconnect_Arg0 = {"ok", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_CAReconnect_Args[1] = {&save_restoreSet_CAReconnect_Arg0}; -IOCSH_FUNCDEF save_restoreSet_CAReconnect_FuncDef = {"save_restoreSet_CAReconnect",1,save_restoreSet_CAReconnect_Args}; -static void save_restoreSet_CAReconnect_CallFunc(const iocshArgBuf *args) {save_restoreSet_CAReconnect(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_CAReconnect_FuncDef = {"save_restoreSet_CAReconnect", 1, + save_restoreSet_CAReconnect_Args}; +static void save_restoreSet_CAReconnect_CallFunc(const iocshArgBuf *args) { save_restoreSet_CAReconnect(args[0].ival); } /* qiao: void save_restoreSet_CallbackTimeout(int t); */ -IOCSH_ARG save_restoreSet_CallbackTimeout_Arg0 = {"t",iocshArgInt}; +IOCSH_ARG save_restoreSet_CallbackTimeout_Arg0 = {"t", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_CallbackTimeout_Args[1] = {&save_restoreSet_CallbackTimeout_Arg0}; -IOCSH_FUNCDEF save_restoreSet_CallbackTimeout_FuncDef = {"save_restoreSet_CallbackTimeout",1,save_restoreSet_CallbackTimeout_Args}; -static void save_restoreSet_CallbackTimeout_CallFunc(const iocshArgBuf *args) {save_restoreSet_CallbackTimeout(args[0].ival);} +IOCSH_FUNCDEF save_restoreSet_CallbackTimeout_FuncDef = {"save_restoreSet_CallbackTimeout", 1, + save_restoreSet_CallbackTimeout_Args}; +static void save_restoreSet_CallbackTimeout_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_CallbackTimeout(args[0].ival); +} /* int asVerify(char *fileName, int verbose, char *restoreFileName) */ -IOCSH_ARG asVerify_Arg0 = {"filename",iocshArgString}; -IOCSH_ARG asVerify_Arg1 = {"verbose",iocshArgInt}; -IOCSH_ARG asVerify_Arg2 = {"restoreFileName",iocshArgString}; +IOCSH_ARG asVerify_Arg0 = {"filename", iocshArgString}; +IOCSH_ARG asVerify_Arg1 = {"verbose", iocshArgInt}; +IOCSH_ARG asVerify_Arg2 = {"restoreFileName", iocshArgString}; IOCSH_ARG_ARRAY asVerify_Args[3] = {&asVerify_Arg0, &asVerify_Arg1, &asVerify_Arg2}; -IOCSH_FUNCDEF asVerify_FuncDef = {"asVerify",3,asVerify_Args}; -static void asVerify_CallFunc(const iocshArgBuf *args) {asVerify(args[0].sval,args[1].ival,args[2].sval);} +IOCSH_FUNCDEF asVerify_FuncDef = {"asVerify", 3, asVerify_Args}; +static void asVerify_CallFunc(const iocshArgBuf *args) { asVerify(args[0].sval, args[1].ival, args[2].sval); } /* void save_restoreSet_periodicDatedBackups(int periodMinutes) */ -IOCSH_ARG save_restoreSet_periodicDatedBackups_Arg0 = {"periodMinutes",iocshArgInt}; +IOCSH_ARG save_restoreSet_periodicDatedBackups_Arg0 = {"periodMinutes", iocshArgInt}; IOCSH_ARG_ARRAY save_restoreSet_periodicDatedBackups_Args[1] = {&save_restoreSet_periodicDatedBackups_Arg0}; -IOCSH_FUNCDEF save_restoreSet_periodicDatedBackups_FuncDef = {"save_restoreSet_periodicDatedBackups",1,save_restoreSet_periodicDatedBackups_Args}; -static void save_restoreSet_periodicDatedBackups_CallFunc(const iocshArgBuf *args) {save_restoreSet_periodicDatedBackups(args[0].ival);} - +IOCSH_FUNCDEF save_restoreSet_periodicDatedBackups_FuncDef = {"save_restoreSet_periodicDatedBackups", 1, + save_restoreSet_periodicDatedBackups_Args}; +static void save_restoreSet_periodicDatedBackups_CallFunc(const iocshArgBuf *args) +{ + save_restoreSet_periodicDatedBackups(args[0].ival); +} void save_restoreRegister(void) { @@ -4104,7 +4025,7 @@ void save_restoreRegister(void) iocshRegister(&save_restoreSet_CAReconnect_FuncDef, save_restoreSet_CAReconnect_CallFunc); iocshRegister(&save_restoreSet_CallbackTimeout_FuncDef, save_restoreSet_CallbackTimeout_CallFunc); iocshRegister(&asVerify_FuncDef, asVerify_CallFunc); - iocshRegister(&save_restoreSet_periodicDatedBackups_FuncDef, save_restoreSet_periodicDatedBackups_CallFunc); + iocshRegister(&save_restoreSet_periodicDatedBackups_FuncDef, save_restoreSet_periodicDatedBackups_CallFunc); } epicsExportRegistrar(save_restoreRegister); diff --git a/asApp/src/save_restore.h b/asApp/src/save_restore.h index 8f25e82..ad412b8 100644 --- a/asApp/src/save_restore.h +++ b/asApp/src/save_restore.h @@ -12,41 +12,45 @@ #define STATIC #endif -#define TATTLE(CA_ERROR_CODE, FMT, ARG) \ -{ \ - int err_code = (CA_ERROR_CODE); \ - if (!(err_code & CA_M_SUCCESS)) \ - printf(FMT, (ARG), ca_message(err_code)); \ -} +#define TATTLE(CA_ERROR_CODE, FMT, ARG) \ + { \ + int err_code = (CA_ERROR_CODE); \ + if (!(err_code & CA_M_SUCCESS)) printf(FMT, (ARG), ca_message(err_code)); \ + } #define CONNECTED(CHID) ((CHID) && (ca_state(CHID) == cs_conn)) /* do a ca_put, if the channel is connected */ -#define TRY_TO_PUT(TYPE, CHID, POINTER) \ -{if (CONNECTED(CHID)) ca_put(TYPE, CHID, POINTER);} +#define TRY_TO_PUT(TYPE, CHID, POINTER) \ + { \ + if (CONNECTED(CHID)) ca_put(TYPE, CHID, POINTER); \ + } #define TRY_TO_PUT_AND_FLUSH(TYPE, CHID, POINTER) \ -{if (CONNECTED(CHID)) {ca_put(TYPE, CHID, POINTER); ca_flush_io();}} - - -#define MAX(a,b) ((a)>(b)?(a):(b)) -#define MIN(a,b) ((a)<(b)?(a):(b)) - -#define SR_STATUS_OK 4 -#define SR_STATUS_SEQ_WARN 3 -#define SR_STATUS_WARN 2 -#define SR_STATUS_FAIL 1 -#define SR_STATUS_INIT 0 + { \ + if (CONNECTED(CHID)) { \ + ca_put(TYPE, CHID, POINTER); \ + ca_flush_io(); \ + } \ + } + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define SR_STATUS_OK 4 +#define SR_STATUS_SEQ_WARN 3 +#define SR_STATUS_WARN 2 +#define SR_STATUS_FAIL 1 +#define SR_STATUS_INIT 0 /* Make sure to leave room for trailing null */ -static char SR_STATUS_STR[5][10] = - {"No Status", " Failure ", " Warning ", " Warning ", " Ok "}; +static char SR_STATUS_STR[5][10] = {"No Status", " Failure ", " Warning ", " Warning ", " Ok "}; #define FLOAT_FMT "%.7g" #define DOUBLE_FMT "%.14g" #define BUF_SIZE 200 -#define EBUF_SIZE BUF_SIZE*2 +#define EBUF_SIZE BUF_SIZE * 2 #define ARRAY_BEGIN '{' #define ARRAY_END '}' #define ELEMENT_BEGIN '\"' @@ -55,18 +59,18 @@ static char SR_STATUS_STR[5][10] = #define ARRAY_MARKER "@array@" #define ARRAY_MARKER_LEN 7 -#define FN_LEN 80 /* filename length */ -#define STRING_LEN MAX_STRING_SIZE /* EPICS max length for string PV */ +#define FN_LEN 80 /* filename length */ +#define STRING_LEN MAX_STRING_SIZE /* EPICS max length for string PV */ #define STATUS_STR_LEN 300 #define PV_NAME_LEN 80 /* string containing a PV name */ #define MAXSTRING 300 struct restoreFileListItem { ELLNODE node; - char *filename; - long restoreStatus; - char *restoreStatusStr; - char *macrostring; + char *filename; + long restoreStatus; + char *restoreStatusStr; + char *macrostring; }; extern ELLLIST pass0List; @@ -83,10 +87,10 @@ extern long SR_write_array_data(FILE *out_fd, char *name, void *pArray, long num extern long SR_array_restore(int pass, FILE *inp_fd, char *PVname, char *value_string, int gobble); extern long SR_put_array_values(char *PVname, void *p_data, long num_values); -#define PATH_SIZE 255 /* max size of the complete path to one file */ +#define PATH_SIZE 255 /* max size of the complete path to one file */ extern volatile int save_restoreIncompleteSetsOk; -extern char saveRestoreFilePath[]; /* path to save files */ +extern char saveRestoreFilePath[]; /* path to save files */ extern volatile int save_restoreNumSeqFiles; extern volatile int save_restoreDebug; extern volatile int save_restoreDatedBackupFiles; @@ -96,15 +100,15 @@ extern void dbrestoreShow(void); extern void makeNfsPath(char *dest, const char *s1, const char *s2); extern int do_asVerify(char *fileName, int verbose, int debug, int write_restore_file, char *restoreFileName); -extern int save_restoreNFSOK; -extern int save_restoreIoErrors; -extern volatile int save_restoreRemountThreshold; +extern int save_restoreNFSOK; +extern int save_restoreIoErrors; +extern volatile int save_restoreRemountThreshold; extern int reboot_restore(char *filename, initHookState init_state); extern int set_pass0_restoreFile(char *filename, char *macrostring); extern int set_pass1_restoreFile(char *filename, char *macrostring); extern struct restoreList restoreFileList; -extern int isAbsolute(const char* filename); +extern int isAbsolute(const char *filename); extern int openReqFile(const char *reqFile, FILE **fpp); extern int eraseFile(const char *filename); @@ -112,12 +116,11 @@ extern int appendToFile(const char *filename, const char *line); extern float mySafeDoubleToFloat(double d); /* strncpy sucks (may copy extra characters, may not null-terminate) */ -#define strNcpy(dest, src, N) { \ - int ii; \ - char *dd=dest; \ - const char *ss=src; \ - for (ii=0; *ss && ii < N-1; ii++) \ - *dd++ = *ss++; \ - *dd = '\0'; \ -} - +#define strNcpy(dest, src, N) \ + { \ + int ii; \ + char *dd = dest; \ + const char *ss = src; \ + for (ii = 0; *ss && ii < N - 1; ii++) *dd++ = *ss++; \ + *dd = '\0'; \ + } diff --git a/asApp/src/tr_dirent.h b/asApp/src/tr_dirent.h index cf3fe56..fd1843c 100644 --- a/asApp/src/tr_dirent.h +++ b/asApp/src/tr_dirent.h @@ -93,7 +93,7 @@ #define DIRENT_H #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) -# define _X86_ +#define _X86_ #endif #include #include @@ -115,81 +115,81 @@ /* Entries missing from MSVC 6.0 */ #if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 +#define FILE_ATTRIBUTE_DEVICE 0x40 #endif /* File type and permission flags for stat() */ #if !defined(S_IFMT) -# define S_IFMT _S_IFMT /* File type mask */ +#define S_IFMT _S_IFMT /* File type mask */ #endif #if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR /* Directory */ +#define S_IFDIR _S_IFDIR /* Directory */ #endif #if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR /* Character device */ +#define S_IFCHR _S_IFCHR /* Character device */ #endif #if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO /* Pipe */ +#define S_IFFIFO _S_IFFIFO /* Pipe */ #endif #if !defined(S_IFREG) -# define S_IFREG _S_IFREG /* Regular file */ +#define S_IFREG _S_IFREG /* Regular file */ #endif #if !defined(S_IREAD) -# define S_IREAD _S_IREAD /* Read permission */ +#define S_IREAD _S_IREAD /* Read permission */ #endif #if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE /* Write permission */ +#define S_IWRITE _S_IWRITE /* Write permission */ #endif #if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC /* Execute permission */ +#define S_IEXEC _S_IEXEC /* Execute permission */ #endif #if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO /* Pipe */ +#define S_IFIFO _S_IFIFO /* Pipe */ #endif #if !defined(S_IFBLK) -# define S_IFBLK 0 /* Block device */ +#define S_IFBLK 0 /* Block device */ #endif #if !defined(S_IFLNK) -# define S_IFLNK 0 /* Link */ +#define S_IFLNK 0 /* Link */ #endif #if !defined(S_IFSOCK) -# define S_IFSOCK 0 /* Socket */ +#define S_IFSOCK 0 /* Socket */ #endif #if defined(_MSC_VER) -# define S_IRUSR S_IREAD /* Read user */ -# define S_IWUSR S_IWRITE /* Write user */ -# define S_IXUSR 0 /* Execute user */ -# define S_IRGRP 0 /* Read group */ -# define S_IWGRP 0 /* Write group */ -# define S_IXGRP 0 /* Execute group */ -# define S_IROTH 0 /* Read others */ -# define S_IWOTH 0 /* Write others */ -# define S_IXOTH 0 /* Execute others */ +#define S_IRUSR S_IREAD /* Read user */ +#define S_IWUSR S_IWRITE /* Write user */ +#define S_IXUSR 0 /* Execute user */ +#define S_IRGRP 0 /* Read group */ +#define S_IWGRP 0 /* Write group */ +#define S_IXGRP 0 /* Execute group */ +#define S_IROTH 0 /* Read others */ +#define S_IWOTH 0 /* Write others */ +#define S_IXOTH 0 /* Execute others */ #endif /* Maximum length of file name */ #if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH +#define PATH_MAX MAX_PATH #endif #if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH +#define FILENAME_MAX MAX_PATH #endif #if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX +#define NAME_MAX FILENAME_MAX #endif /* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK /* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) +#define IFTODT(mode) ((mode)&S_IFMT) #define DTTOIF(type) (type) /* @@ -198,13 +198,13 @@ * only defined for compatibility. These macros should always return false * on Windows. */ -#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) -#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(mode) (((mode)&S_IFMT) == S_IFIFO) +#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) +#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG) +#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK) +#define S_ISCHR(mode) (((mode)&S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode)&S_IFMT) == S_IFBLK) /* Return the exact length of d_namlen without zero terminator */ #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) @@ -212,36 +212,33 @@ /* Return number of bytes needed to store d_namlen */ #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1) - #ifdef __cplusplus extern "C" { #endif - /* Wide-character version */ struct _wdirent { - long d_ino; /* Always zero */ - unsigned short d_reclen; /* Structure size */ - size_t d_namlen; /* Length of name without \0 */ - int d_type; /* File type */ - wchar_t d_name[PATH_MAX + 1]; /* File name */ + long d_ino; /* Always zero */ + unsigned short d_reclen; /* Structure size */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ + wchar_t d_name[PATH_MAX + 1]; /* File name */ }; typedef struct _wdirent _wdirent; struct _WDIR { - struct _wdirent ent; /* Current directory entry */ - WIN32_FIND_DATAW data; /* Private file data */ - int cached; /* True if data is valid */ - HANDLE handle; /* Win32 search handle */ - wchar_t *patt; /* Initial directory name */ + struct _wdirent ent; /* Current directory entry */ + WIN32_FIND_DATAW data; /* Private file data */ + int cached; /* True if data is valid */ + HANDLE handle; /* Win32 search handle */ + wchar_t *patt; /* Initial directory name */ }; typedef struct _WDIR _WDIR; -static _WDIR *_wopendir (const wchar_t *dirname); -static struct _wdirent *_wreaddir (_WDIR *dirp); -static int _wclosedir (_WDIR *dirp); -static void _wrewinddir (_WDIR* dirp); - +static _WDIR *_wopendir(const wchar_t *dirname); +static struct _wdirent *_wreaddir(_WDIR *dirp); +static int _wclosedir(_WDIR *dirp); +static void _wrewinddir(_WDIR *dirp); /* For compatibility with Symbian */ #define wdirent _wdirent @@ -251,14 +248,13 @@ static void _wrewinddir (_WDIR* dirp); #define wclosedir _wclosedir #define wrewinddir _wrewinddir - /* Multi-byte character versions */ struct dirent { - long d_ino; /* Always zero */ - unsigned short d_reclen; /* Structure size */ - size_t d_namlen; /* Length of name without \0 */ - int d_type; /* File type */ - char d_name[PATH_MAX + 1]; /* File name */ + long d_ino; /* Always zero */ + unsigned short d_reclen; /* Structure size */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ + char d_name[PATH_MAX + 1]; /* File name */ }; typedef struct dirent dirent; @@ -268,52 +264,39 @@ struct DIR { }; typedef struct DIR DIR; -static DIR *opendir (const char *dirname); -static struct dirent *readdir (DIR *dirp); -static int closedir (DIR *dirp); -static void rewinddir (DIR* dirp); - +static DIR *opendir(const char *dirname); +static struct dirent *readdir(DIR *dirp); +static int closedir(DIR *dirp); +static void rewinddir(DIR *dirp); /* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); -static int dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count); +static int dirent_mbstowcs_s(size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count); -static int dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, - const wchar_t *wcstr, - size_t count); +static int dirent_wcstombs_s(size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count); -static void dirent_set_errno (int error); +static void dirent_set_errno(int error); /* * Open directory stream DIRNAME for read and return a pointer to the * internal working area that is used to retrieve individual directory * entries. */ -static _WDIR* -_wopendir( - const wchar_t *dirname) +static _WDIR *_wopendir(const wchar_t *dirname) { _WDIR *dirp = NULL; int error; /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); return NULL; } /* Allocate new _WDIR structure */ - dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + dirp = (_WDIR *)malloc(sizeof(struct _WDIR)); if (dirp != NULL) { DWORD n; @@ -323,18 +306,17 @@ _wopendir( dirp->cached = 0; /* Compute the length of full path plus zero terminator */ - n = GetFullPathNameW (dirname, 0, NULL, NULL); + n = GetFullPathNameW(dirname, 0, NULL, NULL); /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + dirp->patt = (wchar_t *)malloc(sizeof(wchar_t) * n + 16); if (dirp->patt) { - /* * Convert relative directory name to an absolute one. This * allows rewinddir() to function correctly even when current * working directory is changed between opendir() and rewinddir(). */ - n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); if (n > 0) { wchar_t *p; @@ -342,34 +324,34 @@ _wopendir( p = dirp->patt + n; if (dirp->patt < p) { switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; } } *p++ = '*'; *p = '\0'; /* Open directory stream and retrieve the first entry */ - if (dirent_first (dirp)) { + if (dirent_first(dirp)) { /* Directory stream opened successfully */ error = 0; } else { /* Cannot retrieve first entry */ error = 1; - dirent_set_errno (ENOENT); + dirent_set_errno(ENOENT); } } else { /* Cannot retrieve full path name */ - dirent_set_errno (ENOENT); + dirent_set_errno(ENOENT); error = 1; } @@ -384,8 +366,8 @@ _wopendir( } /* Clean up in case of error */ - if (error && dirp) { - _wclosedir (dirp); + if (error && dirp) { + _wclosedir(dirp); dirp = NULL; } @@ -398,19 +380,17 @@ _wopendir( * this function include regular files, sub-directories, pseudo-directories * "." and ".." as well as volume labels, hidden files and system files. */ -static struct _wdirent* -_wreaddir( - _WDIR *dirp) +static struct _wdirent *_wreaddir(_WDIR *dirp) { WIN32_FIND_DATAW *datap; struct _wdirent *entp; /* Read next directory entry */ - datap = dirent_next (dirp); + datap = dirent_next(dirp); if (datap) { size_t n; DWORD attr; - + /* Pointer to directory entry to return */ entp = &dirp->ent; @@ -420,7 +400,7 @@ _wreaddir( * to PATH_MAX characters and zero-terminate the buffer. */ n = 0; - while (n < PATH_MAX && datap->cFileName[n] != 0) { + while (n < PATH_MAX && datap->cFileName[n] != 0) { entp->d_name[n] = datap->cFileName[n]; n++; } @@ -441,13 +421,11 @@ _wreaddir( /* Reset dummy fields */ entp->d_ino = 0; - entp->d_reclen = sizeof (struct _wdirent); + entp->d_reclen = sizeof(struct _wdirent); } else { - /* Last directory entry read */ entp = NULL; - } return entp; @@ -458,33 +436,30 @@ _wreaddir( * DIR structure as well as any directory entry read previously by * _wreaddir(). */ -static int -_wclosedir( - _WDIR *dirp) +static int _wclosedir(_WDIR *dirp) { int ok; if (dirp) { - /* Release search handle */ if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); + FindClose(dirp->handle); dirp->handle = INVALID_HANDLE_VALUE; } /* Release search pattern */ if (dirp->patt) { - free (dirp->patt); + free(dirp->patt); dirp->patt = NULL; } /* Release directory structure */ - free (dirp); - ok = /*success*/0; + free(dirp); + ok = /*success*/ 0; } else { /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; + dirent_set_errno(EBADF); + ok = /*failure*/ -1; } return ok; } @@ -493,78 +468,63 @@ _wclosedir( * Rewind directory stream such that _wreaddir() returns the very first * file name again. */ -static void -_wrewinddir( - _WDIR* dirp) +static void _wrewinddir(_WDIR *dirp) { if (dirp) { /* Release existing search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); - } + if (dirp->handle != INVALID_HANDLE_VALUE) { FindClose(dirp->handle); } /* Open new search handle */ - dirent_first (dirp); + dirent_first(dirp); } } /* Get first directory entry (internal) */ -static WIN32_FIND_DATAW* -dirent_first( - _WDIR *dirp) +static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp) { WIN32_FIND_DATAW *datap; /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileW (dirp->patt, &dirp->data); + dirp->handle = FindFirstFileW(dirp->patt, &dirp->data); if (dirp->handle != INVALID_HANDLE_VALUE) { - /* a directory entry is now waiting in memory */ datap = &dirp->data; dirp->cached = 1; } else { - /* Failed to re-open directory: no directory entry in memory */ dirp->cached = 0; datap = NULL; - } return datap; } /* Get next directory entry (internal) */ -static WIN32_FIND_DATAW* -dirent_next( - _WDIR *dirp) +static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp) { WIN32_FIND_DATAW *p; /* Get next directory entry */ if (dirp->cached != 0) { - /* A valid directory entry already in memory */ p = &dirp->data; dirp->cached = 0; } else if (dirp->handle != INVALID_HANDLE_VALUE) { - /* Get the next directory entry from stream */ - if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) { /* Got a file */ p = &dirp->data; } else { /* The very last entry has been processed or an error occured */ - FindClose (dirp->handle); + FindClose(dirp->handle); dirp->handle = INVALID_HANDLE_VALUE; p = NULL; } } else { - /* End of directory stream reached */ p = NULL; - } return p; @@ -573,32 +533,28 @@ dirent_next( /* * Open directory stream using plain old C-string. */ -static DIR* -opendir( - const char *dirname) +static DIR *opendir(const char *dirname) { struct DIR *dirp; int error; /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno(ENOENT); return NULL; } /* Allocate memory for DIR structure */ - dirp = (DIR*) malloc (sizeof (struct DIR)); + dirp = (DIR *)malloc(sizeof(struct DIR)); if (dirp) { wchar_t wname[PATH_MAX + 1]; size_t n; /* Convert directory name to wide-character string */ - error = dirent_mbstowcs_s( - &n, wname, PATH_MAX + 1, dirname, PATH_MAX); + error = dirent_mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX); if (!error) { - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir (wname); + dirp->wdirp = _wopendir(wname); if (dirp->wdirp) { /* Directory stream opened */ error = 0; @@ -623,8 +579,8 @@ opendir( } /* Clean up in case of error */ - if (error && dirp) { - free (dirp); + if (error && dirp) { + free(dirp); dirp = NULL; } @@ -644,22 +600,19 @@ opendir( * ANSI strings to the console code page so many non-ASCII characters will * display correcly. */ -static struct dirent* -readdir( - DIR *dirp) +static struct dirent *readdir(DIR *dirp) { WIN32_FIND_DATAW *datap; struct dirent *entp; /* Read next directory entry */ - datap = dirent_next (dirp->wdirp); + datap = dirent_next(dirp->wdirp); if (datap) { size_t n; int error; /* Attempt to convert file name to multi-byte string */ - error = dirent_wcstombs_s( - &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); + error = dirent_wcstombs_s(&n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); /* * If the file name cannot be represented by a multi-byte string, @@ -671,11 +624,9 @@ readdir( * name unless the file system provides one. At least * VirtualBox shared folders fail to do this. */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = dirent_wcstombs_s( - &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, - sizeof (datap->cAlternateFileName) / - sizeof (datap->cAlternateFileName[0])); + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s(&n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, + sizeof(datap->cAlternateFileName) / sizeof(datap->cAlternateFileName[0])); } if (!error) { @@ -699,7 +650,7 @@ readdir( /* Reset dummy fields */ entp->d_ino = 0; - entp->d_reclen = sizeof (struct dirent); + entp->d_reclen = sizeof(struct dirent); } else { /* @@ -728,26 +679,21 @@ readdir( /* * Close directory stream. */ -static int -closedir( - DIR *dirp) +static int closedir(DIR *dirp) { int ok; if (dirp) { - /* Close wide-character directory stream */ - ok = _wclosedir (dirp->wdirp); + ok = _wclosedir(dirp->wdirp); dirp->wdirp = NULL; /* Release multi-byte character version */ - free (dirp); + free(dirp); } else { - /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; - + dirent_set_errno(EBADF); + ok = /*failure*/ -1; } return ok; } @@ -755,29 +701,21 @@ closedir( /* * Rewind directory stream to beginning. */ -static void -rewinddir( - DIR* dirp) +static void rewinddir(DIR *dirp) { /* Rewind wide-character string directory stream */ - _wrewinddir (dirp->wdirp); + _wrewinddir(dirp->wdirp); } /* Convert multi-byte string to wide character string */ -static int -dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count) +static int dirent_mbstowcs_s(size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, const char *mbstr, size_t count) { int error; -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Microsoft Visual Studio 2005 or later */ - error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); #else @@ -785,27 +723,20 @@ dirent_mbstowcs_s( size_t n; /* Convert to wide-character string */ - n = mbstowcs (wcstr, mbstr, count); + n = mbstowcs(wcstr, mbstr, count); if (n < sizeInWords) { - /* Zero-terminate output buffer */ - if (wcstr) { - wcstr[n] = 0; - } + if (wcstr) { wcstr[n] = 0; } /* Length of resuting multi-byte string WITH zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } + if (pReturnValue) { *pReturnValue = n + 1; } /* Success */ error = 0; } else { - /* Could not convert string */ error = 1; - } #endif @@ -814,20 +745,14 @@ dirent_mbstowcs_s( } /* Convert wide-character string to multi-byte string */ -static int -dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, - const wchar_t *wcstr, - size_t count) +static int dirent_wcstombs_s(size_t *pReturnValue, char *mbstr, size_t sizeInBytes, const wchar_t *wcstr, size_t count) { int error; -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Microsoft Visual Studio 2005 or later */ - error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); #else @@ -835,27 +760,20 @@ dirent_wcstombs_s( size_t n; /* Convert to multi-byte string */ - n = wcstombs (mbstr, wcstr, count); + n = wcstombs(mbstr, wcstr, count); if (n < sizeInBytes) { - /* Zero-terminate output buffer */ - if (mbstr) { - mbstr[n] = '\0'; - } + if (mbstr) { mbstr[n] = '\0'; } /* Lenght of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } + if (pReturnValue) { *pReturnValue = n + 1; } /* Success */ error = 0; } else { - /* Cannot convert string */ error = 1; - } #endif @@ -864,14 +782,12 @@ dirent_wcstombs_s( } /* Set errno variable */ -static void -dirent_set_errno( - int error) +static void dirent_set_errno(int error) { #if defined(_MSC_VER) /* Microsoft Visual Studio */ - _set_errno (error); + _set_errno(error); #else @@ -881,9 +797,7 @@ dirent_set_errno( #endif } - #ifdef __cplusplus } #endif #endif /*DIRENT_H*/ - diff --git a/asApp/src/verify.c b/asApp/src/verify.c index b4d4c29..16c6ace 100644 --- a/asApp/src/verify.c +++ b/asApp/src/verify.c @@ -8,8 +8,8 @@ #include #include /* isalpha */ -#include /* fabs */ -#include /* for safeDoubleToFloat() */ +#include /* fabs */ +#include /* for safeDoubleToFloat() */ #include "cadef.h" #include #include @@ -18,579 +18,603 @@ #include "save_restore.h" #ifndef PVNAME_STRINGSZ -#define PVNAME_STRINGSZ 61 /* includes terminating null */ +#define PVNAME_STRINGSZ 61 /* includes terminating null */ #endif #define PEND_TIME 5.0 #define FSMALL 1.e-6 #define DSMALL 1.e-8 -#define ASVERSION "asVerify R5.3" +#define ASVERSION "asVerify R5.3" -#define WRITE_HEADER if (!wrote_head) {printf(" PVname saved_value live_value\n"); \ -printf(" =============================\n"); wrote_head=1;} +#define WRITE_HEADER \ + if (!wrote_head) { \ + printf(" PVname saved_value live_value\n"); \ + printf(" =============================\n"); \ + wrote_head = 1; \ + } -long read_array(FILE *fp, char *PVname, char *value_string, short field_type, long element_count, - char *read_buffer, int debug); +long read_array(FILE *fp, char *PVname, char *value_string, short field_type, long element_count, char *read_buffer, + int debug); /* verbose==-1 means don't say anything unless there's a problem. */ -int do_asVerify(char *fileName, int verbose, int debug, int write_restore_file, char *restoreFileName) { - float *pfvalue, *pf_read; - double *pdvalue, *pd_read, diff, max_diff=0.; - short *penum_value, *penum_value_read; - char *svalue, *svalue_read; - chid chid; - FILE *fp=NULL, *fr=NULL, *fr1=NULL; - char c, s[BUF_SIZE], *bp, PVname[PV_NAME_LEN+1], value_string[BUF_SIZE]; - char trial_restoreFileName[PATH_SIZE]; - char *CA_buffer=NULL, *read_buffer=NULL, *pc=NULL; - short field_type; - int i, j, n, is_scalar, is_scalar_in_file, is_long_string; - int numPVs, numDifferences, numPVsNotConnected, nspace; - int different, wrote_head=0, status, file_ok=0; - long element_count=0, storageBytes=0, alloc_CA_buffer=0; - +int do_asVerify(char *fileName, int verbose, int debug, int write_restore_file, char *restoreFileName) +{ + float *pfvalue, *pf_read; + double *pdvalue, *pd_read, diff, max_diff = 0.; + short *penum_value, *penum_value_read; + char *svalue, *svalue_read; + chid chid; + FILE *fp = NULL, *fr = NULL, *fr1 = NULL; + char c, s[BUF_SIZE], *bp, PVname[PV_NAME_LEN + 1], value_string[BUF_SIZE]; + char trial_restoreFileName[PATH_SIZE]; + char *CA_buffer = NULL, *read_buffer = NULL, *pc = NULL; + short field_type; + int i, j, n, is_scalar, is_scalar_in_file, is_long_string; + int numPVs, numDifferences, numPVsNotConnected, nspace; + int different, wrote_head = 0, status, file_ok = 0; + long element_count = 0, storageBytes = 0, alloc_CA_buffer = 0; - fp = fopen(fileName,"r"); - if (fp == NULL) {printf("asVerify: Can't open '%s'.\n", fileName); return(-1);} + fp = fopen(fileName, "r"); + if (fp == NULL) { + printf("asVerify: Can't open '%s'.\n", fileName); + return (-1); + } - if (write_restore_file) { - strcpy(trial_restoreFileName, restoreFileName); - strcat(trial_restoreFileName, "B"); - if (debug) {printf("asVerify: restoreFileName '%s'.\n", restoreFileName);} - fr = fopen(trial_restoreFileName,"w"); - if (fr == NULL) { - printf("asVerify: Can't open restore_file '%s' for writing.\n", trial_restoreFileName); - write_restore_file = 0; - } else { - fprintf(fr,"# %s\tAutomatically generated - DO NOT MODIFY - datetime\n", ASVERSION); - } - } - /* check that (copy of) .sav file is good */ - status = fseek(fp, -6, SEEK_END); - fgets(s, 6, fp); - if (strncmp(s, "", 5) == 0) file_ok = 1; - if (!file_ok) { - status = fseek(fp, -7, SEEK_END); - fgets(s, 7, fp); - if (strncmp(s, "", 5) == 0) file_ok = 1; - } - if (status || !file_ok) { - if (verbose>0) printf("asVerify: Can't find marker. File may be bad.\n"); - if (write_restore_file) fprintf(fr,"# # # Could not find end marker in original .sav file. File may be bad.\n"); - } - status = fseek(fp, 0, SEEK_SET); /* file is ok. go to beginning */ - if (status) { - printf("asVerify: Can't go back to beginning of file. I quit.\n"); - fclose(fp); fp = NULL; - if (fr) { fclose(fr); fr = NULL; } - return(-1); - } + if (write_restore_file) { + strcpy(trial_restoreFileName, restoreFileName); + strcat(trial_restoreFileName, "B"); + if (debug) { printf("asVerify: restoreFileName '%s'.\n", restoreFileName); } + fr = fopen(trial_restoreFileName, "w"); + if (fr == NULL) { + printf("asVerify: Can't open restore_file '%s' for writing.\n", trial_restoreFileName); + write_restore_file = 0; + } else { + fprintf(fr, "# %s\tAutomatically generated - DO NOT MODIFY - datetime\n", ASVERSION); + } + } + /* check that (copy of) .sav file is good */ + status = fseek(fp, -6, SEEK_END); + fgets(s, 6, fp); + if (strncmp(s, "", 5) == 0) file_ok = 1; + if (!file_ok) { + status = fseek(fp, -7, SEEK_END); + fgets(s, 7, fp); + if (strncmp(s, "", 5) == 0) file_ok = 1; + } + if (status || !file_ok) { + if (verbose > 0) printf("asVerify: Can't find marker. File may be bad.\n"); + if (write_restore_file) + fprintf(fr, "# # # Could not find end marker in original .sav file. File may be bad.\n"); + } + status = fseek(fp, 0, SEEK_SET); /* file is ok. go to beginning */ + if (status) { + printf("asVerify: Can't go back to beginning of file. I quit.\n"); + fclose(fp); + fp = NULL; + if (fr) { + fclose(fr); + fr = NULL; + } + return (-1); + } - numDifferences = numPVs = numPVsNotConnected = 0; + numDifferences = numPVs = numPVsNotConnected = 0; - /* init CA buffer space */ - storageBytes = 200; - CA_buffer = malloc(2*storageBytes); alloc_CA_buffer = storageBytes; - if (CA_buffer == NULL) { - printf("asVerify: Can't allocate CA buffer. I quit.\n"); - fclose(fp); fp = NULL; - if (fr) { fclose(fr); fr = NULL; } - return(-1); - } + /* init CA buffer space */ + storageBytes = 200; + CA_buffer = malloc(2 * storageBytes); + alloc_CA_buffer = storageBytes; + if (CA_buffer == NULL) { + printf("asVerify: Can't allocate CA buffer. I quit.\n"); + fclose(fp); + fp = NULL; + if (fr) { + fclose(fr); + fr = NULL; + } + return (-1); + } - while ((bp=fgets(s, BUF_SIZE, fp))) { - if (debug>3) printf("\nasVerify: buffer '%s'\n", bp); - if (bp[0] == '#') { - /* A PV to which autosave could not connect, or just a comment in the file. */ - if (strstr(bp, "Search Issued")) numPVsNotConnected++; - if (write_restore_file) fprintf(fr, "%s", bp); - continue; - } - /* NOTE value_string must have room for nearly BUF_SIZE characters */ - n = sscanf(bp,"%80s%c%[^\n\r]", PVname, &c, value_string); - if (debug>3) printf("\nasVerify: PVname='%s', value_string[%d]='%s'\n", - PVname, (int)strlen(value_string), value_string); - if (n<3) *value_string = 0; - if (strlen(PVname) >= PVNAME_STRINGSZ) { - /* Impossible PV name */ - if (write_restore_file) fprintf(fr, "#? %s", bp); - continue; - } - if (isalpha((int)PVname[0]) || isdigit((int)PVname[0])) { - status = ca_create_channel(PVname,NULL,NULL,10,&chid); - if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); - if ((chid == NULL) || (ca_state(chid) != cs_conn)) { - printf("asVerify: *** '%s' not connected. Saved value='%s'\n", PVname, value_string); - numPVsNotConnected++; - if (chid) ca_clear_channel(chid); - if (write_restore_file) fprintf(fr, "#'%s' not connected\n", PVname); - continue; - } - numPVs++; - field_type = ca_field_type(chid); - if (debug>3) printf("'%s' native field_type=%d\n", PVname, field_type); - is_long_string = (field_type==DBF_CHAR) && (PVname[strlen(PVname)-1]=='$'); - /* If DBF_STRING will work, use it. */ - if (field_type!=DBF_FLOAT && field_type!=DBF_DOUBLE && field_type!=DBF_ENUM) - field_type = DBF_STRING; - if (field_type==DBF_ENUM) field_type = DBF_SHORT; + while ((bp = fgets(s, BUF_SIZE, fp))) { + if (debug > 3) printf("\nasVerify: buffer '%s'\n", bp); + if (bp[0] == '#') { + /* A PV to which autosave could not connect, or just a comment in the file. */ + if (strstr(bp, "Search Issued")) numPVsNotConnected++; + if (write_restore_file) fprintf(fr, "%s", bp); + continue; + } + /* NOTE value_string must have room for nearly BUF_SIZE characters */ + n = sscanf(bp, "%80s%c%[^\n\r]", PVname, &c, value_string); + if (debug > 3) + printf("\nasVerify: PVname='%s', value_string[%d]='%s'\n", PVname, (int)strlen(value_string), value_string); + if (n < 3) *value_string = 0; + if (strlen(PVname) >= PVNAME_STRINGSZ) { + /* Impossible PV name */ + if (write_restore_file) fprintf(fr, "#? %s", bp); + continue; + } + if (isalpha((int)PVname[0]) || isdigit((int)PVname[0])) { + status = ca_create_channel(PVname, NULL, NULL, 10, &chid); + if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); + if ((chid == NULL) || (ca_state(chid) != cs_conn)) { + printf("asVerify: *** '%s' not connected. Saved value='%s'\n", PVname, value_string); + numPVsNotConnected++; + if (chid) ca_clear_channel(chid); + if (write_restore_file) fprintf(fr, "#'%s' not connected\n", PVname); + continue; + } + numPVs++; + field_type = ca_field_type(chid); + if (debug > 3) printf("'%s' native field_type=%d\n", PVname, field_type); + is_long_string = (field_type == DBF_CHAR) && (PVname[strlen(PVname) - 1] == '$'); + /* If DBF_STRING will work, use it. */ + if (field_type != DBF_FLOAT && field_type != DBF_DOUBLE && field_type != DBF_ENUM) field_type = DBF_STRING; + if (field_type == DBF_ENUM) field_type = DBF_SHORT; - element_count = ca_element_count(chid); - is_scalar_in_file = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN) != 0; - is_scalar = is_scalar_in_file; - if (element_count > 1) is_scalar = 0; - if (debug>3) printf("asVerify: is_scalar=%d, is_scalar_in_file=%d, is_long_string=%d\n", - is_scalar, is_scalar_in_file, is_long_string); + element_count = ca_element_count(chid); + is_scalar_in_file = strncmp(value_string, ARRAY_MARKER, ARRAY_MARKER_LEN) != 0; + is_scalar = is_scalar_in_file; + if (element_count > 1) is_scalar = 0; + if (debug > 3) + printf("asVerify: is_scalar=%d, is_scalar_in_file=%d, is_long_string=%d\n", is_scalar, + is_scalar_in_file, is_long_string); - /* allocate storage for CA and for reading the file */ - storageBytes = dbr_size_n(field_type, element_count); - if (is_long_string) storageBytes = dbr_size_n(DBF_CHAR, element_count); - if (debug>3) printf("asVerify:type=%d,elements=%ld, storageBytes=%ld\n", - field_type, element_count, storageBytes); - if (alloc_CA_buffer < storageBytes) { - if (CA_buffer) free(CA_buffer); - CA_buffer = malloc(2*storageBytes); alloc_CA_buffer = storageBytes; - } - if (CA_buffer == NULL) { - printf("asVerify: Can't allocate CA buffer. I quit.\n"); - fclose(fp); fp = NULL; - if (fr) { fclose(fr); fr = NULL; } - return(-1); - } - /* use second half of CA_buffer for values read from .sav file */ - read_buffer = CA_buffer+storageBytes; + /* allocate storage for CA and for reading the file */ + storageBytes = dbr_size_n(field_type, element_count); + if (is_long_string) storageBytes = dbr_size_n(DBF_CHAR, element_count); + if (debug > 3) + printf("asVerify:type=%d,elements=%ld, storageBytes=%ld\n", field_type, element_count, storageBytes); + if (alloc_CA_buffer < storageBytes) { + if (CA_buffer) free(CA_buffer); + CA_buffer = malloc(2 * storageBytes); + alloc_CA_buffer = storageBytes; + } + if (CA_buffer == NULL) { + printf("asVerify: Can't allocate CA buffer. I quit.\n"); + fclose(fp); + fp = NULL; + if (fr) { + fclose(fr); + fr = NULL; + } + return (-1); + } + /* use second half of CA_buffer for values read from .sav file */ + read_buffer = CA_buffer + storageBytes; - if (!is_scalar_in_file) { - if (debug>3) printf("asVerify: calling read_array\n"); - memset(read_buffer, 0, storageBytes); - read_array(fp, PVname, value_string, field_type, element_count, read_buffer, debug); - } + if (!is_scalar_in_file) { + if (debug > 3) printf("asVerify: calling read_array\n"); + memset(read_buffer, 0, storageBytes); + read_array(fp, PVname, value_string, field_type, element_count, read_buffer, debug); + } - switch (field_type) { - case DBF_FLOAT: - pfvalue = (float *)CA_buffer; - status = ca_array_get(DBR_FLOAT,element_count,chid,(void *)pfvalue); - if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); - if (!(status & CA_M_SUCCESS)) printf("asVerify: Can't get value from '%s'.\n", PVname); - if (is_scalar == is_scalar_in_file) { - if (is_scalar) { - different = fabs((float)(atof(value_string)) - *pfvalue) > FSMALL; - } else { - pf_read = (float *)read_buffer; - for (i=0, different=0, max_diff=0.; i max_diff) max_diff = diff; - different += diff > FSMALL; - } - } - if (different) numDifferences++; - if (different || (verbose>0)) { - WRITE_HEADER; - if (is_scalar) { - printf("%s%-25s %-25f %f\n", different?"*** ":" ", PVname, (float)(atof(value_string)), *pfvalue); - } else { - printf("%s%-25s (array) %d diff%1c", different?"*** ":" ", PVname, different, different==1?' ':'s'); - if (different) printf(", maxDiff=%f", max_diff); - printf("\n"); - } - } - } else { - printf("asVerify: *** %-25s is %s in file, but %s in ioc.\n", PVname, - is_scalar_in_file?"scalar":"array", is_scalar?"scalar":"array"); - } - if (write_restore_file) { - if (is_scalar) { - fprintf(fr, "%s %.7g\n", PVname, *pfvalue); /* cf. FLOAT_FMT */ - } else { - fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); - for (i=0; i DSMALL; - } else { - pd_read = (double *)read_buffer; - for (i=0, different=0, max_diff=0.; i max_diff) max_diff = diff; - different += diff > DSMALL; - } - } - if (different) numDifferences++; - if (different || (verbose>0)) { - WRITE_HEADER; - if (is_scalar) { - printf("%s%-25s %-25f %f\n", different?"*** ":" ", PVname, atof(value_string), *pdvalue); - } else { - printf("%s%-25s (array) %d diff%1c", different?"*** ":" ", PVname, different, different==1?' ':'s'); - if (different) printf(", maxDiff=%f", max_diff); - printf("\n"); - } - } - } else { - printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, - is_scalar_in_file?"scalar":"array", is_scalar?"scalar":"array"); - } - if (write_restore_file) { - if (is_scalar) { - fprintf(fr, "%s %.14g\n", PVname, *pdvalue); /* cf. DOUBLE_FMT */ - } else { - fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); - for (i=0; i0)) { - WRITE_HEADER; - if (is_scalar) { - printf("%s%-25s %-25d %d\n", different?"*** ":" ", PVname, atoi(value_string), *penum_value); - } else { - printf("%s%-25s (array) %d diff%1c\n", different?"*** ":" ", PVname, different, different==1?' ':'s'); - } - } - } else { - printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, - is_scalar_in_file?"scalar":"array", is_scalar?"scalar":"array"); - } - if (write_restore_file) { - if (is_scalar) { - fprintf(fr, "%s %d\n", PVname, *penum_value); - } else { - fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); - for (i=0; i3) printf("did not reach end of line for long-string PV\n"); - bp = fgets(s, BUF_SIZE, fp); - n = BUF_SIZE-strlen(value_string)-1; - strncat(value_string, bp, n); - if (value_string[strlen(value_string)-1] == '\n') value_string[strlen(value_string)-1] = '\0'; - } - /* Discard additional characters until end of line */ - while (bp[strlen(bp)-1] != '\n') fgets(s, BUF_SIZE, fp); + switch (field_type) { + case DBF_FLOAT: + pfvalue = (float *)CA_buffer; + status = ca_array_get(DBR_FLOAT, element_count, chid, (void *)pfvalue); + if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); + if (!(status & CA_M_SUCCESS)) printf("asVerify: Can't get value from '%s'.\n", PVname); + if (is_scalar == is_scalar_in_file) { + if (is_scalar) { + different = fabs((float)(atof(value_string)) - *pfvalue) > FSMALL; + } else { + pf_read = (float *)read_buffer; + for (i = 0, different = 0, max_diff = 0.; i < element_count; i++) { + diff = fabs(pf_read[i] - pfvalue[i]); + if (diff > max_diff) max_diff = diff; + different += diff > FSMALL; + } + } + if (different) numDifferences++; + if (different || (verbose > 0)) { + WRITE_HEADER; + if (is_scalar) { + printf("%s%-25s %-25f %f\n", different ? "*** " : " ", PVname, + (float)(atof(value_string)), *pfvalue); + } else { + printf("%s%-25s (array) %d diff%1c", different ? "*** " : " ", PVname, different, + different == 1 ? ' ' : 's'); + if (different) printf(", maxDiff=%f", max_diff); + printf("\n"); + } + } + } else { + printf("asVerify: *** %-25s is %s in file, but %s in ioc.\n", PVname, + is_scalar_in_file ? "scalar" : "array", is_scalar ? "scalar" : "array"); + } + if (write_restore_file) { + if (is_scalar) { + fprintf(fr, "%s %.7g\n", PVname, *pfvalue); /* cf. FLOAT_FMT */ + } else { + fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); + for (i = 0; i < element_count; i++) { + fprintf(fr, "%1c%.7g%1c ", ELEMENT_BEGIN, pfvalue[i], ELEMENT_END); + } + fprintf(fr, "%1c\n", ARRAY_END); + } + } + break; + case DBF_DOUBLE: + pdvalue = (double *)CA_buffer; + status = ca_array_get(DBR_DOUBLE, element_count, chid, (void *)pdvalue); + if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); + if (!(status & CA_M_SUCCESS)) printf("asVerify: Can't get value from '%s'.\n", PVname); + if (is_scalar == is_scalar_in_file) { + if (is_scalar) { + different = fabs(atof(value_string) - *pdvalue) > DSMALL; + } else { + pd_read = (double *)read_buffer; + for (i = 0, different = 0, max_diff = 0.; i < element_count; i++) { + diff = fabs(pd_read[i] - pdvalue[i]); + if (diff > max_diff) max_diff = diff; + different += diff > DSMALL; + } + } + if (different) numDifferences++; + if (different || (verbose > 0)) { + WRITE_HEADER; + if (is_scalar) { + printf("%s%-25s %-25f %f\n", different ? "*** " : " ", PVname, atof(value_string), + *pdvalue); + } else { + printf("%s%-25s (array) %d diff%1c", different ? "*** " : " ", PVname, different, + different == 1 ? ' ' : 's'); + if (different) printf(", maxDiff=%f", max_diff); + printf("\n"); + } + } + } else { + printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, + is_scalar_in_file ? "scalar" : "array", is_scalar ? "scalar" : "array"); + } + if (write_restore_file) { + if (is_scalar) { + fprintf(fr, "%s %.14g\n", PVname, *pdvalue); /* cf. DOUBLE_FMT */ + } else { + fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); + for (i = 0; i < element_count; i++) { + fprintf(fr, "%1c%.14g%1c ", ELEMENT_BEGIN, pdvalue[i], ELEMENT_END); + } + fprintf(fr, "%1c\n", ARRAY_END); + } + } + break; + case DBF_SHORT: + penum_value = (short *)CA_buffer; + status = ca_array_get(DBR_SHORT, element_count, chid, (void *)penum_value); + if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); + if (!(status & CA_M_SUCCESS)) printf("Can't get value from '%s'.\n", PVname); + if (is_scalar == is_scalar_in_file) { + if (is_scalar) { + different = atoi(value_string) != *penum_value; + } else { + penum_value_read = (short *)read_buffer; + for (i = 0, different = 0; i < element_count; i++) { + different += (penum_value_read[i] != penum_value[i]); + } + } + if (different) numDifferences++; + if (different || (verbose > 0)) { + WRITE_HEADER; + if (is_scalar) { + printf("%s%-25s %-25d %d\n", different ? "*** " : " ", PVname, atoi(value_string), + *penum_value); + } else { + printf("%s%-25s (array) %d diff%1c\n", different ? "*** " : " ", PVname, different, + different == 1 ? ' ' : 's'); + } + } + } else { + printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, + is_scalar_in_file ? "scalar" : "array", is_scalar ? "scalar" : "array"); + } + if (write_restore_file) { + if (is_scalar) { + fprintf(fr, "%s %d\n", PVname, *penum_value); + } else { + fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); + for (i = 0; i < element_count; i++) { + fprintf(fr, "%1c%d%1c ", ELEMENT_BEGIN, penum_value[i], ELEMENT_END); + } + fprintf(fr, "%1c\n", ARRAY_END); + } + } + break; + case DBF_STRING: + svalue = (char *)CA_buffer; + if (is_long_string) { + /* See if we got the whole line */ + if (bp[strlen(bp) - 1] != '\n') { + /* No, we didn't. One more read will certainly accumulate a value string of length BUF_SIZE */ + if (debug > 3) printf("did not reach end of line for long-string PV\n"); + bp = fgets(s, BUF_SIZE, fp); + n = BUF_SIZE - strlen(value_string) - 1; + strncat(value_string, bp, n); + if (value_string[strlen(value_string) - 1] == '\n') + value_string[strlen(value_string) - 1] = '\0'; + } + /* Discard additional characters until end of line */ + while (bp[strlen(bp) - 1] != '\n') fgets(s, BUF_SIZE, fp); - status = ca_array_get(DBR_CHAR,element_count,chid,(void *)svalue); - } else { - status = ca_array_get(DBR_STRING,element_count,chid,(void *)svalue); - } - if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); - if (!(status & CA_M_SUCCESS)) printf("Can't get value from '%s'.\n", PVname); + status = ca_array_get(DBR_CHAR, element_count, chid, (void *)svalue); + } else { + status = ca_array_get(DBR_STRING, element_count, chid, (void *)svalue); + } + if (status & CA_M_SUCCESS) status = ca_pend_io(PEND_TIME); + if (!(status & CA_M_SUCCESS)) printf("Can't get value from '%s'.\n", PVname); - if ((is_scalar != is_scalar_in_file) && !is_long_string) { - printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, - is_scalar_in_file?"scalar":"array", is_scalar?"scalar":"array"); - } else { - if (is_long_string) { - epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); - different = strncmp(value_string, svalue, BUF_SIZE); - } else if (is_scalar) { - epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); - different = strcmp(value_string, svalue); - } else { - svalue_read = (char *)read_buffer; - for (i=0, different=0; i3) printf("'%40s' != '%40s'\n", &svalue_read[i*MAX_STRING_SIZE], &svalue[i*MAX_STRING_SIZE]); - } - } - if (different) numDifferences++; - if (different || (verbose>0)) { - WRITE_HEADER; - if (is_scalar || is_long_string) { - nspace = 24-strlen(value_string); if (nspace < 1) nspace = 1; - printf("%s%-24s '%s'%*s'%s'\n", different?"*** ":" ", PVname, value_string, nspace, "", svalue); - } else { - printf("%s%-25s (array) %d diff%1c\n", different?"*** ":" ", PVname, different, different==1?' ':'s'); - } - } - } - if (write_restore_file) { - if (is_long_string) { - svalue[BUF_SIZE-1] = '\0'; - fprintf(fr, "%s ", PVname); - epicsStrPrintEscaped(fr, svalue, strlen(svalue)); - fprintf(fr, "\n"); - } else if (is_scalar) { - fprintf(fr, "%s ", PVname); - epicsStrPrintEscaped(fr, svalue, strlen(svalue)); - fprintf(fr, "\n"); - } else { - fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); - for (i=0; i\n"); - fclose(fr); - if (numPVsNotConnected < numPVs/2) { - /* copy trial restore file to real restore file */ - fr = fopen(trial_restoreFileName,"r"); - fr1 = fopen(restoreFileName,"w"); - while ((bp=fgets(s, BUF_SIZE, fr))) { - fputs(s, fr1); - } - fclose(fr); - fclose(fr1); - } - } - if (CA_buffer) free(CA_buffer); - fclose(fp); + if ((is_scalar != is_scalar_in_file) && !is_long_string) { + printf("*** %-25s is %s in file, but %s in ioc.\n", PVname, + is_scalar_in_file ? "scalar" : "array", is_scalar ? "scalar" : "array"); + } else { + if (is_long_string) { + epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); + different = strncmp(value_string, svalue, BUF_SIZE); + } else if (is_scalar) { + epicsStrnRawFromEscaped(value_string, BUF_SIZE, value_string, BUF_SIZE); + different = strcmp(value_string, svalue); + } else { + svalue_read = (char *)read_buffer; + for (i = 0, different = 0; i < element_count; i++) { + epicsStrnRawFromEscaped(svalue_read + (i * MAX_STRING_SIZE), MAX_STRING_SIZE, + svalue_read + (i * MAX_STRING_SIZE), MAX_STRING_SIZE); + j = strncmp(&svalue_read[i * MAX_STRING_SIZE], &svalue[i * MAX_STRING_SIZE], + MAX_STRING_SIZE); + different += (j != 0); + if (debug > 3) + printf("'%40s' != '%40s'\n", &svalue_read[i * MAX_STRING_SIZE], + &svalue[i * MAX_STRING_SIZE]); + } + } + if (different) numDifferences++; + if (different || (verbose > 0)) { + WRITE_HEADER; + if (is_scalar || is_long_string) { + nspace = 24 - strlen(value_string); + if (nspace < 1) nspace = 1; + printf("%s%-24s '%s'%*s'%s'\n", different ? "*** " : " ", PVname, value_string, + nspace, "", svalue); + } else { + printf("%s%-25s (array) %d diff%1c\n", different ? "*** " : " ", PVname, different, + different == 1 ? ' ' : 's'); + } + } + } + if (write_restore_file) { + if (is_long_string) { + svalue[BUF_SIZE - 1] = '\0'; + fprintf(fr, "%s ", PVname); + epicsStrPrintEscaped(fr, svalue, strlen(svalue)); + fprintf(fr, "\n"); + } else if (is_scalar) { + fprintf(fr, "%s ", PVname); + epicsStrPrintEscaped(fr, svalue, strlen(svalue)); + fprintf(fr, "\n"); + } else { + fprintf(fr, "%s %-s %1c ", PVname, ARRAY_MARKER, ARRAY_BEGIN); + for (i = 0; i < element_count; i++) { + pc = &svalue[i * MAX_STRING_SIZE]; + fprintf(fr, "%1c", ELEMENT_BEGIN); + for (j = 0; j < MAX_STRING_SIZE - 1 && *pc; j++, pc++) { + if ((*pc == ELEMENT_BEGIN) || (*pc == ELEMENT_END) || (*pc == ESCAPE)) { + fprintf(fr, "%1c", ESCAPE); + j++; + } + if (*pc == '\n') { + fprintf(fr, "%1cn", ESCAPE); + } else if (*pc == '\r') { + fprintf(fr, "%1cr", ESCAPE); + } else { + fprintf(fr, "%1c", *pc); + } + } + fprintf(fr, "%1c ", ELEMENT_END); + } + fprintf(fr, "%1c\n", ARRAY_END); + } + } + break; + default: printf("!!!%s mishandled field type (%d)\n", PVname, field_type); break; + } + ca_clear_channel(chid); + } + } + if (write_restore_file) { + fprintf(fr, "\n"); + fclose(fr); + if (numPVsNotConnected < numPVs / 2) { + /* copy trial restore file to real restore file */ + fr = fopen(trial_restoreFileName, "r"); + fr1 = fopen(restoreFileName, "w"); + while ((bp = fgets(s, BUF_SIZE, fr))) { fputs(s, fr1); } + fclose(fr); + fclose(fr1); + } + } + if (CA_buffer) free(CA_buffer); + fclose(fp); - if (verbose >= 0) printf("%d PV%sdiffered. (%d PV%schecked; %d PV%snot connected)\n", - numDifferences, numDifferences==1?" ":"s ", numPVs, numPVs==1?" ":"s ", - numPVsNotConnected, numPVsNotConnected==1?" ":"s "); + if (verbose >= 0) + printf("%d PV%sdiffered. (%d PV%schecked; %d PV%snot connected)\n", numDifferences, + numDifferences == 1 ? " " : "s ", numPVs, numPVs == 1 ? " " : "s ", numPVsNotConnected, + numPVsNotConnected == 1 ? " " : "s "); - return(numDifferences + numPVsNotConnected); + return (numDifferences + numPVsNotConnected); } static float safeDoubleToFloat(double d) { - float f; + float f; double abs = fabs(d); - if (d==0.0) { + if (d == 0.0) { f = 0.0; - } else if (abs>=FLT_MAX) { - if (d>0.0) f = FLT_MAX; else f = -FLT_MAX; - } else if (abs<=FLT_MIN) { - if (d>0.0) f = FLT_MIN; else f = -FLT_MIN; + } else if (abs >= FLT_MAX) { + if (d > 0.0) f = FLT_MAX; + else f = -FLT_MAX; + } else if (abs <= FLT_MIN) { + if (d > 0.0) f = FLT_MIN; + else f = -FLT_MIN; } else { f = d; } - return(f); + return (f); } -long read_array(FILE *fp, char *PVname, char *value_string, short field_type, long element_count, - char *read_buffer, int debug) +long read_array(FILE *fp, char *PVname, char *value_string, short field_type, long element_count, char *read_buffer, + int debug) { - int i, j, end_mark_found=0, begin_mark_found=0, end_of_file=0; - int found=0, in_element=0; - long status=0, num_read=0; - char buffer[BUF_SIZE], *bp = NULL; - char string[MAX_STRING_SIZE]; - char *p_char = NULL; - short *p_short = NULL; - float *p_float = NULL; - double *p_double = NULL; + int i, j, end_mark_found = 0, begin_mark_found = 0, end_of_file = 0; + int found = 0, in_element = 0; + long status = 0, num_read = 0; + char buffer[BUF_SIZE], *bp = NULL; + char string[MAX_STRING_SIZE]; + char *p_char = NULL; + short *p_short = NULL; + float *p_float = NULL; + double *p_double = NULL; - /** read array values **/ - if (debug > 1) printf("array_read: line='%80s'\n", value_string); + /** read array values **/ + if (debug > 1) printf("array_read: line='%80s'\n", value_string); - switch (field_type) { - case DBF_DOUBLE: p_double = (double *)read_buffer; break; - case DBF_FLOAT: p_float = (float *)read_buffer; break; - case DBF_ENUM: p_short = (short *)read_buffer; break; - default: p_char = (char *)read_buffer; break; - } - if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { - if (debug > 1) printf("array_read: line='%s'\n", bp); - begin_mark_found = 1; - for (num_read=0; bp && !end_mark_found; ) { - /* Find beginning of array element */ - if (debug > 1) printf("array_read: looking for element[%ld] \n", num_read); - while ((*bp != ELEMENT_BEGIN) && !end_mark_found && !end_of_file) { - if (debug > 1) printf("array_read: buffer contains '%s'\n", bp); - switch (*bp) { - case '\0': - if (debug > 1) printf("array_read: end-of-string\n"); - if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { - printf("read_array: *** EOF during array-parse\n"); - end_of_file = 1; - } - break; - case ARRAY_END: - if (debug > 1) printf("array_read: array-end\n"); - end_mark_found = 1; - break; - default: - ++bp; - break; - } - } - /* + switch (field_type) { + case DBF_DOUBLE: p_double = (double *)read_buffer; break; + case DBF_FLOAT: p_float = (float *)read_buffer; break; + case DBF_ENUM: p_short = (short *)read_buffer; break; + default: p_char = (char *)read_buffer; break; + } + if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) { + if (debug > 1) printf("array_read: line='%s'\n", bp); + begin_mark_found = 1; + for (num_read = 0; bp && !end_mark_found;) { + /* Find beginning of array element */ + if (debug > 1) printf("array_read: looking for element[%ld] \n", num_read); + while ((*bp != ELEMENT_BEGIN) && !end_mark_found && !end_of_file) { + if (debug > 1) printf("array_read: buffer contains '%s'\n", bp); + switch (*bp) { + case '\0': + if (debug > 1) printf("array_read: end-of-string\n"); + if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { + printf("read_array: *** EOF during array-parse\n"); + end_of_file = 1; + } + break; + case ARRAY_END: + if (debug > 1) printf("array_read: array-end\n"); + end_mark_found = 1; + break; + default: ++bp; break; + } + } + /* * Read one element: Accumulate characters of element value into string[], * ignoring any nonzero control characters, and append the value to the local array. */ - if (bp && !end_mark_found && !end_of_file) { - /* *bp == ELEMENT_BEGIN */ - if (debug > 1) printf("array_read: found element-begin: '%s'\n", bp); - for (bp++, j=0; (j < MAX_STRING_SIZE-1) && (*bp != ELEMENT_END); bp++) { - if (*bp == '\0') { - if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { - printf("read_array:array_restore: *** premature EOF.\n"); - end_of_file = 1; - break; - } - if (debug > 1) printf("array_read: new buffer: '%s'\n", bp); - if (*bp == ELEMENT_END) break; - } else if ((*bp == ESCAPE) && ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { - /* escaped character */ - if (debug > 1) printf("array_read: escaped element-begin/end '%s'\n", bp); - bp++; - } - if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ - } - string[j] = '\0'; + if (bp && !end_mark_found && !end_of_file) { + /* *bp == ELEMENT_BEGIN */ + if (debug > 1) printf("array_read: found element-begin: '%s'\n", bp); + for (bp++, j = 0; (j < MAX_STRING_SIZE - 1) && (*bp != ELEMENT_END); bp++) { + if (*bp == '\0') { + if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { + printf("read_array:array_restore: *** premature EOF.\n"); + end_of_file = 1; + break; + } + if (debug > 1) printf("array_read: new buffer: '%s'\n", bp); + if (*bp == ELEMENT_END) break; + } else if ((*bp == ESCAPE) && + ((bp[1] == ELEMENT_BEGIN) || (bp[1] == ELEMENT_END) || (bp[1] == ESCAPE))) { + /* escaped character */ + if (debug > 1) printf("array_read: escaped element-begin/end '%s'\n", bp); + bp++; + } + if (isprint((int)(*bp))) string[j++] = *bp; /* Ignore, e.g., embedded newline */ + } + string[j] = '\0'; - /* + /* * We've accumulated all the characters, or all we can handle in string[]. * If there are more characters than we can handle, just pretend we read them. */ - /* *bp == ELEMENT_END ,*/ - if (debug > 1) printf("array_read: looking for element-end: '%s'\n", bp); - for (found = 0; (found == 0) && !end_of_file; ) { - while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; - switch (*bp) { - case ELEMENT_END: - found = 1; - bp++; - break; - case ESCAPE: - ++bp; - if (*bp == ELEMENT_END || *bp == ESCAPE) { - ++bp; - } - break; - default: - if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { - end_of_file = 1; - found = 1; - } - } - } + /* *bp == ELEMENT_END ,*/ + if (debug > 1) printf("array_read: looking for element-end: '%s'\n", bp); + for (found = 0; (found == 0) && !end_of_file;) { + while (*bp && (*bp != ELEMENT_END) && (*bp != ESCAPE)) bp++; + switch (*bp) { + case ELEMENT_END: + found = 1; + bp++; + break; + case ESCAPE: + ++bp; + if (*bp == ELEMENT_END || *bp == ESCAPE) { ++bp; } + break; + default: + if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { + end_of_file = 1; + found = 1; + } + } + } - /* Append value to local array. */ - if (read_buffer) { - epicsStrnRawFromEscaped(string, MAX_STRING_SIZE, string, MAX_STRING_SIZE); - switch (field_type) { - case DBF_ENUM: - p_short[num_read++] = (short)atol(string); - break; - case DBF_FLOAT: - p_float[num_read++] = safeDoubleToFloat(atof(string)); - break; - case DBF_DOUBLE: - p_double[num_read++] = atof(string); - break; - default: - strncpy(&(p_char[(num_read++)*MAX_STRING_SIZE]), string, MAX_STRING_SIZE); - break; - } - } - } - } /* for (num_read=0; bp && !end_mark_found; ) */ - } /* if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) */ + /* Append value to local array. */ + if (read_buffer) { + epicsStrnRawFromEscaped(string, MAX_STRING_SIZE, string, MAX_STRING_SIZE); + switch (field_type) { + case DBF_ENUM: p_short[num_read++] = (short)atol(string); break; + case DBF_FLOAT: p_float[num_read++] = safeDoubleToFloat(atof(string)); break; + case DBF_DOUBLE: p_double[num_read++] = atof(string); break; + default: strncpy(&(p_char[(num_read++) * MAX_STRING_SIZE]), string, MAX_STRING_SIZE); break; + } + } + } + } /* for (num_read=0; bp && !end_mark_found; ) */ + } /* if ((bp = strchr(value_string, (int)ARRAY_BEGIN)) != NULL) */ - /* clear unused read_buffer space */ - for (i=num_read; i 1) printf("array_read: positioning for next PV '%s'\n", bp); - if (begin_mark_found) { - /* find ARRAY_END (but ARRAY_END inside an element is just another character) */ - in_element = 0; - while (!end_mark_found && !end_of_file) { - switch (*bp) { - case ESCAPE: - if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ - break; - case ARRAY_END: - if (!in_element) end_mark_found = 1; - break; - case '\0': - if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { - printf("read_array: *** EOF during array-end search\n"); - end_of_file = 1; - } - break; - default: - /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ - if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; - break; - } - if (bp) ++bp; - } - } else { - status = -1; - /* just get next line, assuming it contains the next PV */ - if (!end_of_file) { - if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) end_of_file = 1; - } - } - if (debug > 1) printf("array_read: positioned for next PV '%s'\n", bp); - if (!status && end_of_file) status = end_of_file; + /* leave the file pointer ready for next PV (next fgets() should yield next PV) */ + if (debug > 1) printf("array_read: positioning for next PV '%s'\n", bp); + if (begin_mark_found) { + /* find ARRAY_END (but ARRAY_END inside an element is just another character) */ + in_element = 0; + while (!end_mark_found && !end_of_file) { + switch (*bp) { + case ESCAPE: + if (in_element && (bp[1] == ELEMENT_END)) bp++; /* two chars treated as one */ + break; + case ARRAY_END: + if (!in_element) end_mark_found = 1; + break; + case '\0': + if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) { + printf("read_array: *** EOF during array-end search\n"); + end_of_file = 1; + } + break; + default: + /* Can't use ELEMENT_BEGIN, ELEMENT_END as cases; they might be the same. */ + if ((*bp == ELEMENT_BEGIN) || (*bp == ELEMENT_END)) in_element = !in_element; + break; + } + if (bp) ++bp; + } + } else { + status = -1; + /* just get next line, assuming it contains the next PV */ + if (!end_of_file) { + if ((bp = fgets(buffer, BUF_SIZE, fp)) == NULL) end_of_file = 1; + } + } + if (debug > 1) printf("array_read: positioned for next PV '%s'\n", bp); + if (!status && end_of_file) status = end_of_file; - return(status); + return (status); } diff --git a/iocs/autosaveIOC/autosaveApp/src/asMain.cpp b/iocs/autosaveIOC/autosaveApp/src/asMain.cpp index ae0ecb6..a5eb730 100644 --- a/iocs/autosaveIOC/autosaveApp/src/asMain.cpp +++ b/iocs/autosaveIOC/autosaveApp/src/asMain.cpp @@ -11,13 +11,13 @@ #include "epicsThread.h" #include "iocsh.h" -int main(int argc,char *argv[]) +int main(int argc, char *argv[]) { - if(argc>=2) { + if (argc >= 2) { iocsh(argv[1]); epicsThreadSleep(.2); } iocsh(NULL); epicsExit(0); - return(0); + return (0); }