1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fcntl.h>
18 #include <unistd.h>
19 
20 #include "private/bionic_macros.h"
21 
22 template <typename T = int (*)(char*)>
23 class GenericTemporaryFile {
24  public:
mk_fn(mk_fn)25   GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
26     // Since we might be running on the host or the target, and if we're
27     // running on the host we might be running under bionic or glibc,
28     // let's just try both possible temporary directories and take the
29     // first one that works.
30     init("/data/local/tmp");
31     if (fd == -1) {
32       init("/tmp");
33     }
34   }
35 
mk_fn(mk_fn)36   GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
37     init(dirpath);
38   }
39 
~GenericTemporaryFile()40   ~GenericTemporaryFile() {
41     close(fd);
42     unlink(filename);
43   }
44 
reopen()45   void reopen() {
46     close(fd);
47     fd = open(filename, O_RDWR);
48   }
49 
50   int fd;
51   char filename[1024];
52 
53  private:
54   T mk_fn;
55 
init(const char * tmp_dir)56   void init(const char* tmp_dir) {
57     snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
58     fd = mk_fn(filename);
59   }
60 
61   DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
62 };
63 
64 typedef GenericTemporaryFile<> TemporaryFile;
65 
66 class TemporaryDir {
67  public:
TemporaryDir()68   TemporaryDir() {
69     if (!init("/data/local/tmp")) {
70       init("/tmp");
71     }
72   }
73 
~TemporaryDir()74   ~TemporaryDir() {
75     rmdir(dirname);
76   }
77 
78   char dirname[1024];
79 
80  private:
init(const char * tmp_dir)81   bool init(const char* tmp_dir) {
82     snprintf(dirname, sizeof(dirname), "%s/TemporaryDir-XXXXXX", tmp_dir);
83     return (mkdtemp(dirname) != NULL);
84   }
85 
86   DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
87 };
88