Subversion Repositories HelenOS

Rev

Rev 4445 | Rev 4509 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4445 Rev 4463
Line 91... Line 91...
91
    unsigned rlnkcnt;
91
    unsigned rlnkcnt;
92
    ipcarg_t rc;
92
    ipcarg_t rc;
93
    int phone;
93
    int phone;
94
    aid_t msg;
94
    aid_t msg;
95
    ipc_call_t answer;
95
    ipc_call_t answer;
96
           
96
   
97
    /* Resolve the path to the mountpoint. */
97
    /* Resolve the path to the mountpoint. */
98
    rwlock_write_lock(&namespace_rwlock);
98
    rwlock_write_lock(&namespace_rwlock);
99
    if (rootfs.fs_handle) {
99
    if (rootfs.fs_handle) {
100
        /* We already have the root FS. */
100
        /* We already have the root FS. */
101
        if (str_cmp(mp, "/") == 0) {
101
        if (str_cmp(mp, "/") == 0) {
Line 488... Line 488...
488
{
488
{
489
    if (!vfs_files_init()) {
489
    if (!vfs_files_init()) {
490
        ipc_answer_0(rid, ENOMEM);
490
        ipc_answer_0(rid, ENOMEM);
491
        return;
491
        return;
492
    }
492
    }
493
 
493
   
494
    /*
494
    /*
495
     * The POSIX interface is open(path, oflag, mode).
495
     * The POSIX interface is open(path, oflag, mode).
496
     * We can receive oflags and mode along with the VFS_OPEN call; the path
496
     * We can receive oflags and mode along with the VFS_OPEN call; the path
497
     * will need to arrive in another call.
497
     * will need to arrive in another call.
498
     *
498
     *
Line 501... Line 501...
501
     */
501
     */
502
    int lflag = IPC_GET_ARG1(*request);
502
    int lflag = IPC_GET_ARG1(*request);
503
    int oflag = IPC_GET_ARG2(*request);
503
    int oflag = IPC_GET_ARG2(*request);
504
    int mode = IPC_GET_ARG3(*request);
504
    int mode = IPC_GET_ARG3(*request);
505
    size_t len;
505
    size_t len;
506
 
506
   
507
    /*
507
    /*
508
     * Make sure that we are called with exactly one of L_FILE and
508
     * Make sure that we are called with exactly one of L_FILE and
509
     * L_DIRECTORY.
509
     * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
510
     */
510
     */
511
    if ((lflag & (L_FILE | L_DIRECTORY)) == 0 ||
511
    if (((lflag & (L_FILE | L_DIRECTORY)) == 0)
512
        (lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) {
512
        || ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY))
-
 
513
        || ((lflag & L_OPEN) != 0)) {
513
        ipc_answer_0(rid, EINVAL);
514
        ipc_answer_0(rid, EINVAL);
514
        return;
515
        return;
515
    }
516
    }
516
 
517
   
517
    if (oflag & O_CREAT)
518
    if (oflag & O_CREAT)
518
        lflag |= L_CREATE;
519
        lflag |= L_CREATE;
519
    if (oflag & O_EXCL)
520
    if (oflag & O_EXCL)
520
        lflag |= L_EXCLUSIVE;
521
        lflag |= L_EXCLUSIVE;
521
 
522
   
522
    ipc_callid_t callid;
523
    ipc_callid_t callid;
523
 
-
 
524
    if (!ipc_data_write_receive(&callid, &len)) {
524
    if (!ipc_data_write_receive(&callid, &len)) {
525
        ipc_answer_0(callid, EINVAL);
525
        ipc_answer_0(callid, EINVAL);
526
        ipc_answer_0(rid, EINVAL);
526
        ipc_answer_0(rid, EINVAL);
527
        return;
527
        return;
528
    }
528
    }
-
 
529
   
529
    char *path = malloc(len + 1);
530
    char *path = malloc(len + 1);
530
    if (!path) {
531
    if (!path) {
531
        ipc_answer_0(callid, ENOMEM);
532
        ipc_answer_0(callid, ENOMEM);
532
        ipc_answer_0(rid, ENOMEM);
533
        ipc_answer_0(rid, ENOMEM);
533
        return;
534
        return;
534
    }
535
    }
-
 
536
   
535
    int rc;
537
    int rc;
536
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
538
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
537
        ipc_answer_0(rid, rc);
539
        ipc_answer_0(rid, rc);
538
        free(path);
540
        free(path);
539
        return;
541
        return;
Line 547... Line 549...
547
     */
549
     */
548
    if (lflag & L_CREATE)
550
    if (lflag & L_CREATE)
549
        rwlock_write_lock(&namespace_rwlock);
551
        rwlock_write_lock(&namespace_rwlock);
550
    else
552
    else
551
        rwlock_read_lock(&namespace_rwlock);
553
        rwlock_read_lock(&namespace_rwlock);
552
 
554
   
553
    /* The path is now populated and we can call vfs_lookup_internal(). */
555
    /* The path is now populated and we can call vfs_lookup_internal(). */
554
    vfs_lookup_res_t lr;
556
    vfs_lookup_res_t lr;
555
    rc = vfs_lookup_internal(path, lflag, &lr, NULL);
557
    rc = vfs_lookup_internal(path, lflag | L_OPEN, &lr, NULL);
556
    if (rc) {
558
    if (rc != EOK) {
557
        if (lflag & L_CREATE)
559
        if (lflag & L_CREATE)
558
            rwlock_write_unlock(&namespace_rwlock);
560
            rwlock_write_unlock(&namespace_rwlock);
559
        else
561
        else
560
            rwlock_read_unlock(&namespace_rwlock);
562
            rwlock_read_unlock(&namespace_rwlock);
561
        ipc_answer_0(rid, rc);
563
        ipc_answer_0(rid, rc);
562
        free(path);
564
        free(path);
563
        return;
565
        return;
564
    }
566
    }
565
 
567
   
566
    /* Path is no longer needed. */
568
    /* Path is no longer needed. */
567
    free(path);
569
    free(path);
568
 
570
   
569
    vfs_node_t *node = vfs_node_get(&lr);
571
    vfs_node_t *node = vfs_node_get(&lr);
570
    if (lflag & L_CREATE)
572
    if (lflag & L_CREATE)
571
        rwlock_write_unlock(&namespace_rwlock);
573
        rwlock_write_unlock(&namespace_rwlock);
572
    else
574
    else
573
        rwlock_read_unlock(&namespace_rwlock);
575
        rwlock_read_unlock(&namespace_rwlock);
574
 
576
   
575
    /* Truncate the file if requested and if necessary. */
577
    /* Truncate the file if requested and if necessary. */
576
    if (oflag & O_TRUNC) {
578
    if (oflag & O_TRUNC) {
577
        rwlock_write_lock(&node->contents_rwlock);
579
        rwlock_write_lock(&node->contents_rwlock);
578
        if (node->size) {
580
        if (node->size) {
579
            rc = vfs_truncate_internal(node->fs_handle,
581
            rc = vfs_truncate_internal(node->fs_handle,
Line 586... Line 588...
586
            }
588
            }
587
            node->size = 0;
589
            node->size = 0;
588
        }
590
        }
589
        rwlock_write_unlock(&node->contents_rwlock);
591
        rwlock_write_unlock(&node->contents_rwlock);
590
    }
592
    }
591
 
593
   
592
    /*
594
    /*
593
     * Get ourselves a file descriptor and the corresponding vfs_file_t
595
     * Get ourselves a file descriptor and the corresponding vfs_file_t
594
     * structure.
596
     * structure.
595
     */
597
     */
596
    int fd = vfs_fd_alloc();
598
    int fd = vfs_fd_alloc();
Line 599... Line 601...
599
        ipc_answer_0(rid, fd);
601
        ipc_answer_0(rid, fd);
600
        return;
602
        return;
601
    }
603
    }
602
    vfs_file_t *file = vfs_file_get(fd);
604
    vfs_file_t *file = vfs_file_get(fd);
603
    file->node = node;
605
    file->node = node;
604
    if (oflag & O_APPEND)
606
    if (oflag & O_APPEND)
605
        file->append = true;
607
        file->append = true;
606
 
608
   
607
    /*
609
    /*
608
     * The following increase in reference count is for the fact that the
610
     * The following increase in reference count is for the fact that the
609
     * file is being opened and that a file structure is pointing to it.
611
     * file is being opened and that a file structure is pointing to it.
610
     * It is necessary so that the file will not disappear when
612
     * It is necessary so that the file will not disappear when
611
     * vfs_node_put() is called. The reference will be dropped by the
613
     * vfs_node_put() is called. The reference will be dropped by the
612
     * respective VFS_CLOSE.
614
     * respective VFS_CLOSE.
613
     */
615
     */
614
    vfs_node_addref(node);
616
    vfs_node_addref(node);
615
    vfs_node_put(node);
617
    vfs_node_put(node);
-
 
618
   
-
 
619
    /* Success! Return the new file descriptor to the client. */
-
 
620
    ipc_answer_1(rid, EOK, fd);
-
 
621
}
616
 
622
 
-
 
623
void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-
 
624
{
-
 
625
    // FIXME: check for sanity of the supplied fs, dev and index
-
 
626
   
-
 
627
    if (!vfs_files_init()) {
-
 
628
        ipc_answer_0(rid, ENOMEM);
-
 
629
        return;
-
 
630
    }
-
 
631
   
-
 
632
    /*
-
 
633
     * The interface is open_node(fs, dev, index, oflag).
-
 
634
     */
-
 
635
    vfs_lookup_res_t lr;
-
 
636
   
-
 
637
    lr.triplet.fs_handle = IPC_GET_ARG1(*request);
-
 
638
    lr.triplet.dev_handle = IPC_GET_ARG2(*request);
-
 
639
    lr.triplet.index = IPC_GET_ARG3(*request);
-
 
640
    int oflag = IPC_GET_ARG4(*request);
-
 
641
   
-
 
642
    rwlock_read_lock(&namespace_rwlock);
-
 
643
   
-
 
644
    int rc = vfs_open_node_internal(&lr);
-
 
645
    if (rc != EOK) {
-
 
646
        rwlock_read_unlock(&namespace_rwlock);
-
 
647
        ipc_answer_0(rid, rc);
-
 
648
        return;
-
 
649
    }
-
 
650
   
-
 
651
    vfs_node_t *node = vfs_node_get(&lr);
-
 
652
    rwlock_read_unlock(&namespace_rwlock);
-
 
653
   
-
 
654
    /* Truncate the file if requested and if necessary. */
-
 
655
    if (oflag & O_TRUNC) {
-
 
656
        rwlock_write_lock(&node->contents_rwlock);
-
 
657
        if (node->size) {
-
 
658
            rc = vfs_truncate_internal(node->fs_handle,
-
 
659
                node->dev_handle, node->index, 0);
-
 
660
            if (rc) {
-
 
661
                rwlock_write_unlock(&node->contents_rwlock);
-
 
662
                vfs_node_put(node);
-
 
663
                ipc_answer_0(rid, rc);
-
 
664
                return;
-
 
665
            }
-
 
666
            node->size = 0;
-
 
667
        }
-
 
668
        rwlock_write_unlock(&node->contents_rwlock);
-
 
669
    }
-
 
670
   
-
 
671
    /*
-
 
672
     * Get ourselves a file descriptor and the corresponding vfs_file_t
-
 
673
     * structure.
-
 
674
     */
-
 
675
    int fd = vfs_fd_alloc();
-
 
676
    if (fd < 0) {
-
 
677
        vfs_node_put(node);
-
 
678
        ipc_answer_0(rid, fd);
-
 
679
        return;
-
 
680
    }
-
 
681
    vfs_file_t *file = vfs_file_get(fd);
-
 
682
    file->node = node;
-
 
683
    if (oflag & O_APPEND)
-
 
684
        file->append = true;
-
 
685
   
-
 
686
    /*
-
 
687
     * The following increase in reference count is for the fact that the
-
 
688
     * file is being opened and that a file structure is pointing to it.
-
 
689
     * It is necessary so that the file will not disappear when
-
 
690
     * vfs_node_put() is called. The reference will be dropped by the
-
 
691
     * respective VFS_CLOSE.
-
 
692
     */
-
 
693
    vfs_node_addref(node);
-
 
694
    vfs_node_put(node);
-
 
695
   
617
    /* Success! Return the new file descriptor to the client. */
696
    /* Success! Return the new file descriptor to the client. */
618
    ipc_answer_1(rid, EOK, fd);
697
    ipc_answer_1(rid, EOK, fd);
619
}
698
}
620
 
699
 
621
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
700
void vfs_node(ipc_callid_t rid, ipc_call_t *request)
-
 
701
{
-
 
702
    int fd = IPC_GET_ARG1(*request);
-
 
703
   
-
 
704
    /* Lookup the file structure corresponding to the file descriptor. */
-
 
705
    vfs_file_t *file = vfs_file_get(fd);
-
 
706
    if (!file) {
-
 
707
        ipc_answer_0(rid, ENOENT);
-
 
708
        return;
-
 
709
    }
-
 
710
   
-
 
711
    ipc_answer_3(rid, EOK, file->node->fs_handle,
-
 
712
        file->node->dev_handle, file->node->index);
-
 
713
}
-
 
714
 
-
 
715
void vfs_device(ipc_callid_t rid, ipc_call_t *request)
622
{
716
{
623
    int fd = IPC_GET_ARG1(*request);
717
    int fd = IPC_GET_ARG1(*request);
-
 
718
   
-
 
719
    /* Lookup the file structure corresponding to the file descriptor. */
624
    int rc = vfs_fd_free(fd);
720
    vfs_file_t *file = vfs_file_get(fd);
-
 
721
    if (!file) {
-
 
722
        ipc_answer_0(rid, ENOENT);
-
 
723
        return;
-
 
724
    }
-
 
725
   
-
 
726
    /*
-
 
727
     * Lock the open file structure so that no other thread can manipulate
-
 
728
     * the same open file at a time.
-
 
729
     */
-
 
730
    futex_down(&file->lock);
-
 
731
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
-
 
732
   
-
 
733
    /* Make a VFS_DEVICE request at the destination FS server. */
-
 
734
    aid_t msg;
-
 
735
    ipc_call_t answer;
-
 
736
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
-
 
737
        file->node->dev_handle, file->node->index, &answer);
-
 
738
   
-
 
739
    /* Wait for reply from the FS server. */
-
 
740
    ipcarg_t rc;
-
 
741
    async_wait_for(msg, &rc);
-
 
742
   
-
 
743
    vfs_release_phone(fs_phone);
-
 
744
    futex_up(&file->lock);
-
 
745
   
-
 
746
    ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
-
 
747
}
-
 
748
 
-
 
749
void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
-
 
750
{
-
 
751
    int fd = IPC_GET_ARG1(*request);
-
 
752
   
-
 
753
    /* Lookup the file structure corresponding to the file descriptor. */
-
 
754
    vfs_file_t *file = vfs_file_get(fd);
-
 
755
    if (!file) {
-
 
756
        ipc_answer_0(rid, ENOENT);
-
 
757
        return;
-
 
758
    }
-
 
759
   
-
 
760
    /*
-
 
761
     * Lock the open file structure so that no other thread can manipulate
-
 
762
     * the same open file at a time.
-
 
763
     */
-
 
764
    futex_down(&file->lock);
-
 
765
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
-
 
766
   
-
 
767
    /* Make a VFS_SYMC request at the destination FS server. */
-
 
768
    aid_t msg;
-
 
769
    ipc_call_t answer;
-
 
770
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
-
 
771
        file->node->dev_handle, file->node->index, &answer);
-
 
772
   
-
 
773
    /* Wait for reply from the FS server. */
-
 
774
    ipcarg_t rc;
-
 
775
    async_wait_for(msg, &rc);
-
 
776
   
-
 
777
    vfs_release_phone(fs_phone);
-
 
778
    futex_up(&file->lock);
-
 
779
   
625
    ipc_answer_0(rid, rc);
780
    ipc_answer_0(rid, rc);
626
}
781
}
627
 
