Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5215 serge 1
/*
2
 * Copyright (c) 1987 Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms are permitted
6
 * provided that: (1) source distributions retain this entire copyright
7
 * notice and comment, and (2) distributions including binaries display
8
 * the following acknowledgement:  ``This product includes software
9
 * developed by the University of California, Berkeley and its contributors''
10
 * in the documentation or other materials provided with the distribution
11
 * and in all advertising materials mentioning features or use of this
12
 * software. Neither the name of the University nor the names of its
13
 * contributors may be used to endorse or promote products derived
14
 * from this software without specific prior written permission.
15
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
 */
19
/* This is file MKTEMP.C */
20
/* This file may have been modified by DJ Delorie (Jan 1991).  If so,
21
** these modifications are Copyright (C) 1991 DJ Delorie.
22
*/
23
 
24
/*
25
FUNCTION
26
<>, <>, <>, <>,
27
<>---generate unused file name
28
<>---generate unused directory
29
 
30
INDEX
31
	mktemp
32
INDEX
33
	mkdtemp
34
INDEX
35
	mkstemp
36
INDEX
37
	mkstemps
38
INDEX
39
	mkostemp
40
INDEX
41
	mkostemps
42
INDEX
43
	_mktemp_r
44
INDEX
45
	_mkdtemp_r
46
INDEX
47
	_mkstemp_r
48
INDEX
49
	_mkstemps_r
50
INDEX
51
	_mkostemp_r
52
INDEX
53
	_mkostemps_r
54
 
55
ANSI_SYNOPSIS
56
	#include 
57
	char *mktemp(char *<[path]>);
58
	char *mkdtemp(char *<[path]>);
59
	int mkstemp(char *<[path]>);
60
	int mkstemps(char *<[path]>, int <[suffixlen]>);
61
	int mkostemp(char *<[path]>, int <[flags]>);
62
	int mkostemps(char *<[path]>, int <[suffixlen]>, int <[flags]>);
63
 
64
	char *_mktemp_r(struct _reent *<[reent]>, char *<[path]>);
65
	char *_mkdtemp_r(struct _reent *<[reent]>, char *<[path]>);
66
	int *_mkstemp_r(struct _reent *<[reent]>, char *<[path]>);
67
	int *_mkstemps_r(struct _reent *<[reent]>, char *<[path]>, int <[len]>);
68
	int *_mkostemp_r(struct _reent *<[reent]>, char *<[path]>,
69
			 int <[flags]>);
70
	int *_mkostemps_r(struct _reent *<[reent]>, char *<[path]>, int <[len]>,
71
			  int <[flags]>);
72
 
73
DESCRIPTION
74
<>, <>, and <> attempt to generate a file name
75
that is not yet in use for any existing file.  <> and <>
76
create the file and open it for reading and writing; <> simply
77
generates the file name (making <> a security risk).  <>
78
and <> allow the addition of other <> flags, such
79
as <>, <>, or <>.  On platforms with a
80
separate text mode, <> forces <>, while <>
81
allows the choice between <>, <>, or 0 for default.
82
<> attempts to create a directory instead of a file, with a
83
permissions mask of 0700.
84
 
85
You supply a simple pattern for the generated file name, as the string
86
at <[path]>.  The pattern should be a valid filename (including path
87
information if you wish) ending with at least six `<>'
88
characters.  The generated filename will match the leading part of the
89
name you supply, with the trailing `<>' characters replaced by some
90
combination of digits and letters.  With <>, the `<>'
91
characters end <[suffixlen]> bytes before the end of the string.
92
 
93
The alternate functions <<_mktemp_r>>, <<_mkdtemp_r>>, <<_mkstemp_r>>,
94
<<_mkostemp_r>>, <<_mkostemps_r>>, and <<_mkstemps_r>> are reentrant
95
versions.  The extra argument <[reent]> is a pointer to a reentrancy
96
structure.
97
 
98
RETURNS
99
<> returns the pointer <[path]> to the modified string
100
representing an unused filename, unless it could not generate one, or
101
the pattern you provided is not suitable for a filename; in that case,
102
it returns <>.  Be aware that there is an inherent race between
103
generating the name and attempting to create a file by that name;
104
you are advised to use <>.
105
 
106
<> returns the pointer <[path]> to the modified string if the
107
directory was created, otherwise it returns <>.
108
 
109
<>, <>, <>, and <> return a file
110
descriptor to the newly created file, unless it could not generate an
111
unused filename, or the pattern you provided is not suitable for a
112
filename; in that case, it returns <<-1>>.
113
 
114
NOTES
115
Never use <>.  The generated filenames are easy to guess and
116
there's a race between the test if the file exists and the creation
117
of the file.  In combination this makes <> prone to attacks
118
and using it is a security risk.  Whenever possible use <>
119
instead.  It doesn't suffer the race condition.
120
 
121
PORTABILITY
122
ANSI C does not require either <> or <>; the System
123
V Interface Definition requires <> as of Issue 2.  POSIX 2001
124
requires <>, and POSIX 2008 requires <> while
125
deprecating <>.  <>, <>, and <>
126
are not standardized.
127
 
128
Supporting OS subroutines required: <>, <>, <>, <>.
129
*/
130
 
