~ubuntu-branches/ubuntu/quantal/psicode/quantal

« back to all changes in this revision

Viewing changes to src/lib/libpsio/write.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-09-10 14:01:33 UTC
  • Revision ID: james.westby@ubuntu.com-20060910140133-ib2j86trekykfsfv
Tags: upstream-3.2.3
ImportĀ upstreamĀ versionĀ 3.2.3

Show diffs side-by-side

added added

removed removed

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