VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/RTPathUserHome-posix.cpp@ 68033

Last change on this file since 68033 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.3 KB
Line 
1/* $Id: RTPathUserHome-posix.cpp 62477 2016-07-22 18:27:37Z vboxsync $ */
2/** @file
3 * IPRT - Path Manipulation, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.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#define LOG_GROUP RTLOGGROUP_PATH
32#include <stdlib.h>
33#include <limits.h>
34#include <errno.h>
35#include <unistd.h>
36#include <sys/stat.h>
37#include <sys/time.h>
38#include <stdio.h>
39#include <sys/types.h>
40#include <pwd.h>
41
42#include <iprt/path.h>
43#include <iprt/env.h>
44#include <iprt/assert.h>
45#include <iprt/string.h>
46#include <iprt/err.h>
47#include <iprt/log.h>
48#include "internal/path.h"
49#include "internal/fs.h"
50
51
52#ifndef RT_OS_L4
53/**
54 * Worker for RTPathUserHome that looks up the home directory
55 * using the getpwuid_r api.
56 *
57 * @returns IPRT status code.
58 * @param pszPath The path buffer.
59 * @param cchPath The size of the buffer.
60 * @param uid The User ID to query the home directory of.
61 */
62static int rtPathUserHomeByPasswd(char *pszPath, size_t cchPath, uid_t uid)
63{
64 /*
65 * The getpwuid_r function uses the passed in buffer to "allocate" any
66 * extra memory it needs. On some systems we should probably use the
67 * sysconf function to find the appropriate buffer size, but since it won't
68 * work everywhere we'll settle with a 5KB buffer and ASSUME that it'll
69 * suffice for even the lengthiest user descriptions...
70 */
71 char achBuffer[5120];
72 struct passwd Passwd;
73 struct passwd *pPasswd;
74 memset(&Passwd, 0, sizeof(Passwd));
75 int rc = getpwuid_r(uid, &Passwd, &achBuffer[0], sizeof(achBuffer), &pPasswd);
76 if (rc != 0)
77 return RTErrConvertFromErrno(rc);
78 if (!pPasswd) /* uid not found in /etc/passwd */
79 return VERR_PATH_NOT_FOUND;
80
81 /*
82 * Check that it isn't empty and that it exists.
83 */
84 struct stat st;
85 if ( !pPasswd->pw_dir
86 || !*pPasswd->pw_dir
87 || stat(pPasswd->pw_dir, &st)
88 || !S_ISDIR(st.st_mode))
89 return VERR_PATH_NOT_FOUND;
90
91 /*
92 * Convert it to UTF-8 and copy it to the return buffer.
93 */
94 return rtPathFromNativeCopy(pszPath, cchPath, pPasswd->pw_dir, NULL);
95}
96#endif
97
98
99/**
100 * Worker for RTPathUserHome that looks up the home directory
101 * using the HOME environment variable.
102 *
103 * @returns IPRT status code.
104 * @param pszPath The path buffer.
105 * @param cchPath The size of the buffer.
106 */
107static int rtPathUserHomeByEnv(char *pszPath, size_t cchPath)
108{
109 /*
110 * Get HOME env. var it and validate it's existance.
111 */
112 int rc = VERR_PATH_NOT_FOUND;
113 const char *pszHome = RTEnvGet("HOME"); /** @todo Codeset confusion in RTEnv. */
114 if (pszHome)
115
116 {
117 struct stat st;
118 if ( !stat(pszHome, &st)
119 && S_ISDIR(st.st_mode))
120 rc = rtPathFromNativeCopy(pszPath, cchPath, pszHome, NULL);
121 }
122 return rc;
123}
124
125
126RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
127{
128 int rc;
129#ifndef RT_OS_L4
130 /*
131 * We make an exception for the root user and use the system call
132 * getpwuid_r to determine their initial home path instead of
133 * reading it from the $HOME variable. This is because the $HOME
134 * variable does not get changed by sudo (and possibly su and others)
135 * which can cause root-owned files to appear in user's home folders.
136 */
137 uid_t uid = geteuid();
138 if (!uid)
139 rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
140 else
141 rc = rtPathUserHomeByEnv(pszPath, cchPath);
142
143 /*
144 * On failure, retry using the alternative method.
145 * (Should perhaps restrict the retry cases a bit more here...)
146 */
147 if ( RT_FAILURE(rc)
148 && rc != VERR_BUFFER_OVERFLOW)
149 {
150 if (!uid)
151 rc = rtPathUserHomeByEnv(pszPath, cchPath);
152 else
153 rc = rtPathUserHomeByPasswd(pszPath, cchPath, uid);
154 }
155#else /* RT_OS_L4 */
156 rc = rtPathUserHomeByEnv(pszPath, cchPath);
157#endif /* RT_OS_L4 */
158
159 LogFlow(("RTPathUserHome(%p:{%s}, %u): returns %Rrc\n", pszPath,
160 RT_SUCCESS(rc) ? pszPath : "<failed>", cchPath, rc));
161 return rc;
162}
163
Note: See TracBrowser for help on using the repository browser.

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