e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
e42eaf1998-01-02Fredrik Hübinette (Hubbe) #include "fdlib.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h" #include "svalue.h" #include "stralloc.h" #include "array.h" #include "mapping.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "fd_control.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "threads.h"
dfa0b61997-01-21Fredrik Hübinette (Hubbe) #include "module_support.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "constants.h" #include "backend.h" #include "operators.h"
485a1e1997-06-01Henrik Grubbström (Grubba) #include "builtin_functions.h"
2fe5651999-10-29Fredrik Noring #include "bignum.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #include "file_machine.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "file.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
72ef221996-09-23Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_TYPES_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/types.h>
72ef221996-09-23Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/stat.h>
a40d3a1997-06-13Henrik Grubbström (Grubba) #ifdef HAVE_SYS_PARAM_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/param.h>
a40d3a1997-06-13Henrik Grubbström (Grubba) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <signal.h> #include <errno.h>
4f89551998-07-02Henrik Grubbström (Grubba) #ifdef HAVE_LIMITS_H #include <limits.h> #endif /* HAVE_LIMITS_H */
ef1e931998-03-26Henrik Grubbström (Grubba) #include "dmalloc.h"
f8e4e71998-03-24Fredrik Hübinette (Hubbe) #ifdef HAVE_PROCESS_H #include <process.h> #endif
92dc6d2005-04-30Henrik Grubbström (Grubba) #ifdef HAVE_SYS_XATTR_H #include <sys/xattr.h> #endif /* HAVE_SYS_XATTR_H */
6d8b9b2009-08-07Henrik Grubbström (Grubba) #if 0
e0c51f2009-08-06Henrik Grubbström (Grubba) #ifdef HAVE_LIBZFS_INIT #ifdef HAVE_LIBZFS_H #include <libzfs.h> #endif /* HAVE_LIBZFS_H */ static libzfs_handle_t *libzfs_handle; #endif /* HAVE_LIBZFS_INIT */
6d8b9b2009-08-07Henrik Grubbström (Grubba) #endif /* 0 */
e0c51f2009-08-06Henrik Grubbström (Grubba) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
ef1e931998-03-26Henrik Grubbström (Grubba) /* #define DEBUG_FILE */
c679f61998-07-06Henrik Grubbström (Grubba) /* #define READDIR_DEBUG */
61e9a01998-01-25Fredrik Hübinette (Hubbe) 
25cd432001-04-19Martin Stjernholm #ifdef __NT__
1774632003-03-28Martin Stjernholm #include <winbase.h>
097de92006-07-05Martin Stjernholm #include <io.h>
1774632003-03-28Martin Stjernholm 
05f7f52003-03-28Henrik Grubbström (Grubba) /* Old versions of the headerfiles don't have this constant... */ #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif
25cd432001-04-19Martin Stjernholm /* Dynamic load of functions that doesn't exist in all Windows versions. */ static HINSTANCE kernel32lib; #define LINKFUNC(RET,NAME,TYPE) \ typedef RET (WINAPI * PIKE_CONCAT(NAME,type)) TYPE ; \ static PIKE_CONCAT(NAME,type) NAME LINKFUNC(BOOL, movefileex, (
eed8782001-12-22Martin Nilsson  LPCTSTR lpExistingFileName, /* file name */ LPCTSTR lpNewFileName, /* new file name */ DWORD dwFlags /* move options */
25cd432001-04-19Martin Stjernholm ));
f168152005-01-06Henrik Grubbström (Grubba) #endif /* __NT__ */
25cd432001-04-19Martin Stjernholm 
40962a2003-03-27Martin Stjernholm struct array *encode_stat(PIKE_STAT_T *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct array *a;
99946c1996-02-17Fredrik Hübinette (Hubbe)  a=allocate_array(7);
2523ce2003-04-28Martin Stjernholm  a->type_field = BIT_INT;
99946c1996-02-17Fredrik Hübinette (Hubbe)  ITEM(a)[0].u.integer=s->st_mode;
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(S_IFMT & s->st_mode) {
2fe5651999-10-29Fredrik Noring  case S_IFREG: push_int64((INT64)s->st_size);
2523ce2003-04-28Martin Stjernholm  stack_pop_to_no_free (ITEM(a) + 1);
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(ITEM(a)[1]) == T_OBJECT) a->type_field |= BIT_OBJECT;
2fe5651999-10-29Fredrik Noring  break;
99946c1996-02-17Fredrik Hübinette (Hubbe)  case S_IFDIR: ITEM(a)[1].u.integer=-2; break;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef S_IFLNK
99946c1996-02-17Fredrik Hübinette (Hubbe)  case S_IFLNK: ITEM(a)[1].u.integer=-3; break;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
ef1e931998-03-26Henrik Grubbström (Grubba)  default: #ifdef DEBUG_FILE fprintf(stderr, "encode_stat(): mode:%ld\n", (long)S_IFMT & s->st_mode); #endif /* DEBUG_FILE */ ITEM(a)[1].u.integer=-4; break;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
097de92006-07-05Martin Stjernholm  ITEM(a)[2].u.integer = DO_NOT_WARN ((INT_TYPE) s->st_atime); ITEM(a)[3].u.integer = DO_NOT_WARN ((INT_TYPE) s->st_mtime); ITEM(a)[4].u.integer = DO_NOT_WARN ((INT_TYPE) s->st_ctime);
99946c1996-02-17Fredrik Hübinette (Hubbe)  ITEM(a)[5].u.integer=s->st_uid; ITEM(a)[6].u.integer=s->st_gid;
5267b71995-08-09Fredrik Hübinette (Hubbe)  return a; }
3c44292005-04-29Per Hedbor #if defined(HAVE_FSETXATTR) && defined(HAVE_FGETXATTR) && defined(HAVE_FLISTXATTR) /*! @decl array(string) listxattr( string file, void|int(0..1) symlink ) *! *! Return an array of all extended attributes set on the file */
42285f2005-06-01Henrik Grubbström (Grubba) #ifdef HAVE_DARWIN_XATTR #define LISTXATTR(PATH, BUF, SZ) listxattr(PATH, BUF, SZ, 0) #define LLISTXATTR(PATH, BUF, SZ) listxattr(PATH, BUF, SZ, XATTR_NOFOLLOW) #else #define LISTXATTR(PATH, BUF, SZ) listxattr(PATH, BUF, SZ) #define LLISTXATTR(PATH, BUF, SZ) llistxattr(PATH, BUF, SZ) #endif /* !HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor static void f_listxattr(INT32 args) { char buffer[1024]; char *ptr = buffer; char *name; int do_free = 0; int nofollow = 0; ssize_t res;
6d7cf72005-12-27Martin Nilsson  get_all_args( "listxattr", args, "%s.%d", &name, &nofollow );
3c44292005-04-29Per Hedbor  THREADS_ALLOW(); do {
42285f2005-06-01Henrik Grubbström (Grubba)  /* First try, for speed.*/ if (nofollow) res = LLISTXATTR(name, buffer, sizeof(buffer)); else res = LISTXATTR( name, buffer, sizeof(buffer));
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); if( res<0 && errno==ERANGE ) { /* Too little space in stackbuffer.*/
136bf82005-04-29Henrik Grubbström (Grubba)  size_t blen = 65536;
e0c51f2009-08-06Henrik Grubbström (Grubba)  ptr = NULL;
3c44292005-04-29Per Hedbor  do_free = 1; do {
e0c51f2009-08-06Henrik Grubbström (Grubba)  if (!ptr) { ptr = xalloc(blen); } else { char *tmp = realloc( ptr, blen ); if( !tmp ) break; ptr = tmp; }
3c44292005-04-29Per Hedbor  THREADS_ALLOW(); do {
42285f2005-06-01Henrik Grubbström (Grubba)  if (nofollow)
e0c51f2009-08-06Henrik Grubbström (Grubba)  res = LLISTXATTR(name, ptr, sizeof(blen));
42285f2005-06-01Henrik Grubbström (Grubba)  else res = LISTXATTR(name, ptr, blen);
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); blen *= 2;
e0c51f2009-08-06Henrik Grubbström (Grubba)  } while( (res < 0) && (errno == ERANGE) );
3c44292005-04-29Per Hedbor  } pop_n_elems( args );
4800182007-01-25Henrik Grubbström (Grubba)  if (res < 0)
3c44292005-04-29Per Hedbor  {
4800182007-01-25Henrik Grubbström (Grubba)  if (do_free)
3c44292005-04-29Per Hedbor  free(ptr); push_int(0); return; } push_string( make_shared_binary_string( ptr, res ) ); ptr[0]=0; push_string( make_shared_binary_string( ptr, 1 ) ); o_divide();
7863d62005-05-06Martin Nilsson  push_empty_string();
3c44292005-04-29Per Hedbor  f_aggregate(1); o_subtract();
4800182007-01-25Henrik Grubbström (Grubba)  if (do_free) free(ptr);
3c44292005-04-29Per Hedbor }
42285f2005-06-01Henrik Grubbström (Grubba) #ifdef HAVE_DARWIN_XATTR #define GETXATTR(PATH, NAME, BUF, SZ) getxattr(PATH, NAME, BUF, SZ, 0, 0) #define LGETXATTR(PATH, NAME, BUF, SZ) getxattr(PATH, NAME, BUF, SZ, 0, XATTR_NOFOLLOW) #else
32d50a2005-06-01Henrik Grubbström (Grubba) #define GETXATTR(PATH, NAME, BUF, SZ) getxattr(PATH, NAME, BUF, SZ)
42285f2005-06-01Henrik Grubbström (Grubba) #define LGETXATTR(PATH, NAME, BUF, SZ) lgetxattr(PATH, NAME, BUF, SZ) #endif /* !HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor /*! @decl string getxattr(string file, string attr, void|int(0..1) symlink) *! *! Return the value of a specified attribute, or 0 if it does not exist. */ static void f_getxattr(INT32 args) { char buffer[1024]; char *ptr = buffer; int do_free = 0; ssize_t res; char *name, *file; int nofollow=0;
6d7cf72005-12-27Martin Nilsson  get_all_args( "getxattr", args, "%s%s.%d", &file, &name, &nofollow );
3c44292005-04-29Per Hedbor  THREADS_ALLOW(); do {
42285f2005-06-01Henrik Grubbström (Grubba)  /* First try, for speed.*/ if (nofollow)
991d502005-10-04Martin Nilsson  res = LGETXATTR(file, name, buffer, sizeof(buffer));
42285f2005-06-01Henrik Grubbström (Grubba)  else
991d502005-10-04Martin Nilsson  res = GETXATTR(file, name, buffer, sizeof(buffer));
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); if( res<0 && errno==ERANGE ) { /* Too little space in buffer.*/
136bf82005-04-29Henrik Grubbström (Grubba)  size_t blen = 65536;
3c44292005-04-29Per Hedbor  do_free = 1;
6d8b9b2009-08-07Henrik Grubbström (Grubba)  ptr = NULL;
3c44292005-04-29Per Hedbor  do {
6d8b9b2009-08-07Henrik Grubbström (Grubba)  if (!ptr) { ptr = xalloc(blen); } else { char *tmp = realloc( ptr, blen ); if( !tmp ) break; ptr = tmp; }
3c44292005-04-29Per Hedbor  THREADS_ALLOW(); do {
42285f2005-06-01Henrik Grubbström (Grubba)  if (nofollow)
991d502005-10-04Martin Nilsson  res = LGETXATTR(file, name, ptr, blen);
42285f2005-06-01Henrik Grubbström (Grubba)  else
991d502005-10-04Martin Nilsson  res = GETXATTR(file, name, ptr, blen);
3c44292005-04-29Per Hedbor  } while( res < 0 && errno == EINTR ); THREADS_DISALLOW(); blen *= 2;
6d8b9b2009-08-07Henrik Grubbström (Grubba)  } while( (res < 0) && (errno == ERANGE) );
3c44292005-04-29Per Hedbor  } if( res < 0 ) { if( do_free && ptr ) free(ptr); push_int(0); return; } push_string( make_shared_binary_string( ptr, res ) ); if( do_free && ptr ) free( ptr ); }
42285f2005-06-01Henrik Grubbström (Grubba) #ifdef HAVE_DARWIN_XATTR #define REMOVEXATTR(PATH, NAME) removexattr(PATH, NAME, 0) #define LREMOVEXATTR(PATH, NAME) removexattr(PATH, NAME, XATTR_NOFOLLOW) #else #define REMOVEXATTR(PATH, NAME) removexattr(PATH, NAME) #define LREMOVEXATTR(PATH, NAME) lremovexattr(PATH, NAME) #endif /* !HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor /*! @decl void removexattr( string file, string attr , void|int(0..1) symlink) *! Remove the specified extended attribute. */ static void f_removexattr( INT32 args ) { char *name, *file; int nofollow=0, rv;
6d7cf72005-12-27Martin Nilsson  get_all_args( "removexattr", args, "%s%s.%d", &file, &name, &nofollow );
3c44292005-04-29Per Hedbor  THREADS_ALLOW();
42285f2005-06-01Henrik Grubbström (Grubba)  if (nofollow) { while(((rv=LREMOVEXATTR(file, name)) < 0) && (errno == EINTR)) ; } else { while(((rv=REMOVEXATTR(file, name)) < 0) && (errno == EINTR)) ; }
3c44292005-04-29Per Hedbor  THREADS_DISALLOW(); pop_n_elems(args); if( rv < 0 ) { push_int(0); } else { push_int(1); } }
42285f2005-06-01Henrik Grubbström (Grubba) #ifdef HAVE_DARWIN_XATTR #define SETXATTR(PATH, NAME, BUF, SZ, FL) setxattr(PATH, NAME, BUF, SZ, 0, FL) #define LSETXATTR(PATH, NAME, BUF, SZ, FL) setxattr(PATH, NAME, BUF, SZ, 0, (FL)|XATTR_NOFOLLOW) #else
d2ddd82005-06-01Henrik Grubbström (Grubba) #define SETXATTR(PATH, NAME, BUF, SZ, FL) setxattr(PATH, NAME, BUF, SZ, FL)
42285f2005-06-01Henrik Grubbström (Grubba) #define LSETXATTR(PATH, NAME, BUF, SZ, FL) lsetxattr(PATH, NAME, BUF, SZ, FL) #endif /* !HAVE_DARWIN_XATTR */
3c44292005-04-29Per Hedbor /*! @decl void setxattr( string file, string attr, string value, int flags,void|int(0..1) symlink) *! *! Set the attribute @[attr] to the value @[value]. *! *! The flags parameter can be used to refine the semantics of the operation. *!
7e8cb42007-03-04Martin Nilsson  *! @[Stdio.XATTR_CREATE] specifies a pure create, which
3c44292005-04-29Per Hedbor  *! fails if the named attribute exists already. *!
7e8cb42007-03-04Martin Nilsson  *! @[Stdio.XATTR_REPLACE] specifies a pure replace operation, which *! fails if the named attribute does not already exist.
3c44292005-04-29Per Hedbor  *! *! By default (no flags), the extended attribute will be created if need be, *! or will simply replace the value if the attribute exists. *! *! @returns *! 1 if successful, 0 otherwise, setting errno. */ static void f_setxattr( INT32 args ) { char *ind, *file; struct pike_string *val; int flags; int rv; int nofollow=0;
6d7cf72005-12-27Martin Nilsson  get_all_args( "setxattr", args, "%s%s%S%d.%d", &file, &ind, &val, &flags, &nofollow );
3c44292005-04-29Per Hedbor  THREADS_ALLOW();
42285f2005-06-01Henrik Grubbström (Grubba)  if (nofollow) { while(((rv=LSETXATTR(file, ind, val->str, (val->len<<val->size_shift), flags )) < 0) && (errno == EINTR)) ; } else { while(((rv=SETXATTR(file, ind, val->str, (val->len<<val->size_shift), flags )) < 0) && (errno == EINTR)) ; }
3c44292005-04-29Per Hedbor  THREADS_DISALLOW(); pop_n_elems(args); if( rv < 0 ) { push_int(0); } else push_int(1); } #endif
e5b1ac2001-07-01Henrik Grubbström (Grubba) /*! @decl Stdio.Stat file_stat(string path, void|int(0..1) symlink)
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! Stat a file. *!
cbe8c92003-04-07Martin Nilsson  *! If the argument @[symlink] is @expr{1@} symlinks will not be followed.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! If the path specified by @[path] doesn't exist @expr{0@} (zero) will
ea30342001-01-31Henrik Grubbström (Grubba)  *! be returned. *! *! Otherwise an object describing the properties of @[path] will be *! returned. *! *! @note *! In Pike 7.0 and earlier this function returned an array with 7 elements. *! The old behaviour can be simulated with the following function:
f79bd82003-04-01Martin Nilsson  *! @code *! array(int) file_stat(string path, void|int(0..1) symlink) *! { *! File.Stat st = predef::file_stat(path, symlink); *! if (!st) return 0; *! return (array(int))st; *! } *! @endcode
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso
e5b1ac2001-07-01Henrik Grubbström (Grubba)  *! @[Stdio.Stat], @[Stdio.File->stat()]
ea30342001-01-31Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_file_stat(INT32 args) {
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T st;
fa09721996-12-06Per Hedbor  int i, l;
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
fa09721996-12-06Per Hedbor 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args<1)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("file_stat", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if((TYPEOF(sp[-args]) != T_STRING) || sp[-args].u.string->size_shift)
7264822009-10-23Henrik Grubbström (Grubba)  SIMPLE_BAD_ARG_ERROR("file_stat", 1, "string(0..255)");
fa09721996-12-06Per Hedbor 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
9f516a2001-12-16Martin Stjernholm  l = (args>1 && !UNSAFE_IS_ZERO(sp+1-args))?1:0;
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
aa07fe1999-04-05Fredrik Hübinette (Hubbe) 
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
0ec31b2005-10-06Henrik Grubbström (Grubba)  do {
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_LSTAT
0ec31b2005-10-06Henrik Grubbström (Grubba)  if(l) i=fd_lstat(str->str, &st); else
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
0ec31b2005-10-06Henrik Grubbström (Grubba)  i=fd_stat(str->str, &st); } while ((i == -1) && (errno == EINTR));
2f0e402005-10-06Henrik Grubbström (Grubba) 
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); if(i==-1) { push_int(0); }else{
61a4242000-08-27Mirar (Pontus Hagland)  push_stat(&st);
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
cdf56e1999-05-19Mirar (Pontus Hagland) 
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int file_truncate(string file, int length) *! *! Truncates the file @[file] to the length specified in @[length]. *! *! @returns *! Returns 1 if ok, 0 if failed. */
cdf56e1999-05-19Mirar (Pontus Hagland) void f_file_truncate(INT32 args) {
99e4f02004-10-15Henrik Grubbström (Grubba) #if defined(INT64) INT64 len = 0;
cdf56e1999-05-19Mirar (Pontus Hagland) #else
99e4f02004-10-15Henrik Grubbström (Grubba)  off_t len = 0;
cdf56e1999-05-19Mirar (Pontus Hagland) #endif
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
cdf56e1999-05-19Mirar (Pontus Hagland)  int res;
8e8ff82003-01-05Martin Nilsson  if(args < 2) SIMPLE_TOO_FEW_ARGS_ERROR("file_truncate", 2);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("file_truncate", 1, "string");
f202eb2003-03-28Martin Stjernholm 
0311712013-06-17Martin Nilsson #if defined (INT64)
f202eb2003-03-28Martin Stjernholm #if defined (HAVE_FTRUNCATE64) || SIZEOF_OFF_T > SIZEOF_INT_TYPE if(is_bignum_object_in_svalue(&Pike_sp[1-args])) { if (!int64_from_bignum(&len, Pike_sp[1-args].u.object)) Pike_error ("Bad argument 2 to file_truncate(). Length too large.\n"); } else #endif #endif
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[1-args]) != T_INT)
f202eb2003-03-28Martin Stjernholm  SIMPLE_BAD_ARG_ERROR("file_truncate", 2, "int"); else len = sp[1-args].u.integer;
cdf56e1999-05-19Mirar (Pontus Hagland) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
cdf56e1999-05-19Mirar (Pontus Hagland) 
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
d505cf1999-06-02Marcus Comstedt #ifdef __NT__ {
b8c7982000-07-21Henrik Grubbström (Grubba)  HANDLE h = CreateFile(str->str, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
d505cf1999-06-02Marcus Comstedt  NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
7bc62b2000-08-18Henrik Grubbström (Grubba)  if(h == DO_NOT_WARN(INVALID_HANDLE_VALUE)) {
d505cf1999-06-02Marcus Comstedt  errno = GetLastError(); res=-1; } else {
f202eb2003-03-28Martin Stjernholm  LONG high; DWORD err; #ifdef INT64
097de92006-07-05Martin Stjernholm  high = DO_NOT_WARN ((LONG) (len >> 32));
9fa9a22006-07-05Martin Stjernholm  len &= ((INT64) 1 << 32) - 1;
f202eb2003-03-28Martin Stjernholm #else high = 0; #endif if (SetFilePointer(h, DO_NOT_WARN ((LONG) len), &high, FILE_BEGIN) == INVALID_SET_FILE_POINTER && (err = GetLastError()) != NO_ERROR) { errno = err; res = -1; } else if (!SetEndOfFile(h)) {
d505cf1999-06-02Marcus Comstedt  errno = GetLastError(); res=-1; }
f202eb2003-03-28Martin Stjernholm  else res = 0;
d505cf1999-06-02Marcus Comstedt  CloseHandle(h); } } #else /* !__NT__ */
f202eb2003-03-28Martin Stjernholm #ifdef HAVE_TRUNCATE64 res = truncate64 (str->str, len); #else
b8c7982000-07-21Henrik Grubbström (Grubba)  res=truncate(str->str, len);
f202eb2003-03-28Martin Stjernholm #endif
d505cf1999-06-02Marcus Comstedt #endif /* __NT__ */
cdf56e1999-05-19Mirar (Pontus Hagland)  pop_n_elems(args); push_int(!res); }
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl mapping(string:int) filesystem_stat(string path) *! *! Returns a mapping describing the properties of the filesystem *! containing the path specified by @[path]. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! If a filesystem cannot be determined @expr{0@} (zero) will be returned.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! Otherwise a mapping(string:int) with the following fields will be *! returned: *! @mapping *! @member int "blocksize" *! Size in bytes of the filesystem blocks. *! @member int "blocks" *! Size of the entire filesystem in blocks. *! @member int "bfree" *! Number of free blocks in the filesystem. *! @member int "bavail" *! Number of available blocks in the filesystem.
cbe8c92003-04-07Martin Nilsson  *! This is usually somewhat less than the @expr{"bfree"@} value, and
ea30342001-01-31Henrik Grubbström (Grubba)  *! can usually be adjusted with eg tunefs(1M). *! @member int "files" *! Total number of files (aka inodes) allowed by this filesystem. *! @member int "ffree" *! Number of free files in the filesystem. *! @member int "favail" *! Number of available files in the filesystem.
cbe8c92003-04-07Martin Nilsson  *! This is usually the same as the @expr{"ffree"@} value, and can
ea30342001-01-31Henrik Grubbström (Grubba)  *! usually be adjusted with eg tunefs(1M).
d72f472004-02-14Martin Nilsson  *! @member string "fsname" *! Name assigned to the filesystem. This item is not available *! on all systems. *! @member string "fstype" *! Type of filesystem (eg @expr{"nfs"@}). This item is not *! available on all systems.
ea30342001-01-31Henrik Grubbström (Grubba)  *! @endmapping *! *! @note *! Please note that not all members are present on all OSs. *! *! @seealso *! @[file_stat()] */
6469a41998-10-27Per Hedbor #ifdef __NT__ void f_filesystem_stat( INT32 args ) { char *path; DWORD sectors_per_cluster = -1; DWORD bytes_per_sector = -1; DWORD free_clusters = -1; DWORD total_clusters = -1; char _p[4]; char *p = _p; unsigned int free_sectors; unsigned int total_sectors; get_all_args( "filesystem_stat", args, "%s", &path ); if(sp[-1].u.string->len < 2 || path[1] != ':') { p = 0; } else { p[0] = path[0]; p[1] = ':'; p[2] = '\\'; p[3] = 0; } if(!GetDiskFreeSpace( p, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters )) { pop_n_elems(args); push_int( 0 ); return; } free_sectors = sectors_per_cluster * free_clusters; total_sectors = sectors_per_cluster * total_clusters; pop_n_elems( args ); push_text("blocksize"); push_int(bytes_per_sector); push_text("blocks"); push_int(total_sectors); push_text("bfree"); push_int(free_sectors); push_text("bavail"); push_int(free_sectors); f_aggregate_mapping( 8 ); } #else /* !__NT__ */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
343dee1997-12-04Fredrik Hübinette (Hubbe) #if !defined(HAVE_STRUCT_STATFS) && !defined(HAVE_STRUCT_FS_DATA) #undef HAVE_STATFS #endif
485a1e1997-06-01Henrik Grubbström (Grubba) #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) || defined(HAVE_USTAT) #ifdef HAVE_SYS_STATVFS_H
93dfe41997-06-15Henrik Grubbström (Grubba) /* Kludge for broken SCO headerfiles */ #ifdef _SVID3
485a1e1997-06-01Henrik Grubbström (Grubba) #include <sys/statvfs.h>
93dfe41997-06-15Henrik Grubbström (Grubba) #else #define _SVID3 #include <sys/statvfs.h> #undef _SVID3 #endif /* _SVID3 */
485a1e1997-06-01Henrik Grubbström (Grubba) #endif /* HAVE_SYS_STATVFS_H */ #ifdef HAVE_SYS_VFS_H #include <sys/vfs.h> #endif /* HAVE_SYS_VFS_H */
918f831997-06-02Henrik Grubbström (Grubba) #ifdef HAVE_SYS_STATFS_H #include <sys/statfs.h>
93dfe41997-06-15Henrik Grubbström (Grubba) #endif /* HAVE_SYS_STATFS_H */
a40d3a1997-06-13Henrik Grubbström (Grubba) #ifdef HAVE_SYS_PARAM_H #include <sys/param.h>
93dfe41997-06-15Henrik Grubbström (Grubba) #endif /* HAVE_SYS_PARAM_H */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_SYS_MOUNT_H #include <sys/mount.h> #endif /* HAVE_SYS_MOUNT_H */
04d5742004-10-04Sam C. Nicholson #if !defined(HAVE_STATVFS) && !defined(HAVE_STATFS)
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_USTAT_H #include <ustat.h> #endif /* HAVE_USTAT_H */
04d5742004-10-04Sam C. Nicholson #endif /* !HAVE_STATVFS && !HAVE_STATFS */
485a1e1997-06-01Henrik Grubbström (Grubba) void f_filesystem_stat(INT32 args) { #ifdef HAVE_STATVFS struct statvfs st;
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATVFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_STATFS
4870d71997-12-02Henrik Grubbström (Grubba) #ifdef HAVE_STRUCT_STATFS
485a1e1997-06-01Henrik Grubbström (Grubba)  struct statfs st;
4870d71997-12-02Henrik Grubbström (Grubba) #else /* !HAVE_STRUCT_STATFS */ #ifdef HAVE_STRUCT_FS_DATA /* Probably only ULTRIX has this name for the struct */ struct fs_data st; #else /* !HAVE_STRUCT_FS_DATA */ /* Should not be reached */
a4a1722000-12-05Per Hedbor #error No struct to hold statfs() data.
4870d71997-12-02Henrik Grubbström (Grubba) #endif /* HAVE_STRUCT_FS_DATA */ #endif /* HAVE_STRUCT_STATFS */
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_USTAT
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T statbuf;
485a1e1997-06-01Henrik Grubbström (Grubba)  struct ustat st;
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_USTAT */ /* Should not be reached */
a4a1722000-12-05Per Hedbor #error No stat function for filesystems.
485a1e1997-06-01Henrik Grubbström (Grubba) #endif /* HAVE_USTAT */ #endif /* HAVE_STATFS */ #endif /* HAVE_STATVFS */ int i;
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
485a1e1997-06-01Henrik Grubbström (Grubba)  if(args<1)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("filesystem_stat", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("filesystem_stat", 1, "string");
485a1e1997-06-01Henrik Grubbström (Grubba) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
485a1e1997-06-01Henrik Grubbström (Grubba)  THREADS_ALLOW(); #ifdef HAVE_STATVFS
b8c7982000-07-21Henrik Grubbström (Grubba)  i = statvfs(str->str, &st);
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATVFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_STATFS
a40d3a1997-06-13Henrik Grubbström (Grubba) #ifdef HAVE_SYSV_STATFS
b8c7982000-07-21Henrik Grubbström (Grubba)  i = statfs(str->str, &st, sizeof(st), 0);
7c77821997-06-01Henrik Grubbström (Grubba) #else
b8c7982000-07-21Henrik Grubbström (Grubba)  i = statfs(str->str, &st);
a40d3a1997-06-13Henrik Grubbström (Grubba) #endif /* HAVE_SYSV_STATFS */
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_USTAT
b8c7982000-07-21Henrik Grubbström (Grubba)  if (!(i = fd_stat(str->str, &statbuf))) {
485a1e1997-06-01Henrik Grubbström (Grubba)  i = ustat(statbuf.st_rdev, &st); } #else
93dfe41997-06-15Henrik Grubbström (Grubba)  /* Should not be reached */
a4a1722000-12-05Per Hedbor #error No stat function for filesystems.
485a1e1997-06-01Henrik Grubbström (Grubba) #endif /* HAVE_USTAT */ #endif /* HAVE_STATFS */ #endif /* HAVE_STATVFS */ THREADS_DISALLOW(); pop_n_elems(args); if(i==-1) { push_int(0); }else{
8109a52007-10-23Henrik Grubbström (Grubba)  int num_fields = 0;
e7752c1999-06-25Per Hedbor #ifdef HAVE_STATVFS
7342621999-08-26Per Hedbor #if 0
e7752c1999-06-25Per Hedbor  push_text("id"); push_int(st.f_fsid);
8109a52007-10-23Henrik Grubbström (Grubba)  num_fields++;
7342621999-08-26Per Hedbor #endif
e7752c1999-06-25Per Hedbor  push_text("blocksize"); push_int(st.f_frsize); push_text("blocks"); push_int(st.f_blocks); push_text("bfree"); push_int(st.f_bfree); push_text("bavail"); push_int(st.f_bavail); push_text("files"); push_int(st.f_files); push_text("ffree"); push_int(st.f_ffree); push_text("favail"); push_int(st.f_favail);
8109a52007-10-23Henrik Grubbström (Grubba)  num_fields += 7;
f7ad5c1999-02-15Henrik Grubbström (Grubba) #ifdef HAVE_STATVFS_F_FSTR
8f8e6e2014-02-25Per Hedbor  push_text("fsname"); push_text(st.f_fstr);
f7ad5c1999-02-15Henrik Grubbström (Grubba)  num_fields++; #endif /* HAVE_STATVFS_F_FSTR */
8858011998-05-17Henrik Grubbström (Grubba) #ifdef HAVE_STATVFS_F_BASETYPE
e7752c1999-06-25Per Hedbor  push_text("fstype"); push_text(st.f_basetype);
f7ad5c1999-02-15Henrik Grubbström (Grubba)  num_fields++;
8858011998-05-17Henrik Grubbström (Grubba) #endif /* HAVE_STATVFS_F_BASETYPE */
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATVFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_STATFS
4870d71997-12-02Henrik Grubbström (Grubba) #ifdef HAVE_STRUCT_STATFS
4a02c81999-10-04Fredrik Hübinette (Hubbe) #if 0 && HAVE_STATFS_F_FSID
e7752c1999-06-25Per Hedbor  push_text("id"); push_int(st.f_fsid);
8109a52007-10-23Henrik Grubbström (Grubba)  num_fields++;
e7752c1999-06-25Per Hedbor #endif push_text("blocksize"); push_int(st.f_bsize); push_text("blocks"); push_int(st.f_blocks); push_text("bfree"); push_int(st.f_bfree); push_text("files"); push_int(st.f_files); push_text("ffree"); push_int(st.f_ffree); push_text("favail"); push_int(st.f_ffree);
8109a52007-10-23Henrik Grubbström (Grubba)  num_fields += 6;
244e4d1997-06-02Henrik Grubbström (Grubba) #ifdef HAVE_STATFS_F_BAVAIL
e7752c1999-06-25Per Hedbor  push_text("bavail"); push_int(st.f_bavail);
5615c02008-07-02Jonas Wallden  num_fields++;
244e4d1997-06-02Henrik Grubbström (Grubba) #endif /* HAVE_STATFS_F_BAVAIL */
4870d71997-12-02Henrik Grubbström (Grubba) #else /* !HAVE_STRUCT_STATFS */ #ifdef HAVE_STRUCT_FS_DATA /* ULTRIX */
e7752c1999-06-25Per Hedbor  push_text("blocksize"); push_int(st.fd_bsize); push_text("blocks"); push_int(st.fd_btot); push_text("bfree"); push_int(st.fd_bfree); push_text("bavail"); push_int(st.fd_bfreen);
5615c02008-07-02Jonas Wallden  num_fields += 4;
4870d71997-12-02Henrik Grubbström (Grubba) #else /* !HAVE_STRUCT_FS_DATA */ /* Should not be reached */
a4a1722000-12-05Per Hedbor #error No struct to hold statfs() data.
4870d71997-12-02Henrik Grubbström (Grubba) #endif /* HAVE_STRUCT_FS_DATA */ #endif /* HAVE_STRUCT_STATFS */
93dfe41997-06-15Henrik Grubbström (Grubba) #else /* !HAVE_STATFS */
485a1e1997-06-01Henrik Grubbström (Grubba) #ifdef HAVE_USTAT
e7752c1999-06-25Per Hedbor  push_text("bfree"); push_int(st.f_tfree); push_text("ffree"); push_int(st.f_tinode);
8f8e6e2014-02-25Per Hedbor  push_text("fsname"); push_text(st.f_fname);
8109a52007-10-23Henrik Grubbström (Grubba)  num_fields += 3;
485a1e1997-06-01Henrik Grubbström (Grubba) #else
93dfe41997-06-15Henrik Grubbström (Grubba)  /* Should not be reached */
a4a1722000-12-05Per Hedbor #error No stat function for filesystems.
485a1e1997-06-01Henrik Grubbström (Grubba) #endif /* HAVE_USTAT */ #endif /* HAVE_STATFS */ #endif /* HAVE_STATVFS */
8109a52007-10-23Henrik Grubbström (Grubba)  f_aggregate_mapping(num_fields*2);
485a1e1997-06-01Henrik Grubbström (Grubba)  } } #endif /* HAVE_STATVFS || HAVE_STATFS || HAVE_USTAT */
6469a41998-10-27Per Hedbor #endif /* __NT__ */
485a1e1997-06-01Henrik Grubbström (Grubba) 
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int rm(string f) *! *! Remove a file or directory. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{0@} (zero) on failure, @expr{1@} otherwise.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[mkdir()], @[Stdio.recursive_rm()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_rm(INT32 args) {
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T st;
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 i;
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
6df3a62000-08-02Fredrik Hübinette (Hubbe)  destruct_objects_to_destruct();
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!args)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("rm", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("rm", 1, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
fa09721996-12-06Per Hedbor 
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_LSTAT
b8c7982000-07-21Henrik Grubbström (Grubba)  i=fd_lstat(str->str, &st) != -1;
75920f1997-12-28Fredrik Hübinette (Hubbe) #else
b8c7982000-07-21Henrik Grubbström (Grubba)  i=fd_stat(str->str, &st) != -1;
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(i) { if(S_IFDIR == (S_IFMT & st.st_mode)) {
8da5632012-03-14Henrik Grubbström (Grubba)  while (!(i = rmdir(str->str) != -1) && (errno == EINTR)) ;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{
8da5632012-03-14Henrik Grubbström (Grubba)  while (!(i = unlink(str->str) != -1) && (errno == EINTR)) ;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
1048af2001-03-21Martin Stjernholm #ifdef __NT__ /* NT looks at the permissions on the file itself and refuses to * remove files we don't have write access to. Thus we chmod it * and try again, to make rm() more unix-like. */ if (!i && errno == EACCES && !(st.st_mode & _S_IWRITE)) {
8956282001-03-22Henrik Grubbström (Grubba)  if (chmod(str->str, st.st_mode | _S_IWRITE) == -1)
1048af2001-03-21Martin Stjernholm  errno = EACCES; else { if(S_IFDIR == (S_IFMT & st.st_mode)) {
8da5632012-03-14Henrik Grubbström (Grubba)  while (!(i = rmdir(str->str) != -1) && (errno == EINTR)) ;
1048af2001-03-21Martin Stjernholm  }else{
8da5632012-03-14Henrik Grubbström (Grubba)  while (!(i = unlink(str->str) != -1) && (errno == EINTR)) ;
1048af2001-03-21Martin Stjernholm  } if (!i) { /* Failed anyway; try to restore the old mode. */ int olderrno = errno;
8956282001-03-22Henrik Grubbström (Grubba)  chmod(str->str, st.st_mode);
1048af2001-03-21Martin Stjernholm  errno = olderrno; } } } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); }
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int mkdir(string dirname, void|int mode) *! *! Create a directory. *! *! If @[mode] is specified, it's will be used for the new directory after
cbe8c92003-04-07Martin Nilsson  *! being @expr{&@}'ed with the current umask (on OS'es that support this).
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{0@} (zero) on failure, @expr{1@} otherwise.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[rm()], @[cd()], @[Stdio.mkdirhier()]
eb7a812001-01-31Henrik Grubbström (Grubba)  */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_mkdir(INT32 args) {
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
c2f6ca1998-10-30Henrik Grubbström (Grubba)  int mode; int i;
15c1322008-10-30Jonas Wallden  char *s, *s_dup;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!args)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("mkdir", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("mkdir", 1, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5967191999-03-12Martin Stjernholm  mode = 0777; /* &'ed with ~umask anyway. */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args > 1) {
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[1-args]) != T_INT)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Bad argument 2 to mkdir.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
c2f6ca1998-10-30Henrik Grubbström (Grubba)  mode = sp[1-args].u.integer;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
aa07fe1999-04-05Fredrik Hübinette (Hubbe) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = EINVAL; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
76d9522000-08-23Henrik Grubbström (Grubba) 
15c1322008-10-30Jonas Wallden  /* Remove trailing / or \ which is not accepted by all mkdir() implementations (e.g. Mac OS X and Windows) */ s = str->str; s_dup = NULL; if (str->len && (s[str->len - 1] == '/' || s[str->len - 1] == '\\')) { if ((s_dup = strdup(s))) { s = s_dup; s[str->len - 1] = '\0';
67faa72001-04-09Jonas Wallden  }
097de92006-07-05Martin Stjernholm  }
15c1322008-10-30Jonas Wallden  #if MKDIR_ARGS == 2 THREADS_ALLOW_UID(); i = mkdir(s, mode) != -1; THREADS_DISALLOW_UID();
bdfb861997-12-22Fredrik Hübinette (Hubbe) #else
dd990d1998-12-31Fredrik Hübinette (Hubbe)  #ifdef HAVE_LSTAT #define LSTAT lstat #else #define LSTAT stat #endif
5967191999-03-12Martin Stjernholm  { /* Most OS's should have MKDIR_ARGS == 2 nowadays fortunately. */
c2f6ca1998-10-30Henrik Grubbström (Grubba)  int mask = umask(0);
4a02762010-10-30Martin Stjernholm  /* The following is basically the normal THREADS_ALLOW_UID/ * THREADS_DISALLOW_UID macros expanded. They cannot be used * directly due to the nested disallow/allow block below. */ struct thread_state *cur_ts_ext = Pike_interpreter.thread_state; pike_threads_allow_ext (cur_ts_ext COMMA_DLOC);
15c1322008-10-30Jonas Wallden  i = mkdir(s) != -1;
c2f6ca1998-10-30Henrik Grubbström (Grubba)  umask(mask); if (i) {
5967191999-03-12Martin Stjernholm  /* Attempt to set the mode. * * This code needs to be as paranoid as possible. */ struct stat statbuf1; struct stat statbuf2;
15c1322008-10-30Jonas Wallden  i = LSTAT(s, &statbuf1) != -1;
5967191999-03-12Martin Stjernholm  if (i) { i = ((statbuf1.st_mode & S_IFMT) == S_IFDIR); } if (i) { mode = ((mode & 0777) | (statbuf1.st_mode & ~0777)) & ~mask; do {
15c1322008-10-30Jonas Wallden  i = chmod(s, mode) != -1;
700dac2002-02-05Martin Stjernholm  if (i || errno != EINTR) break;
4a02762010-10-30Martin Stjernholm  pike_threads_disallow_ext (cur_ts_ext COMMA_DLOC); check_threads_etc(); pike_threads_allow_ext (cur_ts_ext COMMA_DLOC);
700dac2002-02-05Martin Stjernholm  } while (1);
5967191999-03-12Martin Stjernholm  } if (i) {
15c1322008-10-30Jonas Wallden  i = LSTAT(s, &statbuf2) != -1;
5967191999-03-12Martin Stjernholm  } if (i) { i = (statbuf2.st_mode == mode) && (statbuf1.st_ino == statbuf2.st_ino); if (!i) { errno = EPERM; } }
c2f6ca1998-10-30Henrik Grubbström (Grubba)  if (!i) {
15c1322008-10-30Jonas Wallden  rmdir(s);
c2f6ca1998-10-30Henrik Grubbström (Grubba)  } }
4a02762010-10-30Martin Stjernholm  pike_threads_disallow_ext (cur_ts_ext COMMA_DLOC);
5967191999-03-12Martin Stjernholm  }
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
15c1322008-10-30Jonas Wallden  if (s_dup) free(s_dup);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); }
fd36c61997-01-29Fredrik Hübinette (Hubbe) #undef HAVE_READDIR_R
9d10731998-06-28Henrik Grubbström (Grubba) #if defined(HAVE_SOLARIS_READDIR_R) || defined(HAVE_HPUX_READDIR_R) || \ defined(HAVE_POSIX_READDIR_R)
f131a71997-01-27Fredrik Hübinette (Hubbe) #define HAVE_READDIR_R #endif
c4a5942005-10-05Henrik Grubbström (Grubba) #if defined(_REENTRANT) && defined(HAVE_READDIR_R) #ifdef _PC_NAME_MAX #ifdef HAVE_FPATHCONF #ifdef HAVE_FDOPENDIR #define USE_FDOPENDIR #define USE_FPATHCONF #elif defined(HAVE_DIRFD)
e2cbad2005-10-05Henrik Grubbström (Grubba) #define USE_FPATHCONF
c4a5942005-10-05Henrik Grubbström (Grubba) #endif #endif /* HAVE_FPATHCONF */ #if defined(HAVE_PATHCONF) && !defined(USE_FPATHCONF) #define USE_PATHCONF #endif #endif /* _PC_NAME_MAX */ #endif /* _REENTRANT && HAVE_READDIR_R */
b1510a2004-10-24Martin Nilsson /*! @decl array(string) get_dir(void|string dirname)
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! Returns an array of all filenames in the directory @[dirname], or
b1510a2004-10-24Martin Nilsson  *! @expr{0@} (zero) if the directory does not exist. When no *! @[dirname] is given, current work directory is used.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[mkdir()], @[cd()] */
188dbb2014-03-03Henrik Grubbström (Grubba) #ifdef __NT__
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_get_dir(INT32 args) {
f168152005-01-06Henrik Grubbström (Grubba)  HANDLE dir;
8fd5592005-01-08Henrik Grubbström (Grubba)  WIN32_FIND_DATAW d;
35a2d62005-01-08Henrik Grubbström (Grubba)  struct string_builder sb;
b1510a2004-10-24Martin Nilsson  struct pike_string *str=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
6d7cf72005-12-27Martin Nilsson  get_all_args("get_dir",args,".%T",&str);
b1510a2004-10-24Martin Nilsson  if(!str) {
7cf0162014-05-22Per Hedbor  push_text(".");
62098c2004-11-01Martin Nilsson  str = Pike_sp[-1].u.string; args++;
b1510a2004-10-24Martin Nilsson  }
b8c7982000-07-21Henrik Grubbström (Grubba) 
35a2d62005-01-08Henrik Grubbström (Grubba)  if (str->size_shift == 2) { /* Filenames that are too wide are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return; } init_string_builder_alloc(&sb, str->len+2, 1); string_builder_shared_strcat(&sb, str);
8fd5592005-01-08Henrik Grubbström (Grubba) 
f168152005-01-06Henrik Grubbström (Grubba)  /* Append "/" "*". */
35a2d62005-01-08Henrik Grubbström (Grubba)  if (sb.s->len && (STR1(sb.s)[sb.s->len-1] != '/') && (STR1(sb.s)[sb.s->len-1] != '\\')) { STR1(sb.s)[sb.s->len++] = '/';
f168152005-01-06Henrik Grubbström (Grubba)  }
35a2d62005-01-08Henrik Grubbström (Grubba)  STR1(sb.s)[sb.s->len++] = '*'; STR1(sb.s)[sb.s->len] = '\0'; if (wcslen(STR1(sb.s)) != (size_t)sb.s->len) { /* Filenames with NUL are not supported. */ free_string_builder(&sb);
8fd5592005-01-08Henrik Grubbström (Grubba)  errno = ENOENT; pop_n_elems(args); push_int(0); return; }
64445c2005-01-08Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
50b2a02010-11-01Martin Stjernholm  fprintf(stderr, "FindFirstFile(\"%S\")...\n", STR1(sb.s));
64445c2005-01-08Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
35a2d62005-01-08Henrik Grubbström (Grubba)  dir = FindFirstFileW(STR1(sb.s), &d);
8fd5592005-01-08Henrik Grubbström (Grubba) 
35a2d62005-01-08Henrik Grubbström (Grubba)  free_string_builder(&sb);
f168152005-01-06Henrik Grubbström (Grubba)  if (dir == DO_NOT_WARN(INVALID_HANDLE_VALUE)) {
60b60b2010-11-01Martin Stjernholm  int err = GetLastError();
f168152005-01-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
60b60b2010-11-01Martin Stjernholm  fprintf(stderr, " INVALID_HANDLE_VALUE, error %d\n", err);
f168152005-01-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */ pop_n_elems(args);
60b60b2010-11-01Martin Stjernholm  if (err == ERROR_FILE_NOT_FOUND) { /* Normally there should at least be a "." entry, so this seldom * happens. But it seems unwise to count on it, considering this * being Windows and all.. * * Note: The error is ERROR_PATH_NOT_FOUND if the directory * doesn't exist. */ push_empty_array(); } else { set_errno_from_win32_error (err); push_int(0); }
f168152005-01-06Henrik Grubbström (Grubba)  return; }
60b60b2010-11-01Martin Stjernholm  { int err; BEGIN_AGGREGATE_ARRAY(10);
f168152005-01-06Henrik Grubbström (Grubba) 
60b60b2010-11-01Martin Stjernholm  do {
f168152005-01-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
60b60b2010-11-01Martin Stjernholm  fprintf(stderr, " \"%S\"\n", d.cFileName);
f168152005-01-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
60b60b2010-11-01Martin Stjernholm  /* Filter "." and ".." from the list. */ if(d.cFileName[0]=='.') { if(!d.cFileName[1]) continue; if(d.cFileName[1]=='.' && !d.cFileName[2]) continue; } push_string(make_shared_binary_string1(d.cFileName, wcslen(d.cFileName))); DO_AGGREGATE_ARRAY(120); } while(FindNextFileW(dir, &d)); err = GetLastError();
f168152005-01-06Henrik Grubbström (Grubba)  #ifdef READDIR_DEBUG
60b60b2010-11-01Martin Stjernholm  fprintf(stderr, " DONE, error %d\n", err);
f168152005-01-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
60b60b2010-11-01Martin Stjernholm  FindClose(dir);
f168152005-01-06Henrik Grubbström (Grubba) 
60b60b2010-11-01Martin Stjernholm  END_AGGREGATE_ARRAY;
f168152005-01-06Henrik Grubbström (Grubba) 
60b60b2010-11-01Martin Stjernholm  stack_pop_n_elems_keep_top(args); if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_FILES) { set_errno_from_win32_error (err); pop_stack(); push_int (0); return; } }
188dbb2014-03-03Henrik Grubbström (Grubba) }
f168152005-01-06Henrik Grubbström (Grubba)  #else /* !__NT__ */
71c0062014-03-03Henrik Grubbström (Grubba) /* Note: Also used from file_get_dir(). */ void low_get_dir(DIR *dir, ptrdiff_t name_max)
188dbb2014-03-03Henrik Grubbström (Grubba) { if(dir) {
b160d62004-03-17Henrik Grubbström (Grubba)  struct dirent *d; struct dirent *tmp = NULL; #if defined(_REENTRANT) && defined(HAVE_READDIR_R)
dfa0b61997-01-21Fredrik Hübinette (Hubbe) #define FPR 1024 char buffer[MAXPATHLEN * 4];
9c771d1997-01-22Henrik Grubbström (Grubba)  char *ptrs[FPR];
84f8952000-08-16Henrik Grubbström (Grubba)  ptrdiff_t lens[FPR];
c4a5942005-10-05Henrik Grubbström (Grubba) 
eaf8b91998-07-15Fredrik Hübinette (Hubbe) #ifndef NAME_MAX #define NAME_MAX 1024 #endif
0e90522005-10-05Ben Hutchings  if (name_max < NAME_MAX) name_max = NAME_MAX; if (name_max < 1024) name_max = 1024; if (!(tmp = malloc(sizeof(struct dirent) + name_max + 1))) {
c705d31997-02-28Fredrik Hübinette (Hubbe)  closedir(dir);
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("get_dir(): Out of memory\n");
c705d31997-02-28Fredrik Hübinette (Hubbe)  }
b160d62004-03-17Henrik Grubbström (Grubba) #endif /* _REENTRANT && HAVE_READDIR_R */
c705d31997-02-28Fredrik Hübinette (Hubbe) 
1e09782004-03-13Henrik Grubbström (Grubba)  BEGIN_AGGREGATE_ARRAY(10);
b160d62004-03-17Henrik Grubbström (Grubba) #if defined(_REENTRANT) && defined(HAVE_READDIR_R)
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  while(1) { int e; int num_files=0; char *bufptr=buffer;
a5c6ad1997-01-25Henrik Grubbström (Grubba)  int err = 0;
eaf8d91997-01-22Henrik Grubbström (Grubba) 
6f830e1997-01-22Henrik Grubbström (Grubba)  THREADS_ALLOW();
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  while(1) {
07228a1999-06-19Fredrik Hübinette (Hubbe) #if defined(HAVE_SOLARIS_READDIR_R)
601b1d1997-01-23Henrik Grubbström (Grubba)  /* Solaris readdir_r returns the second arg on success,
a4a1722000-12-05Per Hedbor  * and returns NULL on error or at end of dir.
601b1d1997-01-23Henrik Grubbström (Grubba)  */
f131a71997-01-27Fredrik Hübinette (Hubbe)  errno=0;
eaf8d91997-01-22Henrik Grubbström (Grubba)  do { d=readdir_r(dir, tmp); } while ((!d) && ((errno == EAGAIN)||(errno == EINTR))); if (!d) {
601b1d1997-01-23Henrik Grubbström (Grubba)  /* Solaris readdir_r seems to set errno to ENOENT sometimes. */
7962cb1998-07-02Henrik Grubbström (Grubba)  if (errno == ENOENT) { err = 0; } else { err = errno; }
6f830e1997-01-22Henrik Grubbström (Grubba)  break;
eaf8d91997-01-22Henrik Grubbström (Grubba)  }
601b1d1997-01-23Henrik Grubbström (Grubba) #elif defined(HAVE_HPUX_READDIR_R) /* HPUX's readdir_r returns an int instead: * * 0 - Successfull operation.
a4a1722000-12-05Per Hedbor  * -1 - End of directory or encountered an error (sets errno).
601b1d1997-01-23Henrik Grubbström (Grubba)  */
f131a71997-01-27Fredrik Hübinette (Hubbe)  errno=0;
601b1d1997-01-23Henrik Grubbström (Grubba)  if (readdir_r(dir, tmp)) { d = NULL; err = errno; break; } else { d = tmp; } #elif defined(HAVE_POSIX_READDIR_R) /* POSIX readdir_r returns 0 on success, and ERRNO on failure. * at end of dir it sets the third arg to NULL. */
7962cb1998-07-02Henrik Grubbström (Grubba)  d = NULL;
85d1b51998-07-02Henrik Grubbström (Grubba)  errno = 0;
601b1d1997-01-23Henrik Grubbström (Grubba)  if ((err = readdir_r(dir, tmp, &d)) || !d) {
c679f61998-07-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
188dbb2014-03-03Henrik Grubbström (Grubba)  fprintf(stderr, "POSIX readdir_r() => err %d\n", err); fprintf(stderr, "POSIX readdir_r(), d= 0x%08x\n", (unsigned int)d);
c679f61998-07-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
7962cb1998-07-02Henrik Grubbström (Grubba)  if (err == -1) {
2290ef1998-08-06Henrik Grubbström (Grubba)  /* Solaris readdir_r returns -1, and sets errno. */
7962cb1998-07-02Henrik Grubbström (Grubba)  err = errno; }
c679f61998-07-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
188dbb2014-03-03Henrik Grubbström (Grubba)  fprintf(stderr, "POSIX readdir_r() => errno %d\n", err);
c679f61998-07-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
7962cb1998-07-02Henrik Grubbström (Grubba)  /* Solaris readdir_r seems to set errno to ENOENT sometimes.
2290ef1998-08-06Henrik Grubbström (Grubba)  * * AIX readdir_r seems to set errno to EBADF at end of dir.
7962cb1998-07-02Henrik Grubbström (Grubba)  */
2290ef1998-08-06Henrik Grubbström (Grubba)  if ((err == ENOENT) || (err == EBADF)) {
7962cb1998-07-02Henrik Grubbström (Grubba)  err = 0; }
601b1d1997-01-23Henrik Grubbström (Grubba)  break; }
c679f61998-07-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG
188dbb2014-03-03Henrik Grubbström (Grubba)  fprintf(stderr, "POSIX readdir_r() => \"%s\"\n", d->d_name);
c679f61998-07-06Henrik Grubbström (Grubba) #endif /* READDIR_DEBUG */
601b1d1997-01-23Henrik Grubbström (Grubba) #else
a4a1722000-12-05Per Hedbor #error Unknown readdir_r variant
601b1d1997-01-23Henrik Grubbström (Grubba) #endif
99b8c22003-02-26Henrik Grubbström (Grubba)  /* Filter "." and ".." from the list. */
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  if(d->d_name[0]=='.') {
99b8c22003-02-26Henrik Grubbström (Grubba)  if(NAMLEN(d)==1) continue; if(d->d_name[1]=='.' && NAMLEN(d)==2) continue;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  } if(num_files >= FPR) break; lens[num_files]=NAMLEN(d);
9c771d1997-01-22Henrik Grubbström (Grubba)  if(bufptr+lens[num_files] >= buffer+sizeof(buffer)) break;
59fc9e2014-09-03Martin Nilsson  memcpy(bufptr, d->d_name, lens[num_files]);
9c771d1997-01-22Henrik Grubbström (Grubba)  ptrs[num_files]=bufptr; bufptr+=lens[num_files];
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  num_files++; } THREADS_DISALLOW();
601b1d1997-01-23Henrik Grubbström (Grubba)  if ((!d) && err) {
27e8452004-05-19Martin Nilsson  free(tmp);
188dbb2014-03-03Henrik Grubbström (Grubba)  Pike_error("get_dir(): readdir_r() failed: %d\n", err);
6f830e1997-01-22Henrik Grubbström (Grubba)  }
e0c51f2009-08-06Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG fprintf(stderr, "Pushing %d filenames...\n", num_files); #endif /* READDIR_DEBUG */
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  for(e=0;e<num_files;e++) {
9c771d1997-01-22Henrik Grubbström (Grubba)  push_string(make_shared_binary_string(ptrs[e],lens[e]));
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  } if(d) push_string(make_shared_binary_string(d->d_name,NAMLEN(d))); else break;
1e09782004-03-13Henrik Grubbström (Grubba)  DO_AGGREGATE_ARRAY(120);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  }
1e09782004-03-13Henrik Grubbström (Grubba) 
b160d62004-03-17Henrik Grubbström (Grubba)  free(tmp);
dfa0b61997-01-21Fredrik Hübinette (Hubbe) #else
5267b71995-08-09Fredrik Hübinette (Hubbe)  for(d=readdir(dir); d; d=readdir(dir)) {
188dbb2014-03-03Henrik Grubbström (Grubba) #ifdef READDIR_DEBUG fprintf(stderr, "readdir(): %s\n", d->d_name); #endif /* READDIR_DEBUG */
11d4182003-07-03Henrik Grubbström (Grubba)  /* Filter "." and ".." from the list. */
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(d->d_name[0]=='.') {
5f58422003-02-26Henrik Grubbström (Grubba)  if(NAMLEN(d)==1) continue; if(d->d_name[1]=='.' && NAMLEN(d)==2) continue;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b8c7982000-07-21Henrik Grubbström (Grubba)  push_string(make_shared_binary_string(d->d_name, NAMLEN(d)));
1e09782004-03-13Henrik Grubbström (Grubba)  DO_AGGREGATE_ARRAY(120);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
b160d62004-03-17Henrik Grubbström (Grubba) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  closedir(dir);
1e09782004-03-13Henrik Grubbström (Grubba) 
b160d62004-03-17Henrik Grubbström (Grubba)  END_AGGREGATE_ARRAY; } else {
188dbb2014-03-03Henrik Grubbström (Grubba)  push_int(0); } } void f_get_dir(INT32 args) { #ifdef USE_FDOPENDIR int dir_fd; #endif DIR *dir = NULL; #ifdef HAVE_READDIR_R ptrdiff_t name_max = -1; #endif struct pike_string *str=0; get_all_args("get_dir",args,".%N",&str); if(!str) { #if defined(__amigaos4__) push_empty_string(); #else
7cf0162014-05-22Per Hedbor  push_text(".");
188dbb2014-03-03Henrik Grubbström (Grubba) #endif str = Pike_sp[-1].u.string; args++; } if (string_has_null(str)) { /* Filenames with NUL are not supported. */ errno = ENOENT;
1e09782004-03-13Henrik Grubbström (Grubba)  pop_n_elems(args);
5267b71995-08-09Fredrik Hübinette (Hubbe)  push_int(0);
188dbb2014-03-03Henrik Grubbström (Grubba)  return;
1e09782004-03-13Henrik Grubbström (Grubba)  }
188dbb2014-03-03Henrik Grubbström (Grubba)  THREADS_ALLOW_UID(); #ifdef USE_FDOPENDIR dir_fd = open(str->str, O_RDONLY); if (dir_fd != -1) { #ifdef USE_FPATHCONF name_max = fpathconf(dir_fd, _PC_NAME_MAX); #endif /* USE_FPATHCONF */ dir = fdopendir(dir_fd); if (!dir) close(dir_fd); } #else dir = opendir(str->str); #ifdef USE_FPATHCONF if (dir) { name_max = fpathconf(dirfd(dir), _PC_NAME_MAX); } #endif #endif /* !HAVE_FDOPENDIR */ #ifdef USE_PATHCONF name_max = pathconf(str->str, _PC_NAME_MAX); #endif THREADS_DISALLOW_UID(); low_get_dir(dir, name_max); stack_pop_n_elems_keep_top(args);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
188dbb2014-03-03Henrik Grubbström (Grubba) #endif /* __NT__ */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int cd(string s) *! *! Change the current directory for the whole Pike process. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{1@} for success, @expr{0@} (zero) otherwise.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[getcwd()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_cd(INT32 args) { INT32 i;
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(!args)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("cd", 1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("cd", 1, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str = sp[-args].u.string;
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */ errno = ENOENT; pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  } i = chdir(str->str) != -1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(i); }
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl string getcwd() *! *! Returns the current working directory. *! *! @seealso *! @[cd()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_getcwd(INT32 args) { char *e;
921a531996-02-10Fredrik Hübinette (Hubbe)  char *tmp;
21685c1997-06-04Henrik Grubbström (Grubba) #if defined(HAVE_WORKING_GETCWD) || !defined(HAVE_GETWD)
921a531996-02-10Fredrik Hübinette (Hubbe)  INT32 size; size=1000; do {
dc8d022014-04-27Martin Nilsson  tmp=xalloc(size);
27e8452004-05-19Martin Nilsson  e = getcwd(tmp,size);
921a531996-02-10Fredrik Hübinette (Hubbe)  if (e || errno!=ERANGE) break;
74926b2001-06-07Henrik Grubbström (Grubba)  free(tmp);
21685c1997-06-04Henrik Grubbström (Grubba)  tmp=0;
921a531996-02-10Fredrik Hübinette (Hubbe)  size*=2; } while (size < 10000);
5c8e891995-10-29Fredrik Hübinette (Hubbe) #else
5ad6ac1995-09-25Per Hedbor #ifndef MAXPATHLEN
5c8e891995-10-29Fredrik Hübinette (Hubbe) #define MAXPATHLEN 32768
5ad6ac1995-09-25Per Hedbor #endif
21685c1997-06-04Henrik Grubbström (Grubba)  tmp=xalloc(MAXPATHLEN+1);
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_ALLOW_UID();
74926b2001-06-07Henrik Grubbström (Grubba)  e = getwd(tmp);
ef1e931998-03-26Henrik Grubbström (Grubba)  THREADS_DISALLOW_UID();
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
21685c1997-06-04Henrik Grubbström (Grubba)  if(!e) { if (tmp) free(tmp);
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Failed to fetch current path.\n");
21685c1997-06-04Henrik Grubbström (Grubba)  }
921a531996-02-10Fredrik Hübinette (Hubbe)  pop_n_elems(args);
90e0f72003-12-12Martin Nilsson  push_text(e);
abcca12007-01-25Henrik Grubbström (Grubba)  free(tmp);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
b26d672003-12-17Marcus Comstedt #ifdef HAVE_EXECVE
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int exece(string file, array(string) args)
74fbb42001-03-20Johan Sundström  *! @decl int exece(string file, array(string) args, @
ea30342001-01-31Henrik Grubbström (Grubba)  *! mapping(string:string) env) *!
039f852001-05-09Henrik Grubbström (Grubba)  *! This function transforms the Pike process into a process running *! the program specified in the argument @[file] with the arguments @[args].
ea30342001-01-31Henrik Grubbström (Grubba)  *!
039f852001-05-09Henrik Grubbström (Grubba)  *! If the mapping @[env] is present, it will completely replace all *! environment variables before the new program is executed.
ea30342001-01-31Henrik Grubbström (Grubba)  *!
039f852001-05-09Henrik Grubbström (Grubba)  *! @returns *! This function only returns if something went wrong during @tt{exece(2)@},
cbe8c92003-04-07Martin Nilsson  *! and in that case it returns @expr{0@} (zero).
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @note *! The Pike driver _dies_ when this function is called. You must either *! use @[fork()] or @[Process.create_process()] if you wish to execute a *! program and still run the Pike runtime. *!
b26d672003-12-17Marcus Comstedt  *! This function is not available on all platforms. *!
ea30342001-01-31Henrik Grubbström (Grubba)  *! @seealso *! @[Process.create_process()], @[fork()], @[Stdio.File->pipe()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_exece(INT32 args) { INT32 e; char **argv, **env;
85f59e1998-01-08Fredrik Hübinette (Hubbe)  struct svalue *save_sp; struct mapping *en;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef DECLARE_ENVIRON
5267b71995-08-09Fredrik Hübinette (Hubbe)  extern char **environ;
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  save_sp=sp-args; if(args < 2)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("exece", 2);
5267b71995-08-09Fredrik Hübinette (Hubbe)  e=0;
cb22561995-10-11Fredrik Hübinette (Hubbe)  en=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  switch(args) { default:
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[2-args]) != T_MAPPING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 3, "mapping(string:string)");
5267b71995-08-09Fredrik Hübinette (Hubbe)  en=sp[2-args].u.mapping;
4ecaeb1996-06-09Fredrik Hübinette (Hubbe)  mapping_fix_type_field(en);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
4ecaeb1996-06-09Fredrik Hübinette (Hubbe)  if(m_ind_types(en) & ~BIT_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 3, "mapping(string:string)");
4ecaeb1996-06-09Fredrik Hübinette (Hubbe)  if(m_val_types(en) & ~BIT_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 3, "mapping(string:string)");
5267b71995-08-09Fredrik Hübinette (Hubbe)  case 2:
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[1-args]) != T_ARRAY)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 2, "array(string)");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
2575242004-05-14Martin Nilsson  if(array_fix_type_field(sp[1-args].u.array) & ~BIT_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 2, "array(string)");
5267b71995-08-09Fredrik Hübinette (Hubbe)  case 1:
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[0-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("exece", 1, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
dc8d022014-04-27Martin Nilsson  argv=xalloc((2+sp[1-args].u.array->size) * sizeof(char *));
5267b71995-08-09Fredrik Hübinette (Hubbe)  argv[0]=sp[0-args].u.string->str; for(e=0;e<sp[1-args].u.array->size;e++) { union anything *a; a=low_array_get_item_ptr(sp[1-args].u.array,e,T_STRING); argv[e+1]=a->string->str; } argv[e+1]=0;
cb22561995-10-11Fredrik Hübinette (Hubbe)  if(en)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ae08e12010-09-12Henrik Grubbström (Grubba)  INT32 e, i = 0;
27e8452004-05-19Martin Nilsson  struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
3a1a3b2014-11-03Martin Nilsson  env=calloc(1+m_sizeof(en), sizeof(char *));
27e8452004-05-19Martin Nilsson  if(!env) { free(argv); SIMPLE_OUT_OF_MEMORY_ERROR("exece", (1+m_sizeof(en)*sizeof(char *))); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
27e8452004-05-19Martin Nilsson  NEW_MAPPING_LOOP(en->data) {
2a38db2015-02-17Tobias S. Josefowitz  ref_push_string(k->ind.u.string);
7cf0162014-05-22Per Hedbor  push_text("=");
2a38db2015-02-17Tobias S. Josefowitz  ref_push_string(k->val.u.string);
7bd0ea1996-02-19Fredrik Hübinette (Hubbe)  f_add(3);
ae08e12010-09-12Henrik Grubbström (Grubba)  env[i++]=sp[-1].u.string->str; dmalloc_touch_svalue(sp-1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
27e8452004-05-19Martin Nilsson 
ae08e12010-09-12Henrik Grubbström (Grubba)  env[i]=0;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ env=environ; }
fd36c61997-01-29Fredrik Hübinette (Hubbe)  my_set_close_on_exec(0,0); my_set_close_on_exec(1,0); my_set_close_on_exec(2,0); do_set_close_on_exec();
f8e4e71998-03-24Fredrik Hübinette (Hubbe)  #ifdef __NT__ #define DOCAST(X) ((const char * const *)(X)) #else #define DOCAST(X) (X) #endif
5539c51998-06-08Henrik Grubbström (Grubba)  #ifdef HAVE_BROKEN_F_SETFD do_close_on_exec(); #endif /* HAVE_BROKEN_F_SETFD */
f8e4e71998-03-24Fredrik Hübinette (Hubbe)  execve(argv[0],DOCAST(argv),DOCAST(env));
5267b71995-08-09Fredrik Hübinette (Hubbe)  free((char *)argv); if(env != environ) free((char *)env); pop_n_elems(sp-save_sp); push_int(0); }
b26d672003-12-17Marcus Comstedt #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int mv(string from, string to) *!
eb7b612001-04-18Martin Stjernholm  *! Rename or move a file or directory.
ea30342001-01-31Henrik Grubbström (Grubba)  *!
eb7b612001-04-18Martin Stjernholm  *! If the destination already exists, it will be replaced. *! Replacement often only works if @[to] is of the same type as
25cd432001-04-19Martin Stjernholm  *! @[from], i.e. a file can only be replaced by another file and so *! on. Also, a directory will commonly be replaced only if it's *! empty.
eb7b612001-04-18Martin Stjernholm  *! *! On some OSs this function can't move directories, only rename *! them.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns @expr{0@} (zero) on failure, @expr{1@} otherwise. Call
eb7b612001-04-18Martin Stjernholm  *! @[errno()] to get more error info on failure.
ea30342001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[rm()] */
5267b71995-08-09Fredrik Hübinette (Hubbe) void f_mv(INT32 args) { INT32 i;
b8c7982000-07-21Henrik Grubbström (Grubba)  struct pike_string *str1; struct pike_string *str2;
25cd432001-04-19Martin Stjernholm #ifdef __NT__ int orig_errno = errno; int err;
40962a2003-03-27Martin Stjernholm  PIKE_STAT_T st;
25cd432001-04-19Martin Stjernholm #endif
b8c7982000-07-21Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(args<2)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("mv", 2);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("mv", 1, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args+1]) != T_STRING)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("mv", 2, "string");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b8c7982000-07-21Henrik Grubbström (Grubba)  str1 = sp[-args].u.string; str2 = sp[1-args].u.string;
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str1) || string_has_null(str2)) {
76d9522000-08-23Henrik Grubbström (Grubba)  /* Filenames with NUL are not supported. */
2dd2ee2005-11-12Martin Nilsson  if (string_has_null(str1)) {
76d9522000-08-23Henrik Grubbström (Grubba)  errno = ENOENT; } else { errno = EINVAL; } pop_n_elems(args); push_int(0); return;
b8c7982000-07-21Henrik Grubbström (Grubba)  }
76d9522000-08-23Henrik Grubbström (Grubba) 
eb7b612001-04-18Martin Stjernholm #ifndef __NT__
b8c7982000-07-21Henrik Grubbström (Grubba)  i=rename(str1->str, str2->str);
eb7b612001-04-18Martin Stjernholm #else /* Emulate the behavior of unix rename(2) when the destination exists. */
25cd432001-04-19Martin Stjernholm  if (movefileex) { if (MoveFileEx (str1->str, str2->str, 0)) { i = 0; goto no_nt_rename_kludge; } if ((i = GetLastError()) != ERROR_ALREADY_EXISTS) goto no_nt_rename_kludge; } else { /* Fall back to rename() for W98 and earlier. Unlike MoveFileEx, * it can't move directories between directories. */ if (!rename (str1->str, str2->str)) { i = 0; goto no_nt_rename_kludge; } if ((i = errno) != EEXIST) goto no_nt_rename_kludge; }
eb7b612001-04-18Martin Stjernholm  #ifdef HAVE_LSTAT
25cd432001-04-19Martin Stjernholm  if (fd_lstat (str2->str, &st)) goto no_nt_rename_kludge;
eb7b612001-04-18Martin Stjernholm #else
25cd432001-04-19Martin Stjernholm  if (fd_stat (str2->str, &st)) goto no_nt_rename_kludge;
eb7b612001-04-18Martin Stjernholm #endif
25cd432001-04-19Martin Stjernholm  if ((st.st_mode & S_IFMT) != S_IFDIR && movefileex) { /* MoveFileEx can overwrite a file but not a dir. */ if (!(st.st_mode & _S_IWRITE)) /* Like in f_rm, we got to handle the case that NT looks on the * permissions on the file itself before removing it. */ if (chmod (str2->str, st.st_mode | _S_IWRITE)) goto no_nt_rename_kludge; if (movefileex (str1->str, str2->str, MOVEFILE_REPLACE_EXISTING)) i = 0; /* Success. */ else chmod (str2->str, st.st_mode); } else { char *s = malloc (str2->len + 2), *p; if (!s) { i = movefileex ? ERROR_NOT_ENOUGH_MEMORY : ENOMEM; goto no_nt_rename_kludge; } memcpy (s, str2->str, str2->len); p = s + str2->len; p[2] = 0; if ((st.st_mode & S_IFMT) == S_IFDIR) { /* Check first that the target is empty if it's a directory, so * that we won't even bother trying with the stunt below. */ WIN32_FIND_DATA *dir = malloc (sizeof (WIN32_FIND_DATA));
eb7b612001-04-18Martin Stjernholm  HANDLE h;
25cd432001-04-19Martin Stjernholm  if (!dir) { i = movefileex ? ERROR_NOT_ENOUGH_MEMORY : ENOMEM;
eb7b612001-04-18Martin Stjernholm  goto nt_rename_kludge_end; }
25cd432001-04-19Martin Stjernholm  p[0] = '/', p[1] = '*';
eb7b612001-04-18Martin Stjernholm  h = FindFirstFile (s, dir); if (h != INVALID_HANDLE_VALUE) { do { if (dir->cFileName[0] != '.' ||
6cef252004-11-20Martin Nilsson  (dir->cFileName[1] && (dir->cFileName[1] != '.' || dir->cFileName[2]))) {
eb7b612001-04-18Martin Stjernholm  /* Target dir not empty. */ FindClose (h); free (dir); goto nt_rename_kludge_end; } } while (FindNextFile (h, dir)); FindClose (h); } free (dir);
25cd432001-04-19Martin Stjernholm  }
eb7b612001-04-18Martin Stjernholm 
25cd432001-04-19Martin Stjernholm  /* Move away the target temporarily to do the move, then cleanup * or undo depending on how it went. */ for (p[0] = 'A'; p[0] != 'Z'; p[0]++) for (p[1] = 'A'; p[1] != 'Z'; p[1]++) { if (movefileex) {
6cef252004-11-20Martin Nilsson  if (!movefileex (str2->str, s, 0)) {
25cd432001-04-19Martin Stjernholm  if (GetLastError() == ERROR_ALREADY_EXISTS) continue; else goto nt_rename_kludge_end;
6cef252004-11-20Martin Nilsson  }
25cd432001-04-19Martin Stjernholm  }
6cef252004-11-20Martin Nilsson  else { if (rename (str2->str, s)) {
25cd432001-04-19Martin Stjernholm  if (errno == EEXIST) continue; else goto nt_rename_kludge_end;
6cef252004-11-20Martin Nilsson  } }
25cd432001-04-19Martin Stjernholm  if (movefileex ? movefileex (str1->str, str2->str, MOVEFILE_REPLACE_EXISTING) : !rename (str1->str, str2->str)) { if (!(st.st_mode & _S_IWRITE)) if (chmod (s, st.st_mode | _S_IWRITE)) goto nt_rename_kludge_fail;
8da5632012-03-14Henrik Grubbström (Grubba)  if ((st.st_mode & S_IFMT) == S_IFDIR) { while ((err = rmdir (s)) && (errno == EINTR)) ; } else { while ((err = unlink (s)) && (errno == EINTR)) ; }
25cd432001-04-19Martin Stjernholm  if (!err) { /* Success. */ i = 0;
eb7b612001-04-18Martin Stjernholm  goto nt_rename_kludge_end; }
25cd432001-04-19Martin Stjernholm  nt_rename_kludge_fail: /* Couldn't remove the old target, perhaps the directory * grew files. */ if (!(st.st_mode & _S_IWRITE)) chmod (s, st.st_mode); if (movefileex ? !movefileex (str2->str, str1->str, MOVEFILE_REPLACE_EXISTING) : rename (str2->str, str1->str)) { /* Old target left behind but the rename is still * successful, so we claim success anyway in lack of * better error reporting capabilities. */ i = 0;
eb7b612001-04-18Martin Stjernholm  goto nt_rename_kludge_end;
25cd432001-04-19Martin Stjernholm  } } rename (s, str2->str); goto nt_rename_kludge_end; }
eb7b612001-04-18Martin Stjernholm  nt_rename_kludge_end:
25cd432001-04-19Martin Stjernholm  free (s);
eb7b612001-04-18Martin Stjernholm  }
25cd432001-04-19Martin Stjernholm no_nt_rename_kludge: if (i) { if (movefileex) switch (i) { /* Try to translate NT errors to errno codes that NT's rename() * would return. */ case ERROR_INVALID_NAME: errno = EINVAL; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; case ERROR_ALREADY_EXISTS: errno = EEXIST; break; default: errno = EACCES;
eb7b612001-04-18Martin Stjernholm  } }
25cd432001-04-19Martin Stjernholm  else errno = orig_errno;
eb7b612001-04-18Martin Stjernholm #endif /* __NT__ */
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_n_elems(args); push_int(!i); }
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl string strerror(int errno) *! *! This function returns a description of an error code. The error *! code is usually obtained from eg @[Stdio.File->errno()]. *! *! @note *! On some platforms the string returned can be somewhat nondescriptive. */
f5ac331996-06-21Fredrik Hübinette (Hubbe) void f_strerror(INT32 args) { char *s;
1bd05b2000-03-16Martin Stjernholm  int err;
f5ac331996-06-21Fredrik Hübinette (Hubbe)  if(!args)
8e8ff82003-01-05Martin Nilsson  SIMPLE_TOO_FEW_ARGS_ERROR("strerror", 1);
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_INT)
8e8ff82003-01-05Martin Nilsson  SIMPLE_BAD_ARG_ERROR("strerror", 1, "int");
f5ac331996-06-21Fredrik Hübinette (Hubbe) 
1bd05b2000-03-16Martin Stjernholm  err = sp[-args].u.integer;
f5ac331996-06-21Fredrik Hübinette (Hubbe)  pop_n_elems(args);
1bd05b2000-03-16Martin Stjernholm  if(err < 0 || err > 256 ) s=0; else { #ifdef HAVE_STRERROR s=strerror(err); #else s=0; #endif }
f5ac331996-06-21Fredrik Hübinette (Hubbe)  if(s) push_text(s);
1bd05b2000-03-16Martin Stjernholm  else {
7cf0162014-05-22Per Hedbor  push_text("Error ");
1bd05b2000-03-16Martin Stjernholm  push_int(err); f_add(2); }
f5ac331996-06-21Fredrik Hübinette (Hubbe) }
ea30342001-01-31Henrik Grubbström (Grubba) /*! @decl int errno() *! *! This function returns the system error from the last file operation. *! *! @note *! Note that you should normally use @[Stdio.File->errno()] instead. *! *! @seealso *! @[Stdio.File->errno()], @[strerror()] */
d9fe5e2013-11-05Per Hedbor static void f_errno(INT32 args)
06983f1996-09-22Fredrik Hübinette (Hubbe) { pop_n_elems(args); push_int(errno); }
d9fe5e2013-11-05Per Hedbor 
1b85572013-11-05Henrik Grubbström (Grubba) #if defined(HAVE_ACCESS)
d9fe5e2013-11-05Per Hedbor /*! @decl int access( string path, string|void mode ) *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! access() checks if the calling process can access the file
d9fe5e2013-11-05Per Hedbor  *! @[path]. Symbolic links are dereferenced. *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @param mode *! The @[mode] specifies the accessibility checks to be performed, and *! is either not specified or empty, in which case access() just tests *! if the file exists, or one or more of the characters @expr{"rwx"@}.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! r, w, and x test whether the file exists and grants read, write, *! and execute permissions, respectively.
d9fe5e2013-11-05Per Hedbor  *! *! The check is done using the calling process's real UID and GID, *! rather than the effective IDs as is done when actually attempting *! an operation (e.g., open(2)) on the file. This allows set-user-ID *! programs to easily determine the invoking user's authority. *! *! If the calling process is privileged (i.e., its real UID is zero), *! then an X_OK check is successful for a regular file if execute *! permission is enabled for any of the file owner, group, or other. *! *! @returns
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @int *! @value 1 *! When the file is accessible using the given permissions.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @value 0 *! When the file is not accessible, in which case @[errno] is set *! to one of the following values:
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @int *! @value EACCESS *! Access denied.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @value ELOOP *! Too many symbolic links.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @value ENAMETOOLONG *! The path is too long.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @value ENOENT *! The file does not exist.
d9fe5e2013-11-05Per Hedbor  *!
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @value ENOTDIR *! One of the directories used in @[path] is not, in fact, a directory. *! *! @value EROFS *! The filesystem is read only and write access was requested. *! @endint
d9fe5e2013-11-05Per Hedbor  *!
21cd682013-11-05Henrik Grubbström (Grubba)  *! Other errors can occur, but are not directly related to the *! requested path, such as @expr{ENOMEM@}, etc. *! @endint
d9fe5e2013-11-05Per Hedbor  *! *! @seealso
66f9d82013-11-05Henrik Grubbström (Grubba)  *! @[errno()], @[Stdio.File]
d9fe5e2013-11-05Per Hedbor  */
1b85572013-11-05Henrik Grubbström (Grubba) static void f_access( INT32 args )
d9fe5e2013-11-05Per Hedbor { const char *path; int flags, res; if( args == 2 ) { char *how; int i; get_all_args( "access", args, "%s%s", &path, &how ); flags = 0; for( i=0; how[i]; i++ ) { switch( how[i] ) { case 'r': flags |= R_OK; break; case 'w': flags |= W_OK; break; case 'x': flags |= X_OK; break; } } if( !flags ) flags = F_OK; } else { get_all_args( "access", args, "%s", &path ); flags = F_OK; } THREADS_ALLOW_UID(); do { res = access( path, flags ); } while( (res == -1) && (errno == EINTR) ) THREADS_DISALLOW_UID(); pop_n_elems(args); push_int( !res ); }
1b85572013-11-05Henrik Grubbström (Grubba) #endif
d9fe5e2013-11-05Per Hedbor 
29f9a92013-06-11Martin Nilsson void init_stdio_efuns(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { set_close_on_exec(0,1); set_close_on_exec(1,1); set_close_on_exec(2,1);
6d8b9b2009-08-07Henrik Grubbström (Grubba) #if 0
e0c51f2009-08-06Henrik Grubbström (Grubba) #ifdef HAVE_LIBZFS_INIT libzfs_handle = libzfs_init(); #endif
6d8b9b2009-08-07Henrik Grubbström (Grubba) #endif /* 0 */
e0c51f2009-08-06Henrik Grubbström (Grubba) 
25cd432001-04-19Martin Stjernholm #ifdef __NT__
6df2e12001-10-02Fredrik Hübinette (Hubbe)  { /* MoveFileEx doesn't exist in W98 and earlier. */ /* Correction, it exists but does not work -Hubbe */ OSVERSIONINFO osversion; osversion.dwOSVersionInfoSize=sizeof(osversion); if(GetVersionEx(&osversion)) { switch(osversion.dwPlatformId) { case VER_PLATFORM_WIN32s: /* win32s */ case VER_PLATFORM_WIN32_WINDOWS: /* win9x */ break; default: if ((kernel32lib = LoadLibrary ("kernel32"))) movefileex = (movefileextype) GetProcAddress (kernel32lib, "MoveFileExA"); } } }
25cd432001-04-19Martin Stjernholm #endif
ded48d2002-11-28Martin Nilsson /* function(string,int|void:object) */
1f33e52005-04-08Martin Nilsson  ADD_EFUN("file_stat",f_file_stat,tFunc(tStr tOr(tInt,tVoid),tObjIs_STDIO_STAT), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
cdf56e1999-05-19Mirar (Pontus Hagland) 
ded48d2002-11-28Martin Nilsson  /* function(string,int:int(0..1)) */ ADD_EFUN("file_truncate",f_file_truncate,tFunc(tStr tInt,tInt),OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
d9fe5e2013-11-05Per Hedbor #if defined(HAVE_ACCESS)
1b85572013-11-05Henrik Grubbström (Grubba)  ADD_EFUN("access", f_access, tFunc(tStr tOr(tVoid,tStr),tInt),OPT_EXTERNAL_DEPEND);
d9fe5e2013-11-05Per Hedbor #endif
3c44292005-04-29Per Hedbor #if defined(HAVE_FSETXATTR) && defined(HAVE_FGETXATTR) && defined(HAVE_FLISTXATTR) ADD_EFUN( "listxattr", f_listxattr, tFunc(tStr tOr(tVoid,tInt),tArr(tStr)), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT); ADD_EFUN( "setxattr", f_setxattr, tFunc(tStr tStr tStr tInt tOr(tVoid,tInt),tInt), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT); ADD_EFUN( "getxattr", f_getxattr, tFunc(tStr tStr tOr(tVoid,tInt),tStr), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT); ADD_EFUN( "removexattr", f_removexattr, tFunc(tStr tStr tOr(tVoid,tInt),tInt), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT); #endif
cdf56e1999-05-19Mirar (Pontus Hagland) 
6469a41998-10-27Per Hedbor #if defined(HAVE_STATVFS) || defined(HAVE_STATFS) || defined(HAVE_USTAT) || defined(__NT__)
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:mapping(string:string|int)) */
869bc32004-05-13Martin Stjernholm  ADD_EFUN("filesystem_stat", f_filesystem_stat,tFunc(tStr,tMap(tStr,tOr(tStr,tInt))), OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
485a1e1997-06-01Henrik Grubbström (Grubba) #endif /* HAVE_STATVFS || HAVE_STATFS */
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:int) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_EFUN("errno",f_errno,tFunc(tNone,tInt),OPT_EXTERNAL_DEPEND);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:int) */ ADD_EFUN("rm",f_rm,tFunc(tStr,tInt),OPT_SIDE_EFFECT); /* function(string,void|int:int) */ ADD_EFUN("mkdir",f_mkdir,tFunc(tStr tOr(tVoid,tInt),tInt),OPT_SIDE_EFFECT); /* function(string,string:int) */ ADD_EFUN("mv", f_mv,tFunc(tStr tStr,tInt), OPT_SIDE_EFFECT); /* function(string:string *) */
b1510a2004-10-24Martin Nilsson  ADD_EFUN("get_dir",f_get_dir,tFunc(tOr(tVoid,tStr),tArr(tStr)),OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:int) */ ADD_EFUN("cd",f_cd,tFunc(tStr,tInt),OPT_SIDE_EFFECT); /* function(:string) */
869bc32004-05-13Martin Stjernholm  ADD_EFUN("getcwd",f_getcwd,tFunc(tNone,tStr),OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
b26d672003-12-17Marcus Comstedt  #ifdef HAVE_EXECVE
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(string,mixed*,void|mapping(string:string):int) */ ADD_EFUN("exece",f_exece,tFunc(tStr tArr(tMix) tOr(tVoid,tMap(tStr,tStr)),tInt),OPT_SIDE_EFFECT);
b26d672003-12-17Marcus Comstedt #endif
f5ac331996-06-21Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe) /* function(int:string) */ ADD_EFUN("strerror",f_strerror,tFunc(tInt,tStr),0);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
25cd432001-04-19Martin Stjernholm 
29f9a92013-06-11Martin Nilsson void exit_stdio_efuns(void)
25cd432001-04-19Martin Stjernholm { #ifdef __NT__ if (kernel32lib) { if (FreeLibrary (kernel32lib)) movefileex = 0; kernel32lib = 0; } #endif
6d8b9b2009-08-07Henrik Grubbström (Grubba) #if 0
e0c51f2009-08-06Henrik Grubbström (Grubba) #ifdef HAVE_LIBZFS_INIT libzfs_fini(libzfs_handle); #endif
6d8b9b2009-08-07Henrik Grubbström (Grubba) #endif /* 0 */
25cd432001-04-19Martin Stjernholm }