Subversion Repositories HelenOS

Rev

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

Rev 2752 Rev 2763
Line 33... Line 33...
33
/**
33
/**
34
 * @file    vfs_ops.c
34
 * @file    vfs_ops.c
35
 * @brief   Operations that VFS offers to its clients.
35
 * @brief   Operations that VFS offers to its clients.
36
 */
36
 */
37
 
37
 
-
 
38
#include "vfs.h"
38
#include <ipc/ipc.h>
39
#include <ipc/ipc.h>
39
#include <async.h>
40
#include <async.h>
40
#include <errno.h>
41
#include <errno.h>
41
#include <stdio.h>
42
#include <stdio.h>
42
#include <stdlib.h>
43
#include <stdlib.h>
Line 48... Line 49...
48
#include <unistd.h>
49
#include <unistd.h>
49
#include <ctype.h>
50
#include <ctype.h>
50
#include <fcntl.h>
51
#include <fcntl.h>
51
#include <assert.h>
52
#include <assert.h>
52
#include <atomic.h>
53
#include <atomic.h>
53
#include "vfs.h"
54
#include <vfs/canonify.h>
54
 
55
 
55
/* Forward declarations of static functions. */
56
/* Forward declarations of static functions. */
56
static int vfs_truncate_internal(int, int, unsigned long, size_t);
57
static int vfs_truncate_internal(int, int, unsigned long, size_t);
57
 
58
 
58
/**
59
/**
Line 304... Line 305...
304
    if (!ipc_data_write_receive(&callid, &len)) {
305
    if (!ipc_data_write_receive(&callid, &len)) {
305
        ipc_answer_0(callid, EINVAL);
306
        ipc_answer_0(callid, EINVAL);
306
        ipc_answer_0(rid, EINVAL);
307
        ipc_answer_0(rid, EINVAL);
307
        return;
308
        return;
308
    }
309
    }
309
 
-
 
310
    /*
-
 
311
     * Now we are on the verge of accepting the path.
-
 
312
     *
-
 
313
     * There is one optimization we could do in the future: copy the path
-
 
314
     * directly into the PLB using some kind of a callback.
-
 
315
     */
-
 
316
    char *path = malloc(len + 1);
310
    char *path = malloc(len + 1);
317
   
-
 
318
    if (!path) {
311
    if (!path) {
319
        ipc_answer_0(callid, ENOMEM);
312
        ipc_answer_0(callid, ENOMEM);
320
        ipc_answer_0(rid, ENOMEM);
313
        ipc_answer_0(rid, ENOMEM);
321
        return;
314
        return;
322
    }
315
    }
323
 
-
 
324
    int rc;
316
    int rc;
325
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
317
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
326
        ipc_answer_0(rid, rc);
318
        ipc_answer_0(rid, rc);
327
        free(path);
319
        free(path);
328
        return;
320
        return;
Line 627... Line 619...
627
    if (!ipc_data_write_receive(&callid, &len)) {
619
    if (!ipc_data_write_receive(&callid, &len)) {
628
        ipc_answer_0(callid, EINVAL);
620
        ipc_answer_0(callid, EINVAL);
629
        ipc_answer_0(rid, EINVAL);
621
        ipc_answer_0(rid, EINVAL);
630
        return;
622
        return;
631
    }
623
    }
632
 
-
 
633
    /*
-
 
634
     * Now we are on the verge of accepting the path.
-
 
635
     *
-
 
636
     * There is one optimization we could do in the future: copy the path
-
 
637
     * directly into the PLB using some kind of a callback.
-
 
638
     */
-
 
639
    char *path = malloc(len + 1);
624
    char *path = malloc(len + 1);
640
   
-
 
641
    if (!path) {
625
    if (!path) {
642
        ipc_answer_0(callid, ENOMEM);
626
        ipc_answer_0(callid, ENOMEM);
643
        ipc_answer_0(rid, ENOMEM);
627
        ipc_answer_0(rid, ENOMEM);
644
        return;
628
        return;
645
    }
629
    }
646
 
-
 
647
    int rc;
630
    int rc;
648
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
631
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
649
        ipc_answer_0(rid, rc);
632
        ipc_answer_0(rid, rc);
650
        free(path);
633
        free(path);
651
        return;
634
        return;
Line 670... Line 653...
670
    if (!ipc_data_write_receive(&callid, &len)) {
653
    if (!ipc_data_write_receive(&callid, &len)) {
671
        ipc_answer_0(callid, EINVAL);
654
        ipc_answer_0(callid, EINVAL);
672
        ipc_answer_0(rid, EINVAL);
655
        ipc_answer_0(rid, EINVAL);
673
        return;
656
        return;
674
    }
657
    }
