File: mktmpfil.c

package info (click to toggle)
dosemu-freedos 1%3A0.0.b9r5a%2Betch.1-0etch1
  • links: PTS
  • area: contrib
  • in suites: etch
  • size: 19,744 kB
  • ctags: 23,279
  • sloc: ansic: 143,864; asm: 20,397; makefile: 3,868; perl: 1,106; yacc: 690; sh: 553; pascal: 297; xml: 150; cpp: 67
file content (153 lines) | stat: -rw-r--r-- 4,707 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*	$id$
	$Locker:  $	$Name:  $	$State: Exp $

 	Try to create a temporary file in a specified directory
 	with a given extension.
 	On success the name of the temporary file is returned in a
 	dynamically allocated buffer.
 	The extension is simply appended to the randomized filename and
 	must contain the leading dot.
 *
 *  Comments:
 *    Creates unique filenames and creates the files, too.
 *    The filenames do not contain an extension, but my
 *    consume up to eight (8) characters as filename.
 *
 *    The filenames are prefixed by %TEMP%, %TMP%, %TEMPDIR%,
 *    %TMPDIR%, "\\TEMP", "\\TMP", fullpath_of("."), "<bootdrive>:\\",
 *    "."; in that order, whichever returns a writeable location first
 *
 *    The filenames are created within dymamic memory and must be
 *    free()'ed by the caller himself.
 *    The files are touched, meaning they are created with zero
 *    length and no special attributes, but closed; the caller must
 *    remove the file himself.
 *

	This file bases on TMPNAM.C of FreeCOM v0.81 beta 1.

	$Log: mktmpfil.c,v $
	Revision 1.1  2001/04/12 00:33:53  skaus
	chg: new structure
	chg: If DEBUG enabled, no available commands are displayed on startup
	fix: PTCHSIZE also patches min extra size to force to have this amount
	   of memory available on start
	bugfix: CALL doesn't reset options
	add: PTCHSIZE to patch heap size
	add: VSPAWN, /SWAP switch, .SWP resource handling
	bugfix: COMMAND.COM A:\
	bugfix: CALL: if swapOnExec == ERROR, no change of swapOnExec allowed
	add: command MEMORY
	bugfix: runExtension(): destroys command[-2]
	add: clean.bat
	add: localized CRITER strings
	chg: use LNG files for hard-coded strings (hangForEver(), init.c)
		via STRINGS.LIB
	add: DEL.C, COPY.C, CBREAK.C: STRINGS-based prompts
	add: fixstrs.c: prompts & symbolic keys
	add: fixstrs.c: backslash escape sequences
	add: version IDs to DEFAULT.LNG and validation to FIXSTRS.C
	chg: splitted code apart into LIB\*.c and CMD\*.c
	bugfix: IF is now using error system & STRINGS to report errors
	add: CALL: /N
	
 */
#include "../config.h"

#include <dos.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include <dfn.h>

#include "../include/command.h"
#include "../err_fcts.h"
#include "../include/misc.h"

#define nomem error_out_of_memory

/*
 *  Try to create a temporary file with the supplied path, also
 *  fully-qualify it
 *
 *  If ext != NULL, its contents is appended to a randomized prefix,
 *  most useful, if 'ext' begins with a dot, to give the file to be
 *  created an extension.
 */
char *mktempfile(const char * const path, const char *ext)
{
  char *fn, *newpath;
  int cnt,
    fd;

  if (!path)                    /* to simplify the caller function */
    return 0;

  if ((fn = dfnexpand(path, 0)) == 0)
  {                             /* out-of-mem */
    nomem();
    return 0;
  }

  if (!ext)                     /* make sure it's a legal string */
    ext = "";

  /* The completed name consits of:
     + the absolute path name,
     + the '\\' path component delimited path vs. filename
     + eight (8) characters randomized filename
     + the user-supplied extension
     + the '\0' terminator byte
   */
  if ((newpath = realloc(fn, strlen(fn) + strlen(ext) + 10)) == 0)
  {
    /* out of mem */
    free(fn);
    nomem();
    return 0;
  }

  fn = strchr(newpath, '\0');      /* where the '\\' is to be */
  if (fn[-1] != '\\')           /* maybe 1 byte is wasted here */
    *fn++ = '\\';

  cnt = 0;
  do {             /* randomize filename and probe if it can be created */
    /* OK, this is not that efficient, but easy to implement
       right now -- 1998/10/27 ska */
    sprintf(fn, "CMD%x%s", cnt, ext);
    if (!++cnt)                 /* overflow */
      goto errRet;

    /* loop until either the open succeeded or failed with
       something different then "file already exists"

       However, this failed in Win98 DOSbox on root of
       CD-Rom drive:
       (fd = open(path, O_CREAT | O_EXCL | O_WRONLY
       , S_IREAD | S_IWRITE)) == -1 && errno == EACCES);

       Because DOS returned: EACCES

       Let's assume access() does not fail on directories:
     */
  }
  while(dfnstat(newpath)); /* such entry already exists */

  /* Make semaphore test */
  fd = open(newpath, O_CREAT | O_EXCL | O_WRONLY, S_IREAD | S_IWRITE);
  if (fd != -1)
  {                             /* success */
    close(fd);
    return newpath;
  }

errRet:
  free(newpath);
  return 0;
}