Add basic support for mini2440 board to barebox.
[barebox-mini2440.git] / fs / fs.c
blob3b5f2847c75f27ec3f55840e8bb63811ef122ca0
1 /*
2 * fs.c - posix like file functions
4 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
6 * See file CREDITS for list of people who contributed to this
7 * project.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <common.h>
24 #include <fs.h>
25 #include <driver.h>
26 #include <errno.h>
27 #include <malloc.h>
28 #include <linux/stat.h>
29 #include <fcntl.h>
30 #include <xfuncs.h>
31 #include <init.h>
32 #include <module.h>
34 void *read_file(const char *filename, size_t *size)
36 int fd;
37 struct stat s;
38 void *buf = NULL;
40 if (stat(filename, &s))
41 return NULL;
43 buf = xzalloc(s.st_size + 1);
45 fd = open(filename, O_RDONLY);
46 if (fd < 0)
47 goto err_out;
49 if (read(fd, buf, s.st_size) < s.st_size)
50 goto err_out1;
52 close(fd);
54 if (size)
55 *size = s.st_size;
57 return buf;
59 err_out1:
60 close(fd);
61 err_out:
62 free(buf);
63 return NULL;
66 EXPORT_SYMBOL(read_file);
68 char *mkmodestr(unsigned long mode, char *str)
70 static const char *l = "xwr";
71 int mask = 1, i;
72 char c;
74 switch (mode & S_IFMT) {
75 case S_IFDIR: str[0] = 'd'; break;
76 case S_IFBLK: str[0] = 'b'; break;
77 case S_IFCHR: str[0] = 'c'; break;
78 case S_IFIFO: str[0] = 'f'; break;
79 case S_IFLNK: str[0] = 'l'; break;
80 case S_IFSOCK: str[0] = 's'; break;
81 case S_IFREG: str[0] = '-'; break;
82 default: str[0] = '?';
85 for(i = 0; i < 9; i++) {
86 c = l[i%3];
87 str[9-i] = (mode & mask)?c:'-';
88 mask = mask<<1;
91 if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
92 if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
93 if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
94 str[10] = '\0';
95 return str;
97 EXPORT_SYMBOL(mkmodestr);
99 static char *cwd;
101 static int init_cwd(void)
103 cwd = xzalloc(PATH_MAX);
104 *cwd = '/';
105 return 0;
108 postcore_initcall(init_cwd);
110 char *normalise_path(const char *pathname)
112 char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2);
113 char *in, *out, *slashes[32];
114 int sl = 0;
116 debug("in: %s\n", pathname);
118 if (*pathname != '/')
119 strcpy(path, cwd);
120 strcat(path, "/");
121 strcat(path, pathname);
123 slashes[0] = in = out = path;
125 while (*in) {
126 if(*in == '/') {
127 slashes[sl++] = out;
128 *out++ = *in++;
129 while(*in == '/')
130 in++;
131 } else {
132 if (*in == '.' && (*(in + 1) == '/' || !*(in + 1))) {
133 sl--;
134 if (sl < 0)
135 sl = 0;
136 out = slashes[sl];
137 in++;
138 continue;
140 if (*in == '.' && *(in + 1) == '.') {
141 sl -= 2;
142 if (sl < 0)
143 sl = 0;
144 out = slashes[sl];
145 in += 2;
146 continue;
148 *out++ = *in++;
152 *out-- = 0;
155 * Remove trailing slash
157 if (*out == '/')
158 *out = 0;
160 if (!*path) {
161 *path = '/';
162 *(path + 1) = 0;
165 return path;
167 EXPORT_SYMBOL(normalise_path);
169 static struct mtab_entry *mtab;
171 struct mtab_entry *get_mtab_entry_by_path(const char *_path)
173 struct mtab_entry *match = NULL, *e = mtab;
174 char *path, *tok;
176 if (*_path != '/')
177 return NULL;
179 path = strdup(_path);
181 tok = strchr(path + 1, '/');
182 if (tok)
183 *tok = 0;
185 while (e) {
186 if (!strcmp(path, e->path)) {
187 match = e;
188 break;
190 e = e->next;
193 free(path);
195 return match ? match : mtab;
198 struct mtab_entry *mtab_next_entry(struct mtab_entry *e)
200 if (!e)
201 return mtab;
202 return e->next;
205 const char *fsdev_get_mountpoint(struct fs_device_d *fsdev)
207 return fsdev->mtab.path;
210 static FILE files[MAX_FILES];
212 static FILE *get_file(void)
214 int i;
216 for (i = 3; i < MAX_FILES; i++) {
217 if (!files[i].in_use) {
218 memset(&files[i], 0, sizeof(FILE));
219 files[i].in_use = 1;
220 files[i].no = i;
221 return &files[i];
224 return NULL;
227 static void put_file(FILE *f)
229 files[f->no].in_use = 0;
232 static int check_fd(int fd)
234 if (fd < 0 || fd >= MAX_FILES || !files[fd].in_use) {
235 errno = -EBADF;
236 return errno;
239 return 0;
242 static struct device_d *get_fs_device_by_path(char **path)
244 struct device_d *dev;
245 struct mtab_entry *e;
247 e = get_mtab_entry_by_path(*path);
248 if (!e)
249 return NULL;
250 if (e != mtab)
251 *path += strlen(e->path);
253 dev = e->dev;
255 return dev;
258 static int dir_is_empty(const char *pathname)
260 DIR *dir;
261 struct dirent *d;
262 int ret = 1;
264 dir = opendir(pathname);
265 if (!dir) {
266 errno = -ENOENT;
267 return -ENOENT;
270 while ((d = readdir(dir))) {
271 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
272 continue;
273 ret = 0;
274 break;
277 closedir(dir);
278 return ret;
281 #define S_UB_IS_EMPTY (1 << 31)
282 #define S_UB_EXISTS (1 << 30)
283 #define S_UB_DOES_NOT_EXIST (1 << 29)
286 * Helper function to check the prerequisites of a path given
287 * to fs functions. Besides the flags above S_IFREG and S_IFDIR
288 * can be passed in.
290 static int path_check_prereq(const char *path, unsigned int flags)
292 struct stat s;
293 unsigned int m;
295 errno = 0;
297 if (stat(path, &s)) {
298 if (flags & S_UB_DOES_NOT_EXIST)
299 return 0;
300 errno = -ENOENT;
301 goto out;
304 if (flags & S_UB_DOES_NOT_EXIST) {
305 errno = -EEXIST;
306 goto out;
309 if (flags == S_UB_EXISTS)
310 return 0;
312 m = s.st_mode;
314 if (S_ISDIR(m)) {
315 if (flags & S_IFREG) {
316 errno = -EISDIR;
317 goto out;
319 if ((flags & S_UB_IS_EMPTY) && !dir_is_empty(path)) {
320 errno = -ENOTEMPTY;
321 goto out;
324 if ((flags & S_IFDIR) && S_ISREG(m)) {
325 errno = -ENOTDIR;
326 goto out;
328 out:
329 return errno;
332 const char *getcwd(void)
334 return cwd;
336 EXPORT_SYMBOL(getcwd);
338 int chdir(const char *pathname)
340 char *p = normalise_path(pathname);
341 errno = 0;
343 if (path_check_prereq(p, S_IFDIR))
344 goto out;
346 strcpy(cwd, p);
348 free(p);
349 out:
350 return errno;
352 EXPORT_SYMBOL(chdir);
354 int unlink(const char *pathname)
356 struct device_d *dev;
357 struct fs_driver_d *fsdrv;
358 char *p = normalise_path(pathname);
359 char *freep = p;
361 if (path_check_prereq(pathname, S_IFREG))
362 goto out;
364 dev = get_fs_device_by_path(&p);
365 if (!dev)
366 goto out;
367 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
369 if (!fsdrv->unlink) {
370 errno = -ENOSYS;
371 goto out;
374 errno = fsdrv->unlink(dev, p);
375 out:
376 free(freep);
377 return errno;
379 EXPORT_SYMBOL(unlink);
381 int open(const char *pathname, int flags, ...)
383 struct device_d *dev;
384 struct fs_driver_d *fsdrv;
385 FILE *f;
386 int exist;
387 struct stat s;
388 char *path = normalise_path(pathname);
389 char *freep = path;
391 exist = (stat(path, &s) == 0) ? 1 : 0;
393 if (exist && S_ISDIR(s.st_mode)) {
394 errno = -EISDIR;
395 goto out1;
398 if (!exist && !(flags & O_CREAT)) {
399 errno = -ENOENT;
400 goto out1;
403 f = get_file();
404 if (!f) {
405 errno = -EMFILE;
406 goto out1;
409 dev = get_fs_device_by_path(&path);
410 if (!dev)
411 goto out;
413 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
415 f->dev = dev;
416 f->flags = flags;
418 if ((flags & O_ACCMODE) && !fsdrv->write) {
419 errno = -EROFS;
420 goto out;
423 if (!exist) {
424 if (NULL != fsdrv->create)
425 errno = fsdrv->create(dev, path,
426 S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
427 else
428 errno = -EROFS;
429 if (errno)
430 goto out;
432 errno = fsdrv->open(dev, f, path);
433 if (errno)
434 goto out;
437 if (flags & O_TRUNC) {
438 errno = fsdrv->truncate(dev, f, 0);
439 f->size = 0;
440 if (errno)
441 goto out;
444 if (flags & O_APPEND)
445 f->pos = f->size;
447 free(freep);
448 return f->no;
450 out:
451 put_file(f);
452 out1:
453 free(freep);
454 return errno;
456 EXPORT_SYMBOL(open);
458 int creat(const char *pathname, mode_t mode)
460 return open(pathname, O_CREAT | O_WRONLY | O_TRUNC);
462 EXPORT_SYMBOL(creat);
464 int ioctl(int fd, int request, void *buf)
466 struct device_d *dev;
467 struct fs_driver_d *fsdrv;
468 FILE *f = &files[fd];
470 if (check_fd(fd))
471 return errno;
473 dev = f->dev;
475 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
477 if (fsdrv->ioctl)
478 errno = fsdrv->ioctl(dev, f, request, buf);
479 else
480 errno = -ENOSYS;
481 return errno;
484 int read(int fd, void *buf, size_t count)
486 struct device_d *dev;
487 struct fs_driver_d *fsdrv;
488 FILE *f = &files[fd];
490 if (check_fd(fd))
491 return errno;
493 dev = f->dev;
495 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
497 if (f->pos + count > f->size)
498 count = f->size - f->pos;
499 errno = fsdrv->read(dev, f, buf, count);
501 if (errno > 0)
502 f->pos += errno;
503 return errno;
505 EXPORT_SYMBOL(read);
507 ssize_t write(int fd, const void *buf, size_t count)
509 struct device_d *dev;
510 struct fs_driver_d *fsdrv;
511 FILE *f = &files[fd];
513 if (check_fd(fd))
514 return errno;
516 dev = f->dev;
518 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
519 if (f->pos + count > f->size) {
520 errno = fsdrv->truncate(dev, f, f->pos + count);
521 if (errno) {
522 if (errno != -ENOSPC)
523 return errno;
524 count = f->size - f->pos;
525 if (!count)
526 return errno;
527 } else {
528 f->size = f->pos + count;
531 errno = fsdrv->write(dev, f, buf, count);
533 if (errno > 0)
534 f->pos += errno;
535 return errno;
537 EXPORT_SYMBOL(write);
539 off_t lseek(int fildes, off_t offset, int whence)
541 struct device_d *dev;
542 struct fs_driver_d *fsdrv;
543 FILE *f = &files[fildes];
544 off_t pos;
546 if (check_fd(fildes))
547 return -1;
549 errno = 0;
551 dev = f->dev;
552 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
553 if (!fsdrv->lseek) {
554 errno = -ENOSYS;
555 return -1;
558 switch(whence) {
559 case SEEK_SET:
560 if (offset > f->size)
561 goto out;
562 pos = offset;
563 break;
564 case SEEK_CUR:
565 if (offset + f->pos > f->size)
566 goto out;
567 pos = f->pos + offset;
568 break;
569 case SEEK_END:
570 if (offset)
571 goto out;
572 pos = f->size;
573 break;
574 default:
575 goto out;
578 return fsdrv->lseek(dev, f, pos);
580 out:
581 errno = -EINVAL;
582 return -1;
584 EXPORT_SYMBOL(lseek);
586 int erase(int fd, size_t count, unsigned long offset)
588 struct device_d *dev;
589 struct fs_driver_d *fsdrv;
590 FILE *f = &files[fd];
592 if (check_fd(fd))
593 return errno;
595 dev = f->dev;
597 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
599 if (f->pos + count > f->size)
600 count = f->size - f->pos;
602 if (fsdrv->erase)
603 errno = fsdrv->erase(dev, f, count, offset);
604 else
605 errno = -ENOSYS;
607 return errno;
609 EXPORT_SYMBOL(erase);
611 int protect(int fd, size_t count, unsigned long offset, int prot)
613 struct device_d *dev;
614 struct fs_driver_d *fsdrv;
615 FILE *f = &files[fd];
617 if (check_fd(fd))
618 return errno;
620 dev = f->dev;
622 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
624 if (f->pos + count > f->size)
625 count = f->size - f->pos;
627 if (fsdrv->protect)
628 errno = fsdrv->protect(dev, f, count, offset, prot);
629 else
630 errno = -ENOSYS;
632 return errno;
634 EXPORT_SYMBOL(protect);
636 int protect_file(const char *file, int prot)
638 int fd, ret;
640 fd = open(file, O_WRONLY);
641 if (fd < 0)
642 return fd;
644 ret = protect(fd, ~0, 0, prot);
646 close(fd);
648 return ret;
651 void *memmap(int fd, int flags)
653 struct device_d *dev;
654 struct fs_driver_d *fsdrv;
655 FILE *f = &files[fd];
656 void *ret = (void *)-1;
658 if (check_fd(fd))
659 return ret;
661 dev = f->dev;
663 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
665 if (fsdrv->memmap)
666 errno = fsdrv->memmap(dev, f, &ret, flags);
667 else
668 errno = -EINVAL;
670 return ret;
672 EXPORT_SYMBOL(memmap);
674 int close(int fd)
676 struct device_d *dev;
677 struct fs_driver_d *fsdrv;
678 FILE *f = &files[fd];
680 if (check_fd(fd))
681 return errno;
683 dev = f->dev;
685 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
686 errno = fsdrv->close(dev, f);
688 put_file(f);
689 return errno;
691 EXPORT_SYMBOL(close);
693 static LIST_HEAD(fs_driver_list);
695 int register_fs_driver(struct fs_driver_d *fsdrv)
697 list_add_tail(&fsdrv->list, &fs_driver_list);
698 register_driver(&fsdrv->drv);
699 return 0;
701 EXPORT_SYMBOL(register_fs_driver);
704 * Mount a device to a directory.
705 * We do this by registering a new device on which the filesystem
706 * driver will match. The filesystem driver then grabs the infomation
707 * it needs from the new devices type_data.
709 int mount(const char *device, const char *fsname, const char *_path)
711 struct fs_driver_d *fs_drv = NULL, *f;
712 struct mtab_entry *entry;
713 struct fs_device_d *fsdev;
714 struct device_d *dev, *parent_device = NULL;
715 int ret;
716 char *path = normalise_path(_path);
718 errno = 0;
720 debug("mount: %s on %s type %s\n", device, path, fsname);
722 if (get_mtab_entry_by_path(path) != mtab) {
723 errno = -EBUSY;
724 goto out;
727 if (strchr(path + 1, '/')) {
728 printf("mounting allowed on first directory level only\n");
729 errno = -EBUSY;
730 goto out;
733 list_for_each_entry(f, &fs_driver_list, list) {
734 if (!strcmp(f->drv.name, fsname)) {
735 fs_drv = f;
736 break;
740 if (!fs_drv) {
741 errno = -EINVAL;
742 goto out;
745 if (mtab) {
746 if (path_check_prereq(path, S_IFDIR))
747 goto out;
748 } else {
749 /* no mtab, so we only allow to mount on '/' */
750 if (*path != '/' || *(path + 1)) {
751 errno = -ENOTDIR;
752 goto out;
756 fsdev = xzalloc(sizeof(struct fs_device_d));
757 if (!fs_drv->flags & FS_DRIVER_NO_DEV) {
758 fsdev->backingstore = strdup(device);
759 if (!device) {
760 printf("need a device for driver %s\n", fsname);
761 errno = -ENODEV;
762 free(fsdev);
763 goto out;
766 sprintf(fsdev->dev.name, "%s", fsname);
767 fsdev->dev.type_data = fsdev;
769 if ((ret = register_device(&fsdev->dev))) {
770 free(fsdev);
771 errno = ret;
772 goto out;
775 if (!fsdev->dev.driver) {
776 /* driver didn't accept the device. Bail out */
777 free(fsdev);
778 errno = -EINVAL;
779 goto out;
782 if (parent_device)
783 dev_add_child(parent_device, &fsdev->dev);
785 dev = &fsdev->dev;
787 /* add mtab entry */
788 entry = &fsdev->mtab;
789 sprintf(entry->path, "%s", path);
790 entry->dev = dev;
791 entry->parent_device = parent_device;
792 entry->next = NULL;
794 if (!mtab)
795 mtab = entry;
796 else {
797 struct mtab_entry *e = mtab;
798 while (e->next)
799 e = e->next;
800 e->next = entry;
802 out:
803 free(path);
804 return errno;
806 EXPORT_SYMBOL(mount);
808 int umount(const char *pathname)
810 struct mtab_entry *entry = mtab;
811 struct mtab_entry *last = mtab;
812 char *p = normalise_path(pathname);
813 struct fs_device_d *fsdev;
815 while(entry && strcmp(p, entry->path)) {
816 last = entry;
817 entry = entry->next;
820 free(p);
822 if (!entry) {
823 errno = -EFAULT;
824 return errno;
827 if (entry == mtab)
828 mtab = mtab->next;
829 else
830 last->next = entry->next;
832 unregister_device(entry->dev);
833 fsdev = entry->dev->type_data;
834 free(fsdev->backingstore);
835 free(fsdev);
837 return 0;
839 EXPORT_SYMBOL(umount);
841 DIR *opendir(const char *pathname)
843 DIR *dir = NULL;
844 struct device_d *dev;
845 struct fs_driver_d *fsdrv;
846 char *p = normalise_path(pathname);
847 char *freep = p;
849 if (path_check_prereq(pathname, S_IFDIR))
850 goto out;
852 dev = get_fs_device_by_path(&p);
853 if (!dev)
854 goto out;
855 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
857 debug("opendir: fsdrv: %p\n",fsdrv);
859 dir = fsdrv->opendir(dev, p);
860 if (dir) {
861 dir->dev = dev;
862 dir->fsdrv = fsdrv;
865 out:
866 free(freep);
867 return dir;
869 EXPORT_SYMBOL(opendir);
871 struct dirent *readdir(DIR *dir)
873 if (!dir)
874 return NULL;
876 return dir->fsdrv->readdir(dir->dev, dir);
878 EXPORT_SYMBOL(readdir);
880 int closedir(DIR *dir)
882 if (!dir) {
883 errno = -EBADF;
884 return -1;
887 return dir->fsdrv->closedir(dir->dev, dir);
889 EXPORT_SYMBOL(closedir);
891 int stat(const char *filename, struct stat *s)
893 struct device_d *dev;
894 struct fs_driver_d *fsdrv;
895 struct mtab_entry *e;
896 char *f = normalise_path(filename);
897 char *freep = f;
899 memset(s, 0, sizeof(struct stat));
901 e = get_mtab_entry_by_path(f);
902 if (!e) {
903 errno = -ENOENT;
904 goto out;
907 if (e != mtab && strcmp(f, e->path)) {
908 f += strlen(e->path);
909 dev = e->dev;
910 } else
911 dev = mtab->dev;
913 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
915 if (*f == 0)
916 f = "/";
918 errno = fsdrv->stat(dev, f, s);
919 out:
920 free(freep);
921 return errno;
923 EXPORT_SYMBOL(stat);
925 int mkdir (const char *pathname, mode_t mode)
927 struct fs_driver_d *fsdrv;
928 struct device_d *dev;
929 char *p = normalise_path(pathname);
930 char *freep = p;
932 if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST))
933 goto out;
935 dev = get_fs_device_by_path(&p);
936 if (!dev)
937 goto out;
938 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
940 if (fsdrv->mkdir) {
941 errno = fsdrv->mkdir(dev, p);
942 goto out;
945 errno = -EROFS;
946 out:
947 free(freep);
948 return errno;
950 EXPORT_SYMBOL(mkdir);
952 int rmdir (const char *pathname)
954 struct fs_driver_d *fsdrv;
955 struct device_d *dev;
956 char *p = normalise_path(pathname);
957 char *freep = p;
959 if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY))
960 goto out;
962 dev = get_fs_device_by_path(&p);
963 if (!dev)
964 goto out;
965 fsdrv = (struct fs_driver_d *)dev->driver->type_data;
967 if (fsdrv->rmdir) {
968 errno = fsdrv->rmdir(dev, p);
969 goto out;
972 errno = -EROFS;
973 out:
974 free(freep);
975 return errno;
977 EXPORT_SYMBOL(rmdir);
979 static void memcpy_sz(void *_dst, const void *_src, ulong count, ulong rwsize)
981 ulong dst = (ulong)_dst;
982 ulong src = (ulong)_src;
984 /* no rwsize specification given. Do whatever memcpy likes best */
985 if (!rwsize) {
986 memcpy(_dst, _src, count);
987 return;
990 rwsize = rwsize >> O_RWSIZE_SHIFT;
992 count /= rwsize;
994 while (count-- > 0) {
995 switch (rwsize) {
996 case 1:
997 *((u_char *)dst) = *((u_char *)src);
998 break;
999 case 2:
1000 *((ushort *)dst) = *((ushort *)src);
1001 break;
1002 case 4:
1003 *((ulong *)dst) = *((ulong *)src);
1004 break;
1006 dst += rwsize;
1007 src += rwsize;
1011 ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags)
1013 ulong size;
1014 struct device_d *dev;
1016 if (!cdev->dev)
1017 return -1;
1018 dev = cdev->dev;
1020 size = min((ulong)count, dev->size - offset);
1021 debug("mem_read: dev->map_base: %p size: %d offset: %d\n",dev->map_base, size, offset);
1022 memcpy_sz(buf, (void *)(dev->map_base + offset), size, flags & O_RWSIZE_MASK);
1023 return size;
1025 EXPORT_SYMBOL(mem_read);
1027 ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags)
1029 ulong size;
1030 struct device_d *dev;
1032 if (!cdev->dev)
1033 return -1;
1034 dev = cdev->dev;
1036 size = min((ulong)count, dev->size - offset);
1037 memcpy_sz((void *)(dev->map_base + offset), buf, size, flags & O_RWSIZE_MASK);
1038 return size;
1040 EXPORT_SYMBOL(mem_write);