source: mainline/uspace/lib/c/generic/tmpfile.c@ 1be7bee

Last change on this file since 1be7bee was 4e6a610, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Temporary file functions rework. Fix libposix access() not working on directories.

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/*
2 * Copyright (c) 2018 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file Temporary files
33 */
34
35#include <errno.h>
36#include <fibril_synch.h>
37#include <stdio.h>
38#include <str.h>
39#include <tmpfile.h>
40#include <vfs/vfs.h>
41
42static size_t tmpfile_cnt = 0;
43static FIBRIL_MUTEX_INITIALIZE(tmpfile_lock);
44
45/** Create and open file suitable as temporary file based on template.
46 *
47 * This is designed to allow creating temporary files compatible with POSIX
48 * mk(s)temp and tempnam, as well as for the use of ISO C tmpfile, tmpnam.
49 *
50 * @param templ
51 * @param create If @c false, only construct file name
52 *
53 * @return If @a create is true, open file descriptor on success (and
54 * @a *templ is filled in with actual file name),
55 * if @a create is false, zero on success. -1 on failure.
56 */
57int __tmpfile_templ(char *templ, bool create)
58{
59 size_t tsize;
60 char *p;
61 int file;
62 errno_t rc;
63
64 tsize = str_size(templ);
65 if (tsize < 6)
66 return -1;
67
68 p = templ + tsize - 6;
69 if (str_cmp(p, "XXXXXX") != 0)
70 return -1;
71
72 fibril_mutex_lock(&tmpfile_lock);
73
74 while (tmpfile_cnt < 1000000) {
75 snprintf(p, 6 + 1, "%06zu", tmpfile_cnt);
76 if (create) {
77 /* Try creating file */
78 rc = vfs_lookup(templ, WALK_MUST_CREATE |
79 WALK_REGULAR, &file);
80 if (rc == EOK) {
81 rc = vfs_open(file, MODE_READ | MODE_WRITE);
82 if (rc == EOK) {
83 ++tmpfile_cnt;
84 fibril_mutex_unlock(&tmpfile_lock);
85 return file;
86 }
87
88 vfs_put(file);
89 }
90 } else {
91 /* Test if file exists */
92 rc = vfs_lookup(templ, 0, &file);
93 if (rc != EOK) {
94 ++tmpfile_cnt;
95 fibril_mutex_unlock(&tmpfile_lock);
96 return 0;
97 }
98
99 vfs_put(file);
100 }
101
102 ++tmpfile_cnt;
103 }
104
105 fibril_mutex_unlock(&tmpfile_lock);
106 return -1;
107}
108
109/** Create and open temporary (unnamed) file.
110 *
111 * @return Open file descriptor on success, -1 on failure.
112 */
113int __tmpfile(void)
114{
115 int file;
116 char namebuf[L_tmpnam];
117
118 str_cpy(namebuf, L_tmpnam, "/tmp/tmp.XXXXXX");
119
120 file = __tmpfile_templ(namebuf, true);
121 if (file < 0)
122 return -1;
123
124 (void) vfs_unlink_path(namebuf);
125 return file;
126}
127
128/** Construct temporary file name.
129 *
130 * @param namebuf Buffer that can hold at least L_tmpnam bytes
131 * @return @a namebuf on success, @c NULL on failure
132 */
133char *__tmpnam(char *namebuf)
134{
135 int rc;
136
137 str_cpy(namebuf, L_tmpnam, "/tmp/tmp.XXXXXX");
138
139 rc = __tmpfile_templ(namebuf, false);
140 if (rc < 0)
141 return NULL;
142
143 return namebuf;
144}
145
146/** @}
147 */
Note: See TracBrowser for help on using the repository browser.