This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / system / explorer / shell / unixfs.cpp
1 /*
2  * Copyright 2003 Martin Fuchs
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20  //
21  // Explorer clone
22  //
23  // unixfs.cpp
24  //
25  // Martin Fuchs, 23.07.2003
26  //
27
28
29 #ifdef __linux__
30
31 #include "../utility/utility.h"
32 #include "../utility/shellclasses.h"
33
34 #include "entries.h"
35 #include "unixfs.h"
36
37  // for UnixDirectory::read_directory()
38 #include <dirent.h>
39 #include <sys/stat.h>
40 #include <time.h>
41
42
43 void UnixDirectory::read_directory()
44 {
45         Entry* first_entry = NULL;
46         Entry* last = NULL;
47         Entry* entry;
48
49         int level = _level + 1;
50
51         LPCTSTR path = (LPCTSTR)_path;
52         DIR* pdir = opendir(path);
53
54         if (pdir) {
55                 struct stat st;
56                 struct dirent* ent;
57                 TCHAR buffer[MAX_PATH], *p;
58
59                 for(p=buffer; *path; )
60                         *p++ = *path++;
61
62                 if (p==buffer || p[-1]!='/')
63                         *p++ = '/';
64
65                 while((ent=readdir(pdir))) {
66                         int statres = stat(buffer, &st);
67
68                         if (!statres && S_ISDIR(st.st_mode))
69                                 entry = new UnixDirectory(this, buffer);
70                         else
71                                 entry = new UnixEntry(this);
72
73                         if (!first_entry)
74                                 first_entry = entry;
75
76                         if (last)
77                                 last->_next = entry;
78
79                         lstrcpy(entry->_data.cFileName, ent->d_name);
80                         entry->_data.dwFileAttributes = ent->d_name[0]=='.'? FILE_ATTRIBUTE_HIDDEN: 0;
81
82                         strcpy(p, ent->d_name);
83
84                         if (!statres) {
85                                 if (S_ISDIR(st.st_mode))
86                                         entry->_data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
87
88                                 entry->_data.nFileSizeLow = st.st_size & 0xFFFFFFFF;
89                                 entry->_data.nFileSizeHigh = st.st_size >> 32;
90
91                                 memset(&entry->_data.ftCreationTime, 0, sizeof(FILETIME));
92                                 time_to_filetime(&st.st_atime, &entry->_data.ftLastAccessTime);
93                                 time_to_filetime(&st.st_mtime, &entry->_data.ftLastWriteTime);
94
95                                 entry->_bhfi.nFileIndexLow = ent->d_ino;
96                                 entry->_bhfi.nFileIndexHigh = 0;
97
98                                 entry->_bhfi.nNumberOfLinks = st.st_nlink;
99
100                                 entry->_bhfi_valid = TRUE;
101                         } else {
102                                 entry->_data.nFileSizeLow = 0;
103                                 entry->_data.nFileSizeHigh = 0;
104                                 entry->_bhfi_valid = FALSE;
105                         }
106
107                         entry->_down = NULL;
108                         entry->_up = this;
109                         entry->_expanded = FALSE;
110                         entry->_scanned = FALSE;
111                         entry->_level = level;
112
113                         last = entry;
114                 }
115
116                 last->_next = NULL;
117
118                 closedir(pdir);
119         }
120
121         _down = first_entry;
122         _scanned = true;
123 }
124
125
126 const void* UnixDirectory::get_next_path_component(const void* p)
127 {
128         LPCTSTR s = (LPCTSTR) p;
129
130         while(*s && *s!=TEXT('/'))
131                 ++s;
132
133         while(*s == TEXT('/'))
134                 ++s;
135
136         if (!*s)
137                 return NULL;
138
139         return s;
140 }
141
142
143 Entry* UnixDirectory::find_entry(const void* p)
144 {
145         LPCTSTR name = (LPCTSTR)p;
146
147         for(Entry*entry=_down; entry; entry=entry->_next) {
148                 LPCTSTR p = name;
149                 LPCTSTR q = entry->_data.cFileName;
150
151                 do {
152                         if (!*p || *p==TEXT('/'))
153                                 return entry;
154                 } while(*p++ == *q++);
155         }
156
157         return NULL;
158 }
159
160
161  // get full path of specified directory entry
162 void UnixEntry::get_path(PTSTR path) const
163 {
164         int level = 0;
165         int len = 0;
166
167         for(const Entry* entry=this; entry; level++) {
168                 LPCTSTR name = entry->_data.cFileName;
169                 int l = 0;
170
171                 for(LPCTSTR s=name; *s && *s!=TEXT('/'); s++)
172                         ++l;
173
174                 if (entry->_up) {
175                         if (l > 0) {
176                                 memmove(path+l+1, path, len*sizeof(TCHAR));
177                                 memcpy(path+1, name, l*sizeof(TCHAR));
178                                 len += l+1;
179
180                                 path[0] = TEXT('/');
181                         }
182
183                         entry = entry->_up;
184                 } else {
185                         memmove(path+l, path, len*sizeof(TCHAR));
186                         memcpy(path, name, l*sizeof(TCHAR));
187                         len += l;
188                         break;
189                 }
190         }
191
192         if (!level)
193                 path[len++] = TEXT('/');
194
195         path[len] = TEXT('\0');
196 }
197
198 #endif // __linux__