782
 
-
 
783
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
-
 
784
{
-
 
785
    int fd = IPC_GET_ARG1(*request);
-
 
786
   
-
 
787
    /* Lookup the file structure corresponding to the file descriptor. */
-
 
788
    vfs_file_t *file = vfs_file_get(fd);
-
 
789
    if (!file) {
-
 
790
        ipc_answer_0(rid, ENOENT);
-
 
791
        return;
-
 
792
    }
-
 
793
   
-
 
794
    /*
-
 
795
     * Lock the open file structure so that no other thread can manipulate
-
 
796
     * the same open file at a time.
-
 
797
     */
-
 
798
    futex_down(&file->lock);
-
 
799
   
-
 
800
    int fs_phone = vfs_grab_phone(file->node->fs_handle);
-
 
801
   
-
 
802
    /* Make a VFS_CLOSE request at the destination FS server. */
-
 
803
    aid_t msg;
-
 
804
    ipc_call_t answer;
-
 
805
    msg = async_send_2(fs_phone, IPC_GET_METHOD(*request),
-
 
806
        file->node->dev_handle, file->node->index, &answer);
-
 
807
   
-
 
808
    /* Wait for reply from the FS server. */
-
 
809
    ipcarg_t rc;
-
 
810
    async_wait_for(msg, &rc);
-
 
811
   
-
 
812
    vfs_release_phone(fs_phone);
-
 
813
    futex_up(&file->lock);
-
 
814
   
-
 
815
    int retval = IPC_GET_ARG1(answer);
-
 
816
    if (retval != EOK)
-
 
817
        ipc_answer_0(rid, retval);
-
 
818
   
-
 
819
    retval = vfs_fd_free(fd);
-
 
820
    ipc_answer_0(rid, retval);
-
 
821
}
-
 
