File: read.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 (140 lines) | stat: -rw-r--r-- 3,344 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
140
/*
 * blkio/read.c
 *
 * Copyright (C) 1998 Russell King
 *
 * The block I/O interface allows an OS-independent method to access devices
 *
 * Read data from 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 read_block(blkio_t *blkio, 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    = "sectoraddr";
    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 + nr >= limit) {
      set_error("Unable to access block 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)|1,
    		(blkio->drive << 29) | (sector & 0x1fffffff), data, nr);

    ret = swix(swino, rin(r1|r2|r3|r4), (((unsigned int)blkio->disc_record) << 6)|1,
		(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 read_block(blkio_t *blkio, 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 (read(blkio->fd, data, len) != len)
      break;

    res = nr_blocks;
  } while (0);

  return res;
}
#endif

/* Function: u_int blkio_read (blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
 * Purpose : Read `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 read into
 *         : block     - block number to read
 *         : nr_blocks - number of blocks to read
 * Returns : number of blocks actually read
 */
u_int blkio_read (blkio_t *blkio, void *data, blk_t block, u_int nr_blocks)
{
  u_int res;

  dbg_printf("blkio_read(%p 0x%X +0x%X)", data, block, nr_blocks);
  dbg_level_up();
  dbg_printf("-blocksize=0x%X", blkio->blocksize);

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

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

  return res;
}