mirror of
https://github.com/systemd/systemd.git
synced 2024-12-26 03:22:00 +03:00
[PATCH] add very nice cdsymlinks scripts.
These are from Darren Salt <linux@youmustbejoking.demon.co.uk>
This commit is contained in:
parent
29afcc5f11
commit
79db6912cf
532
extras/cdsymlinks.c
Normal file
532
extras/cdsymlinks.c
Normal file
@ -0,0 +1,532 @@
|
||||
/* cdsymlinks.c
|
||||
*
|
||||
* Map cdrom, cd-r, cdrw, dvd, dvdrw, dvdram to suitable devices.
|
||||
* Prefers cd* for DVD-incapable and cdrom and dvd for read-only devices.
|
||||
* First parameter is the kernel device name.
|
||||
* Second parameter, if present, must be "-d" => output the full mapping.
|
||||
*
|
||||
* Usage:
|
||||
* BUS="ide", KERNEL="hd[a-z]", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
* BUS="scsi", KERNEL="sr[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
* BUS="scsi", KERNEL="scd[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
* (this last one is "just in case")
|
||||
*
|
||||
* (c) 2004 Darren Salt <linux@youmustbejoking.demon.co.uk>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <wordexp.h>
|
||||
|
||||
static const char *progname;
|
||||
|
||||
/* This file provides us with our devices and capabilities information. */
|
||||
#define CDROM_INFO "/proc/sys/dev/cdrom/info"
|
||||
|
||||
/* This file contains our default settings. */
|
||||
#define CONFIGURATION "/etc/udev/cdsymlinks.conf"
|
||||
/* Default output types configuration, in the presence of an empty list */
|
||||
#define OUTPUT_DEFAULT "CD CDRW DVD DVDRW DVDRAM"
|
||||
|
||||
static int debug = 0;
|
||||
|
||||
/* List item */
|
||||
struct list_item_t {
|
||||
struct list_item_t *next;
|
||||
char *data;
|
||||
};
|
||||
|
||||
/* List root. Note offset of list_t->head and list_item_t->next */
|
||||
struct list_t {
|
||||
struct list_item_t *head, *tail;
|
||||
};
|
||||
|
||||
/* Configuration variables */
|
||||
static struct list_t allowed_output = {0};
|
||||
static int numbered_links = 1;
|
||||
|
||||
/* Available devices */
|
||||
static struct list_t Devices = {0};
|
||||
|
||||
/* Devices' capabilities in full (same order as available devices list).
|
||||
* There's no cap_CD; all are assumed able to read CDs.
|
||||
*/
|
||||
static struct list_t cap_DVDRAM = {0}, cap_DVDRW = {0}, cap_DVD = {0},
|
||||
cap_CDRW = {0}, cap_CDR = {0}, cap_CDWMRW = {0},
|
||||
cap_CDMRW = {0};
|
||||
|
||||
/* Device capabilities by name */
|
||||
static struct list_t dev_DVDRAM = {0}, dev_DVDRW = {0}, dev_DVD = {0},
|
||||
dev_CDRW = {0}, dev_CDR = {0}, dev_CDWMRW = {0},
|
||||
dev_CDMRW = {0};
|
||||
#define dev_CD Devices
|
||||
|
||||
|
||||
/*
|
||||
* Some library-like bits first...
|
||||
*/
|
||||
|
||||
static void
|
||||
errexit (const char *reason)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: %s\n", progname, reason, strerror (errno));
|
||||
exit (2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
msgexit (const char *reason)
|
||||
{
|
||||
fprintf (stderr, "%s: %s\n", progname, reason);
|
||||
exit (2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
errwarn (const char *reason)
|
||||
{
|
||||
fprintf (stderr, "%s: warning: %s: %s\n", progname, reason, strerror (errno));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
msgwarn (const char *reason)
|
||||
{
|
||||
fprintf (stderr, "%s: warning: %s\n", progname, reason);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
xmalloc (size_t size)
|
||||
{
|
||||
void *mem = malloc (size);
|
||||
if (size && !mem)
|
||||
msgexit ("malloc failed");
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
xstrdup (const char *text)
|
||||
{
|
||||
char *mem = xmalloc (strlen (text) + 1);
|
||||
return strcpy (mem, text);
|
||||
}
|
||||
|
||||
|
||||
/* Append a string to a list. The string is duplicated. */
|
||||
static void
|
||||
list_append (struct list_t *list, const char *data)
|
||||
{
|
||||
struct list_item_t *node = xmalloc (sizeof (struct list_item_t));
|
||||
node->next = NULL;
|
||||
if (list->tail)
|
||||
list->tail->next = node;
|
||||
list->tail = node;
|
||||
if (!list->head)
|
||||
list->head = node;
|
||||
node->data = xstrdup (data);
|
||||
}
|
||||
|
||||
|
||||
/* Prepend a string to a list. The string is duplicated. */
|
||||
static void
|
||||
list_prepend (struct list_t *list, const char *data)
|
||||
{
|
||||
struct list_item_t *node = xmalloc (sizeof (struct list_item_t));
|
||||
node->next = list->head;
|
||||
list->head = node;
|
||||
if (!list->tail)
|
||||
list->tail = node;
|
||||
node->data = xstrdup (data);
|
||||
}
|
||||
|
||||
|
||||
/* Delete a lists's contents, freeing claimed memory */
|
||||
static void
|
||||
list_delete (struct list_t *list)
|
||||
{
|
||||
struct list_item_t *node = list->head;
|
||||
while (node)
|
||||
{
|
||||
struct list_item_t *n = node;
|
||||
node = node->next;
|
||||
free (n->data);
|
||||
free (n);
|
||||
}
|
||||
list->tail = list->head = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Print out a list on one line, each item space-prefixed, no LF */
|
||||
static void
|
||||
list_print (const struct list_t *list, FILE *stream)
|
||||
{
|
||||
const struct list_item_t *node = (const struct list_item_t *)list;
|
||||
while ((node = node->next) != NULL)
|
||||
fprintf (stream, " %s", node->data);
|
||||
}
|
||||
|
||||
|
||||
/* Return the nth item in a list (count from 0)
|
||||
* If there aren't enough items in the list, return the requested default
|
||||
*/
|
||||
static const struct list_item_t *
|
||||
list_nth (const struct list_t *list, size_t nth)
|
||||
{
|
||||
const struct list_item_t *node = list->head;
|
||||
while (nth && node)
|
||||
{
|
||||
node = node->next;
|
||||
--nth;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/* Return the first matching item in a list, or NULL */
|
||||
static const struct list_item_t *
|
||||
list_search (const struct list_t *list, const char *data)
|
||||
{
|
||||
const struct list_item_t *node = list->head;
|
||||
while (node)
|
||||
{
|
||||
if (!strcmp (node->data, data))
|
||||
return node;
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Split up a string on whitespace & assign the resulting tokens to a list.
|
||||
* Ignore everything up until the first colon (if present).
|
||||
*/
|
||||
static void
|
||||
list_assign_split (struct list_t *list, char *text)
|
||||
{
|
||||
char *token = strchr (text, ':');
|
||||
token = strtok (token ? token + 1 : text, " \t");
|
||||
while (token)
|
||||
{
|
||||
list_prepend (list, token);
|
||||
token = strtok (0, " \t\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Gather the default settings. */
|
||||
static void
|
||||
read_defaults (void)
|
||||
{
|
||||
FILE *conf = fopen (CONFIGURATION, "r");
|
||||
if (!conf)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
errwarn ("error accessing configuration");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *text = NULL;
|
||||
size_t textlen;
|
||||
while (getline (&text, &textlen, conf) != -1)
|
||||
{
|
||||
wordexp_t p = {0};
|
||||
int len = strlen (text);
|
||||
if (len && text[len - 1] == '\n')
|
||||
text[--len] = '\0';
|
||||
if (len && text[len - 1] == '\r')
|
||||
text[--len] = '\0';
|
||||
if (!len)
|
||||
continue;
|
||||
char *token = text + strspn (text, " \t");
|
||||
if (!*token || *token == '#')
|
||||
continue;
|
||||
switch (len = wordexp (text, &p, 0))
|
||||
{
|
||||
case WRDE_NOSPACE:
|
||||
msgexit ("malloc failed");
|
||||
case 0:
|
||||
if (p.we_wordc == 1)
|
||||
{
|
||||
if (!strncmp (p.we_wordv[0], "OUTPUT=", 7))
|
||||
{
|
||||
list_delete (&allowed_output);
|
||||
list_assign_split (&allowed_output, p.we_wordv[0] + 7);
|
||||
}
|
||||
else if (!strncmp (p.we_wordv[0], "NUMBERED_LINKS=", 14))
|
||||
numbered_links = atoi (p.we_wordv[0] + 14);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
msgwarn ("syntax error in configuration file");
|
||||
}
|
||||
wordfree (&p);
|
||||
}
|
||||
if (!feof (conf))
|
||||
errwarn ("error accessing configuration");
|
||||
if (fclose (conf))
|
||||
errwarn ("error accessing configuration");
|
||||
free (text);
|
||||
}
|
||||
if (!allowed_output.head)
|
||||
{
|
||||
char *dflt = strdup (OUTPUT_DEFAULT);
|
||||
list_assign_split (&allowed_output, dflt);
|
||||
free (dflt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* From information supplied by the kernel:
|
||||
* + get the names of the available devices
|
||||
* + populate our capability lists
|
||||
* Order is significant: device item N maps to each capability item N.
|
||||
*/
|
||||
static void
|
||||
populate_capability_lists (void)
|
||||
{
|
||||
FILE *info = fopen (CDROM_INFO, "r");
|
||||
if (!info)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
exit (0);
|
||||
errexit ("error accessing CD/DVD info");
|
||||
}
|
||||
|
||||
char *text = 0;
|
||||
size_t textlen = 0;
|
||||
|
||||
while (getline (&text, &textlen, info) != -1)
|
||||
{
|
||||
if (!strncasecmp (text, "drive name", 10))
|
||||
list_assign_split (&Devices, text);
|
||||
else if (!strncasecmp (text, "Can write DVD-RAM", 17))
|
||||
list_assign_split (&cap_DVDRAM, text);
|
||||
else if (!strncasecmp (text, "Can write DVD-R", 15))
|
||||
list_assign_split (&cap_DVDRW, text);
|
||||
else if (!strncasecmp (text, "Can read DVD", 12))
|
||||
list_assign_split (&cap_DVD, text);
|
||||
else if (!strncasecmp (text, "Can write CD-RW", 15))
|
||||
list_assign_split (&cap_CDRW, text);
|
||||
else if (!strncasecmp (text, "Can write CD-R", 14))
|
||||
list_assign_split (&cap_CDR, text);
|
||||
else if (!strncasecmp (text, "Can read MRW", 14))
|
||||
list_assign_split (&cap_CDMRW, text);
|
||||
else if (!strncasecmp (text, "Can write MRW", 14))
|
||||
list_assign_split (&cap_CDWMRW, text);
|
||||
}
|
||||
if (!feof (info))
|
||||
errexit ("error accessing CD/DVD info");
|
||||
fclose (info);
|
||||
free (text);
|
||||
}
|
||||
|
||||
|
||||
/* Write out the links of type LINK which should be created for device NAME,
|
||||
* taking into account existing links and the capability list for type LINK.
|
||||
*/
|
||||
static void
|
||||
do_output (const char *name, const char *link, const struct list_t *dev)
|
||||
{
|
||||
const struct list_item_t *i = (const struct list_item_t *)dev;
|
||||
if (!i->next)
|
||||
return;
|
||||
|
||||
errno = 0;
|
||||
|
||||
size_t link_len = strlen (link);
|
||||
DIR *dir = opendir ("/dev");
|
||||
if (!dir)
|
||||
errexit ("error reading /dev");
|
||||
|
||||
struct list_t devls = {0}; /* symlinks whose name matches LINK */
|
||||
struct list_t devlinks = {0}; /* those symlinks' targets */
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir (dir)) != NULL)
|
||||
{
|
||||
if (strncmp (entry->d_name, link, link_len))
|
||||
continue; /* wrong name: ignore it */
|
||||
|
||||
/* The rest of the name must be null or consist entirely of digits. */
|
||||
const char *p = entry->d_name + link_len - 1;
|
||||
while (*++p)
|
||||
if (!isdigit (*p))
|
||||
break;
|
||||
if (*p)
|
||||
continue; /* wrong format - ignore */
|
||||
|
||||
/* Assume that it's a symlink and try to read its target. */
|
||||
char buf[sizeof (entry->d_name)];
|
||||
int r = readlink (entry->d_name, buf, sizeof (buf) - 1);
|
||||
if (r < 0)
|
||||
{
|
||||
if (errno == EINVAL)
|
||||
continue; /* not a symlink - ignore */
|
||||
errexit ("error reading link in /dev");
|
||||
}
|
||||
/* We have the name and the target, so update our lists. */
|
||||
buf[r] = 0;
|
||||
list_append (&devls, entry->d_name);
|
||||
list_append (&devlinks, buf);
|
||||
}
|
||||
if (errno)
|
||||
errexit ("error reading /dev");
|
||||
if (closedir (dir))
|
||||
errexit ("error closing /dev");
|
||||
|
||||
/* Now we write our output... */
|
||||
size_t count = 0;
|
||||
while ((i = i->next) != NULL)
|
||||
{
|
||||
int isdev = !strcmp (name, i->data); /* current dev == target dev? */
|
||||
int present = 0;
|
||||
size_t li = -1;
|
||||
const struct list_item_t *l = (const struct list_item_t *)&devlinks;
|
||||
|
||||
/* First, we look for existing symlinks to the target device. */
|
||||
while (++li, (l = l->next) != NULL)
|
||||
{
|
||||
if (strcmp (l->data, i->data))
|
||||
continue;
|
||||
/* Existing symlink found - don't output a new one.
|
||||
* If ISDEV, we output the name of the existing symlink.
|
||||
*/
|
||||
present = 1;
|
||||
if (isdev)
|
||||
printf (" %s", list_nth (&devls, li)->data);
|
||||
}
|
||||
|
||||
/* If we found no existing symlinks for the target device... */
|
||||
if (!present)
|
||||
{
|
||||
char buf[256];
|
||||
snprintf (buf, sizeof (buf), count ? "%s%d" : "%s", link, count);
|
||||
/* Find the next available (not present) symlink name.
|
||||
* We always need to do this for reasons of output consistency: if a
|
||||
* symlink is created by udev as a result of use of this program, we
|
||||
* DON'T want different output!
|
||||
*/
|
||||
while (list_search (&devls, buf))
|
||||
snprintf (buf, sizeof (buf), "%s%d", link, ++count);
|
||||
/* If ISDEV, output it. */
|
||||
if (isdev && (numbered_links || count == 0))
|
||||
printf (" %s", buf);
|
||||
/* If the link isn't in our "existing links" list, add it and increment
|
||||
* our counter.
|
||||
*/
|
||||
if (!list_search (&devls, buf))
|
||||
{
|
||||
list_append (&devls, buf);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_delete (&devls);
|
||||
list_delete (&devlinks);
|
||||
}
|
||||
|
||||
|
||||
/* Populate a device list from a capabilities list. */
|
||||
static void
|
||||
populate_device_list (struct list_t *out, const struct list_t *caps)
|
||||
{
|
||||
const struct list_item_t *cap, *dev;
|
||||
cap = (const struct list_item_t *)caps;
|
||||
dev = (const struct list_item_t *)&Devices;
|
||||
while ((cap = cap->next) != NULL && (dev = dev->next) != NULL)
|
||||
if (cap->data[0] != '0')
|
||||
list_append (out, dev->data);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
progname = argv[0];
|
||||
debug = argc > 2 && !strcmp (argv[2], "-d");
|
||||
|
||||
if (argc < 2 || argc > 2 + debug)
|
||||
msgexit ("usage: cdsymlinks DEVICE [-d]");
|
||||
|
||||
if (chdir ("/dev"))
|
||||
errexit ("can't chdir /dev");
|
||||
|
||||
read_defaults ();
|
||||
populate_capability_lists ();
|
||||
|
||||
/* Construct the device lists from the capability lists. */
|
||||
populate_device_list (&dev_DVDRAM, &cap_DVDRAM);
|
||||
populate_device_list (&dev_DVDRW, &cap_DVDRW);
|
||||
populate_device_list (&dev_DVD, &cap_DVD);
|
||||
populate_device_list (&dev_CDRW, &cap_CDRW);
|
||||
populate_device_list (&dev_CDR, &cap_CDR);
|
||||
populate_device_list (&dev_CDWMRW, &cap_CDWMRW);
|
||||
populate_device_list (&dev_CDMRW, &cap_CDMRW);
|
||||
/* (All devices can read CDs.) */
|
||||
|
||||
if (debug)
|
||||
{
|
||||
#define printdev(DEV) \
|
||||
printf ("%-7s:", #DEV); \
|
||||
list_print (&cap_##DEV, stdout); \
|
||||
list_print (&dev_##DEV, stdout); \
|
||||
puts ("");
|
||||
|
||||
printf ("Devices:");
|
||||
const struct list_item_t *item = (const struct list_item_t *)&Devices;
|
||||
while ((item = item->next) != NULL)
|
||||
printf (" %s", item->data);
|
||||
puts ("");
|
||||
|
||||
printdev (DVDRAM);
|
||||
printdev (DVDRW);
|
||||
printdev (DVD);
|
||||
printdev (CDRW);
|
||||
printdev (CDR);
|
||||
printdev (CDWMRW);
|
||||
printdev (CDMRW);
|
||||
|
||||
printf ("CDROM : (all)");
|
||||
item = (const struct list_item_t *)&dev_CD;
|
||||
while ((item = item->next) != NULL)
|
||||
printf (" %s", item->data);
|
||||
puts ("");
|
||||
}
|
||||
|
||||
/* Write the symlink names. */
|
||||
if (list_search (&allowed_output, "CD"))
|
||||
do_output (argv[1], "cdrom", &dev_CD);
|
||||
if (list_search (&allowed_output, "CDR"))
|
||||
do_output (argv[1], "cd-r", &dev_CDR);
|
||||
if (list_search (&allowed_output, "CDRW"))
|
||||
do_output (argv[1], "cdrw", &dev_CDRW);
|
||||
if (list_search (&allowed_output, "DVD"))
|
||||
do_output (argv[1], "dvd", &dev_DVD);
|
||||
if (list_search (&allowed_output, "DVDRW"))
|
||||
do_output (argv[1], "dvdrw", &dev_DVDRW);
|
||||
if (list_search (&allowed_output, "DVDRAM"))
|
||||
do_output (argv[1], "dvdram", &dev_DVDRAM);
|
||||
if (list_search (&allowed_output, "CDMRW"))
|
||||
do_output (argv[1], "cdmrw", &dev_CDMRW);
|
||||
if (list_search (&allowed_output, "CDWMRW"))
|
||||
do_output (argv[1], "cdwmrw", &dev_CDWMRW);
|
||||
puts ("");
|
||||
|
||||
return 0;
|
||||
}
|
12
extras/cdsymlinks.conf
Normal file
12
extras/cdsymlinks.conf
Normal file
@ -0,0 +1,12 @@
|
||||
# Configuration file for cdsymlinks
|
||||
|
||||
# Output links for these types of devices.
|
||||
# Allowed keywords are CD, CDR, CDRW, DVD, DVDRW, DVDRAM, CDMRW, CDWMRW.
|
||||
# Other words are accepted but ignored.
|
||||
#OUTPUT="CD CDRW DVD DVDRW DVDRAM"
|
||||
|
||||
# Whether to output numbered links.
|
||||
# 1 = output 'cdrom1', 'dvd1' etc. for other devices
|
||||
# 0 = don't output 'cdrom1', 'dvd1' etc.
|
||||
# We always output 'cdrom', 'dvd' etc. for the best-match devices.
|
||||
#NUMBERED_LINKS=1
|
184
extras/cdsymlinks.sh
Normal file
184
extras/cdsymlinks.sh
Normal file
@ -0,0 +1,184 @@
|
||||
#! /bin/sh -e
|
||||
#
|
||||
# Map cdrom, cdm, cdmrw, cd-r, cdrw, dvd, dvdrw, dvdram to suitable devices.
|
||||
# Prefers cd* for DVD-incapable and cdrom and dvd for read-only devices.
|
||||
# First parameter is the kernel device name.
|
||||
# Second parameter, if present, must be "-d" => output the full mapping.
|
||||
#
|
||||
# Usage:
|
||||
# BUS="ide", KERNEL="hd[a-z]", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
# BUS="scsi", KERNEL="sr[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
# BUS="scsi", KERNEL="scd[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
|
||||
# (this last one is "just in case")
|
||||
#
|
||||
# (c) 2004 Darren Salt <linux@youmustbejoking.demon.co.uk>
|
||||
|
||||
test -e /proc/sys/dev/cdrom/info || exit 0
|
||||
|
||||
# Defaults; it's better that you alter them in /etc/udev/cdsymlinks.conf
|
||||
OUTPUT='CD CDRW DVD DVDRW DVDRAM'
|
||||
NUMBERED_LINKS=1
|
||||
|
||||
test -e /etc/udev/cdsymlinks.conf && . /etc/udev/cdsymlinks.conf
|
||||
|
||||
DEBUG=''
|
||||
test "$2" = '-d' && DEBUG=1
|
||||
|
||||
|
||||
# Array emulation. 'setArray FOO a b c' gives FOO=3 FOO_1=a FOO_2=b FOO_3=c
|
||||
setArray () {
|
||||
local _ARRAY=$1
|
||||
local _INDEX=0
|
||||
shift
|
||||
while test $# -ne 0; do
|
||||
eval ${_ARRAY}_$_INDEX="$1"
|
||||
_INDEX=$(($_INDEX+1))
|
||||
shift
|
||||
done
|
||||
eval $_ARRAY=$_INDEX
|
||||
}
|
||||
|
||||
ix () { eval echo -n \$$1_$2; }
|
||||
ixs () { eval $1_$2="$3"; }
|
||||
|
||||
# Args: variable, value
|
||||
# Returns true if value is not in variable (a whitespace-separated list)
|
||||
notin () {
|
||||
test "$2" = '' && return 0
|
||||
local i
|
||||
for i in `eval echo '$'$1`; do
|
||||
test "$i" != "$2" || return 1
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Scan /proc/sys/dev/cdrom/info for details on the present devices
|
||||
setArray DEVICES `sed -re '/^drive name:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray DVDRAMs `sed -re '/^Can write DVD-RAM:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray DVDRWs `sed -re '/^Can write DVD-R:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray DVDs `sed -re '/^Can read DVD:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray CDRWs `sed -re '/^Can write CD-RW:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray CDRs `sed -re '/^Can write CD-R:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray CDMRWs `sed -re '/^Can write MRW:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
setArray CDMs `sed -re '/^Can read MRW:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
|
||||
|
||||
# How many devices do we have?
|
||||
NumDevs=$(($DEVICES-1))
|
||||
Count=''
|
||||
i=-1
|
||||
while test $i -ne $NumDevs; do
|
||||
i=$(($i+1));
|
||||
Count="$i${Count:+ }$Count";
|
||||
done
|
||||
|
||||
# Fill in any missing capabilities information (assume not capable)
|
||||
for i in $Count; do
|
||||
test "`ix DVDRAMs $i`" != '' || ixs DVDRAMs $i 0
|
||||
test "`ix DVDRWs $i`" != '' || ixs DVDRWs $i 0
|
||||
test "`ix DVDs $i`" != '' || ixs DVDs $i 0
|
||||
test "`ix CDRWs $i`" != '' || ixs CDRWs $i 0
|
||||
test "`ix CDRs $i`" != '' || ixs CDRs $i 0
|
||||
test "`ix CDMRWs $i`" != '' || ixs CDMRWs $i 0
|
||||
test "`ix CDMs $i`" != '' || ixs CDMs $i 0
|
||||
done
|
||||
|
||||
DVDRAM=''
|
||||
DVDRW=''
|
||||
DVD=''
|
||||
CDRW=''
|
||||
CDR=''
|
||||
CDMRW=''
|
||||
CDM=''
|
||||
CD=''
|
||||
|
||||
# Calculate symlink->device mappings.
|
||||
# We need to be careful about how we assign mappings because we want
|
||||
# read-only devices to have /dev/cdrom and /dev/dvd.
|
||||
# Hot-plugged CD/DVD devices may well cause this scheme some problems.
|
||||
for i in $Count; do
|
||||
test "`ix DVDRAMs $i`" = 1 && DVDRAM="$DVDRAM `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix DVDRWs $i`" = 1 && DVDRW="$DVDRW `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix DVDs $i`" = 1 && DVD="$DVD `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix CDRWs $i`" = 1 && CDRW="$CDRW `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix CDRs $i`" = 1 && CDR="$CDR `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix CDMRWs $i`" = 1 && CDMRW="$CDMRW `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
test "`ix CDMs $i`" = 1 && CDM="$CDM `ix DEVICES $i`"
|
||||
done
|
||||
for i in $Count; do
|
||||
CD="$CD `ix DEVICES $i`"
|
||||
done
|
||||
|
||||
# Debug output
|
||||
if test "$DEBUG" = 1; then
|
||||
echo 'Devices:' `for i in $Count; do ix DEVICES $i; echo -n \ ; done`
|
||||
echo 'DVDRAM :' `for i in $Count; do ix DVDRAMs $i; echo -n \ ; done` $DVDRAM
|
||||
echo 'DVDRW :' `for i in $Count; do ix DVDRWs $i; echo -n \ ; done` $DVDRW
|
||||
echo 'DVD :' `for i in $Count; do ix DVDs $i; echo -n \ ; done` $DVD
|
||||
echo 'CDRW :' `for i in $Count; do ix CDRWs $i; echo -n \ ; done` $CDRW
|
||||
echo 'CD-R :' `for i in $Count; do ix CDRs $i; echo -n \ ; done` $CDR
|
||||
echo 'CDMRW :' `for i in $Count; do ix CDMRWs $i; echo -n \ ; done` $CDMRW
|
||||
echo 'CDM :' `for i in $Count; do ix CDMs $i; echo -n \ ; done` $CDM
|
||||
echo 'CDROM : (all)' $CD
|
||||
fi
|
||||
|
||||
# Prepare symlink names output
|
||||
output () {
|
||||
test "`eval echo '$'$3`" = '' && return
|
||||
local i
|
||||
local COUNT=''
|
||||
local DEVLS="`ls -dl \"/dev/$2\" \"/dev/$2\"[0-9]* 2>/dev/null`"
|
||||
local PRESENT="`echo "$DEVLS" |
|
||||
sed -re 's!^.* /dev/('$2'[[:digit:]]*) -> [^[:space:]]+$!\1!'`"
|
||||
for i in `eval echo '$'$3`; do
|
||||
# First, we look for existing symlinks to the target device.
|
||||
local DEVPRESENT="`echo "$DEVLS" |
|
||||
sed -re 's!^.* /dev/('$2'[[:digit:]]*) -> '$i'$!\1!; t X; d; :X'`"
|
||||
if test "$DEVPRESENT" != ""; then
|
||||
# Existing symlinks found - don't output a new one.
|
||||
# If the target dev ($1) is the current dev ($i), we output their names.
|
||||
test "$1" = "$i" && echo " $DEVPRESENT" | sed -e 'N; $ s/\n/ /'
|
||||
else
|
||||
# If we found no existing symlinks for the target device...
|
||||
# Find the next available (not present) symlink name.
|
||||
# We always need to do this for reasons of output consistency: if a
|
||||
# symlink is created by udev as a result of use of this program, we
|
||||
# DON'T want different output!
|
||||
until notin PRESENT "$2$COUNT"; do
|
||||
COUNT=$(($COUNT+1))
|
||||
done
|
||||
# If the target dev ($1) is the current dev ($i), we output its name.
|
||||
if test $(($NUMBERED_LINKS)) -ne 0 || test "$COUNT" -eq 0; then
|
||||
test "$i" = "$1" && echo -n " $2$COUNT"
|
||||
fi
|
||||
# If the link isn't in our "existing links" list, add it and increment
|
||||
# our counter.
|
||||
if test ! -e "/dev/$2$COUNT"; then
|
||||
PRESENT="$PRESENT\n$2$COUNT"
|
||||
COUNT=$(($COUNT+1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# And output it
|
||||
notin OUTPUT CD || echo -n "`output "$1" cdrom CD`"
|
||||
notin OUTPUT CDMRW || echo -n "`output "$1" cdmrw CDM`"
|
||||
notin OUTPUT CDWMRW || echo -n "`output "$1" cdwmrw CDMRW`"
|
||||
notin OUTPUT CDR || echo -n "`output "$1" cd-r CDR`"
|
||||
notin OUTPUT CDRW || echo -n "`output "$1" cdrw CDRW`"
|
||||
notin OUTPUT DVD || echo -n "`output "$1" dvd DVD`"
|
||||
notin OUTPUT DVDRW || echo -n "`output "$1" dvdrw DVDRW`"
|
||||
notin OUTPUT DVDRAM || echo -n "`output "$1" dvdram DVDRAM`"
|
||||
echo
|
Loading…
Reference in New Issue
Block a user