1 /* 2 * Copyright 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 20 // 21 // Explorer clone 22 // 23 // unixfs.cpp 24 // 25 // Martin Fuchs, 23.07.2003 26 // 27 28 29 #ifdef __WINE__ 30 31 #include <precomp.h> 32 33 //#include "unixfs.h" 34 35 // for UnixDirectory::read_directory() 36 #include <dirent.h> 37 #include <sys/stat.h> 38 #include <time.h> 39 40 41 void UnixDirectory::read_directory() 42 { 43 Entry* first_entry = NULL; 44 Entry* last = NULL; 45 Entry* entry; 46 47 int level = _level + 1; 48 49 LPCTSTR path = (LPCTSTR)_path; 50 DIR* pdir = opendir(path); 51 52 if (pdir) { 53 struct stat st; 54 struct dirent* ent; 55 TCHAR buffer[MAX_PATH], *p; 56 57 for(p=buffer; *path; ) 58 *p++ = *path++; 59 60 if (p==buffer || p[-1]!='/') 61 *p++ = '/'; 62 63 while((ent=readdir(pdir))) { 64 int statres = stat(buffer, &st); 65 66 if (!statres && S_ISDIR(st.st_mode)) 67 entry = new UnixDirectory(this, buffer); 68 else 69 entry = new UnixEntry(this); 70 71 if (!first_entry) 72 first_entry = entry; 73 74 if (last) 75 last->_next = entry; 76 77 lstrcpy(entry->_data.cFileName, ent->d_name); 78 entry->_data.dwFileAttributes = ent->d_name[0]=='.'? FILE_ATTRIBUTE_HIDDEN: 0; 79 80 strcpy(p, ent->d_name); 81 82 if (!statres) { 83 if (S_ISDIR(st.st_mode)) 84 entry->_data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 85 86 entry->_data.nFileSizeLow = st.st_size & 0xFFFFFFFF; 87 entry->_data.nFileSizeHigh = st.st_size >> 32; 88 89 memset(&entry->_data.ftCreationTime, 0, sizeof(FILETIME)); 90 time_to_filetime(&st.st_atime, &entry->_data.ftLastAccessTime); 91 time_to_filetime(&st.st_mtime, &entry->_data.ftLastWriteTime); 92 93 entry->_bhfi.nFileIndexLow = ent->d_ino; 94 entry->_bhfi.nFileIndexHigh = 0; 95 96 entry->_bhfi.nNumberOfLinks = st.st_nlink; 97 98 entry->_bhfi_valid = TRUE; 99 } else { 100 entry->_data.nFileSizeLow = 0; 101 entry->_data.nFileSizeHigh = 0; 102 entry->_bhfi_valid = FALSE; 103 } 104 105 entry->_up = this; 106 entry->_expanded = FALSE; 107 entry->_scanned = FALSE; 108 entry->_level = level; 109 110 last = entry; 111 } 112 113 last->_next = NULL; 114 115 closedir(pdir); 116 } 117 118 _down = first_entry; 119 _scanned = true; 120 } 121 122 123 const void* UnixDirectory::get_next_path_component(const void* p) 124 { 125 LPCTSTR s = (LPCTSTR) p; 126 127 while(*s && *s!=TEXT('/')) 128 ++s; 129 130 while(*s == TEXT('/')) 131 ++s; 132 133 if (!*s) 134 return NULL; 135 136 return s; 137 } 138 139 140 Entry* UnixDirectory::find_entry(const void* p) 141 { 142 LPCTSTR name = (LPCTSTR)p; 143 144 for(Entry*entry=_down; entry; entry=entry->_next) { 145 LPCTSTR p = name; 146 LPCTSTR q = entry->_data.cFileName; 147 148 do { 149 if (!*p || *p==TEXT('/')) 150 return entry; 151 } while(*p++ == *q++); 152 } 153 154 return NULL; 155 } 156 157 158 // get full path of specified directory entry 159 bool UnixEntry::get_path(PTSTR path, size_t path_count) const 160 { 161 int level = 0; 162 size_t len = 0; 163 164 if (!path || path_count==0) 165 return false; 166 167 if ( path_count > 1 ) 168 { 169 for(const Entry* entry=this; entry; level++) { 170 LPCTSTR name = entry->_data.cFileName; 171 size_t l = 0; 172 173 for(LPCTSTR s=name; *s && *s!=TEXT('/'); s++) 174 ++l; 175 176 if (entry->_up) { 177 if (l > 0) { 178 if ( len+l+1 >= path_count ) 179 { 180 /* compare to 2 here because of terminator plus the '\\' we prepend */ 181 if ( l + 2 > path_count ) 182 len = 0; 183 else 184 len = path_count - l - 2; 185 } 186 memmove(path+l+1, path, len*sizeof(TCHAR)); 187 /* compare to 2 here because of terminator plus the '\\' we prepend */ 188 if ( l+2 >= path_count ) 189 l = path_count - 2; 190 memcpy(path+1, name, l*sizeof(TCHAR)); 191 len += l+1; 192 193 path[0] = TEXT('/'); 194 } 195 196 entry = entry->_up; 197 } else { 198 if ( len+l >= path_count ) 199 { 200 if ( l + 1 > path_count ) 201 len = 0; 202 else 203 len = path_count - l - 1; 204 } 205 memmove(path+l, path, len*sizeof(TCHAR)); 206 if ( l+1 >= path_count ) 207 l = path_count - 1; 208 memcpy(path, name, l*sizeof(TCHAR)); 209 len += l; 210 break; 211 } 212 } 213 214 if ( !level && (len+1 < path_count) ) 215 path[len++] = TEXT('/'); 216 } 217 218 path[len] = TEXT('\0'); 219 220 return true; 221 } 222 223 #endif // __WINE__ 224