File: write.c

package info (click to toggle)
acorn-fdisk 3.0.6-13
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,068 kB
  • sloc: ansic: 5,422; makefile: 99
file content (139 lines) | stat: -rw-r--r-- 3,330 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * blkio/read.c
 *
 * Copyright (C) 1998 Russell King
 *
 * The block I/O interface allows an OS-independent method to access devices
 *
 * Write data to device on RiscOS architecture
 */
#include <errno.h>

#include "util/debug.h"
#include "util/error.h"
#include "blkio.h"
#include "filecore.h"

#ifdef RISCOS
#include "!Swi.h"

static u_int write_block(blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
{
  _kernel_oserror *ret;
  u_int swino, sector, nr, limit, res = 0;
  const char *what, *swiname;

  if (blkio->swi_sectorop) {
    swino   = blkio->swi_sectorop;
    sector  = block * (blkio->blocksize >> blkio->disc_record->d.log2secsize);
    nr      = nr_blocks * blkio->blocksize;
    limit   = 0x20000000;
    what    = "sector";
    swiname = "sectorop";
  } else {
    swino   = blkio->swi_discop;
    sector  = block * blkio->blocksize;
    nr      = nr_blocks * blkio->blocksize;
    limit   = 0x20000000 / blkio->blocksize;
    what    = "discaddr";
    swiname = "discop";
  }

  do {
    if (block >= limit) {
      set_error ("Unable to write %s 0x%X above limit 0x%X", what, block, limit);
      break;
    }
    dbg_printf ("-%s: [r1=0x%X r2=0x%X r3=%p r4=0x%X]", swiname,
    		(((unsigned int)blkio->disc_record) << 6)|2,
    		(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);

    ret = swix (swino, rin(r1|r2|r3|r4), (((unsigned int)blkio->disc_record) << 6)|2,
		(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);
    if (ret) {
      set_error ("%s", ret->errmess);
      break;
    }

    res = nr_blocks;
  } while (0);

  return res;
}
#endif

#ifdef UNIX
#include <unistd.h>
#include <syscall.h>

#if _FILE_OFFSET_BITS == 64

#define my_llseek lseek

#else

#undef SYS__llseek
#define SYS__llseek (__NR__llseek - __NR_SYSCALL_BASE)

static inline
_syscall5(int,_llseek,int,fd,u_int,off_high,u_int,off_low,loff_t *,loff,int,whence);

static loff_t my_llseek(int fd, loff_t off, int whence)
{
  u_int off_high, off_low;

  off_high = off >> 32;
  off_low = off & 0xffffffff;

  _llseek(fd, off_high, off_low, &off, whence);

  return off;
}

#endif

static u_int write_block(blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
{
  u_int len, res = 0;
  loff_t loff;

  loff = (loff_t)block * blkio->blocksize;
  len = nr_blocks * blkio->blocksize;

  do {
    if (my_llseek(blkio->fd, loff, SEEK_SET) != loff)
      break;

    if (write(blkio->fd, data, len) != len)
      break;

    res = nr_blocks;
  } while (0);

  return res;
}
#endif

/* Function: u_int blkio_write (blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
 * Purpose : Write `nr_blocks' blocks starting at `block' from the device previously opened
 *           with blkio_open into memory area `data'
 * Params  : blkio     - structure returned by blkio_open
 *         : data      - memory area to write data from
 *         : block     - block number to write
 *         : nr_blocks - number of blocks to write
 * Returns : number of blocks actually written
 */
u_int blkio_write (blkio_t *blkio, const void *data, blk_t block, u_int nr_blocks)
{
  u_int res;

  dbg_printf ("blkio_write(%p 0x%X +0x%X)", data, block, nr_blocks);
  dbg_level_up ();

  res = write_block(blkio, data, block, nr_blocks);

  dbg_level_down ();
  dbg_printf ("ret=%d", res);

  return res;
}