home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / CD32 / CD32_Support / examples / SA_Examples / nonvolatile / StoreNV.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-31  |  9.7 KB  |  333 lines

  1. /* StoreNV.c
  2.  * 
  3.  * Test of nonvolatile.library/StoreNV()
  4.  * 
  5.  * 
  6.  */
  7.  
  8. /* Includes --------------------------------------------- */
  9. #include <exec/types.h>
  10. #include <exec/libraries.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <dos/rdargs.h>
  14. #include <libraries/nonvolatile.h>
  15. #include <utility/tagitem.h>
  16. #include <clib/exec_protos.h>
  17. #include <clib/dos_protos.h>
  18. #include <clib/nonvolatile_protos.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21.  
  22. #include <pragmas/nonvolatile_pragmas.h>
  23.  
  24. #include "nv.h"   /* local defaults for many programs */
  25.  
  26. /* Defines ------------------------------------------ */
  27. #define PROGNAME "StoreNV"
  28. #define ERRMSG_LIBNOOPEN "Couldn't open %s V%ld (or better)!\n"
  29. #define ERRMSG_MX_OPTS   "Only one of DATA/K,FILE/K,BUFSIZE/K/N may be specified!\n"
  30. #define TEMPLATE "NAME=APPNAME/K,ITEM=ITEMNAME/K,DATA/K,FILE=DATAFILE/K,BUFSIZE/K/N,BUFFILL/N,NULL=NULLTEST/S,ZERO=ZEROTEST/S,KILLREQ/S,TRUEBUFSIZE=BETRUE/S,NOLIE=NOROUNDTONV/S"
  31.  
  32.  
  33. /* Structs ------------------------------ */
  34. struct Opts {
  35.     STRPTR name;                /* application name, default NVTest      */
  36.     STRPTR item;                /* data nv-storage name, default Test01  */
  37.     STRPTR data;                /* string of data to be stored           */
  38.     STRPTR file;                /* file containing data to be stored     */
  39.     ULONG *bufsize;             /* buffer size for optional data pattern */
  40.     LONG  *buffill;             /* buffer pattern                        */
  41.                                 /* Note that only one of data|file|bufsize may be specified */
  42.     LONG nullTest;              /* feed StoreNV a null data pointer        */
  43.     LONG zeroTest;              /* feed StoreNV valid pointer, but 0 bytes */
  44.     LONG killReq;               /* kill requesters for "nv" disk...        */
  45.     LONG beTrue;                /* do NOT do roundup by 10, probably crash */
  46.     LONG noLieAboutSize;        /* don't round size of buffer upwards for feed to StoreNV() */
  47. };
  48.  
  49. /* Protos ------------------------------------------ */
  50. static VOID GoodBye(int);
  51. static LONG doInit(VOID);
  52. static LONG findFileSize(BPTR);
  53. static ULONG lieAboutLength(ULONG);
  54. static ULONG roundUp(ULONG);
  55.  
  56. /* Globals --------------------------------------- */
  57. struct Opts     opts;
  58. struct RDArgs  *rdargs;
  59. struct Library *NVBase;
  60. BPTR            fh;
  61. STRPTR          buf;
  62.  
  63.  
  64. VOID main(int argc, UBYTE *argv[]) {
  65.     LONG fileSize, amtRead;
  66.     STRPTR item, name;
  67.     STRPTR storePtr=NULL;        /* ptr to data to store */
  68.     ULONG storeSize=0UL;         /* byte length of data, fed to StoreNV */
  69.     UWORD snvErr;
  70.     int rc=RETURN_OK, i;
  71.     LONG ioErr;
  72.     BOOL killReq;
  73.     ULONG allocSize;             /* for memory allocations */
  74.  
  75.     if (!doInit()) {
  76.         /* handles mutual exclude of file|data|buffer, too... */
  77.         GoodBye(RETURN_FAIL);
  78.     }
  79.  
  80.     killReq = ((opts.killReq) ? TRUE : FALSE);
  81.  
  82.     /* File options.... read file and put it into a buffer. */
  83.     if (opts.file) {
  84.         fh = Open(opts.file, MODE_OLDFILE);
  85.         if (!fh) {
  86.             PrintFault(IoErr(),PROGNAME);
  87.             Printf("Cannot open file '%s'!\n", opts.file);
  88.             GoodBye(RETURN_FAIL);
  89.         }
  90.         fileSize = findFileSize(fh);
  91.         if (fileSize < 0L) {
  92.             Printf("Cannot use file with size %ld!\n", fileSize);
  93.             GoodBye(RETURN_FAIL);
  94.         }
  95.         allocSize = ((opts.beTrue) ? (ULONG)fileSize : roundUp(fileSize));
  96.         buf = AllocVec(allocSize, MEMF_CLEAR);
  97.         if (!buf) {
  98.             PrintFault(IoErr(),PROGNAME);
  99.             Printf("Cannot allocate %lu bytes of RAM for buffer!\n", allocSize);
  100.             GoodBye(RETURN_FAIL);
  101.         }
  102.         amtRead = Read(fh, buf, fileSize);
  103.         if (amtRead < 0L) {
  104.             PrintFault(IoErr(),PROGNAME);
  105.             PutStr("Error reading; will use storage size of zero.\nHit Control-C to abort.\n");
  106.             Delay(100L);
  107.             if (CheckSignal(SIGBREAKF_CTRL_C)) {
  108.                 GoodBye(RETURN_WARN);
  109.             }
  110.         }
  111.         Printf("Read %ld bytes into buffer.\n", amtRead);
  112.         storeSize = (ULONG)((amtRead >= 0L) ? amtRead : 0UL);
  113.         storePtr = buf;
  114.     }
  115.  
  116.     if (opts.data) {
  117.         /* user has provided string to store */
  118.         storeSize = strlen(opts.data) + 1L;   /* include the NULL */
  119.         allocSize = ((opts.beTrue) ? (ULONG)storeSize : roundUp(storeSize));
  120.         buf = AllocVec(allocSize, MEMF_CLEAR);
  121.         if (!buf) {
  122.             PrintFault(IoErr(),PROGNAME);
  123.             Printf("Cannot allocate %lu bytes of RAM for buffer!\n", allocSize);
  124.             GoodBye(RETURN_FAIL);
  125.         }
  126.         for (i = 0; i < storeSize; i++) {
  127.             buf[i] = opts.data[i];
  128.         }
  129.         storePtr = buf;
  130.     }
  131.     if (opts.bufsize) {
  132.         allocSize = ((opts.beTrue) ? *opts.bufsize : roundUp(*opts.bufsize));
  133.         buf = AllocVec(allocSize, MEMF_CLEAR);
  134.         if (!buf) {
  135.             PrintFault(IoErr(),PROGNAME);
  136.             Printf("Cannot allocate %lu bytes of RAM for buffer!\n", allocSize);
  137.             GoodBye(RETURN_FAIL);
  138.         }
  139.         if (opts.buffill) {
  140.             memset(buf,(UBYTE)(*opts.buffill), allocSize);
  141.         }
  142.         storeSize = *opts.bufsize;   /* not allocSize! */
  143.         storePtr  = buf;
  144.     }
  145.  
  146.     /* nvlib likes its data length in *tens* of bytes.  I have no clue
  147.        how they expect this to not cause enforcer hits.
  148.      */
  149.     if ((!(opts.beTrue)) && (!(opts.noLieAboutSize))) {
  150.         /* this rounds up storeSize, then divides it by 10 */
  151.         storeSize = lieAboutLength(storeSize);
  152.     }
  153.  
  154.     item = ((opts.item) ? opts.item : (STRPTR)DEFAULT_ITEM_NAME);
  155.     name = ((opts.item) ? opts.name : (STRPTR)DEFAULT_APP_NAME);
  156.  
  157.  
  158.     if (opts.nullTest) {
  159.         storePtr = NULL;
  160.     }
  161.     if (opts.zeroTest) {
  162.         storeSize = 0UL;
  163.     }
  164.  
  165.     Printf("Calling StoreNV(%s, %s, $%08lx, %lu, %lu)...\n",
  166.             name, item, storePtr, storeSize, (ULONG)killReq);
  167.  
  168.     Delay(10L);  /* if it's gonna crash, let it print first! */
  169.  
  170.     /* StoreNV() call ---------------------------------------- */
  171.     snvErr = StoreNV(name, item, storePtr, storeSize, killReq);
  172.     ioErr = IoErr();
  173.  
  174.     if (!snvErr) {
  175.         PutStr("StoreNV() reported success.\n");
  176.     }
  177.     else {
  178.         rc = RETURN_ERROR;
  179.         Printf("StoreNV() reported error %lu:\n", (ULONG)(snvErr));
  180.         switch (snvErr) {
  181.             case NVERR_BADNAME:
  182.                 PutStr("  Error in AppName or ItemName.\n");
  183.                 break;
  184.             case NVERR_WRITEPROT:
  185.                 PutStr("  Nonvolatile storage is read-only.\n");
  186.                 break;
  187.             case NVERR_FAIL:
  188.                 PutStr("  Failure in writing data.\n");
  189.                 break;
  190.             case NVERR_FATAL:
  191.                 PutStr("  Fatal error, possible loss of previously-saved data.\n");
  192.                 break;
  193.             default:
  194.                 PutStr("  Unknown error!\n");
  195.                 break;
  196.         }
  197.     }
  198.     Printf("IoErr was %ld  ", ioErr);
  199.     PrintFault(ioErr,NULL);
  200.     if (!ioErr) {
  201.         PutStr("\n");  /* in this case, PrintFault() didn't do a newline... */
  202.     }
  203.  
  204.  
  205.     GoodBye(rc);
  206. }
  207.  
  208. /* roundUp ======================================================
  209.     round a number up to the closest one evenly divisible by 10.
  210.     intended for memory allocations.
  211.  */
  212. static ULONG roundUp(ULONG oldSize) {
  213.  
  214.     if (!(oldSize % 10))
  215.         return(oldSize);
  216.  
  217.     return(oldSize + (oldSize % 10));
  218. }
  219.  
  220. /* findFileSize ==================================================
  221.    Examine()s the file to find its size (and whether it's a file).
  222.    Returns -1 for error.
  223. */
  224. static LONG findFileSize(BPTR f) {
  225.     struct FileInfoBlock *fib;
  226.     LONG result = -1L;
  227.     
  228.     if (fib = AllocDosObjectTags(DOS_FIB, TAG_DONE)) {
  229.         if (ExamineFH(fh, fib)) {
  230.             if (fib->fib_DirEntryType < 0L) {
  231.                 /* ie, it's a file */
  232.                 result = fib->fib_Size;
  233.             }
  234.             else {
  235.                 PutStr("Please specify a *file*, not a directory!\n");
  236.             }
  237.         }
  238.         else {
  239.             PutStr("Couldn't ExamineFH() the file!\n");
  240.         }
  241.         FreeDosObject(DOS_FIB, fib);
  242.     }
  243.     else {
  244.         PutStr("Couldn't allocate RAM for FileInfoBlock!\n");
  245.     }
  246.     
  247.     return(result);
  248. }
  249.  
  250. /* lieAboutLength ===============================================================
  251.    simply round off the given number up to the next number evenly divisible by 10.
  252.    Return that number divided by ten.
  253.  */
  254. static ULONG lieAboutLength(ULONG syze) {
  255.     SHORT odd;
  256.  
  257.     if (odd = syze % 10) {
  258.         syze += (ULONG)(10 - odd);
  259.     }
  260.     return(syze/10UL);
  261. }
  262.  
  263. /* GoodBye ===============================================
  264.    Clean-exit routine.
  265.  */
  266. static VOID GoodBye(int rc) {
  267.  
  268.     if (fh) {
  269.         Close(fh);
  270.     }
  271.  
  272.     if (buf) {
  273.         FreeVec(buf);
  274.     }
  275.  
  276.     if (NVBase) {
  277.         CloseLibrary(NVBase);
  278.     }
  279.  
  280.     if (rdargs) {
  281.         FreeArgs(rdargs);
  282.     }
  283.  
  284.     exit(rc);
  285. }
  286.  
  287. /* doInit =============================================
  288.  * Open libraries, call ReadArgs() if necessary.
  289.  * Returns TRUE for success, FALSE otherwise.
  290.  */
  291. static LONG doInit(VOID) {
  292.     int mx=0;
  293.  
  294.     rdargs = ReadArgs(TEMPLATE, (LONG *)&opts, NULL);
  295.     if (!rdargs) {
  296.         PrintFault(IoErr(), PROGNAME);
  297.         return(FALSE);
  298.     }
  299.  
  300.     NVBase = OpenLibrary("nonvolatile.library", 40L);
  301.     if (!NVBase) {
  302.         Printf(ERRMSG_LIBNOOPEN, "nonvolatile.library", 40L);
  303.         return(FALSE);
  304.     }
  305.  
  306.     /* check mutual-exclude options */
  307.     if (opts.data) {
  308.         mx++;
  309.     }
  310.     if (opts.file) {
  311.         mx++;
  312.         if (mx >= 2L) {
  313.             PutStr(ERRMSG_MX_OPTS);
  314.             return(FALSE);
  315.         }
  316.     }
  317.     if (opts.bufsize) {
  318.         mx++;
  319.         if (mx >= 2L) {
  320.             PutStr(ERRMSG_MX_OPTS);
  321.             return(FALSE);
  322.         }
  323.     }
  324.  
  325.     if ((!mx) && (!opts.nullTest)) {
  326.         PutStr("You must specify a data source (NULL for none).\n");
  327.         return(FALSE);
  328.     }
  329.  
  330.     return(TRUE);
  331. }
  332.  
  333.