3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / kernel / file_systems / ntfs / ntfsdir.c
blob371eaf18504310fa32f6a87888c8b2f3692ac7ea
1 /* ntfsdir.c - directory functions
3 * Copyright (c) 2006 Troeglazov Gerasim (3dEyes**)
5 * This program/include file is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program/include file is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program (in the main directory of the Linux-NTFS
17 * distribution in the file COPYING); if not, write to the Free Software
18 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "ntfsdir.h"
24 #include <ctype.h>
25 #include <dirent.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
36 static int
37 _ntfs_dirent_filler(void *_dirent, const ntfschar *name,
38 const int name_len, const int name_type, const s64 pos, const MFT_REF mref,
39 const unsigned dt_type)
41 char *filename = NULL;
42 dircookie *cookie = (dircookie*)_dirent;
44 if (name_type == FILE_NAME_DOS)
45 return 0;
47 if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user
48 || cookie->show_sys_files) {
49 int len = ntfs_ucstombs(name, name_len, &filename, 0);
50 if (len >= 0 && filename != NULL) {
51 cache_entry* new_entry =
52 (cache_entry*)ntfs_calloc(sizeof(cache_entry));
53 if (new_entry == NULL) {
54 free(filename);
55 return -1;
58 new_entry->ent =
59 (struct dirent*)ntfs_calloc(sizeof(struct dirent) + len);
60 new_entry->ent->d_dev = cookie->dev_id;
61 new_entry->ent->d_ino = MREF(mref);
62 memcpy(new_entry->ent->d_name,filename, len + 1);
63 new_entry->ent->d_reclen = sizeof(struct dirent) + len;
65 if (cookie->cache_root == NULL || cookie->entry == NULL) {
66 cookie->cache_root = new_entry;
67 cookie->entry = cookie->cache_root;
68 cookie->entry->next = NULL;
69 } else {
70 cookie->entry->next = (void*)new_entry;
71 cookie->entry = cookie->entry->next;
72 cookie->entry->next = NULL;
75 free(filename);
76 return 0;
78 return -1;
80 return 0;
84 status_t
85 fs_free_dircookie(fs_volume *_vol, fs_vnode *vnode, void *_cookie)
87 nspace *ns = (nspace*)_vol->private_volume;
88 dircookie *cookie = (dircookie*)_cookie;
90 LOCK_VOL(ns);
91 TRACE("fs_free_dircookie - ENTER\n");
93 if (cookie != NULL) {
94 cache_entry *entry = cookie->cache_root;
95 while (entry != NULL) {
96 cache_entry *next = entry->next;
97 free(entry->ent);
98 free(entry);
99 entry = next;
101 free(cookie);
104 TRACE("fs_free_dircookie - EXIT\n");
105 UNLOCK_VOL(ns);
107 return B_NO_ERROR;
111 status_t
112 fs_opendir(fs_volume *_vol, fs_vnode *_node, void** _cookie)
114 nspace *ns = (nspace*)_vol->private_volume;
115 vnode *node = (vnode*)_node->private_node;
116 dircookie *cookie = NULL;
117 ntfs_inode *ni = NULL;
118 int result = B_NO_ERROR;
120 LOCK_VOL(ns);
121 TRACE("fs_opendir - ENTER\n");
123 ni = ntfs_inode_open(ns->ntvol, node->vnid);
124 if (ni == NULL) {
125 result = ENOENT;
126 goto exit;
129 if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
130 result = EMFILE;
131 goto exit;
134 cookie = (dircookie*)ntfs_calloc(sizeof(dircookie));
135 if (cookie != NULL) {
136 cookie->pos = 0;
137 cookie->dev_id = ns->id;
138 cookie->show_sys_files = ns->show_sys_files;
139 cookie->cache_root = NULL;
140 cookie->entry = cookie->cache_root;
141 *_cookie = (void*)cookie;
142 } else
143 result = ENOMEM;
145 exit:
146 if (ni != NULL)
147 ntfs_inode_close(ni);
149 TRACE("fs_opendir - EXIT\n");
150 UNLOCK_VOL(ns);
152 return result;
156 status_t
157 fs_closedir(fs_volume *_vol, fs_vnode *_node, void *cookie)
159 return B_NO_ERROR;
163 status_t
164 fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf,
165 size_t bufsize, uint32 *num)
167 nspace *ns = (nspace*)_vol->private_volume;
168 vnode *node = (vnode*)_node->private_node;
169 dircookie *cookie = (dircookie*)_cookie;
170 ntfs_inode *ni = NULL;
172 uint32 nameLength = bufsize - sizeof(struct dirent), realLen;
173 int result = B_NO_ERROR;
175 LOCK_VOL(ns);
176 TRACE("fs_readdir - ENTER (sizeof(buf)=%d, bufsize=%d, num=%d\n",
177 sizeof(buf), bufsize, *num);
179 if (!ns || !node || !cookie || !num || bufsize < sizeof(*buf)) {
180 result = EINVAL;
181 goto exit;
184 ni = ntfs_inode_open(ns->ntvol, node->vnid);
185 if (ni == NULL) {
186 TRACE("fs_readdir - dir not opened\n");
187 result = ENOENT;
188 goto exit;
191 if (cookie->cache_root == NULL) {
192 cookie->entry = NULL;
193 result = ntfs_readdir(ni, &cookie->pos, cookie,
194 (ntfs_filldir_t)_ntfs_dirent_filler);
195 cookie->entry = cookie->cache_root;
196 if (result) {
197 result = ENOENT;
198 goto exit;
202 if (cookie->entry == NULL) {
203 result = ENOENT;
204 goto exit;
207 if (cookie->entry->ent == NULL) {
208 result = ENOENT;
209 goto exit;
212 realLen = nameLength > 255 ? 255 : nameLength;
214 buf->d_dev = ns->id;
215 buf->d_ino = cookie->entry->ent->d_ino;
216 strlcpy(buf->d_name, cookie->entry->ent->d_name, realLen + 1);
217 buf->d_reclen = sizeof(struct dirent) + realLen;
219 cookie->entry = (cache_entry*)cookie->entry->next;
221 TRACE("fs_readdir - FILE: [%s]\n",buf->d_name);
223 exit:
224 if (ni != NULL)
225 ntfs_inode_close(ni);
227 if (result == B_NO_ERROR)
228 *num = 1;
229 else
230 *num = 0;
232 if (result == ENOENT)
233 result = B_NO_ERROR;
235 TRACE("fs_readdir - EXIT num=%d result (%s)\n",*num, strerror(result));
236 UNLOCK_VOL(ns);
238 return result;
242 status_t
243 fs_rewinddir(fs_volume *_vol, fs_vnode *_node, void *_cookie)
245 nspace *ns = (nspace*)_vol->private_volume;
246 dircookie *cookie = (dircookie*)_cookie;
247 int result = EINVAL;
249 LOCK_VOL(ns);
250 TRACE("fs_rewinddir - ENTER\n");
252 if (cookie != NULL) {
253 cache_entry *entry = cookie->cache_root;
254 while (entry != NULL) {
255 cache_entry *next = entry->next;
256 free(entry->ent);
257 free(entry);
258 entry = next;
260 cookie->pos = 0;
261 cookie->dev_id = ns->id;
262 cookie->show_sys_files = ns->show_sys_files;
263 cookie->cache_root = NULL;
264 cookie->entry = cookie->cache_root;
265 result = B_NO_ERROR;
268 TRACE("fs_rewinddir - EXIT, result is %s\n", strerror(result));
269 UNLOCK_VOL(ns);
271 return result;