blob: 7dc528e536476dd6cae807cb2e45e4d8f6b78b54 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#define _XOPEN_SOURCE_EXTENDED 1
#include <stdlib.h>
#include "ApplicationFile.h"
#include "ComDiags.h"
#include "DgBaseType.h"
#include "mxCompileUserModule.h"
// create a temporary file and open it for write.
FILE* ApplicationFile::createTempFile(char* nam, char *newNam)
{
// There is a risk of a race condition here:
// "tmpnam, in Application::getTempFileName(), guarantees the name it returns
// isn't in use now and that tmpnam won't returnn same name again in the this
// process. We take that name and add some a suffix (process num). tmpnam's
// guaranteee that the file didn't exist is not of use since we use it as
// the root of our filename. That is, if tmpnam returns "TMPxyz" and we add
// the process number and turn it into "TMPxyz987654", there is no guarantee
// that "TMPxyz987654" doesn't already exist. Also race condition issue
// even for base name. Perhaps use mkstemp instead? Creates file & takes a
// 'template' for name -- you could provide template with process num and/or
// timestamp frag & some identifying chars in it for extra uniqueness &
// identifiability. I made this major because there was no retry code and
// the result of a collision could be nasty."
// OK. mkstemp does what we want here. You'd think simply calling mkstemp
// here and we're done. Not so. It turns out that c89 & nld are sensitive
// to mkstemp's function signature. mkstemp is declared in <stdlib.h>
// guarded by #if _XOPEN_SOURCE_EXTENDED == 1
// If we add these 2 lines
// #define _XOPEN_SOURCE_EXTENDED 1
// #include <stdlib.h>
// to ApplicationFile.h or ApplicationFile.cpp, c89 rejects the mkstemp()
// call in ApplicationFile::createTempFile as an undeclared identifier.
// Attempts to do an in-line declaration of mkstemp as
// int mkstemp(char *);
// seem to pass c89 & nld, but running mxCompileUserModule on OSS results
// in an unresolved reference to mkstemp & an INSPECT session:
// usr/treyes/bin/debug: mxCompileUserModule
// PID: \SQUAW.0,423 mxCompileUserModule (ELF)
// External References Not Resolved to Any User/System Library:
// Prg: mxCompileUserModule -> mkstemp__FPc (PROC)
// It appears that a negative interaction of #include's and #define's
// and c89's various phases conspire to prevent the mkstemp() call from
// being resolved to its declaration in <stdlib.h> and its definition in
// zosshsrl and libossh.srl.
// Splitting ApplicationFile::createTempFile's definition away into its
// own source file (ApplicationFile2.cpp) seems to clear up this negative
// interaction. Sigh :-( These dozen or so lines took 3 days to fix :-(
// Since mxCompileUserModule can potentially be used to sql compile lots,
// possibly thousands, of sql modules, we must work around mkstemp's 26
// unique temporary file name limit. We do this by using tmpnam in
// ApplicationFile::getTempFileName to compose up to TMP_MAX (27,576)
// different temporary file name prefixes.
strcpy(newNam, nam);
// NT has no mkstemp(), so just fall thru and create & open temp file
FILE *tFil = fopen(newNam, "w");
if (!tFil) {
*mxCUMptr << FAIL << DgSqlCode(-2206) << DgString0(newNam);
}
return tFil;
}