131
#include <_ansi.h>
132
#include 
133
#include 
134
#include 
135
#include 
136
#include 
137
#include 
138
#include 
139
#include 
140
 
141
static int
142
_DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen, flags),
143
       struct _reent *ptr _AND
144
       char *path         _AND
145
       register int *doopen _AND
146
       int domkdir        _AND
147
       size_t suffixlen   _AND
148
       int flags)
149
{
150
  register char *start, *trv;
151
  char *end;
152
#ifdef __USE_INTERNAL_STAT64
153
  struct stat64 sbuf;
154
#else
155
  struct stat sbuf;
156
#endif
157
  unsigned int pid;
158
 
159
  pid = _getpid_r (ptr);
160
  for (trv = path; *trv; ++trv)		/* extra X's get set to 0's */
161
    continue;
162
  if (trv - path < suffixlen)
163
    {
164
      ptr->_errno = EINVAL;
165
      return 0;
166
    }
167
  trv -= suffixlen;
168
  end = trv;
169
  while (path < trv && *--trv == 'X')
170
    {
171
      *trv = (pid % 10) + '0';
172
      pid /= 10;
173
    }
174
  if (end - trv < 6)
175
    {
176
      ptr->_errno = EINVAL;
177
      return 0;
178
    }
179
 
180
  /*
181
   * Check the target directory; if you have six X's and it
182
   * doesn't exist this runs for a *very* long time.
183
   */
184
 
185
  for (start = trv + 1;; --trv)
186
    {
187
      if (trv <= path)
188
	break;
189
      if (*trv == '/')
190
	{
191
	  *trv = '\0';
192
#ifdef __USE_INTERNAL_STAT64
193
	  if (_stat64_r (ptr, path, &sbuf))
194
#else
195
	  if (_stat_r (ptr, path, &sbuf))
196
#endif
197
	    return (0);
198
	  if (!(sbuf.st_mode & S_IFDIR))
199
	    {
200
	      ptr->_errno = ENOTDIR;
201
	      return (0);
202
	    }
203
	  *trv = '/';
204
	  break;
205
	}
206
    }
207
 
208
  for (;;)
209
    {
210
#if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 4
211
      if (domkdir)
212
	{
213
#ifdef HAVE_MKDIR
214
	  if (_mkdir_r (ptr, path, 0700) == 0)
215
	    return 1;
216
	  if (ptr->_errno != EEXIST)
217
	    return 0;
218
#else /* !HAVE_MKDIR */
219
	  ptr->_errno = ENOSYS;
220
	  return 0;
221
#endif /* !HAVE_MKDIR */
222
	}
223
      else
224
#endif /* _ELIX_LEVEL */
225
      if (doopen)
226
	{
227
	  if ((*doopen = _open_r (ptr, path, O_CREAT | O_EXCL | O_RDWR | flags,
228
				  0600)) >= 0)
229
	    return 1;
230
	  if (ptr->_errno != EEXIST)
231
	    return 0;
232
	}
233
#ifdef __USE_INTERNAL_STAT64
234
      else if (_stat64_r (ptr, path, &sbuf))
235
#else
236
      else if (_stat_r (ptr, path, &sbuf))
237
#endif
238
	return (ptr->_errno == ENOENT ? 1 : 0);
239
 
240
      /* tricky little algorithm for backward compatibility */
241
      for (trv = start;;)
242
	{
243
	  if (trv == end)
244
	    return 0;
245
	  if (*trv == 'z')
246
	    *trv++ = 'a';
247
	  else
248
	    {
249
	      /* Safe, since it only encounters 7-bit characters.  */
250
	      if (isdigit ((unsigned char) *trv))
251
		*trv = 'a';
252
	      else
253
		++ * trv;
254
	      break;
255
	    }
256
	}
257
    }
258
  /*NOTREACHED*/
259
}
260
 
