~peter-pearse/ubuntu/natty/guile-1.8/prop001

« back to all changes in this revision

Viewing changes to libguile/filesys.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schepler
  • Date: 2006-11-09 03:11:16 UTC
  • Revision ID: james.westby@ubuntu.com-20061109031116-hu0q1jxqg12y6yeg
Tags: upstream-1.8.1+1
ImportĀ upstreamĀ versionĀ 1.8.1+1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002, 2004, 2006 Free Software Foundation, Inc.
 
2
 * 
 
3
 * This library is free software; you can redistribute it and/or
 
4
 * modify it under the terms of the GNU Lesser General Public
 
5
 * License as published by the Free Software Foundation; either
 
6
 * version 2.1 of the License, or (at your option) any later version.
 
7
 *
 
8
 * This library is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public
 
14
 * License along with this library; if not, write to the Free Software
 
15
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 */
 
17
 
 
18
 
 
19
 
 
20
 
 
21
/* See stime.c for comments on why _POSIX_C_SOURCE is not always defined. */
 
22
#define _GNU_SOURCE              /* ask glibc for everything */
 
23
#define _LARGEFILE64_SOURCE      /* ask for stat64 etc */
 
24
#ifdef __hpux
 
25
#define _POSIX_C_SOURCE 199506L  /* for readdir_r */
 
26
#endif
 
27
 
 
28
#if HAVE_CONFIG_H
 
29
#  include <config.h>
 
30
#endif
 
31
 
 
32
/* This blob per the Autoconf manual (under "Particular Functions"). */
 
33
#if HAVE_ALLOCA_H
 
34
# include <alloca.h>
 
35
#elif defined __GNUC__
 
36
# define alloca __builtin_alloca
 
37
#elif defined _AIX
 
38
# define alloca __alloca
 
39
#elif defined _MSC_VER
 
40
# include <malloc.h>
 
41
# define alloca _alloca
 
42
#else
 
43
# include <stddef.h>
 
44
# ifdef  __cplusplus
 
45
extern "C"
 
46
# endif
 
47
void *alloca (size_t);
 
48
#endif
 
49
 
 
50
#include <stdio.h>
 
51
#include <errno.h>
 
52
 
 
53
#include "libguile/_scm.h"
 
54
#include "libguile/smob.h"
 
55
#include "libguile/feature.h"
 
56
#include "libguile/fports.h"
 
57
#include "libguile/private-gc.h"  /* for SCM_MAX */
 
58
#include "libguile/iselect.h"
 
59
#include "libguile/strings.h"
 
60
#include "libguile/vectors.h"
 
61
#include "libguile/lang.h"
 
62
#include "libguile/dynwind.h"
 
63
 
 
64
#include "libguile/validate.h"
 
65
#include "libguile/filesys.h"
 
66
 
 
67
 
 
68
#ifdef HAVE_IO_H
 
69
#include <io.h>
 
70
#endif
 
71
 
 
72
#ifdef HAVE_DIRECT_H
 
73
#include <direct.h>
 
74
#endif
 
75
 
 
76
#ifdef TIME_WITH_SYS_TIME
 
77
# include <sys/time.h>
 
78
# include <time.h>
 
79
#else
 
80
# if HAVE_SYS_TIME_H
 
81
#  include <sys/time.h>
 
82
# else
 
83
#  include <time.h>
 
84
# endif
 
85
#endif
 
86
 
 
87
#ifdef HAVE_UNISTD_H
 
88
#include <unistd.h>
 
89
#endif
 
90
 
 
91
#ifdef LIBC_H_WITH_UNISTD_H
 
92
#include <libc.h>
 
93
#endif
 
94
 
 
95
#ifdef HAVE_SYS_SELECT_H
 
96
#include <sys/select.h>
 
97
#endif
 
98
 
 
99
#ifdef HAVE_STRING_H
 
100
#include <string.h>
 
101
#endif
 
102
 
 
103
#include <sys/types.h>
 
104
#include <sys/stat.h>
 
105
#include <fcntl.h>
 
106
 
 
107
#ifdef HAVE_PWD_H
 
108
#include <pwd.h>
 
109
#endif
 
110
 
 
111
 
 
112
#if defined (__MINGW32__) || defined (_MSC_VER) || defined (__BORLANDC__)
 
113
# include "win32-dirent.h"
 
114
# define NAMLEN(dirent) strlen((dirent)->d_name)
 
115
/* The following bits are per AC_HEADER_DIRENT doco in the autoconf manual */
 
116
#elif HAVE_DIRENT_H
 
117
# include <dirent.h>
 
118
# define NAMLEN(dirent) strlen((dirent)->d_name)
 
119
#else
 
120
# define dirent direct
 
121
# define NAMLEN(dirent) (dirent)->d_namlen
 
122
# if HAVE_SYS_NDIR_H
 
123
#  include <sys/ndir.h>
 
124
# endif
 
125
# if HAVE_SYS_DIR_H
 
126
#  include <sys/dir.h>
 
127
# endif
 
128
# if HAVE_NDIR_H
 
129
#  include <ndir.h>
 
130
# endif
 
131
#endif
 
132
 
 
133
/* Ultrix has S_IFSOCK, but no S_ISSOCK.  Ipe!  */
 
134
#if defined (S_IFSOCK) && ! defined (S_ISSOCK)
 
135
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
 
136
#endif
 
137
 
 
138
/* The MinGW gcc does not define the S_ISSOCK macro. Any other native Windows
 
139
   compiler like BorlandC or MSVC has none of these macros defined. */
 
140
#ifdef __MINGW32__
 
141
 
 
142
# ifdef _S_IFIFO
 
143
#  undef _S_IFIFO
 
144
# endif
 
145
# ifdef _S_IFCHR
 
146
#  undef _S_IFCHR
 
147
# endif
 
148
# ifdef _S_IFBLK
 
149
#  undef _S_IFBLK
 
150
# endif
 
151
# ifdef _S_IFDIR
 
152
#  undef _S_IFDIR
 
153
# endif
 
154
# ifdef _S_IFREG
 
155
#  undef _S_IFREG
 
156
# endif
 
157
# ifdef _S_IFSOCK
 
158
#  undef _S_IFSOCK
 
159
# endif
 
160
 
 
161
# define _S_IFIFO        0x1000  /* FIFO */
 
162
# define _S_IFCHR        0x2000  /* Character */
 
163
# define _S_IFBLK        0x3000  /* Block */
 
164
# define _S_IFDIR        0x4000  /* Directory */
 
165
# define _S_IFREG        0x8000  /* Regular */
 
166
# define _S_IFSOCK       0xC000  /* Socket */
 
167
 
 
168
# ifdef S_ISBLK
 
169
#  undef S_ISBLK
 
170
# endif
 
171
# ifdef S_ISFIFO
 
172
#  undef S_ISFIFO
 
173
# endif
 
174
# ifdef S_ISCHR
 
175
#  undef S_ISCHR
 
176
# endif
 
177
# ifdef S_ISDIR
 
178
#  undef S_ISDIR
 
179
# endif
 
180
# ifdef S_ISREG
 
181
#  undef S_ISREG
 
182
# endif
 
183
# ifdef S_ISSOCK
 
184
#  undef S_ISSOCK
 
185
# endif
 
186
 
 
187
# define S_ISBLK(mode)  (((mode) & _S_IFMT) == _S_IFBLK)
 
188
# define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
 
189
# define S_ISCHR(mode)  (((mode) & _S_IFMT) == _S_IFCHR)
 
190
# define S_ISDIR(mode)  (((mode) & _S_IFMT) == _S_IFDIR)
 
191
# define S_ISREG(mode)  (((mode) & _S_IFMT) == _S_IFREG)
 
192
# define S_ISSOCK(mode) (((mode) & _S_IFMT) == _S_IFSOCK)
 
193
 
 
194
#endif /* __MINGW32__ */
 
195
 
 
196
/* Some more definitions for the native Windows port. */
 
197
#ifdef __MINGW32__
 
198
# define mkdir(path, mode) mkdir (path)
 
199
# define fsync(fd) _commit (fd)
 
200
# define fchmod(fd, mode) (-1)
 
201
#endif /* __MINGW32__ */
 
202
 
 
203
/* dirfd() returns the file descriptor underlying a "DIR*" directory stream.
 
204
   Found on MacOS X for instance.  The following definition is for Solaris
 
205
   10, it's probably not right elsewhere, but that's ok, it shouldn't be
 
206
   used elsewhere.  Crib note: If we need more then gnulib has a dirfd.m4
 
207
   figuring out how to get the fd (dirfd function, dirfd macro, dd_fd field,
 
208
   or d_fd field).  */
 
209
#ifndef dirfd
 
210
#define dirfd(dirstream) ((dirstream)->dd_fd)
 
211
#endif
 
212
 
 
213
 
 
214
 
 
215
/* Two helper macros for an often used pattern */
 
216
 
 
217
#define STRING_SYSCALL(str,cstr,code)        \
 
218
  do {                                       \
 
219
    int eno;                                 \
 
220
    char *cstr = scm_to_locale_string (str); \
 
221
    SCM_SYSCALL (code);                      \
 
222
    eno = errno; free (cstr); errno = eno;   \
 
223
  } while (0)
 
224
 
 
225
#define STRING2_SYSCALL(str1,cstr1,str2,cstr2,code)  \
 
226
  do {                                               \
 
227
    int eno;                                         \
 
228
    char *cstr1, *cstr2;                             \
 
229
    scm_dynwind_begin (0);                             \
 
230
    cstr1 = scm_to_locale_string (str1);             \
 
231
    scm_dynwind_free (cstr1);                          \
 
232
    cstr2 = scm_to_locale_string (str2);             \
 
233
    scm_dynwind_free (cstr2);                          \
 
234
    SCM_SYSCALL (code);                              \
 
235
    eno = errno; scm_dynwind_end (); errno = eno;      \
 
236
  } while (0)
 
