Return the base temporary directory, creating it if needed. :returns: The base temporary directory.
(self)
| 143 | return p |
| 144 | |
| 145 | def getbasetemp(self) -> Path: |
| 146 | """Return the base temporary directory, creating it if needed. |
| 147 | |
| 148 | :returns: |
| 149 | The base temporary directory. |
| 150 | """ |
| 151 | if self._basetemp is not None: |
| 152 | return self._basetemp |
| 153 | |
| 154 | if self._given_basetemp is not None: |
| 155 | basetemp = self._given_basetemp |
| 156 | if basetemp.exists(): |
| 157 | rm_rf(basetemp) |
| 158 | basetemp.mkdir(mode=0o700) |
| 159 | basetemp = basetemp.resolve() |
| 160 | else: |
| 161 | from_env = os.environ.get("PYTEST_DEBUG_TEMPROOT") |
| 162 | temproot = Path(from_env or tempfile.gettempdir()).resolve() |
| 163 | user = get_user() or "unknown" |
| 164 | # use a sub-directory in the temproot to speed-up |
| 165 | # make_numbered_dir() call |
| 166 | rootdir = temproot.joinpath(f"pytest-of-{user}") |
| 167 | try: |
| 168 | rootdir.mkdir(mode=0o700, exist_ok=True) |
| 169 | except OSError: |
| 170 | # getuser() likely returned illegal characters for the platform, use unknown back off mechanism |
| 171 | rootdir = temproot.joinpath("pytest-of-unknown") |
| 172 | rootdir.mkdir(mode=0o700, exist_ok=True) |
| 173 | # Because we use exist_ok=True with a predictable name, make sure |
| 174 | # we are the owners, to prevent any funny business (on unix, where |
| 175 | # temproot is usually shared). |
| 176 | # Also, to keep things private, fixup any world-readable temp |
| 177 | # rootdir's permissions. Historically 0o755 was used, so we can't |
| 178 | # just error out on this, at least for a while. |
| 179 | # Don't follow symlinks, otherwise we're open to symlink-swapping |
| 180 | # TOCTOU vulnerability. |
| 181 | # This check makes us vulnerable to a DoS - a user can `mkdir |
| 182 | # /tmp/pytest-of-otheruser` and then `otheruser` will fail this |
| 183 | # check. For now we don't consider it a real problem. otheruser can |
| 184 | # change their TMPDIR or --basetemp, and maybe give the prankster a |
| 185 | # good scolding. |
| 186 | uid = get_user_id() |
| 187 | if uid is not None: |
| 188 | stat_follow_symlinks = ( |
| 189 | False if os.stat in os.supports_follow_symlinks else True |
| 190 | ) |
| 191 | rootdir_stat = rootdir.stat(follow_symlinks=stat_follow_symlinks) |
| 192 | if stat.S_ISLNK(rootdir_stat.st_mode): |
| 193 | raise OSError( |
| 194 | f"The temporary directory {rootdir} is a symbolic link. " |
| 195 | "Fix this and try again." |
| 196 | ) |
| 197 | if rootdir_stat.st_uid != uid: |
| 198 | raise OSError( |
| 199 | f"The temporary directory {rootdir} is not owned by the current user. " |
| 200 | "Fix this and try again." |
| 201 | ) |
| 202 | if (rootdir_stat.st_mode & 0o077) != 0: |