261
#ifndef O_BINARY
262
# define O_BINARY 0
263
#endif
264
 
265
int
266
_DEFUN(_mkstemp_r, (ptr, path),
267
       struct _reent *ptr _AND
268
       char *path)
269
{
270
  int fd;
271
 
272
  return (_gettemp (ptr, path, &fd, 0, 0, O_BINARY) ? fd : -1);
273
}
274
 
275
#if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 4
276
char *
277
_DEFUN(_mkdtemp_r, (ptr, path),
278
       struct _reent *ptr _AND
279
       char *path)
280
{
281
  return (_gettemp (ptr, path, (int *) NULL, 1, 0, 0) ? path : NULL);
282
}
283
 
284
int
285
_DEFUN(_mkstemps_r, (ptr, path, len),
286
       struct _reent *ptr _AND
287
       char *path _AND
288
       int len)
289
{
290
  int fd;
291
 
292
  return (_gettemp (ptr, path, &fd, 0, len, O_BINARY) ? fd : -1);
293
}
294
 
295
int
296
_DEFUN(_mkostemp_r, (ptr, path, flags),
297
       struct _reent *ptr _AND
298
       char *path _AND
299
       int flags)
300
{
301
  int fd;
302
 
303
  return (_gettemp (ptr, path, &fd, 0, 0, flags & ~O_ACCMODE) ? fd : -1);
304
}
305
 
306
int
307
_DEFUN(_mkostemps_r, (ptr, path, len, flags),
308
       struct _reent *ptr _AND
309
       char *path _AND
310
       int len _AND
311
       int flags)
312
{
313
  int fd;
314
 
315
  return (_gettemp (ptr, path, &fd, 0, len, flags & ~O_ACCMODE) ? fd : -1);
316
}
317
#endif /* _ELIX_LEVEL */
318
 
319
char *
320
_DEFUN(_mktemp_r, (ptr, path),
321
       struct _reent *ptr _AND
322
       char *path)
323
{
324
  return (_gettemp (ptr, path, (int *) NULL, 0, 0, 0) ? path : (char *) NULL);
325
}
326
 
327
#ifndef _REENT_ONLY
328
 
329
int
330
_DEFUN(mkstemp, (path),
331
       char *path)
332
{
333
  int fd;
334
 
335
  return (_gettemp (_REENT, path, &fd, 0, 0, O_BINARY) ? fd : -1);
336
}
337
 
338
# if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 4
339
char *
340
_DEFUN(mkdtemp, (path),
341
       char *path)
342
{
343
  return (_gettemp (_REENT, path, (int *) NULL, 1, 0, 0) ? path : NULL);
344
}
345
 
346
int
347
_DEFUN(mkstemps, (path, len),
348
       char *path _AND
349
       int len)
350
{
351
  int fd;
352
 
353
  return (_gettemp (_REENT, path, &fd, 0, len, O_BINARY) ? fd : -1);
354
}
355
 
356
int
357
_DEFUN(mkostemp, (path, flags),
358
       char *path _AND
359
       int flags)
360
{
361
  int fd;
362
 
363
  return (_gettemp (_REENT, path, &fd, 0, 0, flags & ~O_ACCMODE) ? fd : -1);
364
}
365
 
366
int
367
_DEFUN(mkostemps, (path, len, flags),
368
       char *path _AND
369
       int len _AND
370
       int flags)
371
{
372
  int fd;
373
 
374
  return (_gettemp (_REENT, path, &fd, 0, len, flags & ~O_ACCMODE) ? fd : -1);
375
}
376
# endif /* _ELIX_LEVEL */
377
 
378
char *
379
_DEFUN(mktemp, (path),
380
       char *path)
381
{
382
  return (_gettemp (_REENT, path, (int *) NULL, 0, 0, 0) ? path : (char *) NULL);
383
}
384
 
385
#endif /* ! defined (_REENT_ONLY) */