#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include "sysfs.h"
#include "util.h"


/**
 *	get_mntpt - Check /proc/mounts for where sysfs is mounted.
 */
 
static int get_mntpt(char ** mnt)
{
	FILE * filp;
	char buffer[512];
	char * s;
	int error = -ENODEV;

	filp = fopen("/proc/mounts", "r");
	if (!filp)
		return -EFAULT;

	while ((s = fgets(buffer,512,filp))) {
		char * fstype, * mntpt, * fsname, * end;

		fstype = s;
		mntpt = strchr(s,' ');
		if (mntpt)
			*mntpt++ = '\0';
		else 
			continue;

		fsname = strchr(mntpt,' ');
		if (fsname)
			*fsname++ = '\0';
		else
			continue;

		end = strchr(fsname,' ');
		if (end)
			*end++ = '\0';
		else
			continue;

		if (!strcmp(fsname,"sysfs")) {
			*mnt = strdup(mntpt);
			if (*mnt)
				error = 0;
			else
				error = -ENOMEM;
			goto Done;
		}
	}
Done:
	fclose(filp);
	return error;
}


int sysfs_init(struct sysfs_info * si)
{
	int ret;

	ret = open(".", O_RDONLY);
	if (ret > 0) {
		si->si_cwd_fd = ret;
		ret = 0;
	} else
		return ret;

	if ((ret = get_mntpt(&si->si_mount_dir)))
		goto CloseCwd;

	ret = open(si->si_mount_dir, O_RDONLY);
	if (ret > 0) {
		si->si_mount_fd = ret;
		ret = 0;
		dbg("sysfs mount point opened at %s\n", si->si_mount_dir);
		ret = fchdir(si->si_mount_fd);
		if (ret < 0)
			goto CloseMnt;
	} else
		goto FreeMnt;

 Done:
	return ret;

 CloseMnt:
	close(si->si_mount_fd);
	si->si_mount_fd = 0;
 FreeMnt:
	free(si->si_mount_dir);
	si->si_mount_dir = 0;
 CloseCwd:
	close(si->si_cwd_fd);
	si->si_cwd_fd = 0;
	goto Done;
}


void sysfs_exit(struct sysfs_info * si)
{
	fchdir(si->si_cwd_fd);

	close(si->si_mount_fd);
	free(si->si_mount_dir);

	close(si->si_cwd_fd);
	memset(si, 0, sizeof(struct sysfs_info));
}

