File indexing completed on 2025-05-11 08:22:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #include <stdio.h>
0046 #include <stdlib.h>
0047 #include <string.h>
0048 #include <unistd.h>
0049 #include <errno.h>
0050 #include <fcntl.h>
0051 #include <inttypes.h>
0052 #include <rtems.h>
0053 #include <rtems/libio.h>
0054 #include <rtems/libio_.h>
0055 #include <rtems/seterr.h>
0056 #include <rtems/bspIo.h>
0057 #include <rtems/umon.h>
0058
0059 #include <umon/tfs.h>
0060 #include <umon/monlib.h>
0061
0062 #ifdef RTEMS_TFS_DRIVER_DEBUG
0063 #define RTEMS_TFS_DEBUG 1
0064 #else
0065 #define RTEMS_TFS_DEBUG 0
0066 #endif
0067
0068 #define MAXFILESIZE 0x4000
0069 #define MAXTFDS 15
0070
0071
0072
0073 #ifndef newlib_tfdlock
0074 #define newlib_tfdlock()
0075 #endif
0076
0077 #ifndef newlib_tfdunlock
0078 #define newlib_tfdunlock()
0079 #endif
0080
0081
0082
0083 struct tfdinfo {
0084 int inuse;
0085 int tfd;
0086 char *buf;
0087 char name[TFSNAMESIZE+1];
0088 char info[TFSNAMESIZE+1];
0089 } tfdtable[MAXTFDS];
0090
0091
0092
0093
0094 char TFS_PATHNAME_PREFIX[128];
0095
0096 static const rtems_filesystem_operations_table rtems_tfs_ops;
0097 static const rtems_filesystem_file_handlers_r rtems_tfs_handlers;
0098
0099 static bool rtems_tfs_is_directory(
0100 const char *path,
0101 size_t pathlen
0102 )
0103 {
0104 return path [pathlen - 1] == '/';
0105 }
0106
0107 static int rtems_tfs_mount_me(
0108 rtems_filesystem_mount_table_entry_t *mt_entry,
0109 const void *data
0110 )
0111 {
0112 char *root_path = strdup("/");
0113
0114 if (root_path == NULL) {
0115 rtems_set_errno_and_return_minus_one(ENOMEM);
0116 }
0117
0118 mt_entry->ops = &rtems_tfs_ops;
0119 mt_entry->mt_fs_root->location.handlers = &rtems_tfs_handlers;
0120 mt_entry->mt_fs_root->location.node_access = root_path;
0121
0122 return 0;
0123 }
0124
0125
0126
0127 int rtems_initialize_tfs_filesystem(
0128 const char *path
0129 )
0130 {
0131 int status;
0132
0133 if (!path) {
0134 printk( "TFS: No mount point specified\n" );
0135 return -1;
0136 }
0137
0138 strncpy( TFS_PATHNAME_PREFIX, path, sizeof(TFS_PATHNAME_PREFIX) );
0139
0140 status = mkdir( TFS_PATHNAME_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO );
0141 if ( status == -1 ) {
0142 printk( "TFS: Unable to mkdir %s\n", TFS_PATHNAME_PREFIX );
0143 return status;
0144 }
0145
0146 if (rtems_filesystem_register( "tfs", rtems_tfs_mount_me ) < 0)
0147 return -1;
0148
0149 status = mount( "umon", TFS_PATHNAME_PREFIX, "tfs", RTEMS_FILESYSTEM_READ_WRITE, NULL);
0150
0151 if (status < 0) {
0152 printk( "TFS: Unable to mount on %s\n", TFS_PATHNAME_PREFIX );
0153 perror("TFS mount failed");
0154 }
0155
0156 return(status);
0157 }
0158
0159
0160
0161
0162 static void fixPath(char *path)
0163 {
0164 char *inp, *outp, *base;
0165
0166 outp = inp = path;
0167 base = NULL;
0168 for (;;) {
0169 if (inp[0] == '.') {
0170 if (inp[1] == '\0')
0171 break;
0172 if (inp[1] == '/') {
0173 inp += 2;
0174 continue;
0175 }
0176 if (inp[1] == '.') {
0177 if (inp[2] == '\0') {
0178 if ((base != NULL) && (outp > base)) {
0179 outp--;
0180 while ((outp > base) && (outp[-1] != '/'))
0181 outp--;
0182 }
0183 break;
0184 }
0185 if (inp[2] == '/') {
0186 inp += 3;
0187 if (base == NULL)
0188 continue;
0189 if (outp > base) {
0190 outp--;
0191 while ((outp > base) && (outp[-1] != '/'))
0192 outp--;
0193 }
0194 continue;
0195 }
0196 }
0197 }
0198 if (base == NULL)
0199 base = inp;
0200 while (inp[0] != '/') {
0201 if ((*outp++ = *inp++) == '\0')
0202 return;
0203 }
0204 *outp++ = '/';
0205 while (inp[0] == '/')
0206 inp++;
0207 }
0208 *outp = '\0';
0209 }
0210
0211 static void rtems_tfs_eval_path(rtems_filesystem_eval_path_context_t *self)
0212 {
0213 int eval_flags = rtems_filesystem_eval_path_get_flags(self);
0214
0215 if ((eval_flags & RTEMS_FS_MAKE) == 0) {
0216 int rw = RTEMS_FS_PERMS_READ | RTEMS_FS_PERMS_WRITE;
0217
0218 if ((eval_flags & rw) != rw) {
0219 rtems_filesystem_location_info_t *currentloc =
0220 rtems_filesystem_eval_path_get_currentloc(self);
0221 char *current = currentloc->node_access;
0222 size_t currentlen = strlen(current);
0223 const char *path = rtems_filesystem_eval_path_get_path(self);
0224 size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
0225 size_t len = currentlen + pathlen;
0226
0227 rtems_filesystem_eval_path_clear_path(self);
0228
0229 current = realloc(current, len + 1);
0230 if (current != NULL) {
0231 memcpy(current + currentlen, path, pathlen);
0232 current [len] = '\0';
0233 if (!rtems_tfs_is_directory(current, len)) {
0234 fixPath (current);
0235 }
0236 currentloc->node_access = current;
0237 } else {
0238 rtems_filesystem_eval_path_error(self, ENOMEM);
0239 }
0240 } else {
0241 rtems_filesystem_eval_path_error(self, EINVAL);
0242 }
0243 } else {
0244 rtems_filesystem_eval_path_error(self, EIO);
0245 }
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 static int rtems_tfs_open_worker(
0265 rtems_libio_t *iop,
0266 char *path,
0267 int oflag,
0268 mode_t mode
0269 )
0270 {
0271 static int beenhere = 0;
0272 long flagmode;
0273 int tfdidx, tfd;
0274 struct tfdinfo *tip;
0275 char *buf, *fstr, *istr, *bstr, pathcopy[TFSNAMESIZE*3+1];
0276
0277 if (RTEMS_TFS_DEBUG)
0278 printk("_open_r(%s,0x%x,0x%" PRIx32 ")\n",path,oflag,mode);
0279
0280 if (!beenhere) {
0281 newlib_tfdlock();
0282 for(tfdidx=0;tfdidx<MAXTFDS;tfdidx++)
0283 tfdtable[tfdidx].inuse = 0;
0284
0285 tfdtable[0].inuse = 1;
0286 tfdtable[1].inuse = 1;
0287 tfdtable[2].inuse = 1;
0288 newlib_tfdunlock();
0289 beenhere = 1;
0290 }
0291
0292 istr = fstr = bstr = buf = (char *)0;
0293
0294
0295
0296
0297 if (strlen(path) > TFSNAMESIZE*3) {
0298 return(ENAMETOOLONG);
0299 }
0300 strcpy(pathcopy,path);
0301
0302
0303
0304
0305
0306 fstr = strchr(pathcopy,',');
0307 if (fstr) {
0308 *fstr++ = 0;
0309 istr = strchr(fstr,',');
0310 if (istr) {
0311 *istr++ = 0;
0312 bstr = strchr(istr,',');
0313 if (bstr)
0314 *bstr++ = 0;
0315 }
0316 }
0317 if (strlen(pathcopy) > TFSNAMESIZE) {
0318 return(ENAMETOOLONG);
0319 }
0320 if (istr) {
0321 if (strlen(istr) > TFSNAMESIZE) {
0322 return(ENAMETOOLONG);
0323 }
0324 }
0325
0326
0327
0328 if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
0329 if (mon_tfsstat((char *)pathcopy)) {
0330 return(EEXIST);
0331 }
0332 }
0333
0334
0335
0336
0337
0338
0339
0340
0341 switch(oflag & O_ACCMODE) {
0342 case O_RDONLY:
0343 flagmode = TFS_RDONLY;
0344 break;
0345 case O_WRONLY|O_APPEND:
0346 flagmode = TFS_APPEND;
0347 break;
0348 case O_WRONLY|O_TRUNC:
0349 case O_WRONLY|O_CREAT|O_TRUNC:
0350 mon_tfsunlink((char *)pathcopy);
0351 flagmode = TFS_CREATE|TFS_APPEND;
0352 break;
0353 case O_WRONLY|O_CREAT:
0354 case O_WRONLY|O_CREAT|O_APPEND:
0355 flagmode = TFS_CREATE|TFS_APPEND;
0356 break;
0357 case O_RDWR:
0358 case O_WRONLY|O_CREAT|O_EXCL:
0359 flagmode = TFS_CREATE|TFS_APPEND;
0360 break;
0361 default:
0362 printk("_open_r(): flag 0x%i not supported\n",oflag);
0363 return(ENOTSUP);
0364 }
0365
0366
0367
0368 newlib_tfdlock();
0369 for(tfdidx=0;tfdidx<MAXTFDS;tfdidx++) {
0370 if (tfdtable[tfdidx].inuse == 0)
0371 break;
0372 }
0373 if (tfdidx == MAXTFDS) {
0374 newlib_tfdunlock();
0375 return(EMFILE);
0376 }
0377 tip = &tfdtable[tfdidx];
0378 tip->inuse = 1;
0379 newlib_tfdunlock();
0380
0381
0382
0383
0384
0385
0386
0387 if (flagmode == TFS_RDONLY) {
0388 buf = (char *)0;
0389 } else {
0390 if (bstr)
0391 buf = (char *)strtol(bstr,0,0);
0392 else
0393 buf = malloc(MAXFILESIZE);
0394 if (!buf) {
0395 newlib_tfdlock();
0396 tip->inuse = 0;
0397 newlib_tfdunlock();
0398 return(ENOMEM);
0399 }
0400 }
0401
0402
0403
0404 if (fstr) {
0405 long bflag;
0406
0407 bflag = mon_tfsctrl(TFS_FATOB,(long)fstr,0);
0408 if (bflag == -1) {
0409 return(EINVAL);
0410 }
0411 flagmode |= bflag;
0412 }
0413
0414 if (istr)
0415 strcpy(tip->info,istr);
0416 else
0417 tip->info[0] = 0;
0418
0419 tfd = mon_tfsopen((char *)pathcopy,flagmode,buf);
0420 if (tfd >= 0) {
0421 tip->tfd = tfd;
0422 tip->buf = buf;
0423 strcpy(tip->name,pathcopy);
0424 iop->data0 = (uint32_t)tfdidx;
0425 return(0);
0426 } else {
0427 printk("%s: %s\n",pathcopy,
0428 (char *)mon_tfsctrl(TFS_ERRMSG,tfd,0));
0429 }
0430
0431 if (buf)
0432 free(buf);
0433
0434 newlib_tfdlock();
0435 tip->inuse = 0;
0436 newlib_tfdunlock();
0437 return(EINVAL);
0438 }
0439
0440
0441
0442
0443 static int rtems_tfs_open(
0444 rtems_libio_t *iop,
0445 const char *new_name,
0446 int oflag,
0447 mode_t mode
0448 )
0449 {
0450 char *full_path_name;
0451 int err;
0452
0453 full_path_name = iop->pathinfo.node_access;
0454
0455 if (RTEMS_TFS_DEBUG)
0456 printk("rtems_tfs_open(%s)\n",full_path_name);
0457
0458 if (rtems_tfs_is_directory(full_path_name, strlen(full_path_name))) {
0459 rtems_set_errno_and_return_minus_one (ENOTSUP);
0460 }
0461
0462 err = rtems_tfs_open_worker (iop, full_path_name, oflag, mode);
0463 if (err != 0) {
0464 rtems_set_errno_and_return_minus_one (err);
0465 }
0466
0467 return err;
0468 }
0469
0470
0471
0472
0473 static ssize_t rtems_tfs_read(
0474 rtems_libio_t *iop,
0475 void *buffer,
0476 size_t count
0477 )
0478 {
0479 int ret, fd;
0480
0481 fd = (int) iop->data0;
0482
0483 if (RTEMS_TFS_DEBUG)
0484 printk("_read_r(%d,%zi)\n",fd,count);
0485
0486 if ((fd < 3) || (fd >= MAXTFDS))
0487 return(EBADF);
0488
0489 ret = mon_tfsread(tfdtable[fd].tfd,buffer,count);
0490 if (ret == TFSERR_EOF)
0491 ret = 0;
0492
0493 return(ret);
0494 }
0495
0496
0497
0498
0499 static int rtems_tfs_close(
0500 rtems_libio_t *iop
0501 )
0502 {
0503 int fd;
0504 char *info;
0505 struct tfdinfo *tip;
0506
0507 fd = (int)iop->data0;
0508
0509 if (RTEMS_TFS_DEBUG)
0510 printk("rtems_tfs_close(%d)\n",fd);
0511
0512 if ((fd < 3) || (fd >= MAXTFDS)) {
0513 rtems_set_errno_and_return_minus_one (EBADF);
0514 }
0515
0516 tip = &tfdtable[fd];
0517
0518 if (tip->info[0])
0519 info = tip->info;
0520 else
0521 info = (char *)0;
0522
0523 mon_tfsclose(tip->tfd,info);
0524
0525 if (tip->buf)
0526 free(tip->buf);
0527
0528 newlib_tfdlock();
0529 tip->inuse = 0;
0530 newlib_tfdunlock();
0531 return RTEMS_SUCCESSFUL;
0532 }
0533
0534 static ssize_t rtems_tfs_write(
0535 rtems_libio_t *iop,
0536 const void *buffer,
0537 size_t count
0538 )
0539 {
0540 int ret, fd;
0541
0542 fd = (int) iop->data0;
0543
0544 if (RTEMS_TFS_DEBUG)
0545 printk("rtems_tfs_write(%d,%zi)\n",fd,count);
0546
0547 if ((fd <= 0) || (fd >= MAXTFDS)) {
0548 rtems_set_errno_and_return_minus_one (EBADF);
0549 }
0550
0551 ret = mon_tfswrite(tfdtable[fd].tfd,(char *)buffer,count);
0552 if (ret < 0)
0553 return(-1);
0554
0555 return(ret);
0556 }
0557
0558 static off_t rtems_tfs_lseek(
0559 rtems_libio_t *iop,
0560 off_t offset,
0561 int whence
0562 )
0563 {
0564 int ret, fd;
0565
0566 fd = (int) iop->data0;
0567
0568 if (RTEMS_TFS_DEBUG)
0569 printk("rtems_tfs_lseek(%d,%ld,%d)\n",fd,(long)offset,whence);
0570
0571 switch (whence) {
0572 case SEEK_END:
0573 printk("rtems_tfs_lseek doesn't support SEEK_END\n");
0574 return(-1);
0575 case SEEK_CUR:
0576 whence = TFS_CURRENT;
0577 break;
0578 case SEEK_SET:
0579 whence = TFS_BEGIN;
0580 break;
0581 }
0582 ret = mon_tfsseek(tfdtable[fd].tfd,offset,whence);
0583
0584 if (ret < 0)
0585 return(-1);
0586
0587 return (off_t)ret;
0588 }
0589
0590
0591
0592
0593 static int rtems_tfs_ftruncate(
0594 rtems_libio_t *iop,
0595 off_t count
0596 )
0597 {
0598 int ret, fd;
0599
0600 fd = (int) iop->data0;
0601 ret = mon_tfstruncate(tfdtable[fd].tfd,count);
0602 if (ret != TFS_OKAY)
0603 return(-1);
0604
0605 return(0);
0606 }
0607
0608 static int rtems_tfs_ioctl(
0609 rtems_libio_t *iop,
0610 uint32_t cmd,
0611 void *buf
0612 )
0613 {
0614 int ret;
0615
0616 ret = mon_tfsctrl(cmd,(long)buf,0);
0617 if (ret != TFS_OKAY)
0618 return(-1);
0619
0620 return(0);
0621 }
0622
0623 static int rtems_tfs_fstat(
0624 const rtems_filesystem_location_info_t *loc,
0625 struct stat *buf
0626 )
0627 {
0628 const char *path = loc->node_access;
0629 size_t pathlen = strlen(path);
0630
0631 buf->st_mode = S_IRWXU | S_IRWXG | S_IRWXO
0632 | (rtems_tfs_is_directory(path, pathlen) ? S_IFDIR : S_IFREG);
0633
0634 return 0;
0635 }
0636
0637 static int rtems_tfs_clone_node_info(
0638 rtems_filesystem_location_info_t *loc
0639 )
0640 {
0641 int rv = 0;
0642
0643 loc->node_access = strdup(loc->node_access);
0644
0645 if (loc->node_access == NULL) {
0646 errno = ENOMEM;
0647 rv = -1;
0648 }
0649
0650 return rv;
0651 }
0652
0653 static void rtems_tfs_free_node_info(
0654 const rtems_filesystem_location_info_t *loc
0655 )
0656 {
0657 free(loc->node_access);
0658 }
0659
0660 static bool rtems_tfs_are_nodes_equal(
0661 const rtems_filesystem_location_info_t *a,
0662 const rtems_filesystem_location_info_t *b
0663 )
0664 {
0665 return strcmp(a->node_access, b->node_access) == 0;
0666 }
0667
0668 static const rtems_filesystem_operations_table rtems_tfs_ops = {
0669 .lock_h = rtems_filesystem_default_lock,
0670 .unlock_h = rtems_filesystem_default_unlock,
0671 .eval_path_h = rtems_tfs_eval_path,
0672 .link_h = rtems_filesystem_default_link,
0673 .are_nodes_equal_h = rtems_tfs_are_nodes_equal,
0674 .mknod_h = rtems_filesystem_default_mknod,
0675 .rmnod_h = rtems_filesystem_default_rmnod,
0676 .fchmod_h = rtems_filesystem_default_fchmod,
0677 .chown_h = rtems_filesystem_default_chown,
0678 .clonenod_h = rtems_tfs_clone_node_info,
0679 .freenod_h = rtems_tfs_free_node_info,
0680 .mount_h = rtems_filesystem_default_mount,
0681 .unmount_h = rtems_filesystem_default_unmount,
0682 .fsunmount_me_h = rtems_filesystem_default_fsunmount,
0683 .utimens_h = rtems_filesystem_default_utimens,
0684 .symlink_h = rtems_filesystem_default_symlink,
0685 .readlink_h = rtems_filesystem_default_readlink,
0686 .rename_h = rtems_filesystem_default_rename,
0687 .statvfs_h = rtems_filesystem_default_statvfs
0688 };
0689
0690 static const rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
0691 .open_h = rtems_tfs_open,
0692 .close_h = rtems_tfs_close,
0693 .read_h = rtems_tfs_read,
0694 .write_h = rtems_tfs_write,
0695 .ioctl_h = rtems_tfs_ioctl,
0696 .lseek_h = rtems_tfs_lseek,
0697 .fstat_h = rtems_tfs_fstat,
0698 .ftruncate_h = rtems_tfs_ftruncate,
0699 .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
0700 .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
0701 .fcntl_h = rtems_filesystem_default_fcntl,
0702 .kqfilter_h = rtems_filesystem_default_kqfilter,
0703 .poll_h = rtems_filesystem_default_poll,
0704 .readv_h = rtems_filesystem_default_readv,
0705 .writev_h = rtems_filesystem_default_writev
0706 };