Ejemplo n.º 1
0
static void print_tags(blkid_dev dev, char *show[], int output)
{
	blkid_tag_iterate	iter;
	const char		*type, *value, *devname;
	int			num = 1;

	if (!dev)
		return;

	if (output & OUTPUT_PRETTY_LIST) {
		pretty_print_dev(dev);
		return;
	}

	devname = blkid_dev_devname(dev);

	if (output & OUTPUT_DEVICE_ONLY) {
		printf("%s\n", devname);
		return;
	}

	iter = blkid_tag_iterate_begin(dev);
	while (blkid_tag_next(iter, &type, &value) == 0) {
		if (show[0] && !has_item(show, type))
			continue;
		print_value(output, num++, devname, value, type, strlen(value));
	}
	blkid_tag_iterate_end(iter);

	if (num > 1 && !(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST)))
		printf("\n");
}
Ejemplo n.º 2
0
static void pretty_print_dev(blkid_dev dev)
{
	blkid_tag_iterate	iter;
	const char		*type, *value, *devname;
	const char		*uuid = "", *fs_type = "", *label = "";
	int			len, mount_flags;
	char			mtpt[80];
	errcode_t		retval;

	if (dev == NULL) {
		pretty_print_line("device", "fs_type", "label",
				  "mount point", "UUID");
		for (len=get_terminal_width()-1; len > 0; len--)
			fputc('-', stdout);
		fputc('\n', stdout);
		return;
	}

	devname = blkid_dev_devname(dev);
	if (access(devname, F_OK))
		return;

	/* Get the uuid, label, type */
	iter = blkid_tag_iterate_begin(dev);
	while (blkid_tag_next(iter, &type, &value) == 0) {
		if (!strcmp(type, "UUID"))
			uuid = value;
		if (!strcmp(type, "TYPE"))
			fs_type = value;
		if (!strcmp(type, "LABEL"))
			label = value;
	}
	blkid_tag_iterate_end(iter);

	/* Get the mount point */
	mtpt[0] = 0;
	retval = ext2fs_check_mount_point(devname, &mount_flags,
					  mtpt, sizeof(mtpt));
	if (retval == 0) {
		if (mount_flags & EXT2_MF_MOUNTED) {
			if (!mtpt[0])
				strcpy(mtpt, "(mounted, mtpt unknown)");
		} else if (mount_flags & EXT2_MF_BUSY)
			strcpy(mtpt, "(in use)");
		else
			strcpy(mtpt, "(not mounted)");
	}

	pretty_print_line(devname, fs_type, label, mtpt, uuid);
}
Ejemplo n.º 3
0
static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
{
	blkid_tag_iterate	iter;
	const char		*type, *value;
	int 			i, first = 1;

	if (!dev)
		return;

	if (output & OUTPUT_PRETTY_LIST) {
		pretty_print_dev(dev);
		return;
	}

	if (output & OUTPUT_DEVICE_ONLY) {
		printf("%s\n", blkid_dev_devname(dev));
		return;
	}

	iter = blkid_tag_iterate_begin(dev);
	while (blkid_tag_next(iter, &type, &value) == 0) {
		if (numtag && show) {
			for (i=0; i < numtag; i++)
				if (!strcmp(type, show[i]))
					break;
			if (i >= numtag)
				continue;
		}
		if (output & OUTPUT_VALUE_ONLY) {
			fputs(value, stdout);
			fputc('\n', stdout);
		} else {
			if (first) {
				printf("%s: ", blkid_dev_devname(dev));
				first = 0;
			}
			fputs(type, stdout);
			fputs("=\"", stdout);
			safe_print(value, -1);
			fputs("\" ", stdout);
		}
	}
	blkid_tag_iterate_end(iter);

	if (!first && !(output & OUTPUT_VALUE_ONLY))
		printf("\n");
}
Ejemplo n.º 4
0
static void print_tags(blkid_dev dev, char *show[], int output)
{
	blkid_tag_iterate	iter;
	const char		*type, *value, *devname;
	int			num = 1;
	static int		first = 1;

	if (!dev)
		return;

	if (output & OUTPUT_PRETTY_LIST) {
		pretty_print_dev(dev);
		return;
	}

	devname = blkid_dev_devname(dev);

	if (output & OUTPUT_DEVICE_ONLY) {
		printf("%s\n", devname);
		return;
	}

	iter = blkid_tag_iterate_begin(dev);
	while (blkid_tag_next(iter, &type, &value) == 0) {
		if (show[0] && !has_item(show, type))
			continue;

		if (num == 1 && !first &&
		    (output & (OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)))
			/* add extra line between output from more devices */
			fputc('\n', stdout);

		print_value(output, num++, devname, value, type, strlen(value));
	}
	blkid_tag_iterate_end(iter);

	if (num > 1) {
		if (!(output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST |
						OUTPUT_EXPORT_LIST)))
			printf("\n");
		first = 0;
	}
}
Ejemplo n.º 5
0
static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
{
	blkid_tag_iterate	iter;
	const char		*type, *value;
	int 			i, first = 1;

	if (!dev)
		return;

	if (output & OUTPUT_DEVICE_ONLY) {
		printf("%s\n", blkid_dev_devname(dev));
		return;
	}

	iter = blkid_tag_iterate_begin(dev);
	while (blkid_tag_next(iter, &type, &value) == 0) {
		if (numtag && show) {
			for (i=0; i < numtag; i++)
				if (!strcmp(type, show[i]))
					break;
			if (i >= numtag)
				continue;
		}
		if (first && !(output & OUTPUT_VALUE_ONLY)) {
			printf("%s: ", blkid_dev_devname(dev));
			first = 0;
		}
		if ((output & OUTPUT_VALUE_ONLY))
			printf("%s\n", value);
		else
			printf("%s=\"%s\" ", type, value);
	}
	blkid_tag_iterate_end(iter);

	if (!first && !(output & OUTPUT_VALUE_ONLY))
		printf("\n");
}
Ejemplo n.º 6
0
/*
 * Verify that the data in dev is consistent with what is on the actual
 * block device (using the devname field only).  Normally this will be
 * called when finding items in the cache, but for long running processes
 * is also desirable to revalidate an item before use.
 *
 * If we are unable to revalidate the data, we return the old data and
 * do not set the BLKID_BID_FL_VERIFIED flag on it.
 */
blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
{
    struct stat st;
    time_t diff, now;
    char *fltr[2];
    int fd;

    if (!dev)
        return NULL;

    now = time(0);
    diff = now - dev->bid_time;

    if (stat(dev->bid_name, &st) < 0) {
        DBG(DEBUG_PROBE,
            printf("blkid_verify: error %m (%d) while "
                   "trying to stat %s\n", errno,
                   dev->bid_name));
open_err:
        if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
            /* We don't have read permission, just return cache data. */
            DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
                                    dev->bid_name));
            return dev;
        }
        blkid_free_dev(dev);
        return NULL;
    }

    if (now >= dev->bid_time &&
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
            (st.st_mtime < dev->bid_time ||
             (st.st_mtime == dev->bid_time &&
              st.st_mtim.tv_nsec / 1000 <= dev->bid_utime)) &&
#else
            st.st_mtime <= dev->bid_time &&
#endif
            (diff < BLKID_PROBE_MIN ||
             (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
              diff < BLKID_PROBE_INTERVAL)))
        return dev;

#ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
    DBG(DEBUG_PROBE,
        printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
               "time since last check %lu)\n",
               dev->bid_name, (unsigned long)dev->bid_time,
               (unsigned long)st.st_mtime, (unsigned long)diff));
#else
    DBG(DEBUG_PROBE,
        printf("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\n\t"
               "time since last check %lu)\n",
               dev->bid_name,
               (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime,
               (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000,
               (unsigned long)diff));
#endif

    if (!cache->probe) {
        cache->probe = blkid_new_probe();
        if (!cache->probe) {
            blkid_free_dev(dev);
            return NULL;
        }
    }

    fd = open(dev->bid_name, O_RDONLY|O_CLOEXEC);
    if (fd < 0) {
        DBG(DEBUG_PROBE, printf("blkid_verify: error %m (%d) while "
                                "opening %s\n", errno,
                                dev->bid_name));
        goto open_err;
    }

    if (blkid_probe_set_device(cache->probe, fd, 0, 0)) {
        /* failed to read the device */
        close(fd);
        blkid_free_dev(dev);
        return NULL;
    }

    blkid_probe_enable_superblocks(cache->probe, TRUE);

    blkid_probe_set_superblocks_flags(cache->probe,
                                      BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
                                      BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE);

    blkid_probe_enable_partitions(cache->probe, TRUE);
    blkid_probe_set_partitions_flags(cache->probe, BLKID_PARTS_ENTRY_DETAILS);

    /*
     * If we already know the type, then try that first.
     */
    if (dev->bid_type) {
        blkid_tag_iterate iter;
        const char *type, *value;

        fltr[0] = dev->bid_type;
        fltr[1] = NULL;

        blkid_probe_filter_superblocks_type(cache->probe,
                                            BLKID_FLTR_ONLYIN, fltr);

        if (!blkid_do_probe(cache->probe))
            goto found_type;
        blkid_probe_invert_superblocks_filter(cache->probe);

        /*
         * Zap the device filesystem information and try again
         */
        DBG(DEBUG_PROBE,
            printf("previous fs type %s not valid, "
                   "trying full probe\n", dev->bid_type));
        iter = blkid_tag_iterate_begin(dev);
        while (blkid_tag_next(iter, &type, &value) == 0)
            blkid_set_tag(dev, type, 0, 0);
        blkid_tag_iterate_end(iter);
    }

    /*
     * Probe for all types.
     */
    if (blkid_do_safeprobe(cache->probe)) {
        /* found nothing or error */
        blkid_free_dev(dev);
        dev = NULL;
    }

found_type:
    if (dev) {
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
        struct timeval tv;
        if (!gettimeofday(&tv, NULL)) {
            dev->bid_time = tv.tv_sec;
            dev->bid_utime = tv.tv_usec;
        } else
#endif
            dev->bid_time = time(0);

        dev->bid_devno = st.st_rdev;
        dev->bid_flags |= BLKID_BID_FL_VERIFIED;
        cache->bic_flags |= BLKID_BIC_FL_CHANGED;

        blkid_probe_to_tags(cache->probe, dev);

        DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
                                dev->bid_name, (long long)st.st_rdev, dev->bid_type));
    }

    blkid_reset_probe(cache->probe);
    blkid_probe_reset_superblocks_filter(cache->probe);
    close(fd);
    return dev;
}
Ejemplo n.º 7
0
int get_devinfo(struct s_devinfo *outdev, char *indevname, int min, int maj)
{
    char sysblkdevname[512];
    blkid_tag_iterate iter;
    char sysblkinfo[PATH_MAX];
    const char *type, *value;
    struct stat64 statbuf;
    struct dirent *dir;
    char temp[PATH_MAX];
    blkid_dev dev;
    DIR *dirdesc;
    FILE *finfo;
    int found;
    int fd;
    int i;
    
    // init
    memset(outdev, 0, sizeof(struct s_devinfo));
    
    // defaults values
    outdev->devtype=BLKDEV_INVALID;
    snprintf(outdev->label, sizeof(outdev->label), " ");
    snprintf(outdev->uuid, sizeof(outdev->uuid), "<unknown>");
    snprintf(outdev->fsname, sizeof(outdev->fsname), "<unknown>");
    
    // check the name starts with "/dev/"
    if ((strlen(indevname) < 5) || (memcmp(indevname, "/dev/", 5)!=0))
        return -1;
    
    // get short name ("/dev/sda1" -> "sda1")
    snprintf(outdev->devname, sizeof(outdev->devname), "%s", indevname+5); // skip "/dev/"
    
    // get long name if there is one (eg: LVM / devmapper)
    snprintf(outdev->longname, sizeof(outdev->longname), "%s", indevname);
    if ((dirdesc=opendir("/dev/mapper"))!=NULL)
    {
        found=false;
        while (((dir=readdir(dirdesc)) != NULL) && found==false)
        {
            snprintf(temp, sizeof(temp), "/dev/mapper/%s", dir->d_name);
            if ((stat64(temp, &statbuf)==0) && S_ISBLK(statbuf.st_mode) && 
                (major(statbuf.st_rdev)==maj) && (minor(statbuf.st_rdev)==min))
            {
                snprintf(outdev->longname, sizeof(outdev->longname), "%s", temp);
                found=true;
            }
        }
        closedir(dirdesc);
    }
    
    // get device basic info (size, major, minor)
    if (((fd=open64(outdev->longname, O_RDONLY|O_LARGEFILE))<0) ||
        ((outdev->devsize=lseek64(fd, 0, SEEK_END))<0) ||
        (fstat64(fd, &statbuf)!=0) ||
        (!S_ISBLK(statbuf.st_mode)) ||
        (close(fd)<0))
        return -1;
    outdev->rdev=statbuf.st_rdev;
    outdev->major=major(statbuf.st_rdev);
    outdev->minor=minor(statbuf.st_rdev);
    format_size(outdev->devsize, outdev->txtsize, sizeof(outdev->txtsize), 'h');
    if (outdev->devsize==1024) // ignore extended partitions
        return -1;
    
    // devname shown in /sys/block (eg for HP-cciss: "cciss/c0d0" -> "cciss!c0d0")
    snprintf(sysblkdevname, sizeof(sysblkdevname), "%s", outdev->devname);
    for (i=0; (sysblkdevname[i]!=0) && (i<sizeof(sysblkdevname)); i++)
        if (sysblkdevname[i]=='/')
            sysblkdevname[i]='!';
    
    // check if it's a physical disk (there is a "/sys/block/${devname}/device")
    snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device", sysblkdevname);
    if (stat64(sysblkinfo, &statbuf)==0)
    {
        outdev->devtype=BLKDEV_PHYSDISK;
        snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device/model", sysblkdevname);
        if ( ((finfo=fopen(sysblkinfo, "rb")) != NULL) && (fread(temp, 1, sizeof(temp), finfo)>0) && fclose(finfo)==0 )
            for (i=0; (temp[i]!=0) && (temp[i]!='\r') && (temp[i]!='\n'); i++)
                outdev->name[i]=temp[i];
    }
    else
    {
        outdev->devtype=BLKDEV_FILESYSDEV;
    }
    
    // get blkid infos about the device (label, uuid)
    blkid_cache cache = NULL;
    if (blkid_get_cache(&cache, NULL) < 0)
        return -1;
    if ((dev=blkid_get_dev(cache, outdev->longname, BLKID_DEV_NORMAL))!=NULL)
    {
        iter = blkid_tag_iterate_begin(dev);
        while (blkid_tag_next(iter, &type, &value)==0)
        {
            if (strcmp(type, "LABEL")==0)
                snprintf(outdev->label, sizeof(outdev->label), "%s", value);
            else if (strcmp(type, "UUID")==0)
                snprintf(outdev->uuid, sizeof(outdev->uuid), "%s", value);
            else if (strcmp(type, "TYPE")==0)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "%s", value);
        }
        blkid_tag_iterate_end(iter);
        
        // workaround: blkid < 1.41 don't know ext4 and say it is ext3 instead
        if (strcmp(outdev->fsname, "ext3")==0)
        {
            if (ext3_test(outdev->longname)==true)
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext3");
            else // cannot run ext4_test(): it would fail on an ext4 when e2fsprogs < 1.41
                snprintf(outdev->fsname, sizeof(outdev->fsname), "ext4");
        }
    }
    blkid_put_cache(cache); // free memory allocated by blkid_get_cache
    
    return 0;
}
Ejemplo n.º 8
0
int main (int argc, char ** argv) {
	struct udev * udev;
	struct udev_device * dev;
	char * device = NULL;
   	struct udev_monitor * mon = NULL;
	fd_set readfds;
	int fdcount, devnum, errcount = 0;
	unsigned short int i, major, minor;
	short int * maxminor;

	char * notification = NULL;
	char * icon = NULL;
        NotifyNotification * netlink;
        NotifyNotification *** netlinkref;

	blkid_cache cache = NULL;
	char *read = NULL;
	blkid_tag_iterate iter;
	const char *type, *value, *devname;
	blkid_dev blkdev;

	GError * error = NULL;

	printf("%s: %s v%s (compiled: %s)\n", argv[0], PROGNAME, VERSION, DATE);

	if(!notify_init("Udev-Block-Notification")) {
		fprintf(stderr, "%s: Can't create notify.\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	udev = udev_new();
	if(!udev) {
		fprintf(stderr, "%s: Can't create udev.\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	mon = udev_monitor_new_from_netlink(udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL);
	udev_monitor_enable_receiving(mon);

	netlinkref = malloc(256 * sizeof(size_t));
	for(i = 0; i < 256; i++)
		netlinkref[i] = NULL;
	maxminor = malloc(256 * sizeof(short int));
	for(i = 0; i < 256; i++)
		maxminor[i] = -1;

	while (1) {
                FD_ZERO(&readfds);
                if (mon != NULL)
                        FD_SET(udev_monitor_get_fd(mon), &readfds);

                fdcount = select(udev_monitor_get_fd(mon) + 1, &readfds, NULL, NULL, NULL);

                if ((mon != NULL) && FD_ISSET(udev_monitor_get_fd(mon), &readfds)) {
			dev = udev_monitor_receive_device(mon);
			if(dev) {
				device = (char *) udev_device_get_sysname(dev);
				devnum = udev_device_get_devnum(dev);
				major = devnum / 256;
				minor = devnum - (major * 256);

				switch(udev_device_get_action(dev)[0]) {
					case 'a':
						// a: add
						notification = (char *) malloc(strlen(TEXT_ADD) + strlen(device));
						sprintf(notification, TEXT_ADD, device, major, minor);
						icon = ICON_ADD;
						break;
					case 'r':
						// r: remove
						notification = (char *) malloc(strlen(TEXT_REMOVE) + strlen(device));
						sprintf(notification, TEXT_REMOVE, device, major, minor);
						icon = ICON_REMOVE;
						break;
					case 'm':
						// m: move
						notification = (char *) malloc(strlen(TEXT_MOVE) + strlen(device));
						sprintf(notification, TEXT_MOVE, device, major, minor);
						icon = ICON_MOVE;
						break;
					case 'c':
						// c: change
						notification = (char *) malloc(strlen(TEXT_CHANGE) + strlen(device));
						sprintf(notification, TEXT_CHANGE, device, major, minor);
						icon = ICON_CHANGE;
						break;
					default:
						// we should never get here I think...
						notification = (char *) malloc(strlen(TEXT_DEFAULT) + strlen(device));
						sprintf(notification, TEXT_CHANGE, device, major, minor);
						icon = ICON_DEFAULT;
				}

				blkid_get_cache(&cache, read);
				blkdev = blkid_get_dev(cache, udev_device_get_devnode(dev), BLKID_DEV_NORMAL);
			
				if (blkdev) {
					iter = blkid_tag_iterate_begin(blkdev);
			
					while (blkid_tag_next(iter, &type, &value) == 0) {
						notification = (char *) realloc(notification, strlen(TEXT_TAG) + strlen(notification) + strlen(type) + strlen(value));
						sprintf(notification, TEXT_TAG, notification, type, value);
					}

					blkid_tag_iterate_end(iter);
					blkid_put_cache(cache);
				}

				printf("%s: %s\n", argv[0], notification);

				if (maxminor[major] < minor) {
					netlinkref[major] = realloc(netlinkref[major], (minor + 1) * sizeof(size_t));
			                while(maxminor[major] < minor)
			                        netlinkref[major][++maxminor[major]] = NULL;
			        }
					
				if (netlinkref[major][minor] == NULL) {
					netlink = notify_notification_new("Udev-Block", notification, icon);
					netlinkref[major][minor] = netlink;
				} else {
					netlink = netlinkref[major][minor];
					notify_notification_update(netlink, "Udev-Block", notification, icon);
				}

			        notify_notification_set_timeout(netlink, NOTIFICATION_TIMEOUT);
				notify_notification_set_category(netlink, "Udev-Block");
				notify_notification_set_urgency (netlink, NOTIFY_URGENCY_NORMAL);
	
				while(!notify_notification_show(netlink, &error)) {
					if (errcount > 1) {
						fprintf(stderr, "%s: Looks like we can not reconnect to notification daemon... Exiting.\n", argv[0]);
						exit(EXIT_FAILURE);
					} else {
						g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", argv[0], error->message);
						errcount++;

						g_error_free(error);
						error = NULL;
	
						notify_uninit();

						usleep(500 * 1000);

						if(!notify_init("Udev-Block-Notification")) {
							fprintf(stderr, "%s: Can't create notify.\n", argv[0]);
							exit(EXIT_FAILURE);
						}
					}
				}
				errcount = 0;
	
				free(notification);
				udev_device_unref(dev);
			}
	
			// This is not really needed... But we want to make shure not to eat 100% CPU if anything breaks. ;)
			usleep(500 * 1000);
		}
	}

	udev_unref(udev);
	return EXIT_SUCCESS;
}
Ejemplo n.º 9
0
static int sl_db_update_filesystem(struct sl_database_connection * db, int host_id, int session_id, const char * path) {
	struct stat st;
	int failed = stat(path, &st);
	if (failed)
		return failed;

	struct statfs stfs;
	failed = statfs(path, &stfs);
	if (failed)
		return failed;

	char * device = blkid_devno_to_devname(st.st_dev);
	if (device == NULL) {
		sl_log_write(sl_log_level_notice, sl_log_type_core, "Skip path: { path: %s } because it is not a block device", path);
		return 0;
	}

	char * real_device = realpath(device, NULL);

	blkid_dev dev = blkid_get_dev(cache, real_device, 0);
	// find alternative name
	if (dev == NULL) {
		char * sys_dev;
		asprintf(&sys_dev, "/sys/block/%s/dm/name", real_device + 5);

		int fd = open(sys_dev, O_RDONLY);
		if (fd > -1) {
			char buf[64];
			ssize_t nb_read = read(fd, buf, 64);
			buf[nb_read - 1] = '\0';
			close(fd);

			free(real_device);
			asprintf(&real_device, "/dev/mapper/%s", buf);

			dev = blkid_get_dev(cache, real_device, 0);
		}

		free(sys_dev);
	}
	if (dev == NULL) {
		sl_log_write(sl_log_level_notice, sl_log_type_core, "Skip path: { path: %s } because there is no blkid informations (blkid didn't known filesystem on %s)", path, real_device);
		free(real_device);
		free(device);
		return 0;
	}

	sl_log_write(sl_log_level_notice, sl_log_type_core, "Update filesystem: { path: %s }", path);

	const char * uuid = NULL;
	const char * label = NULL;
	const char * type = NULL;

	blkid_tag_iterate iter = blkid_tag_iterate_begin(dev);
	const char * key, * value;
	while (!blkid_tag_next(iter, &key, &value)) {
		if (!strcmp("UUID", key))
			uuid = value;
		else if (!strcmp("LABEL", key))
			label = value;
		else if (!strcmp("TYPE", key))
			type = value;
	}

	struct sl_filesystem * fs = sl_filesystem_new(uuid, label, type, st.st_dev, path, stfs.f_bfree, stfs.f_blocks, stfs.f_bsize);

	blkid_tag_iterate_end(iter);
	free(device);
	free(real_device);

	int s2fs = db->ops->sync_filesystem(db, session_id, fs);
	if (s2fs < 0) {
		sl_filesystem_free(fs);
		return s2fs;
	}

	failed = sl_db_update_file(db, host_id, session_id, s2fs, path, NULL, &st);

	sl_filesystem_free(fs);

	return failed;
}