darwin-xnu/bsd/miscfs/synthfs/synthfs_util.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/* Copyright (c) 1998, Apple Computer, Inc. All rights reserved. */
  23/*
  24 * Change History:
  25 *
  26 *      17-Aug-1999     Pat Dirks       New today.
  27 *
  28 */
  29
  30#include <mach/mach_types.h>
  31
  32#include <sys/param.h>
  33#include <sys/systm.h>
  34#include <sys/kernel.h>
  35#include <sys/file.h>
  36#include <sys/stat.h>
  37#include <sys/proc.h>
  38#include <sys/conf.h>
  39#include <sys/mount_internal.h>
  40#include <sys/vnode_internal.h>
  41#include <sys/malloc.h>
  42#include <sys/dirent.h>
  43#include <sys/namei.h>
  44#include <sys/attr.h>
  45#include <sys/time.h>
  46#include <sys/uio_internal.h>
  47
  48#include <sys/vm.h>
  49#include <sys/errno.h>
  50#include <vfs/vfs_support.h>
  51
  52#include "synthfs.h"
  53
  54struct synthfs_direntry_head {
  55        u_int32_t d_fileno;             /* file number of entry */
  56        u_int16_t d_reclen;             /* length of this record */
  57        u_int8_t  d_type;               /* file type, see below */
  58        u_int8_t  d_namlen;             /* length of string in d_name */
  59};
  60
  61
  62#define PATHSEPARATOR '/'
  63#define ROOTDIRID 2
  64
  65
  66static int synthfs_insertnode(struct synthfsnode *newnode_sp, struct synthfsnode *parent_sp) {
  67        struct timeval now;
  68        
  69        DBG_ASSERT(parent_sp->s_type == SYNTHFS_DIRECTORY);
  70        
  71    TAILQ_INSERT_TAIL(&parent_sp->s_u.d.d_subnodes, newnode_sp, s_sibling);
  72        ++parent_sp->s_u.d.d_entrycount;
  73        newnode_sp->s_parent = parent_sp;
  74        
  75        parent_sp->s_nodeflags |= IN_CHANGE | IN_MODIFIED;
  76        microtime(&now);
  77        synthfs_update(STOV(parent_sp), &now, &now, 0);
  78        
  79        return 0;
  80}
  81
  82
  83
  84static int synthfs_newnode(mount_t mp, vnode_t dp, const char *name, unsigned long nodeid,
  85                           mode_t mode, __unused proc_t p, enum vtype vtype, vnode_t *vpp) {
  86        int result;
  87    struct synthfsnode *sp;
  88        struct vnode *vp;
  89    struct timeval now;
  90    char *nodename;
  91        struct vnode_fsparam vfsp;
  92
  93     MALLOC(sp, struct synthfsnode *, sizeof(struct synthfsnode), M_SYNTHFS, M_WAITOK);
  94    
  95    if (name == NULL) {
  96        MALLOC(nodename, char *, 1, M_TEMP, M_WAITOK);
  97        nodename[0] = 0;
  98    } else {
  99        MALLOC(nodename, char *, strlen(name) + 1, M_TEMP, M_WAITOK);
 100        strcpy(nodename, name);
 101    };
 102
 103    /* Initialize the relevant synthfsnode fields: */
 104    bzero(sp, sizeof(*sp));
 105    sp->s_nodeid = nodeid;
 106    
 107    /* Initialize all times from a consistent snapshot of the clock: */
 108        microtime(&now);
 109    sp->s_createtime = now;
 110    sp->s_accesstime = now;
 111    sp->s_modificationtime = now;
 112    sp->s_changetime = now;
 113    sp->s_name = nodename;
 114    sp->s_mode = mode;
 115
 116
 117        //bzero(&vfsp, sizeof(struct vnode_fsparam));
 118        vfsp.vnfs_mp = mp;
 119        vfsp.vnfs_vtype = vtype;
 120        vfsp.vnfs_str = "synthfs";
 121        vfsp.vnfs_dvp = 0;
 122        vfsp.vnfs_fsnode = sp;
 123        vfsp.vnfs_cnp = 0;
 124        vfsp.vnfs_vops = synthfs_vnodeop_p;
 125        vfsp.vnfs_rdev = 0;
 126        vfsp.vnfs_filesize = 0;
 127        vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE;
 128        vfsp.vnfs_marksystem = 0;
 129        vfsp.vnfs_markroot = 0;
 130
 131        result = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, &vp); 
 132        if (result != 0) {
 133            DBG_VOP(("getnewvnode failed with error code %d\n", result));
 134            FREE(nodename, M_TEMP);
 135            FREE(sp, M_TEMP);
 136            return result;
 137        }
 138        vnode_ref(vp);
 139
 140    sp->s_vp = vp;
 141
 142    /* If there's a parent directory, update its subnode structures to insert this new node: */
 143    if (dp) {
 144        result = synthfs_insertnode(sp, VTOS(dp));
 145    };
 146
 147    *vpp = vp;
 148
 149    return result;
 150}
 151
 152
 153    
 154int synthfs_remove_entry(struct vnode *vp) {
 155        struct synthfsnode *sp = VTOS(vp);
 156        struct synthfsnode *psp = sp->s_parent;
 157        struct timeval now;
 158        
 159        if (psp) {
 160                TAILQ_REMOVE(&psp->s_u.d.d_subnodes, sp, s_sibling);
 161                --psp->s_u.d.d_entrycount;
 162                
 163                psp->s_nodeflags |= IN_CHANGE | IN_MODIFIED;
 164                microtime(&now);
 165                synthfs_update(STOV(psp), &now, &now, 0);
 166        };
 167        
 168    return 0;
 169}
 170
 171
 172
 173int synthfs_move_rename_entry(struct vnode *source_vp, struct vnode *newparent_vp, char *new_name) {
 174        struct synthfsnode *source_sp = VTOS(source_vp);
 175        struct synthfsnode *parent_sp = VTOS(newparent_vp);
 176        char *new_name_ptr;
 177        int result = 0;
 178        
 179        /* Unlink the entry from its current place: */
 180        result = synthfs_remove_entry(source_vp);
 181        if (result) goto err_exit;
 182
 183        /* Change the name as necessary: */
 184        if (new_name) {
 185                FREE(source_sp->s_name, M_TEMP);
 186                MALLOC(new_name_ptr, char *, strlen(new_name) + 1, M_TEMP, M_WAITOK);
 187                strcpy(new_name_ptr, new_name);
 188                source_sp->s_name = new_name_ptr;
 189        };
 190        
 191        /* Insert the entry in its new home: */
 192        result = synthfs_insertnode(source_sp, parent_sp);
 193
 194err_exit:
 195        return result;
 196}
 197
 198
 199
 200int synthfs_new_directory(struct mount *mp, struct vnode *dp, const char *name, unsigned long nodeid, mode_t mode, struct proc *p, struct vnode **vpp) {
 201        int result;
 202        struct vnode *vp;
 203    struct synthfsnode *sp;
 204        
 205        result = synthfs_newnode(mp, dp, name, nodeid, mode, p, VDIR, &vp);
 206        if (result) {
 207                return result;
 208        };
 209    sp = VTOS(vp);
 210    sp->s_linkcount = 2;
 211        
 212    if (dp) {
 213        ++VTOS(dp)->s_linkcount;                                        /* Account for the [fictitious] ".." link */
 214    };
 215    
 216    /* Set up the directory-specific fields: */
 217    sp->s_type = SYNTHFS_DIRECTORY;
 218    sp->s_u.d.d_entrycount = 0;                                         /* No entries in this directory yet */
 219    TAILQ_INIT(&sp->s_u.d.d_subnodes);                          /* No subnodes of this directory yet */
 220
 221    *vpp = vp;
 222    
 223    return 0;
 224}
 225
 226
 227
 228int synthfs_remove_directory(struct vnode *vp) {
 229        struct synthfsnode *sp = VTOS(vp);
 230        struct synthfsnode *psp = sp->s_parent;
 231
 232        if (psp && (sp->s_type == SYNTHFS_DIRECTORY) && (psp != sp)) {
 233                --psp->s_linkcount;                                     /* account for the [fictitious] ".." link now removed */
 234        };
 235        vnode_rele(vp);
 236
 237        /* Do the standard cleanup involved in pruning an entry from the filesystem: */
 238        return synthfs_remove_entry(vp);                        /* Do whatever standard cleanup is required */
 239}
 240
 241
 242
 243int synthfs_new_symlink(
 244                struct mount *mp,
 245                struct vnode *dp,
 246                const char *name,
 247                unsigned long nodeid,
 248                char *targetstring,
 249                struct proc *p,
 250                struct vnode **vpp) {
 251        
 252        int result;
 253        struct vnode *vp;
 254        struct synthfsnode *sp;
 255        
 256        result = synthfs_newnode(mp, dp, name, nodeid, 0, p, VLNK,  &vp);
 257        if (result) {
 258                return result;
 259        };
 260    sp = VTOS(vp);
 261    sp->s_linkcount = 1;
 262        
 263    /* Set up the symlink-specific fields: */
 264    sp->s_type = SYNTHFS_SYMLINK;
 265    sp->s_u.s.s_length = strlen(targetstring);
 266    MALLOC(sp->s_u.s.s_symlinktarget, char *, sp->s_u.s.s_length + 1, M_TEMP, M_WAITOK);
 267    strcpy(sp->s_u.s.s_symlinktarget, targetstring);
 268    
 269    *vpp = vp;
 270    
 271    return 0;
 272}
 273
 274
 275
 276int synthfs_remove_symlink(struct vnode *vp) {
 277        struct synthfsnode *sp = VTOS(vp);
 278        
 279        FREE(sp->s_u.s.s_symlinktarget, M_TEMP);
 280        vnode_rele(vp);
 281
 282        /* Do the standard cleanup involved in pruning an entry from the filesystem: */
 283        return synthfs_remove_entry(vp);                                        /* Do whatever standard cleanup is required */
 284}
 285
 286
 287
 288
 289
 290
 291long synthfs_adddirentry(u_int32_t fileno, u_int8_t type, const char *name, struct uio *uio) {
 292    struct synthfs_direntry_head direntry;
 293        long namelength;
 294    int padding;
 295    long padtext = 0;
 296    unsigned short direntrylength;
 297
 298    namelength = ((name == NULL) ? 0 : strlen(name) + 1);
 299    padding = (4 - (namelength & 3)) & 3;
 300    direntrylength = sizeof(struct synthfs_direntry_head) + namelength + padding;
 301
 302        direntry.d_fileno = fileno;
 303    direntry.d_reclen = direntrylength;
 304        direntry.d_type = type;
 305        direntry.d_namlen = namelength;
 306
 307    if (uio_resid(uio) < direntry.d_reclen) {
 308        direntrylength = 0;
 309    } else {
 310        uiomove((caddr_t)(&direntry), sizeof(direntry), uio);
 311        if (name != NULL) {
 312            uiomove((caddr_t)name, namelength, uio);
 313        };
 314        if (padding > 0) {
 315            uiomove((caddr_t)&padtext, padding, uio);
 316        };
 317    };
 318
 319    return direntrylength;
 320}
 321
 322
 323
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.