From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ananth N Mavinakayanahalli Date: Fri, 02 Jan 2004 05:03:40 +0000 Subject: [PATCH] libsysfs update for refresh + namedev.c changes Message-Id: <20040102054453.GA25764@in.ibm.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: linux-hotplug@vger.kernel.org Hello Greg, Please find inlined a (_BIG_) patch against udev-012 which contains updates to libsysfs (pre-release) for refresh and also changes to namedev.c to take advantage of it. Tested with a usb-storage device with a LABEL rule for both normal and klibc builds. I still owe you the updated libsysfs.txt. Thanks, Ananth -- Ananth Narayan Linux Technology Center, IBM Software Lab, INDIA diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/libsysfs.h udev-012/libsysfs/libsysfs.h --- temp/udev-012/libsysfs/libsysfs.h 2003-12-18 23:07:51.000000000 +0530 +++ udev-012/libsysfs/libsysfs.h 2004-01-02 09:40:20.000000000 +0530 @@ -62,18 +62,20 @@ }; struct sysfs_directory { + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + + /* Private: for internal use only */ struct dlist *subdirs; struct dlist *links; struct dlist *attributes; - unsigned char name[SYSFS_NAME_LEN]; - unsigned char path[SYSFS_PATH_MAX]; }; struct sysfs_driver { unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* for internal use only */ + /* Private: for internal use only */ struct dlist *devices; struct sysfs_directory *directory; }; @@ -85,7 +87,7 @@ unsigned char driver_name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* for internal use only */ + /* Private: for internal use only */ struct sysfs_device *parent; struct dlist *children; struct sysfs_directory *directory; @@ -95,7 +97,7 @@ unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* for internal use only */ + /* Private: for internal use only */ struct dlist *devices; struct sysfs_directory *directory; }; @@ -104,7 +106,7 @@ unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* internal use only */ + /* Private: for internal use only */ struct dlist *drivers; struct dlist *devices; struct sysfs_directory *directory; @@ -115,7 +117,7 @@ unsigned char classname[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* for internal use only */ + /* Private: for internal use only */ struct sysfs_class_device *parent; struct sysfs_device *sysdevice; /* NULL if virtual */ struct sysfs_driver *driver; /* NULL if not implemented */ @@ -126,7 +128,7 @@ unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; - /* for internal use only */ + /* Private: for internal use only */ struct dlist *devices; struct sysfs_directory *directory; }; @@ -138,8 +140,8 @@ /* * Function Prototypes */ -extern int sysfs_trailing_slash(unsigned char *path); extern int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len); +extern int sysfs_remove_trailing_slash(unsigned char *path); extern int sysfs_get_name_from_path(const unsigned char *path, unsigned char *name, size_t len); extern int sysfs_path_is_dir(const unsigned char *path); @@ -161,7 +163,9 @@ const unsigned char *new_value, size_t len); extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr, const unsigned char * name); -extern int sysfs_refresh_attributes(struct dlist *attrlist); +extern int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir); +extern int sysfs_refresh_dir_links(struct sysfs_directory *sysdir); +extern int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir); extern void sysfs_close_directory(struct sysfs_directory *sysdir); extern struct sysfs_directory *sysfs_open_directory(const unsigned char *path); extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir); @@ -179,6 +183,9 @@ (struct sysfs_directory *dir, unsigned char *linkname); extern struct sysfs_attribute *sysfs_get_directory_attribute (struct sysfs_directory *dir, unsigned char *attrname); +extern struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir); +extern struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir); +extern struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir); /* sysfs driver access */ extern void sysfs_close_driver(struct sysfs_driver *driver); @@ -189,9 +196,12 @@ (struct sysfs_driver *drv, const unsigned char *name); extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver); extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver); +extern struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver); extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver); extern struct sysfs_device *sysfs_get_driver_device (struct sysfs_driver *driver, const unsigned char *name); +extern struct dlist *sysfs_refresh_driver_attributes + (struct sysfs_driver *driver); extern struct sysfs_attribute *sysfs_open_driver_attr(const unsigned char *bus, const unsigned char *drv, const unsigned char *attrib); @@ -208,6 +218,8 @@ extern struct sysfs_attribute *sysfs_get_device_attr (struct sysfs_device *dev, const unsigned char *name); extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device); +extern struct dlist *sysfs_refresh_device_attributes + (struct sysfs_device *device); extern struct sysfs_attribute *sysfs_open_device_attr(const unsigned char *bus, const unsigned char *bus_id, const unsigned char *attrib); @@ -221,6 +233,7 @@ extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus); extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus); extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus); +extern struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus); extern struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, unsigned char *attrname); extern struct sysfs_device *sysfs_open_bus_device(unsigned char *busname, @@ -247,6 +260,8 @@ (struct sysfs_class *class, unsigned char *name); extern struct dlist *sysfs_get_classdev_attributes (struct sysfs_class_device *cdev); +extern struct dlist *sysfs_refresh_classdev_attributes + (struct sysfs_class_device *cdev); extern struct sysfs_attribute *sysfs_get_classdev_attr (struct sysfs_class_device *clsdev, const unsigned char *name); extern struct sysfs_attribute *sysfs_open_classdev_attr diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_bus.c udev-012/libsysfs/sysfs_bus.c --- temp/udev-012/libsysfs/sysfs_bus.c 2003-12-18 23:46:16.000000000 +0530 +++ udev-012/libsysfs/sysfs_bus.c 2004-01-02 09:40:07.000000000 +0530 @@ -209,9 +209,7 @@ return NULL; } - if (sysfs_trailing_slash(buspath) = 0) - strcat(buspath, "/"); - + strcat(buspath, "/"); strcat(buspath, SYSFS_BUS_NAME); strcat(buspath, "/"); strcat(buspath, name); @@ -226,6 +224,11 @@ } strcpy(bus->name, name); strcpy(bus->path, buspath); + if ((sysfs_remove_trailing_slash(bus->path)) != 0) { + dprintf("Incorrect path to bus %s\n", bus->path); + sysfs_close_bus(bus); + return NULL; + } return bus; } @@ -296,21 +299,38 @@ if (bus->directory->attributes = NULL) { if ((sysfs_read_dir_attributes(bus->directory)) != 0) return NULL; - } else { - if ((sysfs_path_is_dir(bus->path)) != 0) { - dprintf("Bus at %s no longer exists\n", bus->path); - return NULL; - } - if ((sysfs_refresh_attributes - (bus->directory->attributes)) != 0) { - dprintf("Error refreshing bus attributes\n"); - return NULL; - } } return bus->directory->attributes; } /** + * sysfs_refresh_bus_attributes: refreshes the bus's list of attributes + * @bus: sysfs_bus whose attributes to refresh + * + * NOTE: Upon return, prior references to sysfs_attributes for this bus + * _may_ not be valid + * + * Returns list of attributes on success and NULL on failure + */ +struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus) +{ + if (bus = NULL) { + errno = EINVAL; + return NULL; + } + + if (bus->directory = NULL) + return (sysfs_get_bus_attributes(bus)); + + if ((sysfs_refresh_dir_attributes(bus->directory)) != 0) { + dprintf("Error refreshing bus attributes\n"); + return NULL; + } + + return (bus->directory->attributes); +} + +/** * sysfs_get_bus_attribute: gets a specific bus attribute, if buses had * attributes. * @bus: bus to retrieve attribute from @@ -357,8 +377,7 @@ return NULL; } - if (sysfs_trailing_slash(path) = 0) - strcat(path, "/"); + strcat(path, "/"); strcat(path, SYSFS_BUS_NAME); strcat(path, "/"); strcat(path, busname); diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_class.c udev-012/libsysfs/sysfs_class.c --- temp/udev-012/libsysfs/sysfs_class.c 2003-12-18 23:57:38.000000000 +0530 +++ udev-012/libsysfs/sysfs_class.c 2004-01-02 09:51:15.000000000 +0530 @@ -160,6 +160,11 @@ } strcpy(cdev->path, path); + if ((sysfs_remove_trailing_slash(cdev->path)) != 0) { + dprintf("Invalid path to class device %s\n", cdev->path); + sysfs_close_class_device(cdev); + return NULL; + } set_classdev_classname(cdev); return cdev; @@ -179,6 +184,10 @@ errno = EINVAL; return NULL; } + + if (cls->devices != NULL) + return cls->devices; + if (cls->directory = NULL) { cls->directory = sysfs_open_directory(cls->path); if (cls->directory = NULL) @@ -226,16 +235,16 @@ dprintf("Sysfs not supported on this system\n"); return NULL; } - if (sysfs_trailing_slash(classpath) = 0) - strcat(classpath, "/"); /* * We shall now treat "block" also as a class. Hence, check here * if "name" is "block" and proceed accordingly */ if (strcmp(name, SYSFS_BLOCK_NAME) = 0) { + strcat(classpath, "/"); strcat(classpath, SYSFS_BLOCK_NAME); } else { + strcat(classpath, "/"); strcat(classpath, SYSFS_CLASS_NAME); strcat(classpath, "/"); strcat(classpath, name); @@ -252,6 +261,11 @@ } strcpy(cls->name, name); strcpy(cls->path, classpath); + if ((sysfs_remove_trailing_slash(cls->path)) != 0) { + dprintf("Invalid path to class device %s\n", cls->path); + sysfs_close_class(cls); + return NULL; + } return cls; } @@ -264,8 +278,6 @@ struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *class, unsigned char *name) { - struct dlist *devlist = NULL; - if (class = NULL || name = NULL) { errno = EINVAL; return NULL; @@ -273,7 +285,7 @@ if (class->devices = NULL) { class->devices = sysfs_get_class_devices(class); - if (devlist = NULL) + if (class->devices = NULL) return NULL; } return (struct sysfs_class_device *)dlist_find_custom(class->devices, @@ -291,14 +303,21 @@ (struct sysfs_class_device *clsdev) { struct sysfs_link *devlink = NULL; + unsigned char devpath[SYSFS_PATH_MAX]; if (clsdev = NULL) { errno = EINVAL; return NULL; } - - if (clsdev->sysdevice != NULL) - return (clsdev->sysdevice); + strcpy(devpath, clsdev->path); + strcat(devpath, "/device"); + if ((sysfs_path_is_link(devpath)) != 0) { + if (clsdev->sysdevice != NULL) { + sysfs_close_device(clsdev->sysdevice); + clsdev->sysdevice = NULL; + } + return NULL; + } if (clsdev->directory = NULL) { clsdev->directory = sysfs_open_directory(clsdev->path); @@ -306,8 +325,24 @@ return NULL; } devlink = sysfs_get_directory_link(clsdev->directory, "device"); - if (devlink = NULL) + if (devlink = NULL) { + if (clsdev->sysdevice != NULL) { + dprintf("Device link no longer exists\n"); + sysfs_close_device(clsdev->sysdevice); + clsdev->sysdevice = NULL; + } return NULL; + } + + if (clsdev->sysdevice != NULL) { + if (!strncmp(devlink->target, clsdev->sysdevice->path, + SYSFS_PATH_MAX)) + /* sysdevice hasn't changed */ + return (clsdev->sysdevice); + else + /* come here only if the device link for has changed */ + sysfs_close_device(clsdev->sysdevice); + } clsdev->sysdevice = sysfs_open_device_path(devlink->target); if (clsdev->sysdevice = NULL) @@ -329,31 +364,56 @@ (struct sysfs_class_device *clsdev) { struct sysfs_link *drvlink = NULL; + unsigned char drvpath[SYSFS_PATH_MAX]; if (clsdev = NULL) { errno = EINVAL; return NULL; } - - if (clsdev->driver != NULL) - return (clsdev->driver); - + strcpy(drvpath, clsdev->path); + strcat(drvpath, "/driver"); + if ((sysfs_path_is_link(drvpath)) != 0) { + if (clsdev->driver != NULL) { + sysfs_close_driver(clsdev->driver); + clsdev->driver = NULL; + } + return NULL; + } + if (clsdev->directory = NULL) { clsdev->directory = sysfs_open_directory(clsdev->path); if (clsdev->directory = NULL) return NULL; } drvlink = sysfs_get_directory_link(clsdev->directory, "driver"); - if (drvlink != NULL) { - clsdev->driver = sysfs_open_driver_path(drvlink->target); - if (clsdev->driver = NULL) - return NULL; - + if (drvlink = NULL) { + if (clsdev->driver != NULL) { + dprintf("Driver link no longer exists\n"); + sysfs_close_driver(clsdev->driver); + clsdev->driver = NULL; + } + return NULL; + } + if (clsdev->driver != NULL) { + if (!strncmp(drvlink->target, clsdev->driver->path, + SYSFS_PATH_MAX)) + /* driver hasn't changed */ + return (clsdev->driver); + else + /* come here only if the device link for has changed */ + sysfs_close_driver(clsdev->driver); } + + clsdev->driver = sysfs_open_driver_path(drvlink->target); + if (clsdev->driver = NULL) + return NULL; + if (clsdev->sysdevice != NULL) + strcpy(clsdev->sysdevice->driver_name, clsdev->driver->name); + return (clsdev->driver); } - -/* + +/** * get_blockdev_parent: Get the parent class device for a "block" subsystem * device if present * @clsdev: block subsystem class device whose parent needs to be found @@ -361,48 +421,28 @@ */ static int get_blockdev_parent(struct sysfs_class_device *clsdev) { - unsigned char parent_path[SYSFS_PATH_MAX], value[256], *c = NULL; - - memset(parent_path, 0, SYSFS_PATH_MAX); - strcpy(parent_path, clsdev->path); + unsigned char parent_path[SYSFS_PATH_MAX], *c = NULL; + strcpy(parent_path, clsdev->path); c = strstr(parent_path, SYSFS_BLOCK_NAME); - if (c = NULL) { - dprintf("Class device %s does not belong to BLOCK subsystem", - clsdev->name); - return 1; - } - c += strlen(SYSFS_BLOCK_NAME); if (*c = '/') c++; else goto errout; - - /* validate whether the given class device is a partition or not */ - if ((strncmp(c, clsdev->name, strlen(clsdev->name))) = 0) { - dprintf("%s not a partition\n", clsdev->name); - return 1; - } - c = strchr(c, '/'); - if (c = NULL) - goto errout; - *c = '\0'; - - /* Now validate if the parent has the "dev" attribute */ - memset(value, 0, 256); - strcat(parent_path, "/dev"); - if ((sysfs_read_attribute_value(parent_path, value, 256)) != 0) { - dprintf("Block device %s does not have a parent\n", - clsdev->name); - return 1; - } - - c = strrchr(parent_path, '/'); + + /* validate whether the given class device is a partition or not */ + if ((strncmp(c, clsdev->name, strlen(clsdev->name))) = 0) { + dprintf("%s not a partition\n", clsdev->name); + return 1; + } + + c = strchr(c, '/'); if (c = NULL) goto errout; *c = '\0'; + clsdev->parent = sysfs_open_class_device_path(parent_path); if (clsdev->parent = NULL) { dprintf("Error opening the parent class device at %s\n", @@ -467,13 +507,11 @@ dprintf("Error getting sysfs mount path\n"); return -1; } - - if (sysfs_trailing_slash(path) = 0) - strcat(path, "/"); - if (strcmp(classname, SYSFS_BLOCK_NAME) = 0) { + strcat(path, "/"); strcat(path, SYSFS_BLOCK_NAME); } else { + strcat(path, "/"); strcat(path, SYSFS_CLASS_NAME); strcat(path, "/"); strcat(path, classname); @@ -537,27 +575,41 @@ return NULL; } if (cdev->directory->attributes = NULL) { - if ((sysfs_read_dir_attributes(cdev->directory)) != 0) { - dprintf("Error reading attributes for directory %s\n", - cdev->directory->path); + if ((sysfs_read_dir_attributes(cdev->directory)) != 0) return NULL; - } - } else { - if ((sysfs_path_is_dir(cdev->path)) != 0) { - dprintf("Class device at %s no longer exists\n", - cdev->path); - return NULL; - } - if ((sysfs_refresh_attributes - (cdev->directory->attributes)) != 0) { - dprintf("Error refreshing classdev attributes\n"); - return NULL; - } } return (cdev->directory->attributes); } /** + * sysfs_refresh_clsassdev_attributes: refreshes the driver's list of attributes + * @clsdev: sysfs_class_device whose attributes to refresh + * + * NOTE: Upon return, prior references to sysfs_attributes for this classdev + * _may_ not be valid + * + * Returns list of attributes on success and NULL on failure + */ +struct dlist *sysfs_refresh_classdev_attributes + (struct sysfs_class_device *clsdev) +{ + if (clsdev = NULL) { + errno = EINVAL; + return NULL; + } + + if (clsdev->directory = NULL) + return (sysfs_get_classdev_attributes(clsdev)); + + if ((sysfs_refresh_dir_attributes(clsdev->directory)) != 0) { + dprintf("Error refreshing class_device attributes\n"); + return NULL; + } + + return (clsdev->directory->attributes); +} + +/** * sysfs_get_classdev_attr: searches class device's attributes by name * @clsdev: class device to look through * @name: attribute name to get @@ -597,15 +649,10 @@ struct sysfs_directory) { if ((sysfs_path_is_dir(sdir->path)) != 0) continue; - if (sdir->attributes = NULL) { - cur = sysfs_get_directory_attribute(sdir, - (unsigned char *)name); - } else { - if ((sysfs_refresh_attributes - (sdir->attributes)) = 0) - cur = sysfs_get_directory_attribute(sdir, + cur = sysfs_get_directory_attribute(sdir, (unsigned char *)name); - } + if (cur = NULL) + continue; } } return cur; diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_device.c udev-012/libsysfs/sysfs_device.c --- temp/udev-012/libsysfs/sysfs_device.c 2003-12-19 00:53:02.000000000 +0530 +++ udev-012/libsysfs/sysfs_device.c 2004-01-02 09:40:07.000000000 +0530 @@ -197,6 +197,11 @@ return NULL; } strcpy(dev->path, path); + if ((sysfs_remove_trailing_slash(dev->path)) != 0) { + dprintf("Invalid path to device %s\n", dev->path); + sysfs_close_device(dev); + return NULL; + } /* * The "name" attribute no longer exists... return the device's * sysfs representation instead, in the "dev->name" field, which @@ -334,8 +339,7 @@ return NULL; } - if (sysfs_trailing_slash(rootpath) = 0) - strcat(rootpath, "/"); + strcat(rootpath, "/"); strcat(rootpath, SYSFS_DEVICES_NAME); strcat(rootpath, "/"); strcat(rootpath, name); @@ -352,6 +356,11 @@ } strcpy(root->name, name); strcpy(root->path, rootpath); + if ((sysfs_remove_trailing_slash(root->path)) != 0) { + dprintf("Invalid path to root device %s\n", root->path); + sysfs_close_root_device(root); + return NULL; + } return root; } @@ -373,21 +382,38 @@ if (device->directory->attributes = NULL) { if ((sysfs_read_dir_attributes(device->directory)) != 0) return NULL; - } else { - if ((sysfs_path_is_dir(device->path)) != 0) { - dprintf("Device at %s no longer exists", device->path); - return NULL; - } - if ((sysfs_refresh_attributes - (device->directory->attributes)) != 0) { - dprintf("Error refreshing device attributes\n"); - return NULL; - } } return (device->directory->attributes); } /** + * sysfs_refresh_device_attributes: refreshes the device's list of attributes + * @device: sysfs_device whose attributes to refresh + * + * NOTE: Upon return, prior references to sysfs_attributes for this device + * _may_ not be valid + * + * Returns list of attributes on success and NULL on failure + */ +struct dlist *sysfs_refresh_device_attributes(struct sysfs_device *device) +{ + if (device = NULL) { + errno = EINVAL; + return NULL; + } + + if (device->directory = NULL) + return (sysfs_get_device_attributes(device)); + + if ((sysfs_refresh_dir_attributes(device->directory)) != 0) { + dprintf("Error refreshing device attributes\n"); + return NULL; + } + + return (device->directory->attributes); +} + +/** * sysfs_get_device_attr: searches dev's attributes by name * @dev: device to look through * @name: attribute name to get @@ -396,22 +422,19 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, const unsigned char *name) { - struct sysfs_attribute *cur = NULL; struct dlist *attrlist = NULL; if (dev = NULL || name = NULL) { errno = EINVAL; return NULL; } - + attrlist = sysfs_get_device_attributes(dev); if (attrlist = NULL) return NULL; - cur = sysfs_get_directory_attribute(dev->directory, - (unsigned char *)name); - - return cur; + return sysfs_get_directory_attribute(dev->directory, + (unsigned char *)name); } /** @@ -437,8 +460,7 @@ dprintf ("Sysfs not supported on this system\n"); return -1; } - if (sysfs_trailing_slash(bus_path) = 0) - strcat(bus_path, "/"); + strcat(bus_path, "/"); strcat(bus_path, SYSFS_BUS_NAME); strcat(bus_path, "/"); strcat(bus_path, bus); diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_dir.c udev-012/libsysfs/sysfs_dir.c --- temp/udev-012/libsysfs/sysfs_dir.c 2003-12-22 12:23:47.000000000 +0530 +++ udev-012/libsysfs/sysfs_dir.c 2004-01-02 09:40:07.000000000 +0530 @@ -195,7 +195,7 @@ return -1; } if ((strncmp(sysattr->value, new_value, sysattr->len)) = 0) { - dprintf("Attribute %s already has the requested value %s\n", + dprintf("Attr %s already has the requested value %s\n", sysattr->name, new_value); return 0; } @@ -274,7 +274,7 @@ return -1; } #ifdef __KLIBC__ - pgsize = 0x1000; + pgsize = 0x1000; #else pgsize = sysconf(_SC_PAGESIZE); #endif @@ -468,6 +468,13 @@ errno = EINVAL; return NULL; } + + if (sysfs_path_is_dir(path) != 0) { + dprintf("Invalid path directory %s\n", path); + errno = EINVAL; + return NULL; + } + sdir = alloc_directory(); if (sdir = NULL) { dprintf("Error allocating directory %s\n", path); @@ -514,39 +521,6 @@ } /** - * sysfs_refresh_attributes: Refresh attributes list - * @attrlist: list of attributes to refresh - * Returns 0 on success, 1 on failure - */ -int sysfs_refresh_attributes(struct dlist *attrlist) -{ - struct sysfs_attribute *attr = NULL; - - if (attrlist = NULL) { - errno = EINVAL; - return 1; - } - dlist_for_each_data(attrlist, attr, struct sysfs_attribute) { - if (attr->method & SYSFS_METHOD_SHOW) { - if ((sysfs_read_attribute(attr)) != 0) { - dprintf("Error reading attribute %s\n", - attr->path); - if ((sysfs_path_is_file(attr->path)) != 0) { - dprintf("Attr %s no longer exists\n", - attr->name); - } - } - } else { - if ((sysfs_path_is_file(attr->path)) != 0) { - dprintf("Attr %s no longer exists\n", - attr->name); - } - } - } - return 0; -} - -/** * add_attribute: open and add attribute at path to given directory * @sysdir: directory to add attribute to * @path: path to attribute @@ -633,7 +607,6 @@ { DIR *dir = NULL; struct dirent *dirent = NULL; - struct stat astats; unsigned char file_path[SYSFS_PATH_MAX]; int retval = 0; @@ -655,11 +628,7 @@ strncpy(file_path, sysdir->path, SYSFS_PATH_MAX); strcat(file_path, "/"); strcat(file_path, dirent->d_name); - if ((lstat(file_path, &astats)) != 0) { - dprintf("stat failed\n"); - continue; - } - if (S_ISREG(astats.st_mode)) + if ((sysfs_path_is_file(file_path)) = 0) retval = add_attribute(sysdir, file_path); } closedir(dir); @@ -675,7 +644,6 @@ { DIR *dir = NULL; struct dirent *dirent = NULL; - struct stat astats; unsigned char file_path[SYSFS_PATH_MAX]; int retval = 0; @@ -697,11 +665,7 @@ strncpy(file_path, sysdir->path, SYSFS_PATH_MAX); strcat(file_path, "/"); strcat(file_path, dirent->d_name); - if ((lstat(file_path, &astats)) != 0) { - dprintf("stat failed\n"); - continue; - } - if (S_ISLNK(astats.st_mode)) { + if ((sysfs_path_is_link(file_path)) = 0) { retval = add_link(sysdir, file_path); if (retval != 0) break; @@ -720,7 +684,6 @@ { DIR *dir = NULL; struct dirent *dirent = NULL; - struct stat astats; unsigned char file_path[SYSFS_PATH_MAX]; int retval = 0; @@ -742,11 +705,7 @@ strncpy(file_path, sysdir->path, SYSFS_PATH_MAX); strcat(file_path, "/"); strcat(file_path, dirent->d_name); - if ((lstat(file_path, &astats)) != 0) { - dprintf("stat failed\n"); - continue; - } - if (S_ISDIR(astats.st_mode)) + if ((sysfs_path_is_dir(file_path)) = 0) retval = add_subdirectory(sysdir, file_path); } closedir(dir); @@ -802,6 +761,90 @@ } /** + * sysfs_refresh_dir_attributes: Refresh attributes list + * @sysdir: directory whose list of attributes to refresh + * Returns 0 on success, 1 on failure + */ +int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir) +{ + if (sysdir = NULL) { + errno = EINVAL; + return 1; + } + if ((sysfs_path_is_dir(sysdir->path)) != 0) { + dprintf("Invalid path to directory %s\n", sysdir->path); + errno = EINVAL; + return 1; + } + if (sysdir->attributes != NULL) { + dlist_destroy(sysdir->attributes); + sysdir->attributes = NULL; + } + if ((sysfs_read_dir_attributes(sysdir)) != 0) { + dprintf("Error refreshing attributes for directory %s\n", + sysdir->path); + return 1; + } + return 0; +} + +/** + * sysfs_refresh_dir_links: Refresh links list + * @sysdir: directory whose list of links to refresh + * Returns 0 on success, 1 on failure + */ +int sysfs_refresh_dir_links(struct sysfs_directory *sysdir) +{ + if (sysdir = NULL) { + errno = EINVAL; + return 1; + } + if ((sysfs_path_is_dir(sysdir->path)) != 0) { + dprintf("Invalid path to directory %s\n", sysdir->path); + errno = EINVAL; + return 1; + } + if (sysdir->links != NULL) { + dlist_destroy(sysdir->links); + sysdir->links = NULL; + } + if ((sysfs_read_dir_links(sysdir)) != 0) { + dprintf("Error refreshing links for directory %s\n", + sysdir->path); + return 1; + } + return 0; +} + +/** + * sysfs_refresh_dir_subdirs: Refresh subdirs list + * @sysdir: directory whose list of subdirs to refresh + * Returns 0 on success, 1 on failure + */ +int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir) +{ + if (sysdir = NULL) { + errno = EINVAL; + return 1; + } + if ((sysfs_path_is_dir(sysdir->path)) != 0) { + dprintf("Invalid path to directory %s\n", sysdir->path); + errno = EINVAL; + return 1; + } + if (sysdir->subdirs != NULL) { + dlist_destroy(sysdir->subdirs); + sysdir->subdirs = NULL; + } + if ((sysfs_read_dir_subdirs(sysdir)) != 0) { + dprintf("Error refreshing subdirs for directory %s\n", + sysdir->path); + return 1; + } + return 0; +} + +/** * sysfs_get_directory_attribute: retrieves attribute attrname from current * directory only * @dir: directory to retrieve attribute from @@ -826,19 +869,25 @@ attr = (struct sysfs_attribute *)dlist_find_custom (dir->attributes, attrname, dir_attribute_name_equal); - if (attr = NULL) { + if (attr != NULL) { + if ((sysfs_read_attribute(attr)) != 0) { + dprintf("Error reading attribute %s\n", attr->name); + return NULL; + } + } else { memset(new_path, 0, SYSFS_PATH_MAX); strcpy(new_path, dir->path); strcat(new_path, "/"); strcat(new_path, attrname); if ((sysfs_path_is_file(new_path)) = 0) { - if ((add_attribute(dir, new_path)) = 0) { + if ((add_attribute(dir, new_path)) = 0) { attr = (struct sysfs_attribute *) - dlist_find_custom(dir->attributes, + dlist_find_custom(dir->attributes, attrname, dir_attribute_name_equal); } } } + return attr; } @@ -855,9 +904,13 @@ errno = EINVAL; return NULL; } - if (dir->links = NULL) + if (dir->links = NULL) { if ((sysfs_read_dir_links(dir) != 0) || (dir->links = NULL)) return NULL; + } else { + if ((sysfs_refresh_dir_links(dir)) != 0) + return NULL; + } return (struct sysfs_link *)dlist_find_custom(dir->links, linkname, dir_link_name_equal); @@ -940,3 +993,63 @@ } return NULL; } + +/** + * sysfs_get_dir_attributes: returns dlist of directory attributes + * @dir: directory to retrieve attributes from + * returns dlist of attributes or NULL + */ +struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir) +{ + if (dir = NULL) { + errno = EINVAL; + return NULL; + } + + if (dir->attributes = NULL) { + if (sysfs_read_dir_attributes(dir) != 0) + return NULL; + } + + return (dir->attributes); +} + +/** + * sysfs_get_dir_links: returns dlist of directory links + * @dir: directory to return links for + * returns dlist of links or NULL + */ +struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir) +{ + if (dir = NULL) { + errno = EINVAL; + return NULL; + } + + if (dir->links = NULL) { + if (sysfs_read_dir_links(dir) != 0) + return NULL; + } + + return (dir->links); +} + +/** + * sysfs_get_dir_subdirs: returns dlist of directory subdirectories + * @dir: directory to return subdirs for + * returns dlist of subdirs or NULL + */ +struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir) +{ + if (dir = NULL) { + errno = EINVAL; + return NULL; + } + + if (dir->subdirs = NULL) { + if (sysfs_read_dir_subdirs(dir) != 0) + return NULL; + } + + return (dir->subdirs); +} diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_driver.c udev-012/libsysfs/sysfs_driver.c --- temp/udev-012/libsysfs/sysfs_driver.c 2003-12-19 00:16:14.000000000 +0530 +++ udev-012/libsysfs/sysfs_driver.c 2004-01-02 09:40:07.000000000 +0530 @@ -103,6 +103,11 @@ return NULL; } strcpy(driver->path, path); + if ((sysfs_remove_trailing_slash(driver->path)) != 0) { + dprintf("Invalid path to driver %s\n", driver->path); + sysfs_close_driver(driver); + return NULL; + } return driver; } @@ -125,26 +130,38 @@ return NULL; } if (driver->directory->attributes = NULL) { - if ((sysfs_read_dir_attributes(driver->directory)) != 0) { - dprintf("Error reading driver attributes\n"); - return NULL; - } - } else { - if ((sysfs_path_is_dir(driver->path)) != 0) { - dprintf("Driver at %s no longer exists\n", - driver->path); - return NULL; - } - if ((sysfs_refresh_attributes - (driver->directory->attributes)) != 0) { - dprintf("Error refreshing driver attributes\n"); + if ((sysfs_read_dir_attributes(driver->directory)) != 0) return NULL; - } } return(driver->directory->attributes); } /** + * sysfs_refresh_driver_attributes: refreshes the driver's list of attributes + * @driver: sysfs_driver whose attributes to refresh + * + * NOTE: Upon return, prior references to sysfs_attributes for this driver + * _may_ not be valid + * + * Returns list of attributes on success and NULL on failure + */ +struct dlist *sysfs_refresh_driver_attributes(struct sysfs_driver *driver) +{ + if (driver = NULL) { + errno = EINVAL; + return NULL; + } + if (driver->directory = NULL) + return (sysfs_get_driver_attributes(driver)); + + if ((sysfs_refresh_dir_attributes(driver->directory)) != 0) { + dprintf("Error refreshing driver attributes\n"); + return NULL; + } + return (driver->directory->attributes); +} + +/** * sysfs_get_driver_attr: searches driver's attributes by name * @drv: driver to look through * @name: attribute name to get @@ -153,7 +170,6 @@ struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv, const unsigned char *name) { - struct sysfs_attribute *cur = NULL; struct dlist *attrlist = NULL; if (drv = NULL) { @@ -163,9 +179,10 @@ attrlist = sysfs_get_driver_attributes(drv); if (attrlist != NULL) - cur = sysfs_get_directory_attribute(drv->directory, + return NULL; + + return sysfs_get_directory_attribute(drv->directory, (unsigned char *)name); - return cur; } /** @@ -234,6 +251,38 @@ } /** + * sysfs_refresh_driver_devices: Refreshes drivers list of devices + * @driver: sysfs_driver whose devices list needs to be refreshed + * + * NOTE: Upon return from this function, prior sysfs_device references from + * this driver's list of devices _may_ not be valid + * + * Returns dlist of devices on success and NULL on failure + */ +struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver) +{ + if (driver = NULL) { + errno = EINVAL; + return NULL; + } + + if (driver->devices != NULL) { + dlist_destroy(driver->devices); + driver->devices = NULL; + } + + if (driver->directory = NULL) + return (sysfs_get_driver_devices(driver)); + + if ((sysfs_refresh_dir_links(driver->directory)) != 0) { + dprintf("Error refreshing driver links\n"); + return NULL; + } + + return (sysfs_get_driver_devices(driver)); +} + +/** * sysfs_get_driver_device: looks up a device from a list of driver's devices * and returns its sysfs_device corresponding to it * @driver: sysfs_driver on which to search @@ -285,8 +334,7 @@ dprintf("Error getting sysfs mount path\n"); return -1; } - if (sysfs_trailing_slash(path) = 0) - strcat(path, "/"); + strcat(path, "/"); strcat(path, SYSFS_BUS_NAME); strcat(path, "/"); strcat(path, bus); diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/libsysfs/sysfs_utils.c udev-012/libsysfs/sysfs_utils.c --- temp/udev-012/libsysfs/sysfs_utils.c 2003-12-19 00:50:24.000000000 +0530 +++ udev-012/libsysfs/sysfs_utils.c 2004-01-02 09:40:07.000000000 +0530 @@ -27,6 +27,30 @@ #endif /** + * sysfs_remove_trailing_slash: Removes any trailing '/' in the given path + * @path: Path to look for the trailing '/' + * Returns 0 on success 1 on error + */ +int sysfs_remove_trailing_slash(unsigned char *path) +{ + unsigned char *c = NULL; + + if (path = NULL) { + errno = EINVAL; + return 1; + } + c = strrchr(path, '/'); + if (c = NULL) { + dprintf("Invalid path %s\n", path); + errno = EINVAL; + return 1; + } + if (*(c+1) = '\0') + *c = '\0'; + return 0; +} + +/** * sysfs_get_mnt_path: Gets the mount point for specified filesystem. * @fs_type: filesystem type to retrieve mount point * @mnt_path: place to put the retrieved mount path @@ -72,28 +96,14 @@ errno = EINVAL; ret = -1; } + if ((sysfs_remove_trailing_slash(mnt_path)) != 0) + ret = -1; + return ret; #endif } /* - * sysfs_trailing_slash: checks if there's a trailing slash to path - * @path: path to check - * returns 1 if true and 0 if not - */ -int sysfs_trailing_slash(unsigned char *path) -{ - unsigned char *s = NULL; - - if (path = NULL) - return 0; - s = &path[strlen(path)-1]; - if (strncmp(s, "/", 1) = 0) - return 1; - return 0; -} - -/* * sysfs_get_mnt_path: Gets the sysfs mount point. * @mnt_path: place to put "sysfs" mount point * @len: size of mnt_path @@ -109,9 +119,11 @@ return -1; } sysfs_path = getenv(SYSFS_PATH_ENV); - if (sysfs_path != NULL) + if (sysfs_path != NULL) { strncpy(mnt_path, sysfs_path, len); - else + if ((sysfs_remove_trailing_slash(mnt_path)) != 0) + return 1; + } else ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len); return ret; @@ -152,7 +164,7 @@ strncpy(name, n, len); return 0; } - + /** * sysfs_get_link: returns link source * @path: symbolic link's path @@ -178,32 +190,69 @@ if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) { return -1; } - d = linkpath; - - /* getting rid of leading "../.." */ - while (*d = '/' || *d = '.') { - if (*d = '/') - slashes++; - d++; - } - - d--; - - s = &devdir[strlen(devdir)-1]; - while (s != NULL && count != (slashes+1)) { - s--; - if (*s = '/') - count++; + /* + * Three cases here: + * 1. relative path => format ../.. + * 2. absolute path => format /abcd/efgh + * 3. relative path _from_ this dir => format abcd/efgh + */ + switch (*d) { + case '.': + /* + * handle the case where link is of type ./abcd/xxx + */ + strncpy(target, devdir, len); + if (*(d+1) = '/') + d += 2; + else if (*(d+1) = '.') + goto parse_path; + s = strrchr(target, '/'); + if (s != NULL) { + *(s+1) = '\0'; + strcat(target, d); + } else { + strcpy(target, d); + } + break; + /* + * relative path + * getting rid of leading "../.." + */ +parse_path: + while (*d = '/' || *d = '.') { + if (*d = '/') + slashes++; + d++; + } + d--; + s = &devdir[strlen(devdir)-1]; + while (s != NULL && count != (slashes+1)) { + s--; + if (*s = '/') + count++; + } + strncpy(s, d, (SYSFS_PATH_MAX-strlen(devdir))); + strncpy(target, devdir, len); + break; + case '/': + /* absolute path - copy as is */ + strncpy(target, linkpath, len); + break; + default: + /* relative path from this directory */ + strncpy(target, devdir, len); + s = strrchr(target, '/'); + if (s != NULL) { + *(s+1) = '\0'; + strcat(target, linkpath); + } else { + strcpy(target, linkpath); + } } - - strncpy(s, d, (SYSFS_PATH_MAX-strlen(devdir))); - strncpy(target, devdir, len); - return 0; } - /** * sysfs_del_name: free function for sysfs_open_subsystem_list * @name: memory area to be freed @@ -245,8 +294,8 @@ dprintf("Error getting sysfs mount point\n"); return NULL; } - if (sysfs_trailing_slash(sysfs_path) = 0) - strcat(sysfs_path, "/"); + + strcat(sysfs_path, "/"); strcat(sysfs_path, name); dir = sysfs_open_directory(sysfs_path); if (dir = NULL) { @@ -318,8 +367,7 @@ return NULL; } - if (sysfs_trailing_slash(sysfs_path) = 0) - strcat(sysfs_path, "/"); + strcat(sysfs_path, "/"); strcat(sysfs_path, SYSFS_BUS_NAME); strcat(sysfs_path, "/"); strcat(sysfs_path, name); @@ -376,7 +424,7 @@ } if (S_ISDIR(astats.st_mode)) return 0; - + return 1; } @@ -399,7 +447,7 @@ } if (S_ISLNK(astats.st_mode)) return 0; - + return 1; } @@ -422,6 +470,6 @@ } if (S_ISREG(astats.st_mode)) return 0; - + return 1; } diff -Nru --exclude=klibc --exclude=SCCS temp/udev-012/namedev.c udev-012/namedev.c --- temp/udev-012/namedev.c 2003-12-31 03:54:46.000000000 +0530 +++ udev-012/namedev.c 2004-01-02 09:45:54.000000000 +0530 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -632,13 +633,10 @@ static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_dev) { - struct sysfs_device *sysfs_device; - struct sysfs_class_device *class_dev_parent; + struct sysfs_device *sysfs_device = NULL; + struct sysfs_class_device *class_dev_parent = NULL; + struct timespec tspec; int loop; - char filename[SYSFS_PATH_MAX + 6]; - int retval; - char *temp; - int partition = 0; /* Figure out where the device symlink is at. For char devices this will * always be in the class_dev->path. But for block devices, it's different. @@ -649,67 +647,22 @@ * symlink yet. We do sit and spin on waiting for them right now, we should * possibly have a whitelist for these devices here... */ - strcpy(filename, class_dev->path); - dbg("filename = %s", filename); - if (strcmp(class_dev->classname, SYSFS_BLOCK_NAME) = 0) { - if (isdigit(class_dev->path[strlen(class_dev->path)-1])) { - temp = strrchr(filename, '/'); - if (temp) { - char *temp2 = strrchr(filename, '/'); - partition = 1; - *temp = 0x00; - dbg("temp2 = %s", temp2); - if (temp2 && (strcmp(temp2, "/block") = 0)) { - /* oops, we have no parent block device, so go back to original directory */ - strcpy(filename, class_dev->path); - partition = 0; - } - } - } - } - strcat(filename, "/device"); - - loop = 2; - while (loop--) { - struct stat buf; - dbg("looking for '%s'", filename); - retval = stat(filename, &buf); - if (!retval) - break; - /* sleep to give the kernel a chance to create the device file */ - sleep(1); - } - - loop = 1; /* FIXME put a real value in here for when everything is fixed... */ - while (loop--) { - /* find the sysfs_device for this class device */ - /* Wouldn't it really be nice if libsysfs could do this for us? */ - sysfs_device = sysfs_get_classdev_device(class_dev); + class_dev_parent = sysfs_get_classdev_parent(class_dev); + if (class_dev_parent) + dbg("really a partition"); + + tspec.tv_sec = 0; + tspec.tv_nsec = 10000000; /* sleep 10 millisec */ + loop = 10; + while (loop--) { + nanosleep(&tspec, NULL); + if (class_dev_parent) + sysfs_device = sysfs_get_classdev_device(class_dev_parent); + else + sysfs_device = sysfs_get_classdev_device(class_dev); + if (sysfs_device != NULL) goto exit; - - /* if it's a partition, we need to get the parent device */ - if (partition) { - /* FIXME HACK HACK HACK HACK - * for some reason partitions need this extra sleep here, in order - * to wait for the device properly. Once the libsysfs code is - * fixed properly, this sleep should go away, and we can just loop above. - */ - sleep(1); - dbg("really is a partition"); - class_dev_parent = sysfs_get_classdev_parent(class_dev); - if (class_dev_parent = NULL) { - dbg("sysfs_get_classdev_parent for class device '%s' failed", class_dev->name); - } else { - dbg("class_dev_parent->name='%s'", class_dev_parent->name); - sysfs_device = sysfs_get_classdev_device(class_dev_parent); - if (sysfs_device != NULL) - goto exit; - } - } - /* sleep to give the kernel a chance to create the link */ - /* FIXME remove comment... - sleep(1); */ } dbg("Timed out waiting for device symlink, continuing on anyway..."); exit: ------------------------------------------------------- This SF.net email is sponsored by: IBM Linux Tutorials. Become an expert in LINUX or just sharpen your skills. Sign up for IBM's Free Linux Tutorials. Learn everything from the bash shell to sys admin. Click now! http://ads.osdn.com/?ad_id78&alloc_id371&op=click _______________________________________________ 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