You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.0 KiB

/* vim:set ts=4 sw=4 tw=0 noet ft=c:
*
* fs/sdcardfs/sysfs.c
*
* Copyright (C) 2017, Inc.
* Author: gaoxiang
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details.
*/
#include "sdcardfs.h"
#ifdef SDCARDFS_PLUGIN_PRIVACY_SPACE
static ssize_t
sdcardfs_sysfs_sb_blocked_users_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf) {
struct sdcardfs_sb_info *sbi = container_of(kobj,
struct sdcardfs_sb_info, kobj);
ssize_t len = 0;
if (sbi->blocked_userid >= 0)
len = snprintf(buf, PAGE_SIZE, "%d %d",
sbi->blocked_userid, sbi->appid_excluded);
buf[len++] = '\n';
buf[len++] = '\0';
return len;
}
static ssize_t
sdcardfs_sysfs_sb_blocked_users_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t len) {
struct sdcardfs_sb_info *sbi = container_of(kobj,
struct sdcardfs_sb_info, kobj);
int args = sscanf(buf, "%d%d", &sbi->blocked_userid,
&sbi->appid_excluded);
if (args <= 0)
sbi->blocked_userid = -1;
else if (args <= 1)
sbi->appid_excluded = -1;
/* print some debug messages for the privacyspace feature */
if (sbi->blocked_userid < 0)
pr_warn("all users have access to %s now", kobj->name);
else {
pr_warn("user/%d has been blocked from accessing %s",
sbi->blocked_userid, kobj->name);
if (sbi->appid_excluded >= 0)
pr_warn("but appid/%d will be excluded",
sbi->appid_excluded);
}
return len;
}
#endif
static ssize_t
sdcardfs_sysfs_sb_device_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf) {
struct sdcardfs_sb_info *sbi = container_of(kobj,
struct sdcardfs_sb_info, kobj);
return snprintf(buf, PAGE_SIZE, "%s\n", sbi->obbpath_s);
}
static void __sdcardfs_sysfs_sb_release(struct kobject *kobj)
{
struct sdcardfs_sb_info *sbi = container_of(kobj,
struct sdcardfs_sb_info, kobj);
kfree(sbi);
}
static ssize_t
sdcardfs_sysfs_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
struct kobj_attribute *ka =
container_of(attr, struct kobj_attribute, attr);
return ka->show(kobj, ka, buf);
}
static ssize_t
sdcardfs_sysfs_attr_store(struct kobject *kobj,
struct attribute *attr, const char *buf,
size_t len)
{
struct kobj_attribute *ka;
char *s = skip_spaces(buf);
len -= s - buf;
buf = s;
if (len == 0 || *buf == '\0')
return -EINVAL;
ka = container_of(attr, struct kobj_attribute, attr);
return ka->store(kobj, ka, buf, len);
}
#define __SYSFS_ATTR_RW(name) \
(struct kobj_attribute)__ATTR(name, S_IWUSR | S_IRUGO, \
sdcardfs_sysfs_sb_##name##_show, sdcardfs_sysfs_sb_##name##_store)
#define __SYSFS_ATTR_RO(name) \
(struct kobj_attribute)__ATTR(name, S_IRUGO, \
sdcardfs_sysfs_sb_##name##_show, NULL)
static struct sysfs_ops sysfs_op = {
.show = sdcardfs_sysfs_attr_show,
.store = sdcardfs_sysfs_attr_store
};
static struct attribute *sb_attrs[] = {
&__SYSFS_ATTR_RO(device).attr,
#ifdef SDCARDFS_PLUGIN_PRIVACY_SPACE
&__SYSFS_ATTR_RW(blocked_users).attr,
#endif
NULL, /* need to NULL terminate the list of attributes */
};
static struct kobj_type sb_ktype = {
.release = __sdcardfs_sysfs_sb_release,
.sysfs_ops = &sysfs_op,
.default_attrs = sb_attrs,
};
static struct kset *sdcardfs_kset;
int sdcardfs_sysfs_init(void)
{
/* located under /sys/fs/ */
sdcardfs_kset = kset_create_and_add(SDCARDFS_NAME, NULL, fs_kobj);
return sdcardfs_kset == NULL ? -ENOMEM : 0;
}
void sdcardfs_sysfs_exit(void)
{
BUG_ON(sdcardfs_kset == NULL);
kset_unregister(sdcardfs_kset);
}
int sdcardfs_sysfs_register_sb(struct super_block *sb)
{
int err;
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(sb);
BUG_ON(sdcardfs_kset == NULL);
sbi->kobj.kset = sdcardfs_kset;
err = kobject_init_and_add(&sbi->kobj, &sb_ktype, NULL,
"%u:%u", MAJOR(sb->s_dev), MINOR(sb->s_dev));
if (err) {
//errln("failed to kobject_init_and_add, err=%d", err);
pr_err("failed to kobject_init_and_add, err=%d", err);
return err;
}
/* send the uevent that the kobject is added to the sysfs */
kobject_uevent(&sbi->kobj, KOBJ_ADD);
return 0;
}