static int i2cdetect_dash_l(struct dirtree *node) { int suffix_len = strlen("/name"); int bus; char *fname, *p; unsigned long funcs; if (!node->parent) return DIRTREE_RECURSE; // Skip the directory itself. if (sscanf(node->name, "i2c-%d", &bus) != 1) return 0; funcs = i2c_get_funcs(bus); fname = dirtree_path(node, &suffix_len); strcat(fname, "/name"); xreadfile(fname, toybuf, sizeof(toybuf)); free(fname); if ((p = strchr(toybuf, '\n'))) *p = 0; // "i2c-1 i2c Synopsys DesignWare I2C adapter I2C adapter" printf("%s\t%-10s\t%-32s\t%s\n", node->name, (funcs & I2C_FUNC_I2C) ? "i2c" : "?", toybuf, (funcs & I2C_FUNC_I2C) ? "I2C Adapter" : "?"); return 0; }
// Get directory information. static int retell_dir(struct dirtree *root) { char *fpath = NULL; if (root->again) { xputc('\n'); return 0; } if (S_ISDIR(root->st.st_mode) && !root->parent) return (DIRTREE_RECURSE | DIRTREE_COMEAGAIN); fpath = dirtree_path(root, NULL); //Special case: with '-a' option and '.'/'..' also included in printing list. if ((root->name[0] != '.') || (toys.optflags & FLAG_a)) { print_file_attr(fpath); if (S_ISDIR(root->st.st_mode) && (toys.optflags & FLAG_R) && dirtree_notdotdot(root)) { xprintf("\n%s:\n", fpath); free(fpath); return (DIRTREE_RECURSE | DIRTREE_COMEAGAIN); } } free(fpath); return 0; }
// Update attribute of given file. static int update_attr(struct dirtree *root) { unsigned long fval = 0; char *fpath = NULL; int fd; if (!dirtree_notdotdot(root)) return 0; /* * if file is a link and recursive is set or file is not regular+link+dir * (like fifo or dev file) then escape the file. */ if ((S_ISLNK(root->st.st_mode) && chattr.recursive) || (!S_ISREG(root->st.st_mode) && !S_ISLNK(root->st.st_mode) && !S_ISDIR(root->st.st_mode))) return 0; fpath = dirtree_path(root, NULL); if (-1 == (fd=open(fpath, O_RDONLY | O_NONBLOCK))) { free(fpath); return DIRTREE_ABORT; } // Get current attr of file. if (ext2_getflag(fd, &(root->st), &fval) < 0) { perror_msg("read flags of '%s'", fpath); free(fpath); xclose(fd); return DIRTREE_ABORT; } if (chattr.set) { // for '=' operator. if (ext2_setflag(fd, &(root->st), chattr.set) < 0) perror_msg("setting flags '%s'", fpath); } else { // for '-' / '+' operator. fval &= ~(chattr.rm); fval |= chattr.add; if (!S_ISDIR(root->st.st_mode)) fval &= ~FS_DIRSYNC_FL; if (ext2_setflag(fd, &(root->st), fval) < 0) perror_msg("setting flags '%s'", fpath); } if (chattr.vflag) { // set file version if (ioctl(fd, FS_IOC_SETVERSION, (void*)&chattr.version) < 0) perror_msg("while setting version on '%s'", fpath); } free(fpath); xclose(fd); if (S_ISDIR(root->st.st_mode) && chattr.recursive) return DIRTREE_RECURSE; return 0; }
char *dirtree_path(struct dirtree *node, int *plen) { char *path; int len; if (!node) { path = xmalloc(*plen); *plen = 0; return path; } len = (plen ? *plen : 0)+strlen(node->name)+1; path = dirtree_path(node->parent, &len); if (len && path[len-1] != '/') path[len++]='/'; len = (stpcpy(path+len, node->name) - path); if (plen) *plen = len; return path; }
struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, int flags) { struct dirtree *dt = NULL; struct stat st; int len = 0, linklen = 0; if (name) { // open code this because haven't got node to call dirtree_parentfd() on yet int fd = parent ? parent->data : AT_FDCWD; if (xfstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW*!(flags&DIRTREE_SYMFOLLOW))) goto error; if (S_ISLNK(st.st_mode)) { if (0>(linklen = xreadlinkat(fd, name, libbuf, 4095))) goto error; libbuf[linklen++]=0; } len = strlen(name); } dt = xzalloc((len = sizeof(struct dirtree)+len+1)+linklen); dt->parent = parent; if (name) { memcpy(&(dt->st), &st, sizeof(struct stat)); strcpy(dt->name, name); if (linklen) { dt->symlink = memcpy(len+(char *)dt, libbuf, linklen); dt->data = --linklen; } } return dt; error: if (!(flags&DIRTREE_SHUTUP) && notdotdot(name)) { char *path = parent ? dirtree_path(parent, 0) : ""; perror_msg("%s%s%s", path, parent ? "/" : "", name); if (parent) free(path); } if (parent) parent->symlink = (char *)1; free(dt); return 0; }
static int callback(struct dirtree *node) { // Entries in /sys/class/block aren't char devices, so skip 'em. (We'll // get block devices out of /sys/block.) if(!strcmp(node->name, "block")) return 0; // Does this directory have a "dev" entry in it? // This is path based because the hotplug callbacks are if (S_ISDIR(node->st.st_mode) || S_ISLNK(node->st.st_mode)) { int len=4; char *dev = dirtree_path(node, &len); strcpy(dev+len, "/dev"); if (!access(dev, R_OK)) make_device(dev); free(dev); } // Circa 2.6.25 the entries more than 2 deep are all either redundant // (mouse#, event#) or unnamed (every usb_* entry is called "device"). return (node->parent && node->parent->parent) ? 0 : DIRTREE_RECURSE; }