From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean Tourrilhes Date: Sat, 24 Feb 2007 02:36:14 +0000 Subject: PATCH : new key MODEFILE Message-Id: <20070224023614.GA28903@bougret.hpl.hp.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable To: linux-hotplug@vger.kernel.org Hi, I was looking into using the key name RUN and PROGRAM in udev, and I realised that udev attempt to run those programs even if they don't exist. This is a bit wasteful timewise... In shell programming, you typically do something like this : if [ -x /sbin/myprogram ]; then /sbin/myprogram $MYARGS fi My first thought was to hack the RUN and PROGRAM keys to check the existence of the program to be launched (cut to the first whitespace...), but this was a bit hackish. I also thought that a generic facility to test file existence/permisions would be useful. Maybe we want to replicate this kind of construct : if [ -x /sbin/myprogram ] && [ -r /etc/itsconfigfile ]; then /sbin/myprogram $MYARGS fi And you can think of many other interesting ideas along those lines, where you can use dummy files to impact the rules as an alternative to env variables... So, I decided to create a real MODEMASK key in udev. This idea is that this key take a filename and a permission key and verify that the file has such permission. The example above would be : MODEMASK{/sbin/myprogram}=3D"0100", MODEMASK{/etc/itsconfigfile}=3D"0400", = The good news is that it was not so bad, and the changes very localised. I tested it with udev-103, and verified that the patch applies to udev-105. Patch included... Regards, Jean --------------------------------------------------------------------- diff -u -p udev-103-pristine/udev_rules.c udev-103/udev_rules.c --- udev-103-pristine/udev_rules.c 2006-10-20 05:43:35.000000000 -0700 +++ udev-103/udev_rules.c 2007-02-23 18:13:54.000000000 -0800 @@ -609,6 +609,53 @@ static int match_key(const char *key_nam return -1; } =20 +static int match_modemask(const char *key_name, struct udev_rule *rule, st= ruct key *key, const char *key_file) +{ + int match; + char value[PATH_SIZE]; + char filename[PATH_SIZE]; + struct stat stats; + mode_t modemask; + char *eptr; + + if (key->operation !=3D KEY_OP_MATCH && + key->operation !=3D KEY_OP_NOMATCH) + return 0; + + strlcpy(value, rule->buf + key->val_off, sizeof(value)); + + /* Value should be a mode mask - octal integer */ + modemask =3D strtol(value, &eptr, 8); + /* Parsing error =3D no match */ + if(*eptr !=3D '\0') + return -1; + + /* Check if we have an absolute path, otherwise default to /dev */ + if(key_file[0] =3D '/') + snprintf(filename, sizeof(filename), "%s", key_file); + else + snprintf(filename, sizeof(filename), "%s/%s", udev_root, key_file); + filename[sizeof(filename)-1] =3D '\0'; + + /* If file does not exist -> no match */ + if (stat(filename, &stats) !=3D 0) + return -1; + dbg("match %s '%o' <-> '%o'", key_name, modemask, stats.st_mode); + + /* Check if match -> we make a binary AND of the two numbers */ + match =3D stats.st_mode & modemask; + if (match && (key->operation !=3D KEY_OP_NOMATCH)) { + dbg("%s is true (matching value)", key_name); + return 0; + } + if (!match && (key->operation =3D KEY_OP_NOMATCH)) { + dbg("%s is true (non-matching value)", key_name); + return 0; + } + dbg("%s is false", key_name); + return -1; +} + /* match a single rule against a given device and possibly its parent devi= ces */ static int match_rule(struct udevice *udev, struct udev_rule *rule) { @@ -690,6 +737,19 @@ static int match_rule(struct udevice *ud } } =20 + /* Check for matching MODEMASK attribute pairs */ + for (i =3D 0; i < rule->modemask.count; i++) { + struct key_pair *pair =3D &rule->modemask.keys[i]; + + if (pair->key.operation =3D KEY_OP_MATCH || + pair->key.operation =3D KEY_OP_NOMATCH) { + const char *key_name =3D key_pair_name(rule, pair); + + if (match_modemask("MODEMASK", rule, &pair->key, key_name)) + goto nomatch; + } + } + /* walk up the chain of parent devices and find a match */ udev->dev_parent =3D udev->dev; while (1) { diff -u -p udev-103-pristine/udev_rules.h udev-103/udev_rules.h --- udev-103-pristine/udev_rules.h 2006-10-20 05:43:35.000000000 -0700 +++ udev-103/udev_rules.h 2007-02-23 17:37:40.000000000 -0800 @@ -71,6 +71,7 @@ struct udev_rule { struct key_pairs attrs; =20 struct key_pairs env; + struct key_pairs modemask; struct key program; struct key result; struct key import; diff -u -p udev-103-pristine/udev_rules_parse.c udev-103/udev_rules_parse.c --- udev-103-pristine/udev_rules_parse.c 2006-10-20 05:43:35.000000000 -0700 +++ udev-103/udev_rules_parse.c 2007-02-23 17:17:56.000000000 -0800 @@ -400,6 +400,18 @@ static int add_to_rules(struct udev_rule continue; } =20 + if (strncasecmp(key, "MODEMASK{", sizeof("MODEMASK{")-1) =3D 0) { + attr =3D get_key_attribute(key + sizeof("MODEMASK")-1); + if (attr =3D NULL) { + err("error parsing MODEMASK attribute"); + goto invalid; + } + if (add_rule_key_pair(rule, &rule->modemask, operation, attr, value) != =3D 0) + goto invalid; + valid =3D 1; + continue; + } + if (strcasecmp(key, "PROGRAM") =3D 0) { add_rule_key(rule, &rule->program, operation, value); valid =3D 1; ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=3Djoin.php&p=3Dsourceforge&CID=DEVD= EV _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel