[PATCH] cleanup mult field string handling

Here I try to cleanup our various multifield iteration over the strings.
Inspired by our nice list.h we now have a macro to iterate over the string
and process the parts of it:
It makes the code more readable and we don't change the string while we
process it like the former strsep() does.

Example:

  foreach_strpart(dev->symlink, " ", pos, len) {
  	if (strncmp(&dev->symlink[pos], find_name, len) != 0)
  		continue;

  	...
  }

For the callout part selector %c{2} we separate now not only by space but
also newline and return characters, cause some programs may give multiline
values back. A possible RESULT match must contain wildcards for these
characters.

Also a bug in the recent udevinfo symlink query feature is fixed.
This commit is contained in:
kay.sievers@vrfy.org 2004-03-03 18:16:35 -08:00 committed by Greg KH
parent 88ed4bbe56
commit 9fe3f9a938
6 changed files with 85 additions and 95 deletions

View file

@ -214,14 +214,12 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize,
struct sysfs_device *sysfs_device) struct sysfs_device *sysfs_device)
{ {
char temp[NAME_SIZE]; char temp[NAME_SIZE];
char temp1[NAME_SIZE];
char *tail; char *tail;
char *pos; char *pos;
char *pos2;
char *pos3;
char *attr; char *attr;
int len; int len;
int i; int i;
int spos, slen;
char c; char c;
struct sysfs_attribute *tmpattr; struct sysfs_attribute *tmpattr;
@ -278,20 +276,17 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize,
if (attr != NULL) if (attr != NULL)
i = atoi(attr); i = atoi(attr);
if (i > 0) { if (i > 0) {
strfieldcpy(temp1, udev->program_result); foreach_strpart(udev->program_result, " \n\r", spos, slen) {
pos2 = temp1;
while (i) {
i--; i--;
pos3 = strsep(&pos2, " "); if (i == 0)
if (pos3 == NULL) {
dbg("requested part of result string not found");
break; break;
}
} }
if (pos3) { if (i > 0) {
strnfieldcat(string, pos3, maxsize); dbg("requested part of result string not found");
dbg("substitute part of result string '%s'", pos3); break;
} }
strnfieldcat(string, udev->program_result + spos, slen+1);
dbg("substitute part of result string '%s'", pos);
} else { } else {
strnfieldcat(string, udev->program_result, maxsize); strnfieldcat(string, udev->program_result, maxsize);
dbg("substitute result string '%s'", udev->program_result); dbg("substitute result string '%s'", udev->program_result);

View file

@ -186,16 +186,16 @@ static int unlink_entry(char *filename)
static int create_node(struct udevice *dev, int fake) static int create_node(struct udevice *dev, int fake)
{ {
char filename[255]; char filename[NAME_SIZE];
char linktarget[255]; char linkname[NAME_SIZE];
char partitionname[255]; char linktarget[NAME_SIZE];
char *linkname; char partitionname[NAME_SIZE];
char *symlinks;
int retval = 0; int retval = 0;
uid_t uid = 0; uid_t uid = 0;
gid_t gid = 0; gid_t gid = 0;
int i; int i;
int tail; int tail;
int pos, len;
strfieldcpy(filename, udev_root); strfieldcpy(filename, udev_root);
strfieldcat(filename, dev->name); strfieldcat(filename, dev->name);
@ -279,47 +279,41 @@ static int create_node(struct udevice *dev, int fake)
selinux_add_node(filename); selinux_add_node(filename);
/* create symlink if requested */ /* create symlink if requested */
if (dev->symlink[0] != '\0') { foreach_strpart(dev->symlink, " ", pos, len) {
symlinks = dev->symlink; strnfieldcpy(linkname, dev->symlink + pos, len+1);
while (1) { strfieldcpy(filename, udev_root);
linkname = strsep(&symlinks, " "); strfieldcat(filename, linkname);
if (linkname == NULL || linkname[0] == '\0') dbg("symlink '%s' to node '%s' requested", filename, dev->name);
break; if (!fake)
if (strrchr(linkname, '/'))
create_path(filename);
strfieldcpy(filename, udev_root); /* optimize relative link */
strfieldcat(filename, linkname); linktarget[0] = '\0';
dbg("symlink '%s' to node '%s' requested", filename, dev->name); i = 0;
if (!fake) tail = 0;
if (strrchr(linkname, '/')) while ((dev->name[i] == linkname[i]) && dev->name[i]) {
create_path(filename); if (dev->name[i] == '/')
tail = i+1;
i++;
}
while (linkname[i] != '\0') {
if (linkname[i] == '/')
strfieldcat(linktarget, "../");
i++;
}
/* optimize relative link */ strfieldcat(linktarget, &dev->name[tail]);
linktarget[0] = '\0';
i = 0;
tail = 0;
while ((dev->name[i] == linkname[i]) && dev->name[i]) {
if (dev->name[i] == '/')
tail = i+1;
i++;
}
while (linkname[i] != '\0') {
if (linkname[i] == '/')
strfieldcat(linktarget, "../");
i++;
}
strfieldcat(linktarget, &dev->name[tail]); if (!fake)
unlink_entry(filename);
if (!fake) dbg("symlink(%s, %s)", linktarget, filename);
unlink_entry(filename); if (!fake) {
retval = symlink(linktarget, filename);
dbg("symlink(%s, %s)", linktarget, filename); if (retval != 0)
if (!fake) { dbg("symlink(%s, %s) failed with error '%s'",
retval = symlink(linktarget, filename); linktarget, filename, strerror(errno));
if (retval != 0)
dbg("symlink(%s, %s) failed with error '%s'",
linktarget, filename, strerror(errno));
}
} }
} }

View file

@ -67,12 +67,12 @@ static int delete_path(char *path)
static int delete_node(struct udevice *dev) static int delete_node(struct udevice *dev)
{ {
char filename[255]; char filename[NAME_SIZE];
char partitionname[255]; char linkname[NAME_SIZE];
char *symlinks; char partitionname[NAME_SIZE];
char *linkname;
int retval; int retval;
int i; int i;
int pos, len;
strfieldcpy(filename, udev_root); strfieldcpy(filename, udev_root);
strfieldcat(filename, dev->name); strfieldcat(filename, dev->name);
@ -101,28 +101,22 @@ static int delete_node(struct udevice *dev)
if (strchr(dev->name, '/')) if (strchr(dev->name, '/'))
delete_path(filename); delete_path(filename);
if (dev->symlink[0] != '\0') { foreach_strpart(dev->symlink, " ", pos, len) {
symlinks = dev->symlink; strnfieldcpy(linkname, dev->symlink + pos, len+1);
while (1) { strfieldcpy(filename, udev_root);
linkname = strsep(&symlinks, " "); strfieldcat(filename, linkname);
if (linkname == NULL)
break;
strfieldcpy(filename, udev_root); dbg("unlinking symlink '%s'", filename);
strfieldcat(filename, linkname); retval = unlink(filename);
if (errno == ENOENT)
dbg("unlinking symlink '%s'", filename); retval = 0;
retval = unlink(filename); if (retval) {
if (errno == ENOENT) dbg("unlink(%s) failed with error '%s'",
retval = 0; filename, strerror(errno));
if (retval) { return retval;
dbg("unlink(%s) failed with error '%s'", }
filename, strerror(errno)); if (strchr(dev->symlink, '/')) {
return retval; delete_path(filename);
}
if (strchr(dev->symlink, '/')) {
delete_path(filename);
}
} }
} }

6
udev.h
View file

@ -97,6 +97,12 @@ do { \
snprintf((to) + strlen(to), maxsize - strlen(to)-1, "%u", i); \ snprintf((to) + strlen(to), maxsize - strlen(to)-1, "%u", i); \
} while (0) } while (0)
#define foreach_strpart(str, separator, pos, len) \
for(pos = 0, len = strcspn(str, separator); \
(pos) < strlen(str); \
pos = pos + (len) + 1, len = strcspn((str) + pos, separator)) \
if (len > 0)
static inline char *get_action(void) static inline char *get_action(void)
{ {
char *action; char *action;

View file

@ -179,7 +179,8 @@ static int find_found;
static int find_device_by_name(char *path, struct udevice *dev) static int find_device_by_name(char *path, struct udevice *dev)
{ {
int l, i, j; int pos, len;
if (strncmp(dev->name, find_name, sizeof(dev->name)) == 0) { if (strncmp(dev->name, find_name, sizeof(dev->name)) == 0) {
memcpy(find_dev, dev, sizeof(struct udevice)); memcpy(find_dev, dev, sizeof(struct udevice));
strnfieldcpy(find_path, path, NAME_SIZE); strnfieldcpy(find_path, path, NAME_SIZE);
@ -188,20 +189,18 @@ static int find_device_by_name(char *path, struct udevice *dev)
return 1; return 1;
} }
/* look for matching symlink*/ /* look for matching symlink*/
l = strlen(dev->symlink); foreach_strpart(dev->symlink, " ", pos, len) {
if (!l) if (strncmp(&dev->symlink[pos], find_name, len) != 0)
return 0; continue;
i = j = 0;
do { if (len != strlen(find_name))
j = strcspn(&dev->symlink[i], " "); continue;
if (j && strncmp(&dev->symlink[i], find_name, j) == 0) {
memcpy(find_dev, dev, sizeof(struct udevice)); memcpy(find_dev, dev, sizeof(struct udevice));
strnfieldcpy(find_path, path, NAME_SIZE); strnfieldcpy(find_path, path, NAME_SIZE);
find_found = 1; find_found = 1;
return 1; return 1;
} }
i = i + j + 1;
} while (i < l);
return 0; return 0;
} }

View file

@ -35,6 +35,8 @@ Specify the sysfs path of the device to query.
.TP .TP
.BI \-n " name" .BI \-n " name"
Specify the name of the node or the symlink for the device to query. Specify the name of the node or the symlink for the device to query.
Partition names generated with the NAME{all_partitons} option can not be
queried, the main device must be used instead.
.TP .TP
.B \-a .B \-a
Print all Print all