dir-posix.cpp revision 078be063a5450fff88881d9e194befe904d4e4e4
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * IPRT - Directory manipulation, POSIX.
af84459fbf938e508fd10b01cb8d699c79083813takashi * Copyright (C) 2006-2010 Oracle Corporation
af84459fbf938e508fd10b01cb8d699c79083813takashi * This file is part of VirtualBox Open Source Edition (OSE), as
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * available from http://www.virtualbox.org. This file is free software;
af84459fbf938e508fd10b01cb8d699c79083813takashi * you can redistribute it and/or modify it under the terms of the GNU
af84459fbf938e508fd10b01cb8d699c79083813takashi * General Public License (GPL) as published by the Free Software
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * Foundation, in version 2 as it comes in the "COPYING" file of the
2e545ce2450a9953665f701bb05350f0d3f26275nd * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af84459fbf938e508fd10b01cb8d699c79083813takashi * The contents of this file may alternatively be used under the terms
af84459fbf938e508fd10b01cb8d699c79083813takashi * of the Common Development and Distribution License Version 1.0
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * VirtualBox OSE distribution, in which case the provisions of the
af84459fbf938e508fd10b01cb8d699c79083813takashi * CDDL are applicable instead of those of the GPL.
af84459fbf938e508fd10b01cb8d699c79083813takashi * You may elect to license modified versions of this file under the
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * terms and conditions of either the GPL or the CDDL or both.
af84459fbf938e508fd10b01cb8d699c79083813takashi/*******************************************************************************
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen* Header Files *
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen*******************************************************************************/
af84459fbf938e508fd10b01cb8d699c79083813takashi bool fRc = false;
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe LogFlow(("RTDirExists(%p={%s}): returns %RTbool\n", pszPath, pszPath, fRc));
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweRTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode)
4bebf996eb7002ebfe897d46a0e0572390604a77nd * mkdir on nfs mount points has been/is busted in various
4bebf996eb7002ebfe897d46a0e0572390604a77nd * during the Nevada development cycle. We've observed:
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * - Build 111b (2009.06) returns EACCES.
4bebf996eb7002ebfe897d46a0e0572390604a77nd * - Build ca. 70-80 returns ENOSYS.
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe LogFlow(("RTDirCreate(%p={%s}, %RTfmode): returns %Rrc\n", pszPath, pszPath, fMode, rc));
57c845e03570b3641fbf41d4f139e2a9b49e406and char const *pszNativePath;
7e9d90004f580231e0376880710dc25408950ab9rbowen LogFlow(("RTDirRemove(%p={%s}): returns %Rrc\n", pszPath, pszPath, rc));
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Linux: The fsync() man page hints at this being required for ensuring
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * consistency between directory and file in case of a crash.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Solaris: No mentioned is made of directories on the fsync man page.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * While rename+fsync will do what we want on ZFS, the code needs more
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * careful studying wrt whether the directory entry of a new file is
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * implicitly synced when the file is synced (it's very likely for ZFS).
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * FreeBSD: The FFS fsync code seems to flush the directory entry as well
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * in some cases. Don't know exactly what's up with rename, but from the
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * look of things fsync(dir) should work.
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh int fd = open(pszPath, O_RDONLY | O_DIRECTORY, 0);
af84459fbf938e508fd10b01cb8d699c79083813takashi * Convert to a native path and try opendir.
fed47023e9be04c612b5f6d4a5ee2b8e7c587181rbowen int rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL);
c8c717fafa0a09ed13469a603a178921b851dd22igalic * Init data.
b7f8d802ecaed65eada1fc31472d06d8460d5528igalic memset(&pDir->Data, 0, RT_OFFSETOF(RTDIR, Data.d_name)); /* not strictly necessary */
acf65805923cf80834c39689cc0e2a8e7201c186sf * Validate input.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Close the handle.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe AssertMsgFailed(("closedir(%p) -> errno=%d (%Rrc)\n", pDir->pDir, errno, rc));
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Ensure that there is unread data in the buffer
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * and that there is a converted filename hanging around.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * @returns IPRT status code.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * @param pDir the open directory. Fully validated.
253547fb9cc7986e84ff68aef076f664fc4169dctakashi /** @todo try avoid the rematching on buffer overflow errors. */
253547fb9cc7986e84ff68aef076f664fc4169dctakashi * Fetch data?
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe int rc = readdir_r(pDir->pDir, &pDir->Data, &pResult);
8559a67073808d84d85bb5dd552d4247caafe709sf //AssertRC(rc);
8559a67073808d84d85bb5dd552d4247caafe709sf * Convert the filename to UTF-8.
8559a67073808d84d85bb5dd552d4247caafe709sf int rc = rtPathFromNative(&pDir->pszName, pDir->Data.d_name, pDir->pszPath);
4bebf996eb7002ebfe897d46a0e0572390604a77nd * Converts the d_type field to IPRT directory entry type.
4bebf996eb7002ebfe897d46a0e0572390604a77nd * @returns IPRT directory entry type.
4bebf996eb7002ebfe897d46a0e0572390604a77nd * @param Unix
af84459fbf938e508fd10b01cb8d699c79083813takashi#endif /*HAVE_DIRENT_D_TYPE */
cd34a6fbf0a2619544a72eadb73f309370bf6682wroweRTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Validate and digest input.
8e9c6d6438af1ccb46adaa60d34caa3ac98f3851igalic AssertMsgReturn(VALID_PTR(pDirEntry), ("%p\n", pDirEntry), VERR_INVALID_POINTER);
7159c12b7697fe9f5ab3a533cc6dfc3d57803053igalic AssertMsgReturn(VALID_PTR(pcbDirEntry), ("%p\n", pcbDirEntry), VERR_INVALID_POINTER);
8e9c6d6438af1ccb46adaa60d34caa3ac98f3851igalic AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]),
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])),
1d45c1463a8bc69bab1c07a4729269ec7333e713rbowen * Fetch more data if necessary and/or convert the name.
1d45c1463a8bc69bab1c07a4729269ec7333e713rbowen * Check if we've got enough space to return the data.
4126704c4950bfd46d32ad54e3b106ac6d868a73sf const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh * Setup the returned data.
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh pDirEntry->INodeId = pDir->Data.d_ino; /* may need #ifdefing later */
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh pDirEntry->enmType = rtDirType(pDir->Data.d_type);
a1ceb0cd0152edea3c72f4d9dcb352bae6ef273fjorton /* free cached data */
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe LogFlow(("RTDirRead(%p:{%s}, %p:{%s}, %p:{%u}): returns %Rrc\n",
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe pDir, pDir->pszPath, pDirEntry, RT_SUCCESS(rc) ? pDirEntry->szName : "<failed>",
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Fills dummy info into the info structure.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * This function is called if we cannot stat the file.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * @param pInfo The struct in question.
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowestatic void rtDirSetDummyInfo(PRTFSOBJINFO pInfo, RTDIRENTRYTYPE enmType)
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_UNKNOWN: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_FIFO: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FIFO;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_DEV_CHAR: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_DEV_CHAR;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_DIRECTORY: pInfo->Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_DEV_BLOCK: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_DEV_BLOCK;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_FILE: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE;
7ffcb32836c716e53b7f4b856ee16d9139b8d3bdsf case RTDIRENTRYTYPE_SYMLINK: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_SYMLINK;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe case RTDIRENTRYTYPE_SOCKET: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_SOCKET;
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe case RTDIRENTRYTYPE_WHITEOUT: pInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_WHITEOUT;
acf65805923cf80834c39689cc0e2a8e7201c186sfRTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
cd34a6fbf0a2619544a72eadb73f309370bf6682wrowe * Validate and digest input.
af84459fbf938e508fd10b01cb8d699c79083813takashi AssertMsgReturn(VALID_PTR(pDirEntry), ("%p\n", pDirEntry), VERR_INVALID_POINTER);
af84459fbf938e508fd10b01cb8d699c79083813takashi AssertMsgReturn( enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
727872d18412fc021f03969b8641810d8896820bhumbedooh ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
727872d18412fc021f03969b8641810d8896820bhumbedooh AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
727872d18412fc021f03969b8641810d8896820bhumbedooh AssertMsgReturn(VALID_PTR(pcbDirEntry), ("%p\n", pcbDirEntry), VERR_INVALID_POINTER);
0d0ba3a410038e179b695446bb149cce6264e0abnd AssertMsgReturn(cbDirEntry >= (unsigned)RT_OFFSETOF(RTDIRENTRYEX, szName[2]),
0d0ba3a410038e179b695446bb149cce6264e0abnd ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])),
727872d18412fc021f03969b8641810d8896820bhumbedooh * Fetch more data if necessary and/or convert the name.
0d0ba3a410038e179b695446bb149cce6264e0abnd * Check if we've got enough space to return the data.
43365cc9aaf2bea5be539bea80c5eb7c926ce148humbedooh const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
if (pcbDirEntry)
if (pszNamePath)
#ifdef HAVE_DIRENT_D_TYPE
return rc;
AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
return rc;