File: umdevtrivhd.c

package info (click to toggle)
umview 0.8.2-1.2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 5,472 kB
  • sloc: ansic: 67,309; sh: 11,160; ruby: 914; makefile: 424; python: 141
file content (141 lines) | stat: -rw-r--r-- 3,292 bytes parent folder | download | duplicates (5)
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
141
#include <stdio.h>
#include <string.h>
#include "umdev.h"
#include "stdlib.h"
#include <errno.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <config.h>

#define STD_SIZE 64*1024
#define STD_SECTORSIZE 512
char *testdisk;
char readonly=0;
unsigned long long hd_size;
struct hd_geometry hd_geom;

static int hd_open(char type, dev_t device, struct dev_info *di)
{
	return 0;
}

static int hd_read(char type, dev_t device, char *buf, size_t len, loff_t pos, struct dev_info *di)
{
	loff_t rlen;
	if (pos > hd_size) pos=hd_size;
	if (pos+len <= hd_size) 
		rlen=len;
	else
		rlen=hd_size-pos;
	memcpy(buf,testdisk+pos,rlen);
	return rlen;
}

static int hd_write(char type, dev_t device, const char *buf, size_t len, loff_t pos, struct dev_info *di)
{
	loff_t rlen;
	if (pos > hd_size) pos=hd_size;
	if (pos+len <= hd_size)
		rlen=len;
	else
		rlen=hd_size-pos;
	memcpy(testdisk+pos,buf,rlen);
	return rlen;
}

static int hd_release(char type, dev_t device, struct dev_info *di)
{
	return 0;
}

static loff_t hd_lseek(char type, dev_t device, loff_t offset, int whence, loff_t pos, struct dev_info *di)
{
	loff_t rv;
	switch (whence) {
		case SEEK_SET:
			rv=offset;
			break;
		case SEEK_CUR:
			rv=pos+offset;
			break;
		case SEEK_END:
			rv=hd_size+offset;
			break;
	}
	if (rv<0) rv=0;
	if (rv>hd_size) rv=hd_size;
	return rv;
}

static int hd_init(char type, dev_t device, char *path, unsigned long flags, char *args,struct umdev *devhandle)
{
	hd_size=STD_SIZE;
	hd_geom.start=0;
	if (hd_size == (unsigned int) hd_size) {
		hd_geom.heads=16;
		hd_geom.sectors=16;
		hd_geom.cylinders=(hd_size+(hd_geom.heads*hd_geom.sectors)-1)/(hd_geom.heads*hd_geom.sectors);
	} else {
		hd_geom.heads=128;
		hd_geom.sectors=128;
		hd_geom.cylinders=(hd_size+(hd_geom.heads*hd_geom.sectors)-1)/(hd_geom.heads*hd_geom.sectors);
	}
	hd_size=hd_geom.heads*hd_geom.sectors*hd_geom.cylinders;
	if (!testdisk) {
		testdisk=malloc(hd_size * STD_SECTORSIZE);
	}
	return 0;
}

static int hd_ioctl(char type, dev_t device, int req, void * arg, struct dev_info *di)
{
	switch (req) {
		case BLKROSET: if (*(int *)arg != 0)
										 readonly=1;
									 break;
		case BLKROGET: *(int *)arg = readonly;
									 break;
		case BLKSSZGET: *(int *)arg = STD_SECTORSIZE;
										break;
		case BLKRRPART: break;
		case BLKGETSIZE: *(int *)arg = hd_size;
										 break;
		case BLKGETSIZE64: *(long long *)arg = hd_size;
											 break;
		case HDIO_GETGEO: {
												struct hd_geometry *hdg = arg;
												*hdg=hd_geom;
											}
										 break;
		default: return -EINVAL;
	}
	return 0;
}

static int hd_ioctl_params(char type, dev_t device, int req, struct dev_info *di)
{
	switch (req) {
		case BLKROSET: return (sizeof(int) | IOCTL_R);
		case BLKROGET: return (sizeof(int) | IOCTL_W);
		case BLKSSZGET: return (sizeof(int) | IOCTL_W);
		case BLKRRPART: return 0;
		case BLKGETSIZE: return (sizeof(int) | IOCTL_W);
		case BLKGETSIZE64: return (sizeof(long long) | IOCTL_W);
		case HDIO_GETGEO: return (sizeof(struct hd_geometry) | IOCTL_W);
		default: return 0;
	}
}

struct umdev_operations umdev_ops={
	.open=hd_open,
	.read=hd_read,
	.write=hd_write,
	.release=hd_release,
	.lseek=hd_lseek,
	.init=hd_init,
	.ioctl=hd_ioctl,
	.ioctlparms=hd_ioctl_params,
};