237
 
 
238
 
 
239
 
 
240
/* {Permissions}
 
241
 */
 
242
 
 
243
#ifdef HAVE_CHOWN
 
244
SCM_DEFINE (scm_chown, "chown", 3, 0, 0, 
 
245
            (SCM object, SCM owner, SCM group),
 
246
            "Change the ownership and group of the file referred to by @var{object} to\n"
 
247
            "the integer values @var{owner} and @var{group}.  @var{object} can be\n"
 
248
            "a string containing a file name or, if the platform\n"
 
249
            "supports fchown, a port or integer file descriptor\n"
 
250
            "which is open on the file.  The return value\n"
 
251
            "is unspecified.\n\n"
 
252
            "If @var{object} is a symbolic link, either the\n"
 
253
            "ownership of the link or the ownership of the referenced file will be\n"
 
254
            "changed depending on the operating system (lchown is\n"
 
255
            "unsupported at present).  If @var{owner} or @var{group} is specified\n"
 
256
            "as @code{-1}, then that ID is not changed.")
 
257
#define FUNC_NAME s_scm_chown
 
258
{
 
259
  int rv;
 
260
 
 
261
  object = SCM_COERCE_OUTPORT (object);
 
262
 
 
263
#ifdef HAVE_FCHOWN
 
264
  if (scm_is_integer (object) || (SCM_OPFPORTP (object)))
 
265
    {
 
266
      int fdes = (SCM_OPFPORTP (object)?
 
267
                  SCM_FPORT_FDES (object) : scm_to_int (object));
 
268
 
 
269
      SCM_SYSCALL (rv = fchown (fdes, scm_to_int (owner), scm_to_int (group)));
 
270
    }
 
271
  else
 
272
#endif
 
273
    {
 
274
      STRING_SYSCALL (object, c_object,
 
275
                      rv = chown (c_object,
 
276
                                  scm_to_int (owner), scm_to_int (group)));
 
277
    }
 
278
  if (rv == -1)
 
279
    SCM_SYSERROR;
 
280
  return SCM_UNSPECIFIED;
 
281
}
 
282
#undef FUNC_NAME
 
283
#endif /* HAVE_CHOWN */
 
284
 
 
285
 
 
286
SCM_DEFINE (scm_chmod, "chmod", 2, 0, 0,
 
287
            (SCM object, SCM mode),
 
288
            "Changes the permissions of the file referred to by @var{obj}.\n"
 
289
            "@var{obj} can be a string containing a file name or a port or integer file\n"
 
290
            "descriptor which is open on a file (in which case @code{fchmod} is used\n"
 
291
            "as the underlying system call).\n"
 
292
            "@var{mode} specifies\n"
 
293
            "the new permissions as a decimal number, e.g., @code{(chmod \"foo\" #o755)}.\n"
 
294
            "The return value is unspecified.")
 
295
#define FUNC_NAME s_scm_chmod
 
296
{
 
297
  int rv;
 
298
  int fdes;
 
299
 
 
300
  object = SCM_COERCE_OUTPORT (object);
 
301
 
 
302
  if (scm_is_integer (object) || SCM_OPFPORTP (object))
 
303
    {
 
304
      if (scm_is_integer (object))
 
305
        fdes = scm_to_int (object);
 
306
      else
 
307
        fdes = SCM_FPORT_FDES (object);
 
308
      SCM_SYSCALL (rv = fchmod (fdes, scm_to_int (mode)));
 
309
    }
 
310
  else
 
311
    {
 
312
      STRING_SYSCALL (object, c_object,
 
313
                      rv = chmod (c_object, scm_to_int (mode)));
 
314
    }
 
315
  if (rv == -1)
 
316
    SCM_SYSERROR;
 
317
  return SCM_UNSPECIFIED;
 
318
}
 
319
#undef FUNC_NAME
 
320
 
 
321
SCM_DEFINE (scm_umask, "umask", 0, 1, 0, 
 
322
            (SCM mode),
 
323
            "If @var{mode} is omitted, returns a decimal number representing the current\n"
 
324
            "file creation mask.  Otherwise the file creation mask is set to\n"
 
325
            "@var{mode} and the previous value is returned.\n\n"
 
326
            "E.g., @code{(umask #o022)} sets the mask to octal 22, decimal 18.")
 
327
#define FUNC_NAME s_scm_umask
 
328
{
 
329
  mode_t mask;
 
330
  if (SCM_UNBNDP (mode))
 
331
    {
 
332
      mask = umask (0);
 
333
      umask (mask);
 
334
    }
 
335
  else
 
336
    {
 
337
      mask = umask (scm_to_uint (mode));
 
338
    }
 
339
  return scm_from_uint (mask);
 
340
}
 
341
#undef FUNC_NAME
 
342
 
 
343
 
 
344
 
 
345
SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0, 
 
346
            (SCM path, SCM flags, SCM mode),
 
347
            "Similar to @code{open} but return a file descriptor instead of\n"
 
348
            "a port.")
 
349
#define FUNC_NAME s_scm_open_fdes
 
350
{
 
351
  int fd;
 
352
  int iflags;
 
353
  int imode;
 
354
 
 
355
  iflags = SCM_NUM2INT (2, flags);
 
356
  imode = SCM_NUM2INT_DEF (3, mode, 0666);
 
357
  STRING_SYSCALL (path, c_path, fd = open_or_open64 (c_path, iflags, imode));
 
358
  if (fd == -1)
 
359
    SCM_SYSERROR;
 
360
  return scm_from_int (fd);
 
361
}
 
362
#undef FUNC_NAME
 
363
 
 
364
SCM_DEFINE (scm_open, "open", 2, 1, 0, 
 
365
            (SCM path, SCM flags, SCM mode),
 
366
            "Open the file named by @var{path} for reading and/or writing.\n"
 
367
            "@var{flags} is an integer specifying how the file should be opened.\n"
 
368
            "@var{mode} is an integer specifying the permission bits of the file, if\n"
 
369
            "it needs to be created, before the umask is applied.  The default is 666\n"
 
370
            "(Unix itself has no default).\n\n"
 
371
            "@var{flags} can be constructed by combining variables using @code{logior}.\n"
 
372
            "Basic flags are:\n\n"
 
373
            "@defvar O_RDONLY\n"
 
374
            "Open the file read-only.\n"
 
375
            "@end defvar\n"
 
376
            "@defvar O_WRONLY\n"
 
377
            "Open the file write-only.\n"
 
378
            "@end defvar\n"
 
379
            "@defvar O_RDWR\n"
 
380
            "Open the file read/write.\n"
 
381
            "@end defvar\n"
 
382
            "@defvar O_APPEND\n"
 
383
            "Append to the file instead of truncating.\n"
 
384
            "@end defvar\n"
 
385
            "@defvar O_CREAT\n"
 
386
            "Create the file if it does not already exist.\n"
 
387
            "@end defvar\n\n"
 
388
            "See the Unix documentation of the @code{open} system call\n"
 
389
            "for additional flags.")
 
390
#define FUNC_NAME s_scm_open
 
391
{
 
392
  SCM newpt;
 
393
  char *port_mode;
 
394
  int fd;
 
395
  int iflags;
 
396
 
 
397
  fd = scm_to_int (scm_open_fdes (path, flags, mode));
 
398
  iflags = SCM_NUM2INT (2, flags);
 
399
  if (iflags & O_RDWR)
 
400
    {
 
401
      if (iflags & O_APPEND)
 
402
        port_mode = "a+";
 
403
      else if (iflags & O_CREAT)
 
404
        port_mode = "w+";
 
405
      else
 
406
        port_mode = "r+";
 
407
    }
 
408
  else {
 
409
    if (iflags & O_APPEND)
 
410
      port_mode = "a";
 
411
    else if (iflags & O_WRONLY)
 
412
      port_mode = "w";
 
413
    else
 
414
      port_mode = "r";
 
415
  }
 
416
  newpt = scm_fdes_to_port (fd, port_mode, path);
 
417
  return newpt;
 
418
}
 
419
#undef FUNC_NAME
 
420
 
 
421
SCM_DEFINE (scm_close, "close", 1, 0, 0, 
 
422
            (SCM fd_or_port),
 
423
            "Similar to close-port (@pxref{Closing, close-port}),\n"
 
424
            "but also works on file descriptors.  A side\n"
 
425
            "effect of closing a file descriptor is that any ports using that file\n"
 
426
            "descriptor are moved to a different file descriptor and have\n"
 
427
            "their revealed counts set to zero.")
 
428
#define FUNC_NAME s_scm_close
 
429
{
 
430
  int rv;
 
431
  int fd;
 
432
 
 
433
  fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
 
434
 
 
435
  if (SCM_PORTP (fd_or_port))
 
436
    return scm_close_port (fd_or_port);
 
437
  fd = scm_to_int (fd_or_port);
 
438
  scm_evict_ports (fd);         /* see scsh manual.  */
 
439
  SCM_SYSCALL (rv = close (fd));
 
440
  /* following scsh, closing an already closed file descriptor is
 
441
     not an error.  */
 
442
  if (rv < 0 && errno != EBADF)
 
443
    SCM_SYSERROR;
 
444
  return scm_from_bool (rv >= 0);
 
445
}
 
446
#undef FUNC_NAME
 
447
 
 
448
SCM_DEFINE (scm_close_fdes, "close-fdes", 1, 0, 0, 
 
449
            (SCM fd),
 
450
            "A simple wrapper for the @code{close} system call.\n"
 
451
            "Close file descriptor @var{fd}, which must be an integer.\n"
 
452
            "Unlike close (@pxref{Ports and File Descriptors, close}),\n"
 
453
            "the file descriptor will be closed even if a port is using it.\n"
 
454
            "The return value is unspecified.")
 
