FreeBASIC  0.91.0
file_dir.c
Go to the documentation of this file.
1 /* dir() */
2 
3 #include "../fb.h"
4 #ifndef HOST_CYGWIN
5  #include <direct.h>
6 #endif
7 #include <windows.h>
8 
9 typedef struct {
10  int in_use;
11  int attrib;
12 #ifdef HOST_CYGWIN
13  WIN32_FIND_DATA data;
14  HANDLE handle;
15 #else
16  struct _finddata_t data;
17  long handle;
18 #endif
19 } FB_DIRCTX;
20 
21 static void close_dir ( void )
22 {
23  FB_DIRCTX *ctx = FB_TLSGETCTX( DIR );
24 #ifdef HOST_MINGW
25  _findclose( ctx->handle );
26 #else
27  FindClose( ctx->handle );
28 #endif
29  ctx->in_use = FALSE;
30 }
31 
32 static char *find_next ( int *attrib )
33 {
34  char *name = NULL;
35  FB_DIRCTX *ctx = FB_TLSGETCTX( DIR );
36 
37 #ifdef HOST_MINGW
38  do
39  {
40  if( _findnext( ctx->handle, &ctx->data ) )
41  {
42  close_dir( );
43  name = NULL;
44  break;
45  }
46  name = ctx->data.name;
47  }
48  while( ctx->data.attrib & ~ctx->attrib );
49 
50  *attrib = ctx->data.attrib & ~0xFFFFFF00;
51 
52 #else
53  do {
54  if( !FindNextFile( ctx->handle, &ctx->data ) ) {
55  close_dir();
56  name = NULL;
57  break;
58  }
59  name = ctx->data.cFileName;
60  } while( ctx->data.dwFileAttributes & ~ctx->attrib );
61 
62  *attrib = ctx->data.dwFileAttributes & ~0xFFFFFF00;
63 #endif
64 
65  return name;
66 }
67 
68 FBCALL FBSTRING *fb_Dir( FBSTRING *filespec, int attrib, int *out_attrib )
69 {
70  FB_DIRCTX *ctx;
71  FBSTRING *res;
72  ssize_t len;
73  int tmp_attrib;
74  char *name;
75  int handle_ok;
76 
77  if( out_attrib == NULL )
78  out_attrib = &tmp_attrib;
79 
80  len = FB_STRSIZE( filespec );
81  name = NULL;
82 
83  ctx = FB_TLSGETCTX( DIR );
84 
85  if( len > 0 )
86  {
87  /* findfirst */
88  if( ctx->in_use )
89  close_dir( );
90 
91 #ifdef HOST_MINGW
92  ctx->handle = _findfirst( filespec->data, &ctx->data );
93  handle_ok = ctx->handle != -1;
94 #else
95  ctx->handle = FindFirstFile( filespec->data, &ctx->data );
96  handle_ok = ctx->handle != INVALID_HANDLE_VALUE;
97 #endif
98  if( handle_ok )
99  {
100  /* Handle any other possible bits different Windows versions could return */
101  ctx->attrib = attrib | 0xFFFFFF00;
102 
103  /* archive bit not set? set the dir bit at least.. */
104  if( (attrib & 0x10) == 0 )
105  ctx->attrib |= 0x20;
106 
107 #ifdef HOST_MINGW
108  if( ctx->data.attrib & ~ctx->attrib )
109  name = find_next( out_attrib );
110  else
111  {
112  name = ctx->data.name;
113  *out_attrib = ctx->data.attrib & ~0xFFFFFF00;
114  }
115 #else
116  if( ctx->data.dwFileAttributes & ~ctx->attrib )
117  name = find_next( out_attrib );
118  else
119  {
120  name = ctx->data.cFileName;
121  *out_attrib = ctx->data.dwFileAttributes & ~0xFFFFFF00;
122  }
123 #endif
124  if( name )
125  ctx->in_use = TRUE;
126  }
127  } else {
128  /* findnext */
129  if( ctx->in_use )
130  name = find_next( out_attrib );
131  }
132 
133  FB_STRLOCK();
134 
135  /* store filename if found */
136  if( name ) {
137  len = strlen( name );
138  res = fb_hStrAllocTemp_NoLock( NULL, len );
139  if( res )
140  fb_hStrCopy( res->data, name, len );
141  else
142  res = &__fb_ctx.null_desc;
143  } else {
144  res = &__fb_ctx.null_desc;
145  *out_attrib = 0;
146  }
147 
148  fb_hStrDelTemp_NoLock( filespec );
149 
150  FB_STRUNLOCK();
151 
152  return res;
153 }