root/trunk/txlib/txtname.c

Revision 1, 12.5 kB (checked in by jvw, 3 years ago)

Initial check-in for TxWin? version 1.02 sources

Line 
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, TrueName section
34//
35
36#include <txlib.h>                              // TxLib interface
37#include <txwpriv.h>                            // private window interface
38
39#include <sys/stat.h>                           // for low level stuff
40
41// Normalize relative path+filename specification (canonicalize)
42static char *TxFsRealPath                       // RET   resulting name (pfn)
43(
44   char               *pfn                      // INOUT path+filename (LINE)
45);
46
47
48/*****************************************************************************/
49// Query type for specified path and resolve truename (canonical)
50// Directorynames (for DIR or stripped filename) will ALWAYS end in a '\'
51/*****************************************************************************/
52ULONG  TxTrueNameDir                            // RET   0 = Dir, 80 = File
53(                                               //       others are errors
54   char               *path,                    // IN    path/fn specification
55   BOOL                stripfile,               // IN    strip filename part
56   char               *truename                 // OUT   true filename or NULL
57)
58{
59   ULONG               rc = TXTN_DIR;           // return value, dir
60   TXLN                pspec;                   // path/fn, modifyable
61   TXLN                tname;                   // True name, internal
62   int                 last;
63   #if   defined (WIN32)
64      ULONG            ulAttr;
65      char            *p;
66   #elif defined (DOS32)
67      union  REGS      regs;
68      struct SREGS     sreg;
69      TXDX_RMINFO      txdx_rmi;
70      char            *fn;
71      char            *tn;
72      struct stat      fstat;
73   #elif defined (LINUX)
74      struct stat      fstat;
75   #else
76      FILESTATUS3      fstat;
77   #endif
78
79   ENTER();
80   TRACES(("path: '%s'\n", path));
81   if (strlen(path) == 0)
82   {
83      strcpy( pspec, ".");                      // use current directory
84   }
85   else
86   {
87      strcpy( pspec, path);
88      last = strlen(pspec) -1;
89      if (pspec[ last] == FS_PATH_SEP)
90      {
91         if (((pspec[1] != ':') && (last > 1)) || (last > 2))
92         {
93            pspec[last] = '\0';                 // remove trailing \ from DIR
94         }
95      }
96   }
97   TRACES(("path: '%s' - pspec: '%s'\n", path, pspec));
98   #if defined (WIN32)
99      ulAttr = GetFileAttributes(pspec);
100      if (ulAttr != TXINVALID)
101      {
102         GetFullPathName( pspec, TXMAXLN, tname, &p);
103         if ((ulAttr & FILE_ATTRIBUTE_DIRECTORY) == 0)
104         {
105            if (stripfile)
106            {
107               TxStripBaseName( tname);
108            }
109            rc = TXTN_FILE;
110         }
111      }
112      else
113      {
114         if (stripfile)
115         {
116            TxStripBaseName( pspec);
117            if ((strlen(pspec) != 2) || (pspec[1] != ':'))
118            {
119               if (GetFullPathName(pspec, TXMAXLN, tname, &p) == 0)
120               {
121                  rc = TX_INVALID_DRIVE;
122               }
123            }
124            else                                // Root directory
125            {
126               strcpy( tname, pspec);
127            }
128         }
129      }
130   #elif defined (DOS32)
131      if ((txwa->dpmi1 != NULL) && (txwa->dpmi2 != NULL))
132      {                                         // proper TXinit/term
133         memset( txwa->dpmi1, 0, 512);
134         memset( txwa->dpmi2, 0, 512);
135         fn    = txwa->dpmi1;                   // DPMI compatible mem
136         tn    = txwa->dpmi2;                   // DPMI compatible mem
137
138         strcpy( fn, pspec);                    // filename IN
139
140         memset( &regs,  0, sizeof(regs));
141         memset( &sreg,  0, sizeof(sreg));
142
143         memset( &txdx_rmi, 0, sizeof(txdx_rmi));
144         txdx_rmi.eax = 0x6000;                 // Canonical filename AH=60
145         txdx_rmi.ds  = txDpmiSegment(fn);      // in  fname (ds:dx, dx=0)
146         txdx_rmi.es  = txDpmiSegment(tn);      // out tname (es:di, di=0)
147
148         TRHEXS( 100,  &txdx_rmi,  sizeof(txdx_rmi), "txdx_rmi");
149
150         regs.w.ax    = TXDX_DPMI_RMINT;        // simulate realmode INT
151         regs.h.bl    = TXDX_DOS;               // DOS interrupt 21
152         regs.x.edi   = FP_OFF( &txdx_rmi);     // real mode register struct
153         sreg.es      = FP_SEG( &txdx_rmi);
154
155         txDpmiCall( &regs, &sreg);
156
157         TRHEXS( 100,  txwa->dpmi2,  512, "dpmi2 (tname)");
158         TRACES(("regs.x.cflag:%4.4hx  ax:%4.4hx\n", regs.x.cflag, TXWORD.ax));
159
160         if (regs.x.cflag == 0)
161         {
162            if ((tn[0] == '\\') &&              // Hack to correct strange
163                (tn[1] == '\\') &&              // truename resolved for
164                (tn[2] != '\\') &&              // CDROM paths on FreeDOS
165                (tn[3] == '.')  &&              // using the generic driver
166                (tn[4] == '\\'))                // like: "\\O.\B." for "O:"
167            {
168               tname[0] = tn[2];                // driveletter
169               tname[1] = ':';
170               tname[2] = '\0';
171               strcat( tname, tn + 7);          // corrected truename OUT
172            }
173            else
174            {
175               strcpy( tname, tn);              // truename OUT
176            }
177            if (stat( tname, &fstat) == NO_ERROR)
178            {
179               if (S_ISREG(fstat.st_mode))      // regular file ?
180               {
181                  if (stripfile)
182                  {
183                     TxStripBaseName( tname);
184                  }
185                  rc = TXTN_FILE;
186               }
187            }
188            else
189            {
190               rc = ERROR_FILE_NOT_FOUND;
191            }
192         }
193         else
194         {
195            rc = TXWORD.ax;
196         }
197      }
198   #elif defined (LINUX)
199      strcpy( tname, TxFsRealPath(pspec));      // canonicalized
200      if (stat( tname, &fstat) == NO_ERROR)
201      {
202         if (S_ISREG(fstat.st_mode))            // regular file ?
203         {
204            rc = TXTN_FILE;
205         }
206      }
207      else if ((errno == EFBIG) ||              // must be a large-file
208               (errno == EOVERFLOW))
209      {
210         rc = TXTN_FILE;
211      }
212      else
213      {
214         rc = ERROR_FILE_NOT_FOUND;
215      }
216      if (rc == TXTN_FILE)
217      {
218         if (stripfile)
219         {
220            TxStripBaseName( tname);
221         }
222      }
223   #else
224      rc = DosQPathInfo(pspec,                  // Path string
225                        FIL_STANDARD,           // Path data required
226                        &fstat,                 // Path data buffer
227                        sizeof(fstat));         // Path data buffer size
228      TRACES(("DosQPathInfo '%s' FIL_STANDARD rc: %lu\n", pspec, rc));
229      switch (rc)
230      {
231         case NO_ERROR:
232            rc = DosQPathInfo( pspec,  FIL_QUERYFULLNAME, tname, TXMAXLN);
233            TRACES(("DosQPathInfo '%s' FIL_QUERYFULLNAME rc: %lu\n", pspec, rc));
234            TRACES(("resolved name from API: '%s'\n", tname));
235            if ((fstat.attrFile & FILE_DIRECTORY) == 0)
236            {
237               if (stripfile)
238               {
239                  TxStripBaseName( tname);
240               }
241               rc = TXTN_FILE;
242            }
243            break;
244
245         case ERROR_INVALID_PATH:               // wildcard or root
246            if (stripfile)
247            {
248               TxStripBaseName( pspec);
249               if ((strlen(pspec) != 2) || (pspec[1] != ':'))
250               {
251                  rc = DosQPathInfo( pspec,  FIL_QUERYFULLNAME, tname, TXMAXLN);
252                  TRACES(("DosQPathInfo '%s' FIL_QUERYFULLNAME rc: %lu\n", pspec, rc));
253                  TRACES(("resolved name from API: '%s'\n", tname));
254               }
255               else                             // Root directory
256               {
257                  strcpy( tname, pspec);
258                  rc = TXTN_DIR;
259               }
260            }
261            break;
262
263         default:
264            strcpy( tname, "");                 // return empty name
265            break;
266      }
267   #endif
268   TRACES(("tname: '%s'\n", tname));
269   if (truename != NULL)                        // return the name ?
270   {
271      strcpy( truename, tname);
272      if (((rc == TXTN_DIR) || stripfile) &&
273          (truename[strlen(truename)-1] != FS_PATH_SEP))
274      {
275         strcat( truename, FS_PATH_STR);
276      }
277      TRACES(("true : '%s'\n", truename));
278   }
279   RETURN (rc);
280}                                               // end 'TxTrueNameDir'
281/*---------------------------------------------------------------------------*/
282
283
284#if defined (LINUX)
285/*****************************************************************************/
286// Normalize relative path+filename specification (canonicalize)
287/*****************************************************************************/
288static char *TxFsRealPath                       // RET   resulting name (pfn)
289(
290   char               *pfn                      // INOUT path+filename (LINE)
291)
292{
293   char               *s, *p;                   // search pointers
294   TXLN                prefix;
295   TXTS                token;
296
297   ENTER();
298
299   TRACES(( "Starting  pfn: '%s'\n", pfn));
300   if (*pfn == FS_PATH_SEP)                     // first is root, absolute
301   {
302      strcpy( prefix, "");
303   }
304   else
305   {
306      getcwd( prefix, TXMAXLN);
307   }
308   if (*pfn == '.')
309   {
310      strcat( prefix, pfn +1);
311   }
312   else
313   {
314      if (*pfn != FS_PATH_SEP)                  // no root yet
315      {
316         strcat( prefix, FS_PATH_STR);
317      }
318      strcat( prefix, pfn);
319   }
320   strcpy( pfn, prefix);
321   TRACES(( "Cleanup   pfn: '%s'\n", pfn));
322
323   sprintf( token, "%c..", FS_PATH_SEP);        // parent directory token
324   while ((s = strstr( pfn, token)) != NULL)
325   {
326      if (s == pfn)                             // pfn IS token /..
327      {
328         strcpy( pfn, "");                      // remove it
329      }
330      else                                      // token embedded in path
331      {
332         for (p = s-1; (p > pfn) && (*p != FS_PATH_SEP); p--)
333         {
334            //- search backward to path separator
335         }
336         memcpy( p, s+3, strlen(s+3) +1);       // remove "xx/.." residues
337      }
338      if (strlen(pfn) == 0)                     // found the root, empty now
339      {
340         strcpy( pfn, FS_PATH_STR);             // leave single root char
341      }
342      TRACES(( "Cleaned   pfn: '%s' using token '%s'\n", pfn, token));
343   }
344   sprintf( token, ".%c", FS_PATH_SEP);         // current directory token
345   while ((s = strstr( pfn, token)) != NULL)
346   {
347      memcpy( s, s+2, strlen(s+2) +1);          // remove "./" residues
348      TRACES(( "Cleaned   pfn: '%s' using token '%s'\n", pfn, token));
349   }
350   TRACES(( "Resulting pfn: '%s'\n", pfn));
351   RETURN (pfn);
352}                                               // end '*TxFsRealPath'
353/*---------------------------------------------------------------------------*/
354#endif
Note: See TracBrowser for help on using the browser.