| 1 | // |
|---|
| 2 | // TxWin, Textmode Windowing Library |
|---|
| 3 | // |
|---|
| 4 | // Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk |
|---|
| 5 | // |
|---|
| 6 | // ========================================================================== |
|---|
| 7 | // |
|---|
| 8 | // This file contains Original Code and/or Modifications of Original Code as |
|---|
| 9 | // defined in and that are subject to the GNU Lesser General Public License. |
|---|
| 10 | // You may not use this file except in compliance with the License. |
|---|
| 11 | // BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE. |
|---|
| 12 | // A copy of the License is provided with the Original Code and Modifications, |
|---|
| 13 | // and is also available at http://www.dfsee.com/txwin/lgpl.htm |
|---|
| 14 | // |
|---|
| 15 | // This library is free software; you can redistribute it and/or modify |
|---|
| 16 | // it under the terms of the GNU Lesser General Public License as published |
|---|
| 17 | // by the Free Software Foundation; either version 2.1 of the License, |
|---|
| 18 | // or (at your option) any later version. |
|---|
| 19 | // |
|---|
| 20 | // This library 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. |
|---|
| 23 | // See the GNU Lesser General Public License for more details. |
|---|
| 24 | // |
|---|
| 25 | // You should have received a copy of the GNU Lesser General Public License |
|---|
| 26 | // along with this library; (lgpl.htm) if not, write to the Free Software |
|---|
| 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 28 | // |
|---|
| 29 | // Questions on TxWin licensing can be directed to: txwin@fsys.nl |
|---|
| 30 | // |
|---|
| 31 | // ========================================================================== |
|---|
| 32 | // |
|---|
| 33 | // TxLib filesystem functions, make std and 8.3 paths |
|---|
| 34 | // |
|---|
| 35 | |
|---|
| 36 | #include <txlib.h> // TxLib interface |
|---|
| 37 | |
|---|
| 38 | #include <sys/stat.h> // for low level stuff |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | /*****************************************************************************/ |
|---|
| 42 | // Create path in a recursive fashion |
|---|
| 43 | /*****************************************************************************/ |
|---|
| 44 | ULONG TxMakePath // RET result |
|---|
| 45 | ( |
|---|
| 46 | char *filename // IN relative/absolute path |
|---|
| 47 | ) |
|---|
| 48 | { |
|---|
| 49 | ULONG rc = NO_ERROR; // return value |
|---|
| 50 | #if defined (WIN32) |
|---|
| 51 | char *p = NULL; |
|---|
| 52 | ULONG ulAttr; |
|---|
| 53 | #elif defined (DOS32) |
|---|
| 54 | char *p = NULL; |
|---|
| 55 | unsigned usAttr; // attributes (dos.h) |
|---|
| 56 | #elif defined (LINUX) |
|---|
| 57 | //- to be refined |
|---|
| 58 | #else |
|---|
| 59 | char *p = NULL; |
|---|
| 60 | FILESTATUS3 fstat; |
|---|
| 61 | #endif |
|---|
| 62 | |
|---|
| 63 | ENTER(); |
|---|
| 64 | |
|---|
| 65 | #if defined (WIN32) |
|---|
| 66 | ulAttr = GetFileAttributes(filename); |
|---|
| 67 | if (ulAttr != TXINVALID) |
|---|
| 68 | { |
|---|
| 69 | if ((ulAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) |
|---|
| 70 | { |
|---|
| 71 | TxPrint("\nCannot create directory, a file '%s' exists ", filename); |
|---|
| 72 | rc = ERROR_FILE_EXISTS; // file with same name exists |
|---|
| 73 | } |
|---|
| 74 | } |
|---|
| 75 | else // not existing |
|---|
| 76 | { |
|---|
| 77 | rc = NO_ERROR; |
|---|
| 78 | if (strcmp(filename+1, ":")) // no bare drive specification |
|---|
| 79 | { |
|---|
| 80 | if ((p = TxStripBaseName(filename)) != NULL) // last component |
|---|
| 81 | { |
|---|
| 82 | rc = TxMakePath(filename); |
|---|
| 83 | *(--p) = FS_PATH_SEP; // join last part again |
|---|
| 84 | } |
|---|
| 85 | if (rc == NO_ERROR) |
|---|
| 86 | { |
|---|
| 87 | if (!CreateDirectory(filename, NULL)) // New, no security |
|---|
| 88 | { |
|---|
| 89 | rc = TX_ERROR; |
|---|
| 90 | } |
|---|
| 91 | } |
|---|
| 92 | } |
|---|
| 93 | } |
|---|
| 94 | #elif defined (DOS32) |
|---|
| 95 | rc = (ULONG) _dos_getfileattr(filename, &usAttr); |
|---|
| 96 | TRACES(("get attr, RC %lu, attr %hx on: '%s'\n", rc, usAttr, filename)); |
|---|
| 97 | if (rc == NO_ERROR) |
|---|
| 98 | { |
|---|
| 99 | if ((usAttr & _A_SUBDIR) == 0) // it is an existing file |
|---|
| 100 | { |
|---|
| 101 | TxPrint("\nCannot create directory, a file '%s' exists ", filename); |
|---|
| 102 | rc = ERROR_FILE_EXISTS; // file with same name exists |
|---|
| 103 | } |
|---|
| 104 | } |
|---|
| 105 | else // not existing |
|---|
| 106 | { |
|---|
| 107 | rc = NO_ERROR; |
|---|
| 108 | if (strcmp(filename+1, ":")) // no bare drive specification |
|---|
| 109 | { |
|---|
| 110 | if ((p = TxStripBaseName(filename)) != NULL) // find last component |
|---|
| 111 | { |
|---|
| 112 | rc = TxMakePath(filename); |
|---|
| 113 | *(--p) = FS_PATH_SEP; // join last part again |
|---|
| 114 | } |
|---|
| 115 | if (rc == NO_ERROR) |
|---|
| 116 | { |
|---|
| 117 | if (mkdir( filename) != 0) |
|---|
| 118 | { |
|---|
| 119 | rc = TX_ERROR; |
|---|
| 120 | } |
|---|
| 121 | } |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | #elif defined (LINUX) |
|---|
| 125 | //- to be refined |
|---|
| 126 | #else |
|---|
| 127 | rc = DosQPathInfo(filename, // Path string |
|---|
| 128 | FIL_STANDARD, // Path data required |
|---|
| 129 | &fstat, // Path data buffer |
|---|
| 130 | sizeof(fstat)); // Path data buffer size |
|---|
| 131 | TRACES(("DosQPathInfo, RC %lu on: '%s'\n", rc, filename)); |
|---|
| 132 | if (rc == NO_ERROR) |
|---|
| 133 | { |
|---|
| 134 | if ((fstat.attrFile & FILE_DIRECTORY) == 0) |
|---|
| 135 | { |
|---|
| 136 | TxPrint("\nCannot create directory, a file '%s' exists ", filename); |
|---|
| 137 | rc = ERROR_FILE_EXISTS; // file with same name exists |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | else |
|---|
| 141 | { |
|---|
| 142 | rc = NO_ERROR; |
|---|
| 143 | if (strcmp(filename+1, ":")) // no bare drive specification |
|---|
| 144 | { |
|---|
| 145 | if ((p = TxStripBaseName(filename)) != NULL) // find last component |
|---|
| 146 | { |
|---|
| 147 | rc = TxMakePath(filename); |
|---|
| 148 | *(--p) = FS_PATH_SEP; // join last part again |
|---|
| 149 | } |
|---|
| 150 | if (rc == NO_ERROR) |
|---|
| 151 | { |
|---|
| 152 | rc = DosMkDir(filename, NULL); // Create New, without EA's |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | #endif |
|---|
| 157 | RETURN (rc); |
|---|
| 158 | } // end 'TxMakePath' |
|---|
| 159 | /*---------------------------------------------------------------------------*/ |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | /*****************************************************************************/ |
|---|
| 163 | // Make an 8-dot-3 compatible copy of supplied path/filename string (no spaces) |
|---|
| 164 | /*****************************************************************************/ |
|---|
| 165 | ULONG TxMake8dot3 // RET length converted name |
|---|
| 166 | ( |
|---|
| 167 | char *filename, // IN relative/absolute path |
|---|
| 168 | char *fname8d3 // OUT 8dot3 compatible |
|---|
| 169 | ) |
|---|
| 170 | { |
|---|
| 171 | ULONG rc = 0; // return value |
|---|
| 172 | char *p = filename; // ptr in source name |
|---|
| 173 | char *d = fname8d3; // ptr in converted name |
|---|
| 174 | ULONG cs = 0; // checksum for segment |
|---|
| 175 | ULONG i = 0; // length converted part |
|---|
| 176 | |
|---|
| 177 | ENTER(); |
|---|
| 178 | |
|---|
| 179 | TRACES(("filename : '%s'\n", filename)); |
|---|
| 180 | do |
|---|
| 181 | { |
|---|
| 182 | if ((*p == '\\') || (*p == '/') || // end of any segment |
|---|
| 183 | (*p == ':') || (*p == 0)) |
|---|
| 184 | { |
|---|
| 185 | if (*p == ':') // end of drive part |
|---|
| 186 | { |
|---|
| 187 | cs = 0; // no cs on drive part |
|---|
| 188 | } |
|---|
| 189 | else if ((cs != 0) && (i > 8)) // add cs to converted ? |
|---|
| 190 | { // . plus 3 upcase hex digits |
|---|
| 191 | cs = ((cs ^ (cs >> 24)) &0xfff); // XOR and shuffle a bit |
|---|
| 192 | sprintf( d, ".%3.3lX", cs); |
|---|
| 193 | d += strlen(d); // advance to end of string |
|---|
| 194 | } |
|---|
| 195 | *d++ = *p; // copy character, convert space |
|---|
| 196 | i = 0; // reset count on next segment |
|---|
| 197 | cs = 0; // reset checksum |
|---|
| 198 | } |
|---|
| 199 | else // other characters |
|---|
| 200 | { |
|---|
| 201 | if (i < 8) |
|---|
| 202 | { |
|---|
| 203 | if (*p == '.') // dot in dir/file name |
|---|
| 204 | { |
|---|
| 205 | if (strcspn( p+1, "\\/") <= 3) // will be valid if total |
|---|
| 206 | { // stays 12 or less (8+1+3) |
|---|
| 207 | *d = '.'; // so keep the original dot |
|---|
| 208 | i = 4; // avoid conversion on next 3 |
|---|
| 209 | } |
|---|
| 210 | else // translate to '_' because |
|---|
| 211 | { // .XXX will be added for cs |
|---|
| 212 | *d = '_'; |
|---|
| 213 | i++; |
|---|
| 214 | } |
|---|
| 215 | } |
|---|
| 216 | else |
|---|
| 217 | { |
|---|
| 218 | *d = *p; // copy character |
|---|
| 219 | i++; |
|---|
| 220 | } |
|---|
| 221 | d++; // advance counter & dest |
|---|
| 222 | } |
|---|
| 223 | else // conversion will happen |
|---|
| 224 | { |
|---|
| 225 | if ((i == 8) && (*p == '.')) // dot in dir/file name |
|---|
| 226 | { |
|---|
| 227 | if (strcspn( p+1, "\\/") <= 3) // will be valid if total |
|---|
| 228 | { // stays 12 or less (8+1+3) |
|---|
| 229 | *d++ = '.'; // so keep the original dot |
|---|
| 230 | i = 4; // avoid conversion on next 3 |
|---|
| 231 | } |
|---|
| 232 | else // translate to '_' because |
|---|
| 233 | { // .XXX will be added for cs |
|---|
| 234 | *(d-3) = *(d-2); // shift last 2 chars back |
|---|
| 235 | *(d-2) = *(d-1); |
|---|
| 236 | if (*p == '.') |
|---|
| 237 | { |
|---|
| 238 | *(d-1) = '_'; |
|---|
| 239 | } |
|---|
| 240 | else |
|---|
| 241 | { |
|---|
| 242 | *(d-1) = *p; |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | i++; |
|---|
| 246 | rc = 1; // signal conversion made |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | else |
|---|
| 250 | { |
|---|
| 251 | *(d-3) = *(d-2); // shift last 2 chars back |
|---|
| 252 | *(d-2) = *(d-1); |
|---|
| 253 | if (*p == '.') |
|---|
| 254 | { |
|---|
| 255 | *(d-1) = '_'; |
|---|
| 256 | } |
|---|
| 257 | else |
|---|
| 258 | { |
|---|
| 259 | *(d-1) = *p; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | i++; |
|---|
| 263 | rc = 1; // signal conversion made |
|---|
| 264 | } |
|---|
| 265 | } |
|---|
| 266 | cs *= 2; // multiply by 2 |
|---|
| 267 | cs += *p; // add char to checksum |
|---|
| 268 | } |
|---|
| 269 | if (*p != 0) |
|---|
| 270 | { |
|---|
| 271 | p++; |
|---|
| 272 | } |
|---|
| 273 | } while ((*p != 0) || (i >= 8)); // until end and cs added |
|---|
| 274 | *d = 0; // always terminated |
|---|
| 275 | |
|---|
| 276 | TxRepl( fname8d3, ' ', '_'); // translate spaces |
|---|
| 277 | if (rc != 0) // conversion made ? |
|---|
| 278 | { |
|---|
| 279 | rc = strlen( fname8d3); |
|---|
| 280 | } |
|---|
| 281 | TRACES(("fname out: '%s'\n", fname8d3)); |
|---|
| 282 | RETURN (rc); |
|---|
| 283 | } // end 'TxMake8dot3' |
|---|
| 284 | /*---------------------------------------------------------------------------*/ |
|---|