#ident "$URL: svn://elmer/devel/SVN/SDDAS/trunk/libdB/CreateDbf.c $ %D% SwRI" #include #include #include #include #include #include #include #include #include #include #include "dbf.h" /********************* ** >FILE: CreateDbf.c *********************/ Header_t tHeader; /****************************************************** ** Function: int MakeOneFieldDesc(dbfRecord_t *D, ** FieldDesc_t *F, ** FieldRecord_t *Field) ** ** dbfRecord_t *D - pointer to database structure ** FieldDesc_t *F - pointer to source field information ** FieldRecord_t *Field - pointer to destination field information ** ** Description: ** define one field (copy the field into the header) ** ** Return Values: ** ***************** *****************/ int MakeOneFieldDesc(dbfRecord_t *D, FieldDesc_t *F, FieldRecord_t *Field) { /* | copy the field info into the header */ if (islower((int) Field->Typ)) Field->Typ = toupper ((int) Field->Typ); memcpy(F, &Field->Name[0], 10); /* | set the type and length of the field */ *(*F+11) = Field->Typ; *(*F+16) = Field->Len; switch(Field->Typ) { case MEMO: D->WithMemo = (char) sTrue; case CHARACTER: case DATE: case LOGICAL: Field->Dec = 0; break; /* | decimals will only exist of the field is numeric */ case NUMERIC: *(*F+17) = Field->Dec; break; default: sprintf(msg, "Unknown field type '%c' for field name: '%s'\n", Field->Typ, Field->Name); dbf_code = UNKNOWN_FIELD_TYPE; return FAILURE; } /* | increment the record size by the length of the field */ D->RecLen += Field->Len; return SUCCESS; } /* | || ||| MakeFieldDescs() - define all fields, store the info in the header buffer || | */ int MakeFieldDescs(dbfRecord_t *D, FieldRecord_t *Flds) { int i, rval; /* | start with the record length of 1, this element will be used to determine | if this record has been deleted or not; '*' means deleted while ' ' means | this record is not deleted */ D->RecLen = 1; /* | loop over all fields */ for (i=1; i<=D->NumFields; i++) { if ((rval=MakeOneFieldDesc(D, (FieldDesc_t *)&tHeader[i*32], Flds++)) != SUCCESS) { return rval; } } return SUCCESS; } /* | || ||| MakeHeader() - generate necessary header info based on the record info || | */ #define Lo(a) ((unsigned char)(a % 256)) #define Hi(a) ((unsigned char)(a / 255)) int MakeHeader(dbfRecord_t *D, FieldRecord_t *Flds) { int rval; struct tm *mytm; time_t tloc = 1; /* | initialize the header buffer to hold all the structure info for the | database file */ memset(tHeader, 0, sizeof(Header_t)); /* | generate the month, day, and year for the header info */ time(&tloc); mytm = localtime(&tloc); tHeader[1] = (unsigned char)mytm->tm_year; /* Year */ tHeader[2] = (unsigned char)mytm->tm_mon+1; /* Month of year */ tHeader[3] = (unsigned char)mytm->tm_mday; /* Day of month */ /* | set the memo field, set the header length based upon the | number of fields passed in */ D->WithMemo = (char) sFalse; D->HeadLen = (D->NumFields + 1) * 32; tHeader[D->HeadLen] = 0xD; D->HeadLen = D->HeadLen + 1; tHeader[8] = Lo(D->HeadLen); tHeader[9] = Hi(D->HeadLen); /* | define all the fields */ if ((rval=MakeFieldDescs(D, Flds)) != SUCCESS) { return rval; } if ((SDDAS_BOOL) D->WithMemo == sTrue) { tHeader[0] = DB3WithMemo; } else { tHeader[0] = DB3File; } /* | must break the record length into 2 bytes and store */ tHeader[10] = Lo(D->RecLen); tHeader[11] = Hi(D->RecLen); return SUCCESS; } /***************************************************************************** ** Function: int CreateDbf(int *handle, char *fn, int n, FieldRecord_t *Flds) ** ** int *handle - database handle ** char *fn - file name for to create for the database ** int n - number of fields in the database ** FieldRecord_t *Flds - pointer to the field descriptions ** ** Description: ** Call this procedure with the full pathname of the file that you want ** to create (fn), the number of fields in a record (n), and a pointer ** to an array of FieldRecord_t (Flds). The procedure will initialize all ** the data structures in the dbfRecord (D). ** ** Return Values: ** ***************** *****************/ dbRet_t CreateDbf(SDDAS_INT *handle, char *fn, SDDAS_INT n, FieldRecord_t *Flds) { SDDAS_INT i, offset; dbRet_t rval; dbfRecord_t *D; memset(tHeader, 0, sizeof(Header_t)); if ((D = GetNewDbfHandle(handle)) == NULL) return FAILURE; /* | set the number of fields passed in then put them into the database | structure */ D->NumFields = n; /* | fill the header with the field info */ if ((rval=MakeHeader(D, Flds)) != SUCCESS) { return rval; } /* | store away the database file name and open the file */ (void)strcpy(D->FileName, fn); if ((D->dFile = open(D->FileName, O_WRONLY | O_CREAT | O_BINARY, 0666)) < 0) { dbf_code = errno; sprintf(msg, "'%s'", D->FileName); return FAILURE; } /* | set the number of record in the database to zero */ tHeader[4] = 0; tHeader[5] = 0; tHeader[6] = 0; tHeader[7] = 0; /* | write out the header info */ if (write(D->dFile, tHeader, D->HeadLen) < 0) { dbf_code = errno; sprintf(msg, "'%s'", D->FileName); return FAILURE; } /* | initialize the header status, the number of records currently in the | database and the date of the last update */ D->hStatus = NotUpdated; D->NumRecs = 0; memcpy(D->HeadProlog, tHeader, sizeof(D->HeadProlog)); (void)strcpy(D->DateOfUpdate, " / / "); (void)sprintf(D->DateOfUpdate, "%02d/%02d/%02d", tHeader[2], tHeader[3], tHeader[1]); /* | allocate the memory for the current database record (only one) */ if ((D->CurRecord = (DataRecord_t *)calloc(1, D->RecLen)) == NULL) { dbf_msg_clr; dbf_code = errno; return FAILURE; } /* | allocate the memory for the field definitions in the database structure */ if ((D->Fields = (FieldRecord_t *)calloc(D->NumFields, sizeof(FieldRecord_t))) == NULL) { dbf_code = errno; dbf_msg_clr; return FAILURE; } /* | store the field definitions in the database structure */ offset = 1; for (i=0; iNumFields; i++) { D->Fields[i] = Flds[i]; D->Fields[i].Parm = (char *)&(D->CurRecord[0][offset]); offset += D->Fields[i].Len; } /* | this database has just been created, there are no records in it .. yet */ D->CurRec = 0; dbf_code = 0; dbf_msg_clr; return SUCCESS; }