/* * Parse a single line of data, and return a newly allocated dev struct. * Add the new device to the cache struct, if one was read. * * Lines are of the form <device [TAG="value" ...]>/dev/foo</device> * * Returns -ve value on error. * Returns 0 otherwise. * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL * (e.g. comment lines, unknown XML content, etc). */ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) { blkid_dev dev; int ret; if (!cache || !dev_p) return -BLKID_ERR_PARAM; *dev_p = NULL; DBG(READ, ul_debug("line: %s", cp)); if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) return ret; dev = *dev_p; while ((ret = parse_tag(cache, dev, &cp)) > 0) { ; } if (dev->bid_type == NULL) { DBG(READ, ul_debug("blkid: device %s has no TYPE",dev->bid_name)); blkid_free_dev(dev); goto done; } done: return ret; }
/** * blkid_send_uevent: * @devname: absolute path to the device * @action: event string * * Returns: -1 in case of failure, or 0 on success. */ int blkid_send_uevent(const char *devname, const char *action) { char uevent[PATH_MAX]; struct stat st; FILE *f; int rc = -1; DBG(EVALUATE, ul_debug("%s: uevent '%s' requested", devname, action)); if (!devname || !action) return -1; if (stat(devname, &st) || !S_ISBLK(st.st_mode)) return -1; snprintf(uevent, sizeof(uevent), "/sys/dev/block/%d:%d/uevent", major(st.st_rdev), minor(st.st_rdev)); f = fopen(uevent, "w" UL_CLOEXECSTR); if (f) { rc = 0; if (fputs(action, f) >= 0) rc = 0; if (close_stream(f) != 0) DBG(EVALUATE, ul_debug("write failed: %s", uevent)); } DBG(EVALUATE, ul_debug("%s: send uevent %s", uevent, rc == 0 ? "SUCCESS" : "FAILED")); return rc; }
/** * mnt_init_debug: * @mask: debug mask (0xffff to enable full debugging) * * If the @mask is not specified, then this function reads * the LIBMOUNT_DEBUG environment variable to get the mask. * * Already initialized debugging stuff cannot be changed. Calling * this function twice has no effect. */ void mnt_init_debug(int mask) { if (libmount_debug_mask) return; __UL_INIT_DEBUG(libmount, MNT_DEBUG_, mask, LIBMOUNT_DEBUG); if (libmount_debug_mask != MNT_DEBUG_INIT && libmount_debug_mask != (MNT_DEBUG_HELP|MNT_DEBUG_INIT)) { const char *ver = NULL; const char **features = NULL, **p; mnt_get_library_version(&ver); mnt_get_library_features(&features); DBG(INIT, ul_debug("library debug mask: 0x%04x", libmount_debug_mask)); DBG(INIT, ul_debug("library version: %s", ver)); p = features; while (p && *p) DBG(INIT, ul_debug(" feature: %s", *p++)); } ON_DBG(HELP, ul_debug_print_masks("LIBMOUNT_DEBUG", UL_DEBUG_MASKNAMES(libmount))); }
/* * Note that the @target has to be an absolute path (so at least "/"). The * @filename returns an allocated buffer with the last path component, for example: * * mnt_chdir_to_parent("/mnt/test", &buf) ==> chdir("/mnt"), buf="test" */ int mnt_chdir_to_parent(const char *target, char **filename) { char *buf, *parent, *last = NULL; char cwd[PATH_MAX]; int rc = -EINVAL; if (!target || *target != '/') return -EINVAL; DBG(UTILS, ul_debug("moving to %s parent", target)); buf = strdup(target); if (!buf) return -ENOMEM; if (*(buf + 1) != '\0') { last = stripoff_last_component(buf); if (!last) goto err; } parent = buf && *buf ? buf : "/"; if (chdir(parent) == -1) { DBG(UTILS, ul_debug("failed to chdir to %s: %m", parent)); rc = -errno; goto err; } if (!getcwd(cwd, sizeof(cwd))) { DBG(UTILS, ul_debug("failed to obtain current directory: %m")); rc = -errno; goto err; } if (strcmp(cwd, parent) != 0) { DBG(UTILS, ul_debug( "unexpected chdir (expected=%s, cwd=%s)", parent, cwd)); goto err; } DBG(CXT, ul_debug( "current directory moved to %s [last_component='%s']", parent, last)); if (filename) { *filename = buf; if (!last || !*last) memcpy(*filename, ".", 2); else memmove(*filename, last, strlen(last) + 1); } else free(buf); return 0; err: free(buf); return rc; }
static int write_output(char *obuf, ssize_t bytes) { DBG(PTY, ul_debug(" writing output")); if (write_all(STDOUT_FILENO, obuf, bytes)) { DBG(PTY, ul_debug(" writing output *failed*")); warn(_("write failed")); return -errno; } return 0; }
static char *evaluate_by_udev(const char *token, const char *value, int uevent) { char dev[PATH_MAX]; char *path = NULL; size_t len; struct stat st; DBG(EVALUATE, ul_debug("evaluating by udev %s=%s", token, value)); if (!strcmp(token, "UUID")) strcpy(dev, _PATH_DEV_BYUUID "/"); else if (!strcmp(token, "LABEL")) strcpy(dev, _PATH_DEV_BYLABEL "/"); else if (!strcmp(token, "PARTLABEL")) strcpy(dev, _PATH_DEV_BYPARTLABEL "/"); else if (!strcmp(token, "PARTUUID")) strcpy(dev, _PATH_DEV_BYPARTUUID "/"); else { DBG(EVALUATE, ul_debug("unsupported token %s", token)); return NULL; /* unsupported tag */ } len = strlen(dev); if (blkid_encode_string(value, &dev[len], sizeof(dev) - len) != 0) return NULL; DBG(EVALUATE, ul_debug("expected udev link: %s", dev)); if (stat(dev, &st)) goto failed; /* link or device does not exist */ if (!S_ISBLK(st.st_mode)) return NULL; path = canonicalize_path(dev); if (!path) return NULL; #ifdef CONFIG_BLKID_VERIFY_UDEV if (verify_tag(path, token, value)) goto failed; #endif return path; failed: DBG(EVALUATE, ul_debug("failed to evaluate by udev")); if (uevent && path) blkid_send_uevent(path, "change"); free(path); return NULL; }
/* * Look for LABEL (name) in the FAT root directory. */ static unsigned char *search_fat_label(blkid_probe pr, uint64_t offset, uint32_t entries) { struct vfat_dir_entry *ent, *dir = NULL; uint32_t i; DBG(LOWPROBE, ul_debug("\tlook for label in root-dir " "(entries: %d, offset: %jd)", entries, offset)); if (!blkid_probe_is_tiny(pr)) { /* large disk, read whole root directory */ dir = (struct vfat_dir_entry *) blkid_probe_get_buffer(pr, offset, (blkid_loff_t) entries * sizeof(struct vfat_dir_entry)); if (!dir) return NULL; } for (i = 0; i < entries; i++) { /* * The root directory could be relatively large (4-16kB). * Fortunately, the LABEL is usually the first entry in the * directory. On tiny disks we call read() per entry. */ if (!dir) ent = (struct vfat_dir_entry *) blkid_probe_get_buffer(pr, (blkid_loff_t) offset + (i * sizeof(struct vfat_dir_entry)), sizeof(struct vfat_dir_entry)); else ent = &dir[i]; if (!ent || ent->name[0] == 0x00) break; if ((ent->name[0] == FAT_ENTRY_FREE) || (ent->cluster_high != 0 || ent->cluster_low != 0) || ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) continue; if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) { DBG(LOWPROBE, ul_debug("\tfound fs LABEL at entry %d", i)); return ent->name; } } return NULL; }
/* * Allocate a new device struct with device name filled in. Will handle * finding the device on lines of the form: * <device foo=bar>devname</device> * <device>devname<foo>bar</foo></device> */ static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) { char *start, *tmp, *end, *name; int ret; if ((ret = parse_start(cp)) <= 0) return ret; start = tmp = strchr(*cp, '>'); if (!start) { DBG(READ, ul_debug("blkid: short line parsing dev: %s", *cp)); return -BLKID_ERR_CACHE; } start = skip_over_blank(start + 1); end = skip_over_word(start); DBG(READ, ul_debug("device should be %*s", (int)(end - start), start)); if (**cp == '>') *cp = end; else (*cp)++; *tmp = '\0'; if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { DBG(READ, ul_debug("blkid: missing </device> ending: %s", end)); } else if (tmp) *tmp = '\0'; if (end - start <= 1) { DBG(READ, ul_debug("blkid: empty device name: %s", *cp)); return -BLKID_ERR_CACHE; } name = strndup(start, end - start); if (name == NULL) return -BLKID_ERR_MEM; DBG(READ, ul_debug("found dev %s", name)); if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) { free(name); return -BLKID_ERR_MEM; } free(name); return 1; }
/* * Read a bsd_disklabel from sector 0 or from the starting sector of p. * If it has the right magic, return 0. */ static int bsd_readlabel(struct fdisk_context *cxt) { struct fdisk_bsd_label *l; struct bsd_disklabel *d; int t; off_t offset = 0; l = self_label(cxt); d = self_disklabel(cxt); if (l->dos_part) /* BSD is nested within DOS partition, get the begin of the * partition. Note that DOS uses native sector size. */ offset = dos_partition_get_start(l->dos_part) * cxt->sector_size; if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) return -1; if (read_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0) return errno ? -errno : -1; /* The offset to begin of the disk label. Note that BSD uses * 512-byte (default) sectors. */ memmove(d, &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE + BSD_LABELOFFSET], sizeof(*d)); if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) { DBG(LABEL, ul_debug("not found magic")); return -1; } for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) { d->d_partitions[t].p_size = 0; d->d_partitions[t].p_offset = 0; d->d_partitions[t].p_fstype = BSD_FS_UNUSED; } if (d->d_npartitions > BSD_MAXPARTITIONS) fdisk_warnx(cxt, ("Too many partitions (%d, maximum is %d)."), d->d_npartitions, BSD_MAXPARTITIONS); /* let's follow in-PT geometry */ cxt->geom.sectors = d->d_nsectors; cxt->geom.heads = d->d_ntracks; cxt->geom.cylinders = d->d_ncylinders; cxt->label->nparts_cur = d->d_npartitions; cxt->label->nparts_max = BSD_MAXPARTITIONS; DBG(LABEL, ul_debug("read BSD label")); return 0; }
/* * Don't export this to libmount API -- utab is private library stuff. * * If the file does not exist and @writable argument is not NULL, then it will * try to create the directory (e.g. /run/mount) and the file. * * Returns: 1 if utab is a regular file, and 0 in case of * error (check errno for more details). */ int mnt_has_regular_utab(const char **utab, int *writable) { struct stat st; int rc; const char *filename = utab && *utab ? *utab : mnt_get_utab_path(); if (writable) *writable = 0; if (utab && !*utab) *utab = filename; DBG(UTILS, ul_debug("utab: %s", filename)); rc = lstat(filename, &st); if (rc == 0) { /* file exists */ if (S_ISREG(st.st_mode)) { if (writable) *writable = !try_write(filename); return 1; } goto done; /* it's not a regular file */ } if (writable) { char *dirname = strdup(filename); if (!dirname) goto done; stripoff_last_component(dirname); /* remove filename */ rc = mkdir(dirname, S_IWUSR| S_IRUSR|S_IRGRP|S_IROTH| S_IXUSR|S_IXGRP|S_IXOTH); free(dirname); if (rc && errno != EEXIST) goto done; /* probably EACCES */ *writable = !try_write(filename); if (*writable) return 1; } done: DBG(UTILS, ul_debug("%s: irregular/non-writable file", filename)); return 0; }
/** * blkid_evaluate_tag: * @token: token name (e.g "LABEL" or "UUID") or unparsed tag (e.g. "LABEL=foo") * @value: token data (e.g. "foo") * @cache: pointer to cache (or NULL when you don't want to re-use the cache) * * Returns: allocated string with a device name. */ char *blkid_evaluate_tag(const char *token, const char *value, blkid_cache *cache) { struct blkid_config *conf = NULL; char *t = NULL, *v = NULL; char *ret = NULL; int i; if (!token) return NULL; if (!cache || !*cache) blkid_init_debug(0); DBG(EVALUATE, ul_debug("evaluating %s%s%s", token, value ? "=" : "", value ? value : "")); if (!value) { if (!strchr(token, '=')) { ret = strdup(token); goto out; } blkid_parse_tag_string(token, &t, &v); if (!t || !v) goto out; token = t; value = v; } conf = blkid_read_config(NULL); if (!conf) goto out; for (i = 0; i < conf->nevals; i++) { if (conf->eval[i] == BLKID_EVAL_UDEV) ret = evaluate_by_udev(token, value, conf->uevent); else if (conf->eval[i] == BLKID_EVAL_SCAN) ret = evaluate_by_scan(token, value, cache, conf); if (ret) break; } DBG(EVALUATE, ul_debug("%s=%s evaluated as %s", token, value, ret)); out: blkid_free_config(conf); free(t); free(v); return ret; }
int mnt_get_gid(const char *groupname, gid_t *gid) { int rc = -1; struct group grp; struct group *gr; size_t sz = get_pw_record_size(); char *buf; if (!groupname || !gid) return -EINVAL; buf = malloc(sz); if (!buf) return -ENOMEM; if (!getgrnam_r(groupname, &grp, buf, sz, &gr) && gr) { *gid= gr->gr_gid; rc = 0; } else { DBG(UTILS, ul_debug( "cannot convert '%s' groupname to GID", groupname)); rc = errno ? -errno : -EINVAL; } free(buf); return rc; }
/** * mnt_optstr_prepend_option: * @optstr: option string or NULL, returns a reallocated string * @name: value name * @value: value * * Returns: 0 on success or <0 in case of error. After an error the @optstr should * be unmodified. */ int mnt_optstr_prepend_option(char **optstr, const char *name, const char *value) { int rc = 0; char *tmp; if (!optstr) return -EINVAL; if (!name || !*name) return 0; tmp = *optstr; *optstr = NULL; rc = mnt_optstr_append_option(optstr, name, value); if (!rc && tmp && *tmp) rc = mnt_optstr_append_option(optstr, tmp, NULL); if (!rc) { free(tmp); return 0; } free(*optstr); *optstr = tmp; DBG(OPTIONS, ul_debug("failed to prepend '%s[=%s]' to '%s'", name, value, *optstr)); return rc; }
static pid_t path_to_tid(const char *filename) { char *path = mnt_resolve_path(filename, NULL); char *p, *end = NULL; pid_t tid = 0; if (!path) goto done; p = strrchr(path, '/'); if (!p) goto done; *p = '\0'; p = strrchr(path, '/'); if (!p) goto done; p++; errno = 0; tid = strtol(p, &end, 10); if (errno || p == end || (end && *end)) { tid = 0; goto done; } DBG(TAB, ul_debug("TID for %s is %d", filename, tid)); done: free(path); return tid; }
static char *evaluate_by_scan(const char *token, const char *value, blkid_cache *cache, struct blkid_config *conf) { blkid_cache c = cache ? *cache : NULL; char *res; DBG(EVALUATE, ul_debug("evaluating by blkid scan %s=%s", token, value)); if (!c) { char *cachefile = blkid_get_cache_filename(conf); blkid_get_cache(&c, cachefile); free(cachefile); } if (!c) return NULL; res = blkid_get_devname(c, token, value); if (cache) *cache = c; else blkid_put_cache(c); return res; }
static int get_user_reply(const char *prompt, char *buf, size_t bufsz) { char *p; size_t sz; #ifdef HAVE_LIBREADLINE if (isatty(STDIN_FILENO)) { p = readline(prompt); if (!p) return 1; memcpy(buf, p, bufsz); free(p); } else #endif { fputs(prompt, stdout); fflush(stdout); if (!fgets(buf, bufsz, stdin)) return 1; } for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */ if (p > buf) memmove(buf, p, p - buf); /* remove blank space */ sz = strlen(buf); if (sz && *(buf + sz - 1) == '\n') *(buf + sz - 1) = '\0'; DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf)); return 0; }
static int get_filesystems(const char *filename, char ***filesystems, const char *pattern) { int rc = 0; FILE *f; char line[129]; f = fopen(filename, "r" UL_CLOEXECSTR); if (!f) return 1; DBG(UTILS, ul_debug("reading filesystems list from: %s", filename)); while (fgets(line, sizeof(line), f)) { char name[sizeof(line)]; if (*line == '#' || strncmp(line, "nodev", 5) == 0) continue; if (sscanf(line, " %128[^\n ]\n", name) != 1) continue; if (strcmp(name, "*") == 0) { rc = 1; break; /* end of the /etc/filesystems */ } if (pattern && !mnt_match_fstype(name, pattern)) continue; rc = add_filesystem(filesystems, name); if (rc) break; } fclose(f); return rc; }
/* * Extract a tag from the line. * * Return 1 if a valid tag was found. * Return 0 if no tag found. * Return -ve error code. */ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) { char *name = NULL; char *value = NULL; int ret; if (!cache || !dev) return -BLKID_ERR_PARAM; if ((ret = parse_token(&name, &value, cp)) <= 0 /* && (ret = parse_xml(&name, &value, cp)) <= 0 */) return ret; DBG(READ, ul_debug("tag: %s=\"%s\"", name, value)); /* Some tags are stored directly in the device struct */ if (!strcmp(name, "DEVNO")) dev->bid_devno = strtoull(value, NULL, 0); else if (!strcmp(name, "PRI")) dev->bid_pri = strtol(value, NULL, 0); else if (!strcmp(name, "TIME")) { char *end = NULL; dev->bid_time = strtoull(value, &end, 0); if (end && *end == '.') dev->bid_utime = strtoull(end + 1, NULL, 0); } else ret = blkid_set_tag(dev, name, value, strlen(value)); return ret < 0 ? ret : 1; }
/* * Start parsing a new line from the cache. * * line starts with "<device" return 1 -> continue parsing line * line starts with "<foo", empty, or # return 0 -> skip line * line starts with other, return -BLKID_ERR_CACHE -> error */ static int parse_start(char **cp) { char *p; p = strip_line(*cp); /* Skip comment or blank lines. We can't just NUL the first '#' char, * in case it is inside quotes, or escaped. */ if (*p == '\0' || *p == '#') return 0; if (!strncmp(p, "<device", 7)) { DBG(READ, ul_debug("found device header: %8s", p)); p += 7; *cp = p; return 1; } if (*p == '<') return 0; return -BLKID_ERR_CACHE; }
int mnt_get_uid(const char *username, uid_t *uid) { int rc = -1; struct passwd pwd; struct passwd *pw; size_t sz = get_pw_record_size(); char *buf; if (!username || !uid) return -EINVAL; buf = malloc(sz); if (!buf) return -ENOMEM; if (!getpwnam_r(username, &pwd, buf, sz, &pw) && pw) { *uid= pw->pw_uid; rc = 0; } else { DBG(UTILS, ul_debug( "cannot convert '%s' username to UID", username)); rc = errno ? -errno : -EINVAL; } free(buf); return rc; }
/* * Parses one line from utab file */ static int mnt_parse_utab_line(struct libmnt_fs *fs, const char *s) { const char *p = s; assert(fs); assert(s); assert(!fs->source); assert(!fs->target); while (p && *p) { char *end = NULL; while (*p == ' ') p++; if (!*p) break; if (!fs->source && !strncmp(p, "SRC=", 4)) { char *v = unmangle(p + 4, &end); if (!v) goto enomem; __mnt_fs_set_source_ptr(fs, v); } else if (!fs->target && !strncmp(p, "TARGET=", 7)) { fs->target = unmangle(p + 7, &end); if (!fs->target) goto enomem; } else if (!fs->root && !strncmp(p, "ROOT=", 5)) { fs->root = unmangle(p + 5, &end); if (!fs->root) goto enomem; } else if (!fs->bindsrc && !strncmp(p, "BINDSRC=", 8)) { fs->bindsrc = unmangle(p + 8, &end); if (!fs->bindsrc) goto enomem; } else if (!fs->user_optstr && !strncmp(p, "OPTS=", 5)) { fs->user_optstr = unmangle(p + 5, &end); if (!fs->user_optstr) goto enomem; } else if (!fs->attrs && !strncmp(p, "ATTRS=", 6)) { fs->attrs = unmangle(p + 6, &end); if (!fs->attrs) goto enomem; } else { /* unknown variable */ while (*p && *p != ' ') p++; } if (end) p = end; } return 0; enomem: DBG(TAB, ul_debug("utab parse error: ENOMEM")); return -ENOMEM; }
int get_user_reply(struct fdisk_context *cxt, const char *prompt, char *buf, size_t bufsz) { char *p; size_t sz; do { fputs(prompt, stdout); fflush(stdout); if (!fgets(buf, bufsz, stdin)) { if (fdisk_label_is_changed(fdisk_get_label(cxt, NULL))) { fprintf(stderr, _("\nDo you really want to quit? ")); if (fgets(buf, bufsz, stdin) && !rpmatch(buf)) continue; } fdisk_free_context(cxt); exit(EXIT_FAILURE); } else break; } while (1); for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */ if (p > buf) memmove(buf, p, p - buf); /* remove blank space */ sz = strlen(buf); if (sz && *(buf + sz - 1) == '\n') *(buf + sz - 1) = '\0'; DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf)); return 0; }
static void init_tty(struct su_context *su) { su->isterm = isatty(STDIN_FILENO) ? 1 : 0; DBG(TTY, ul_debug("initialize [is-term=%s]", su->isterm ? "true" : "false")); if (su->isterm) get_terminal_name(NULL, &su->tty_name, &su->tty_number); }
static void __attribute__((__noreturn__)) done(struct script_control *ctl) { DBG(MISC, ul_debug("done!")); if (ctl->isterm) tcsetattr(STDIN_FILENO, TCSADRAIN, &ctl->attrs); if (!ctl->quiet) printf(_("Script done, file is %s\n"), ctl->fname); #ifdef HAVE_LIBUTEMPTER if (ctl->master >= 0) utempter_remove_record(ctl->master); #endif kill(ctl->child, SIGTERM); /* make sure we don't create orphans */ if (ctl->timingfp) fclose(ctl->timingfp); fclose(ctl->typescriptfp); if (ctl->rc_wanted) { if (WIFSIGNALED(ctl->childstatus)) exit(WTERMSIG(ctl->childstatus) + 0x80); else exit(WEXITSTATUS(ctl->childstatus)); } exit(EXIT_SUCCESS); }
/* * Returns 1 if the @major number is associated with @drvname. */ int blkid_driver_has_major(const char *drvname, int major) { FILE *f; char buf[128]; int match = 0; f = fopen(_PATH_PROC_DEVICES, "r" UL_CLOEXECSTR); if (!f) return 0; while (fgets(buf, sizeof(buf), f)) { /* skip to block dev section */ if (strncmp("Block devices:\n", buf, sizeof(buf)) == 0) break; } while (fgets(buf, sizeof(buf), f)) { int maj; char name[64 + 1]; if (sscanf(buf, "%d %64[^\n ]", &maj, name) != 2) continue; if (maj == major && strcmp(name, drvname) == 0) { match = 1; break; } } fclose(f); DBG(DEVNO, ul_debug("major %d %s associated with '%s' driver", major, match ? "is" : "is NOT", drvname)); return match; }
static void findin(const char *dir, const char *pattern, int *count, char **wait) { DIR *dirp; struct dirent *dp; dirp = opendir(dir); if (dirp == NULL) return; DBG(SEARCH, ul_debug("find '%s' in '%s'", pattern, dir)); while ((dp = readdir(dirp)) != NULL) { if (!filename_equal(pattern, dp->d_name)) continue; if (uflag && *count == 0) xasprintf(wait, "%s/%s", dir, dp->d_name); else if (uflag && *count == 1 && *wait) { printf("%s: %s %s/%s", pattern, *wait, dir, dp->d_name); free(*wait); *wait = NULL; } else printf(" %s/%s", dir, dp->d_name); ++(*count); } closedir(dirp); return; }
static int filename_equal(const char *cp, const char *dp) { int i = strlen(dp); DBG(SEARCH, ul_debug("compare '%s' and '%s'", cp, dp)); if (dp[0] == 's' && dp[1] == '.' && filename_equal(cp, dp + 2)) return 1; if (!strcmp(dp + i - 2, ".Z")) i -= 2; else if (!strcmp(dp + i - 3, ".gz")) i -= 3; else if (!strcmp(dp + i - 3, ".xz")) i -= 3; else if (!strcmp(dp + i - 4, ".bz2")) i -= 4; while (*cp && *dp && *cp == *dp) cp++, dp++, i--; if (*cp == 0 && *dp == 0) return 1; while (isdigit(*dp)) dp++; if (*cp == 0 && *dp++ == '.') { --i; while (i > 0 && *dp) if (--i, *dp++ == '.') return (*dp++ == 'C' && *dp++ == 0); return 1; } return 0; }
void blkid__scan_dir(char *dirname, dev_t devno, struct dir_list **list, char **devname) { DIR *dir; struct dirent *dp; struct stat st; if ((dir = opendir(dirname)) == NULL) return; while ((dp = readdir(dir)) != NULL) { #ifdef _DIRENT_HAVE_D_TYPE if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_BLK && dp->d_type != DT_LNK && dp->d_type != DT_DIR) continue; #endif if (dp->d_name[0] == '.' && ((dp->d_name[1] == 0) || ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) continue; if (fstat_at(dirfd(dir), dirname, dp->d_name, &st, 0)) continue; if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { *devname = blkid_strconcat(dirname, "/", dp->d_name); DBG(DEVNO, ul_debug("found 0x%llx at %s", (long long)devno, *devname)); break; } if (!list || !S_ISDIR(st.st_mode)) continue; /* add subdirectory (but not symlink) to the list */ #ifdef _DIRENT_HAVE_D_TYPE if (dp->d_type == DT_LNK) continue; if (dp->d_type == DT_UNKNOWN) #endif { if (fstat_at(dirfd(dir), dirname, dp->d_name, &st, 1) || !S_ISDIR(st.st_mode)) continue; /* symlink or lstat() failed */ } if (*dp->d_name == '.' || ( #ifdef _DIRENT_HAVE_D_TYPE dp->d_type == DT_DIR && #endif strcmp(dp->d_name, "shm") == 0)) /* ignore /dev/.{udev,mount,mdadm} and /dev/shm */ continue; add_to_dirlist(dirname, dp->d_name, list); } closedir(dir); return; }
void fdisk_label_set_disabled(struct fdisk_label *lb, int disabled) { assert(lb); DBG(LABEL, ul_debug("%s label %s", lb->name, disabled ? "DISABLED" : "ENABLED")); lb->disabled = disabled ? 1 : 0; }
static void pty_cleanup(struct su_context *su) { if (su->pty_master == -1) return; DBG(PTY, ul_debug("cleanup")); if (su->isterm) tcsetattr(STDIN_FILENO, TCSADRAIN, &su->stdin_attrs); }