1/****************************************************************************
2 * fs/driver/fs_findblockdriver.c
3 *
4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
5 * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/)
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20
21/****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25#include "vfs_config.h"
26
27#include "sys/types.h"
28#include "sys/mount.h"
29#include "errno.h"
30#include "fs/driver.h"
31#include "string.h"
32
33/****************************************************************************
34 * Public Functions
35 ****************************************************************************/
36
37/****************************************************************************
38 * Name: find_blockdriver
39 *
40 * Description:
41 *   Return the inode of the block driver specified by 'pathname'
42 *
43 * Input Parameters:
44 *   pathname   - The full path to the block driver to be located
45 *   mountflags - If MS_RDONLY is not set, then driver must support write
46 *                operations (see include/sys/mount.h)
47 *   ppinode    - Address of the location to return the inode reference
48 *
49 * Returned Value:
50 *   Returns zero on success or a negated errno on failure:
51 *
52 *   ENOENT  - No block driver of this name is registered
53 *   ENOTBLK - The inode associated with the pathname is not a block driver
54 *   EACCESS - The MS_RDONLY option was not set but this driver does not
55 *             support write access
56 *
57 ****************************************************************************/
58int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp)
59{
60  int ret;
61  struct Vnode *vp = NULL;
62
63  /* Sanity checks */
64
65  /* Find the vnode registered with this pathname */
66  VnodeHold();
67  ret = VnodeLookup(pathname, &vp, V_DUMMY);
68  if (ret < 0)
69    {
70      ret = -EACCES;
71      goto errout;
72    }
73
74  /* Verify that the vnode is a block driver. */
75  if (vp->type != VNODE_TYPE_BLK)
76    {
77      PRINT_DEBUG("%s is not a block driver\n", pathname);
78      ret = -ENOTBLK;
79      goto errout;
80    }
81
82  /* Make sure that the vnode supports the requested access */
83
84  struct block_operations *i_bops = (struct block_operations *)((struct drv_data *)vp->data)->ops;
85
86  if (i_bops == NULL || i_bops->read == NULL || (i_bops->write == NULL && (mountflags & MS_RDONLY) == 0))
87    {
88      PRINT_DEBUG("%s does not support requested access\n", pathname);
89      ret = -EACCES;
90      goto errout;
91    }
92
93  *vpp = vp;
94  VnodeDrop();
95  return OK;
96
97errout:
98  VnodeDrop();
99  return ret;
100}
101