675
 
-
 
676
    /*
-
 
677
     * Now we are on the verge of accepting the path.
-
 
678
     *
-
 
679
     * There is one optimization we could do in the future: copy the path
-
 
680
     * directly into the PLB using some kind of a callback.
-
 
681
     */
-
 
682
    char *path = malloc(len + 1);
658
    char *path = malloc(len + 1);
683
   
-
 
684
    if (!path) {
659
    if (!path) {
685
        ipc_answer_0(callid, ENOMEM);
660
        ipc_answer_0(callid, ENOMEM);
686
        ipc_answer_0(rid, ENOMEM);
661
        ipc_answer_0(rid, ENOMEM);
687
        return;
662
        return;
688
    }
663
    }
689
 
-
 
690
    int rc;
664
    int rc;
691
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
665
    if ((rc = ipc_data_write_finalize(callid, path, len))) {
692
        ipc_answer_0(rid, rc);
666
        ipc_answer_0(rid, rc);
693
        free(path);
667
        free(path);
694
        return;
668
        return;
Line 696... Line 670...
696
    path[len] = '\0';
670
    path[len] = '\0';
697
   
671
   
698
    rwlock_write_lock(&namespace_rwlock);
672
    rwlock_write_lock(&namespace_rwlock);
699
    lflag &= L_DIRECTORY;   /* sanitize lflag */
673
    lflag &= L_DIRECTORY;   /* sanitize lflag */
700
    vfs_lookup_res_t lr;
674
    vfs_lookup_res_t lr;
701
    rc = vfs_lookup_internal(path, lflag | L_DESTROY, &lr, NULL);
675
    rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, NULL);
702
    free(path);
676
    free(path);
703
    if (rc != EOK) {
677
    if (rc != EOK) {
704
        rwlock_write_unlock(&namespace_rwlock);
678
        rwlock_write_unlock(&namespace_rwlock);
705
        ipc_answer_0(rid, rc);
679
        ipc_answer_0(rid, rc);
706
        return;
680
        return;
Line 716... Line 690...
716
    rwlock_write_unlock(&namespace_rwlock);
690
    rwlock_write_unlock(&namespace_rwlock);
717
    vfs_node_put(node);
691
    vfs_node_put(node);
718
    ipc_answer_0(rid, EOK);
692
    ipc_answer_0(rid, EOK);
719
}
693
}
720
 
694
 
-
 
695
void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
-
 
696
{
-
 
697
    size_t len;
-
 
698
    ipc_callid_t callid;
-
 
699
    int rc;
-
 
700
 
-
 
701
    /* Retrieve the old path. */
-
 
702
    if (!ipc_data_write_receive(&callid, &len)) {
-
 
703
        ipc_answer_0(callid, EINVAL);
-
 
704
        ipc_answer_0(rid, EINVAL);
-
 
705
        return;
-
 
706
    }
-
 
707
    char *old = malloc(len + 1);
-
 
708
    if (!old) {
-
 
709
        ipc_answer_0(callid, ENOMEM);
-
 
710
        ipc_answer_0(rid, ENOMEM);
-
 
711
        return;
-
 
712
    }
-
 
713
    if ((rc = ipc_data_write_finalize(callid, old, len))) {
-
 
714
        ipc_answer_0(rid, rc);
-
 
715
        free(old);
-
 
716
        return;
-
 
717
    }
-
 
718
    old[len] = '\0';
-
 
719
   
-
 
720
    /* Retrieve the new path. */
-
 
721
    if (!ipc_data_write_receive(&callid, &len)) {
-
 
722
        ipc_answer_0(callid, EINVAL);
-
 
723
        ipc_answer_0(rid, EINVAL);
-
 
724
        free(old);
-
 
725
        return;
-
 
726
    }
-
 
727
    char *new = malloc(len + 1);
-
 
728
    if (!new) {
-
 
729
        ipc_answer_0(callid, ENOMEM);
-
 
730
        ipc_answer_0(rid, ENOMEM);
-
 
731
        free(old);
-
 
732
        return;
-
 
733
    }
-
 
734
    if ((rc = ipc_data_write_finalize(callid, new, len))) {
-
 
735
        ipc_answer_0(rid, rc);
-
 
736
        free(old);
-
 
737
        free(new);
-
 
738
        return;
-
 
739
    }
-
 
740
    new[len] = '\0';
-
 
741
 
-
 
742
    char *oldc = canonify(old, &len);
-
 
743
    char *newc = canonify(new, NULL);
-
 
744
    if (!oldc || !newc) {
-
 
745
        ipc_answer_0(rid, EINVAL);
-
 
746
        free(old);
-
 
747
        free(new);
-
 
748
        return;
-
 
749
    }
-
 
750
    if (!strncmp(newc, oldc, len)) {
-
 
751
        /* oldc is a prefix of newc */
-
 
752
        ipc_answer_0(rid, EINVAL);
-
 
753
        free(old);
-
 
754
        free(new);
-
 
755
        return;
-
 
756
    }
-
 
757
   
-
 
758
    vfs_lookup_res_t old_lr;
-
 
759
    vfs_lookup_res_t new_lr;
-
 
760
    vfs_lookup_res_t new_par_lr;
-
 
761
    rwlock_write_lock(&namespace_rwlock);
-
 
762
    /* Lookup the node belonging to the old file name. */
-
 
763
    rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
-
 
764
    if (rc != EOK) {
-
 
765
        rwlock_write_unlock(&namespace_rwlock);
-
 
766
        ipc_answer_0(rid, rc);
-
 
767
        free(old);
-
 
768
        free(new);
-
 
769
        return;
-
 
770
    }
-
 
771
    vfs_node_t *old_node = vfs_node_get(&old_lr);
-
 
772
    if (!old_node) {
-
 
773
        rwlock_write_unlock(&namespace_rwlock);
-
 
774
        ipc_answer_0(rid, ENOMEM);
-
 
775
        free(old);
-
 
776
        free(new);
-
 
777
        return;
-
 
778
    }
-
 
779
    /* Lookup parent of the new file name. */
-
 
780
    rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL);