455
#define FUNC_NAME s_scm_close_fdes
 
456
{
 
457
  int c_fd;
 
458
  int rv;
 
459
 
 
460
  c_fd = scm_to_int (fd);
 
461
  SCM_SYSCALL (rv = close (c_fd));
 
462
  if (rv < 0)
 
463
    SCM_SYSERROR;
 
464
  return SCM_UNSPECIFIED;
 
465
}
 
466
#undef FUNC_NAME
 
467
 
 
468
 
 
469
/* {Files}
 
470
 */
 
471
 
 
472
SCM_SYMBOL (scm_sym_regular, "regular");
 
473
SCM_SYMBOL (scm_sym_directory, "directory");
 
474
#ifdef S_ISLNK
 
475
SCM_SYMBOL (scm_sym_symlink, "symlink");
 
476
#endif
 
477
SCM_SYMBOL (scm_sym_block_special, "block-special");
 
478
SCM_SYMBOL (scm_sym_char_special, "char-special");
 
479
SCM_SYMBOL (scm_sym_fifo, "fifo");
 
480
SCM_SYMBOL (scm_sym_sock, "socket");
 
481
SCM_SYMBOL (scm_sym_unknown, "unknown");
 
482
 
 
483
static SCM 
 
484
scm_stat2scm (struct stat_or_stat64 *stat_temp)
 
485
{
 
486
  SCM ans = scm_c_make_vector (15, SCM_UNSPECIFIED);
 
487
  
 
488
  SCM_SIMPLE_VECTOR_SET(ans, 0, scm_from_ulong (stat_temp->st_dev));
 
489
  SCM_SIMPLE_VECTOR_SET(ans, 1, scm_from_ino_t_or_ino64_t (stat_temp->st_ino));
 
490
  SCM_SIMPLE_VECTOR_SET(ans, 2, scm_from_ulong (stat_temp->st_mode));
 
491
  SCM_SIMPLE_VECTOR_SET(ans, 3, scm_from_ulong (stat_temp->st_nlink));
 
492
  SCM_SIMPLE_VECTOR_SET(ans, 4, scm_from_ulong (stat_temp->st_uid));
 
493
  SCM_SIMPLE_VECTOR_SET(ans, 5, scm_from_ulong (stat_temp->st_gid));
 
494
#ifdef HAVE_STRUCT_STAT_ST_RDEV
 
495
  SCM_SIMPLE_VECTOR_SET(ans, 6, scm_from_ulong (stat_temp->st_rdev));
 
496
#else
 
497
  SCM_SIMPLE_VECTOR_SET(ans, 6, SCM_BOOL_F);
 
498
#endif
 
499
  SCM_SIMPLE_VECTOR_SET(ans, 7, scm_from_off_t_or_off64_t (stat_temp->st_size));
 
500
  SCM_SIMPLE_VECTOR_SET(ans, 8, scm_from_ulong (stat_temp->st_atime));
 
501
  SCM_SIMPLE_VECTOR_SET(ans, 9, scm_from_ulong (stat_temp->st_mtime));
 
502
  SCM_SIMPLE_VECTOR_SET(ans, 10, scm_from_ulong (stat_temp->st_ctime));
 
503
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
 
504
  SCM_SIMPLE_VECTOR_SET(ans, 11, scm_from_ulong (stat_temp->st_blksize));
 
505
#else
 
506
  SCM_SIMPLE_VECTOR_SET(ans, 11, scm_from_ulong (4096L));
 
507
#endif
 
508
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
 
509
  SCM_SIMPLE_VECTOR_SET(ans, 12, scm_from_blkcnt_t_or_blkcnt64_t (stat_temp->st_blocks));
 
510
#else
 
511
  SCM_SIMPLE_VECTOR_SET(ans, 12, SCM_BOOL_F);
 
512
#endif
 
513
  {
 
514
    int mode = stat_temp->st_mode;
 
515
    
 
516
    if (S_ISREG (mode))
 
517
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_regular);
 
518
    else if (S_ISDIR (mode))
 
519
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_directory);
 
520
#ifdef S_ISLNK
 
521
    /* systems without symlinks probably don't have S_ISLNK */
 
522
    else if (S_ISLNK (mode))
 
523
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_symlink);
 
524
#endif
 
525
    else if (S_ISBLK (mode))
 
526
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_block_special);
 
527
    else if (S_ISCHR (mode))
 
528
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_char_special);
 
529
    else if (S_ISFIFO (mode))
 
530
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_fifo);
 
531
#ifdef S_ISSOCK
 
532
    else if (S_ISSOCK (mode))
 
533
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_sock);
 
534
#endif
 
535
    else
 
536
      SCM_SIMPLE_VECTOR_SET(ans, 13, scm_sym_unknown);
 
537
 
 
538
    SCM_SIMPLE_VECTOR_SET(ans, 14, scm_from_int ((~S_IFMT) & mode));
 
539
 
 
540
    /* the layout of the bits in ve[14] is intended to be portable.
 
541
       If there are systems that don't follow the usual convention,
 
542
       the following could be used:
 
543
 
 
544
       tmp = 0;
 
545
       if (S_ISUID & mode) tmp += 1;
 
546
       tmp <<= 1;
 
547
       if (S_IRGRP & mode) tmp += 1;
 
548
       tmp <<= 1;
 
549
       if (S_ISVTX & mode) tmp += 1;
 
550
       tmp <<= 1;
 
551
       if (S_IRUSR & mode) tmp += 1;
 
552
       tmp <<= 1;
 
553
       if (S_IWUSR & mode) tmp += 1;
 
554
       tmp <<= 1;
 
555
       if (S_IXUSR & mode) tmp += 1;
 
556
       tmp <<= 1;
 
557
       if (S_IWGRP & mode) tmp += 1;
 
558
       tmp <<= 1;
 
559
       if (S_IXGRP & mode) tmp += 1;
 
560
       tmp <<= 1;
 
561
       if (S_IROTH & mode) tmp += 1;
 
562
       tmp <<= 1;
 
563
       if (S_IWOTH & mode) tmp += 1;
 
564
       tmp <<= 1;
 
565
       if (S_IXOTH & mode) tmp += 1; 
 
566
 
 
567
       SCM_SIMPLE_VECTOR_SET(ans, 14, scm_from_int (tmp));
 
568
       
 
569
       */
 
570
  }  
 
571
 
 
572
  return ans;
 
573
}
 
574
 
 
575
#ifdef __MINGW32__
 
576
/*
 
577
 * Try getting the appropiate stat buffer for a given file descriptor
 
578
 * under Windows. It differentiates between file, pipe and socket 
 
579
 * descriptors.
 
580
 */
 
581
static int fstat_Win32 (int fdes, struct stat *buf)
 
582
{
 
583
  int error, optlen = sizeof (int);
 
584
 
 
585
  memset (buf, 0, sizeof (struct stat));
 
586
 
 
587
  /* Is this a socket ? */
 
588
  if (getsockopt (fdes, SOL_SOCKET, SO_ERROR, (void *) &error, &optlen) >= 0)
 
589
    {
 
590
      buf->st_mode = _S_IFSOCK | _S_IREAD | _S_IWRITE | _S_IEXEC;
 
591
      buf->st_nlink = 1;
 
592
      buf->st_atime = buf->st_ctime = buf->st_mtime = time (NULL);
 
593
      return 0;
 
594
    }
 
595
  /* Maybe a regular file or pipe ? */
 
596
  return fstat (fdes, buf);
 
597
}
 
598
#endif /* __MINGW32__ */
 
599
 
 
600
SCM_DEFINE (scm_stat, "stat", 1, 0, 0, 
 
601
            (SCM object),
 
602
            "Return an object containing various information about the file\n"
 
603
            "determined by @var{obj}.  @var{obj} can be a string containing\n"
 
604
            "a file name or a port or integer file descriptor which is open\n"
 
605
            "on a file (in which case @code{fstat} is used as the underlying\n"
 
606
            "system call).\n"
 
607
            "\n"
 
608
            "The object returned by @code{stat} can be passed as a single\n"
 
609
            "parameter to the following procedures, all of which return\n"
 
610
            "integers:\n"
 
611
            "\n"
 
612
            "@table @code\n"
 
613
            "@item stat:dev\n"
 
614
            "The device containing the file.\n"
 
615
            "@item stat:ino\n"
 
616
            "The file serial number, which distinguishes this file from all\n"
 
617
            "other files on the same device.\n"
 
618
            "@item stat:mode\n"
 
619
            "The mode of the file.  This includes file type information and\n"
 
620
            "the file permission bits.  See @code{stat:type} and\n"
 
621
            "@code{stat:perms} below.\n"
 
622
            "@item stat:nlink\n"
 
623
            "The number of hard links to the file.\n"
 
624
            "@item stat:uid\n"
 
625
            "The user ID of the file's owner.\n"
 
626
            "@item stat:gid\n"
 
627
            "The group ID of the file.\n"
 
628
            "@item stat:rdev\n"
 
629
            "Device ID; this entry is defined only for character or block\n"
 
630
            "special files.\n"
 
631
            "@item stat:size\n"
 
632
            "The size of a regular file in bytes.\n"
 
633
            "@item stat:atime\n"
 
634
            "The last access time for the file.\n"
 
635
            "@item stat:mtime\n"
 
636
            "The last modification time for the file.\n"
 
637
            "@item stat:ctime\n"
 
638
            "The last modification time for the attributes of the file.\n"
 
639
            "@item stat:blksize\n"
 
640
            "The optimal block size for reading or writing the file, in\n"
 
641
            "bytes.\n"
 
642
            "@item stat:blocks\n"
 
643
            "The amount of disk space that the file occupies measured in\n"
 
644
            "units of 512 byte blocks.\n"
 
645
            "@end table\n"
 
646
            "\n"
 
647
            "In addition, the following procedures return the information\n"
 
648
            "from stat:mode in a more convenient form:\n"
 
649
            "\n"
 
650
            "@table @code\n"
 
651
            "@item stat:type\n"
 
652
            "A symbol representing the type of file.  Possible values are\n"
 
653
            "regular, directory, symlink, block-special, char-special, fifo,\n"
 
654
            "socket and unknown\n"
 
655
            "@item stat:perms\n"
 
656
            "An integer representing the access permission bits.\n"
 
657
            "@end table")
 
