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;
}
|