-
 
781
    if (rc != EOK) {
-
 
782
        rwlock_write_unlock(&namespace_rwlock);
-
 
783
        ipc_answer_0(rid, rc);
-
 
784
        free(old);
-
 
785
        free(new);
-
 
786
        return;
-
 
787
    }
-
 
788
    /* Check whether linking to the same file system instance. */
-
 
789
    if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
-
 
790
        (old_node->dev_handle != new_par_lr.triplet.dev_handle)) {
-
 
791
        rwlock_write_unlock(&namespace_rwlock);
-
 
792
        ipc_answer_0(rid, EXDEV);   /* different file systems */
-
 
793
        free(old);
-
 
794
        free(new);
-
 
795
        return;
-
 
796
    }
-
 
797
    /* Destroy the old link for the new name. */
-
 
798
    vfs_node_t *new_node = NULL;
-
 
799
    rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
-
 
800
    switch (rc) {
-
 
801
    case ENOENT:
-
 
802
        /* simply not in our way */
-
 
803
        break;
-
 
804
    case EOK:
-
 
805
        new_node = vfs_node_get(&new_lr);
-
 
806
        if (!new_node) {
-
 
807
            rwlock_write_unlock(&namespace_rwlock);
-
 
808
            ipc_answer_0(rid, ENOMEM);
-
 
809
            free(old);
-
 
810
            free(new);
-
 
811
            return;
-
 
812
        }
-
 
813
        new_node->lnkcnt--;
-
 
814
        break;
-
 
815
    default:
-
 
816
        rwlock_write_unlock(&namespace_rwlock);
-
 
817
        ipc_answer_0(rid, ENOTEMPTY);
-
 
818
        free(old);
-
 
819
        free(new);
-
 
820
        return;
-
 
821
    }
-
 
822
    /* Create the new link for the new name. */
-
 
823
    rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
-
 
824
    if (rc != EOK) {
-
 
825
        rwlock_write_unlock(&namespace_rwlock);
-
 
826
        if (new_node)
-
 
827
            vfs_node_put(new_node);
-
 
828
        ipc_answer_0(rid, rc);
-
 
829
        free(old);
-
 
830
        free(new);
-
 
831
        return;
-
 
832
    }
-
 
833
    old_node->lnkcnt++;
-
 
834
    /* Destroy the link for the old name. */
-
 
835
    rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
-
 
836
    if (rc != EOK) {
-
 
837
        rwlock_write_unlock(&namespace_rwlock);
-
 
838
        vfs_node_put(old_node);
-
 
839
        if (new_node)
-
 
840
            vfs_node_put(new_node);
-
 
841
        ipc_answer_0(rid, rc);
-
 
842
        free(old);
-
 
843
        free(new);
-
 
844
        return;
-
 
845
    }
-
 
846
    old_node->lnkcnt--;
-
 
847
    rwlock_write_unlock(&namespace_rwlock);
-
 
848
    vfs_node_put(old_node);
-
 
849
    if (new_node)
-
 
850
        vfs_node_put(new_node);
-
 
851
    free(old);
-
 
852
    free(new);
-
 
853
    ipc_answer_0(rid, EOK);
-
 
854
}
-
 
855
 
721
/**
856
/**
722
 * @}
857
 * @}
723
 */
858
 */