658
#define FUNC_NAME s_scm_stat
 
659
{
 
660
  int rv;
 
661
  int fdes;
 
662
  struct stat_or_stat64 stat_temp;
 
663
 
 
664
  if (scm_is_integer (object))
 
665
    {
 
666
#ifdef __MINGW32__
 
667
      SCM_SYSCALL (rv = fstat_Win32 (scm_to_int (object), &stat_temp));
 
668
#else
 
669
      SCM_SYSCALL (rv = fstat_or_fstat64 (scm_to_int (object), &stat_temp));
 
670
#endif
 
671
    }
 
672
  else if (scm_is_string (object))
 
673
    {
 
674
      char *file = scm_to_locale_string (object);
 
675
#ifdef __MINGW32__
 
676
      char *p;
 
677
      p = file + strlen (file) - 1;
 
678
      while (p > file && (*p == '/' || *p == '\\'))
 
679
        *p-- = '\0';
 
680
#endif
 
681
      SCM_SYSCALL (rv = stat_or_stat64 (file, &stat_temp));
 
682
      free (file);
 
683
    }
 
684
  else
 
685
    {
 
686
      object = SCM_COERCE_OUTPORT (object);
 
687
      SCM_VALIDATE_OPFPORT (1, object);
 
688
      fdes = SCM_FPORT_FDES (object);
 
689
#ifdef __MINGW32__
 
690
      SCM_SYSCALL (rv = fstat_Win32 (fdes, &stat_temp));
 
691
#else
 
692
      SCM_SYSCALL (rv = fstat_or_fstat64 (fdes, &stat_temp));
 
693
#endif
 
694
    }
 
695
 
 
696
  if (rv == -1)
 
697
    {
 
698
      int en = errno;
 
699
 
 
700
      SCM_SYSERROR_MSG ("~A: ~S",
 
701
                        scm_list_2 (scm_strerror (scm_from_int (en)),
 
702
                                    object),
 
703
                        en);
 
704
    }
 
705
  return scm_stat2scm (&stat_temp);
 
706
}
 
707
#undef FUNC_NAME
 
708
 
 
709
 
 
710
/* {Modifying Directories}
 
711
 */
 
712
 
 
713
#ifdef HAVE_LINK
 
714
SCM_DEFINE (scm_link, "link", 2, 0, 0,
 
715
            (SCM oldpath, SCM newpath),
 
716
            "Creates a new name @var{newpath} in the file system for the\n"
 
717
            "file named by @var{oldpath}.  If @var{oldpath} is a symbolic\n"
 
718
            "link, the link may or may not be followed depending on the\n"
 
719
            "system.")
 
720
#define FUNC_NAME s_scm_link
 
721
{
 
722
  int val;
 
723
 
 
724
  STRING2_SYSCALL (oldpath, c_oldpath,
 
725
                   newpath, c_newpath,
 
726
                   val = link (c_oldpath, c_newpath));
 
727
  if (val != 0)
 
728
    SCM_SYSERROR;
 
729
  return SCM_UNSPECIFIED;
 
730
}
 
731
#undef FUNC_NAME
 
732
#endif /* HAVE_LINK */
 
733
 
 
734
#ifdef HAVE_RENAME
 
735
#define my_rename rename
 
736
#else
 
737
static int
 
738
my_rename (const char *oldname, const char *newname)
 
739
{
 
740
  int rv;
 
741
 
 
742
  SCM_SYSCALL (rv = link (oldname, newname));
 
743
  if (rv == 0)
 
744
    {
 
745
      SCM_SYSCALL (rv = unlink (oldname));
 
746
      if (rv != 0)
 
747
        /* unlink failed.  remove new name */
 
748
        SCM_SYSCALL (unlink (newname)); 
 
749
    }
 
750
  return rv;
 
751
}
 
752
#endif
 
753
 
 
754
SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
 
755
            (SCM oldname, SCM newname),
 
756
            "Renames the file specified by @var{oldname} to @var{newname}.\n"
 
757
            "The return value is unspecified.")
 
758
#define FUNC_NAME s_scm_rename
 
759
{
 
760
  int rv;
 
761
 
 
762
  STRING2_SYSCALL (oldname, c_oldname,
 
763
                   newname, c_newname,
 
764
                   rv = my_rename (c_oldname, c_newname));
 
765
  if (rv != 0)
 
766
    SCM_SYSERROR;
 
767
  return SCM_UNSPECIFIED;
 
768
}
 
769
#undef FUNC_NAME
 
770
 
 
771
 
 
772
SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0, 
 
773
           (SCM str),
 
774
            "Deletes (or \"unlinks\") the file specified by @var{path}.")
 
775
#define FUNC_NAME s_scm_delete_file
 
776
{
 
777
  int ans;
 
778
  STRING_SYSCALL (str, c_str, ans = unlink (c_str));
 
779
  if (ans != 0)
 
780
    SCM_SYSERROR;
 
781
  return SCM_UNSPECIFIED;
 
782
}
 
783
#undef FUNC_NAME
 
784
 
 
785
#ifdef HAVE_MKDIR
 
786
SCM_DEFINE (scm_mkdir, "mkdir", 1, 1, 0,
 
787
            (SCM path, SCM mode),
 
788
            "Create a new directory named by @var{path}.  If @var{mode} is omitted\n"
 
789
            "then the permissions of the directory file are set using the current\n"
 
790
            "umask.  Otherwise they are set to the decimal value specified with\n"
 
791
            "@var{mode}.  The return value is unspecified.")
 
792
#define FUNC_NAME s_scm_mkdir
 
793
{
 
794
  int rv;
 
795
  mode_t mask;
 
796
 
 
797
  if (SCM_UNBNDP (mode))
 
798
    {
 
799
      mask = umask (0);
 
800
      umask (mask);
 
801
      STRING_SYSCALL (path, c_path, rv = mkdir (c_path, 0777 ^ mask));
 
802
    }
 
803
  else
 
804
    {
 
805
      STRING_SYSCALL (path, c_path, rv = mkdir (c_path, scm_to_uint (mode)));
 
806
    }
 
807
  if (rv != 0)
 
808
    SCM_SYSERROR;
 
809
  return SCM_UNSPECIFIED;
 
810
}
 
811
#undef FUNC_NAME
 
812
#endif /* HAVE_MKDIR */
 
813
 
 
814
#ifdef HAVE_RMDIR
 
815
SCM_DEFINE (scm_rmdir, "rmdir", 1, 0, 0, 
 
816
            (SCM path),
 
817
            "Remove the existing directory named by @var{path}.  The directory must\n"
 
818
            "be empty for this to succeed.  The return value is unspecified.")
 
819
#define FUNC_NAME s_scm_rmdir
 
820
{
 
821
  int val;
 
822
 
 
823
  STRING_SYSCALL (path, c_path, val = rmdir (c_path));
 
824
  if (val != 0)
 
825
    SCM_SYSERROR;
 
826
  return SCM_UNSPECIFIED;
 
827
}
 
828
#undef FUNC_NAME
 
829
#endif
 
830
 
 
831
 
 
832
 
 
833
/* {Examining Directories}
 
834
 */
 
835
 
 
836
scm_t_bits scm_tc16_dir;
 
837
 
 
838
 
 
839
SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0, 
 
840
            (SCM obj),
 
841
            "Return a boolean indicating whether @var{object} is a directory\n"
 
842
            "stream as returned by @code{opendir}.")
 
843
#define FUNC_NAME s_scm_directory_stream_p
 
844
{
 
845
  return scm_from_bool (SCM_DIRP (obj));
 
846
}
 
847
#undef FUNC_NAME
 
848
 
 
849
 
 
850
SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0, 
 
851
            (SCM dirname),
 
852
            "Open the directory specified by @var{path} and return a directory\n"
 
853
            "stream.")
 
854
#define FUNC_NAME s_scm_opendir
 
855
{
 
856
  DIR *ds;
 
857
  STRING_SYSCALL (dirname, c_dirname, ds = opendir (c_dirname));
 
858
  if (ds == NULL)
 
859
    SCM_SYSERROR;
 
860
  SCM_RETURN_NEWSMOB (scm_tc16_dir | SCM_DIR_FLAG_OPEN, ds);
 
861
}
 
862
#undef FUNC_NAME
 
863
 
 
864
 
 
865
/* FIXME: The glibc manual has a portability note that readdir_r may not
 
866
   null-terminate its return string.  The circumstances outlined for this
 
867
   are not clear, nor is it clear what should be done about it.  Lets use
 
868
   NAMLEN and worry about what else should be done if/when someone can
 
869
   figure it out.  */
 
870
 
 
871
SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0, 
 
872
            (SCM port),
 
873
            "Return (as a string) the next directory entry from the directory stream\n"
 
874
            "@var{stream}.  If there is no remaining entry to be read then the\n"
 
875
            "end of file object is returned.")
 
876
#define FUNC_NAME s_scm_readdir
 
