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
|
/*
*
* Copyright (C) 1997-2022, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: ofstd
*
* Author: Marco Eichelberg
*
* Purpose:
* classes: OFFilenameCreator
*
*/
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/offname.h"
#include "dcmtk/ofstd/ofcast.h"
#include "dcmtk/ofstd/ofstd.h" /* for OFString::myrand_r */
#include "dcmtk/ofstd/ofstdinc.h"
#include <cerrno>
#include <ctime>
BEGIN_EXTERN_C
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for time_t */
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat() */
#endif
END_EXTERN_C
/* give up after this number of unsuccessful attempts to create a unique filename */
#define MAX_TRY 1024
OFFilenameCreator::OFFilenameCreator()
: creation_time(0)
{
creation_time = OFstatic_cast(unsigned long, time(NULL));
}
OFFilenameCreator::OFFilenameCreator(const OFFilenameCreator& copy)
: creation_time(copy.creation_time)
{
}
OFFilenameCreator::~OFFilenameCreator()
{
}
OFFilenameCreator &OFFilenameCreator::operator=(const OFFilenameCreator& copy)
{
creation_time = copy.creation_time;
return *this;
}
OFBool OFFilenameCreator::makeFilename(unsigned int &seed, const char *dir, const char *prefix, const char *postfix, OFString &filename)
{
OFBool done = OFFalse;
OFBool result = OFTrue;
struct stat stat_buf;
int stat_result = 0;
unsigned tries = 0;
do
{
// create filename
filename.clear();
if (prefix) filename = prefix;
addLongToString(creation_time, filename);
// on some systems OFrand_r may produce only 16-bit random numbers.
// To be on the safe side, we use two random numbers for the upper and the lower 16 bits.
addLongToString((((OFrand_r(seed) & 0xFFFF) << 16) | (OFrand_r(seed) & 0xFFFF)), filename);
if (postfix) filename += postfix;
OFStandard::sanitizeFilename(filename);
if (dir)
{
OFString dirname = dir;
dirname += PATH_SEPARATOR;
dirname += filename;
filename = dirname;
}
// check if filename exists
stat_result = stat(filename.c_str(), &stat_buf);
if (stat_result == 0)
{
if (++tries == MAX_TRY)
{
done = OFTrue;
result = OFFalse;
}
} else {
// file does not exists, bail out
done = OFTrue;
if (errno != ENOENT) result=OFFalse; // something wrong with path
}
} while (!done);
return result;
}
void OFFilenameCreator::addLongToString(unsigned long l, OFString &s)
{
l &= 0xFFFFFFFFL;
unsigned long m;
int idx=7;
char chr_array[9];
OFStandard::strlcpy(chr_array, "00000000", 9);
while (l)
{
m = l & 0x0FL;
l >>= 4;
if (m > 9)
chr_array[idx--] = OFstatic_cast(char, 'a'+(m-10));
else chr_array[idx--] = OFstatic_cast(char, '0'+m);
}
s += chr_array;
return;
}
unsigned int OFFilenameCreator::hashString(const char *str)
{
/* very simple hash function: XOR result with string character and rotate left by 1 bit. */
unsigned int result = OFstatic_cast(unsigned int, -1);
if (str)
{
while (*str != '\0')
{
result %= *str++;
if (OFstatic_cast(signed int, result) <0) result = (result << 1)| 1; else result <<= 1;
}
}
return result;
}
|