~ubuntu-branches/ubuntu/precise/psicode/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck, Michael Banck, Daniel Leidert
  • Date: 2009-02-23 00:12:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090223001202-rutldoy3dimfpesc
Tags: 3.4.0-1
* New upstream release.

[ Michael Banck ]
* debian/patches/01_DESTDIR.dpatch: Refreshed.
* debian/patches/02_FHS.dpatch: Removed, applied upstream.
* debian/patches/03_debian_docdir: Likewise.
* debian/patches/04_man.dpatch: Likewise.
* debian/patches/06_466828_fix_gcc_43_ftbfs.dpatch: Likewise.
* debian/patches/07_464867_move_executables: Fixed and refreshed.
* debian/patches/00list: Adjusted.
* debian/control: Improved description.
* debian/patches-held: Removed.
* debian/rules (install/psi3): Do not ship the ruby bindings for now.

[ Daniel Leidert ]
* debian/rules: Fix txtdir via DEB_MAKE_INSTALL_TARGET.
* debian/patches/01_DESTDIR.dpatch: Refreshed.

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 start   = The entry-relative starting page/offset to write the data.
19
 
**  \param end     = 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 start, psio_address *end)
27
 
{
28
 
  psio_ud *this_unit;
29
 
  psio_tocentry *this_entry, *last_entry;
30
 
  psio_address start_toc, start_data, end_data; /* global addresses */
31
 
  ULI tocentry_size;
32
 
  int dirty = 0;
33
 
 
34
 
  this_unit = &(psio_unit[unit]);
35
 
 
36
 
  /* Find the entry in the TOC */
37
 
  this_entry = psio_tocscan(unit, key);
38
 
 
39
 
  tocentry_size = sizeof(psio_tocentry) - 2*sizeof(psio_tocentry *);
40
 
 
41
 
  if(this_entry == NULL) { /* New TOC entry */
42
 
    if(start.page||start.offset) psio_error(unit,PSIO_ERROR_BLKSTART);
43
 
 
44
 
    dirty = 1; /* set flag for writing the TOC header */
45
 
 
46
 
    this_entry = (psio_tocentry *) malloc(sizeof(psio_tocentry));
47
 
    strcpy(this_entry->key,key);
48
 
    this_entry->next = NULL;
49
 
    this_entry->last = NULL;
50
 
 
51
 
    /* Compute the global address of the new entry */
52
 
    if(!(this_unit->toclen)) { /* First TOC entry */
53
 
      this_entry->sadd.page = 0;
54
 
      this_entry->sadd.offset = sizeof(ULI); /* offset for the toclen value stored first */
55
 
      this_unit->toc = this_entry;
56
 
    }
57
 
    else {  /* Use ending address from last TOC entry */
58
 
      last_entry = psio_toclast(unit);
59
 
      this_entry->sadd = last_entry->eadd;
60
 
      last_entry->next = this_entry;
61
 
      this_entry->last = last_entry;
62
 
    }
63
 
 
64
 
    /* compute important global addresses for the entry */
65
 
    start_toc = this_entry->sadd;
66
 
    start_data = psio_get_address(start_toc, tocentry_size);
67
 
    start_data = psio_get_global_address(start_data, start);
68
 
    end_data = psio_get_address(start_data, size);
69
 
 
70
 
    /* Set the end address for this_entry */
71
 
    this_entry->eadd = end_data;
72
 
 
73
 
    /* Update the unit's TOC stats */
74
 
    this_unit->toclen++;
75
 
    psio_wt_toclen(unit, this_unit->toclen);
76
 
 
77
 
    /* Update end (an entry-relative address) for the caller */
78
 
    *end = psio_get_address(start,size);
79
 
  }
80
 
  else { /* Old TOC entry */
81
 
 
82
 
    /* Compute the global starting page and offset for the block */
83
 
    start_toc = this_entry->sadd;
84
 
    start_data = psio_get_address(start_toc, tocentry_size);
85
 
    start_data = psio_get_global_address(start_data, start);
86
 
 
87
 
    /* Make sure this block doesn't start past the end of the entry */
88
 
    if(start_data.page > this_entry->eadd.page)
89
 
      psio_error(unit,PSIO_ERROR_BLKSTART);
90
 
    else if((start_data.page == this_entry->eadd.page) &&
91
 
            (start_data.offset > this_entry->eadd.offset))
92
 
      psio_error(unit,PSIO_ERROR_BLKSTART);
93
 
 
94
 
    /* Compute the new global ending address for the entry, if necessary */
95
 
    end_data = psio_get_address(start_data, size);
96
 
    if(end_data.page > this_entry->eadd.page) {
97
 
      if(this_entry->next != NULL) {
98
 
        fprintf(stderr, "PSIO_ERROR: Attempt to write into next entry: %d, %s\n", unit, key);
99
 
        psio_error(unit, PSIO_ERROR_BLKEND);
100
 
      }
101
 
      this_entry->eadd = end_data;
102
 
      dirty = 1; /* set flag for writing the TOC header */
103
 
    }
104
 
    else if((end_data.page == this_entry->eadd.page) &&
105
 
            (end_data.offset > this_entry->eadd.offset))
106
 
      {
107
 
        if(this_entry->next != NULL) {
108
 
          fprintf(stderr, "PSIO_ERROR: Attempt to write into next entry: %d, %s\n", unit, key);
109
 
          psio_error(unit, PSIO_ERROR_BLKEND);
110
 
        }
111
 
        this_entry->eadd = end_data;
112
 
        dirty = 1; /* set flag for writing the TOC header */
113
 
      }
114
 
 
115
 
    /* Update end (an entry-relative address) for the caller */
116
 
    *end = psio_get_address(start, size);
117
 
  }
118
 
 
119
 
  if(dirty) /* Need to first write/update the TOC header for this record */
120
 
    psio_rw(unit, (char *) this_entry, start_toc, tocentry_size, 1);
121
 
 
122
 
  /* Now write the actual data to the unit */
123
 
  psio_rw(unit, buffer, start_data, size, 1);
124
 
 
125
 
#ifdef PSIO_STATS
126
 
  psio_writlen[unit] += size;
127
 
#endif
128
 
 
129
 
  return(1);
130
 
}