VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/fs.cpp@ 34002

最後變更 在這個檔案從34002是 34002,由 vboxsync 提交於 14 年 前

iprt: Working on tar vfs.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 13.7 KB
 
1/* $Id: fs.cpp 34002 2010-11-11 17:16:37Z vboxsync $ */
2/** @file
3 * IPRT - File System.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#ifndef RT_OS_WINDOWS
32# define RTTIME_INCL_TIMESPEC
33# include <sys/time.h>
34# include <sys/param.h>
35# ifndef DEV_BSIZE
36# include <sys/stat.h>
37# define DEV_BSIZE S_BLKSIZE /** @todo bird: add DEV_BSIZE to sys/param.h on OS/2. */
38# endif
39# include <grp.h>
40# include <pwd.h>
41#endif
42
43#include <iprt/fs.h>
44#include "internal/iprt.h"
45
46#include <iprt/asm.h>
47#include <iprt/assert.h>
48#include <iprt/ctype.h>
49#include <iprt/path.h>
50#include <iprt/string.h>
51#include <iprt/time.h>
52#include "internal/fs.h"
53
54
55/**
56 * Converts dos-style attributes to Unix attributes.
57 *
58 * @returns
59 * @param fMode The mode mask containing dos-style attributes only.
60 * @param pszName The filename which this applies to (exe check).
61 * @param cbName The length of that filename. (optional, set 0)
62 */
63RTFMODE rtFsModeFromDos(RTFMODE fMode, const char *pszName, size_t cbName)
64{
65 fMode &= ~((1 << RTFS_DOS_SHIFT) - 1);
66
67 /* everything is readable. */
68 fMode |= RTFS_UNIX_IRUSR | RTFS_UNIX_IRGRP | RTFS_UNIX_IROTH;
69 if (fMode & RTFS_DOS_DIRECTORY)
70 /* directories are executable. */
71 fMode |= RTFS_TYPE_DIRECTORY | RTFS_UNIX_IXUSR | RTFS_UNIX_IXGRP | RTFS_UNIX_IXOTH;
72 else
73 {
74 fMode |= RTFS_TYPE_FILE;
75 if (!cbName && pszName)
76 cbName = strlen(pszName);
77 if (cbName >= 4 && pszName[cbName - 4] == '.')
78 {
79 /* check for executable extension. */
80 const char *pszExt = &pszName[cbName - 3];
81 char szExt[4];
82 szExt[0] = RT_C_TO_LOWER(pszExt[0]);
83 szExt[1] = RT_C_TO_LOWER(pszExt[1]);
84 szExt[2] = RT_C_TO_LOWER(pszExt[2]);
85 szExt[3] = '\0';
86 if ( !memcmp(szExt, "exe", 4)
87 || !memcmp(szExt, "bat", 4)
88 || !memcmp(szExt, "com", 4)
89 || !memcmp(szExt, "cmd", 4)
90 || !memcmp(szExt, "btm", 4)
91 )
92 fMode |= RTFS_UNIX_IXUSR | RTFS_UNIX_IXGRP | RTFS_UNIX_IXOTH;
93 }
94 }
95
96 /* Is it really a symbolic link? */
97 if (fMode & RTFS_DOS_NT_REPARSE_POINT)
98 fMode = (fMode & ~RTFS_TYPE_MASK) | RTFS_TYPE_SYMLINK;
99
100 /* writable? */
101 if (!(fMode & RTFS_DOS_READONLY))
102 fMode |= RTFS_UNIX_IWUSR | RTFS_UNIX_IWGRP | RTFS_UNIX_IWOTH;
103 return fMode;
104}
105
106
107/**
108 * Converts Unix attributes to Dos-style attributes.
109 *
110 * @returns File mode mask.
111 * @param fMode The mode mask containing dos-style attributes only.
112 * @param pszName The filename which this applies to (hidden check).
113 * @param cbName The length of that filename. (optional, set 0)
114 */
115RTFMODE rtFsModeFromUnix(RTFMODE fMode, const char *pszName, size_t cbName)
116{
117 fMode &= RTFS_UNIX_MASK;
118
119 if (!(fMode & (RTFS_UNIX_IWUSR | RTFS_UNIX_IWGRP | RTFS_UNIX_IWOTH)))
120 fMode |= RTFS_DOS_READONLY;
121 if (RTFS_IS_DIRECTORY(fMode))
122 fMode |= RTFS_DOS_DIRECTORY;
123 if (!(fMode & RTFS_DOS_MASK))
124 fMode |= RTFS_DOS_NT_NORMAL;
125 if (!(fMode & RTFS_DOS_HIDDEN) && pszName)
126 {
127 pszName = RTPathFilename(pszName);
128 if (pszName && *pszName == '.')
129 fMode |= RTFS_DOS_HIDDEN;
130 }
131 return fMode;
132}
133
134
135/**
136 * Normalizes the give mode mask.
137 *
138 * It will create the missing unix or dos mask from the other (one
139 * of them is required by all APIs), and guess the file type if that's
140 * missing.
141 *
142 * @returns Normalized file mode.
143 * @param fMode The mode mask that may contain a partial/incomplete mask.
144 * @param pszName The filename which this applies to (exe check).
145 * @param cbName The length of that filename. (optional, set 0)
146 */
147RTFMODE rtFsModeNormalize(RTFMODE fMode, const char *pszName, size_t cbName)
148{
149 if (!(fMode & RTFS_UNIX_MASK))
150 fMode = rtFsModeFromDos(fMode, pszName, cbName);
151 else if (!(fMode & RTFS_DOS_MASK))
152 fMode = rtFsModeFromUnix(fMode, pszName, cbName);
153 else if (!(fMode & RTFS_TYPE_MASK))
154 fMode |= fMode & RTFS_DOS_DIRECTORY ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE;
155 else if (RTFS_IS_DIRECTORY(fMode))
156 fMode |= RTFS_DOS_DIRECTORY;
157 return fMode;
158}
159
160
161/**
162 * Checks if the file mode is valid or not.
163 *
164 * @return true if valid.
165 * @return false if invalid, done bitching.
166 * @param fMode The file mode.
167 */
168bool rtFsModeIsValid(RTFMODE fMode)
169{
170 AssertMsgReturn( (!RTFS_IS_DIRECTORY(fMode) && !(fMode & RTFS_DOS_DIRECTORY))
171 || (RTFS_IS_DIRECTORY(fMode) && (fMode & RTFS_DOS_DIRECTORY)),
172 ("%RTfmode\n", fMode), false);
173 AssertMsgReturn(RTFS_TYPE_MASK & fMode,
174 ("%RTfmode\n", fMode), false);
175 /** @todo more checks! */
176 return true;
177}
178
179
180/**
181 * Checks if the file mode is valid as a permission mask or not.
182 *
183 * @return true if valid.
184 * @return false if invalid, done bitching.
185 * @param fMode The file mode.
186 */
187bool rtFsModeIsValidPermissions(RTFMODE fMode)
188{
189 AssertMsgReturn( (!RTFS_IS_DIRECTORY(fMode) && !(fMode & RTFS_DOS_DIRECTORY))
190 || (RTFS_IS_DIRECTORY(fMode) && (fMode & RTFS_DOS_DIRECTORY)),
191 ("%RTfmode\n", fMode), false);
192 /** @todo more checks! */
193 return true;
194}
195
196#ifndef RT_OS_WINDOWS
197
198/**
199 * Internal worker function which setups RTFSOBJINFO based on a UNIX stat struct.
200 *
201 * @param pObjInfo The file system object info structure to setup.
202 * @param pStat The stat structure to use.
203 * @param pszName The filename which this applies to (exe/hidden check).
204 * @param cbName The length of that filename. (optional, set 0)
205 */
206void rtFsConvertStatToObjInfo(PRTFSOBJINFO pObjInfo, const struct stat *pStat, const char *pszName, unsigned cbName)
207{
208 pObjInfo->cbObject = pStat->st_size;
209 pObjInfo->cbAllocated = pStat->st_blocks * DEV_BSIZE;
210
211#ifdef HAVE_STAT_NSEC
212 RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->AccessTime, pStat->st_atime), pStat->st_atimensec);
213 RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, pStat->st_mtime), pStat->st_mtimensec);
214 RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, pStat->st_ctime), pStat->st_ctimensec);
215#ifdef HAVE_STAT_BIRTHTIME
216 RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->BirthTime, pStat->st_birthtime), pStat->st_birthtimensec);
217#endif
218
219#elif defined(HAVE_STAT_TIMESPEC_BRIEF)
220 RTTimeSpecSetTimespec(&pObjInfo->AccessTime, &pStat->st_atim);
221 RTTimeSpecSetTimespec(&pObjInfo->ModificationTime, &pStat->st_mtim);
222 RTTimeSpecSetTimespec(&pObjInfo->ChangeTime, &pStat->st_ctim);
223# ifdef HAVE_STAT_BIRTHTIME
224 RTTimeSpecSetTimespec(&pObjInfo->BirthTime, &pStat->st_birthtim);
225# endif
226
227#elif defined(HAVE_STAT_TIMESPEC)
228 RTTimeSpecSetTimespec(&pObjInfo->AccessTime, pStat->st_atimespec);
229 RTTimeSpecSetTimespec(&pObjInfo->ModificationTime, pStat->st_mtimespec);
230 RTTimeSpecSetTimespec(&pObjInfo->ChangeTime, pStat->st_ctimespec);
231# ifdef HAVE_STAT_BIRTHTIME
232 RTTimeSpecSetTimespec(&pObjInfo->BirthTime, pStat->st_birthtimespec);
233# endif
234
235#else /* just the normal stuff */
236 RTTimeSpecSetSeconds(&pObjInfo->AccessTime, pStat->st_atime);
237 RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, pStat->st_mtime);
238 RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, pStat->st_ctime);
239# ifdef HAVE_STAT_BIRTHTIME
240 RTTimeSpecSetSeconds(&pObjInfo->BirthTime, pStat->st_birthtime);
241# endif
242#endif
243#ifndef HAVE_STAT_BIRTHTIME
244 pObjInfo->BirthTime = pObjInfo->ChangeTime;
245#endif
246
247
248 /* the file mode */
249 RTFMODE fMode = pStat->st_mode & RTFS_UNIX_MASK;
250 Assert(RTFS_UNIX_ISUID == S_ISUID);
251 Assert(RTFS_UNIX_ISGID == S_ISGID);
252#ifdef S_ISTXT
253 Assert(RTFS_UNIX_ISTXT == S_ISTXT);
254#elif defined(S_ISVTX)
255 Assert(RTFS_UNIX_ISTXT == S_ISVTX);
256#else
257#error "S_ISVTX / S_ISTXT isn't defined"
258#endif
259 Assert(RTFS_UNIX_IRWXU == S_IRWXU);
260 Assert(RTFS_UNIX_IRUSR == S_IRUSR);
261 Assert(RTFS_UNIX_IWUSR == S_IWUSR);
262 Assert(RTFS_UNIX_IXUSR == S_IXUSR);
263 Assert(RTFS_UNIX_IRWXG == S_IRWXG);
264 Assert(RTFS_UNIX_IRGRP == S_IRGRP);
265 Assert(RTFS_UNIX_IWGRP == S_IWGRP);
266 Assert(RTFS_UNIX_IXGRP == S_IXGRP);
267 Assert(RTFS_UNIX_IRWXO == S_IRWXO);
268 Assert(RTFS_UNIX_IROTH == S_IROTH);
269 Assert(RTFS_UNIX_IWOTH == S_IWOTH);
270 Assert(RTFS_UNIX_IXOTH == S_IXOTH);
271 Assert(RTFS_TYPE_FIFO == S_IFIFO);
272 Assert(RTFS_TYPE_DEV_CHAR == S_IFCHR);
273 Assert(RTFS_TYPE_DIRECTORY == S_IFDIR);
274 Assert(RTFS_TYPE_DEV_BLOCK == S_IFBLK);
275 Assert(RTFS_TYPE_FILE == S_IFREG);
276 Assert(RTFS_TYPE_SYMLINK == S_IFLNK);
277 Assert(RTFS_TYPE_SOCKET == S_IFSOCK);
278#ifdef S_IFWHT
279 Assert(RTFS_TYPE_WHITEOUT == S_IFWHT);
280#endif
281 Assert(RTFS_TYPE_MASK == S_IFMT);
282
283 pObjInfo->Attr.fMode = rtFsModeFromUnix(fMode, pszName, cbName);
284
285 /* additional unix attribs */
286 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
287 pObjInfo->Attr.u.Unix.uid = pStat->st_uid;
288 pObjInfo->Attr.u.Unix.gid = pStat->st_gid;
289 pObjInfo->Attr.u.Unix.cHardlinks = pStat->st_nlink;
290 pObjInfo->Attr.u.Unix.INodeIdDevice = pStat->st_dev;
291 pObjInfo->Attr.u.Unix.INodeId = pStat->st_ino;
292#ifdef HAVE_STAT_FLAGS
293 pObjInfo->Attr.u.Unix.fFlags = pStat->st_flags;
294#else
295 pObjInfo->Attr.u.Unix.fFlags = 0;
296#endif
297#ifdef HAVE_STAT_GEN
298 pObjInfo->Attr.u.Unix.GenerationId = pStat->st_gen;
299#else
300 pObjInfo->Attr.u.Unix.GenerationId = 0;
301#endif
302 pObjInfo->Attr.u.Unix.Device = pStat->st_rdev;
303}
304
305
306/**
307 * Set user-owner additional attributes.
308 *
309 * @param pObjInfo The object info to fill add attrs for.
310 * @param uid The user id.
311 */
312void rtFsObjInfoAttrSetUnixOwner(PRTFSOBJINFO pObjInfo, RTUID uid)
313{
314 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
315 pObjInfo->Attr.u.UnixOwner.uid = uid;
316 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
317
318 char achBuf[_4K];
319 struct passwd Pwd;
320 struct passwd *pPwd;
321 int rc = getpwuid_r(uid, &Pwd, achBuf, sizeof(achBuf), &pPwd);
322 if (!rc && pPwd)
323 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), pPwd->pw_name);
324}
325
326
327/**
328 * Set user-group additional attributes.
329 *
330 * @param pObjInfo The object info to fill add attrs for.
331 * @param gid The group id.
332 */
333void rtFsObjInfoAttrSetUnixGroup(PRTFSOBJINFO pObjInfo, RTUID gid)
334{
335 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
336 pObjInfo->Attr.u.UnixGroup.gid = gid;
337 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
338
339 char achBuf[_4K];
340 struct group Grp;
341 struct group *pGrp;
342
343 int rc = getgrgid_r(gid, &Grp, achBuf, sizeof(achBuf), &pGrp);
344 if (!rc && pGrp)
345 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), pGrp->gr_name);
346}
347
348#endif /* !RT_OS_WINDOWS */
349
350
351RTDECL(const char *) RTFsTypeName(RTFSTYPE enmType)
352{
353 switch (enmType)
354 {
355 case RTFSTYPE_UNKNOWN: return "unknown";
356 case RTFSTYPE_UDF: return "udf";
357 case RTFSTYPE_ISO9660: return "iso9660";
358 case RTFSTYPE_FUSE: return "fuse";
359 case RTFSTYPE_VBOXSHF: return "vboxshf";
360
361 case RTFSTYPE_EXT: return "ext";
362 case RTFSTYPE_EXT2: return "ext2";
363 case RTFSTYPE_EXT3: return "ext3";
364 case RTFSTYPE_EXT4: return "ext4";
365 case RTFSTYPE_XFS: return "xfs";
366 case RTFSTYPE_CIFS: return "cifs";
367 case RTFSTYPE_SMBFS: return "smbfs";
368 case RTFSTYPE_TMPFS: return "tmpfs";
369 case RTFSTYPE_SYSFS: return "sysfs";
370 case RTFSTYPE_PROC: return "proc";
371
372 case RTFSTYPE_NTFS: return "ntfs";
373 case RTFSTYPE_FAT: return "fat";
374
375 case RTFSTYPE_ZFS: return "zfs";
376 case RTFSTYPE_UFS: return "ufs";
377 case RTFSTYPE_NFS: return "nfs";
378
379 case RTFSTYPE_HFS: return "hfs";
380 case RTFSTYPE_AUTOFS: return "autofs";
381 case RTFSTYPE_DEVFS: return "devfs";
382
383 case RTFSTYPE_HPFS: return "hpfs";
384 case RTFSTYPE_JFS: return "jfs";
385
386 case RTFSTYPE_END: return "end";
387 case RTFSTYPE_32BIT_HACK: break;
388 }
389
390 /* Don't put this in as 'default:', we wish GCC to warn about missing cases. */
391 static char s_asz[4][64];
392 static uint32_t volatile s_i = 0;
393 uint32_t i = ASMAtomicIncU32(&s_i) % RT_ELEMENTS(s_asz);
394 RTStrPrintf(s_asz[i], sizeof(s_asz[i]), "type=%d", enmType);
395 return s_asz[i];
396}
397
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette