projects/linux·blob master · refs

821 lines · 20.4 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * fs/sysfs/file.c - sysfs regular (text) file implementation
4 *
5 * Copyright (c) 2001-3 Patrick Mochel
6 * Copyright (c) 2007 SUSE Linux Products GmbH
7 * Copyright (c) 2007 Tejun Heo <[email protected]>
8 *
9 * Please see Documentation/filesystems/sysfs.rst for more information.
10 */
11
12#include <linux/module.h>
13#include <linux/kobject.h>
14#include <linux/slab.h>
15#include <linux/list.h>
16#include <linux/mutex.h>
17#include <linux/seq_file.h>
18#include <linux/mm.h>
19
20#include "sysfs.h"
21
22static struct kobject *sysfs_file_kobj(struct kernfs_node *kn)
23{
24 guard(rcu)();
25 return rcu_dereference(kn->__parent)->priv;
26}
27
28/*
29 * Determine ktype->sysfs_ops for the given kernfs_node. This function
30 * must be called while holding an active reference.
31 */
32static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
33{
34 struct kobject *kobj = sysfs_file_kobj(kn);
35
36 if (kn->flags & KERNFS_LOCKDEP)
37 lockdep_assert_held(kn);
38 return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
39}
40
41/*
42 * Reads on sysfs are handled through seq_file, which takes care of hairy
43 * details like buffering and seeking. The following function pipes
44 * sysfs_ops->show() result through seq_file.
45 */
46static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
47{
48 struct kernfs_open_file *of = sf->private;
49 struct kobject *kobj = sysfs_file_kobj(of->kn);
50 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
51 ssize_t count;
52 char *buf;
53
54 if (WARN_ON_ONCE(!ops->show))
55 return -EINVAL;
56
57 /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
58 count = seq_get_buf(sf, &buf);
59 if (count < PAGE_SIZE) {
60 seq_commit(sf, -1);
61 return 0;
62 }
63 memset(buf, 0, PAGE_SIZE);
64
65 count = ops->show(kobj, of->kn->priv, buf);
66 if (count < 0)
67 return count;
68
69 /*
70 * The code works fine with PAGE_SIZE return but it's likely to
71 * indicate truncated result or overflow in normal use cases.
72 */
73 if (count >= PAGE_SIZE) {
74 WARN(1, "OOB write or bad count %zd at %pS\n", count, ops->show);
75 /* Try to struggle along */
76 count = PAGE_SIZE - 1;
77 }
78 seq_commit(sf, count);
79 return 0;
80}
81
82static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
83 size_t count, loff_t pos)
84{
85 const struct bin_attribute *battr = of->kn->priv;
86 struct kobject *kobj = sysfs_file_kobj(of->kn);
87 loff_t size = file_inode(of->file)->i_size;
88
89 if (!count)
90 return 0;
91
92 if (size) {
93 if (pos >= size)
94 return 0;
95 if (pos + count > size)
96 count = size - pos;
97 }
98
99 if (!battr->read)
100 return -EIO;
101
102 return battr->read(of->file, kobj, battr, buf, pos, count);
103}
104
105/* kernfs read callback for regular sysfs files with pre-alloc */
106static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
107 size_t count, loff_t pos)
108{
109 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
110 struct kobject *kobj = sysfs_file_kobj(of->kn);
111 ssize_t len;
112
113 /*
114 * If buf != of->prealloc_buf, we don't know how
115 * large it is, so cannot safely pass it to ->show
116 */
117 if (WARN_ON_ONCE(buf != of->prealloc_buf))
118 return 0;
119 len = ops->show(kobj, of->kn->priv, buf);
120 if (len < 0)
121 return len;
122 if (len >= (ssize_t)PAGE_SIZE) {
123 printk("fill_read_buffer: %pS returned bad count\n", ops->show);
124 len = PAGE_SIZE - 1;
125 }
126 if (pos) {
127 if (len <= pos)
128 return 0;
129 len -= pos;
130 memmove(buf, buf + pos, len);
131 }
132 return min_t(ssize_t, count, len);
133}
134
135/* kernfs write callback for regular sysfs files */
136static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
137 size_t count, loff_t pos)
138{
139 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
140 struct kobject *kobj = sysfs_file_kobj(of->kn);
141
142 if (!count)
143 return 0;
144
145 return ops->store(kobj, of->kn->priv, buf, count);
146}
147
148/* kernfs write callback for bin sysfs files */
149static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
150 size_t count, loff_t pos)
151{
152 const struct bin_attribute *battr = of->kn->priv;
153 struct kobject *kobj = sysfs_file_kobj(of->kn);
154 loff_t size = file_inode(of->file)->i_size;
155
156 if (size) {
157 if (size <= pos)
158 return -EFBIG;
159 count = min_t(ssize_t, count, size - pos);
160 }
161 if (!count)
162 return 0;
163
164 if (!battr->write)
165 return -EIO;
166
167 return battr->write(of->file, kobj, battr, buf, pos, count);
168}
169
170static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
171 struct vm_area_struct *vma)
172{
173 const struct bin_attribute *battr = of->kn->priv;
174 struct kobject *kobj = sysfs_file_kobj(of->kn);
175
176 return battr->mmap(of->file, kobj, battr, vma);
177}
178
179static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
180 int whence)
181{
182 const struct bin_attribute *battr = of->kn->priv;
183 struct kobject *kobj = sysfs_file_kobj(of->kn);
184
185 if (battr->llseek)
186 return battr->llseek(of->file, kobj, battr, offset, whence);
187 else
188 return generic_file_llseek(of->file, offset, whence);
189}
190
191static int sysfs_kf_bin_open(struct kernfs_open_file *of)
192{
193 const struct bin_attribute *battr = of->kn->priv;
194
195 if (battr->f_mapping)
196 of->file->f_mapping = battr->f_mapping();
197
198 return 0;
199}
200
201void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
202{
203 struct kernfs_node *kn = kobj->sd, *tmp;
204
205 if (kn && dir)
206 kn = kernfs_find_and_get(kn, dir);
207 else
208 kernfs_get(kn);
209
210 if (kn && attr) {
211 tmp = kernfs_find_and_get(kn, attr);
212 kernfs_put(kn);
213 kn = tmp;
214 }
215
216 if (kn) {
217 kernfs_notify(kn);
218 kernfs_put(kn);
219 }
220}
221EXPORT_SYMBOL_GPL(sysfs_notify);
222
223static const struct kernfs_ops sysfs_file_kfops_empty = {
224};
225
226static const struct kernfs_ops sysfs_file_kfops_ro = {
227 .seq_show = sysfs_kf_seq_show,
228};
229
230static const struct kernfs_ops sysfs_file_kfops_wo = {
231 .write = sysfs_kf_write,
232};
233
234static const struct kernfs_ops sysfs_file_kfops_rw = {
235 .seq_show = sysfs_kf_seq_show,
236 .write = sysfs_kf_write,
237};
238
239static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
240 .read = sysfs_kf_read,
241 .prealloc = true,
242};
243
244static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
245 .write = sysfs_kf_write,
246 .prealloc = true,
247};
248
249static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
250 .read = sysfs_kf_read,
251 .write = sysfs_kf_write,
252 .prealloc = true,
253};
254
255static const struct kernfs_ops sysfs_bin_kfops_ro = {
256 .read = sysfs_kf_bin_read,
257};
258
259static const struct kernfs_ops sysfs_bin_kfops_wo = {
260 .write = sysfs_kf_bin_write,
261};
262
263static const struct kernfs_ops sysfs_bin_kfops_rw = {
264 .read = sysfs_kf_bin_read,
265 .write = sysfs_kf_bin_write,
266};
267
268static const struct kernfs_ops sysfs_bin_kfops_mmap = {
269 .read = sysfs_kf_bin_read,
270 .write = sysfs_kf_bin_write,
271 .mmap = sysfs_kf_bin_mmap,
272 .open = sysfs_kf_bin_open,
273 .llseek = sysfs_kf_bin_llseek,
274};
275
276int sysfs_add_file_mode_ns(struct kernfs_node *parent,
277 const struct attribute *attr, umode_t mode, kuid_t uid,
278 kgid_t gid, const struct ns_common *ns)
279{
280 struct kobject *kobj = parent->priv;
281 const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
282 struct lock_class_key *key = NULL;
283 const struct kernfs_ops *ops = NULL;
284 struct kernfs_node *kn;
285
286 /* every kobject with an attribute needs a ktype assigned */
287 if (WARN(!sysfs_ops, KERN_ERR
288 "missing sysfs attribute operations for kobject: %s\n",
289 kobject_name(kobj)))
290 return -EINVAL;
291
292 if (mode & SYSFS_PREALLOC) {
293 if (sysfs_ops->show && sysfs_ops->store)
294 ops = &sysfs_prealloc_kfops_rw;
295 else if (sysfs_ops->show)
296 ops = &sysfs_prealloc_kfops_ro;
297 else if (sysfs_ops->store)
298 ops = &sysfs_prealloc_kfops_wo;
299 } else {
300 if (sysfs_ops->show && sysfs_ops->store)
301 ops = &sysfs_file_kfops_rw;
302 else if (sysfs_ops->show)
303 ops = &sysfs_file_kfops_ro;
304 else if (sysfs_ops->store)
305 ops = &sysfs_file_kfops_wo;
306 }
307
308 if (!ops)
309 ops = &sysfs_file_kfops_empty;
310
311#ifdef CONFIG_DEBUG_LOCK_ALLOC
312 if (!attr->ignore_lockdep)
313 key = attr->key ?: (struct lock_class_key *)&attr->skey;
314#endif
315
316 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
317 PAGE_SIZE, ops, (void *)attr, ns, key);
318 if (IS_ERR(kn)) {
319 if (PTR_ERR(kn) == -EEXIST)
320 sysfs_warn_dup(parent, attr->name);
321 return PTR_ERR(kn);
322 }
323 return 0;
324}
325
326int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
327 const struct bin_attribute *battr, umode_t mode, size_t size,
328 kuid_t uid, kgid_t gid, const struct ns_common *ns)
329{
330 const struct attribute *attr = &battr->attr;
331 struct lock_class_key *key = NULL;
332 const struct kernfs_ops *ops;
333 struct kernfs_node *kn;
334
335 if (battr->mmap)
336 ops = &sysfs_bin_kfops_mmap;
337 else if (battr->read && battr->write)
338 ops = &sysfs_bin_kfops_rw;
339 else if (battr->read)
340 ops = &sysfs_bin_kfops_ro;
341 else if (battr->write)
342 ops = &sysfs_bin_kfops_wo;
343 else
344 ops = &sysfs_file_kfops_empty;
345
346#ifdef CONFIG_DEBUG_LOCK_ALLOC
347 if (!attr->ignore_lockdep)
348 key = attr->key ?: (struct lock_class_key *)&attr->skey;
349#endif
350
351 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
352 size, ops, (void *)attr, ns, key);
353 if (IS_ERR(kn)) {
354 if (PTR_ERR(kn) == -EEXIST)
355 sysfs_warn_dup(parent, attr->name);
356 return PTR_ERR(kn);
357 }
358 return 0;
359}
360
361/**
362 * sysfs_create_file_ns - create an attribute file for an object with custom ns
363 * @kobj: object we're creating for
364 * @attr: attribute descriptor
365 * @ns: namespace the new file should belong to
366 */
367int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
368 const struct ns_common *ns)
369{
370 kuid_t uid;
371 kgid_t gid;
372
373 if (WARN_ON(!kobj || !kobj->sd || !attr))
374 return -EINVAL;
375
376 kobject_get_ownership(kobj, &uid, &gid);
377 return sysfs_add_file_mode_ns(kobj->sd, attr, attr->mode, uid, gid, ns);
378}
379EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
380
381int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr)
382{
383 int err = 0;
384 int i;
385
386 for (i = 0; ptr[i] && !err; i++)
387 err = sysfs_create_file(kobj, ptr[i]);
388 if (err)
389 while (--i >= 0)
390 sysfs_remove_file(kobj, ptr[i]);
391 return err;
392}
393EXPORT_SYMBOL_GPL(sysfs_create_files);
394
395/**
396 * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
397 * @kobj: object we're acting for.
398 * @attr: attribute descriptor.
399 * @group: group name.
400 */
401int sysfs_add_file_to_group(struct kobject *kobj,
402 const struct attribute *attr, const char *group)
403{
404 struct kernfs_node *parent;
405 kuid_t uid;
406 kgid_t gid;
407 int error;
408
409 if (group) {
410 parent = kernfs_find_and_get(kobj->sd, group);
411 } else {
412 parent = kobj->sd;
413 kernfs_get(parent);
414 }
415
416 if (!parent)
417 return -ENOENT;
418
419 kobject_get_ownership(kobj, &uid, &gid);
420 error = sysfs_add_file_mode_ns(parent, attr, attr->mode, uid, gid,
421 NULL);
422 kernfs_put(parent);
423
424 return error;
425}
426EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
427
428/**
429 * sysfs_chmod_file - update the modified mode value on an object attribute.
430 * @kobj: object we're acting for.
431 * @attr: attribute descriptor.
432 * @mode: file permissions.
433 *
434 */
435int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
436 umode_t mode)
437{
438 struct kernfs_node *kn;
439 struct iattr newattrs;
440 int rc;
441
442 kn = kernfs_find_and_get(kobj->sd, attr->name);
443 if (!kn)
444 return -ENOENT;
445
446 newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO);
447 newattrs.ia_valid = ATTR_MODE;
448
449 rc = kernfs_setattr(kn, &newattrs);
450
451 kernfs_put(kn);
452 return rc;
453}
454EXPORT_SYMBOL_GPL(sysfs_chmod_file);
455
456/**
457 * sysfs_break_active_protection - break "active" protection
458 * @kobj: The kernel object @attr is associated with.
459 * @attr: The attribute to break the "active" protection for.
460 *
461 * With sysfs, just like kernfs, deletion of an attribute is postponed until
462 * all active .show() and .store() callbacks have finished unless this function
463 * is called. Hence this function is useful in methods that implement self
464 * deletion.
465 */
466struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
467 const struct attribute *attr)
468{
469 struct kernfs_node *kn;
470
471 kobject_get(kobj);
472 kn = kernfs_find_and_get(kobj->sd, attr->name);
473 if (kn)
474 kernfs_break_active_protection(kn);
475 else
476 kobject_put(kobj);
477 return kn;
478}
479EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
480
481/**
482 * sysfs_unbreak_active_protection - restore "active" protection
483 * @kn: Pointer returned by sysfs_break_active_protection().
484 *
485 * Undo the effects of sysfs_break_active_protection(). Since this function
486 * calls kernfs_put() on the kernfs node that corresponds to the 'attr'
487 * argument passed to sysfs_break_active_protection() that attribute may have
488 * been removed between the sysfs_break_active_protection() and
489 * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after
490 * this function has returned.
491 */
492void sysfs_unbreak_active_protection(struct kernfs_node *kn)
493{
494 struct kobject *kobj = sysfs_file_kobj(kn);
495
496 kernfs_unbreak_active_protection(kn);
497 kernfs_put(kn);
498 kobject_put(kobj);
499}
500EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
501
502/**
503 * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
504 * @kobj: object we're acting for
505 * @attr: attribute descriptor
506 * @ns: namespace tag of the file to remove
507 *
508 * Hash the attribute name and namespace tag and kill the victim.
509 */
510void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
511 const struct ns_common *ns)
512{
513 struct kernfs_node *parent = kobj->sd;
514
515 kernfs_remove_by_name_ns(parent, attr->name, ns);
516}
517EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
518
519/**
520 * sysfs_remove_file_self - remove an object attribute from its own method
521 * @kobj: object we're acting for
522 * @attr: attribute descriptor
523 *
524 * See kernfs_remove_self() for details.
525 */
526bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
527{
528 struct kernfs_node *parent = kobj->sd;
529 struct kernfs_node *kn;
530 bool ret;
531
532 kn = kernfs_find_and_get(parent, attr->name);
533 if (WARN_ON_ONCE(!kn))
534 return false;
535
536 ret = kernfs_remove_self(kn);
537
538 kernfs_put(kn);
539 return ret;
540}
541EXPORT_SYMBOL_GPL(sysfs_remove_file_self);
542
543void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr)
544{
545 int i;
546
547 for (i = 0; ptr[i]; i++)
548 sysfs_remove_file(kobj, ptr[i]);
549}
550EXPORT_SYMBOL_GPL(sysfs_remove_files);
551
552/**
553 * sysfs_remove_file_from_group - remove an attribute file from a group.
554 * @kobj: object we're acting for.
555 * @attr: attribute descriptor.
556 * @group: group name.
557 */
558void sysfs_remove_file_from_group(struct kobject *kobj,
559 const struct attribute *attr, const char *group)
560{
561 struct kernfs_node *parent;
562
563 if (group) {
564 parent = kernfs_find_and_get(kobj->sd, group);
565 } else {
566 parent = kobj->sd;
567 kernfs_get(parent);
568 }
569
570 if (parent) {
571 kernfs_remove_by_name(parent, attr->name);
572 kernfs_put(parent);
573 }
574}
575EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
576
577/**
578 * sysfs_create_bin_file - create binary file for object.
579 * @kobj: object.
580 * @attr: attribute descriptor.
581 */
582int sysfs_create_bin_file(struct kobject *kobj,
583 const struct bin_attribute *attr)
584{
585 kuid_t uid;
586 kgid_t gid;
587
588 if (WARN_ON(!kobj || !kobj->sd || !attr))
589 return -EINVAL;
590
591 kobject_get_ownership(kobj, &uid, &gid);
592 return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode,
593 attr->size, uid, gid, NULL);
594}
595EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
596
597/**
598 * sysfs_remove_bin_file - remove binary file for object.
599 * @kobj: object.
600 * @attr: attribute descriptor.
601 */
602void sysfs_remove_bin_file(struct kobject *kobj,
603 const struct bin_attribute *attr)
604{
605 kernfs_remove_by_name(kobj->sd, attr->attr.name);
606}
607EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
608
609static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid,
610 kgid_t kgid)
611{
612 struct iattr newattrs = {
613 .ia_valid = ATTR_UID | ATTR_GID,
614 .ia_uid = kuid,
615 .ia_gid = kgid,
616 };
617 return kernfs_setattr(kn, &newattrs);
618}
619
620/**
621 * sysfs_link_change_owner - change owner of a sysfs file.
622 * @kobj: object of the kernfs_node the symlink is located in.
623 * @targ: object of the kernfs_node the symlink points to.
624 * @name: name of the link.
625 * @kuid: new owner's kuid
626 * @kgid: new owner's kgid
627 *
628 * This function looks up the sysfs symlink entry @name under @kobj and changes
629 * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of
630 * @targ.
631 *
632 * Returns 0 on success or error code on failure.
633 */
634int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
635 const char *name, kuid_t kuid, kgid_t kgid)
636{
637 struct kernfs_node *kn = NULL;
638 int error;
639
640 if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs)
641 return -EINVAL;
642
643 error = -ENOENT;
644 kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns);
645 if (!kn)
646 goto out;
647
648 error = -EINVAL;
649 if (kernfs_type(kn) != KERNFS_LINK)
650 goto out;
651 if (kn->symlink.target_kn->priv != targ)
652 goto out;
653
654 error = internal_change_owner(kn, kuid, kgid);
655
656out:
657 kernfs_put(kn);
658 return error;
659}
660
661/**
662 * sysfs_file_change_owner - change owner of a sysfs file.
663 * @kobj: object.
664 * @name: name of the file to change.
665 * @kuid: new owner's kuid
666 * @kgid: new owner's kgid
667 *
668 * This function looks up the sysfs entry @name under @kobj and changes the
669 * ownership to @kuid/@kgid.
670 *
671 * Returns 0 on success or error code on failure.
672 */
673int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid,
674 kgid_t kgid)
675{
676 struct kernfs_node *kn;
677 int error;
678
679 if (!name)
680 return -EINVAL;
681
682 if (!kobj->state_in_sysfs)
683 return -EINVAL;
684
685 kn = kernfs_find_and_get(kobj->sd, name);
686 if (!kn)
687 return -ENOENT;
688
689 error = internal_change_owner(kn, kuid, kgid);
690
691 kernfs_put(kn);
692
693 return error;
694}
695
696/**
697 * sysfs_change_owner - change owner of the given object.
698 * @kobj: object.
699 * @kuid: new owner's kuid
700 * @kgid: new owner's kgid
701 *
702 * Change the owner of the default directory, files, groups, and attributes of
703 * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs
704 * entries for a kobject are added by driver core. In summary,
705 * sysfs_change_owner() takes care of the default directory entry for @kobj,
706 * the default attributes associated with the ktype of @kobj and the default
707 * attributes associated with the ktype of @kobj.
708 * Additional properties not added by driver core have to be changed by the
709 * driver or subsystem which created them. This is similar to how
710 * driver/subsystem specific entries are removed.
711 *
712 * Returns 0 on success or error code on failure.
713 */
714int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid)
715{
716 int error;
717 const struct kobj_type *ktype;
718
719 if (!kobj->state_in_sysfs)
720 return -EINVAL;
721
722 /* Change the owner of the kobject itself. */
723 error = internal_change_owner(kobj->sd, kuid, kgid);
724 if (error)
725 return error;
726
727 ktype = get_ktype(kobj);
728 if (ktype) {
729 /*
730 * Change owner of the default groups associated with the
731 * ktype of @kobj.
732 */
733 error = sysfs_groups_change_owner(kobj, ktype->default_groups,
734 kuid, kgid);
735 if (error)
736 return error;
737 }
738
739 return 0;
740}
741
742/**
743 * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer.
744 * @buf: start of PAGE_SIZE buffer.
745 * @fmt: format
746 * @...: optional arguments to @format
747 *
748 *
749 * Returns number of characters written to @buf.
750 */
751int sysfs_emit(char *buf, const char *fmt, ...)
752{
753 va_list args;
754 int len;
755
756 if (WARN(!buf || offset_in_page(buf),
757 "invalid sysfs_emit: buf:%p\n", buf))
758 return 0;
759
760 va_start(args, fmt);
761 len = vscnprintf(buf, PAGE_SIZE, fmt, args);
762 va_end(args);
763
764 return len;
765}
766EXPORT_SYMBOL_GPL(sysfs_emit);
767
768/**
769 * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer.
770 * @buf: start of PAGE_SIZE buffer.
771 * @at: offset in @buf to start write in bytes
772 * @at must be >= 0 && < PAGE_SIZE
773 * @fmt: format
774 * @...: optional arguments to @fmt
775 *
776 *
777 * Returns number of characters written starting at &@buf[@at].
778 */
779int sysfs_emit_at(char *buf, int at, const char *fmt, ...)
780{
781 va_list args;
782 int len;
783
784 if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE,
785 "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at))
786 return 0;
787
788 va_start(args, fmt);
789 len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args);
790 va_end(args);
791
792 return len;
793}
794EXPORT_SYMBOL_GPL(sysfs_emit_at);
795
796/**
797 * sysfs_bin_attr_simple_read - read callback to simply copy from memory.
798 * @file: attribute file which is being read.
799 * @kobj: object to which the attribute belongs.
800 * @attr: attribute descriptor.
801 * @buf: destination buffer.
802 * @off: offset in bytes from which to read.
803 * @count: maximum number of bytes to read.
804 *
805 * Simple ->read() callback for bin_attributes backed by a buffer in memory.
806 * The @private and @size members in struct bin_attribute must be set to the
807 * buffer's location and size before the bin_attribute is created in sysfs.
808 *
809 * Bounds check for @off and @count is done in sysfs_kf_bin_read().
810 * Negative value check for @off is done in vfs_setpos() and default_llseek().
811 *
812 * Returns number of bytes written to @buf.
813 */
814ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj,
815 const struct bin_attribute *attr, char *buf,
816 loff_t off, size_t count)
817{
818 memcpy(buf, attr->private + off, count);
819 return count;
820}
821EXPORT_SYMBOL_GPL(sysfs_bin_attr_simple_read);