| [0b990d] | 1 | /*!
 | 
|---|
 | 2 |    \file write.c
 | 
|---|
 | 3 |    \ingroup (PSIO)
 | 
|---|
 | 4 | */
 | 
|---|
 | 5 | 
 | 
|---|
 | 6 | #include <stdlib.h>
 | 
|---|
 | 7 | #include <string.h>
 | 
|---|
 | 8 | #include <util/psi3/libpsio/psio.h>
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 | namespace psi3 {
 | 
|---|
 | 11 | namespace libpsio {
 | 
|---|
 | 12 | 
 | 
|---|
 | 13 | /*!
 | 
|---|
 | 14 | ** PSIO_WRITE(): Writes data to a TOC entry in a PSI file.
 | 
|---|
 | 15 | **
 | 
|---|
 | 16 | **  \param unit   = The PSI unit number used to identify the file to all read
 | 
|---|
 | 17 | **                  and write functions.
 | 
|---|
 | 18 | **  \param key    = The TOC keyword identifying the desired entry.
 | 
|---|
 | 19 | **  \param buffer = The buffer from which the data is written.
 | 
|---|
 | 20 | **  \param size   = The number of bytes to write.
 | 
|---|
 | 21 | **  \param sadd   = The entry-relative starting page/offset to write the data.
 | 
|---|
 | 22 | **  \param eadd   = A pointer to the entry-relative page/offset for the next
 | 
|---|
 | 23 | **                  byte after the end of the write request.
 | 
|---|
 | 24 | **
 | 
|---|
 | 25 | ** \ingroup (PSIO)
 | 
|---|
 | 26 | */
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | int psio_write(unsigned int unit, char *key, char *buffer, ULI size,
 | 
|---|
 | 29 |                psio_address rel_start, psio_address *rel_end)
 | 
|---|
 | 30 | {
 | 
|---|
 | 31 |   psio_ud *this_unit;
 | 
|---|
 | 32 |   psio_tocentry *this_entry, *last_entry;
 | 
|---|
 | 33 |   psio_address address, end_address;
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 |   this_unit = &(psio_unit[unit]);
 | 
|---|
 | 36 | 
 | 
|---|
 | 37 |   /* Find the entry in the TOC */
 | 
|---|
 | 38 |   this_entry = psio_tocscan(unit, key);
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 |   if(this_entry == NULL) { /* New TOC entry */
 | 
|---|
 | 41 |     if(rel_start.page||rel_start.offset) psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 |     this_entry = (psio_tocentry *) malloc(sizeof(psio_tocentry));
 | 
|---|
 | 44 |     strcpy(this_entry->key,key);
 | 
|---|
 | 45 |     this_entry->next = NULL;
 | 
|---|
 | 46 |     this_entry->last = NULL;
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 |     /* Compute the address of the entry */
 | 
|---|
 | 49 |     if(!(this_unit->toclen)) { /* First TOC entry */
 | 
|---|
 | 50 |       this_entry->sadd.page = 0;
 | 
|---|
 | 51 |       this_entry->sadd.offset = 3*sizeof(ULI);
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 |       this_unit->toc = this_entry;
 | 
|---|
 | 54 |     }
 | 
|---|
 | 55 |     else {  /* Use ending address from last TOC entry */
 | 
|---|
 | 56 |       last_entry = psio_toclast(unit);
 | 
|---|
 | 57 |       this_entry->sadd = last_entry->eadd;
 | 
|---|
 | 58 | 
 | 
|---|
 | 59 |       last_entry->next = this_entry;
 | 
|---|
 | 60 |       this_entry->last = last_entry;
 | 
|---|
 | 61 |     }
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 |     /* Data for the write call */
 | 
|---|
 | 64 |     address = this_entry->sadd;
 | 
|---|
 | 65 | 
 | 
|---|
 | 66 |     /* Set the end address for this_entry */
 | 
|---|
 | 67 |     this_entry->eadd = psio_get_address(this_entry->sadd, size);
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 |     /* Update the unit's TOC stats */
 | 
|---|
 | 70 |     this_unit->toclen++;
 | 
|---|
 | 71 |     this_unit->tocaddress = this_entry->eadd;
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 |     /* Update the rel_end argument value for the caller */
 | 
|---|
 | 74 |     *rel_end = psio_get_address(rel_start,size);
 | 
|---|
 | 75 |   }
 | 
|---|
 | 76 |   else { /* Old TOC entry */
 | 
|---|
 | 77 | 
 | 
|---|
 | 78 |     /* Compute the global starting page and offset for the block */
 | 
|---|
 | 79 |     address = psio_get_global_address(this_entry->sadd, rel_start);
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 |     /* Make sure this block doesn't start past the end of the entry */
 | 
|---|
 | 82 |     if(address.page > this_entry->eadd.page)
 | 
|---|
 | 83 |       psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
 | 84 |     else if((address.page == this_entry->eadd.page) &&
 | 
|---|
 | 85 |             (address.offset > this_entry->eadd.offset))
 | 
|---|
 | 86 |       psio_error(unit,PSIO_ERROR_BLKSTART);
 | 
|---|
 | 87 | 
 | 
|---|
 | 88 |     /* Compute the new global ending address for the entry, if necessary */
 | 
|---|
 | 89 |     end_address = psio_get_address(address, size);
 | 
|---|
 | 90 |     if(end_address.page > this_entry->eadd.page) {
 | 
|---|
 | 91 |       if(this_entry->next != NULL) {
 | 
|---|
 | 92 |         fprintf(stderr, "PSIO_ERROR: Attempt to write into next entry: %d, %s\n", 
 | 
|---|
 | 93 |                 unit, key);
 | 
|---|
 | 94 |         psio_error(unit, PSIO_ERROR_BLKEND);
 | 
|---|
 | 95 |       }
 | 
|---|
 | 96 |       this_entry->eadd = end_address;
 | 
|---|
 | 97 |       this_unit->tocaddress = end_address;
 | 
|---|
 | 98 |           
 | 
|---|
 | 99 |     }
 | 
|---|
 | 100 |     else if((end_address.page == this_entry->eadd.page) &&
 | 
|---|
 | 101 |             (end_address.offset > this_entry->eadd.offset))
 | 
|---|
 | 102 |       {
 | 
|---|
 | 103 |         if(this_entry->next != NULL) {
 | 
|---|
 | 104 |           fprintf(stderr, "PSIO_ERROR: Attempt to write into next entry: %d, %s\n", 
 | 
|---|
 | 105 |                   unit, key);
 | 
|---|
 | 106 |           psio_error(unit, PSIO_ERROR_BLKEND);
 | 
|---|
 | 107 |         }
 | 
|---|
 | 108 |         this_entry->eadd = end_address;
 | 
|---|
 | 109 |         this_unit->tocaddress = end_address;
 | 
|---|
 | 110 |       }
 | 
|---|
 | 111 | 
 | 
|---|
 | 112 |     /* Update the eadd argument value for the caller */
 | 
|---|
 | 113 |     *rel_end = psio_get_address(rel_start, size);
 | 
|---|
 | 114 |   }
 | 
|---|
 | 115 | 
 | 
|---|
 | 116 |   /* Now write the actual data to the unit */
 | 
|---|
 | 117 |   psio_rw(unit, buffer, address, size, 1);
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 | #ifdef PSIO_STATS
 | 
|---|
 | 120 |   psio_writlen[unit] += size;
 | 
|---|
 | 121 | #endif
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 |   return(0);
 | 
|---|
 | 124 | }
 | 
|---|
 | 125 | 
 | 
|---|
 | 126 | }
 | 
|---|
 | 127 | }
 | 
|---|