File: paride.c

package info (click to toggle)
resmgr 1.0-2sarge2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 308 kB
  • ctags: 313
  • sloc: ansic: 3,165; sh: 556; makefile: 109
file content (133 lines) | stat: -rw-r--r-- 2,858 bytes parent folder | download
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
/*
 * Handling of generic paride devices - this is needed to find the
 * /dev/pg* device corresponding to e.g. a CD writer on Linux.
 *
 * Copyright (C) 2002, Olaf Kirch <okir@lst.de>
 */

#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
#include "resmgrd.h"

typedef unsigned int paride_id_t;

typedef struct res_paride_name res_paride_name_t;
struct res_paride_name {
	res_name_t	base;
	paride_id_t	id;
};

static res_name_t *	res_paride_parse_name(const char *);
static const char * 	res_paride_print_name(res_name_t *);
static void	 	res_paride_free_name(res_name_t *);
static int		res_paride_match(res_name_t *, res_device_t *);
static int		res_paride_open(res_name_t *, int);
static int		get_paride_id(const char *, paride_id_t *);

#define paride_id_match(namep, idp) \
	((namep)->paride_id.id == ((idp)->id & ((namep)->paride_id.mask)))

res_family_t		res_family_paride = {
	"paride",
	DEV_FLAGS_PARIDE,	/* devices must have this flag set
				 * otherwise we will not allow access
				 * to the raw device */
	res_paride_parse_name,
	res_paride_print_name,
	res_paride_free_name,
	res_paride_match,
	res_paride_open
};

/*
 * PARIDE devices can be named
 * 	paride:/dev/foobar
 * 	paride:minor
 * 	paride:minor:/dev/foobar
 */
res_name_t *
res_paride_parse_name(const char *name)
{
	res_paride_name_t *sp;
	paride_id_t	paride_id;

	if (name[0] == '/') {
		if (get_paride_id(name, &paride_id) < 0)
			return 0;
	} else {
		paride_id = strtoul(name, (char **) name, 0);
		if (*name != ':' && *name)
			return NULL;
	}

	sp = (res_paride_name_t *) calloc(1, sizeof(*sp));
	sp->base.ops = &res_family_paride;
	sp->id = paride_id;
	return (res_name_t *) sp;
}

void
res_paride_free_name(res_name_t *np)
{
	free(np);
}

const char *
res_paride_print_name(res_name_t *np)
{
	static char	namebuf[64];
	u_int32_t	id;

	id = ((res_paride_name_t *) np)->id;
	snprintf(namebuf, sizeof(namebuf), "paride:%u:/dev/pg%u", id, id);
	return namebuf;
}

int
res_paride_match(res_name_t *np, res_device_t *dev)
{
	res_paride_name_t *sp = (res_paride_name_t *) np;
	paride_id_t	dev_id;

	if (get_paride_id(dev->name, &dev_id) < 0)
		return 0;

	return sp->id == dev_id;
}

int
res_paride_open(res_name_t *np, int flags)
{
	res_paride_name_t *sp = (res_paride_name_t *) np;
	char		pg_name[64];
	int		fd = -1;

	snprintf(pg_name, sizeof(pg_name), "/dev/pg%u", sp->id);
	if ((np = res_name_parse(pg_name)) != NULL)
		fd = res_name_open(np, flags);
	res_name_free(np);
	return fd;
}

int
get_paride_id(const char *name, paride_id_t *idp)
{
	struct stat	stb;

	if (stat(name, &stb) < 0)
		return -1;
	if (!S_ISCHR(stb.st_mode))
		return -1;
	switch (major(stb.st_rdev)) {
	case 46: /* paride CD */
	case 97: /* paride generic */
		*idp = minor(stb.st_rdev);
		return 0;
	}
	return -1;
}