822
 
628
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
823
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
629
{
824
{
630
 
825
 
631
    /*
826
    /*
632
     * The following code strongly depends on the fact that the files data
827
     * The following code strongly depends on the fact that the files data
Line 703... Line 898...
703
     * ourselves. Note that call arguments are immutable in this case so we
898
     * ourselves. Note that call arguments are immutable in this case so we
704
     * don't have to bother.
899
     * don't have to bother.
705
     */
900
     */
706
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
901
    ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
707
   
902
   
708
    vfs_release_phone(fs_phone);
-
 
709
   
-
 
710
    /* Wait for reply from the FS server. */
903
    /* Wait for reply from the FS server. */
711
    ipcarg_t rc;
904
    ipcarg_t rc;
712
    async_wait_for(msg, &rc);
905
    async_wait_for(msg, &rc);
-
 
906
   
-
 
907
    vfs_release_phone(fs_phone);
-
 
908
   
713
    size_t bytes = IPC_GET_ARG1(answer);
909
    size_t bytes = IPC_GET_ARG1(answer);
714
 
910
 
715
    if (file->node->type == VFS_NODE_DIRECTORY)
911
    if (file->node->type == VFS_NODE_DIRECTORY)
716
        rwlock_read_unlock(&namespace_rwlock);
912
        rwlock_read_unlock(&namespace_rwlock);
717
   
913
   
Line 1114... Line 1310...
1114
    ipc_answer_0(rid, EOK);
1310
    ipc_answer_0(rid, EOK);
1115
}
1311
}
1116
 
1312
 
1117
/**
1313
/**
1118
 * @}
1314
 * @}
1119
 */
1315
 */