view xd.c @ 0:e0bbaa717f41 draft default tip

lol J
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 25 Nov 2013 11:56:30 -0500 (2013-11-25)
parents
children
line wrap: on
line source
/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Xenos: file directory, attributes, & permission                         */

#ifdef _WIN32
#include <windows.h>
#include <winbase.h>
#endif

#include "j.h"
#include "x.h"

#if !SY_WINCE
char* toascbuf(char* s){ return s;}
char* tounibuf(char* s){ return s;}
#else
wchar_t* tounibuf(char* src)
{
	static wchar_t buf[2048+1];

	wchar_t* p=buf;
	if(2048>strlen(src))
	{
		while(*src)	*p++=*src++;
	}
	*p=0;
	return buf;
}

char *toascbuf(wchar_t *src)
{
	static char buf[2048+1];

	char* p=buf;
	if(2048>wcslen(src))
	{
		while(*src)	*p++=(char)*src++;
	}
	*p=0;
	return buf;
}
#define _A_NORMAL   FILE_ATTRIBUTE_NORMAL
#define _A_RDONLY   FILE_ATTRIBUTE_READONLY
#define _A_HIDDEN   FILE_ATTRIBUTE_HIDDEN
#define _A_SYSTEM   FILE_ATTRIBUTE_SYSTEM
#define _A_VOLID    0
#define _A_SUBDIR   FILE_ATTRIBUTE_DIRECTORY
#define _A_ARCH     FILE_ATTRIBUTE_ARCHIVE

#endif 

#if (SYS & SYS_DOS)

#if !SY_WINCE
#include <ctype.h>
#include <io.h>
#include <dos.h>
#include <direct.h>
#include <time.h>
#endif

#ifndef F_OK            /* for access() */
#define F_OK            0x00
#define X_OK            0x01
#define W_OK            0x02
#define R_OK            0x04
#endif

#ifndef _A_VOLID
#define _A_VOLID        0x00
#endif

#define _A_ALL          (_A_NORMAL+_A_RDONLY+_A_HIDDEN+_A_SYSTEM+_A_VOLID+ \
                         _A_SUBDIR+_A_ARCH)

static A jtattv(J jt,U x){A z;C*s;
 GA(z,LIT,6,1,0); s=CAV(z);
 s[0]=x&_A_RDONLY?'r':'-';
 s[1]=x&_A_HIDDEN?'h':'-';
 s[2]=x&_A_SYSTEM?'s':'-';
 s[3]=x&_A_VOLID ?'v':'-';
 s[4]=x&_A_SUBDIR?'d':'-';
 s[5]=x&_A_ARCH  ?'a':'-';
 R z;
}    /* convert from 16-bit attributes x into 6-element string */

static S jtattu(J jt,A w){C*s;I i,n;S z=0;
 RZ(w=vs(w)); 
 n=AN(w); s=CAV(w);
 for(i=0;i<n;++i)switch(s[i]){
  case 'r': z^=_A_RDONLY; break;
  case 'h': z^=_A_HIDDEN; break;
  case 's': z^=_A_SYSTEM; break;
  case 'v': z^=_A_VOLID;  break;
  case 'd': z^=_A_SUBDIR; break;
  case 'a': z^=_A_ARCH;   break;
  case '-':               break;
  default:  ASSERT(0,EVDOMAIN);
 }
 R z;
}    /* convert from 6-element string into 16-bit attributes */

F1(jtfullname){C*s; C dirpath[1000];
 RZ(w=str0(w));
 s=CAV(w); DO(AN(w), if(' '!=*s)break; ++s;);
#if SY_WINCE
 if(*s=='\\'||*s=='/') strcpy(dirpath,s);
 else {strcpy(dirpath, "\\"); strcat(dirpath,s);}
#else
 _fullpath(dirpath,s,NPATH); 
#endif
 R cstr(dirpath);
}

#if !SY_WINCE

