std::string SysInfo::device_from_id()

in src/sys_info.cc [265:305]


	std::string SysInfo::device_from_id(dev_t device_id) {
		// this looks at the symlink in sys/class/block/$dev
		// the symlink here ends with "block/$devname/$partitionname" or "block/$devname"
		// in either case, we get the 'up one' name, ie $devname or "block"
		// if we get someting that isn't "block", then that's the actual device. otherwise, if it's
		// "block", we know that the original name is the device name, so just return that
		
		// this shouldn't happen if sys-info's been initialized properly
		if (!id_to_device.count(device_id)) {
			fprintf(
				stderr,
				"Tried to lookup nonexistent device %u,%u in sys_info!\n",
				major(device_id),
				minor(device_id));
			exit(1);
		}

		std::string dev_name = id_to_device[device_id];
	
		std::string linkpath = "/sys/class/block/" + dev_name;
		char the_link[PATH_MAX+1] = {0};
		ssize_t link_size = readlink(linkpath.c_str(), the_link, PATH_MAX);
		if (link_size == -1) {
			fprintf(stderr, "Error reading link!\n");
			perror("readlink");
			exit(1);
		}
		// add null terminator; readlink has few guarantees
		the_link[link_size] = '\0';

		// these use statically allocated memory, or modify the original path. don't free them
		char * up_one = dirname(the_link);			// "abc/abc/sda/sda1" -> "abc/abc/sda"
		char * up_one_name = basename(up_one);		// "abc/abc/sda" -> "sda"

		// if the device is not a partition, then the 'one up' path is 'block' instead
		if (strncmp(up_one_name, "block", 5) == 0) {
			return dev_name;	// so just return the original name we had
		}

		return std::string(up_one_name);
	}