877
{
 
878
  struct dirent_or_dirent64 *rdent;
 
879
 
 
880
  SCM_VALIDATE_DIR (1, port);
 
881
  if (!SCM_DIR_OPEN_P (port))
 
882
    SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
 
883
 
 
884
#if HAVE_READDIR_R
 
885
  /* As noted in the glibc manual, on various systems (such as Solaris) the
 
886
     d_name[] field is only 1 char and you're expected to size the dirent
 
887
     buffer for readdir_r based on NAME_MAX.  The SCM_MAX expressions below
 
888
     effectively give either sizeof(d_name) or NAME_MAX+1, whichever is
 
889
     bigger.
 
890
 
 
891
     On solaris 10 there's no NAME_MAX constant, it's necessary to use
 
892
     pathconf().  We prefer NAME_MAX though, since it should be a constant
 
893
     and will therefore save a system call.  We also prefer it since dirfd()
 
894
     is not available everywhere.
 
895
 
 
896
     An alternative to dirfd() would be to open() the directory and then use
 
897
     fdopendir(), if the latter is available.  That'd let us hold the fd
 
898
     somewhere in the smob, or just the dirent size calculated once.  */
 
899
  {
 
900
    struct dirent_or_dirent64 de; /* just for sizeof */
 
901
    DIR    *ds = (DIR *) SCM_CELL_WORD_1 (port);
 
902
    size_t namlen;
 
903
#ifdef NAME_MAX
 
904
    char   buf [SCM_MAX (sizeof (de),
 
905
                         sizeof (de) - sizeof (de.d_name) + NAME_MAX + 1)];
 
906
#else
 
907
    char   *buf;
 
908
    long   name_max = fpathconf (dirfd (ds), _PC_NAME_MAX);
 
909
    if (name_max == -1)
 
910
      SCM_SYSERROR;
 
911
    buf = alloca (SCM_MAX (sizeof (de),
 
912
                           sizeof (de) - sizeof (de.d_name) + name_max + 1));
 
913
#endif
 
914
 
 
915
    errno = 0;
 
916
    SCM_SYSCALL (readdir_r_or_readdir64_r (ds, (struct dirent_or_dirent64 *) buf, &rdent));
 
917
    if (errno != 0)
 
918
      SCM_SYSERROR;
 
919
    if (! rdent)
 
920
      return SCM_EOF_VAL;
 
921
 
 
922
    namlen = NAMLEN (rdent);
 
923
 
 
924
    return (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
 
925
            : SCM_EOF_VAL);
 
926
  }
 
927
#else
 
928
  {
 
929
    SCM ret;
 
930
    scm_dynwind_begin (0);
 
931
    scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
 
932
 
 
933
    errno = 0;
 
934
    SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_CELL_WORD_1 (port)));
 
935
    if (errno != 0)
 
936
      SCM_SYSERROR;
 
937
 
 
938
    ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
 
939
           : SCM_EOF_VAL);
 
940
 
 
941
    scm_dynwind_end ();
 
942
    return ret;
 
943
  }
 
944
#endif
 
945
}
 
946
#undef FUNC_NAME
 
947
 
 
948
 
 
949
SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0, 
 
950
            (SCM port),
 
951
            "Reset the directory port @var{stream} so that the next call to\n"
 
952
            "@code{readdir} will return the first directory entry.")
 
953
#define FUNC_NAME s_scm_rewinddir
 
954
{
 
955
  SCM_VALIDATE_DIR (1, port);
 
956
  if (!SCM_DIR_OPEN_P (port))
 
957
    SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
 
958
 
 
959
  rewinddir ((DIR *) SCM_CELL_WORD_1 (port));
 
960
 
 
961
  return SCM_UNSPECIFIED;
 
962
}
 
963
#undef FUNC_NAME
 
964
 
 
965
 
 
966
SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0, 
 
967
            (SCM port),
 
968
            "Close the directory stream @var{stream}.\n"
 
969
            "The return value is unspecified.")
 
970
#define FUNC_NAME s_scm_closedir
 
971
{
 
972
  SCM_VALIDATE_DIR (1, port);
 
973
 
 
974
  if (SCM_DIR_OPEN_P (port))
 
975
    {
 
976
      int sts;
 
977
 
 
978
      SCM_SYSCALL (sts = closedir ((DIR *) SCM_CELL_WORD_1 (port)));
 
979
      if (sts != 0)
 
980
        SCM_SYSERROR;
 
981
 
 
982
      SCM_SET_CELL_WORD_0 (port, scm_tc16_dir);
 
983
    }
 
984
 
 
985
  return SCM_UNSPECIFIED;
 
986
}
 
987
#undef FUNC_NAME
 
988
 
 
989
 
 
990
static int 
 
991
scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
 
992
{
 
993
  scm_puts ("#<", port);
 
994
  if (!SCM_DIR_OPEN_P (exp))
 
995
    scm_puts ("closed: ", port);
 
996
  scm_puts ("directory stream ", port);
 
997
  scm_uintprint (SCM_CELL_WORD_1 (exp), 16, port);
 
998
  scm_putc ('>', port);
 
999
  return 1;
 
1000
}
 
1001
 
 
1002
 
 
1003
static size_t 
 
1004
scm_dir_free (SCM p)
 
1005
{
 
1006
  if (SCM_DIR_OPEN_P (p))
 
1007
    closedir ((DIR *) SCM_CELL_WORD_1 (p));
 
1008
  return 0;
 
1009
}
 
1010
 
 
1011
 
 
1012
/* {Navigating Directories}
 
1013
 */
 
1014
 
 
1015
 
 
1016
SCM_DEFINE (scm_chdir, "chdir", 1, 0, 0, 
 
1017
            (SCM str),
 
1018
            "Change the current working directory to @var{path}.\n"
 
1019
            "The return value is unspecified.")
 
1020
#define FUNC_NAME s_scm_chdir
 
1021
{
 
1022
  int ans;
 
1023
 
 
1024
  STRING_SYSCALL (str, c_str, ans = chdir (c_str));
 
1025
  if (ans != 0)
 
1026
    SCM_SYSERROR;
 
1027
  return SCM_UNSPECIFIED;
 
1028
}
 
1029
#undef FUNC_NAME
 
1030
 
 
1031
#ifdef HAVE_GETCWD
 
1032
SCM_DEFINE (scm_getcwd, "getcwd", 0, 0, 0,
 
1033
            (),
 
1034
            "Return the name of the current working directory.")
 
1035
#define FUNC_NAME s_scm_getcwd
 
1036
{
 
1037
  char *rv;
 
1038
  size_t size = 100;
 
1039
  char *wd;
 
1040
  SCM result;
 
1041
 
 
1042
  wd = scm_malloc (size);
 
1043
  while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
 
1044
    {
 
1045
      free (wd);
 
1046
      size *= 2;
 
1047
      wd = scm_malloc (size);
 
1048
    }
 
1049
  if (rv == 0)
 
1050
    {
 
1051
      int save_errno = errno;
 
1052
      free (wd);
 
1053
      errno = save_errno;
 
1054
      SCM_SYSERROR;
 
1055
    }
 
1056
  result = scm_from_locale_stringn (wd, strlen (wd));
 
1057
  free (wd);
 
1058
  return result;
 
1059
}
 
1060
#undef FUNC_NAME
 
1061
#endif /* HAVE_GETCWD */
 
1062
 
 
1063
 
 
1064
 
 
1065
#ifdef HAVE_SELECT
 
1066
 
 
1067
/* check that element is a port or file descriptor.  if it's a port
 
1068
   and its buffer is ready for use, add it to the ports_ready list.
 
1069
   otherwise add its file descriptor to *set.  the type of list can be
 
1070
   determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
 
1071
   SCM_ARG3 for excepts.  */
 
1072
static int
 
1073
set_element (SELECT_TYPE *set, SCM *ports_ready, SCM element, int pos)
 
1074
{
 
1075
  int fd;
 
1076
 
 
1077
  if (scm_is_integer (element))
 
1078
    {
 
1079
      fd = scm_to_int (element);
 
1080
    }
 
1081
  else
 
1082
    {
 
1083
      int use_buf = 0;
 
1084
 
 
1085
      element = SCM_COERCE_OUTPORT (element);
 
1086
      SCM_ASSERT (SCM_OPFPORTP (element), element, pos, "select");
 
1087
      if (pos == SCM_ARG1)
 
1088
        {
 
1089
          /* check whether port has buffered input.  */
 
1090
          scm_t_port *pt = SCM_PTAB_ENTRY (element);
 
1091
      
 
1092
          if (pt->read_pos < pt->read_end)
 
1093
            use_buf = 1;
 
1094
        }
 
1095
      else if (pos == SCM_ARG2)
 
1096
        {
 
1097
          /* check whether port's output buffer has room.  */
 
1098
          scm_t_port *pt = SCM_PTAB_ENTRY (element);
 
1099
 
 
1100
          /* > 1 since writing the last byte in the buffer causes flush.  */
 
1101
          if (pt->write_end - pt->write_pos > 1)
 
1102
            use_buf = 1;
 
1103
        }
 
1104
      fd = use_buf ? -1 : SCM_FPORT_FDES (element);
 
1105
    }
 
1106
  if (fd == -1)
 
1107
    *ports_ready = scm_cons (element, *ports_ready);
 
1108
  else
 
1109
    FD_SET (fd, set);
 
1110
  return fd;
 
1111
}
 
1112
 
 
1113
/* check list_or_vec, a list or vector of ports or file descriptors,
 
1114
   adding each member to either the ports_ready list (if it's a port
 
1115
   with a usable buffer) or to *set.  the kind of list_or_vec can be
 
1116
   determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
 
1117
   SCM_ARG3 for excepts.  */
 