F1(jtjfperm1){A y,fn,z;C *s;F f;int x; US *p,*q;
 F1RANK(0,jtjfperm1,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=AAV0(w);
 RZ(fn=toutf16x(y));
 p=USAV(fn); q=p+AN(fn)-3;
 GA(z,LIT,3,1,0); s=CAV(z);
 x=_waccess(p,R_OK); if(0>x)R jerrno();
 s[0]=x?'-':'r';
 s[1]=_waccess(p,W_OK)?'-':'w';
 s[2]=wcscmp(q,L"exe")&&wcscmp(q,L"bat")&&wcscmp(q,L"com")?'-':'x';
 R z;
}

F2(jtjfperm2){A y,fn;C*s;F f;int x=0;US *p;
 F2RANK(1,0,jtjfperm2,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=AAV0(w);
 RZ(a=vs(a)); ASSERT(3==AN(a),EVLENGTH); 
 RZ(fn=toutf16x(y));
 s=CAV(y);
 p=USAV(fn);;
 s=CAV(a);
 if('r'==s[0]) x|=S_IREAD;  else ASSERT('-'==s[0],EVDOMAIN);
 if('w'==s[1]) x|=S_IWRITE; else ASSERT('-'==s[1],EVDOMAIN);
 if('x'==s[2]) x|=S_IEXEC;  else ASSERT('-'==s[2],EVDOMAIN);
 R _wchmod(p,x)?jerrno():mtm;
}

#else /* SY_WINCE: */

F1(jtjfperm1){A y,z;C*p,*q,*s;F f; DWORD attr;
 F1RANK(0,jtjfperm1,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=AAV0(w);
 p=CAV(y); q=p+AN(y)-3;
 GA(z,LIT,3,1,0); s=CAV(z);
 if((attr=GetFileAttributes(tounibuf(p)))==0xFFFFFFFF)R jerrno();
 s[0]='r';
 s[1]=attr&FILE_ATTRIBUTE_READONLY?'-':'w';
 s[2]=strcmp(q,"exe")&&strcmp(q,"bat")&&strcmp(q,"com")?'-':'x';
 R z;
}

F2(jtjfperm2){ASSERT(0,EVNONCE);}

#endif
#endif

/* jdir produces a 5-column matrix of boxes:                 */
/* 0 name                                                    */
/* 1 time of last write, y m d h m s                         */
/* 2 size                                                    */
/* 3 permission -- 0 read  1 write  2 execute                */
/* 4 attributes                                              */
/*   0 read-only    3 volume label                           */
/*   1 hidden       4 directory                              */
/*   2 system       5 archive (modified since last back-up)  */

#if SY_WIN32

#include <stdlib.h>

UINT getfileattr(char *);
int setfileattr(char*, UINT);

static A jtdir1(J jt,LPWIN32_FIND_DATAW f,C* fn) {A z,*zv;C rwx[3],*s,*t;I n,ts[6];
 FILETIME local_ftime; SYSTEMTIME x;

 FileTimeToLocalFileTime(&f->ftLastWriteTime, &local_ftime);
 FileTimeToSystemTime(&local_ftime, &x);
 ts[0]=x.wYear;   ts[1]=x.wMonth;  ts[2]=x.wDay;
 ts[3]=x.wHour;   ts[4]=x.wMinute; ts[5]=x.wSecond;
 s=fn; n=strlen(s); t=s+n-3;
 rwx[0]='r';
 rwx[1]=f->dwFileAttributes & FILE_ATTRIBUTE_READONLY ?'-':'w';
 rwx[2]=strcmp(t,"exe")&&strcmp(t,"bat")&&strcmp(t,"com")?'-':'x';
 GA(z,BOX,5,1,0); zv=AAV(z);
 RZ(zv[0]=str(n,s)); 
 RZ(zv[1]=vec(INT,6L,ts));
#if SY_64
 RZ(zv[2]=sc(((I)f->nFileSizeHigh<<32) + (I)f->nFileSizeLow));
#else
 RZ(zv[2]=sc(   (f->nFileSizeHigh || 0>(I)f->nFileSizeLow)?-1:f->nFileSizeLow ));  
#endif
 RZ(zv[3]=str(3L,rwx));
 RZ(zv[4]=attv((S)f->dwFileAttributes));
 R z;
}

F1(jtjdir){PROLOG;A z,fn,*zv;I j=0,n=32;HANDLE fh; WIN32_FIND_DATAW f; C fnbuffer[10000]; C* name;
 RZ(w);
 RZ(w=vs(!AR(w)&&BOX&AT(w)?ope(w):w));
 RZ(fn=jttoutf16x(jt,w));
 fh=FindFirstFileW((US*)CAV(fn),&f);
 GA(z,BOX,n,1,0); zv=AAV(z);
 if (fh!=INVALID_HANDLE_VALUE) {
  do {
   jttoutf8x(jt,fnbuffer,sizeof fnbuffer,f.cFileName);
   name = fnbuffer;
   if(strcmp(name,".")&&strcmp(name,"..")){
    if(j==n){RZ(z=ext(0,z)); n=AN(z); zv=AAV(z);}
    RZ(zv[j++]=jtdir1(jt,&f,fnbuffer)); 
   }
  } while (FindNextFileW(fh,&f));
  FindClose(fh);
 }
 z=j?ope(j<n?vec(BOX,j,zv):z):reshape(v2(0L,5L),ace);
 EPILOG(z);
}

F1(jtjfatt1){A y,fn;F f;U x;
 F1RANK(0,jtjfatt1,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=AAV0(w);
 RZ(fn=toutf16x(y));
 x=GetFileAttributesW(USAV(fn));
 if(-1!=x) R attv(x);
 jsignal(EVFNAME); R 0; 
}

F2(jtjfatt2){A y,fn;F f;U x;
 F2RANK(1,0,jtjfatt2,0);
 RE(x=attu(a));
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=AAV0(w);
 RZ(fn=toutf16x(y));
 if(SetFileAttributesW(USAV(fn), x)) R one;
 jsignal(EVFNAME); R 0;
}

#endif

#if (SYS & SYS_UNIX)

/* FIXME:   rename J link() function so we can include unistd.h */
#define R_OK    4               /* Test for read permission.    */
#define W_OK    2               /* Test for write permission.   */
#define X_OK    1               /* Test for execute permission. */

#include <sys/stat.h>
#include <dirent.h>
#include <time.h>

#if SYS&(SYS_SUN4+SYS_SGI)
#include "fnmatch.h"
#else
#include <fnmatch.h>
#endif


/* Return mode_t formatted into a static 10-character buffer. */
static C*modebuf(mode_t m){C c;static C b[11];I t=m;
 strcpy(b+1,"rwxrwxrwx");
 DO(9, if(!(m&1))b[9-i]='-'; m>>=1;); 
 if(t&S_ISUID)b[3]=(b[3]=='x')?'s':'S';
 if(t&S_ISGID)b[6]=(b[6]=='x')?'s':'S';
 if(t&S_ISVTX)b[9]=(b[9]=='x')?'t':'T';
 switch(t&S_IFMT){
  case S_IFBLK:  b[0]='b'; break;
  case S_IFCHR:  b[0]='c'; break;
  case S_IFDIR:  b[0]='d'; break;
#if !(SYS & SYS_UNIX)
  case S_IFFIFO: b[0]='f'; break;    /*IVL */
#endif
  case S_IFLNK:  b[0]='l'; break;
  case S_IFSOCK: b[0]='s'; break;
  case S_IFREG:  b[0]='-'; break;
  default:       b[0]='?';
 }
 R b;
}

/* 
 linux32 stat fails on big files - so it uses stat64
 but can't get it to work with struct stat64
 so struct stat is used (wrong, but seems to work)
*/

#if SYS & SYS_LINUX
#define stat stat64
#endif

 
static int ismatch(J jt,C*pat,C*name){ 
 strcpy(jt->dirbase,name); if(stat(jt->dirnamebuf,&jt->dirstatbuf))R 0;
 if('.'!=*pat && ((!strcmp(name,"."))||(!strcmp(name,".."))))R 0;
 if(fnmatch(pat,name,0)) R 0;
/* Set up dirrwx, diratts, and dirmode for this file */
 jt->dirrwx[0]=access(jt->dirnamebuf,R_OK)?'-':'r';
 jt->dirrwx[1]=access(jt->dirnamebuf,W_OK)?'-':'w';
 jt->dirrwx[2]=access(jt->dirnamebuf,X_OK)?'-':'x';
 strcpy(jt->diratts,"------");
 jt->diratts[0]=(jt->dirrwx[0]=='r'&&jt->dirrwx[1]=='-')?'r':'-';
 jt->diratts[1]=('.'==name[0])?'h':'-';
 strcpy(jt->dirmode,modebuf(jt->dirstatbuf.st_mode));
 jt->diratts[4]=('d'==jt->dirmode[0])?'d':'-';
 R 1;
}

static A jtdir1(J jt,struct dirent*f){A z,*zv;C*s,att[16];I n,ts[6],i,m,sz;S x;struct tm *tm;
 tm=localtime(&jt->dirstatbuf.st_mtime);
 ts[0]=1900+tm->tm_year; ts[1]=1+tm->tm_mon; ts[2]=tm->tm_mday;
 ts[3]=tm->tm_hour; ts[4]=tm->tm_min; ts[5]=tm->tm_sec;
 s=f->d_name; n=strlen(s);
 GA(z,BOX,6,1,0); zv=AAV(z);
 RZ(zv[0]=vec(LIT,n,s)); 
 RZ(zv[1]=vec(INT,6L,ts));
 sz=jt->dirstatbuf.st_size;
 sz=sz<0?-1:sz;
 RZ(zv[2]=sc(sz));
 RZ(zv[3]=vec(LIT,3L, jt->dirrwx ));
 RZ(zv[4]=vec(LIT, 6L,jt->diratts));
 RZ(zv[5]=vec(LIT,10L,jt->dirmode));
 R z;
}

F1(jtjdir){PROLOG;A*v,z,*zv;C*dir,*pat,*s,*x;I j=0,n=32;DIR*DP;struct dirent *f;
 RZ(w);
 RZ(w=str0(vs(!AR(w)&&BOX&AT(w)?ope(w):w)));
 s=CAV(w);
 if(x=strrchr(s,'/')){dir=s==x?"/":s; pat=x+1; *x=0;}else{dir="."; pat=s;}
 if(NULL==(DP=opendir(dir)))R reshape(v2(0L,6L),ace);
 /*
  * SYSV and BSD have different return types for sprintf(),
  * so we use less efficient but portable code.
  */
 sprintf(jt->dirnamebuf,"%s/",dir); jt->dirbase=jt->dirnamebuf+strlen(jt->dirnamebuf); f=readdir(DP);
 GA(z,BOX,n,1,0); zv=AAV(z);
 while(f){
  if(ismatch(jt,pat,f->d_name)){
   if(j==n){RZ(z=ext(0,z)); n=AN(z); zv=AAV(z);}
   RZ(zv[j++]=dir1(f)); 
  }
  f=readdir(DP);
 }
 closedir(DP);
 z=j?ope(j<n?vec(BOX,j,zv):z):reshape(v2(0L,6L),ace);
 EPILOG(z);
}



F1(jtjfatt1){ASSERT(0,EVNONCE);}
F2(jtjfatt2){ASSERT(0,EVNONCE);}


F1(jtjfperm1){A y;F f;
 F1RANK(0,jtjfperm1,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=str0(AAV0(w));
 if(0!=stat(CAV(y),&jt->dirstatbuf))R jerrno();
 R vec(LIT,9L,1+modebuf(jt->dirstatbuf.st_mode));
}


static struct tperms {C*c;I p[4];} permtab[]=
    {  {"-r"  ,{0,S_IRUSR}},
       {"-w"  ,{0,S_IWUSR}},
       {"-xSs",{0,S_IXUSR,S_ISUID,S_ISUID+S_IXUSR}},
       {"-r"  ,{0,S_IRGRP}},
       {"-w"  ,{0,S_IWGRP}},
       {"-xSs",{0,S_IXGRP,S_ISGID,S_ISGID+S_IXGRP}},
       {"-r"  ,{0,S_IROTH}},
       {"-w"  ,{0,S_IWOTH}},
       {"-xTt",{0,S_IXOTH,S_ISVTX,S_ISVTX+S_IXOTH}},
    };

F2(jtjfperm2){A y;C*s;F f;int x=0,i;C*m;
 F2RANK(1,0,jtjfperm2,0);
 RE(f=stdf(w)); if(f)ASSERT(y=fname(sc((I)f)),EVFNUM) else y=str0(AAV0(w));
 RZ(a=vs(a)); ASSERT(9==AN(a),EVLENGTH); s=CAV(a);
 for(i=0;i<9;i++)
    {ASSERT(NULL!=(m=strchr(permtab[i].c,s[i])),EVDOMAIN);
     x|=permtab[i].p[m-permtab[i].c];}
 R chmod(CAV(y),x)?jerrno():mtm;
}


#endif

/* ----------------------------------------------------------------------- */


#if ! (SYS & SYS_DOS)
F1(jtfullname){R w;}
#endif