int Volume::mountVol() { dev_t deviceNodes[DirectVolume::MAX_PARTITIONS]; int n, i, rc = 0, curState; char errmsg[255]; int flags = getFlags(); /* we igore the setting of "VOL_PROVIDES_ASEC". if the storage is primary, then we will handle "Asec" */ //bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; const char* externalStorage = getenv("EXTERNAL_STORAGE"); bool providesAsec = externalStorage && !strcmp(getFuseMountpoint(), externalStorage); // TODO: handle "bind" style mounts, for emulated storage char decrypt_state[PROPERTY_VALUE_MAX]; char crypto_state[PROPERTY_VALUE_MAX]; char encrypt_progress[PROPERTY_VALUE_MAX]; if (mPreState != Volume::State_Shared && mVm->isSomeVolumeShared()) { SLOGI("Some volume is State_Shared, force to share current volume, %s \n", getLabel()); return mVm->shareVolume(getLabel(), "ums"); } property_get("vold.decrypt", decrypt_state, ""); property_get("vold.encrypt_progress", encrypt_progress, ""); #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT char *otgNodePath = getOtgNodePath(); #endif /* Don't try to mount the volumes if we have not yet entered the disk password * or are in the process of encrypting. */ if ((getState() == Volume::State_NoMedia) || ((!strcmp(decrypt_state, "trigger_restart_min_framework") || encrypt_progress[0]) && providesAsec)) { snprintf(errmsg, sizeof(errmsg), "Volume %s %s mount failed - no media", getLabel(), getFuseMountpoint()); mVm->getBroadcaster()->sendBroadcast( ResponseCode::VolumeMountFailedNoMedia, errmsg, false); errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; if (getState() == Volume::State_Pending) { mRetryMount = true; } return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX return 0; } #ifdef MTK_SHARED_SDCARD SLOGI("mountvol: IsEmmcStorage=%d", IsEmmcStorage()); if (IsEmmcStorage()) { property_set("ctl.start", "sdcard"); waitForServiceState("sdcard", "running"); setState(Volume::State_Mounted); return 0; } #endif n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } SLOGD("Found %d device nodes", n); #ifndef MTK_EMULATOR_SUPPORT if (!IsEmmcStorage() && !strncmp(getLabel(), "sdcard", 6)) { #ifdef MTK_FAT_ON_NAND if( -1 == mLoopDeviceIdx){ #endif SLOGD("Reinit SD card"); if (mVm->reinitExternalSD()){ SLOGE("Fail: reinitExternalSD()"); /* Card inserted but fail to reinit, there is something wrong with this card */ errno = EIO; return -1; } #ifdef MTK_FAT_ON_NAND } #endif } #endif /* If we're running encrypted, and the volume is marked as encryptable and nonremovable, * and also marked as providing Asec storage, then we need to decrypt * that partition, and update the volume object to point to it's new decrypted * block device */ property_get("ro.crypto.state", crypto_state, ""); if (providesAsec && ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) && !strcmp(crypto_state, "encrypted") && !isDecrypted()) { char new_sys_path[MAXPATHLEN]; char nodepath[256]; int new_major, new_minor; if (n != 1) { /* We only expect one device node returned when mounting encryptable volumes */ SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint()); return -1; } if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), new_sys_path, sizeof(new_sys_path), &new_major, &new_minor)) { SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint()); return -1; } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { if (createDeviceNode(otgNodePath, new_major, new_minor)) { SLOGE("usbotg: Volume mountVol Error making device node '%s' (%s)", otgNodePath, strerror(errno)); } updateDeviceInfo(otgNodePath, new_major, new_minor); } else #endif /* We now have the new sysfs path for the decrypted block device, and the * majore and minor numbers for it. So, create the device, update the * path to the new sysfs path, and continue. */ { snprintf(nodepath, sizeof(nodepath), "/dev/block/vold/%d:%d", new_major, new_minor); if (createDeviceNode(nodepath, new_major, new_minor)) { SLOGE("Error making device node '%s' (%s)", nodepath, strerror(errno)); } // Todo: Either create sys filename from nodepath, or pass in bogus path so // vold ignores state changes on this internal device. updateDeviceInfo(nodepath, new_major, new_minor); /* Get the device nodes again, because they just changed */ n = getDeviceNodes((dev_t *) &deviceNodes, DirectVolume::MAX_PARTITIONS); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } } } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { setState(Volume::State_Checking); if (0 != mkdir(getMountpoint(), 0700)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint()); } if (0 != chown(getMountpoint(), AID_MEDIA_RW, AID_MEDIA_RW)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getMountpoint()); } if (0 != mkdir(getFuseMountpoint(), 0755)) { SLOGE("usbotg: Volume mountVol (%s) mkdir failed (%s)" , getFuseMountpoint(), strerror(errno)); } else { SLOGD("usbotg: Volume mountVol (%s) mkdir success", getFuseMountpoint()); } int fd; int counter = 0; while(1) { counter++; if( counter == 10) { SLOGD("timeout open otgNodePath counter:%d\n",counter); break; } if ((fd = open(otgNodePath, O_RDONLY)) < 0) { SLOGE(" cannot open device '%s' (errno=%d) (%s)", otgNodePath, errno,strerror(errno)); usleep(30000); } else { SLOGD(" can access %s successfully", otgNodePath); close(fd); break; } } if (Fat::check(otgNodePath)) { SLOGE("usbotg: %s fat check fail (%s)\n", otgNodePath, strerror(errno)); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); return -1; } if (Fat::doMount(otgNodePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { SLOGE("usbotg: Volume mountVol %s Otg failed to mount via VFAT (%s)\n", otgNodePath, strerror(errno)); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); setState(Volume::State_Idle); return -1; } extractMetadata(otgNodePath); //fork sdcard process instead of witch service in init.rc struct sigaction act, oact; act.sa_handler = sigCld; act.sa_flags = 0; sigemptyset(&act.sa_mask); if (sigaction(SIGCHLD, &act, &oact) <0) { SLOGD("Error occured on signal"); return -1; } pid_t pid = fork(); if (pid < 0) { SLOGD("Error occured on fork"); return 0; } else if (pid == 0) { SLOGD("usbotg: Volume mountVol go execv,pid=%d", pid); const char* mountCmd = "/system/bin/sdcard"; const char* mountpoint = getMountpoint(); const char* fusemountpoint = getFuseMountpoint(); const char* argv0[] = { mountCmd, "-u", "1023", "-g", "1023", "-w", "1023", "-d", mountpoint, fusemountpoint, NULL }; SLOGD("%s %s %s %s %s %s %s %s %s %s", argv0[0], argv0[1], argv0[2], argv0[3], argv0[4], argv0[5], argv0[6], argv0[7], argv0[8], argv0[9]); if (execv(mountCmd,(char* const*)argv0) < 0) { ALOGE("execv(%s) failed: %s\n", mountCmd, strerror(errno)); SLOGD("usbotg: Volume mountVol mounted failed"); char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); exit(127); } exit(127); } else{ SLOGD("usbotg: Volume mountVol mounted succed,pid=%d",pid); setState(Volume::State_Mounted); mPid = pid; return 0; } } #endif for (i = 0; i < n; i++) { char devicePath[255]; sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]), minor(deviceNodes[i])); if (deviceNodes[i] == (dev_t)(-1)) { SLOGE("Partition '%s' is invalid dev_t. Skip mounting!", devicePath); continue; } SLOGI("%s being considered for volume %s\n", devicePath, getLabel()); errno = 0; if ((getState() == Volume::State_NoMedia) ) { SLOGI("NoMedia! skip mounting the storage. Update errno to ENODEV"); errno = ENODEV; return -1; } setState(Volume::State_Checking); /* * If FS check failed, we should move on to next partition * instead of returning an error */ __CHECK_FAT_AGAIN: if (Fat::check(devicePath)) { #if 0 if (errno == ENODATA) { SLOGW("%s does not contain a FAT filesystem\n", devicePath); continue; } errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); return -1; #else #ifdef MTK_EMMC_SUPPORT if ( mVm->isFirstBoot() && IsEmmcStorage()) { SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath); if (Fat::format(devicePath, 0, false)) { SLOGE("Failed to format (%s)", strerror(errno)); } else { SLOGI("Format successfully. (%s)\n", devicePath); property_set("persist.vold.first_boot", "0"); goto __CHECK_FAT_AGAIN; } } #endif #ifdef MTK_FAT_ON_NAND char first_boot[PROPERTY_VALUE_MAX] ; property_get("persist.vold.fat_first_boot", first_boot, "1"); if (!strcmp(first_boot, "1") && !strcmp(getLabel(), "sdcard0")) { SLOGI("** This is first boot and internal sd is not formatted. Try to format it. (%s)\n", devicePath); if (Fat::format(devicePath, 0, false)) { SLOGE("Failed to format %s(%d)", strerror(errno), errno); } else { SLOGI("%s format successfully\n", devicePath); property_set("persist.vold.fat_first_boot", "0"); goto __CHECK_FAT_AGAIN; } } #endif SLOGW("%s failed FS checks, move on to next partition", devicePath); continue; #endif } #ifdef MTK_EMMC_SUPPORT else { if ( mVm->isFirstBoot() && IsEmmcStorage()) { property_set("persist.vold.first_boot", "0"); } } #endif errno = 0; int gid; #ifdef MTK_EMMC_DISCARD if (Fat::doMount(devicePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true, IsEmmcStorage())) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } #else //MTK_EMMC_DISCARD if (Fat::doMount(devicePath, getMountpoint(), false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } #endif //MTK_EMMC_DISCARD SLOGI("providesAsec = %d", providesAsec); extractMetadata(devicePath); #ifdef MTK_2SDCARD_SWAP char secImgDir[PATH_MAX]; sprintf(secImgDir, "%s/.android_secure", getMountpoint()); SLOGI("Create %s in advance", secImgDir); /* Whether primary or secondary storage, create .android folder in advance to prevent from media out of space for Bindmounts fail This case happens in SWAP feature. */ if (access(secImgDir, R_OK | X_OK)) { if (errno == ENOENT) { if (mkdir(secImgDir, 0777)) { SLOGE("Failed to create %s (%s)", secImgDir, strerror(errno)); } } else { SLOGE("Failed to access %s (%s)", secImgDir, strerror(errno)); } } #endif if (providesAsec && mountAsecExternal() != 0) { SLOGE("Failed to mount secure area (%s)", strerror(errno)); umount(getMountpoint()); setState(Volume::State_Idle); return -1; } char service[64]; char service_id[64]; strcpy(service_id, getMountpoint()+strlen(Volume::MEDIA_DIR)+1); snprintf(service, 64, "fuse_%s", service_id); property_set("ctl.start", service); waitForServiceState(service, "running"); int fd; if ((fd = open(devicePath, O_RDONLY)) < 0) { SLOGE("Cannot open device '%s' (errno=%d)", devicePath, errno); } else { setState(Volume::State_Mounted, Fat::isFat32(fd)); close(fd); } mCurrentlyMountedKdev = deviceNodes[i]; return 0; } SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); curState = getState(); if (curState == Volume::State_NoMedia) { SLOGI("Mount fail caused by NoMedia! Update errno to ENODEV"); errno = ENODEV; } if ((curState != Volume::State_NoMedia) && (curState != Volume::State_Mounted)) { setState(Volume::State_Idle); } if(curState == Volume::State_Mounted) { return 0; } return -1; }
/* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc p; char *ttname; int num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = KI_MAXCOMLEN; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.p_comm, num); P->cmd[num] = '\0'; P->pid = p.p_pid; P->ppid = p.p_ppid; P->pgrp = p.p__pgid; P->session = p.p_sid; P->rss = p.p_vm_rssize; P->vsize = p.p_vm_dsize + p.p_vm_dsize + p.p_vm_ssize; /* XXX */ P->start_time = p.p_ustart_sec; P->wchan = (unsigned long) p.p_wchan; P->state = p.p_stat; P->nice = p.p_nice; P->flags = p.p_psflags; P->tpgid = p.p_tpgid; P->processor = p.p_cpuid; /* we like it Linux-encoded :-) */ tty_maj = major (p.p_tdev); tty_min = minor (p.p_tdev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); if (p.p_tdev != NODEV && (ttname = devname (p.p_tdev, S_IFCHR)) != NULL) { memcpy (P->tty_text, ttname, sizeof (P->tty_text)); } if (p.p_tdev == NODEV) { /* XXX how do we associate X with its tty? */ #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) memcpy (P->tty_text, "/dev/ttyC4", sizeof (P->tty_text)); #else memcpy (P->tty_text, "/dev/ttyC0", sizeof (P->tty_text)); #endif } if (P->pid != pid) { return FALSE; } return TRUE; }
/* Write out a tar header for the specified file/directory/whatever */ static int writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, const char *fileName, struct stat *statbuf) { struct tar_header_t header; memset(&header, 0, sizeof(header)); strncpy(header.name, header_name, sizeof(header.name)); /* POSIX says to mask mode with 07777. */ PUT_OCTAL(header.mode, statbuf->st_mode & 07777); PUT_OCTAL(header.uid, statbuf->st_uid); PUT_OCTAL(header.gid, statbuf->st_gid); memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ PUT_OCTAL(header.mtime, statbuf->st_mtime); /* Enter the user and group names */ safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname)); safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname)); if (tbInfo->hlInfo) { /* This is a hard link */ header.typeflag = LNKTYPE; strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* Write out long linkname if needed */ if (header.linkname[sizeof(header.linkname)-1]) writeLongname(tbInfo->tarFd, GNULONGLINK, tbInfo->hlInfo->name, 0); #endif } else if (S_ISLNK(statbuf->st_mode)) { char *lpath = xmalloc_readlink_or_warn(fileName); if (!lpath) return FALSE; header.typeflag = SYMTYPE; strncpy(header.linkname, lpath, sizeof(header.linkname)); #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* Write out long linkname if needed */ if (header.linkname[sizeof(header.linkname)-1]) writeLongname(tbInfo->tarFd, GNULONGLINK, lpath, 0); #else /* If it is larger than 100 bytes, bail out */ if (header.linkname[sizeof(header.linkname)-1]) { free(lpath); bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); return FALSE; } #endif free(lpath); } else if (S_ISDIR(statbuf->st_mode)) { header.typeflag = DIRTYPE; /* Append '/' only if there is a space for it */ if (!header.name[sizeof(header.name)-1]) header.name[strlen(header.name)] = '/'; } else if (S_ISCHR(statbuf->st_mode)) { header.typeflag = CHRTYPE; PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); } else if (S_ISBLK(statbuf->st_mode)) { header.typeflag = BLKTYPE; PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); } else if (S_ISFIFO(statbuf->st_mode)) { header.typeflag = FIFOTYPE; } else if (S_ISREG(statbuf->st_mode)) { /* header.size field is 12 bytes long */ /* Does octal-encoded size fit? */ uoff_t filesize = statbuf->st_size; if (sizeof(filesize) <= 4 || filesize <= (uoff_t)0777777777777LL ) { PUT_OCTAL(header.size, filesize); } /* Does base256-encoded size fit? * It always does unless off_t is wider than 64 bits. */ else if (ENABLE_FEATURE_TAR_GNU_EXTENSIONS #if ULLONG_MAX > 0xffffffffffffffffLL /* 2^64-1 */ && (filesize <= 0x3fffffffffffffffffffffffLL) #endif ) { /* GNU tar uses "base-256 encoding" for very large numbers. * Encoding is binary, with highest bit always set as a marker * and sign in next-highest bit: * 80 00 .. 00 - zero * bf ff .. ff - largest positive number * ff ff .. ff - minus 1 * c0 00 .. 00 - smallest negative number */ char *p8 = header.size + sizeof(header.size); do { *--p8 = (uint8_t)filesize; filesize >>= 8; } while (p8 != header.size); *p8 |= 0x80; } else {
static unsigned int walk_directory(struct imgspec* const spec, struct hostprog_path* const path, struct entry** previous) { struct dirent** dirlst; int dirlst_count; int dirlst_index; __u64 dir_sz = 0; __u64 dir_lvl = hostprog_path_lvls(path); dirlst_count = scandir(path->p_path, &dirlst, NULL, hostprog_scandirsort); if (dirlst_count < 0) error("failed to read \"%s\": %s", path->p_path, strerror(errno)); for (dirlst_index = 0; dirlst_index < dirlst_count; dirlst_index++) { struct dirent* dent = dirlst[dirlst_index]; /* Skip "." and ".." directories, just like mkcramfs. */ if (hostprog_path_dotdir(dent->d_name)) continue; hostprog_path_dirnamelvl(path, dir_lvl); if (hostprog_path_append(path, dent->d_name) != 0) error("failed to add a filename to the hostprog_path"); struct stat st; if (lstat(path->p_path, &st) < 0) { /* Maybe this should be an error? Files missing in the image * could possibly seem like an error to the user. */ warning("skipping \"unlstatable\" file \"%s\": %s", path->p_path, strerror(errno)); spec->sp_skipnodes++; continue; } if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { /* If the file is a regular file which can not be read, then * it might as well be skipped. * * This should also possibly be an error. */ if (access(path->p_path, R_OK) < 0) { warning("skipping unreadable file \"%s\": %s", path->p_path, strerror(errno)); spec->sp_skipnodes++; continue; } /* Completely empty files seems pretty pointless to include * in the image. */ if (!st.st_size) { message(VERBOSITY_1, ">>> skipping empty file \"%s\"", path->p_path); spec->sp_skipnodes++; continue; } } else if (!spec->sp_incsocks && S_ISSOCK(st.st_mode)) { warning("skipping socket \"%s\"", path->p_path); spec->sp_skipnodes++; continue; } /* Files should never be skipped after this point since that * would mess up the image size estimation. */ struct entry* ent = malloc(sizeof(*ent)); if (!ent) error("failed to alloc an entry for \"%s\"", path->p_path); memset(ent, 0, sizeof(*ent)); ent->e_name = strdup(dent->d_name); if (!ent->e_name) error("failed to copy the entry name for \"%s\"", path->p_path); ent->e_mode = st.st_mode; ent->e_size = st.st_size; ent->e_fd = -1; ENTRY_SET_XID(spec, ent, e_uid, st.st_uid, MICROFS_IUID_WIDTH); ENTRY_SET_XID(spec, ent, e_gid, st.st_gid, MICROFS_IGID_WIDTH); if (S_ISDIR(ent->e_mode)) { ent->e_size = walk_directory(spec, path, &ent->e_firstchild); } else if (S_ISREG(ent->e_mode) || S_ISLNK(ent->e_mode)) { if (ent->e_size > MICROFS_MAXFILESIZE) { error("\"%s\" is too big, max file size is %llu bytes", path->p_path, MICROFS_MAXFILESIZE); } else if (ent->e_size > MICROFS_MAXCRAMSIZE) { warning("\"%s\" is a big file, microfs works best with files" " smaller than %llu bytes", path->p_path, MICROFS_MAXCRAMSIZE); } ent->e_path = strdup(path->p_path); if (!ent->e_path) { error("failed to copy the entry path for \"%s\"", path->p_path); } if (spec->sp_shareblocks) { if (hostprog_stack_push(spec->sp_regstack, ent) < 0) error("failed to push an entry to the regular file stack: %s", strerror(errno)); } } else if (S_ISCHR(ent->e_mode) || S_ISBLK(ent->e_mode)) { ent->e_size = makedev_lim(major(st.st_rdev), minor(st.st_rdev), MICROFS_ISIZE_WIDTH); } else if (S_ISFIFO(ent->e_mode) || S_ISSOCK(ent->e_mode)) { ent->e_size = 0; } else { error("unexpected file mode encountered"); } /* %namelen() could actually fail here if the d_name is too * long, but that will terminate the program, so that is fine. */ dir_sz += update_upperbound(spec, ent, namelen(dent->d_name)); update_stats(spec, ent); message(VERBOSITY_1, "+ %c %s", nodtype(ent->e_mode), path->p_path); *previous = ent; previous = &ent->e_sibling; } free(dirlst); hostprog_path_dirnamelvl(path, dir_lvl); /* This should never happen, but if it ever does, it is * clearly an error. */ if (dir_sz > MICROFS_MAXDIRSIZE) { error("achievement unlocked: the directory size for \"%s\"" " is %llu bytes, the maximum supported size is %llu bytes" " - this is impressive in a very scary way", path->p_path, dir_sz, MICROFS_MAXDIRSIZE); } return dir_sz; }
/* * Returns true if dev is /dev/mem or /dev/kmem. */ int iskmemdev(dev_t dev) { return (major(dev) == 3 && minor(dev) < 2); }
/** * legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'. * @node: name of the MTD device node * @mtd: the MTD device information is returned here * * This function is similar to 'mtd_get_dev_info()' and has the same * conventions. */ int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd) { struct stat st; struct mtd_info_user ui; int fd, ret; loff_t offs = 0; struct proc_parse_info pi; if (stat(node, &st)) { sys_errmsg("cannot open \"%s\"", node); if (errno == ENOENT) normsg("MTD subsystem is old and does not support " "sysfs, so MTD character device nodes have " "to exist"); } if (!S_ISCHR(st.st_mode)) { errno = EINVAL; return errmsg("\"%s\" is not a character device", node); } memset(mtd, '\0', sizeof(struct mtd_dev_info)); mtd->major = major(st.st_rdev); mtd->minor = minor(st.st_rdev); if (mtd->major != MTD_DEV_MAJOR) { errno = EINVAL; return errmsg("\"%s\" has major number %d, MTD devices have " "major %d", node, mtd->major, MTD_DEV_MAJOR); } mtd->mtd_num = mtd->minor / 2; fd = open(node, O_RDONLY); if (fd == -1) return sys_errmsg("cannot open \"%s\"", node); if (ioctl(fd, MEMGETINFO, &ui)) { sys_errmsg("MEMGETINFO ioctl request failed"); goto out_close; } ret = ioctl(fd, MEMGETBADBLOCK, &offs); if (ret == -1) { if (errno != EOPNOTSUPP) { sys_errmsg("MEMGETBADBLOCK ioctl failed"); goto out_close; } errno = 0; mtd->bb_allowed = 0; } else mtd->bb_allowed = 1; mtd->type = ui.type; mtd->size = ui.size; mtd->eb_size = ui.erasesize; mtd->min_io_size = ui.writesize; mtd->oob_size = ui.oobsize; if (mtd->min_io_size <= 0) { errmsg("mtd%d (%s) has insane min. I/O unit size %d", mtd->mtd_num, node, mtd->min_io_size); goto out_close; } if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) { errmsg("mtd%d (%s) has insane eraseblock size %d", mtd->mtd_num, node, mtd->eb_size); goto out_close; } if (mtd->size <= 0 || mtd->size < mtd->eb_size) { errmsg("mtd%d (%s) has insane size %lld", mtd->mtd_num, node, mtd->size); goto out_close; } mtd->eb_cnt = mtd->size / mtd->eb_size; switch(mtd->type) { case MTD_ABSENT: errmsg("mtd%d (%s) is removable and is not present", mtd->mtd_num, node); goto out_close; case MTD_RAM: strcpy((char *)mtd->type_str, "ram"); break; case MTD_ROM: strcpy((char *)mtd->type_str, "rom"); break; case MTD_NORFLASH: strcpy((char *)mtd->type_str, "nor"); break; case MTD_NANDFLASH: strcpy((char *)mtd->type_str, "nand"); break; case MTD_MLCNANDFLASH: strcpy((char *)mtd->type_str, "mlc-nand"); break; case MTD_DATAFLASH: strcpy((char *)mtd->type_str, "dataflash"); break; case MTD_UBIVOLUME: strcpy((char *)mtd->type_str, "ubi"); break; default: goto out_close; } if (ui.flags & MTD_WRITEABLE) mtd->writable = 1; mtd->subpage_size = mtd->min_io_size; close(fd); ret = legacy_get_mtd_oobavail(node); mtd->oobavail = ret > 0 ? ret : 0; /* * Unfortunately, the device name is not available via ioctl, and * we have to parse /proc/mtd to get it. */ ret = proc_parse_start(&pi); if (ret) return -1; while (proc_parse_next(&pi)) { if (pi.mtd_num == mtd->mtd_num) { strcpy((char *)mtd->name, pi.name); return 0; } } errmsg("mtd%d not found in \"%s\"", mtd->mtd_num, MTD_PROC_FILE); errno = ENOENT; return -1; out_close: close(fd); return -1; }
setconf() { register struct hp_ctlr *hc; register struct hp_device *hd; register struct genericconf *gc; register char *cp; int unit, part, swaponroot = 0; if (rootdev != NODEV) goto doswap; unit = 0; part = 0; if (boothowto & RB_ASKNAME) { char name[128]; retry: printf("root device? "); gets(name); for (gc = genericconf; gc->gc_driver; gc++) if (gc->gc_name[0] == name[0] && gc->gc_name[1] == name[1]) goto gotit; printf("use one of:"); for (gc = genericconf; gc->gc_driver; gc++) printf(" %s%%d", gc->gc_name); printf("\n"); goto retry; gotit: cp = &name[2]; if (*cp < '0' || *cp > '9') { printf("bad/missing unit number\n"); goto retry; } while (*cp >= '0' && *cp <= '9') unit = 10 * unit + *cp++ - '0'; if (*cp < 'a' || *cp > 'h') { printf("bad/missing partiiton number\n"); goto retry; } part = *cp++ - 'a'; /* if (*cp == '*') swaponroot++; */ goto found; } for (gc = genericconf; gc->gc_driver; gc++) { for (hd = hp_dinit; hd->hp_driver; hd++) { if (hd->hp_alive == 0) continue; if (hd->hp_unit == 0 && hd->hp_driver == (struct driver *)gc->gc_driver) { printf("root on %s0\n", hd->hp_driver->d_name); goto found; } } } printf("no suitable root\n"); asm("stop #0x2700"); found: gc->gc_root = makedev(major(gc->gc_root), (unit * 8) + part ); rootdev = gc->gc_root; /* printf("using root device: %s%d%c\n", gc->gc_name, unit, 'a' + part); */ doswap: swdevt[0].sw_dev = argdev = dumpdev = makedev(major(rootdev), (minor(rootdev) & ~0x7) + 1); /* printf("using swap device: %s%d%c\n", gc->gc_name, unit, 'a' + (minor(swdevt[0].sw_dev) & 0x7)); */ /* swap size and dumplo set during autoconfigure */ if (swaponroot) rootdev = dumpdev; }
std::string api_version_to_string(int version) { if (major(version) == 0) return rsimpl::to_string() << version; return rsimpl::to_string() << major(version) << "." << minor(version) << "." << patch(version); }
/* ARGSUSED */ int bpfopen(dev_t dev, int flags, __unused int fmt, __unused struct proc *p) { struct bpf_d *d; lck_mtx_lock(bpf_mlock); if ((unsigned int) minor(dev) >= nbpfilter) { lck_mtx_unlock(bpf_mlock); return (ENXIO); } /* * New device nodes are created on demand when opening the last one. * The programming model is for processes to loop on the minor starting at 0 * as long as EBUSY is returned. The loop stops when either the open succeeds or * an error other that EBUSY is returned. That means that bpf_make_dev_t() must * block all processes that are opening the last node. If not all * processes are blocked, they could unexpectedly get ENOENT and abort their * opening loop. */ if ((unsigned int) minor(dev) == (nbpfilter - 1)) bpf_make_dev_t(major(dev)); /* * Each minor can be opened by only one process. If the requested * minor is in use, return EBUSY. * * Important: bpfopen() and bpfclose() have to check and set the status of a device * in the same lockin context otherwise the device may be leaked because the vnode use count * will be unpextectly greater than 1 when close() is called. */ if (bpf_dtab[minor(dev)] == 0) { bpf_dtab[minor(dev)] = (void *)1; /* Mark opening */ } else { lck_mtx_unlock(bpf_mlock); return (EBUSY); } d = (struct bpf_d *)_MALLOC(sizeof(struct bpf_d), M_DEVBUF, M_WAIT); if (d == NULL) { /* this really is a catastrophic failure */ printf("bpfopen: malloc bpf_d failed\n"); bpf_dtab[minor(dev)] = NULL; lck_mtx_unlock(bpf_mlock); return ENOMEM; } bzero(d, sizeof(struct bpf_d)); /* * It is not necessary to take the BPF lock here because no other * thread can access the device until it is marked opened... */ /* Mark "in use" and do most initialization. */ d->bd_bufsize = bpf_bufsize; d->bd_sig = SIGIO; d->bd_seesent = 1; d->bd_oflags = flags; #if CONFIG_MACF_NET mac_bpfdesc_label_init(d); mac_bpfdesc_label_associate(kauth_cred_get(), d); #endif bpf_dtab[minor(dev)] = d; /* Mark opened */ lck_mtx_unlock(bpf_mlock); return (0); }
/*===========================================================================* * mount_fs * *===========================================================================*/ int mount_fs( dev_t dev, char mountpoint[PATH_MAX], endpoint_t fs_e, int rdonly, char mount_label[LABEL_MAX] ) { int i, r = OK, found, isroot, mount_root, con_reqs, slot; struct fproc *tfp, *rfp; struct dmap *dp; struct vnode *root_node, *vp = NULL; struct vmnt *new_vmp, *parent_vmp; char *label; struct node_details res; struct lookup resolve; /* Look up block device driver label when dev is not a pseudo-device */ label = ""; if (!is_nonedev(dev)) { /* Get driver process' endpoint */ dp = &dmap[major(dev)]; if (dp->dmap_driver == NONE) { printf("VFS: no driver for dev %d\n", dev); return(EINVAL); } label = dp->dmap_label; assert(strlen(label) > 0); } /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/ found = FALSE; for (i = 0; i < NR_MNTS; ++i) { if (vmnt[i].m_dev == dev) found = TRUE; } if (found) { return(EBUSY); } else if ((new_vmp = get_free_vmnt()) == NULL) { return(ENOMEM); } if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r); isroot = (strcmp(mountpoint, "/") == 0); mount_root = (isroot && have_root < 2); /* Root can be mounted twice: * 1: ramdisk * 2: boot disk (e.g., harddisk) */ if (!mount_root) { /* Get vnode of mountpoint */ lookup_init(&resolve, mountpoint, PATH_NOFLAGS, &parent_vmp, &vp); resolve.l_vmnt_lock = VMNT_EXCL; resolve.l_vnode_lock = VNODE_WRITE; if ((vp = eat_path(&resolve, fp)) == NULL) r = err_code; else if (vp->v_ref_count == 1) { /*Tell FS on which vnode it is mounted (glue into mount tree)*/ r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr); } else r = EBUSY; if (vp != NULL) { /* Quickly unlock to allow back calls (from e.g. FUSE) to * relock */ unlock_vmnt(parent_vmp); } if (r != OK) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(r); } } /* We'll need a vnode for the root inode */ if ((root_node = get_free_vnode()) == NULL) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(err_code); } lock_vnode(root_node, VNODE_OPCL); /* Record process as a system process */ if (isokendpt(fs_e, &slot) != OK) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vnode(root_node); unlock_vmnt(new_vmp); return(EINVAL); } rfp = &fproc[slot]; rfp->fp_flags |= FP_SRV_PROC; /* File Servers are also services */ /* Store some essential vmnt data first */ new_vmp->m_fs_e = fs_e; new_vmp->m_dev = dev; if (rdonly) new_vmp->m_flags |= VMNT_READONLY; else new_vmp->m_flags &= ~VMNT_READONLY; /* Tell FS which device to mount */ new_vmp->m_flags |= VMNT_MOUNTING; r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs); new_vmp->m_flags &= ~VMNT_MOUNTING; if (r != OK) { mark_vmnt_free(new_vmp); unlock_vnode(root_node); if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(r); } lock_bsf(); /* Fill in root node's fields */ root_node->v_fs_e = res.fs_e; root_node->v_inode_nr = res.inode_nr; root_node->v_mode = res.fmode; root_node->v_uid = res.uid; root_node->v_gid = res.gid; root_node->v_size = res.fsize; root_node->v_sdev = NO_DEV; root_node->v_fs_count = 1; root_node->v_ref_count = 1; /* Root node is indeed on the partition */ root_node->v_vmnt = new_vmp; root_node->v_dev = new_vmp->m_dev; if (con_reqs == 0) new_vmp->m_comm.c_max_reqs = 1; /* Default if FS doesn't tell us */ else new_vmp->m_comm.c_max_reqs = con_reqs; new_vmp->m_comm.c_cur_reqs = 0; if (mount_root) { /* Superblock and root node already read. * Nothing else can go wrong. Perform the mount. */ new_vmp->m_root_node = root_node; new_vmp->m_mounted_on = NULL; strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); if (is_nonedev(dev)) alloc_nonedev(dev); update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); ROOT_DEV = dev; ROOT_FS_E = fs_e; /* Replace all root and working directories */ for (i = 0, tfp = fproc; i < NR_PROCS; i++, tfp++) { if (tfp->fp_pid == PID_FREE) continue; #define MAKEROOT(what) { \ if (what) put_vnode(what); \ dup_vnode(root_node); \ what = root_node; \ } MAKEROOT(tfp->fp_rd); MAKEROOT(tfp->fp_wd); } unlock_vnode(root_node); unlock_vmnt(new_vmp); have_root++; /* We have a (new) root */ unlock_bsf(); return(OK); } /* File types may not conflict. */ if (!S_ISDIR(vp->v_mode) && S_ISDIR(root_node->v_mode)) r = EISDIR; /* If error, return the super block and both inodes; release the vmnt. */ if (r != OK) { unlock_vnode(vp); unlock_vnode(root_node); mark_vmnt_free(new_vmp); unlock_vmnt(new_vmp); put_vnode(vp); put_vnode(root_node); unlock_bsf(); return(r); } /* Nothing else can go wrong. Perform the mount. */ new_vmp->m_mounted_on = vp; new_vmp->m_root_node = root_node; strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); /* Allocate the pseudo device that was found, if not using a real device. */ if (is_nonedev(dev)) alloc_nonedev(dev); /* The new FS will handle block I/O requests for its device now. */ if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF)) update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); unlock_vnode(vp); unlock_vnode(root_node); unlock_vmnt(new_vmp); unlock_bsf(); return(OK); }
int fstat(int fd, struct stat *st) { int ret; struct linux_stat lst; struct ifreq ifr; ret = syscall(SYS_fstat, fd, &lst); if (ret == -1) { errno = EBADF; return -1; } st->st_size = lst.st_size; switch (lst.st_mode & LINUX_S_IFMT) { case LINUX_S_IFSOCK: __platform_socket_fd = fd; /* currently no support for raw socket networking */ lst.st_mode = 0; break; case LINUX_S_IFBLK: syscall(SYS_ioctl, fd, BLKGETSIZE64, &st->st_size); break; case LINUX_S_IFCHR: /* macvtap has a dynamic major number, so hard to test */ if (lst.st_rdev != makedev(10, 200) && major(lst.st_rdev) < 128) break; ret = syscall(SYS_ioctl, fd, TUNGETIFF, &ifr); if (ret == 0) { /* we do not yet support macvtap offload facilities */ if (ifr.ifr_flags & IFF_VNET_HDR) { ifr.ifr_flags &= ~IFF_VNET_HDR; syscall(SYS_ioctl, fd, TUNSETIFF, &ifr); } /* use sock type to tell config we are network */ lst.st_mode = LINUX_S_IFSOCK; /* find mac address */ ret = syscall(SYS_ioctl, fd, SIOCGIFHWADDR, &ifr); if (ret == -1 && __platform_socket_fd != -1) ret = syscall(SYS_ioctl, __platform_socket_fd, SIOCGIFHWADDR, &ifr); if (ret == 0) { memcpy(st->st_hwaddr, ifr.ifr_addr.sa_data, 6); } __platform_pollfd[__platform_npoll].fd = fd; __platform_pollfd[__platform_npoll].events = POLLIN | POLLPRI; __platform_npoll++; } break; } st->st_mode = (LINUX_S_ISDIR (lst.st_mode) ? S_IFDIR : 0) | (LINUX_S_ISCHR (lst.st_mode) ? S_IFCHR : 0) | (LINUX_S_ISBLK (lst.st_mode) ? S_IFBLK : 0) | (LINUX_S_ISREG (lst.st_mode) ? S_IFREG : 0) | (LINUX_S_ISFIFO(lst.st_mode) ? S_IFIFO : 0) | (LINUX_S_ISLNK (lst.st_mode) ? S_IFLNK : 0) | (LINUX_S_ISSOCK(lst.st_mode) ? S_IFSOCK : 0); /* if we are passed in /dev/urandom use as a random source */ if (LINUX_S_ISCHR(lst.st_mode) && lst.st_rdev == makedev(1, 9)) __platform_random_fd = fd; return 0; }
static void device_added(struct udev_device *udev_device) { const char *path, *name = NULL; char *config_info = NULL; const char *syspath; const char *tags_prop; const char *key, *value, *tmp; InputOption *input_options; InputAttributes attrs = { }; DeviceIntPtr dev = NULL; struct udev_list_entry *set, *entry; struct udev_device *parent; int rc; dev_t devnum; path = udev_device_get_devnode(udev_device); syspath = udev_device_get_syspath(udev_device); if (!path || !syspath) return; if (!check_seat(udev_device)) return; devnum = udev_device_get_devnum(udev_device); #ifdef CONFIG_UDEV_KMS if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) { const char *sysname = udev_device_get_sysname(udev_device); if (strncmp(sysname, "card", 4) != 0) return; /* Check for devices already added through xf86platformProbe() */ if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum))) return; LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path); config_udev_odev_setup_attribs(path, syspath, major(devnum), minor(devnum), NewGPUDeviceRequest); return; } #endif if (!udev_device_get_property_value(udev_device, "ID_INPUT")) { LogMessageVerb(X_INFO, 10, "config/udev: ignoring device %s without " "property ID_INPUT set\n", path); return; } input_options = input_option_new(NULL, "_source", "server/udev"); if (!input_options) return; parent = udev_device_get_parent(udev_device); if (parent) { const char *ppath = udev_device_get_devnode(parent); const char *product = udev_device_get_property_value(parent, "PRODUCT"); const char *pnp_id = udev_device_get_sysattr_value(parent, "id"); unsigned int usb_vendor, usb_model; name = udev_device_get_sysattr_value(parent, "name"); LOG_SYSATTR(ppath, "name", name); if (!name) { name = udev_device_get_property_value(parent, "NAME"); LOG_PROPERTY(ppath, "NAME", name); } /* construct USB ID in lowercase hex - "0000:ffff" */ if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { char *usb_id; if (asprintf(&usb_id, "%04x:%04x", usb_vendor, usb_model) == -1) usb_id = NULL; else LOG_PROPERTY(ppath, "PRODUCT", product); attrs.usb_id = usb_id; } while (!pnp_id && (parent = udev_device_get_parent(parent))) { pnp_id = udev_device_get_sysattr_value(parent, "id"); if (!pnp_id) continue; attrs.pnp_id = strdup(pnp_id); ppath = udev_device_get_devnode(parent); LOG_SYSATTR(ppath, "id", pnp_id); } } if (!name) name = "(unnamed)"; else attrs.product = strdup(name); input_options = input_option_new(input_options, "name", name); input_options = input_option_new(input_options, "path", path); input_options = input_option_new(input_options, "device", path); input_options = input_option_new(input_options, "major", itoa(major(devnum))); input_options = input_option_new(input_options, "minor", itoa(minor(devnum))); if (path) attrs.device = strdup(path); tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags"); LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop); attrs.tags = xstrtokenize(tags_prop, ","); if (asprintf(&config_info, "udev:%s", syspath) == -1) { config_info = NULL; goto unwind; } if (device_is_duplicate(config_info)) { LogMessage(X_WARNING, "config/udev: device %s already added. " "Ignoring.\n", name); goto unwind; } set = udev_device_get_properties_list_entry(udev_device); udev_list_entry_foreach(entry, set) { key = udev_list_entry_get_name(entry); if (!key) continue; value = udev_list_entry_get_value(entry); if (!strncasecmp(key, UDEV_XKB_PROP_KEY, sizeof(UDEV_XKB_PROP_KEY) - 1)) { LOG_PROPERTY(path, key, value); tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1; if (!strcasecmp(tmp, "rules")) input_options = input_option_new(input_options, "xkb_rules", value); else if (!strcasecmp(tmp, "layout")) input_options = input_option_new(input_options, "xkb_layout", value); else if (!strcasecmp(tmp, "variant")) input_options = input_option_new(input_options, "xkb_variant", value); else if (!strcasecmp(tmp, "model")) input_options = input_option_new(input_options, "xkb_model", value); else if (!strcasecmp(tmp, "options")) input_options = input_option_new(input_options, "xkb_options", value); } else if (!strcmp(key, "ID_VENDOR")) { LOG_PROPERTY(path, key, value); attrs.vendor = strdup(value); } else if (!strcmp(key, "ID_INPUT_KEY")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_KEY; } else if (!strcmp(key, "ID_INPUT_KEYBOARD")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_KEYBOARD; } else if (!strcmp(key, "ID_INPUT_MOUSE")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_POINTER; } else if (!strcmp(key, "ID_INPUT_JOYSTICK")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_JOYSTICK; } else if (!strcmp(key, "ID_INPUT_TABLET")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TABLET; } else if (!strcmp(key, "ID_INPUT_TABLET_PAD")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TABLET_PAD; } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHPAD; } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHSCREEN; } }
setconf() { #if NMBA > 0 register struct mba_device *mi; #endif register struct uba_device *ui; register struct genericconf *gc; register char *cp, *gp; int unit, swaponroot = 0; if (rootdev != NODEV) goto doswap; unit = 0; if (boothowto & RB_ASKNAME) { char name[128]; retry: printf("root device? "); gets(name); for (gc = genericconf; gc->gc_driver; gc++) for (cp = name, gp = gc->gc_name; *cp == *gp; cp++) if (*++gp == 0) goto gotit; printf( "use hp%%d, up%%d, ra%%d, rb%%d, rl%%d, hk%%d or kra%%d\n"); goto retry; gotit: if (*++cp < '0' || *cp > '9') { printf("bad/missing unit number\n"); goto retry; } while (*cp >= '0' && *cp <= '9') unit = 10 * unit + *cp++ - '0'; if (*cp == '*') swaponroot++; goto found; } for (gc = genericconf; gc->gc_driver; gc++) { #if NMBA > 0 for (mi = mbdinit; mi->mi_driver; mi++) { if (mi->mi_alive == 0) continue; if (mi->mi_unit == unit && mi->mi_driver == (struct mba_driver *)gc->gc_driver) { printf("root on %s%d\n", mi->mi_driver->md_dname, unit); goto found; } } #endif for (ui = ubdinit; ui->ui_driver; ui++) { if (ui->ui_alive == 0) continue; if (ui->ui_unit == unit && ui->ui_driver == (struct uba_driver *)gc->gc_driver) { printf("root on %s%d\n", ui->ui_driver->ud_dname, unit); goto found; } } } printf("no suitable root\n"); asm("halt"); found: gc->gc_root = makedev(major(gc->gc_root), unit*8); rootdev = gc->gc_root; doswap: swdevt[0].sw_dev = argdev = dumpdev = makedev(major(rootdev), minor(rootdev)+1); /* swap size and dumplo set during autoconfigure */ if (swaponroot) rootdev = dumpdev; }
static bool rm_mounts_create_tables(RmMountTable *self) { /* partition dev_t to disk dev_t */ self->part_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)rm_part_info_free); /* disk dev_t to boolean indication if disk is rotational */ self->disk_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)rm_disk_info_free); self->nfs_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); /* Mapping dev_t => true (used as set) */ self->evilfs_table = g_hash_table_new(NULL, NULL); RmMountEntry *entry = NULL; RmMountEntries *mnt_entries = rm_mount_list_open(self); if(mnt_entries == NULL) { return false; } while((entry = rm_mount_list_next(mnt_entries))) { RmStat stat_buf_folder; if(rm_sys_stat(entry->dir, &stat_buf_folder) == -1) { continue; } dev_t whole_disk = 0; gchar is_rotational = true; char diskname[PATH_MAX]; memset(diskname, 0, sizeof(diskname)); RmStat stat_buf_dev; if(rm_sys_stat(entry->fsname, &stat_buf_dev) == -1) { char *nfs_marker = NULL; /* folder rm_sys_stat() is ok but devname rm_sys_stat() is not; this happens for example * with tmpfs and with nfs mounts. Try to handle a few such cases. * */ if(rm_mounts_is_ramdisk(entry->fsname)) { strncpy(diskname, entry->fsname, sizeof(diskname)); is_rotational = false; whole_disk = stat_buf_folder.st_dev; } else if((nfs_marker = strstr(entry->fsname, ":/")) != NULL) { size_t until_slash = MIN((int)sizeof(entry->fsname), nfs_marker - entry->fsname); strncpy(diskname, entry->fsname, until_slash); is_rotational = true; /* Assign different dev ids (with major id 0) to different nfs servers */ if(!g_hash_table_contains(self->nfs_table, diskname)) { g_hash_table_insert(self->nfs_table, g_strdup(diskname), NULL); } whole_disk = makedev(0, g_hash_table_size(self->nfs_table)); } else { strncpy(diskname, "unknown", sizeof(diskname)); is_rotational = true; whole_disk = 0; } } else { if(rm_mounts_devno_to_wholedisk( entry, stat_buf_dev.st_rdev, diskname, sizeof(diskname), &whole_disk ) == -1) { /* folder and devname rm_sys_stat() are ok but blkid failed; this happens when? * Treat as a non-rotational device using devname dev as whole_disk key * */ rm_log_debug(RED"devno_to_wholedisk failed for %s\n"RESET, entry->fsname); whole_disk = stat_buf_dev.st_dev; strncpy(diskname, entry->fsname, sizeof(diskname)); is_rotational = false; } else { is_rotational = rm_mounts_is_rotational_blockdev(diskname); } } g_hash_table_insert( self->part_table, GUINT_TO_POINTER(stat_buf_folder.st_dev), rm_part_info_new (entry->dir, whole_disk)); /* small hack, so also the full disk id can be given to the api below */ if (!g_hash_table_contains(self->part_table, GINT_TO_POINTER(whole_disk))) { g_hash_table_insert( self->part_table, GUINT_TO_POINTER(whole_disk), rm_part_info_new (entry->dir, whole_disk)); } if (!g_hash_table_contains(self->disk_table, GINT_TO_POINTER(whole_disk))) { g_hash_table_insert( self->disk_table, GINT_TO_POINTER(whole_disk), rm_disk_info_new(diskname, is_rotational)); } rm_log_info("%02u:%02u %50s -> %02u:%02u %-12s (underlying disk: %s; rotational: %3s\n)", major(stat_buf_folder.st_dev), minor(stat_buf_folder.st_dev), entry->dir, major(whole_disk), minor(whole_disk), entry->fsname, diskname, is_rotational ? "yes" : "no" ); } #if HAVE_SYSCTL if(DISK_TABLE) { g_hash_table_unref(DISK_TABLE); } #endif rm_mount_list_close(mnt_entries); return true; }
int main (int argc, char *argv[]) { get_options (argc, argv); struct statfs fsbuf; float disktotal, diskfree, diskused; int diskpercent; if (statfs (mountpath, &fsbuf) < 0) exit (2); float mbratio = ((float)fsbuf.f_bsize) / 1048576.0; disktotal = (fsbuf.f_blocks * mbratio) / 1024.0; diskfree = (fsbuf.f_bfree * mbratio) / 1024.0; diskused = disktotal - diskfree; diskpercent = (100 * (fsbuf.f_blocks - fsbuf.f_bfree)) / fsbuf.f_blocks; /* For hddtemp, the mount path needs to be looked up in a mount table to find * the corresponding device. To speed things up when the monitor is run again, the * device path is available from the cache. Repeated mount table scans avoided. */ struct stat mountstat; if (stat (mountpath, &mountstat) < 0) exit (3); char cachepath[256], cachedisk[256], buffer[256], mntbuffer[256]; float maxdisktemp = 0.0, disktemp = 0.0; int cacheupdate = 0, ret; struct mntent mountent; char *diskpath = NULL; FILE *file; sprintf (cachepath, "/dev/shm/diskinfo.%d.%d.%d", major (mountstat.st_dev), minor (mountstat.st_dev), getuid ()); /* If the cache exists, read it instead of scanning the mount table. The device * path is added to the cache the first time the monitor is run. If the cache does * not yet exist, then need to scan a mount table to find the device path. */ if ((file = fopen (cachepath, "r"))) { char cachemount[256]; fgets (buffer, 256, file); ret = sscanf (buffer, "%s %s %f", cachemount, cachedisk, &maxdisktemp); assert (ret == 3); fclose (file); assert (strcmp (mountpath, cachemount) == 0); diskpath = cachedisk; } else /* Scan a mount table to get the device path */ { struct stat mntstat; file = setmntent ("/proc/mounts", "r"); assert (file != NULL); while (getmntent_r (file, &mountent, mntbuffer, 256)) { if (stat (mountent.mnt_dir, &mntstat)) continue; /* NB: Will looking for an entry beginning with slash always work? */ if (mountstat.st_dev == mntstat.st_dev && mountent.mnt_fsname[0] == '/') { diskpath = mountent.mnt_fsname; break; } } endmntent (file); cacheupdate = 1; } assert (diskpath != NULL); /* Get the current temperature of the disk. Use hddtemp for this because is has a * reference database for most HDDs. Might be quicker to consult the daemonized version * of hddtemp, will debate that idea for a future modification to this program. However, * because this program is intended to be run only infrequently say every 30 seconds there * is not all that much overhead in piping input from hddtemp. And there are minimal * processes that need to be left running all the time when using a pipe. */ char hddtemp[256], *ID = NULL; sprintf (hddtemp, "/usr/sbin/hddtemp %s", diskpath); if ((file = popen (hddtemp, "r"))) { char *temp; fgets (buffer, 256, file); pclose (file); temp = strstr((ID = strstr(buffer, ": ") + 2), ": ") + 2; *(temp - 2) = temp[strlen (temp) - 1] = '\0'; disktemp = atof (temp); if (disktemp > maxdisktemp) { maxdisktemp = disktemp; cacheupdate = 1; } } assert (ID != NULL); /* Create a new cache or update the cache if there is new maximum disk * temperature. Avoid unnecessary cache writes. */ if (cacheupdate) if ((file = fopen (cachepath, "w"))) { fprintf (file, "%s %s %f\n", mountpath, diskpath, maxdisktemp); fclose (file); } /* Recalculate temperatures as farenheit */ char CF = 'C'; if (showfarenheit) { CF = 'F'; disktemp = (disktemp * 1.8) + 32.0; maxdisktemp = (maxdisktemp * 1.8) + 32.0; } /** XFCE GENMON XML **/ /* Icon */ printf ("<img>%s</img>\n", iconfile); /* Text */ printf ("<txt>%sG\n%d°%c</txt>\n", du(diskused), (int)disktemp, CF); /* Tool tip */ printf ("<tool>ID: %s\n", ID); printf ("Mount: %s Device: %s\n", mountpath, diskpath); printf ("Total: %.2fG Available: %.2fG Used: %.2fG (%d%%)\n", disktotal, diskfree, diskused, diskpercent); printf ("Maximum temperature observed: %d°%c</tool>\n", (int)maxdisktemp, CF); /* Percent bar */ if (showbar) printf ("<bar>%d</bar>\n", diskpercent); return 0; }
/* * Display() takes a linked list of FTSENT structures and passes the list * along with any other necessary information to the print function. P * points to the parent directory of the display list. */ static void display(FTSENT *p, FTSENT *list) { struct stat *sp; DISPLAY d; FTSENT *cur; NAMES *np; u_int64_t btotal, stotal; off_t maxsize; blkcnt_t maxblock; ino_t maxinode; int maxmajor, maxminor; uint32_t maxnlink; int bcfile, entries, flen, glen, ulen, maxflags, maxgroup; unsigned int maxlen; int maxuser, needstats; const char *user, *group; char buf[21]; /* 64 bits == 20 digits, +1 for NUL */ char nuser[12], ngroup[12]; char *flags = NULL; /* * If list is NULL there are two possibilities: that the parent * directory p has no children, or that fts_children() returned an * error. We ignore the error case since it will be replicated * on the next call to fts_read() on the post-order visit to the * directory p, and will be signalled in traverse(). */ if (list == NULL) return; needstats = f_inode || f_longform || f_size; flen = 0; maxinode = maxnlink = 0; bcfile = 0; maxuser = maxgroup = maxflags = maxlen = 0; btotal = stotal = maxblock = maxsize = 0; maxmajor = maxminor = 0; for (cur = list, entries = 0; cur; cur = cur->fts_link) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { warnx("%s: %s", cur->fts_name, strerror(cur->fts_errno)); cur->fts_number = NO_PRINT; rval = EXIT_FAILURE; continue; } /* * P is NULL if list is the argv list, to which different rules * apply. */ if (p == NULL) { /* Directories will be displayed later. */ if (cur->fts_info == FTS_D && !f_listdir) { cur->fts_number = NO_PRINT; continue; } } else { /* Only display dot file if -a/-A set. */ if (cur->fts_name[0] == '.' && !f_listdot) { cur->fts_number = NO_PRINT; continue; } } if (cur->fts_namelen > maxlen) maxlen = cur->fts_namelen; if (needstats) { sp = cur->fts_statp; if (sp->st_blocks > maxblock) maxblock = sp->st_blocks; if (sp->st_ino > maxinode) maxinode = sp->st_ino; if (sp->st_nlink > maxnlink) maxnlink = sp->st_nlink; if (sp->st_size > maxsize) maxsize = sp->st_size; if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) { bcfile = 1; if (major(sp->st_rdev) > maxmajor) maxmajor = major(sp->st_rdev); if (minor(sp->st_rdev) > maxminor) maxminor = minor(sp->st_rdev); } btotal += sp->st_blocks; stotal += sp->st_size; if (f_longform) { if (f_numericonly || (user = user_from_uid(sp->st_uid, 0)) == NULL) { (void)snprintf(nuser, sizeof(nuser), "%u", sp->st_uid); user = nuser; } if (f_numericonly || (group = group_from_gid(sp->st_gid, 0)) == NULL) { (void)snprintf(ngroup, sizeof(ngroup), "%u", sp->st_gid); group = ngroup; } if ((ulen = strlen(user)) > maxuser) maxuser = ulen; if ((glen = strlen(group)) > maxgroup) maxgroup = glen; if (f_flags) { flags = flags_to_string((u_long)sp->st_flags, "-"); if ((flen = strlen(flags)) > maxflags) maxflags = flen; } else flen = 0; if ((np = malloc(sizeof(NAMES) + ulen + glen + flen + 2)) == NULL) err(EXIT_FAILURE, NULL); np->user = &np->data[0]; (void)strcpy(np->user, user); np->group = &np->data[ulen + 1]; (void)strcpy(np->group, group); if (f_flags) { np->flags = &np->data[ulen + glen + 2]; (void)strcpy(np->flags, flags); free(flags); } cur->fts_pointer = np; } } ++entries; } if (!entries) return; d.list = list; d.entries = entries; d.maxlen = maxlen; if (needstats) { d.btotal = btotal; d.stotal = stotal; if (f_humanize) { d.s_block = 4; /* min buf length for humanize_number */ } else { (void)snprintf(buf, sizeof(buf), "%llu", (long long)howmany(maxblock, blocksize)); d.s_block = strlen(buf); if (f_commas) /* allow for commas before every third digit */ d.s_block += (d.s_block - 1) / 3; } d.s_flags = maxflags; d.s_group = maxgroup; (void)snprintf(buf, sizeof(buf), "%llu", (unsigned long long)maxinode); d.s_inode = strlen(buf); (void)snprintf(buf, sizeof(buf), "%u", maxnlink); d.s_nlink = strlen(buf); if (f_humanize) { d.s_size = 4; /* min buf length for humanize_number */ } else { (void)snprintf(buf, sizeof(buf), "%llu", (long long)maxsize); d.s_size = strlen(buf); if (f_commas) /* allow for commas before every third digit */ d.s_size += (d.s_size - 1) / 3; } d.s_user = maxuser; if (bcfile) { (void)snprintf(buf, sizeof(buf), "%u", maxmajor); d.s_major = strlen(buf); (void)snprintf(buf, sizeof(buf), "%u", maxminor); d.s_minor = strlen(buf); if (d.s_major + d.s_minor + 2 > d.s_size) d.s_size = d.s_major + d.s_minor + 2; else if (d.s_size - d.s_minor - 2 > d.s_major) d.s_major = d.s_size - d.s_minor - 2; } else { d.s_major = 0; d.s_minor = 0; } } printfcn(&d); output = 1; if (f_longform) for (cur = list; cur; cur = cur->fts_link) free(cur->fts_pointer); }
int rpmcpioHeaderWrite(rpmcpio_t cpio, char * path, struct stat * st) { struct cpioCrcPhysicalHeader hdr_s; struct cpioCrcPhysicalHeader * hdr = &hdr_s; char field[64]; size_t len, written; dev_t dev; int rc = 0; if ((cpio->mode & O_ACCMODE) != O_WRONLY) { return RPMERR_WRITE_FAILED; } if (cpio->fileend != cpio->offset) { return RPMERR_WRITE_FAILED; } if (st->st_size >= CPIO_FILESIZE_MAX) { return RPMERR_FILE_SIZE; } rc = rpmcpioWritePad(cpio, 4); if (rc) { return rc; } SET_NUM_FIELD(hdr->inode, st->st_ino, field); SET_NUM_FIELD(hdr->mode, st->st_mode, field); SET_NUM_FIELD(hdr->uid, st->st_uid, field); SET_NUM_FIELD(hdr->gid, st->st_gid, field); SET_NUM_FIELD(hdr->nlink, st->st_nlink, field); SET_NUM_FIELD(hdr->mtime, st->st_mtime, field); SET_NUM_FIELD(hdr->filesize, st->st_size, field); dev = major(st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field); dev = minor(st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field); dev = major(st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field); dev = minor(st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field); len = strlen(path) + 1; SET_NUM_FIELD(hdr->namesize, len, field); memcpy(hdr->checksum, "00000000", 8); written = Fwrite(CPIO_NEWC_MAGIC, 6, 1, cpio->fd); cpio->offset += written; if (written != 6) { return RPMERR_WRITE_FAILED; } written = Fwrite(hdr, PHYS_HDR_SIZE, 1, cpio->fd); cpio->offset += written; if (written != PHYS_HDR_SIZE) { return RPMERR_WRITE_FAILED; } written = Fwrite(path, len, 1, cpio->fd); cpio->offset += written; if (written != len) { return RPMERR_WRITE_FAILED; } rc = rpmcpioWritePad(cpio, 4); cpio->fileend = cpio->offset + st->st_size; return rc; }
/* Create a device file named FILE_NAME, with permission and special bits MODE and device number DEV (which can be constructed from major and minor device numbers with the `makedev' macro above). */ int __xmknod (int vers, const char *file_name, mode_t mode, dev_t *dev) { error_t err; file_t dir, node; char *name; char buf[100], *bp; const char *translator; size_t len; if (vers != _MKNOD_VER) return __hurd_fail (EINVAL); if (S_ISCHR (mode)) { translator = _HURD_CHRDEV; len = sizeof (_HURD_CHRDEV); } else if (S_ISBLK (mode)) { translator = _HURD_BLKDEV; len = sizeof (_HURD_BLKDEV); } else if (S_ISFIFO (mode)) { translator = _HURD_FIFO; len = sizeof (_HURD_FIFO); } else { errno = EINVAL; return -1; } if (! S_ISFIFO (mode)) { /* We set the translator to "ifmt\0major\0minor\0", where IFMT depends on the S_IFMT bits of our MODE argument, and MAJOR and MINOR are ASCII decimal (octal or hex would do as well) representations of our arguments. Thus the convention is that CHRDEV and BLKDEV translators are invoked with two non-switch arguments, giving the major and minor device numbers in %i format. */ bp = buf + sizeof (buf); *--bp = '\0'; bp = _itoa (minor (*dev), bp, 10, 0); *--bp = '\0'; bp = _itoa (major (*dev), bp, 10, 0); memcpy (bp - len, translator, len); translator = bp - len; len = buf + sizeof (buf) - translator; } dir = __file_name_split (file_name, &name); if (dir == MACH_PORT_NULL) return -1; /* Create a new, unlinked node in the target directory. */ err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node); if (! err) /* Set the node's translator to make it a device. */ err = __file_set_translator (node, FS_TRANS_EXCL | FS_TRANS_SET, FS_TRANS_EXCL | FS_TRANS_SET, 0, translator, len, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); if (! err) /* Link the node, now a valid device, into the target directory. */ err = __dir_link (dir, node, name, 1); __mach_port_deallocate (__mach_task_self (), dir); __mach_port_deallocate (__mach_task_self (), node); if (err) return __hurd_fail (err); return 0; }
/*===========================================================================* * lmfs_rw_scattered * *===========================================================================*/ void lmfs_rw_scattered( dev_t dev, /* major-minor device number */ struct buf **bufq, /* pointer to array of buffers */ int bufqsize, /* number of buffers */ int rw_flag /* READING or WRITING */ ) { /* Read or write scattered data from a device. */ register struct buf *bp; int gap; register int i; register iovec_t *iop; static iovec_t iovec[NR_IOREQS]; off_t pos; int iov_per_block; int start_in_use = bufs_in_use, start_bufqsize = bufqsize; assert(bufqsize >= 0); if(bufqsize == 0) return; /* for READING, check all buffers on the list are obtained and held * (count > 0) */ if (rw_flag == READING) { for(i = 0; i < bufqsize; i++) { assert(bufq[i] != NULL); assert(bufq[i]->lmfs_count > 0); } /* therefore they are all 'in use' and must be at least this many */ assert(start_in_use >= start_bufqsize); } assert(dev != NO_DEV); assert(fs_block_size > 0); iov_per_block = roundup(fs_block_size, PAGE_SIZE) / PAGE_SIZE; assert(iov_per_block < NR_IOREQS); /* (Shell) sort buffers on lmfs_blocknr. */ gap = 1; do gap = 3 * gap + 1; while (gap <= bufqsize); while (gap != 1) { int j; gap /= 3; for (j = gap; j < bufqsize; j++) { for (i = j - gap; i >= 0 && bufq[i]->lmfs_blocknr > bufq[i + gap]->lmfs_blocknr; i -= gap) { bp = bufq[i]; bufq[i] = bufq[i + gap]; bufq[i + gap] = bp; } } } /* Set up I/O vector and do I/O. The result of bdev I/O is OK if everything * went fine, otherwise the error code for the first failed transfer. */ while (bufqsize > 0) { int nblocks = 0, niovecs = 0; int r; for (iop = iovec; nblocks < bufqsize; nblocks++) { int p; vir_bytes vdata, blockrem; bp = bufq[nblocks]; if (bp->lmfs_blocknr != (block_t) bufq[0]->lmfs_blocknr + nblocks) break; if(niovecs >= NR_IOREQS-iov_per_block) break; vdata = (vir_bytes) bp->data; blockrem = fs_block_size; for(p = 0; p < iov_per_block; p++) { vir_bytes chunk = blockrem < PAGE_SIZE ? blockrem : PAGE_SIZE; iop->iov_addr = vdata; iop->iov_size = chunk; vdata += PAGE_SIZE; blockrem -= chunk; iop++; niovecs++; } assert(p == iov_per_block); assert(blockrem == 0); } assert(nblocks > 0); assert(niovecs > 0); pos = (off_t)bufq[0]->lmfs_blocknr * fs_block_size; if (rw_flag == READING) r = bdev_gather(dev, pos, iovec, niovecs, BDEV_NOFLAGS); else r = bdev_scatter(dev, pos, iovec, niovecs, BDEV_NOFLAGS); /* Harvest the results. The driver may have returned an error, or it * may have done less than what we asked for. */ if (r < 0) { printf("fs cache: I/O error %d on device %d/%d, block %u\n", r, major(dev), minor(dev), bufq[0]->lmfs_blocknr); } for (i = 0; i < nblocks; i++) { bp = bufq[i]; if (r < (ssize_t) fs_block_size) { /* Transfer failed. */ if (i == 0) { bp->lmfs_dev = NO_DEV; /* Invalidate block */ } break; } if (rw_flag == READING) { bp->lmfs_dev = dev; /* validate block */ lmfs_put_block(bp, PARTIAL_DATA_BLOCK); } else { MARKCLEAN(bp); } r -= fs_block_size; } bufq += i; bufqsize -= i; if (rw_flag == READING) { /* Don't bother reading more than the device is willing to * give at this time. Don't forget to release those extras. */ while (bufqsize > 0) { lmfs_put_block(*bufq++, PARTIAL_DATA_BLOCK); bufqsize--; } } if (rw_flag == WRITING && i == 0) { /* We're not making progress, this means we might keep * looping. Buffers remain dirty if un-written. Buffers are * lost if invalidate()d or LRU-removed while dirty. This * is better than keeping unwritable blocks around forever.. */ break; } } if(rw_flag == READING) { assert(start_in_use >= start_bufqsize); /* READING callers assume all bufs are released. */ assert(start_in_use - start_bufqsize == bufs_in_use); } }
/* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; int err; struct stat st; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } #if defined __sun /* Solaris */ if (fstat (fd, &st) < 0) return errno; if (!(S_ISCHR (st.st_mode) && major (st.st_rdev) == 0)) { errno = ENOTTY; return errno; } { /* Master ptys can be recognized through a STREAMS ioctl. See "STREAMS-based Pseudo-Terminal Subsystem" <http://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html> and "STREAMS ioctl commands" <http://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html> */ struct strioctl ioctl_arg; ioctl_arg.ic_cmd = ISPTM; ioctl_arg.ic_timout = 0; ioctl_arg.ic_len = 0; ioctl_arg.ic_dp = NULL; if (ioctl (fd, I_STR, &ioctl_arg) < 0) { errno = ENOTTY; return errno; } } { char tmpbuf[9 + 10 + 1]; int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #elif defined _AIX || defined __osf__ /* AIX, OSF/1 */ /* This implementation returns /dev/pts/N, like ptsname() does. Whereas the generic implementation below returns /dev/ttypN. Both are correct, but let's be consistent with ptsname(). */ if (fstat (fd, &st) < 0) return errno; if (!S_ISCHR (st.st_mode)) { errno = ENOTTY; return errno; } { int ret; int dev; char tmpbuf[9 + 10 + 1]; int n; # ifdef _AIX ret = ioctl (fd, ISPTM, &dev); # endif # ifdef __osf__ ret = ioctl (fd, ISPTM, NULL); dev = ret; # endif if (ret < 0) { errno = ENOTTY; return errno; } n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #else if (!__isatty (fd)) { #if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */ /* Set errno. */ if (fcntl (fd, F_GETFL) != -1) errno = ENOTTY; #else /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ #endif return errno; } if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } err = __ttyname_r (fd, buf, buflen); if (err != 0) { __set_errno (err); return errno; } if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0) buf[sizeof (_PATH_DEV) - 1] = 't'; #endif if (__stat (buf, &st) < 0) return errno; __set_errno (save_errno); return 0; }
static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *name, *node, *pttype, *devtype; int boot_nr = -1, home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); name = udev_device_get_devnode(d); if (!name) name = udev_device_get_syspath(d); if (!name) { log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum)); return 0; } parent = udev_device_get_parent(d); if (!parent) { log_debug("%s: not a partitioned device, ignoring.", name); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("%s: parent doesn't have a device type, ignoring.", name); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("%s: parent isn't a raw disk, ignoring.", name); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("%s: parent device does not have device node, ignoring.", name); return 0; } log_debug("%s: root device %s.", name, node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to allocate prober: %m", node); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == 1) return 0; /* no results */ else if (r == -2) { log_warning("%s: probe gave ambiguous results, ignoring", node); return 0; } else if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node); errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to determine partition table type: %m", node); /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("%s: not a GPT partition table, ignoring.", node); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to list partitions: %m", node); } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "%s: failed to enumerate partitions: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; flags = blkid_partition_get_flags(pp); if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_NO_AUTO) continue; if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_ESP)) { /* We only care for the first /boot partition */ if (boot && nr >= boot_nr) continue; /* Note that we do not honour the "no-auto" * flag for the ESP, as it is often unset, to * hide it from Windows. */ boot_nr = nr; r = free_and_strdup(&boot, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_HOME)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&home, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&srv, subnode); if (r < 0) return log_oom(); } }
/* Return value will become exit code. * It's ok to exit instead of return. */ static NOINLINE int cpio_o(void) { static const char trailer[] ALIGN1 = "TRAILER!!!"; struct name_s { struct name_s *next; char name[1]; }; struct inodes_s { struct inodes_s *next; struct name_s *names; struct stat st; }; struct inodes_s *links = NULL; off_t bytes = 0; /* output bytes count */ while (1) { const char *name; char *line; struct stat st; line = (option_mask32 & CPIO_OPT_NUL_TERMINATED) ? bb_get_chunk_from_file(stdin, NULL) : xmalloc_fgetline(stdin); if (line) { /* Strip leading "./[./]..." from the filename */ name = line; while (name[0] == '.' && name[1] == '/') { while (*++name == '/') continue; } if (!*name) { /* line is empty */ free(line); continue; } if ((option_mask32 & CPIO_OPT_DEREF) ? stat(name, &st) : lstat(name, &st) ) { abort_cpio_o: bb_simple_perror_msg_and_die(name); } if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode))) st.st_size = 0; /* paranoia */ /* Store hardlinks for later processing, dont output them */ if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) { struct name_s *n; struct inodes_s *l; /* Do we have this hardlink remembered? */ l = links; while (1) { if (l == NULL) { /* Not found: add new item to "links" list */ l = xzalloc(sizeof(*l)); l->st = st; l->next = links; links = l; break; } if (l->st.st_ino == st.st_ino) { /* found */ break; } l = l->next; } /* Add new name to "l->names" list */ n = xmalloc(sizeof(*n) + strlen(name)); strcpy(n->name, name); n->next = l->names; l->names = n; free(line); continue; } } else { /* line == NULL: EOF */ next_link: if (links) { /* Output hardlink's data */ st = links->st; name = links->names->name; links->names = links->names->next; /* GNU cpio is reported to emit file data * only for the last instance. Mimic that. */ if (links->names == NULL) links = links->next; else st.st_size = 0; /* NB: we leak links->names and/or links, * this is intended (we exit soon anyway) */ } else { /* If no (more) hardlinks to output, * output "trailer" entry */ name = trailer; /* st.st_size == 0 is a must, but for uniformity * in the output, we zero out everything */ memset(&st, 0, sizeof(st)); /* st.st_nlink = 1; - GNU cpio does this */ } } bytes += printf("070701" "%08X%08X%08X%08X%08X%08X%08X" "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */ /* strlen+1: */ "%08X" /* chksum: */ "00000000" /* (only for "070702" files) */ /* name,NUL: */ "%s%c", (unsigned)(uint32_t) st.st_ino, (unsigned)(uint32_t) st.st_mode, (unsigned)(uint32_t) st.st_uid, (unsigned)(uint32_t) st.st_gid, (unsigned)(uint32_t) st.st_nlink, (unsigned)(uint32_t) st.st_mtime, (unsigned)(uint32_t) st.st_size, (unsigned)(uint32_t) major(st.st_dev), (unsigned)(uint32_t) minor(st.st_dev), (unsigned)(uint32_t) major(st.st_rdev), (unsigned)(uint32_t) minor(st.st_rdev), (unsigned)(strlen(name) + 1), name, '\0'); bytes = cpio_pad4(bytes); if (st.st_size) { if (S_ISLNK(st.st_mode)) { char *lpath = xmalloc_readlink_or_warn(name); if (!lpath) goto abort_cpio_o; bytes += printf("%s", lpath); free(lpath); } else { /* S_ISREG */ int fd = xopen(name, O_RDONLY); fflush_all(); /* We must abort if file got shorter too! */ bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size); bytes += st.st_size; close(fd); } bytes = cpio_pad4(bytes); } if (!line) { if (name != trailer) goto next_link; /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */ return EXIT_SUCCESS; } free(line); } /* end of "while (1)" */ }
/* Executes SCSI command (or at least forwards it to lower layers). * Clears os_err field prior to active call (whose result may set it * again). */ int do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose) { struct sg_pt_linux_scsi * ptp = &vp->impl; void * p; if (! bsg_major_checked) { bsg_major_checked = 1; find_bsg_major(verbose); } if (NULL == sg_warnings_strm) sg_warnings_strm = stderr; ptp->os_err = 0; if (ptp->in_err) { if (verbose) fprintf(sg_warnings_strm, "Replicated or unused set_scsi_pt... " "functions\n"); return SCSI_PT_DO_BAD_PARAMS; } if (bsg_major <= 0) return do_scsi_pt_v3(ptp, fd, time_secs, verbose); else { struct stat a_stat; if (fstat(fd, &a_stat) < 0) { ptp->os_err = errno; if (verbose) fprintf(sg_warnings_strm, "fstat() failed with os_err " "(errno) = %d\n", ptp->os_err); return -ptp->os_err; } #ifdef HAVE_LINUX_KDEV_T_H if (! S_ISCHR(a_stat.st_mode) || (bsg_major != (int)MAJOR(a_stat.st_rdev))) return do_scsi_pt_v3(ptp, fd, time_secs, verbose); #else if (! S_ISCHR(a_stat.st_mode) || (bsg_major != (int)major(a_stat.st_rdev))) return do_scsi_pt_v3(ptp, fd, time_secs, verbose); #endif } if (! ptp->io_hdr.request) { if (verbose) fprintf(sg_warnings_strm, "No SCSI command (cdb) given (v4)\n"); return SCSI_PT_DO_BAD_PARAMS; } /* io_hdr.timeout is in milliseconds */ ptp->io_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT); if (ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 0)) { p = (void *)(long)ptp->io_hdr.response; memset(p, 0, ptp->io_hdr.max_response_len); } if (ioctl(fd, SG_IO, &ptp->io_hdr) < 0) { ptp->os_err = errno; if (verbose) fprintf(sg_warnings_strm, "ioctl(SG_IO v4) failed with os_err " "(errno) = %d\n", ptp->os_err); return -ptp->os_err; } return 0; }
int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectedImage **ret) { #ifdef HAVE_BLKID sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL; _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; bool is_gpt, is_mbr, generic_rw, multiple_generic = false; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *generic_node = NULL; const char *pttype = NULL, *usage = NULL; struct udev_list_entry *first, *item; blkid_partlist pl; int r, generic_nr; struct stat st; unsigned i; assert(fd >= 0); assert(ret); assert(root_hash || root_hash_size == 0); /* Probes a disk image, and returns information about what it found in *ret. * * Returns -ENOPKG if no suitable partition table or file system could be found. * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */ if (root_hash) { /* If a root hash is supplied, then we use the root partition that has a UUID that match the first * 128bit of the root hash. And we use the verity partition that has a UUID that match the final * 128bit. */ if (root_hash_size < sizeof(sd_id128_t)) return -EINVAL; memcpy(&root_uuid, root_hash, sizeof(sd_id128_t)); memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t)); if (sd_id128_is_null(root_uuid)) return -EINVAL; if (sd_id128_is_null(verity_uuid)) return -EINVAL; } if (fstat(fd, &st) < 0) return -errno; if (!S_ISBLK(st.st_mode)) return -ENOTBLK; b = blkid_new_probe(); if (!b) return -ENOMEM; errno = 0; r = blkid_probe_set_device(b, fd, 0, 0); if (r != 0) { if (errno == 0) return -ENOMEM; return -errno; } blkid_probe_enable_superblocks(b, 1); blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE); blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) { log_debug("Failed to identify any partition table."); return -ENOPKG; } if (r != 0) { if (errno == 0) return -EIO; return -errno; } m = new0(DissectedImage, 1); if (!m) return -ENOMEM; (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { _cleanup_free_ char *t = NULL, *n = NULL; const char *fstype = NULL; /* OK, we have found a file system, that's our root partition then. */ (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (fstype) { t = strdup(fstype); if (!t) return -ENOMEM; } if (asprintf(&n, "/dev/block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) return -ENOMEM; m->partitions[PARTITION_ROOT] = (DissectedPartition) { .found = true, .rw = true, .partno = -1, .architecture = _ARCHITECTURE_INVALID, .fstype = t, .node = n, }; t = n = NULL; m->encrypted = streq(fstype, "crypto_LUKS"); *ret = m; m = NULL; return 0; } (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (!pttype) return -ENOPKG; is_gpt = streq_ptr(pttype, "gpt"); is_mbr = streq_ptr(pttype, "dos"); if (!is_gpt && !is_mbr) return -ENOPKG; errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return -ENOMEM; return -errno; } udev = udev_new(); if (!udev) return -errno; d = udev_device_new_from_devnum(udev, 'b', st.st_rdev); if (!d) return -ENOMEM; for (i = 0;; i++) { int n, z; if (i >= 10) { log_debug("Kernel partitions never appeared."); return -ENXIO; } e = udev_enumerate_new(udev); if (!e) return -errno; r = udev_enumerate_add_match_parent(e, d); if (r < 0) return r; r = udev_enumerate_scan_devices(e); if (r < 0) return r; /* Count the partitions enumerated by the kernel */ n = 0; first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) n++; /* Count the partitions enumerated by blkid */ z = blkid_partlist_numof_partitions(pl); if (n == z + 1) break; if (n > z + 1) { log_debug("blkid and kernel partition list do not match."); return -EIO; } if (n < z + 1) { unsigned j; /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a * synchronous call that waits until probing is complete. */ for (j = 0; j < 20; j++) { r = ioctl(fd, BLKRRPART, 0); if (r < 0) r = -errno; if (r >= 0 || r != -EBUSY) break; /* If something else has the device open, such as an udev rule, the ioctl will return * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a * bit, and try again. * * This is really something they should fix in the kernel! */ usleep(50 * USEC_PER_MSEC); } if (r < 0) return r; } e = udev_enumerate_unref(e); } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; blkid_partition pp; const char *node; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) return -errno; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (st.st_rdev == qn) continue; node = udev_device_get_devnode(q); if (!node) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; flags = blkid_partition_get_flags(pp); nr = blkid_partition_get_partno(pp); if (nr < 0) continue; if (is_gpt) { int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID; const char *stype, *sid, *fstype = NULL; sd_id128_t type_id, id; bool rw = true; if (flags & GPT_FLAG_NO_AUTO) continue; sid = blkid_partition_get_uuid(pp); if (!sid) continue; if (sd_id128_from_string(sid, &id) < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; if (sd_id128_equal(type_id, GPT_HOME)) { designator = PARTITION_HOME; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_SRV)) { designator = PARTITION_SRV; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ESP)) { designator = PARTITION_ESP; fstype = "vfat"; } #ifdef GPT_ROOT_NATIVE else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) { /* If a root ID is specified, ignore everything but the root id */ if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) continue; designator = PARTITION_ROOT; architecture = native_architecture(); rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) { m->can_verity = true; /* Ignore verity unless a root hash is specified */ if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) continue; designator = PARTITION_ROOT_VERITY; fstype = "DM_verity_hash"; architecture = native_architecture(); rw = false; } #endif #ifdef GPT_ROOT_SECONDARY else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) { /* If a root ID is specified, ignore everything but the root id */ if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) continue; designator = PARTITION_ROOT_SECONDARY; architecture = SECONDARY_ARCHITECTURE; rw = !(flags & GPT_FLAG_READ_ONLY); } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) { m->can_verity = true; /* Ignore verity unless root has is specified */ if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) continue; designator = PARTITION_ROOT_SECONDARY_VERITY; fstype = "DM_verity_hash"; architecture = SECONDARY_ARCHITECTURE; rw = false; } #endif else if (sd_id128_equal(type_id, GPT_SWAP)) { designator = PARTITION_SWAP; fstype = "swap"; } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) { if (generic_node) multiple_generic = true; else { generic_nr = nr; generic_rw = !(flags & GPT_FLAG_READ_ONLY); generic_node = strdup(node); if (!generic_node) return -ENOMEM; } } if (designator != _PARTITION_DESIGNATOR_INVALID) { _cleanup_free_ char *t = NULL, *n = NULL; /* First one wins */ if (m->partitions[designator].found) continue; if (fstype) { t = strdup(fstype); if (!t) return -ENOMEM; } n = strdup(node); if (!n) return -ENOMEM; m->partitions[designator] = (DissectedPartition) { .found = true, .partno = nr, .rw = rw, .architecture = architecture, .node = n, .fstype = t, }; n = t = NULL; } } else if (is_mbr) {
/*===========================================================================* * common_open * *===========================================================================*/ int common_open(char path[PATH_MAX], int oflags, mode_t omode, int for_exec) { /* Common code from do_creat and do_open. */ int b, r, exist = TRUE; devmajor_t major_dev; dev_t dev; mode_t bits; struct filp *filp, *filp2; struct vnode *vp; struct vmnt *vmp; struct dmap *dp; struct lookup resolve; int fd, start = 0; /* Remap the bottom two bits of oflags. */ bits = (mode_t) mode_map[oflags & O_ACCMODE]; if (!bits) return(EINVAL); /* See if file descriptor and filp slots are available. */ if ((r = get_fd(fp, start, bits, &fd, &filp)) != OK) return(r); lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); /* If O_CREATE is set, try to make the file. */ if (oflags & O_CREAT) { omode = I_REGULAR | (omode & ALLPERMS & fp->fp_umask); vp = new_node(&resolve, oflags, omode); r = err_code; if (r == OK) exist = FALSE; /* We just created the file */ else if (r != EEXIST) { /* other error */ if (vp) unlock_vnode(vp); unlock_filp(filp); return(r); } else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL flag is set this is an error */ } else { /* Scan path name */ resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_OPCL; if ((vp = eat_path(&resolve, fp)) == NULL) { unlock_filp(filp); return(err_code); } if (vmp != NULL) unlock_vmnt(vmp); } /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[fd] = filp; filp->filp_count = 1; filp->filp_vno = vp; filp->filp_flags = oflags; if (oflags & O_CLOEXEC) FD_SET(fd, &fp->fp_cloexec_set); /* Only do the normal open code if we didn't just create the file. */ if (exist) { /* Check permissions based on the given open flags, except when we are * opening an executable for the purpose of passing a file descriptor * to its interpreter for execution, in which case we check the X bit. */ if ((r = forbidden(fp, vp, for_exec ? X_BIT : bits)) == OK) { /* Opening reg. files, directories, and special files differ */ switch (vp->v_mode & S_IFMT) { case S_IFREG: /* Truncate regular file if O_TRUNC. */ if (oflags & O_TRUNC) { if ((r = forbidden(fp, vp, W_BIT)) != OK) break; upgrade_vnode_lock(vp); truncate_vnode(vp, 0); } break; case S_IFDIR: /* Directories may be read but not written. */ r = (bits & W_BIT ? EISDIR : OK); break; case S_IFCHR: /* Invoke the driver for special processing. */ dev = vp->v_sdev; /* TTY needs to know about the O_NOCTTY flag. */ r = cdev_open(fd, dev, bits | (oflags & O_NOCTTY)); vp = filp->filp_vno; /* Might be updated by * cdev_open after cloning */ break; case S_IFBLK: lock_bsf(); /* Invoke the driver for special processing. */ dev = vp->v_sdev; r = bdev_open(dev, bits); if (r != OK) { unlock_bsf(); break; } major_dev = major(vp->v_sdev); dp = &dmap[major_dev]; if (dp->dmap_driver == NONE) { printf("VFS: block driver disappeared!\n"); unlock_bsf(); r = ENXIO; break; } /* Check whether the device is mounted or not. If so, * then that FS is responsible for this device. * Otherwise we default to ROOT_FS. */ vp->v_bfs_e = ROOT_FS_E; /* By default */ for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) if (vmp->m_dev == vp->v_sdev && !(vmp->m_flags & VMNT_FORCEROOTBSF)) { vp->v_bfs_e = vmp->m_fs_e; } /* Send the driver label to the file system that will * handle the block I/O requests (even when its label * and endpoint are known already), but only when it is * the root file system. Other file systems will * already have it anyway. */ if (vp->v_bfs_e != ROOT_FS_E) { unlock_bsf(); break; } if (req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_label) != OK) { printf("VFS: error sending driver label\n"); bdev_close(dev); r = ENXIO; } unlock_bsf(); break; case S_IFIFO: /* Create a mapped inode on PFS which handles reads and writes to this named pipe. */ upgrade_vnode_lock(vp); r = map_vnode(vp, PFS_PROC_NR); if (r == OK) { if (vp->v_ref_count == 1) { if (vp->v_size != 0) r = truncate_vnode(vp, 0); } oflags |= O_APPEND; /* force append mode */ filp->filp_flags = oflags; } if (r == OK) { r = pipe_open(fd, vp, bits, oflags); } if (r != ENXIO) { /* See if someone else is doing a rd or wt on * the FIFO. If so, use its filp entry so the * file position will be automatically shared. */ b = (bits & R_BIT ? R_BIT : W_BIT); filp->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(vp, b)) != NULL) { /* Co-reader or writer found. Use it.*/ fp->fp_filp[fd] = filp2; filp2->filp_count++; filp2->filp_vno = vp; filp2->filp_flags = oflags; /* v_count was incremented after the vnode * has been found. i_count was incremented * incorrectly in FS, not knowing that we * were going to use an existing filp * entry. Correct this error. */ unlock_vnode(vp); put_vnode(vp); } else { /* Nobody else found. Restore filp. */ filp->filp_count = 1; } } break; case S_IFSOCK: r = EOPNOTSUPP; break; default: printf("VFS: attempt to open file <%llu,%llu> of " "type 0%o\n", vp->v_dev, vp->v_inode_nr, vp->v_mode & S_IFMT); r = EIO; } } } unlock_filp(filp); /* If error, release inode. */ if (r != OK) { if (r != SUSPEND) { fp->fp_filp[fd] = NULL; filp->filp_count = 0; filp->filp_vno = NULL; put_vnode(vp); } } else { r = fd; } return(r); }
int file_fsmagic(struct r_magic_set *ms, const char *fn, struct stat *sb) { int ret = 0; int mime = ms->flags & R_MAGIC_MIME; #ifdef S_IFLNK char buf[BUFSIZ+4]; int nch; struct stat tstatbuf; #endif if (!fn) return 0; /* * Fstat is cheaper but fails for files you don't have read perms on. * On 4.2BSD and similar systems, use lstat() to identify symlinks. */ #ifdef S_IFLNK if ((ms->flags & R_MAGIC_SYMLINK) == 0) ret = lstat (fn, sb); else #endif ret = stat (fn, sb); /* don't merge into if; see "ret =" above */ if (ret) { if (ms->flags & R_MAGIC_ERROR) { file_error (ms, errno, "cannot stat `%s'", fn); return -1; } if (file_printf (ms, "cannot open `%s' (%s)", fn, strerror (errno)) == -1) return -1; return 1; } if (mime) { if ((sb->st_mode & S_IFMT) != S_IFREG) { if ((mime & R_MAGIC_MIME_TYPE) && file_printf (ms, "application/x-not-regular-file") == -1) return -1; return 1; } } else { #ifdef S_ISUID if (sb->st_mode & S_ISUID) if (file_printf(ms, "setuid ") == -1) return -1; #endif #ifdef S_ISGID if (sb->st_mode & S_ISGID) if (file_printf(ms, "setgid ") == -1) return -1; #endif #ifdef S_ISVTX if (sb->st_mode & S_ISVTX) if (file_printf(ms, "sticky ") == -1) return -1; #endif } switch (sb->st_mode & S_IFMT) { case S_IFDIR: if (file_printf (ms, "directory") == -1) return -1; return 1; #ifdef S_IFCHR case S_IFCHR: /* * If -s has been specified, treat character special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. */ if ((ms->flags & R_MAGIC_DEVICES) != 0) break; #ifdef HAVE_STAT_ST_RDEV # ifdef dv_unit if (file_printf (ms, "character special (%d/%d/%d)", major (sb->st_rdev), dv_unit(sb->st_rdev), dv_subunit (sb->st_rdev)) == -1) return -1; # else if (file_printf (ms, "character special (%ld/%ld)", (long) major (sb->st_rdev), (long) minor(sb->st_rdev)) == -1) return -1; # endif #else if (file_printf (ms, "character special") == -1) return -1; #endif return 1; #endif #ifdef S_IFBLK case S_IFBLK: /* * If -s has been specified, treat block special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. */ if ((ms->flags & R_MAGIC_DEVICES) != 0) break; #ifdef HAVE_STAT_ST_RDEV # ifdef dv_unit if (file_printf(ms, "block special (%d/%d/%d)", major(sb->st_rdev), dv_unit(sb->st_rdev), dv_subunit(sb->st_rdev)) == -1) return -1; # else if (file_printf(ms, "block special (%ld/%ld)", (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1) return -1; # endif #else if (file_printf(ms, "block special") == -1) return -1; #endif return 1; #endif /* TODO add code to handle V7 MUX and Blit MUX files */ #ifdef S_IFIFO case S_IFIFO: if((ms->flags & R_MAGIC_DEVICES) != 0) break; if (file_printf(ms, "fifo (named pipe)") == -1) return -1; return 1; #endif #ifdef S_IFDOOR case S_IFDOOR: return (file_printf (ms, "door") == -1)? -1:1; #endif #ifdef S_IFLNK case S_IFLNK: if ((nch = readlink (fn, buf, BUFSIZ-1)) <= 0) { if (ms->flags & R_MAGIC_ERROR) { file_error (ms, errno, "unreadable symlink `%s'", fn); return -1; } if (file_printf(ms, "unreadable symlink `%s' (%s)", fn, strerror(errno)) == -1) return -1; return 1; } buf[nch] = '\0'; /* readlink(2) does not do this */ /* If broken symlink, say so and quit early. */ if (*buf == '/') { if (stat(buf, &tstatbuf) < 0) return bad_link(ms, errno, buf); } else { char *tmp; char buf2[BUFSIZ+BUFSIZ+4]; if (!(tmp = strrchr(fn, '/'))) { tmp = buf; /* in current directory anyway */ } else { if (tmp - fn + 1 > BUFSIZ) { if (ms->flags & R_MAGIC_ERROR) { file_error (ms, 0, "path too long: `%s'", buf); return -1; } if (file_printf (ms, "path too long: `%s'", fn) == -1) return -1; return 1; } snprintf (buf2, sizeof (buf2), "%s%s", fn, buf); tmp = buf2; } if (stat (tmp, &tstatbuf) < 0) return bad_link(ms, errno, buf); } /* Otherwise, handle it. */ if ((ms->flags & R_MAGIC_SYMLINK) != 0) { const char *p; ms->flags &= R_MAGIC_SYMLINK; p = r_magic_file(ms, buf); ms->flags |= R_MAGIC_SYMLINK; return p != NULL ? 1 : -1; } else { /* just print what it points to */ if (file_printf (ms, "symbolic link to `%s'", buf) == -1) return -1; } return 1; #endif #ifdef S_IFSOCK case S_IFSOCK: if (file_printf(ms, "socket") == -1) return -1; return 1; #endif case S_IFREG: break; default: file_error (ms, 0, "invalid mode 0%o", sb->st_mode); return -1; /*NOTREACHED*/ } /* * regular file, check next possibility * * If stat() tells us the file has zero length, report here that * the file is empty, so we can skip all the work of opening and * reading the file. * But if the -s option has been given, we skip this optimization, * since on some systems, stat() reports zero size for raw disk * partitions. (If the block special device really has zero length, * the fact that it is empty will be detected and reported correctly * when we read the file.) */ if ((ms->flags & R_MAGIC_DEVICES) == 0 && sb->st_size == 0) { if ((!mime || (mime & R_MAGIC_MIME_TYPE)) && file_printf (ms, mime ? "application/x-empty" : "empty") == -1) return -1; return 1; } return 0; }
int default_init() { struct stat s; int i; /* FIXME: other modules might need this, too */ rec_buffer_init(); send_buffer_init(); if (stat(drv.device, &s) == -1) { logprintf(LIRC_ERROR, "could not get file information for %s", drv.device); logperror(LIRC_ERROR, "default_init()"); return (0); } /* file could be unix socket, fifo and native lirc device */ if (S_ISSOCK(s.st_mode)) { struct sockaddr_un addr; addr.sun_family = AF_UNIX; strncpy(addr.sun_path, drv.device, sizeof(addr.sun_path) - 1); drv.fd = socket(AF_UNIX, SOCK_STREAM, 0); if (drv.fd == -1) { logprintf(LIRC_ERROR, "could not create socket"); logperror(LIRC_ERROR, "default_init()"); return (0); } if (connect(drv.fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { logprintf(LIRC_ERROR, "could not connect to unix socket %s", drv.device); logperror(LIRC_ERROR, "default_init()"); default_deinit(); close(drv.fd); return (0); } logprintf(LIRC_TRACE, "using unix socket lirc device"); drv.features = LIRC_CAN_REC_MODE2 | LIRC_CAN_SEND_PULSE; drv.rec_mode = LIRC_MODE_MODE2; /* this might change in future */ drv.send_mode = LIRC_MODE_PULSE; return (1); } if ((drv.fd = open(drv.device, O_RDWR)) < 0) { logprintf(LIRC_ERROR, "could not open %s", drv.device); logperror(LIRC_ERROR, "default_init()"); return (0); } if (S_ISFIFO(s.st_mode)) { logprintf(LIRC_TRACE, "using defaults for the Irman"); drv.features = LIRC_CAN_REC_MODE2; drv.rec_mode = LIRC_MODE_MODE2; /* this might change in future */ return (1); } else if (!S_ISCHR(s.st_mode)) { default_deinit(); logprintf(LIRC_ERROR, "%s is not a character device!!!", drv.device); logperror(LIRC_ERROR, "something went wrong during installation"); return (0); } else if (default_ioctl(LIRC_GET_FEATURES, &drv.features) == -1) { logprintf(LIRC_ERROR, "could not get hardware features"); logprintf(LIRC_ERROR, "this device driver does not support the LIRC ioctl interface"); if (major(s.st_rdev) == 13) { logprintf(LIRC_ERROR, "did you mean to use the devinput driver instead of the %s driver?", drv.name); } else { logprintf(LIRC_ERROR, "major number of %s is %lu", drv.device, (__u32) major(s.st_rdev)); logprintf(LIRC_ERROR, "make sure %s is a LIRC device and use a current version of the driver", drv.device); } default_deinit(); return (0); } else { if (!(LIRC_CAN_SEND(drv.features) || LIRC_CAN_REC(drv.features))) { logprintf(LIRC_TRACE, "driver supports neither sending nor receiving of IR signals"); } if (LIRC_CAN_SEND(drv.features) && LIRC_CAN_REC(drv.features)) { logprintf(LIRC_TRACE, "driver supports both sending and receiving"); } else if (LIRC_CAN_SEND(drv.features)) { logprintf(LIRC_TRACE, "driver supports sending"); } else if (LIRC_CAN_REC(drv.features)) { logprintf(LIRC_TRACE, "driver supports receiving"); } } /* set send/receive method */ drv.send_mode = 0; if (LIRC_CAN_SEND(drv.features)) { for (i = 0; supported_send_modes[i] != 0; i++) { if (LIRC_CAN_SEND(drv.features) == supported_send_modes[i]) { drv.send_mode = LIRC_SEND2MODE(supported_send_modes[i]); break; } } if (supported_send_modes[i] == 0) { logprintf(LIRC_NOTICE, "the send method of the driver is not yet supported by lircd"); } } drv.rec_mode = 0; if (LIRC_CAN_REC(drv.features)) { for (i = 0; supported_rec_modes[i] != 0; i++) { if (LIRC_CAN_REC(drv.features) == supported_rec_modes[i]) { drv.rec_mode = LIRC_REC2MODE(supported_rec_modes[i]); break; } } if (supported_rec_modes[i] == 0) { logprintf(LIRC_NOTICE, "the receive method of the driver is not yet supported by lircd"); } } if (drv.rec_mode == LIRC_MODE_MODE2) { /* get resolution */ drv.resolution = 0; if ((drv.features & LIRC_CAN_GET_REC_RESOLUTION) && (default_ioctl(LIRC_GET_REC_RESOLUTION, &drv.resolution) != -1)) { logprintf(LIRC_TRACE, "resolution of receiver: %d", drv.resolution); } } else if (drv.rec_mode == LIRC_MODE_LIRCCODE) { if (default_ioctl(LIRC_GET_LENGTH, (void*) &drv.code_length) == -1) { logprintf(LIRC_ERROR, "could not get code length"); logperror(LIRC_ERROR, "default_init()"); default_deinit(); return (0); } if (drv.code_length > sizeof(ir_code) * CHAR_BIT) { logprintf(LIRC_ERROR, "lircd can not handle %lu bit codes", drv.code_length); default_deinit(); return (0); } } if (!(drv.send_mode || drv.rec_mode)) { default_deinit(); return (0); } return (1); }
void vtrans(struct vnode *vp, int i, int flag, off_t offset) { struct vnode vn; struct filestat fst; char rw[3], mode[17]; char *badtype = NULL, *filename; filename = badtype = NULL; if (!KVM_READ(vp, &vn, sizeof (struct vnode))) { dprintf("can't read vnode at %p for pid %ld", vp, (long)Pid); return; } if (vn.v_type == VNON || vn.v_tag == VT_NON) badtype = "none"; else if (vn.v_type == VBAD) badtype = "bad"; else switch (vn.v_tag) { case VT_UFS: case VT_MFS: if (!ufs_filestat(&vn, &fst)) badtype = "error"; break; case VT_NFS: if (!nfs_filestat(&vn, &fst)) badtype = "error"; break; case VT_EXT2FS: if (!ext2fs_filestat(&vn, &fst)) badtype = "error"; break; case VT_ISOFS: if (!isofs_filestat(&vn, &fst)) badtype = "error"; break; case VT_MSDOSFS: if (!msdos_filestat(&vn, &fst)) badtype = "error"; break; case VT_XFS: if (!xfs_filestat(&vn, &fst)) badtype = "error"; break; case VT_NULL: if (!null_filestat(&vn, &fst)) badtype = "error"; break; default: { static char unknown[30]; snprintf(badtype = unknown, sizeof unknown, "?(%x)", vn.v_tag); break; } } if (checkfile) { int fsmatch = 0; DEVS *d; if (badtype) return; for (d = devs; d != NULL; d = d->next) if (d->fsid == fst.fsid) { fsmatch = 1; if (d->ino == fst.fileid) { filename = d->name; break; } } if (fsmatch == 0 || (filename == NULL && fsflg == 0)) return; } PREFIX(i); if (badtype) { (void)printf(" - - %10s -\n", badtype); return; } if (nflg) (void)printf(" %2ld,%-2ld", (long)major(fst.fsid), (long)minor(fst.fsid)); else (void)printf(" %-8s", getmnton(vn.v_mount)); if (nflg) (void)snprintf(mode, sizeof mode, "%o", fst.mode); else strmode(fst.mode, mode); (void)printf(" %6ld %11s", fst.fileid, mode); rw[0] = '\0'; if (flag & FREAD) strlcat(rw, "r", sizeof rw); if (flag & FWRITE) strlcat(rw, "w", sizeof rw); printf(" %2s", rw); switch (vn.v_type) { case VBLK: case VCHR: { char *name; if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? S_IFCHR : S_IFBLK)) == NULL)) printf(" %2d,%-3d", major(fst.rdev), minor(fst.rdev)); else printf(" %7s", name); if (oflg) printf(" "); break; } default: printf(" %8lld", (long long)fst.size); if (oflg) printf(":%-8lld", (long long)offset); } if (filename && !fsflg) printf(" %s", filename); putchar('\n'); }
/* * Determine ppa number that specifies ifname. * * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, * the code that's used here is the old code for HP-UX 10.x. * * However, HP-UX 10.20, at least, appears to have such a member * in its "dl_hp_ppa_info_t" structure, so the new code is used. * The new code didn't work on an old 10.20 system on which Rick * Jones of HP tried it, but with later patches installed, it * worked - it appears that the older system had those members but * didn't put anything in them, so, if the search by name fails, we * do the old search. * * Rick suggests that making sure your system is "up on the latest * lancommon/DLPI/driver patches" is probably a good idea; it'd fix * that problem, as well as allowing libpcap to see packets sent * from the system on which the libpcap application is being run. * (On 10.20, in addition to getting the latest patches, you need * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; * a posting to "comp.sys.hp.hpux" at * * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 * * says that, to see the machine's outgoing traffic, you'd need to * apply the right patches to your system, and also set that variable * with: echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem * which could be put in, for example, "/sbin/init.d/lan". * * Setting the variable is not necessary on HP-UX 11.x. */ static int get_dlpi_ppa(register int fd, register const char *device, register int unit, register char *ebuf) { register dl_hp_ppa_ack_t *ap; register dl_hp_ppa_info_t *ipstart, *ip; register int i; char dname[100]; register u_long majdev; struct stat statbuf; dl_hp_ppa_req_t req; char buf[MAXDLBUF]; char *ppa_data_buf; dl_hp_ppa_ack_t *dlp; struct strbuf ctl; int flags; int ppa; memset((char *)&req, 0, sizeof(req)); req.dl_primitive = DL_HP_PPA_REQ; memset((char *)buf, 0, sizeof(buf)); if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) return (PCAP_ERROR); ctl.maxlen = DL_HP_PPA_ACK_SIZE; ctl.len = 0; ctl.buf = (char *)buf; flags = 0; /* * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) * which is NOT big enough for a DL_HP_PPA_REQ. * * This causes libpcap applications to fail on a system with HP-APA * installed. * * To figure out how big the returned data is, we first call getmsg * to get the small head and peek at the head to get the actual data * length, and then issue another getmsg to get the actual PPA data. */ /* get the head first */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); return (PCAP_ERROR); } dlp = (dl_hp_ppa_ack_t *)ctl.buf; if (dlp->dl_primitive != DL_HP_PPA_ACK) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", (bpf_u_int32)dlp->dl_primitive); return (PCAP_ERROR); } if (ctl.len < DL_HP_PPA_ACK_SIZE) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); return (PCAP_ERROR); } /* allocate buffer */ if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); return (PCAP_ERROR); } ctl.maxlen = dlp->dl_length; ctl.len = 0; ctl.buf = (char *)ppa_data_buf; /* get the data */ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); free(ppa_data_buf); return (PCAP_ERROR); } if (ctl.len < dlp->dl_length) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "get_dlpi_ppa: hpppa ack too small (%d < %lu)", ctl.len, (unsigned long)dlp->dl_length); free(ppa_data_buf); return (PCAP_ERROR); } ap = (dl_hp_ppa_ack_t *)buf; ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; ip = ipstart; #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 /* * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" * member that should, in theory, contain the part of the * name for the device that comes before the unit number, * and should also have a "dl_module_id_2" member that may * contain an alternate name (e.g., I think Ethernet devices * have both "lan", for "lanN", and "snap", for "snapN", with * the former being for Ethernet packets and the latter being * for 802.3/802.2 packets). * * Search for the device that has the specified name and * instance number. */ for (i = 0; i < ap->dl_count; i++) { if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || strcmp((const char *)ip->dl_module_id_2, device) == 0) && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } #else /* * We don't have that member, so the search is impossible; make it * look as if the search failed. */ i = ap->dl_count; #endif if (i == ap->dl_count) { /* * Well, we didn't, or can't, find the device by name. * * HP-UX 10.20, whilst it has "dl_module_id_1" and * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", * doesn't seem to fill them in unless the system is * at a reasonably up-to-date patch level. * * Older HP-UX 10.x systems might not have those fields * at all. * * Therefore, we'll search for the entry with the major * device number of a device with the name "/dev/<dev><unit>", * if such a device exists, as the old code did. */ snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); if (stat(dname, &statbuf) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", dname, pcap_strerror(errno)); return (PCAP_ERROR); } majdev = major(statbuf.st_rdev); ip = ipstart; for (i = 0; i < ap->dl_count; i++) { if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit) break; ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); } } if (i == ap->dl_count) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "can't find /dev/dlpi PPA for %s%d", device, unit); return (PCAP_ERROR_NO_SUCH_DEVICE); } if (ip->dl_hdw_state == HDW_DEAD) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s%d: hardware state: DOWN\n", device, unit); free(ppa_data_buf); return (PCAP_ERROR); } ppa = ip->dl_ppa; free(ppa_data_buf); return (ppa); }
int Volume::formatVol(bool wipe) { dev_t deviceNodes[DirectVolume::MAX_PARTITIONS]; bool isForceFat32 = false; if (getState() == Volume::State_NoMedia) { errno = ENODEV; return -1; } else if (getState() != Volume::State_Idle) { errno = EBUSY; return -1; } #ifdef MTK_SHARED_SDCARD if(IsEmmcStorage()){ SLOGE("It is not allowed to format internal SDCARD with MTK_SHARED_SDCARD enabled"); errno = -EPERM; return errno; } #endif if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); setState(Volume::State_Mounted); // mCurrentlyMountedKdev = XXX errno = EBUSY; return -1; } SLOGI("mDiskNumParts = %d\n", getDeviceNumParts()); bool formatEntireDevice = (mPartIdx == -1); char devicePath[255]; dev_t diskNode = getDiskDevice(); dev_t partNode = MKDEV(MAJOR(diskNode), MINOR(diskNode) + (formatEntireDevice ? 1 : mPartIdx)); setState(Volume::State_Formatting); int ret = -1; #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT char *otgNodePath = getOtgNodePath(); if (0 == strcmp(getLabel(), "usbotg")) { if (NULL == otgNodePath) { SLOGE("usbotg: Volume formatVol otgNodePath is NULL"); goto err; } SLOGD("usbotg: Volume formatVol otgNodePath = %s", otgNodePath); // Only initialize the MBR if we are formatting the entire device if (formatEntireDevice) { SLOGI("usbotg: Volume formatVol call initializeMbr().\n"); if (initializeMbr(otgNodePath)) { SLOGE("usbotg: Volume formatVol failed to initialize MBR (%s)", strerror(errno)); goto err; } SLOGI("usbotg: Volume formatVol exit initializeMbr().\n"); } if (Fat::format(otgNodePath, 0, wipe, isForceFat32)) { SLOGE("usbotg: Volume formatVol Failed to format (%s)", strerror(errno)); goto err; } } else { // Only initialize the MBR if we are formatting the entire device if (formatEntireDevice) { sprintf(devicePath, "/dev/block/vold/%d:%d", major(diskNode), minor(diskNode)); SLOGI("Call initializeMbr().\n"); if (initializeMbr(devicePath)) { SLOGE("Failed to initialize MBR (%s)", strerror(errno)); goto err; } SLOGI("Exit initializeMbr().\n"); } sprintf(devicePath, "/dev/block/vold/%d:%d", major(partNode), minor(partNode)); if (mDebug) { SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); } #ifdef MTK_ICUSB_SUPPORT if(!strcmp(getLabel(), "icusb1") || !strcmp(getLabel(), "icusb2")){ isForceFat32 = true; } #endif if (Fat::format(devicePath, 0, wipe, isForceFat32)) { SLOGE("Failed to format (%s)", strerror(errno)); goto err; } } #else { // Only initialize the MBR if we are formatting the entire device if (formatEntireDevice) { sprintf(devicePath, "/dev/block/vold/%d:%d", major(diskNode), minor(diskNode)); SLOGI("Call initializeMbr().\n"); if (initializeMbr(devicePath)) { SLOGE("Failed to initialize MBR (%s)", strerror(errno)); goto err; } } sprintf(devicePath, "/dev/block/vold/%d:%d", major(partNode), minor(partNode)); if (mDebug) { SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); } #ifdef MTK_ICUSB_SUPPORT if(!strcmp(getLabel(), "icusb1") || !strcmp(getLabel(), "icusb2")){ isForceFat32 = true; } #endif if (Fat::format(devicePath, 0, wipe, isForceFat32)) { SLOGE("Failed to format (%s)", strerror(errno)); goto err; } } #endif ret = 0; err: setState(Volume::State_Idle); return ret; }