1*0ca3913dSOlivier Deprez /* 2*0ca3913dSOlivier Deprez * Copyright (c) 2019, Arm Limited. All rights reserved. 3*0ca3913dSOlivier Deprez * 4*0ca3913dSOlivier Deprez * SPDX-License-Identifier: BSD-3-Clause 5*0ca3913dSOlivier Deprez */ 6*0ca3913dSOlivier Deprez 7*0ca3913dSOlivier Deprez #include <cdefs.h> 8*0ca3913dSOlivier Deprez #include <common/debug.h> 9*0ca3913dSOlivier Deprez #include <lib/debugfs.h> 10*0ca3913dSOlivier Deprez #include <string.h> 11*0ca3913dSOlivier Deprez 12*0ca3913dSOlivier Deprez #include "dev.h" 13*0ca3913dSOlivier Deprez 14*0ca3913dSOlivier Deprez #define NR_MOUNT_POINTS 4 15*0ca3913dSOlivier Deprez 16*0ca3913dSOlivier Deprez struct mount_point { 17*0ca3913dSOlivier Deprez chan_t *new; 18*0ca3913dSOlivier Deprez chan_t *old; 19*0ca3913dSOlivier Deprez }; 20*0ca3913dSOlivier Deprez 21*0ca3913dSOlivier Deprez /* This array contains all the available channels of the filesystem. 22*0ca3913dSOlivier Deprez * A file descriptor is the index of a specific channel in this array. 23*0ca3913dSOlivier Deprez */ 24*0ca3913dSOlivier Deprez static chan_t fdset[NR_CHANS]; 25*0ca3913dSOlivier Deprez 26*0ca3913dSOlivier Deprez /* This array contains all the available mount points of the filesystem. */ 27*0ca3913dSOlivier Deprez static struct mount_point mount_points[NR_MOUNT_POINTS]; 28*0ca3913dSOlivier Deprez 29*0ca3913dSOlivier Deprez /* This variable stores the channel associated to the root directory. */ 30*0ca3913dSOlivier Deprez static chan_t slash_channel; 31*0ca3913dSOlivier Deprez 32*0ca3913dSOlivier Deprez /* This function creates a channel from a device index and registers 33*0ca3913dSOlivier Deprez * it to fdset. 34*0ca3913dSOlivier Deprez */ 35*0ca3913dSOlivier Deprez static chan_t *create_new_channel(unsigned char index) 36*0ca3913dSOlivier Deprez { 37*0ca3913dSOlivier Deprez chan_t *channel = NULL; 38*0ca3913dSOlivier Deprez int i; 39*0ca3913dSOlivier Deprez 40*0ca3913dSOlivier Deprez for (i = 0; i < NR_CHANS; i++) { 41*0ca3913dSOlivier Deprez if (fdset[i].index == NODEV) { 42*0ca3913dSOlivier Deprez channel = &fdset[i]; 43*0ca3913dSOlivier Deprez channel->index = index; 44*0ca3913dSOlivier Deprez break; 45*0ca3913dSOlivier Deprez } 46*0ca3913dSOlivier Deprez } 47*0ca3913dSOlivier Deprez 48*0ca3913dSOlivier Deprez return channel; 49*0ca3913dSOlivier Deprez } 50*0ca3913dSOlivier Deprez 51*0ca3913dSOlivier Deprez /******************************************************************************* 52*0ca3913dSOlivier Deprez * This function returns a pointer to an existing channel in fdset from a file 53*0ca3913dSOlivier Deprez * descriptor. 54*0ca3913dSOlivier Deprez ******************************************************************************/ 55*0ca3913dSOlivier Deprez static chan_t *fd_to_channel(int fd) 56*0ca3913dSOlivier Deprez { 57*0ca3913dSOlivier Deprez if ((fd < 0) || (fd >= NR_CHANS) || (fdset[fd].index == NODEV)) { 58*0ca3913dSOlivier Deprez return NULL; 59*0ca3913dSOlivier Deprez } 60*0ca3913dSOlivier Deprez 61*0ca3913dSOlivier Deprez return &fdset[fd]; 62*0ca3913dSOlivier Deprez } 63*0ca3913dSOlivier Deprez 64*0ca3913dSOlivier Deprez /******************************************************************************* 65*0ca3913dSOlivier Deprez * This function returns a file descriptor from a channel. 66*0ca3913dSOlivier Deprez * The caller must be sure that the channel is registered in fdset. 67*0ca3913dSOlivier Deprez ******************************************************************************/ 68*0ca3913dSOlivier Deprez static int channel_to_fd(chan_t *channel) 69*0ca3913dSOlivier Deprez { 70*0ca3913dSOlivier Deprez return (channel == NULL) ? -1 : (channel - fdset); 71*0ca3913dSOlivier Deprez } 72*0ca3913dSOlivier Deprez 73*0ca3913dSOlivier Deprez /******************************************************************************* 74*0ca3913dSOlivier Deprez * This function checks the validity of a mode. 75*0ca3913dSOlivier Deprez ******************************************************************************/ 76*0ca3913dSOlivier Deprez static bool is_valid_mode(int mode) 77*0ca3913dSOlivier Deprez { 78*0ca3913dSOlivier Deprez if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR))) { 79*0ca3913dSOlivier Deprez return false; 80*0ca3913dSOlivier Deprez } 81*0ca3913dSOlivier Deprez if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR))) { 82*0ca3913dSOlivier Deprez return false; 83*0ca3913dSOlivier Deprez } 84*0ca3913dSOlivier Deprez if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE))) { 85*0ca3913dSOlivier Deprez return false; 86*0ca3913dSOlivier Deprez } 87*0ca3913dSOlivier Deprez 88*0ca3913dSOlivier Deprez return true; 89*0ca3913dSOlivier Deprez } 90*0ca3913dSOlivier Deprez 91*0ca3913dSOlivier Deprez /******************************************************************************* 92*0ca3913dSOlivier Deprez * This function extracts the next part of the given path contained and puts it 93*0ca3913dSOlivier Deprez * in token. It returns a pointer to the remainder of the path. 94*0ca3913dSOlivier Deprez ******************************************************************************/ 95*0ca3913dSOlivier Deprez static const char *next(const char *path, char *token) 96*0ca3913dSOlivier Deprez { 97*0ca3913dSOlivier Deprez int index; 98*0ca3913dSOlivier Deprez const char *cursor; 99*0ca3913dSOlivier Deprez 100*0ca3913dSOlivier Deprez while (*path == '/') { 101*0ca3913dSOlivier Deprez ++path; 102*0ca3913dSOlivier Deprez } 103*0ca3913dSOlivier Deprez 104*0ca3913dSOlivier Deprez index = 0; 105*0ca3913dSOlivier Deprez cursor = path; 106*0ca3913dSOlivier Deprez if (*path != '\0') { 107*0ca3913dSOlivier Deprez while (*cursor != '/' && *cursor != '\0') { 108*0ca3913dSOlivier Deprez if (index == NAMELEN) { 109*0ca3913dSOlivier Deprez return NULL; 110*0ca3913dSOlivier Deprez } 111*0ca3913dSOlivier Deprez token[index++] = *cursor++; 112*0ca3913dSOlivier Deprez } 113*0ca3913dSOlivier Deprez } 114*0ca3913dSOlivier Deprez token[index] = '\0'; 115*0ca3913dSOlivier Deprez 116*0ca3913dSOlivier Deprez return cursor; 117*0ca3913dSOlivier Deprez } 118*0ca3913dSOlivier Deprez 119*0ca3913dSOlivier Deprez /******************************************************************************* 120*0ca3913dSOlivier Deprez * This function returns the driver index in devtab of the driver 121*0ca3913dSOlivier Deprez * identified by id. 122*0ca3913dSOlivier Deprez ******************************************************************************/ 123*0ca3913dSOlivier Deprez static int get_device_index(int id) 124*0ca3913dSOlivier Deprez { 125*0ca3913dSOlivier Deprez int index; 126*0ca3913dSOlivier Deprez dev_t * const *dp; 127*0ca3913dSOlivier Deprez 128*0ca3913dSOlivier Deprez for (index = 0, dp = devtab; *dp && (*dp)->id != id; ++dp) { 129*0ca3913dSOlivier Deprez index++; 130*0ca3913dSOlivier Deprez } 131*0ca3913dSOlivier Deprez 132*0ca3913dSOlivier Deprez if (*dp == NULL) { 133*0ca3913dSOlivier Deprez return -1; 134*0ca3913dSOlivier Deprez } 135*0ca3913dSOlivier Deprez 136*0ca3913dSOlivier Deprez return index; 137*0ca3913dSOlivier Deprez } 138*0ca3913dSOlivier Deprez 139*0ca3913dSOlivier Deprez /******************************************************************************* 140*0ca3913dSOlivier Deprez * This function clears a given channel fields 141*0ca3913dSOlivier Deprez ******************************************************************************/ 142*0ca3913dSOlivier Deprez static void channel_clear(chan_t *channel) 143*0ca3913dSOlivier Deprez { 144*0ca3913dSOlivier Deprez channel->offset = 0; 145*0ca3913dSOlivier Deprez channel->qid = 0; 146*0ca3913dSOlivier Deprez channel->index = NODEV; 147*0ca3913dSOlivier Deprez channel->dev = 0; 148*0ca3913dSOlivier Deprez channel->mode = 0; 149*0ca3913dSOlivier Deprez } 150*0ca3913dSOlivier Deprez 151*0ca3913dSOlivier Deprez /******************************************************************************* 152*0ca3913dSOlivier Deprez * This function closes the channel pointed to by c. 153*0ca3913dSOlivier Deprez ******************************************************************************/ 154*0ca3913dSOlivier Deprez void channel_close(chan_t *channel) 155*0ca3913dSOlivier Deprez { 156*0ca3913dSOlivier Deprez if (channel != NULL) { 157*0ca3913dSOlivier Deprez channel_clear(channel); 158*0ca3913dSOlivier Deprez } 159*0ca3913dSOlivier Deprez } 160*0ca3913dSOlivier Deprez 161*0ca3913dSOlivier Deprez /******************************************************************************* 162*0ca3913dSOlivier Deprez * This function copies data from src to dst after applying the offset of the 163*0ca3913dSOlivier Deprez * channel c. nbytes bytes are expected to be copied unless the data goes over 164*0ca3913dSOlivier Deprez * dst + len. 165*0ca3913dSOlivier Deprez * It returns the actual number of bytes that were copied. 166*0ca3913dSOlivier Deprez ******************************************************************************/ 167*0ca3913dSOlivier Deprez int buf_to_channel(chan_t *channel, void *dst, void *src, int nbytes, long len) 168*0ca3913dSOlivier Deprez { 169*0ca3913dSOlivier Deprez const char *addr = src; 170*0ca3913dSOlivier Deprez 171*0ca3913dSOlivier Deprez if ((channel == NULL) || (dst == NULL) || (src == NULL)) { 172*0ca3913dSOlivier Deprez return 0; 173*0ca3913dSOlivier Deprez } 174*0ca3913dSOlivier Deprez 175*0ca3913dSOlivier Deprez if (channel->offset >= len) { 176*0ca3913dSOlivier Deprez return 0; 177*0ca3913dSOlivier Deprez } 178*0ca3913dSOlivier Deprez 179*0ca3913dSOlivier Deprez if ((channel->offset + nbytes) > len) { 180*0ca3913dSOlivier Deprez nbytes = len - channel->offset; 181*0ca3913dSOlivier Deprez } 182*0ca3913dSOlivier Deprez 183*0ca3913dSOlivier Deprez memcpy(dst, addr + channel->offset, nbytes); 184*0ca3913dSOlivier Deprez 185*0ca3913dSOlivier Deprez channel->offset += nbytes; 186*0ca3913dSOlivier Deprez 187*0ca3913dSOlivier Deprez return nbytes; 188*0ca3913dSOlivier Deprez } 189*0ca3913dSOlivier Deprez 190*0ca3913dSOlivier Deprez /******************************************************************************* 191*0ca3913dSOlivier Deprez * This function checks whether a channel (identified by its device index and 192*0ca3913dSOlivier Deprez * qid) is registered as a mount point. 193*0ca3913dSOlivier Deprez * Returns a pointer to the channel it is mounted to when found, NULL otherwise. 194*0ca3913dSOlivier Deprez ******************************************************************************/ 195*0ca3913dSOlivier Deprez static chan_t *mount_point_to_channel(int index, qid_t qid) 196*0ca3913dSOlivier Deprez { 197*0ca3913dSOlivier Deprez chan_t *channel; 198*0ca3913dSOlivier Deprez struct mount_point *mp; 199*0ca3913dSOlivier Deprez 200*0ca3913dSOlivier Deprez for (mp = mount_points; mp < &mount_points[NR_MOUNT_POINTS]; mp++) { 201*0ca3913dSOlivier Deprez channel = mp->new; 202*0ca3913dSOlivier Deprez if (channel == NULL) { 203*0ca3913dSOlivier Deprez continue; 204*0ca3913dSOlivier Deprez } 205*0ca3913dSOlivier Deprez 206*0ca3913dSOlivier Deprez if ((channel->index == index) && (channel->qid == qid)) { 207*0ca3913dSOlivier Deprez return mp->old; 208*0ca3913dSOlivier Deprez } 209*0ca3913dSOlivier Deprez } 210*0ca3913dSOlivier Deprez 211*0ca3913dSOlivier Deprez return NULL; 212*0ca3913dSOlivier Deprez } 213*0ca3913dSOlivier Deprez 214*0ca3913dSOlivier Deprez /******************************************************************************* 215*0ca3913dSOlivier Deprez * This function calls the attach function of the driver identified by id. 216*0ca3913dSOlivier Deprez ******************************************************************************/ 217*0ca3913dSOlivier Deprez chan_t *attach(int id, int dev) 218*0ca3913dSOlivier Deprez { 219*0ca3913dSOlivier Deprez /* Get the devtab index for the driver identified by id */ 220*0ca3913dSOlivier Deprez int index = get_device_index(id); 221*0ca3913dSOlivier Deprez 222*0ca3913dSOlivier Deprez if (index < 0) { 223*0ca3913dSOlivier Deprez return NULL; 224*0ca3913dSOlivier Deprez } 225*0ca3913dSOlivier Deprez 226*0ca3913dSOlivier Deprez return devtab[index]->attach(id, dev); 227*0ca3913dSOlivier Deprez } 228*0ca3913dSOlivier Deprez 229*0ca3913dSOlivier Deprez /******************************************************************************* 230*0ca3913dSOlivier Deprez * This function is the default implementation of the driver attach function. 231*0ca3913dSOlivier Deprez * It creates a new channel and returns a pointer to it. 232*0ca3913dSOlivier Deprez ******************************************************************************/ 233*0ca3913dSOlivier Deprez chan_t *devattach(int id, int dev) 234*0ca3913dSOlivier Deprez { 235*0ca3913dSOlivier Deprez chan_t *channel; 236*0ca3913dSOlivier Deprez int index; 237*0ca3913dSOlivier Deprez 238*0ca3913dSOlivier Deprez index = get_device_index(id); 239*0ca3913dSOlivier Deprez if (index < 0) { 240*0ca3913dSOlivier Deprez return NULL; 241*0ca3913dSOlivier Deprez } 242*0ca3913dSOlivier Deprez 243*0ca3913dSOlivier Deprez channel = create_new_channel(index); 244*0ca3913dSOlivier Deprez if (channel == NULL) { 245*0ca3913dSOlivier Deprez return NULL; 246*0ca3913dSOlivier Deprez } 247*0ca3913dSOlivier Deprez 248*0ca3913dSOlivier Deprez channel->dev = dev; 249*0ca3913dSOlivier Deprez channel->qid = CHDIR; 250*0ca3913dSOlivier Deprez 251*0ca3913dSOlivier Deprez return channel; 252*0ca3913dSOlivier Deprez } 253*0ca3913dSOlivier Deprez 254*0ca3913dSOlivier Deprez /******************************************************************************* 255*0ca3913dSOlivier Deprez * This function returns a channel given a path. 256*0ca3913dSOlivier Deprez * It goes through the filesystem, from the root namespace ('/') or from a 257*0ca3913dSOlivier Deprez * device namespace ('#'), switching channel on mount points. 258*0ca3913dSOlivier Deprez ******************************************************************************/ 259*0ca3913dSOlivier Deprez chan_t *path_to_channel(const char *path, int mode) 260*0ca3913dSOlivier Deprez { 261*0ca3913dSOlivier Deprez int i, n; 262*0ca3913dSOlivier Deprez const char *path_next; 263*0ca3913dSOlivier Deprez chan_t *mnt, *channel; 264*0ca3913dSOlivier Deprez char elem[NAMELEN]; 265*0ca3913dSOlivier Deprez 266*0ca3913dSOlivier Deprez if (path == NULL) { 267*0ca3913dSOlivier Deprez return NULL; 268*0ca3913dSOlivier Deprez } 269*0ca3913dSOlivier Deprez 270*0ca3913dSOlivier Deprez switch (path[0]) { 271*0ca3913dSOlivier Deprez case '/': 272*0ca3913dSOlivier Deprez channel = clone(&slash_channel, NULL); 273*0ca3913dSOlivier Deprez path_next = path; 274*0ca3913dSOlivier Deprez break; 275*0ca3913dSOlivier Deprez case '#': 276*0ca3913dSOlivier Deprez path_next = next(path + 1, elem); 277*0ca3913dSOlivier Deprez if (path_next == NULL) { 278*0ca3913dSOlivier Deprez goto noent; 279*0ca3913dSOlivier Deprez } 280*0ca3913dSOlivier Deprez 281*0ca3913dSOlivier Deprez n = 0; 282*0ca3913dSOlivier Deprez for (i = 1; (elem[i] >= '0') && (elem[i] <= '9'); i++) { 283*0ca3913dSOlivier Deprez n += elem[i] - '0'; 284*0ca3913dSOlivier Deprez } 285*0ca3913dSOlivier Deprez 286*0ca3913dSOlivier Deprez if (elem[i] != '\0') { 287*0ca3913dSOlivier Deprez goto noent; 288*0ca3913dSOlivier Deprez } 289*0ca3913dSOlivier Deprez 290*0ca3913dSOlivier Deprez channel = attach(elem[0], n); 291*0ca3913dSOlivier Deprez break; 292*0ca3913dSOlivier Deprez default: 293*0ca3913dSOlivier Deprez return NULL; 294*0ca3913dSOlivier Deprez } 295*0ca3913dSOlivier Deprez 296*0ca3913dSOlivier Deprez if (channel == NULL) { 297*0ca3913dSOlivier Deprez return NULL; 298*0ca3913dSOlivier Deprez } 299*0ca3913dSOlivier Deprez 300*0ca3913dSOlivier Deprez for (path_next = next(path_next, elem); *elem; 301*0ca3913dSOlivier Deprez path_next = next(path_next, elem)) { 302*0ca3913dSOlivier Deprez if ((channel->qid & CHDIR) == 0) { 303*0ca3913dSOlivier Deprez goto notfound; 304*0ca3913dSOlivier Deprez } 305*0ca3913dSOlivier Deprez 306*0ca3913dSOlivier Deprez if (devtab[channel->index]->walk(channel, elem) < 0) { 307*0ca3913dSOlivier Deprez channel_close(channel); 308*0ca3913dSOlivier Deprez goto notfound; 309*0ca3913dSOlivier Deprez } 310*0ca3913dSOlivier Deprez 311*0ca3913dSOlivier Deprez mnt = mount_point_to_channel(channel->index, channel->qid); 312*0ca3913dSOlivier Deprez if (mnt != NULL) { 313*0ca3913dSOlivier Deprez clone(mnt, channel); 314*0ca3913dSOlivier Deprez } 315*0ca3913dSOlivier Deprez } 316*0ca3913dSOlivier Deprez 317*0ca3913dSOlivier Deprez if (path_next == NULL) { 318*0ca3913dSOlivier Deprez goto notfound; 319*0ca3913dSOlivier Deprez } 320*0ca3913dSOlivier Deprez 321*0ca3913dSOlivier Deprez /* TODO: check mode */ 322*0ca3913dSOlivier Deprez return channel; 323*0ca3913dSOlivier Deprez 324*0ca3913dSOlivier Deprez notfound: 325*0ca3913dSOlivier Deprez channel_close(channel); 326*0ca3913dSOlivier Deprez noent: 327*0ca3913dSOlivier Deprez return NULL; 328*0ca3913dSOlivier Deprez } 329*0ca3913dSOlivier Deprez 330*0ca3913dSOlivier Deprez /******************************************************************************* 331*0ca3913dSOlivier Deprez * This function calls the clone function of the driver associated to the 332*0ca3913dSOlivier Deprez * channel c. 333*0ca3913dSOlivier Deprez ******************************************************************************/ 334*0ca3913dSOlivier Deprez chan_t *clone(chan_t *c, chan_t *nc) 335*0ca3913dSOlivier Deprez { 336*0ca3913dSOlivier Deprez return devtab[c->index]->clone(c, nc); 337*0ca3913dSOlivier Deprez } 338*0ca3913dSOlivier Deprez 339*0ca3913dSOlivier Deprez /******************************************************************************* 340*0ca3913dSOlivier Deprez * This function is the default implementation of the driver clone function. 341*0ca3913dSOlivier Deprez * It creates a new channel and returns a pointer to it. 342*0ca3913dSOlivier Deprez * It clones channel into new_channel. 343*0ca3913dSOlivier Deprez ******************************************************************************/ 344*0ca3913dSOlivier Deprez chan_t *devclone(chan_t *channel, chan_t *new_channel) 345*0ca3913dSOlivier Deprez { 346*0ca3913dSOlivier Deprez if (channel == NULL) { 347*0ca3913dSOlivier Deprez return NULL; 348*0ca3913dSOlivier Deprez } 349*0ca3913dSOlivier Deprez 350*0ca3913dSOlivier Deprez if (new_channel == NULL) { 351*0ca3913dSOlivier Deprez new_channel = create_new_channel(channel->index); 352*0ca3913dSOlivier Deprez if (new_channel == NULL) { 353*0ca3913dSOlivier Deprez return NULL; 354*0ca3913dSOlivier Deprez } 355*0ca3913dSOlivier Deprez } 356*0ca3913dSOlivier Deprez 357*0ca3913dSOlivier Deprez new_channel->qid = channel->qid; 358*0ca3913dSOlivier Deprez new_channel->dev = channel->dev; 359*0ca3913dSOlivier Deprez new_channel->mode = channel->mode; 360*0ca3913dSOlivier Deprez new_channel->offset = channel->offset; 361*0ca3913dSOlivier Deprez new_channel->index = channel->index; 362*0ca3913dSOlivier Deprez 363*0ca3913dSOlivier Deprez return new_channel; 364*0ca3913dSOlivier Deprez } 365*0ca3913dSOlivier Deprez 366*0ca3913dSOlivier Deprez /******************************************************************************* 367*0ca3913dSOlivier Deprez * This function is the default implementation of the driver walk function. 368*0ca3913dSOlivier Deprez * It goes through all the elements of tab using the gen function until a match 369*0ca3913dSOlivier Deprez * is found with name. 370*0ca3913dSOlivier Deprez * If a match is found, it copies the qid of the new directory. 371*0ca3913dSOlivier Deprez ******************************************************************************/ 372*0ca3913dSOlivier Deprez int devwalk(chan_t *channel, const char *name, const dirtab_t *tab, 373*0ca3913dSOlivier Deprez int ntab, devgen_t *gen) 374*0ca3913dSOlivier Deprez { 375*0ca3913dSOlivier Deprez int i; 376*0ca3913dSOlivier Deprez dir_t dir; 377*0ca3913dSOlivier Deprez 378*0ca3913dSOlivier Deprez if ((channel == NULL) || (name == NULL) || (gen == NULL)) { 379*0ca3913dSOlivier Deprez return -1; 380*0ca3913dSOlivier Deprez } 381*0ca3913dSOlivier Deprez 382*0ca3913dSOlivier Deprez if ((name[0] == '.') && (name[1] == '\0')) { 383*0ca3913dSOlivier Deprez return 1; 384*0ca3913dSOlivier Deprez } 385*0ca3913dSOlivier Deprez 386*0ca3913dSOlivier Deprez for (i = 0; ; i++) { 387*0ca3913dSOlivier Deprez switch ((*gen)(channel, tab, ntab, i, &dir)) { 388*0ca3913dSOlivier Deprez case 0: 389*0ca3913dSOlivier Deprez /* Intentional fall-through */ 390*0ca3913dSOlivier Deprez case -1: 391*0ca3913dSOlivier Deprez return -1; 392*0ca3913dSOlivier Deprez case 1: 393*0ca3913dSOlivier Deprez if (strncmp(name, dir.name, NAMELEN) != 0) { 394*0ca3913dSOlivier Deprez continue; 395*0ca3913dSOlivier Deprez } 396*0ca3913dSOlivier Deprez channel->qid = dir.qid; 397*0ca3913dSOlivier Deprez return 1; 398*0ca3913dSOlivier Deprez } 399*0ca3913dSOlivier Deprez } 400*0ca3913dSOlivier Deprez } 401*0ca3913dSOlivier Deprez 402*0ca3913dSOlivier Deprez /******************************************************************************* 403*0ca3913dSOlivier Deprez * This is a helper function which exposes the content of a directory, element 404*0ca3913dSOlivier Deprez * by element. It is meant to be called until the end of the directory is 405*0ca3913dSOlivier Deprez * reached or an error occurs. 406*0ca3913dSOlivier Deprez * It returns -1 on error, 0 on end of directory and 1 when a new file is found. 407*0ca3913dSOlivier Deprez ******************************************************************************/ 408*0ca3913dSOlivier Deprez int dirread(chan_t *channel, dir_t *dir, const dirtab_t *tab, 409*0ca3913dSOlivier Deprez int ntab, devgen_t *gen) 410*0ca3913dSOlivier Deprez { 411*0ca3913dSOlivier Deprez int i, ret; 412*0ca3913dSOlivier Deprez 413*0ca3913dSOlivier Deprez if ((channel == NULL) || (dir == NULL) || (gen == NULL)) { 414*0ca3913dSOlivier Deprez return -1; 415*0ca3913dSOlivier Deprez } 416*0ca3913dSOlivier Deprez 417*0ca3913dSOlivier Deprez i = channel->offset/sizeof(dir_t); 418*0ca3913dSOlivier Deprez ret = (*gen)(channel, tab, ntab, i, dir); 419*0ca3913dSOlivier Deprez if (ret == 1) { 420*0ca3913dSOlivier Deprez channel->offset += sizeof(dir_t); 421*0ca3913dSOlivier Deprez } 422*0ca3913dSOlivier Deprez 423*0ca3913dSOlivier Deprez return ret; 424*0ca3913dSOlivier Deprez } 425*0ca3913dSOlivier Deprez 426*0ca3913dSOlivier Deprez /******************************************************************************* 427*0ca3913dSOlivier Deprez * This function sets the elements of dir. 428*0ca3913dSOlivier Deprez ******************************************************************************/ 429*0ca3913dSOlivier Deprez void make_dir_entry(chan_t *channel, dir_t *dir, 430*0ca3913dSOlivier Deprez const char *name, long length, qid_t qid, unsigned int mode) 431*0ca3913dSOlivier Deprez { 432*0ca3913dSOlivier Deprez if ((channel == NULL) || (dir == NULL) || (name == NULL)) { 433*0ca3913dSOlivier Deprez return; 434*0ca3913dSOlivier Deprez } 435*0ca3913dSOlivier Deprez 436*0ca3913dSOlivier Deprez strlcpy(dir->name, name, sizeof(dir->name)); 437*0ca3913dSOlivier Deprez dir->length = length; 438*0ca3913dSOlivier Deprez dir->qid = qid; 439*0ca3913dSOlivier Deprez dir->mode = mode; 440*0ca3913dSOlivier Deprez 441*0ca3913dSOlivier Deprez if ((qid & CHDIR) != 0) { 442*0ca3913dSOlivier Deprez dir->mode |= O_DIR; 443*0ca3913dSOlivier Deprez } 444*0ca3913dSOlivier Deprez 445*0ca3913dSOlivier Deprez dir->index = channel->index; 446*0ca3913dSOlivier Deprez dir->dev = channel->dev; 447*0ca3913dSOlivier Deprez } 448*0ca3913dSOlivier Deprez 449*0ca3913dSOlivier Deprez /******************************************************************************* 450*0ca3913dSOlivier Deprez * This function is the default implementation of the internal driver gen 451*0ca3913dSOlivier Deprez * function. 452*0ca3913dSOlivier Deprez * It copies and formats the information of the nth element of tab into dir. 453*0ca3913dSOlivier Deprez ******************************************************************************/ 454*0ca3913dSOlivier Deprez int devgen(chan_t *channel, const dirtab_t *tab, int ntab, int n, dir_t *dir) 455*0ca3913dSOlivier Deprez { 456*0ca3913dSOlivier Deprez const dirtab_t *dp; 457*0ca3913dSOlivier Deprez 458*0ca3913dSOlivier Deprez if ((channel == NULL) || (dir == NULL) || (tab == NULL) || 459*0ca3913dSOlivier Deprez (n >= ntab)) { 460*0ca3913dSOlivier Deprez return 0; 461*0ca3913dSOlivier Deprez } 462*0ca3913dSOlivier Deprez 463*0ca3913dSOlivier Deprez dp = &tab[n]; 464*0ca3913dSOlivier Deprez make_dir_entry(channel, dir, dp->name, dp->length, dp->qid, dp->perm); 465*0ca3913dSOlivier Deprez return 1; 466*0ca3913dSOlivier Deprez } 467*0ca3913dSOlivier Deprez 468*0ca3913dSOlivier Deprez /******************************************************************************* 469*0ca3913dSOlivier Deprez * This function returns a file descriptor identifying the channel associated to 470*0ca3913dSOlivier Deprez * the given path. 471*0ca3913dSOlivier Deprez ******************************************************************************/ 472*0ca3913dSOlivier Deprez int open(const char *path, int mode) 473*0ca3913dSOlivier Deprez { 474*0ca3913dSOlivier Deprez chan_t *channel; 475*0ca3913dSOlivier Deprez 476*0ca3913dSOlivier Deprez if (path == NULL) { 477*0ca3913dSOlivier Deprez return -1; 478*0ca3913dSOlivier Deprez } 479*0ca3913dSOlivier Deprez 480*0ca3913dSOlivier Deprez if (is_valid_mode(mode) == false) { 481*0ca3913dSOlivier Deprez return -1; 482*0ca3913dSOlivier Deprez } 483*0ca3913dSOlivier Deprez 484*0ca3913dSOlivier Deprez channel = path_to_channel(path, mode); 485*0ca3913dSOlivier Deprez 486*0ca3913dSOlivier Deprez return channel_to_fd(channel); 487*0ca3913dSOlivier Deprez } 488*0ca3913dSOlivier Deprez 489*0ca3913dSOlivier Deprez /******************************************************************************* 490*0ca3913dSOlivier Deprez * This function closes the channel identified by the file descriptor fd. 491*0ca3913dSOlivier Deprez ******************************************************************************/ 492*0ca3913dSOlivier Deprez int close(int fd) 493*0ca3913dSOlivier Deprez { 494*0ca3913dSOlivier Deprez chan_t *channel; 495*0ca3913dSOlivier Deprez 496*0ca3913dSOlivier Deprez channel = fd_to_channel(fd); 497*0ca3913dSOlivier Deprez if (channel == NULL) { 498*0ca3913dSOlivier Deprez return -1; 499*0ca3913dSOlivier Deprez } 500*0ca3913dSOlivier Deprez 501*0ca3913dSOlivier Deprez channel_close(channel); 502*0ca3913dSOlivier Deprez return 0; 503*0ca3913dSOlivier Deprez } 504*0ca3913dSOlivier Deprez 505*0ca3913dSOlivier Deprez /******************************************************************************* 506*0ca3913dSOlivier Deprez * This function is the default implementation of the driver stat function. 507*0ca3913dSOlivier Deprez * It goes through all the elements of tab using the gen function until a match 508*0ca3913dSOlivier Deprez * is found with file. 509*0ca3913dSOlivier Deprez * If a match is found, dir contains the information file. 510*0ca3913dSOlivier Deprez ******************************************************************************/ 511*0ca3913dSOlivier Deprez int devstat(chan_t *dirc, const char *file, dir_t *dir, 512*0ca3913dSOlivier Deprez const dirtab_t *tab, int ntab, devgen_t *gen) 513*0ca3913dSOlivier Deprez { 514*0ca3913dSOlivier Deprez int i, r = 0; 515*0ca3913dSOlivier Deprez chan_t *c, *mnt; 516*0ca3913dSOlivier Deprez 517*0ca3913dSOlivier Deprez if ((dirc == NULL) || (dir == NULL) || (gen == NULL)) { 518*0ca3913dSOlivier Deprez return -1; 519*0ca3913dSOlivier Deprez } 520*0ca3913dSOlivier Deprez 521*0ca3913dSOlivier Deprez c = path_to_channel(file, O_STAT); 522*0ca3913dSOlivier Deprez if (c == NULL) { 523*0ca3913dSOlivier Deprez return -1; 524*0ca3913dSOlivier Deprez } 525*0ca3913dSOlivier Deprez 526*0ca3913dSOlivier Deprez for (i = 0; ; i++) { 527*0ca3913dSOlivier Deprez switch ((*gen)(dirc, tab, ntab, i, dir)) { 528*0ca3913dSOlivier Deprez case 0: 529*0ca3913dSOlivier Deprez /* Intentional fall-through */ 530*0ca3913dSOlivier Deprez case -1: 531*0ca3913dSOlivier Deprez r = -1; 532*0ca3913dSOlivier Deprez goto leave; 533*0ca3913dSOlivier Deprez case 1: 534*0ca3913dSOlivier Deprez mnt = mount_point_to_channel(dir->index, dir->qid); 535*0ca3913dSOlivier Deprez if (mnt != NULL) { 536*0ca3913dSOlivier Deprez dir->qid = mnt->qid; 537*0ca3913dSOlivier Deprez dir->index = mnt->index; 538*0ca3913dSOlivier Deprez } 539*0ca3913dSOlivier Deprez 540*0ca3913dSOlivier Deprez if ((dir->qid != c->qid) || (dir->index != c->index)) { 541*0ca3913dSOlivier Deprez continue; 542*0ca3913dSOlivier Deprez } 543*0ca3913dSOlivier Deprez 544*0ca3913dSOlivier Deprez goto leave; 545*0ca3913dSOlivier Deprez } 546*0ca3913dSOlivier Deprez } 547*0ca3913dSOlivier Deprez 548*0ca3913dSOlivier Deprez leave: 549*0ca3913dSOlivier Deprez channel_close(c); 550*0ca3913dSOlivier Deprez return r; 551*0ca3913dSOlivier Deprez } 552*0ca3913dSOlivier Deprez 553*0ca3913dSOlivier Deprez /******************************************************************************* 554*0ca3913dSOlivier Deprez * This function calls the stat function of the driver associated to the parent 555*0ca3913dSOlivier Deprez * directory of the file in path. 556*0ca3913dSOlivier Deprez * The result is stored in dir. 557*0ca3913dSOlivier Deprez ******************************************************************************/ 558*0ca3913dSOlivier Deprez int stat(const char *path, dir_t *dir) 559*0ca3913dSOlivier Deprez { 560*0ca3913dSOlivier Deprez int r; 561*0ca3913dSOlivier Deprez size_t len; 562*0ca3913dSOlivier Deprez chan_t *channel; 563*0ca3913dSOlivier Deprez char *p, dirname[PATHLEN]; 564*0ca3913dSOlivier Deprez 565*0ca3913dSOlivier Deprez if ((path == NULL) || (dir == NULL)) { 566*0ca3913dSOlivier Deprez return -1; 567*0ca3913dSOlivier Deprez } 568*0ca3913dSOlivier Deprez 569*0ca3913dSOlivier Deprez len = strlen(path); 570*0ca3913dSOlivier Deprez if ((len + 1) > sizeof(dirname)) { 571*0ca3913dSOlivier Deprez return -1; 572*0ca3913dSOlivier Deprez } 573*0ca3913dSOlivier Deprez 574*0ca3913dSOlivier Deprez memcpy(dirname, path, len); 575*0ca3913dSOlivier Deprez for (p = dirname + len; p > dirname; --p) { 576*0ca3913dSOlivier Deprez if (*p != '/') { 577*0ca3913dSOlivier Deprez break; 578*0ca3913dSOlivier Deprez } 579*0ca3913dSOlivier Deprez } 580*0ca3913dSOlivier Deprez 581*0ca3913dSOlivier Deprez p = memrchr(dirname, '/', p - dirname); 582*0ca3913dSOlivier Deprez if (p == NULL) { 583*0ca3913dSOlivier Deprez return -1; 584*0ca3913dSOlivier Deprez } 585*0ca3913dSOlivier Deprez 586*0ca3913dSOlivier Deprez dirname[p - dirname + 1] = '\0'; 587*0ca3913dSOlivier Deprez 588*0ca3913dSOlivier Deprez channel = path_to_channel(dirname, O_STAT); 589*0ca3913dSOlivier Deprez if (channel == NULL) { 590*0ca3913dSOlivier Deprez return -1; 591*0ca3913dSOlivier Deprez } 592*0ca3913dSOlivier Deprez 593*0ca3913dSOlivier Deprez r = devtab[channel->index]->stat(channel, path, dir); 594*0ca3913dSOlivier Deprez channel_close(channel); 595*0ca3913dSOlivier Deprez 596*0ca3913dSOlivier Deprez return r; 597*0ca3913dSOlivier Deprez } 598*0ca3913dSOlivier Deprez 599*0ca3913dSOlivier Deprez /******************************************************************************* 600*0ca3913dSOlivier Deprez * This function calls the read function of the driver associated to fd. 601*0ca3913dSOlivier Deprez * It fills buf with at most n bytes. 602*0ca3913dSOlivier Deprez * It returns the number of bytes that were actually read. 603*0ca3913dSOlivier Deprez ******************************************************************************/ 604*0ca3913dSOlivier Deprez int read(int fd, void *buf, int n) 605*0ca3913dSOlivier Deprez { 606*0ca3913dSOlivier Deprez chan_t *channel; 607*0ca3913dSOlivier Deprez 608*0ca3913dSOlivier Deprez if (buf == NULL) { 609*0ca3913dSOlivier Deprez return -1; 610*0ca3913dSOlivier Deprez } 611*0ca3913dSOlivier Deprez 612*0ca3913dSOlivier Deprez channel = fd_to_channel(fd); 613*0ca3913dSOlivier Deprez if (channel == NULL) { 614*0ca3913dSOlivier Deprez return -1; 615*0ca3913dSOlivier Deprez } 616*0ca3913dSOlivier Deprez 617*0ca3913dSOlivier Deprez if (((channel->qid & CHDIR) != 0) && (n < sizeof(dir_t))) { 618*0ca3913dSOlivier Deprez return -1; 619*0ca3913dSOlivier Deprez } 620*0ca3913dSOlivier Deprez 621*0ca3913dSOlivier Deprez return devtab[channel->index]->read(channel, buf, n); 622*0ca3913dSOlivier Deprez } 623*0ca3913dSOlivier Deprez 624*0ca3913dSOlivier Deprez /******************************************************************************* 625*0ca3913dSOlivier Deprez * This function calls the write function of the driver associated to fd. 626*0ca3913dSOlivier Deprez * It writes at most n bytes of buf. 627*0ca3913dSOlivier Deprez * It returns the number of bytes that were actually written. 628*0ca3913dSOlivier Deprez ******************************************************************************/ 629*0ca3913dSOlivier Deprez int write(int fd, void *buf, int n) 630*0ca3913dSOlivier Deprez { 631*0ca3913dSOlivier Deprez chan_t *channel; 632*0ca3913dSOlivier Deprez 633*0ca3913dSOlivier Deprez if (buf == NULL) { 634*0ca3913dSOlivier Deprez return -1; 635*0ca3913dSOlivier Deprez } 636*0ca3913dSOlivier Deprez 637*0ca3913dSOlivier Deprez channel = fd_to_channel(fd); 638*0ca3913dSOlivier Deprez if (channel == NULL) { 639*0ca3913dSOlivier Deprez return -1; 640*0ca3913dSOlivier Deprez } 641*0ca3913dSOlivier Deprez 642*0ca3913dSOlivier Deprez if ((channel->qid & CHDIR) != 0) { 643*0ca3913dSOlivier Deprez return -1; 644*0ca3913dSOlivier Deprez } 645*0ca3913dSOlivier Deprez 646*0ca3913dSOlivier Deprez return devtab[channel->index]->write(channel, buf, n); 647*0ca3913dSOlivier Deprez } 648*0ca3913dSOlivier Deprez 649*0ca3913dSOlivier Deprez /******************************************************************************* 650*0ca3913dSOlivier Deprez * This function calls the seek function of the driver associated to fd. 651*0ca3913dSOlivier Deprez * It applies the offset off according to the strategy whence. 652*0ca3913dSOlivier Deprez ******************************************************************************/ 653*0ca3913dSOlivier Deprez int seek(int fd, long off, int whence) 654*0ca3913dSOlivier Deprez { 655*0ca3913dSOlivier Deprez chan_t *channel; 656*0ca3913dSOlivier Deprez 657*0ca3913dSOlivier Deprez channel = fd_to_channel(fd); 658*0ca3913dSOlivier Deprez if (channel == NULL) { 659*0ca3913dSOlivier Deprez return -1; 660*0ca3913dSOlivier Deprez } 661*0ca3913dSOlivier Deprez 662*0ca3913dSOlivier Deprez if ((channel->qid & CHDIR) != 0) { 663*0ca3913dSOlivier Deprez return -1; 664*0ca3913dSOlivier Deprez } 665*0ca3913dSOlivier Deprez 666*0ca3913dSOlivier Deprez return devtab[channel->index]->seek(channel, off, whence); 667*0ca3913dSOlivier Deprez } 668*0ca3913dSOlivier Deprez 669*0ca3913dSOlivier Deprez /******************************************************************************* 670*0ca3913dSOlivier Deprez * This function is the default error implementation of the driver mount 671*0ca3913dSOlivier Deprez * function. 672*0ca3913dSOlivier Deprez ******************************************************************************/ 673*0ca3913dSOlivier Deprez chan_t *deverrmount(chan_t *channel, const char *spec) 674*0ca3913dSOlivier Deprez { 675*0ca3913dSOlivier Deprez return NULL; 676*0ca3913dSOlivier Deprez } 677*0ca3913dSOlivier Deprez 678*0ca3913dSOlivier Deprez /******************************************************************************* 679*0ca3913dSOlivier Deprez * This function is the default error implementation of the driver write 680*0ca3913dSOlivier Deprez * function. 681*0ca3913dSOlivier Deprez ******************************************************************************/ 682*0ca3913dSOlivier Deprez int deverrwrite(chan_t *channel, void *buf, int n) 683*0ca3913dSOlivier Deprez { 684*0ca3913dSOlivier Deprez return -1; 685*0ca3913dSOlivier Deprez } 686*0ca3913dSOlivier Deprez 687*0ca3913dSOlivier Deprez /******************************************************************************* 688*0ca3913dSOlivier Deprez * This function is the default error implementation of the driver seek 689*0ca3913dSOlivier Deprez * function. 690*0ca3913dSOlivier Deprez ******************************************************************************/ 691*0ca3913dSOlivier Deprez int deverrseek(chan_t *channel, long off, int whence) 692*0ca3913dSOlivier Deprez { 693*0ca3913dSOlivier Deprez return -1; 694*0ca3913dSOlivier Deprez } 695*0ca3913dSOlivier Deprez 696*0ca3913dSOlivier Deprez /******************************************************************************* 697*0ca3913dSOlivier Deprez * This function is the default implementation of the driver seek function. 698*0ca3913dSOlivier Deprez * It applies the offset off according to the strategy whence to the channel c. 699*0ca3913dSOlivier Deprez ******************************************************************************/ 700*0ca3913dSOlivier Deprez int devseek(chan_t *channel, long off, int whence) 701*0ca3913dSOlivier Deprez { 702*0ca3913dSOlivier Deprez switch (whence) { 703*0ca3913dSOlivier Deprez case KSEEK_SET: 704*0ca3913dSOlivier Deprez channel->offset = off; 705*0ca3913dSOlivier Deprez break; 706*0ca3913dSOlivier Deprez case KSEEK_CUR: 707*0ca3913dSOlivier Deprez channel->offset += off; 708*0ca3913dSOlivier Deprez break; 709*0ca3913dSOlivier Deprez case KSEEK_END: 710*0ca3913dSOlivier Deprez /* Not implemented */ 711*0ca3913dSOlivier Deprez return -1; 712*0ca3913dSOlivier Deprez } 713*0ca3913dSOlivier Deprez 714*0ca3913dSOlivier Deprez return 0; 715*0ca3913dSOlivier Deprez } 716*0ca3913dSOlivier Deprez 717*0ca3913dSOlivier Deprez /******************************************************************************* 718*0ca3913dSOlivier Deprez * This function registers the channel associated to the path new as a mount 719*0ca3913dSOlivier Deprez * point for the channel c. 720*0ca3913dSOlivier Deprez ******************************************************************************/ 721*0ca3913dSOlivier Deprez static int add_mount_point(chan_t *channel, const char *new) 722*0ca3913dSOlivier Deprez { 723*0ca3913dSOlivier Deprez int i; 724*0ca3913dSOlivier Deprez chan_t *cn; 725*0ca3913dSOlivier Deprez struct mount_point *mp; 726*0ca3913dSOlivier Deprez 727*0ca3913dSOlivier Deprez if (new == NULL) { 728*0ca3913dSOlivier Deprez goto err0; 729*0ca3913dSOlivier Deprez } 730*0ca3913dSOlivier Deprez 731*0ca3913dSOlivier Deprez cn = path_to_channel(new, O_READ); 732*0ca3913dSOlivier Deprez if (cn == NULL) { 733*0ca3913dSOlivier Deprez goto err0; 734*0ca3913dSOlivier Deprez } 735*0ca3913dSOlivier Deprez 736*0ca3913dSOlivier Deprez if ((cn->qid & CHDIR) == 0) { 737*0ca3913dSOlivier Deprez goto err1; 738*0ca3913dSOlivier Deprez } 739*0ca3913dSOlivier Deprez 740*0ca3913dSOlivier Deprez for (i = NR_MOUNT_POINTS - 1; i >= 0; i--) { 741*0ca3913dSOlivier Deprez mp = &mount_points[i]; 742*0ca3913dSOlivier Deprez if (mp->new == NULL) { 743*0ca3913dSOlivier Deprez break; 744*0ca3913dSOlivier Deprez } 745*0ca3913dSOlivier Deprez } 746*0ca3913dSOlivier Deprez 747*0ca3913dSOlivier Deprez if (i < 0) { 748*0ca3913dSOlivier Deprez goto err1; 749*0ca3913dSOlivier Deprez } 750*0ca3913dSOlivier Deprez 751*0ca3913dSOlivier Deprez mp->new = cn; 752*0ca3913dSOlivier Deprez mp->old = channel; 753*0ca3913dSOlivier Deprez 754*0ca3913dSOlivier Deprez return 0; 755*0ca3913dSOlivier Deprez 756*0ca3913dSOlivier Deprez err1: 757*0ca3913dSOlivier Deprez channel_close(cn); 758*0ca3913dSOlivier Deprez err0: 759*0ca3913dSOlivier Deprez return -1; 760*0ca3913dSOlivier Deprez } 761*0ca3913dSOlivier Deprez 762*0ca3913dSOlivier Deprez /******************************************************************************* 763*0ca3913dSOlivier Deprez * This function registers the path new as a mount point for the path old. 764*0ca3913dSOlivier Deprez ******************************************************************************/ 765*0ca3913dSOlivier Deprez int bind(const char *old, const char *new) 766*0ca3913dSOlivier Deprez { 767*0ca3913dSOlivier Deprez chan_t *channel; 768*0ca3913dSOlivier Deprez 769*0ca3913dSOlivier Deprez channel = path_to_channel(old, O_BIND); 770*0ca3913dSOlivier Deprez if (channel == NULL) { 771*0ca3913dSOlivier Deprez return -1; 772*0ca3913dSOlivier Deprez } 773*0ca3913dSOlivier Deprez 774*0ca3913dSOlivier Deprez if (add_mount_point(channel, new) < 0) { 775*0ca3913dSOlivier Deprez channel_close(channel); 776*0ca3913dSOlivier Deprez return -1; 777*0ca3913dSOlivier Deprez } 778*0ca3913dSOlivier Deprez 779*0ca3913dSOlivier Deprez return 0; 780*0ca3913dSOlivier Deprez } 781*0ca3913dSOlivier Deprez 782*0ca3913dSOlivier Deprez /******************************************************************************* 783*0ca3913dSOlivier Deprez * This function calls the mount function of the driver associated to the path 784*0ca3913dSOlivier Deprez * srv. 785*0ca3913dSOlivier Deprez * It mounts the path srv on the path where. 786*0ca3913dSOlivier Deprez ******************************************************************************/ 787*0ca3913dSOlivier Deprez int mount(const char *srv, const char *where, const char *spec) 788*0ca3913dSOlivier Deprez { 789*0ca3913dSOlivier Deprez chan_t *channel, *mount_point_chan; 790*0ca3913dSOlivier Deprez int ret; 791*0ca3913dSOlivier Deprez 792*0ca3913dSOlivier Deprez channel = path_to_channel(srv, O_RDWR); 793*0ca3913dSOlivier Deprez if (channel == NULL) { 794*0ca3913dSOlivier Deprez goto err0; 795*0ca3913dSOlivier Deprez } 796*0ca3913dSOlivier Deprez 797*0ca3913dSOlivier Deprez mount_point_chan = devtab[channel->index]->mount(channel, spec); 798*0ca3913dSOlivier Deprez if (mount_point_chan == NULL) { 799*0ca3913dSOlivier Deprez goto err1; 800*0ca3913dSOlivier Deprez } 801*0ca3913dSOlivier Deprez 802*0ca3913dSOlivier Deprez ret = add_mount_point(mount_point_chan, where); 803*0ca3913dSOlivier Deprez if (ret < 0) { 804*0ca3913dSOlivier Deprez goto err2; 805*0ca3913dSOlivier Deprez } 806*0ca3913dSOlivier Deprez 807*0ca3913dSOlivier Deprez channel_close(channel); 808*0ca3913dSOlivier Deprez 809*0ca3913dSOlivier Deprez return 0; 810*0ca3913dSOlivier Deprez 811*0ca3913dSOlivier Deprez err2: 812*0ca3913dSOlivier Deprez channel_close(mount_point_chan); 813*0ca3913dSOlivier Deprez err1: 814*0ca3913dSOlivier Deprez channel_close(channel); 815*0ca3913dSOlivier Deprez err0: 816*0ca3913dSOlivier Deprez return -1; 817*0ca3913dSOlivier Deprez } 818*0ca3913dSOlivier Deprez 819*0ca3913dSOlivier Deprez /******************************************************************************* 820*0ca3913dSOlivier Deprez * This function initializes the device environment. 821*0ca3913dSOlivier Deprez * It creates the '/' channel. 822*0ca3913dSOlivier Deprez * It links the device drivers to the physical drivers. 823*0ca3913dSOlivier Deprez ******************************************************************************/ 824*0ca3913dSOlivier Deprez void debugfs_init(void) 825*0ca3913dSOlivier Deprez { 826*0ca3913dSOlivier Deprez chan_t *channel, *cloned_channel; 827*0ca3913dSOlivier Deprez 828*0ca3913dSOlivier Deprez for (channel = fdset; channel < &fdset[NR_CHANS]; channel++) { 829*0ca3913dSOlivier Deprez channel_clear(channel); 830*0ca3913dSOlivier Deprez } 831*0ca3913dSOlivier Deprez 832*0ca3913dSOlivier Deprez channel = devattach('/', 0); 833*0ca3913dSOlivier Deprez if (channel == NULL) { 834*0ca3913dSOlivier Deprez panic(); 835*0ca3913dSOlivier Deprez } 836*0ca3913dSOlivier Deprez 837*0ca3913dSOlivier Deprez cloned_channel = clone(channel, &slash_channel); 838*0ca3913dSOlivier Deprez if (cloned_channel == NULL) { 839*0ca3913dSOlivier Deprez panic(); 840*0ca3913dSOlivier Deprez } 841*0ca3913dSOlivier Deprez 842*0ca3913dSOlivier Deprez channel_close(channel); 843*0ca3913dSOlivier Deprez devlink(); 844*0ca3913dSOlivier Deprez } 845*0ca3913dSOlivier Deprez 846*0ca3913dSOlivier Deprez __dead2 void devpanic(const char *cause) 847*0ca3913dSOlivier Deprez { 848*0ca3913dSOlivier Deprez panic(); 849*0ca3913dSOlivier Deprez } 850