1118
static int
 
1119
fill_select_type (SELECT_TYPE *set, SCM *ports_ready, SCM list_or_vec, int pos)
 
1120
{
 
1121
  int max_fd = 0;
 
1122
 
 
1123
  if (scm_is_simple_vector (list_or_vec))
 
1124
    {
 
1125
      int i = SCM_SIMPLE_VECTOR_LENGTH (list_or_vec);
 
1126
      
 
1127
      while (--i >= 0)
 
1128
        {
 
1129
          int fd = set_element (set, ports_ready,
 
1130
                                SCM_SIMPLE_VECTOR_REF (list_or_vec, i), pos);
 
1131
 
 
1132
          if (fd > max_fd)
 
1133
            max_fd = fd;
 
1134
        }
 
1135
    }
 
1136
  else
 
1137
    {
 
1138
      while (!SCM_NULL_OR_NIL_P (list_or_vec))
 
1139
        {
 
1140
          int fd = set_element (set, ports_ready, SCM_CAR (list_or_vec), pos);
 
1141
 
 
1142
          if (fd > max_fd)
 
1143
            max_fd = fd;
 
1144
          list_or_vec = SCM_CDR (list_or_vec);
 
1145
        }
 
1146
    }
 
1147
 
 
1148
  return max_fd;
 
1149
}
 
1150
 
 
1151
/* if element (a file descriptor or port) appears in *set, cons it to
 
1152
   list.  return list.  */
 
1153
static SCM
 
1154
get_element (SELECT_TYPE *set, SCM element, SCM list)
 
1155
{
 
1156
  int fd;
 
1157
 
 
1158
  if (scm_is_integer (element))
 
1159
    {
 
1160
      fd = scm_to_int (element);
 
1161
    }
 
1162
  else
 
1163
    {
 
1164
      fd = SCM_FPORT_FDES (SCM_COERCE_OUTPORT (element));
 
1165
    }
 
1166
  if (FD_ISSET (fd, set))
 
1167
    list = scm_cons (element, list);
 
1168
  return list;
 
1169
}
 
1170
 
 
1171
/* construct component of scm_select return value.
 
1172
   set: pointer to set of file descriptors found by select to be ready
 
1173
   ports_ready: ports ready due to buffering
 
1174
   list_or_vec: original list/vector handed to scm_select.
 
1175
   the return value is a list/vector of ready ports/file descriptors. 
 
1176
   works by finding the objects in list which correspond to members of
 
1177
   *set and appending them to ports_ready.  result is converted to a
 
1178
   vector if list_or_vec is a vector.  */
 
1179
static SCM 
 
1180
retrieve_select_type (SELECT_TYPE *set, SCM ports_ready, SCM list_or_vec)
 
1181
{
 
1182
  SCM answer_list = ports_ready;
 
1183
 
 
1184
  if (scm_is_simple_vector (list_or_vec))
 
1185
    {
 
1186
      int i = SCM_SIMPLE_VECTOR_LENGTH (list_or_vec);
 
1187
 
 
1188
      while (--i >= 0)
 
1189
        {
 
1190
          answer_list = get_element (set,
 
1191
                                     SCM_SIMPLE_VECTOR_REF (list_or_vec, i),
 
1192
                                     answer_list);
 
1193
        }
 
1194
      return scm_vector (answer_list);
 
1195
    }
 
1196
  else
 
1197
    {
 
1198
      /* list_or_vec must be a list.  */
 
1199
      while (!SCM_NULL_OR_NIL_P (list_or_vec))
 
1200
        {
 
1201
          answer_list = get_element (set, SCM_CAR (list_or_vec), answer_list);
 
1202
          list_or_vec = SCM_CDR (list_or_vec);
 
1203
        }
 
1204
      return answer_list;
 
1205
    }
 
1206
}
 
1207
 
 
1208
/* Static helper functions above refer to s_scm_select directly as s_select */
 
1209
SCM_DEFINE (scm_select, "select", 3, 2, 0, 
 
1210
            (SCM reads, SCM writes, SCM excepts, SCM secs, SCM usecs),
 
1211
            "This procedure has a variety of uses: waiting for the ability\n"
 
1212
            "to provide input, accept output, or the existence of\n"
 
1213
            "exceptional conditions on a collection of ports or file\n"
 
1214
            "descriptors, or waiting for a timeout to occur.\n"
 
1215
            "It also returns if interrupted by a signal.\n\n"
 
1216
            "@var{reads}, @var{writes} and @var{excepts} can be lists or\n"
 
1217
            "vectors, with each member a port or a file descriptor.\n"
 
1218
            "The value returned is a list of three corresponding\n"
 
1219
            "lists or vectors containing only the members which meet the\n"
 
1220
            "specified requirement.  The ability of port buffers to\n"
 
1221
            "provide input or accept output is taken into account.\n"
 
1222
            "Ordering of the input lists or vectors is not preserved.\n\n"
 
1223
            "The optional arguments @var{secs} and @var{usecs} specify the\n"
 
1224
            "timeout.  Either @var{secs} can be specified alone, as\n"
 
1225
            "either an integer or a real number, or both @var{secs} and\n"
 
1226
            "@var{usecs} can be specified as integers, in which case\n"
 
1227
            "@var{usecs} is an additional timeout expressed in\n"
 
1228
            "microseconds.  If @var{secs} is omitted or is @code{#f} then\n"
 
1229
            "select will wait for as long as it takes for one of the other\n"
 
1230
            "conditions to be satisfied.\n\n"
 
1231
            "The scsh version of @code{select} differs as follows:\n"
 
1232
            "Only vectors are accepted for the first three arguments.\n"
 
1233
            "The @var{usecs} argument is not supported.\n"
 
1234
            "Multiple values are returned instead of a list.\n"
 
1235
            "Duplicates in the input vectors appear only once in output.\n"
 
1236
            "An additional @code{select!} interface is provided.")
 
1237
#define FUNC_NAME s_scm_select
 
1238
{
 
1239
  struct timeval timeout;
 
1240
  struct timeval * time_ptr;
 
1241
  SELECT_TYPE read_set;
 
1242
  SELECT_TYPE write_set;
 
1243
  SELECT_TYPE except_set;
 
1244
  int read_count;
 
1245
  int write_count;
 
1246
  int except_count;
 
1247
  /* these lists accumulate ports which are ready due to buffering.
 
1248
     their file descriptors don't need to be added to the select sets.  */
 
1249
  SCM read_ports_ready = SCM_EOL;
 
1250
  SCM write_ports_ready = SCM_EOL;
 
1251
  int max_fd;
 
1252
 
 
1253
  if (scm_is_simple_vector (reads))
 
1254
    {
 
1255
      read_count = SCM_SIMPLE_VECTOR_LENGTH (reads);
 
1256
    }
 
1257
  else
 
1258
    {
 
1259
      read_count = scm_ilength (reads);
 
1260
      SCM_ASSERT (read_count >= 0, reads, SCM_ARG1, FUNC_NAME);
 
1261
    }
 
1262
  if (scm_is_simple_vector (writes))
 
1263
    {
 
1264
      write_count = SCM_SIMPLE_VECTOR_LENGTH (writes);
 
1265
    }
 
1266
  else
 
1267
    {
 
1268
      write_count = scm_ilength (writes);
 
1269
      SCM_ASSERT (write_count >= 0, writes, SCM_ARG2, FUNC_NAME);
 
1270
    }
 
1271
  if (scm_is_simple_vector (excepts))
 
1272
    {
 
1273
      except_count = SCM_SIMPLE_VECTOR_LENGTH (excepts);
 
1274
    }
 
1275
  else
 
1276
    {
 
1277
      except_count = scm_ilength (excepts);
 
1278
      SCM_ASSERT (except_count >= 0, excepts, SCM_ARG3, FUNC_NAME);
 
1279
    }
 
1280
 
 
1281
  FD_ZERO (&read_set);
 
1282
  FD_ZERO (&write_set);
 
1283
  FD_ZERO (&except_set);
 
1284
 
 
1285
  max_fd = fill_select_type (&read_set, &read_ports_ready, reads, SCM_ARG1);
 
1286
 
 
1287
  {
 
1288
    int write_max = fill_select_type (&write_set, &write_ports_ready, 
 
1289
                                      writes, SCM_ARG2);
 
1290
    int except_max = fill_select_type (&except_set, NULL,
 
1291
                                       excepts, SCM_ARG3);
 
1292
 
 
1293
    if (write_max > max_fd)
 
1294
      max_fd = write_max;
 
1295
    if (except_max > max_fd)
 
1296
      max_fd = except_max;
 
1297
  }
 
1298
 
 
1299
  /* if there's a port with a ready buffer, don't block, just
 
1300
     check for ready file descriptors.  */
 
1301
  if (!scm_is_null (read_ports_ready) || !scm_is_null (write_ports_ready))
 
1302
    {
 
1303
      timeout.tv_sec = 0;
 
1304
      timeout.tv_usec = 0;
 
1305
      time_ptr = &timeout;
 
1306
    }
 
1307
  else if (SCM_UNBNDP (secs) || scm_is_false (secs))
 
1308
    time_ptr = 0;
 
1309
  else
 
1310
    {
 
1311
      if (scm_is_unsigned_integer (secs, 0, ULONG_MAX))
 
1312
        {
 
1313
          timeout.tv_sec = scm_to_ulong (secs);
 
1314
          if (SCM_UNBNDP (usecs))
 
1315
            timeout.tv_usec = 0;
 
1316
          else
 
1317
            timeout.tv_usec = scm_to_long (usecs);
 
1318
        }
 
1319
      else
 
1320
        {
 
1321
          double fl = scm_to_double (secs);
 
1322
 
 
1323
          if (!SCM_UNBNDP (usecs))
 
1324
            SCM_WRONG_TYPE_ARG (4, secs);
 
1325
          if (fl > LONG_MAX)
 
1326
            SCM_OUT_OF_RANGE (4, secs);
 
1327
          timeout.tv_sec = (long) fl;
 
1328
          timeout.tv_usec = (long) ((fl - timeout.tv_sec) * 1000000);
 
1329
        }
 
1330
      time_ptr = &timeout;
 
1331
    }
 
1332
 
 
1333
  {
 
1334
    int rv = scm_std_select (max_fd + 1,
 
1335
                             &read_set, &write_set, &except_set,
 
1336
                             time_ptr);
 
1337
    if (rv < 0)
 
1338
      SCM_SYSERROR;
 
1339
  }
 
1340
  return scm_list_3 (retrieve_select_type (&read_set, read_ports_ready, reads),
 
1341
                     retrieve_select_type (&write_set, write_ports_ready, writes),
 
1342
                     retrieve_select_type (&except_set, SCM_EOL, excepts));
 
1343
}
 
