1 /* $Id$
2  *  Provides temp files & directories operating functions
3  *
4  * (c) Stas Degteff <g@grumbler.org>, 2:5080/102@fidonet
5  *
6  *  Latest version may be foind on http://husky.sourceforge.net
7  *
8  *
9  * HUSKYLIB: common defines, types and functions for HUSKY
10  *
11  * This is part of The HUSKY Fidonet Software project:
12  * see http://husky.sourceforge.net for details
13  *
14  *
15  * HUSKYLIB is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * HUSKYLIB is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; see file COPYING. If not, write to the
27  * Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28  *
29  * See also http://www.gnu.org, license may be found here.
30  */
31 
32 /* standard headers */
33 #include <errno.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 
40 
41 /* huskylib: compiler.h */
42 #include <compiler.h>
43 
44 
45 /* compiler-dependent headers */
46 #ifdef HAS_UNISTD_H
47 #   include <unistd.h>
48 #endif
49 
50 #ifdef HAS_IO_H
51 #   include <io.h>
52 #endif
53 
54 
55 /* huskylib headers */
56 #define DLLEXPORT
57 #include <huskyext.h>
58 
59 /* huskylib headers */
60 #include <log.h>
61 #include <temp.h>
62 #include <memory.h>
63 #include <xstr.h>
64 #include <strext.h>
65 
66 /***  Declarations & defines  ***********************************************/
67 
68 
69 /***  Implementation  *******************************************************/
70 
71 /* If mkstemps() not implemented, use this function.
72  * parameters example:
73  *   tempfilename = "/path/prefixXXXXX.suffix"
74  *   tempfilename = "/path/prefixXXXXX"
75  *  "XXXXX" replaced with random char sequence
76  */
MKSTEMPS(char * tempfilename)77 int MKSTEMPS( char *tempfilename )
78 {  char *ttt;
79    int fd=-1;
80    char *pp;
81 
82    if (tempfilename == NULL)
83      return -1;
84 
85    ttt = sstrdup(tempfilename);
86    pp = strrchr(ttt, '.');
87    if( ttt[strlen(ttt)-1]!='X' && pp && (pp>ttt && *(pp-1)=='X') ){ /* suffix presents */
88      do{
89          *pp = 0;
90          if( !mktemp(ttt) )
91            break;
92          *pp = '.';
93          fd = open( ttt, O_EXCL | O_CREAT | O_RDWR, S_IREAD | S_IWRITE );
94      }while( fd==-1 && errno == EEXIST && (strcpy(ttt,tempfilename), 1) );
95    }else{
96      do{
97          if( !mktemp(ttt) )
98            break;
99          fd = open( ttt, O_EXCL | O_CREAT | O_RDWR, S_IREAD | S_IWRITE );
100      }while( fd==-1 && errno == EEXIST && (strcpy(ttt,tempfilename), 1) );
101    }
102    if(fd!=-1) strcpy(tempfilename,ttt);
103    nfree(ttt);
104    return fd;
105 }
106 
107 /* Create new file with random name & specified suffix in specified directory.
108  * path = temporary directory
109  * ext = file name suffix
110  * mode = 'w' or 'b' - file open mode (text or binary); default = fopen() default
111  * Place to 'name' variable name of created file (from malloc() memory pool),
112  * if name is not NULL its free().
113  * Return file descriptor or NULL
114  */
115 
createTempFileIn(const char * path,const char * ext,char mode,char ** name)116 FILE *createTempFileIn(const char *path, const char *ext, char mode, char **name)
117 { int tempfh=-1; FILE *tempfd=NULL; char *tempfilename=NULL;
118   char *ii=0;
119 
120   if( !path || !path[0] ){
121     w_log(LL_ERR, "temp::createTempFileIn(): pathname is empty!");
122     return NULL;
123   }
124   w_log( LL_FUNC, "createtempfileIn() start" );
125 
126   xstrcat( &tempfilename, (char *)path );
127   ii = tempfilename + strlen(tempfilename) -1;
128   if( *ii == PATH_DELIM ) *ii=0; /* strip trailing slash */
129 
130   xscatprintf( &tempfilename, "%cXXXXXX.%s", PATH_DELIM, ext);
131 
132   w_log(LL_FILENAME, "Temp. file mask: %s", tempfilename);
133 
134   tempfh = MKSTEMPS(tempfilename);
135   if( tempfh == -1 )
136   { w_log( LL_ERR, "Cannot create temp. file (Mask %s): %s", tempfilename, strerror(errno) );
137     w_log( LL_FUNC, "createTempFileIn() rc=NULL" );
138     return NULL;
139   }
140   if( mode == 't' )
141      tempfd = fdopen(tempfh,"wt");
142   else if( mode == 'b' )
143      tempfd = fdopen(tempfh,"wb");
144   else
145      tempfd = fdopen(tempfh,"w");
146   if( !tempfd )
147   { w_log( LL_CRIT, "Cannot reopen file '%s': %s", tempfilename, strerror(errno) );
148     return NULL;
149   }
150   w_log( LL_FILE, "Created temp file %s", tempfilename );
151   if( name!= NULL )
152   { nfree(*name);
153    *name = sstrdup(tempfilename);
154   }
155   w_log( LL_FUNC, "createTempFileIn() OK fd=%p", tempfd );
156   return tempfd;
157 }
158 
159 
160 /* Create new file with random name & specified suffix (text mode).
161  * pconfig = fidoconfig structure pointer
162  * ext = file name suffix
163  * Place to 'name' variable name of created file (from malloc() memory pool),
164  * if name is not NULL its free().
165  * Return file descriptor or NULL
166  */
createTempTextFile(char * tempDir,char ** name)167 FILE *createTempTextFile(char *tempDir, char **name)
168 { if(tempDir)
169     return createTempFileIn(tempDir, TEMPFILESUFFIX, 't', name);
170   else{
171     w_log(LL_ERR, "tempDir not defined in config, temp. file can't created");
172     return NULL;
173   }
174 }
175 
176 /* Create new file with random name & specified suffix (binary mode).
177  * pconfig = fidoconfig structure pointer
178  * ext = file name suffix
179  * Place to 'name' variable name of created file (from malloc() memory pool),
180  * if name is not NULL its free().
181  * Return file descriptor or NULL
182  */
createTempBinFile(char * tempDir,char ** name)183 FILE *createTempBinFile(char *tempDir, char **name)
184 { if(tempDir)
185     return createTempFileIn(tempDir, TEMPFILESUFFIX, 'b', name);
186   else{
187     w_log(LL_ERR, "tempDir not defined in config, temp. file can't created");
188     return NULL;
189   }
190 }
191 
192 
193 #ifdef TEST_TEMP_C
194 
195 #include <string.h>
196 #include <errno.h>
197 #include <stdio.h>
198 
199 /*  Test */
main()200 void main()
201 { FILE *fd;
202   s_fidoconfig *config;
203   char *name=NULL;
204 
205   config = readConfig("../test.cfg");
206   fd = createTempBinFile(config, &name);
207   if( !fd )
208     printf("error creating %s: %s\n", name, strerror(errno) );
209   else
210   {  printf("created: %s\n", name);
211      fclose (fd);
212      unlink(name);
213   }
214   disposeConfig(config);
215 }
216 #endif
217