• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/dirent/fs_seekdir.c
3  *
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.  The
7  * ASF licenses this file to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance with the
9  * License.  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, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  *
19  ****************************************************************************/
20 
21 /****************************************************************************
22  * Included Files
23  ****************************************************************************/
24 
25 #include "vfs_config.h"
26 #include "sys/types.h"
27 #include "dirent.h"
28 #include "errno.h"
29 #include "fs/dirent_fs.h"
30 #include "vnode.h"
31 
32 /****************************************************************************
33  * Private Functions
34  ****************************************************************************/
35 /****************************************************************************
36  * Name: seekmountptdir
37  ****************************************************************************/
38 
seekmountptdir(struct fs_dirent_s * idir,off_t offset)39 static inline void seekmountptdir(struct fs_dirent_s *idir, off_t offset)
40 {
41   struct Vnode *vnode;
42   off_t pos;
43 
44   /* Determine a starting point for the seek.  If the seek
45    * is "forward" from the current position, then we will
46    * start at the current poisition.  Otherwise, we will
47    * "rewind" to the root dir.
48    */
49 
50   vnode = idir->fd_root;
51   if (offset < idir->fd_position)
52     {
53       if (vnode->vop != NULL && vnode->vop->Rewinddir != NULL)
54         {
55           /* Perform the rewinddir() operation */
56 
57           vnode->vop->Rewinddir(vnode, idir);
58           pos = 0;
59         }
60       else
61         {
62           /* We can't do the seek and there is no way to return
63            * an error indication.
64            */
65 
66           return;
67         }
68     }
69   else
70     {
71       pos = idir->fd_position;
72     }
73 
74   /* This is a brute force approach... we will just read
75    * directory entries until we are at the desired position.
76    */
77 
78   idir->read_cnt = 1;
79 
80   while (pos < offset)
81     {
82       if (!vnode->vop || !vnode->vop->Readdir ||
83            vnode->vop->Readdir(vnode, idir) <= 0)
84         {
85           /* We can't read the next entry and there is no way to return
86            * an error indication.
87            */
88 
89            return;
90         }
91 
92       /* Increment the position on each successful read */
93 
94       pos++;
95     }
96 
97   /* If we get here the directory position has been successfully set */
98   idir->fd_position = pos;
99 }
100 
101 /****************************************************************************
102  * Public Functions
103  ****************************************************************************/
104 
105 /****************************************************************************
106  * Name: seekdir
107  *
108  * Description:
109  *   The seekdir() function sets the location in the directory stream from
110  *   which the next readdir() call will start.  seekdir() should be used with
111  *   an offset returned by telldir().
112  *
113  * Input Parameters:
114  *   dirp -- An instance of type DIR created by a previous
115  *     call to opendir();
116  *   offset -- offset to seek to
117  *
118  * Returned Value:
119  *   None
120  *
121  ****************************************************************************/
122 
seekdir(DIR * dirp,long offset)123 void seekdir(DIR *dirp, long offset)
124 {
125   struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
126 
127   if (!idir || !idir->fd_root || idir->fd_status != DIRENT_MAGIC)
128     {
129       set_errno(EBADF);
130       return;
131     }
132 
133   if (offset < 0)
134     {
135       set_errno(EINVAL);
136       return;
137     }
138 
139   seekmountptdir(idir, offset);
140 }
141