1344
#undef FUNC_NAME
 
1345
#endif /* HAVE_SELECT */
 
1346
 
 
1347
 
 
1348
 
 
1349
#ifdef HAVE_FCNTL
 
1350
SCM_DEFINE (scm_fcntl, "fcntl", 2, 1, 0,
 
1351
            (SCM object, SCM cmd, SCM value),
 
1352
            "Apply @var{command} to the specified file descriptor or the underlying\n"
 
1353
            "file descriptor of the specified port.  @var{value} is an optional\n"
 
1354
            "integer argument.\n\n"
 
1355
            "Values for @var{command} are:\n\n"
 
1356
            "@table @code\n"
 
1357
            "@item F_DUPFD\n"
 
1358
            "Duplicate a file descriptor\n"
 
1359
            "@item F_GETFD\n"
 
1360
            "Get flags associated with the file descriptor.\n"
 
1361
            "@item F_SETFD\n"
 
1362
            "Set flags associated with the file descriptor to @var{value}.\n"
 
1363
            "@item F_GETFL\n"
 
1364
            "Get flags associated with the open file.\n"
 
1365
            "@item F_SETFL\n"
 
1366
            "Set flags associated with the open file to @var{value}\n"
 
1367
            "@item F_GETOWN\n"
 
1368
            "Get the process ID of a socket's owner, for @code{SIGIO} signals.\n"
 
1369
            "@item F_SETOWN\n"
 
1370
            "Set the process that owns a socket to @var{value}, for @code{SIGIO} signals.\n"
 
1371
            "@item FD_CLOEXEC\n"
 
1372
            "The value used to indicate the \"close on exec\" flag with @code{F_GETFL} or\n"
 
1373
            "@code{F_SETFL}.\n"
 
1374
            "@end table")
 
1375
#define FUNC_NAME s_scm_fcntl
 
1376
{
 
1377
  int rv;
 
1378
  int fdes;
 
1379
  int ivalue;
 
1380
 
 
1381
  object = SCM_COERCE_OUTPORT (object);
 
1382
 
 
1383
  if (SCM_OPFPORTP (object))
 
1384
    fdes = SCM_FPORT_FDES (object);
 
1385
  else
 
1386
    fdes = scm_to_int (object);
 
1387
 
 
1388
  if (SCM_UNBNDP (value))
 
1389
    ivalue = 0;
 
1390
  else
 
1391
    ivalue = scm_to_int (value);
 
1392
 
 
1393
  SCM_SYSCALL (rv = fcntl (fdes, scm_to_int (cmd), ivalue));
 
1394
  if (rv == -1)
 
1395
    SCM_SYSERROR;
 
1396
  return scm_from_int (rv);
 
1397
}
 
1398
#undef FUNC_NAME
 
1399
#endif /* HAVE_FCNTL */
 
1400
 
 
1401
SCM_DEFINE (scm_fsync, "fsync", 1, 0, 0, 
 
1402
            (SCM object),
 
1403
            "Copies any unwritten data for the specified output file descriptor to disk.\n"
 
1404
            "If @var{port/fd} is a port, its buffer is flushed before the underlying\n"
 
1405
            "file descriptor is fsync'd.\n"
 
1406
            "The return value is unspecified.")
 
1407
#define FUNC_NAME s_scm_fsync
 
1408
{
 
1409
  int fdes;
 
1410
 
 
1411
  object = SCM_COERCE_OUTPORT (object);
 
1412
 
 
1413
  if (SCM_OPFPORTP (object))
 
1414
    {
 
1415
      scm_flush (object);
 
1416
      fdes = SCM_FPORT_FDES (object);
 
1417
    }
 
1418
  else
 
1419
    fdes = scm_to_int (object);
 
1420
 
 
1421
  if (fsync (fdes) == -1)
 
1422
    SCM_SYSERROR;
 
1423
  return SCM_UNSPECIFIED;
 
1424
}
 
1425
#undef FUNC_NAME
 
1426
 
 
1427
#ifdef HAVE_SYMLINK
 
1428
SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0,
 
1429
            (SCM oldpath, SCM newpath),
 
1430
            "Create a symbolic link named @var{path-to} with the value (i.e., pointing to)\n"
 
1431
            "@var{path-from}.  The return value is unspecified.")
 
1432
#define FUNC_NAME s_scm_symlink
 
1433
{
 
1434
  int val;
 
1435
 
 
1436
  STRING2_SYSCALL (oldpath, c_oldpath,
 
1437
                   newpath, c_newpath,
 
1438
                   val = symlink (c_oldpath, c_newpath));
 
1439
  if (val != 0)
 
1440
    SCM_SYSERROR;
 
1441
  return SCM_UNSPECIFIED;
 
1442
}
 
1443
#undef FUNC_NAME
 
1444
#endif /* HAVE_SYMLINK */
 
1445
 
 
1446
#ifdef HAVE_READLINK
 
1447
SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0, 
 
1448
            (SCM path),
 
1449
            "Return the value of the symbolic link named by @var{path} (a\n"
 
1450
            "string), i.e., the file that the link points to.")
 
1451
#define FUNC_NAME s_scm_readlink
 
1452
{
 
1453
  int rv;
 
1454
  int size = 100;
 
1455
  char *buf;
 
1456
  SCM result;
 
1457
  char *c_path;
 
1458
  
 
1459
  scm_dynwind_begin (0);
 
1460
 
 
1461
  c_path = scm_to_locale_string (path);
 
1462
  scm_dynwind_free (c_path);
 
1463
 
 
1464
  buf = scm_malloc (size);
 
1465
 
 
1466
  while ((rv = readlink (c_path, buf, size)) == size)
 
1467
    {
 
1468
      free (buf);
 
1469
      size *= 2;
 
1470
      buf = scm_malloc (size);
 
1471
    }
 
1472
  if (rv == -1)
 
1473
    {
 
1474
      int save_errno = errno;
 
1475
      free (buf);
 
1476
      errno = save_errno;
 
1477
      SCM_SYSERROR;
 
1478
    }
 
1479
  result = scm_take_locale_stringn (buf, rv);
 
1480
 
 
1481
  scm_dynwind_end ();
 
1482
  return result;
 
1483
}
 
1484
#undef FUNC_NAME
 
1485
#endif /* HAVE_READLINK */
 
1486
 
 
1487
#ifdef HAVE_LSTAT
 
1488
SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0, 
 
1489
            (SCM str),
 
1490
            "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n"
 
1491
            "it will return information about a symbolic link itself, not the\n"
 
1492
            "file it points to.  @var{path} must be a string.")
 
1493
#define FUNC_NAME s_scm_lstat
 
1494
{
 
1495
  int rv;
 
1496
  struct stat_or_stat64 stat_temp;
 
1497
 
 
1498
  STRING_SYSCALL (str, c_str, rv = lstat_or_lstat64 (c_str, &stat_temp));
 
1499
  if (rv != 0)
 
1500
    {
 
1501
      int en = errno;
 
1502
 
 
1503
      SCM_SYSERROR_MSG ("~A: ~S",
 
1504
                        scm_list_2 (scm_strerror (scm_from_int (en)), str),
 
1505
                        en);
 
1506
    }
 
1507
  return scm_stat2scm (&stat_temp);
 
1508
}
 
1509
#undef FUNC_NAME
 
1510
#endif /* HAVE_LSTAT */
 
1511
 
 
1512
SCM_DEFINE (scm_copy_file, "copy-file", 2, 0, 0,
 
1513
            (SCM oldfile, SCM newfile),
 
1514
            "Copy the file specified by @var{path-from} to @var{path-to}.\n"
 
1515
            "The return value is unspecified.")
 
1516
#define FUNC_NAME s_scm_copy_file
 
