1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 38 // Modified to support the Haiku FAT driver. 39 40 #ifdef FS_SHELL 41 #include "fssh_api_wrapper.h" 42 #else 43 #include <disk_device_manager.h> 44 #include <real_time_clock.h> 45 #endif 46 47 #include "sys/param.h" 48 #include "sys/systm.h" 49 #include "sys/buf.h" 50 #include "sys/malloc.h" 51 #include "sys/namei.h" 52 #include "sys/vnode.h" 53 54 #include "fs/msdosfs/denode.h" 55 #include "fs/msdosfs/direntry.h" 56 57 58 #ifdef USER 59 #define dprintf printf 60 #endif 61 62 63 /*! Output is in GMT, provided the user has set the timezone. 64 In fat_shell, output is in local time. 65 */ 66 void 67 vfs_timestamp(struct timespec* tsp) 68 { 69 // get local time 70 bigtime_t usecs = real_time_clock_usecs(); 71 72 // convert to GMT 73 int32 offset = 0; 74 #ifdef _KERNEL_MODE 75 offset = (int32)get_timezone_offset(); 76 #elif defined USER 77 time_t the_time; 78 struct tm the_tm; 79 80 time(&the_time); 81 localtime_r(&the_time, &the_tm); 82 offset = (int32)the_tm.tm_gmtoff; 83 #endif 84 85 tsp->tv_sec = usecs / 1000000; 86 tsp->tv_sec -= offset; 87 tsp->tv_nsec = (usecs - tsp->tv_sec * 1000000LL) * 1000LL; 88 89 return; 90 } 91 92 93 /*! Allocate a struct vnode and initialize it to a generic state. 94 95 */ 96 int 97 getnewvnode(const char* tag, struct mount* mp, struct vop_vector* vops, struct vnode** vpp) 98 { 99 struct vnode* newBsdNode = calloc(1, sizeof(struct vnode)); 100 if (newBsdNode == NULL) 101 return ENOMEM; 102 103 newBsdNode->v_type = VNON; 104 newBsdNode->v_state = VSTATE_UNINITIALIZED; 105 newBsdNode->v_data = NULL; 106 newBsdNode->v_mount = mp; 107 newBsdNode->v_rdev = NULL; 108 newBsdNode->v_vflag = 0; 109 newBsdNode->v_vnlock = &newBsdNode->v_lock; 110 rw_lock_init(&newBsdNode->v_vnlock->haikuRW, "fat vnode"); 111 newBsdNode->v_bufobj.bo_flag = 0; 112 newBsdNode->v_parent = 0; 113 newBsdNode->v_mime = NULL; 114 newBsdNode->v_cache = NULL; 115 newBsdNode->v_file_map = NULL; 116 newBsdNode->v_resizing = false; 117 newBsdNode->v_sync = false; 118 119 *vpp = newBsdNode; 120 121 return 0; 122 } 123 124 125 /*! Used by detrunc to update the associated cache. If vp is a regular file, the hook must 126 update file cache size separately. 127 */ 128 int 129 vtruncbuf(struct vnode* vp, off_t length, int blksize) 130 { 131 status_t status = B_OK; 132 133 if (vp->v_type == VREG) { 134 // calling file_cache_set_size here might cause a deadlock because the node is locked 135 // at this point 136 file_map_set_size(vp->v_file_map, length); 137 return 0; 138 } 139 if (vp->v_type == VDIR) { 140 status = discard_clusters(vp, length); 141 return B_TO_POSIX_ERROR(status); 142 } 143 144 return B_ERROR; 145 } 146 147 148 /*! Get a ref to vp and optionally write-lock it. 149 150 */ 151 int 152 vget(struct vnode* vp, int flags) 153 { 154 status_t status = B_OK; 155 156 if ((flags & LK_EXCLUSIVE) != 0) { 157 status = rw_lock_write_lock(&vp->v_vnlock->haikuRW); 158 if (status != B_OK) 159 return B_TO_POSIX_ERROR(status); 160 } else if (flags != 0) { 161 return EINVAL; 162 } 163 164 status = acquire_vnode(vp->v_mount->mnt_fsvolume, VTODE(vp)->de_inode); 165 166 return B_TO_POSIX_ERROR(status); 167 } 168