1517
{
 
1518
  char *c_oldfile, *c_newfile;
 
1519
  int oldfd, newfd;
 
1520
  int n, rv;
 
1521
  char buf[BUFSIZ];
 
1522
  struct stat_or_stat64 oldstat;
 
1523
 
 
1524
  scm_dynwind_begin (0);
 
1525
  
 
1526
  c_oldfile = scm_to_locale_string (oldfile);
 
1527
  scm_dynwind_free (c_oldfile);
 
1528
  c_newfile = scm_to_locale_string (newfile);
 
1529
  scm_dynwind_free (c_newfile);
 
1530
 
 
1531
  oldfd = open_or_open64 (c_oldfile, O_RDONLY);
 
1532
  if (oldfd == -1)
 
1533
    SCM_SYSERROR;
 
1534
 
 
1535
#ifdef __MINGW32__
 
1536
  SCM_SYSCALL (rv = fstat_Win32 (oldfd, &oldstat));
 
1537
#else
 
1538
  SCM_SYSCALL (rv = fstat_or_fstat64 (oldfd, &oldstat));
 
1539
#endif
 
1540
  if (rv == -1)
 
1541
    goto err_close_oldfd;
 
1542
 
 
1543
  /* use POSIX flags instead of 07777?.  */
 
1544
  newfd = open_or_open64 (c_newfile, O_WRONLY | O_CREAT | O_TRUNC,
 
1545
                          oldstat.st_mode & 07777);
 
1546
  if (newfd == -1)
 
1547
    {
 
1548
    err_close_oldfd:
 
1549
      close (oldfd);
 
1550
      SCM_SYSERROR;
 
1551
    }
 
1552
 
 
1553
  while ((n = read (oldfd, buf, sizeof buf)) > 0)
 
1554
    if (write (newfd, buf, n) != n)
 
1555
      {
 
1556
        close (oldfd);
 
1557
        close (newfd);
 
1558
        SCM_SYSERROR;
 
1559
      }
 
1560
  close (oldfd);
 
1561
  if (close (newfd) == -1)
 
1562
    SCM_SYSERROR;
 
1563
 
 
1564
  scm_dynwind_end ();
 
1565
  return SCM_UNSPECIFIED;
 
1566
}
 
1567
#undef FUNC_NAME
 
1568
 
 
1569
 
 
1570
/* Filename manipulation */
 
1571
 
 
1572
SCM scm_dot_string;
 
1573
 
 
1574
SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0, 
 
1575
            (SCM filename),
 
1576
            "Return the directory name component of the file name\n"
 
1577
            "@var{filename}. If @var{filename} does not contain a directory\n"
 
1578
            "component, @code{.} is returned.")
 
1579
#define FUNC_NAME s_scm_dirname
 
1580
{
 
1581
  const char *s;
 
1582
  long int i;
 
1583
  unsigned long int len;
 
1584
 
 
1585
  SCM_VALIDATE_STRING (1, filename);
 
1586
 
 
1587
  s = scm_i_string_chars (filename);
 
1588
  len = scm_i_string_length (filename);
 
1589
 
 
1590
  i = len - 1;
 
1591
#ifdef __MINGW32__
 
1592
  while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
 
1593
  while (i >= 0 && (s[i] != '/' && s[i] != '\\')) --i;
 
1594
  while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
 
1595
#else
 
1596
  while (i >= 0 && s[i] == '/') --i;
 
1597
  while (i >= 0 && s[i] != '/') --i;
 
1598
  while (i >= 0 && s[i] == '/') --i;
 
1599
#endif /* ndef __MINGW32__ */
 
1600
  if (i < 0)
 
1601
    {
 
1602
#ifdef __MINGW32__
 
1603
      if (len > 0 && (s[0] == '/' || s[0] == '\\'))
 
1604
#else
 
1605
      if (len > 0 && s[0] == '/')
 
1606
#endif /* ndef __MINGW32__ */
 
1607
        return scm_c_substring (filename, 0, 1);
 
1608
      else
 
1609
        return scm_dot_string;
 
1610
    }
 
1611
  else
 
1612
    return scm_c_substring (filename, 0, i + 1);
 
1613
}
 
1614
#undef FUNC_NAME
 
1615
 
 
1616
SCM_DEFINE (scm_basename, "basename", 1, 1, 0, 
 
1617
            (SCM filename, SCM suffix),
 
1618
            "Return the base name of the file name @var{filename}. The\n"
 
1619
            "base name is the file name without any directory components.\n"
 
1620
            "If @var{suffix} is provided, and is equal to the end of\n"
 
1621
            "@var{basename}, it is removed also.")
 
1622
#define FUNC_NAME s_scm_basename
 
1623
{
 
1624
  const char *f, *s = 0;
 
1625
  int i, j, len, end;
 
1626
 
 
1627
  SCM_VALIDATE_STRING (1, filename);
 
1628
  f = scm_i_string_chars (filename);
 
1629
  len = scm_i_string_length (filename);
 
1630
 
 
1631
  if (SCM_UNBNDP (suffix))
 
1632
    j = -1;
 
1633
  else
 
1634
    {
 
1635
      SCM_VALIDATE_STRING (2, suffix);
 
1636
      s = scm_i_string_chars (suffix);
 
1637
      j = scm_i_string_length (suffix) - 1;
 
1638
    }
 
1639
  i = len - 1;
 
1640
#ifdef __MINGW32__
 
1641
  while (i >= 0 && (f[i] == '/' || f[i] == '\\')) --i;
 
1642
#else
 
1643
  while (i >= 0 && f[i] == '/') --i;
 
1644
#endif /* ndef __MINGW32__ */
 
1645
  end = i;
 
1646
  while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j;
 
1647
  if (j == -1)
 
1648
    end = i;
 
1649
#ifdef __MINGW32__
 
1650
  while (i >= 0 && f[i] != '/' && f[i] != '\\') --i;
 
1651
#else
 
1652
  while (i >= 0 && f[i] != '/') --i;
 
1653
#endif /* ndef __MINGW32__ */
 
1654
  if (i == end)
 
1655
    {
 
1656
#ifdef __MINGW32__
 
1657
      if (len > 0 && (f[0] == '/' || f[0] == '\\'))
 
1658
#else
 
1659
      if (len > 0 && f[0] == '/')
 
1660
#endif /* ndef __MINGW32__ */
 
1661
        return scm_c_substring (filename, 0, 1);
 
1662
      else
 
1663
        return scm_dot_string;
 
1664
    }
 
1665
  else
 
1666
    return scm_c_substring (filename, i+1, end+1);
 
1667
}
 
1668
#undef FUNC_NAME
 
1669
 
 
1670
 
 
1671
 
 
1672
 
 
1673
 
 
1674
void
 
1675
scm_init_filesys ()
 
1676
{
 
1677
  scm_tc16_dir = scm_make_smob_type ("directory", 0);
 
1678
  scm_set_smob_free (scm_tc16_dir, scm_dir_free);
 
1679
  scm_set_smob_print (scm_tc16_dir, scm_dir_print);
 
1680
 
 
1681
  scm_dot_string = scm_permanent_object (scm_from_locale_string ("."));
 
1682
  
 
1683
#ifdef O_RDONLY
 
1684
  scm_c_define ("O_RDONLY", scm_from_long (O_RDONLY));
 
1685
#endif         
 
1686
#ifdef O_WRONLY
 
1687
  scm_c_define ("O_WRONLY", scm_from_long (O_WRONLY));
 
1688
#endif         
 
1689
#ifdef O_RDWR
 
1690
  scm_c_define ("O_RDWR", scm_from_long (O_RDWR));
 
1691
#endif         
 
1692
#ifdef O_CREAT
 
1693
  scm_c_define ("O_CREAT", scm_from_long (O_CREAT));
 
1694
#endif         
 
1695
#ifdef O_EXCL  
 
1696
  scm_c_define ("O_EXCL", scm_from_long (O_EXCL));
 
1697
#endif         
 
1698
#ifdef O_NOCTTY
 
1699
  scm_c_define ("O_NOCTTY", scm_from_long (O_NOCTTY));
 
1700
#endif         
 
1701
#ifdef O_TRUNC 
 
1702
  scm_c_define ("O_TRUNC", scm_from_long (O_TRUNC));
 
1703
#endif         
 
1704
#ifdef O_APPEND
 
1705
  scm_c_define ("O_APPEND", scm_from_long (O_APPEND));
 
1706
#endif         
 
1707
#ifdef O_NONBLOCK
 
1708
  scm_c_define ("O_NONBLOCK", scm_from_long (O_NONBLOCK));
 
1709
#endif         
 
1710
#ifdef O_NDELAY
 
1711
  scm_c_define ("O_NDELAY", scm_from_long (O_NDELAY));
 
1712
#endif         
 
1713
#ifdef O_SYNC  
 
1714
  scm_c_define ("O_SYNC", scm_from_long (O_SYNC));
 
1715
#endif 
 
1716
#ifdef O_LARGEFILE  
 
1717
  scm_c_define ("O_LARGEFILE", scm_from_long (O_LARGEFILE));
 
1718
#endif 
 
1719
 
 
1720
#ifdef F_DUPFD  
 
1721
  scm_c_define ("F_DUPFD", scm_from_long (F_DUPFD));
 
1722
#endif 
 
1723
#ifdef F_GETFD  
 
1724
  scm_c_define ("F_GETFD", scm_from_long (F_GETFD));
 
1725
#endif 
 
1726
#ifdef F_SETFD  
 
1727
  scm_c_define ("F_SETFD", scm_from_long (F_SETFD));
 
1728
#endif 
 
1729
#ifdef F_GETFL  
 
1730
  scm_c_define ("F_GETFL", scm_from_long (F_GETFL));
 
1731
#endif 
 
1732
#ifdef F_SETFL  
 
1733
  scm_c_define ("F_SETFL", scm_from_long (F_SETFL));
 
1734
#endif 
 
1735
#ifdef F_GETOWN  
 
1736
  scm_c_define ("F_GETOWN", scm_from_long (F_GETOWN));
 
1737
#endif 
 
1738
#ifdef F_SETOWN  
 
1739
  scm_c_define ("F_SETOWN", scm_from_long (F_SETOWN));
 
1740
#endif 
 
1741
#ifdef FD_CLOEXEC  
 
1742
  scm_c_define ("FD_CLOEXEC", scm_from_long (FD_CLOEXEC));
 
1743
#endif
 
1744
 
 
1745
#include "libguile/filesys.x"
 
1746
}
 
1747
 
 
1748
/*
 
1749
  Local Variables:
 
1750
  c-file-style: "gnu"
 
1751
  End:
 
1752
*/