Add epoll and do more release readiness changes
This change also pays off some of the remaining technical debt with stdio, file descriptors, and memory managemnt polyfills.main
parent
a9ea949df8
commit
3e4fd4b0ad
2
Makefile
2
Makefile
|
@ -316,7 +316,7 @@ COSMOPOLITAN_HEADERS = \
|
||||||
|
|
||||||
o/$(MODE)/cosmopolitan.a: $(filter-out o/libc/stubs/exit11.o,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_OBJS)))
|
o/$(MODE)/cosmopolitan.a: $(filter-out o/libc/stubs/exit11.o,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_OBJS)))
|
||||||
o/cosmopolitan.h: \
|
o/cosmopolitan.h: \
|
||||||
o/$(MODE)/tool/build/rollup.com.dbg \
|
o/$(MODE)/tool/build/rollup.com \
|
||||||
libc/integral/normalize.inc \
|
libc/integral/normalize.inc \
|
||||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
|
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
|
||||||
@ACTION=ROLLUP TARGET=$@ build/do $^ >$@
|
@ACTION=ROLLUP TARGET=$@ build/do $^ >$@
|
||||||
|
|
205
ape/ape.S
205
ape/ape.S
|
@ -34,7 +34,6 @@
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/config.h"
|
#include "ape/config.h"
|
||||||
#include "ape/lib/apm.h"
|
|
||||||
#include "ape/lib/pc.h"
|
#include "ape/lib/pc.h"
|
||||||
#include "ape/macros.h"
|
#include "ape/macros.h"
|
||||||
#include "ape/notice.inc"
|
#include "ape/notice.inc"
|
||||||
|
@ -49,7 +48,7 @@
|
||||||
|
|
||||||
#define USE_SYMBOL_HACK 0
|
#define USE_SYMBOL_HACK 0
|
||||||
|
|
||||||
.source "NOTICE"
|
.source "LICENSE"
|
||||||
.source "ape/ape.S"
|
.source "ape/ape.S"
|
||||||
.source "ape/ape.lds"
|
.source "ape/ape.lds"
|
||||||
.section .text,"ax",@progbits
|
.section .text,"ax",@progbits
|
||||||
|
@ -360,85 +359,9 @@ pcread: push %ax
|
||||||
xor %ax,%ax # try disk reset on error
|
xor %ax,%ax # try disk reset on error
|
||||||
int $0x13
|
int $0x13
|
||||||
pop %ax
|
pop %ax
|
||||||
jmp 1b
|
jmp pcread
|
||||||
.endfn pcread
|
.endfn pcread
|
||||||
|
|
||||||
/ Waits for serial lines to become idle.
|
|
||||||
/
|
|
||||||
/ @param di short array of serial ports (0 means not present)
|
|
||||||
/ @param si number of items in array
|
|
||||||
/ @mode long,legacy,real
|
|
||||||
sflush: mov %si,%cx
|
|
||||||
mov %di,%si
|
|
||||||
xor %dx,%dx
|
|
||||||
0: lodsb
|
|
||||||
mov %al,%dl
|
|
||||||
lodsb
|
|
||||||
mov %al,%dh
|
|
||||||
test %ax,%ax
|
|
||||||
jz 2f
|
|
||||||
add $UART_LSR,%dx
|
|
||||||
mov $UART_TTYIDL,%ah
|
|
||||||
1: in %dx,%al
|
|
||||||
and %ah,%al
|
|
||||||
rep
|
|
||||||
nop
|
|
||||||
jz 1b
|
|
||||||
loop 0b
|
|
||||||
2: ret
|
|
||||||
.endfn sflush,globl
|
|
||||||
|
|
||||||
/ Transmits byte over serial line.
|
|
||||||
/
|
|
||||||
/ This is both blocking and asynchronous.
|
|
||||||
/
|
|
||||||
/ @param di character to send
|
|
||||||
/ @param si serial port
|
|
||||||
/ @mode long,legacy,real
|
|
||||||
/ @see ttytxr
|
|
||||||
sputc: push %ax
|
|
||||||
push %cx
|
|
||||||
push %dx
|
|
||||||
mov %si,%dx
|
|
||||||
add $UART_LSR,%dx
|
|
||||||
mov $UART_TTYTXR,%ah
|
|
||||||
1: in %dx,%al
|
|
||||||
and %ah,%al
|
|
||||||
jnz 2f
|
|
||||||
rep
|
|
||||||
nop
|
|
||||||
jmp 1b
|
|
||||||
2: mov %di,%ax
|
|
||||||
mov %si,%dx
|
|
||||||
out %al,%dx
|
|
||||||
pop %dx
|
|
||||||
pop %cx
|
|
||||||
pop %ax
|
|
||||||
ret
|
|
||||||
.endfn sputc,globl
|
|
||||||
|
|
||||||
/ Shuts down personal computer.
|
|
||||||
/
|
|
||||||
/ @mode real
|
|
||||||
/ @noreturn
|
|
||||||
apmoff: mov $0x5300,%ax # apm installation check
|
|
||||||
xor %bx,%bx # for the apm bios itself
|
|
||||||
int $APM_SERVICE
|
|
||||||
jc 1f
|
|
||||||
cmp $'P<<8|'M,%bx # did apm bios service interrupt?
|
|
||||||
jne 1f
|
|
||||||
mov $0x5301,%ax # real mode interface connect
|
|
||||||
xor %bx,%bx # to apm bios device
|
|
||||||
int $APM_SERVICE # ignore errors e.g. already connected
|
|
||||||
xor %bx,%bx
|
|
||||||
xor %cx,%cx
|
|
||||||
mov $0x5307,%ax # set power state
|
|
||||||
mov $1,%bl # for all devices within my dominion
|
|
||||||
mov $3,%cl # to off
|
|
||||||
int $APM_SERVICE
|
|
||||||
1: call panic
|
|
||||||
.endfn apmoff,globl
|
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼
|
│ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
@ -1156,115 +1079,41 @@ sinit: mov %di,%dx
|
||||||
2: ret
|
2: ret
|
||||||
.endfn sinit,global,hidden
|
.endfn sinit,global,hidden
|
||||||
|
|
||||||
/ Abnormally exits program.
|
|
||||||
/
|
|
||||||
/ @param di message
|
|
||||||
/ @mode real
|
|
||||||
/ @noreturn
|
|
||||||
rldie: call rlpute
|
|
||||||
call rloff
|
|
||||||
.endfn rldie,globl,hidden
|
|
||||||
|
|
||||||
/ Shuts down machine.
|
|
||||||
/
|
|
||||||
/ @mode real
|
|
||||||
/ @noreturn
|
|
||||||
rloff: mov $kBiosDataAreaXlm+COM1,%di
|
|
||||||
mov $4,%si
|
|
||||||
call sflush
|
|
||||||
call apmoff
|
|
||||||
.endfn rloff,globl,hidden
|
|
||||||
|
|
||||||
/ Prints error message.
|
|
||||||
/
|
|
||||||
/ @param di message
|
|
||||||
/ @mode real
|
|
||||||
rlpute: mov kBiosDataAreaXlm+METAL_STDERR(%bx),%si
|
|
||||||
test %si,%si
|
|
||||||
jnz 1f
|
|
||||||
mov kBiosDataAreaXlm+METAL_STDOUT,%si
|
|
||||||
1: xor %ax,%ax
|
|
||||||
push %ax
|
|
||||||
push %si
|
|
||||||
mov $REAL(.Lstr.crlf),%ax
|
|
||||||
push %ax
|
|
||||||
push %si
|
|
||||||
push %di
|
|
||||||
push %si
|
|
||||||
mov $REAL(.Lstr.error),%ax
|
|
||||||
push %ax
|
|
||||||
1: pop %di
|
|
||||||
test %di,%di
|
|
||||||
jz 2f
|
|
||||||
pop %si
|
|
||||||
call rlput2
|
|
||||||
jmp 1b
|
|
||||||
2: ret
|
|
||||||
.endfn rlpute,globl,hidden
|
|
||||||
|
|
||||||
/ Prints string to both video and serial.
|
|
||||||
/
|
|
||||||
/ @param di NUL-terminated string
|
|
||||||
/ @param si serial port
|
|
||||||
/ @mode real
|
|
||||||
rlput2: push %di
|
|
||||||
push %si
|
|
||||||
call rvputs
|
|
||||||
pop %si
|
|
||||||
pop %di
|
|
||||||
test %si,%si
|
|
||||||
jz 1f
|
|
||||||
call sputs
|
|
||||||
1: ret
|
|
||||||
.endfn rlput2,globl,hidden
|
|
||||||
|
|
||||||
/ Writes string to serial line.
|
|
||||||
/
|
|
||||||
/ @param di NUL-terminated string
|
|
||||||
/ @param si serial port
|
|
||||||
/ @mode long,legacy,real
|
|
||||||
sputs: push %bx
|
|
||||||
mov %di,%bx
|
|
||||||
1: xchg %bx,%si
|
|
||||||
lodsb
|
|
||||||
xchg %bx,%si
|
|
||||||
test %al,%al
|
|
||||||
jz 2f
|
|
||||||
mov %ax,%di
|
|
||||||
push %si
|
|
||||||
rlcall sputc
|
|
||||||
pop %si
|
|
||||||
jmp 1b
|
|
||||||
2: pop %bx
|
|
||||||
ret
|
|
||||||
.endfn sputs,globl
|
|
||||||
|
|
||||||
/ Video put string.
|
/ Video put string.
|
||||||
/
|
/
|
||||||
/ @param di is the string
|
/ @param di is the string
|
||||||
/ @mode real
|
/ @mode real
|
||||||
rvputs: mov %di,%si
|
rvputs: push %bp
|
||||||
|
push %bx
|
||||||
|
mov %di,%si
|
||||||
0: lodsb
|
0: lodsb
|
||||||
test %al,%al
|
test %al,%al
|
||||||
je 1f
|
je 1f
|
||||||
rlcall rvputc
|
|
||||||
jmp 0b
|
|
||||||
1: ret
|
|
||||||
.endfn rvputs,globl,hidden
|
|
||||||
|
|
||||||
/ Video put char.
|
|
||||||
/
|
|
||||||
/ @param al is the char
|
|
||||||
/ @mode real
|
|
||||||
rvputc: push %bx # don't clobber bp,bx,di,si,cx
|
|
||||||
push %bp # original ibm pc scroll up bug
|
|
||||||
mov $7,%bx # normal mda/cga style page zero
|
mov $7,%bx # normal mda/cga style page zero
|
||||||
mov $0x0e,%ah # teletype output al cp437
|
mov $0x0e,%ah # teletype output al cp437
|
||||||
int $0x10 # vidya service
|
int $0x10 # vidya service
|
||||||
pop %bp # preserves al
|
jmp 0b
|
||||||
pop %bx
|
1: pop %bx
|
||||||
|
pop %bp
|
||||||
ret
|
ret
|
||||||
.endfn rvputc
|
.endfn rvputs,globl,hidden
|
||||||
|
|
||||||
|
/ Abnormally halts startup.
|
||||||
|
/
|
||||||
|
/ @param di message
|
||||||
|
/ @mode real
|
||||||
|
/ @noreturn
|
||||||
|
rldie: push %di
|
||||||
|
mov $REAL(.Lstr.error),%di
|
||||||
|
call rvputs
|
||||||
|
pop %di
|
||||||
|
call rvputs
|
||||||
|
mov $REAL(.Lstr.crlf),%di
|
||||||
|
call rvputs
|
||||||
|
xor %ax,%ax # get keystroke
|
||||||
|
int $0x16 # keyboard service
|
||||||
|
jmp triplf
|
||||||
|
.endfn rldie,globl,hidden
|
||||||
|
|
||||||
/* █ █▒
|
/* █ █▒
|
||||||
█ █
|
█ █
|
||||||
|
@ -1321,6 +1170,7 @@ longmodeloader:
|
||||||
jc 9f
|
jc 9f
|
||||||
call unreal
|
call unreal
|
||||||
/ call hiload
|
/ call hiload
|
||||||
|
call pinit
|
||||||
jmp golong
|
jmp golong
|
||||||
9: mov $REAL(.Lstr.e820),%ax
|
9: mov $REAL(.Lstr.e820),%ax
|
||||||
call rldie
|
call rldie
|
||||||
|
@ -1568,7 +1418,6 @@ pinit: push %ds
|
||||||
/ @see Intel Manual V3A §4.1.2
|
/ @see Intel Manual V3A §4.1.2
|
||||||
golong: cli
|
golong: cli
|
||||||
lidt XLM(BADIDT)
|
lidt XLM(BADIDT)
|
||||||
call pinit
|
|
||||||
mov %cr4,%eax
|
mov %cr4,%eax
|
||||||
or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax
|
or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax
|
||||||
mov %eax,%cr4
|
mov %eax,%cr4
|
||||||
|
|
|
@ -21,7 +21,7 @@ APE_LIB_A_OBJS = \
|
||||||
$(APE_LIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
$(APE_LIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||||
o/$(MODE)/ape/ape.lds.zip.o \
|
o/$(MODE)/ape/ape.lds.zip.o \
|
||||||
o/$(MODE)/ape/ape.S.zip.o \
|
o/$(MODE)/ape/ape.S.zip.o \
|
||||||
o/$(MODE)/NOTICE.zip.o
|
o/$(MODE)/LICENSE.zip.o
|
||||||
|
|
||||||
APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok)
|
APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok)
|
||||||
APE_LIB_A_DIRECTDEPS = LIBC_STR LIBC_STUBS
|
APE_LIB_A_DIRECTDEPS = LIBC_STR LIBC_STUBS
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
/* UNIX v7 usr/src/games/hangman.c
|
||||||
|
*
|
||||||
|
* Copyright 2002 Caldera International Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code and documentation must retain the
|
||||||
|
* above copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer. Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided with
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
* All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
*
|
||||||
|
* This product includes software developed or owned by Caldera
|
||||||
|
* International, Inc.
|
||||||
|
*
|
||||||
|
* Neither the name of Caldera International, Inc. nor the names of
|
||||||
|
* other contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENCE BY CALDERA
|
||||||
|
* INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/rand/rand.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/time/time.h"
|
||||||
|
#include "third_party/zlib/zlib.h"
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
#define DICT "usr/share/dict/hangman"
|
||||||
|
#define MAXERR 7
|
||||||
|
#define MINSCORE 0
|
||||||
|
#define MINLEN 7
|
||||||
|
|
||||||
|
char *dictfile;
|
||||||
|
int alive,lost;
|
||||||
|
FILE *dict;
|
||||||
|
long int dictlen;
|
||||||
|
float errors=0, words=0;
|
||||||
|
char word[26],alph[26],realword[26];
|
||||||
|
|
||||||
|
void fatal(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s\n",s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
long tvec;
|
||||||
|
struct stat statb;
|
||||||
|
time(&tvec);
|
||||||
|
srand(tvec);
|
||||||
|
if((dict=fopen(dictfile,"r"))==NULL) fatal("no dictionary");
|
||||||
|
if(stat(dictfile,&statb)<0) fatal("can't stat");
|
||||||
|
dictlen=statb.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
double frand()
|
||||||
|
{
|
||||||
|
return(rand()/32768.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pscore()
|
||||||
|
{
|
||||||
|
if(words!=0) printf("(%4.2f/%.0f) ",errors/words,words);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getword()
|
||||||
|
{ char wbuf[128],c;
|
||||||
|
int i,j;
|
||||||
|
loop:
|
||||||
|
if(fscanf(dict,"%s\n",wbuf)==EOF)
|
||||||
|
{ fseek(dict,0L,0);
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
if((c=wbuf[0])>'z' || c<'a') goto loop;
|
||||||
|
for(i=j=0;wbuf[j]!=0;i++,j++)
|
||||||
|
{ if(wbuf[j]=='-') j++;
|
||||||
|
wbuf[i]=wbuf[j];
|
||||||
|
}
|
||||||
|
wbuf[i]=0;
|
||||||
|
if(i<MINLEN) goto loop;
|
||||||
|
for(j=0;j<i;j++)
|
||||||
|
if((c=wbuf[j])<'a' || c>'z') goto loop;
|
||||||
|
pscore();
|
||||||
|
strcpy(realword,wbuf);
|
||||||
|
for(j=0;j<i;word[j++]='.');
|
||||||
|
}
|
||||||
|
|
||||||
|
void startnew()
|
||||||
|
{ int i;
|
||||||
|
long int pos;
|
||||||
|
char buf[128];
|
||||||
|
for(i=0;i<26;i++) word[i]=alph[i]=realword[i]=0;
|
||||||
|
pos=frand()*dictlen;
|
||||||
|
pos%=dictlen;
|
||||||
|
fseek(dict,pos,0);
|
||||||
|
fscanf(dict,"%s\n",buf);
|
||||||
|
getword();
|
||||||
|
alive=MAXERR;
|
||||||
|
lost=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stateout()
|
||||||
|
{ int i;
|
||||||
|
printf("guesses: ");
|
||||||
|
for(i=0;i<26;i++)
|
||||||
|
if(alph[i]!=0) putchar(alph[i]);
|
||||||
|
printf(" word: %s ",word);
|
||||||
|
printf("errors: %d/%d\n",MAXERR-alive,MAXERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getguess()
|
||||||
|
{ char gbuf[128],c;
|
||||||
|
int ok=0,i;
|
||||||
|
loop:
|
||||||
|
printf("guess: ");
|
||||||
|
if(gets(gbuf)==NULL)
|
||||||
|
{ putchar('\n');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if((c=gbuf[0])<'a' || c>'z')
|
||||||
|
{ printf("lower case\n");
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
if(alph[c-'a']!=0)
|
||||||
|
{ printf("you guessed that\n");
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
else alph[c-'a']=c;
|
||||||
|
for(i=0;realword[i]!=0;i++)
|
||||||
|
if(realword[i]==c)
|
||||||
|
{ word[i]=c;
|
||||||
|
ok=1;
|
||||||
|
}
|
||||||
|
if(ok==0)
|
||||||
|
{ alive--;
|
||||||
|
errors=errors+1;
|
||||||
|
if(alive<=0) lost=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i=0;word[i]!=0;i++)
|
||||||
|
if(word[i]=='.') return;
|
||||||
|
alive=0;
|
||||||
|
lost=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wordout()
|
||||||
|
{
|
||||||
|
errors=errors+2;
|
||||||
|
printf("the answer was %s, you blew it\n",realword);
|
||||||
|
}
|
||||||
|
|
||||||
|
void youwon()
|
||||||
|
{
|
||||||
|
printf("you win, the word is %s\n",realword);
|
||||||
|
}
|
||||||
|
|
||||||
|
main(argc,argv)
|
||||||
|
char **argv;
|
||||||
|
{
|
||||||
|
if(argc==1) dictfile=DICT;
|
||||||
|
else dictfile=argv[1];
|
||||||
|
setup();
|
||||||
|
for(;;)
|
||||||
|
{ startnew();
|
||||||
|
while(alive>0)
|
||||||
|
{ stateout();
|
||||||
|
getguess();
|
||||||
|
}
|
||||||
|
words=words+1;
|
||||||
|
if(lost) wordout();
|
||||||
|
else youwon();
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
#include "libc/zip.h"
|
#include "libc/zip.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
#include "third_party/getopt/getopt.h"
|
#include "third_party/getopt/getopt.h"
|
||||||
#include "tool/viz/lib/knobs.h"
|
#include "tool/viz/lib/knobs.h"
|
||||||
|
|
||||||
|
|
|
@ -278,22 +278,12 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
||||||
* @see lockcmpxchg()
|
* @see lockcmpxchg()
|
||||||
*/
|
*/
|
||||||
#define cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
|
#define cmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
|
||||||
({ \
|
|
||||||
bool DidIt; \
|
|
||||||
asm(ZFLAG_ASM("cmpxchg\t%3,%1") \
|
|
||||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*(IFTHING)), "+a"(*(ISEQUALTOME)) \
|
|
||||||
: "r"((typeof(*(IFTHING)))(REPLACEITWITHME)) \
|
|
||||||
: "cc"); \
|
|
||||||
DidIt; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define ezcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
|
|
||||||
({ \
|
({ \
|
||||||
bool DidIt; \
|
bool DidIt; \
|
||||||
autotype(IFTHING) IfThing = (IFTHING); \
|
autotype(IFTHING) IfThing = (IFTHING); \
|
||||||
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
|
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
|
||||||
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
|
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
|
||||||
asm(ZFLAG_ASM("cmpxchg\t%3,%1") \
|
asm volatile(ZFLAG_ASM("cmpxchg\t%3,%1") \
|
||||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
|
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
|
||||||
: "r"(ReplaceItWithMe) \
|
: "r"(ReplaceItWithMe) \
|
||||||
: "cc"); \
|
: "cc"); \
|
||||||
|
@ -310,9 +300,12 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
||||||
#define lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
|
#define lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME) \
|
||||||
({ \
|
({ \
|
||||||
bool DidIt; \
|
bool DidIt; \
|
||||||
asm(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
|
autotype(IFTHING) IfThing = (IFTHING); \
|
||||||
: ZFLAG_CONSTRAINT(DidIt), "+m"(*(IFTHING)), "+a"(*(ISEQUALTOME)) \
|
typeof(*IfThing) IsEqualToMe = (ISEQUALTOME); \
|
||||||
: "r"((typeof(*(IFTHING)))(REPLACEITWITHME)) \
|
typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME); \
|
||||||
|
asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1") \
|
||||||
|
: ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
|
||||||
|
: "r"(ReplaceItWithMe) \
|
||||||
: "cc"); \
|
: "cc"); \
|
||||||
DidIt; \
|
DidIt; \
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,6 +33,6 @@ textwindows int chdir$nt(const char *path) {
|
||||||
if (SetCurrentDirectory(path16)) {
|
if (SetCurrentDirectory(path16)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
textwindows int close$nt(int fd) {
|
textwindows int close$nt(int fd) {
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
if (isfdopen(fd)) {
|
if (__isfdopen(fd)) {
|
||||||
if (g_fds.p[fd].kind == kFdFile) {
|
if (g_fds.p[fd].kind == kFdFile) {
|
||||||
/*
|
/*
|
||||||
* Like Linux, closing a file on Windows doesn't guarantee it's
|
* Like Linux, closing a file on Windows doesn't guarantee it's
|
||||||
|
@ -37,8 +37,8 @@ textwindows int close$nt(int fd) {
|
||||||
if (g_fds.p[fd].kind == kFdConsole) {
|
if (g_fds.p[fd].kind == kFdConsole) {
|
||||||
ok &= CloseHandle(g_fds.p[fd].extra);
|
ok &= CloseHandle(g_fds.p[fd].extra);
|
||||||
}
|
}
|
||||||
removefd(fd);
|
__removefd(fd);
|
||||||
return ok ? 0 : winerr();
|
return ok ? 0 : __winerr();
|
||||||
} else {
|
} else {
|
||||||
return ebadf();
|
return ebadf();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,10 @@
|
||||||
#include "libc/bits/weaken.h"
|
#include "libc/bits/weaken.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/macros.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes file descriptor.
|
* Closes file descriptor.
|
||||||
|
@ -32,17 +33,24 @@
|
||||||
*/
|
*/
|
||||||
int close(int fd) {
|
int close(int fd) {
|
||||||
int rc;
|
int rc;
|
||||||
if (fd == -1) return einval();
|
if (fd < 0) return einval();
|
||||||
if (isfdkind(fd, kFdZip)) {
|
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
rc = weaken(__zipos_close)(
|
rc = weaken(__zipos_close)(fd);
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle);
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
|
||||||
|
rc = weaken(close$epoll)(fd);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
rc = close$sysv(fd);
|
rc = close$sysv(fd);
|
||||||
} else if (isfdkind(fd, kFdSocket)) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||||
rc = weaken(closesocket$nt)(fd);
|
rc = weaken(closesocket$nt)(fd);
|
||||||
} else {
|
} else if (fd < g_fds.n &&
|
||||||
|
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||||
rc = close$nt(fd);
|
rc = close$nt(fd);
|
||||||
|
} else {
|
||||||
|
rc = ebadf();
|
||||||
|
}
|
||||||
|
if (fd < g_fds.n) {
|
||||||
|
g_fds.p[fd].kind = kFdEmpty;
|
||||||
|
g_fds.f = MIN(g_fds.f, fd);
|
||||||
}
|
}
|
||||||
removefd(fd);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,17 @@
|
||||||
* Implements dup(), dup2(), and dup3() for Windows NT.
|
* Implements dup(), dup2(), and dup3() for Windows NT.
|
||||||
*/
|
*/
|
||||||
textwindows int dup$nt(int oldfd, int newfd, int flags) {
|
textwindows int dup$nt(int oldfd, int newfd, int flags) {
|
||||||
if (!isfdkind(oldfd, kFdFile)) return ebadf();
|
if (!__isfdkind(oldfd, kFdFile)) return ebadf();
|
||||||
if (newfd == -1) {
|
if (newfd == -1) {
|
||||||
if ((newfd = createfd()) == -1) return -1;
|
if ((newfd = __getemptyfd()) == -1) {
|
||||||
} else if (isfdindex(newfd)) {
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (__ensurefds(newfd) != -1) {
|
||||||
if (g_fds.p[newfd].kind != kFdEmpty) {
|
if (g_fds.p[newfd].kind != kFdEmpty) {
|
||||||
close(newfd);
|
close(newfd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
do {
|
return -1;
|
||||||
if (growfds() == -1) return -1;
|
|
||||||
} while (newfd >= g_fds.n);
|
|
||||||
}
|
}
|
||||||
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
|
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
|
||||||
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
|
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
|
||||||
|
@ -49,6 +49,6 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
|
||||||
g_fds.p[newfd].flags = flags;
|
g_fds.p[newfd].flags = flags;
|
||||||
return newfd;
|
return newfd;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ textwindows int fadvise$nt(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||||
struct NtIoStatusBlock iostatus;
|
struct NtIoStatusBlock iostatus;
|
||||||
struct NtFileBasicInformation basicinfo;
|
struct NtFileBasicInformation basicinfo;
|
||||||
struct NtFileAccessInformation accessinfo;
|
struct NtFileAccessInformation accessinfo;
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
sharemode = /* xxx: no clue how to query this */
|
sharemode = /* xxx: no clue how to query this */
|
||||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
|
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete;
|
||||||
/* TODO(jart): can we do it in one call w/ NtQueryObject? */
|
/* TODO(jart): can we do it in one call w/ NtQueryObject? */
|
||||||
|
@ -56,7 +56,7 @@ textwindows int fadvise$nt(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return winerr();
|
return __winerr();
|
||||||
} else if (status == kNtStatusDllNotFound) {
|
} else if (status == kNtStatusDllNotFound) {
|
||||||
return enosys();
|
return enosys();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -51,7 +51,7 @@ int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
return posix_fallocate$sysv(fd, offset, length);
|
return posix_fallocate$sysv(fd, offset, length);
|
||||||
} else if (IsWindows()) {
|
} else if (IsWindows()) {
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
if (mode == FALLOC_FL_ZERO_RANGE) {
|
if (mode == FALLOC_FL_ZERO_RANGE) {
|
||||||
if (DeviceIoControl(
|
if (DeviceIoControl(
|
||||||
g_fds.p[fd].handle, kNtFsctlSetZeroData,
|
g_fds.p[fd].handle, kNtFsctlSetZeroData,
|
||||||
|
@ -59,7 +59,7 @@ int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
|
||||||
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
|
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
} else if (!mode && !offset) {
|
} else if (!mode && !offset) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -21,20 +21,31 @@
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/consts/fd.h"
|
#include "libc/sysv/consts/fd.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
|
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
case F_GETFL:
|
||||||
|
return g_fds.p[fd].flags;
|
||||||
|
case F_SETFL:
|
||||||
|
return (g_fds.p[fd].flags = arg);
|
||||||
case F_GETFD:
|
case F_GETFD:
|
||||||
if (!GetHandleInformation(g_fds.p[fd].handle, &flags)) return -1;
|
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||||
arg = (flags & FD_CLOEXEC) ^ FD_CLOEXEC;
|
return FD_CLOEXEC;
|
||||||
return arg;
|
} else {
|
||||||
case F_SETFD:
|
|
||||||
arg ^= FD_CLOEXEC;
|
|
||||||
if (!SetHandleInformation(g_fds.p[fd].handle, FD_CLOEXEC, arg)) return -1;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
case F_SETFD:
|
||||||
|
if (arg & O_CLOEXEC) {
|
||||||
|
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||||
|
return FD_CLOEXEC;
|
||||||
|
} else {
|
||||||
|
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return 0; /* TODO(jart): Implement me. */
|
return 0; /* TODO(jart): Implement me. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int fdatasync$nt(int fd) {
|
textwindows int fdatasync$nt(int fd) {
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
/*
|
/*
|
||||||
* XXX: On Windows NT this might be more analagous to fflush() and
|
* XXX: On Windows NT this might be more analagous to fflush() and
|
||||||
* Microsoft docs say to do manual block i/o for database-ish
|
* Microsoft docs say to do manual block i/o for database-ish
|
||||||
* guarantees on disk persistence. Consider: Really good UPS.
|
* guarantees on disk persistence. Consider: Really good UPS.
|
||||||
*/
|
*/
|
||||||
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : winerr();
|
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : __winerr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
|
||||||
enum FdKind fdkind(int fd) {
|
enum FdKind fdkind(int fd) {
|
||||||
if (isfdindex(fd)) {
|
if (0 <= fd && fd <= g_fds.n) {
|
||||||
return g_fds.p[fd].kind;
|
return g_fds.p[fd].kind;
|
||||||
} else {
|
} else {
|
||||||
return kFdEmpty;
|
return kFdEmpty;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
textwindows int flock$nt(int fd, int op) {
|
textwindows int flock$nt(int fd, int op) {
|
||||||
struct NtOverlapped ov;
|
struct NtOverlapped ov;
|
||||||
struct NtByHandleFileInformation info;
|
struct NtByHandleFileInformation info;
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
memset(&ov, 0, sizeof(ov));
|
memset(&ov, 0, sizeof(ov));
|
||||||
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
|
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
|
||||||
((!(op & LOCK_UN) &&
|
((!(op & LOCK_UN) &&
|
||||||
|
@ -39,6 +39,6 @@ textwindows int flock$nt(int fd, int op) {
|
||||||
info.nFileSizeHigh, &ov)))) {
|
info.nFileSizeHigh, &ov)))) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,6 @@ textwindows int fstat$nt(int64_t handle, struct stat *st) {
|
||||||
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
|
st->st_blocks = roundup(actualsize, PAGESIZE) / 512;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,20 +22,20 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about file, via open()'d descriptor.
|
* Returns information about file, via open()'d descriptor.
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
int fstat(int fd, struct stat *st) {
|
int fstat(int fd, struct stat *st) {
|
||||||
if (isfdkind(fd, kFdZip)) {
|
if (__isfdkind(fd, kFdZip)) {
|
||||||
return weaken(__zipos_fstat)(
|
return weaken(__zipos_fstat)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
return fstat$sysv(fd, st);
|
return fstat$sysv(fd, st);
|
||||||
} else {
|
} else {
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
return fstat$nt(g_fds.p[fd].handle, st);
|
return fstat$nt(g_fds.p[fd].handle, st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,14 @@
|
||||||
textwindows int ftruncate$nt(int fd, uint64_t length) {
|
textwindows int ftruncate$nt(int fd, uint64_t length) {
|
||||||
bool32 ok;
|
bool32 ok;
|
||||||
int64_t tell;
|
int64_t tell;
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
tell = -1;
|
tell = -1;
|
||||||
if (SetFilePointerEx(g_fds.p[fd].handle, 0, &tell, kNtFileCurrent)) {
|
if (SetFilePointerEx(g_fds.p[fd].handle, 0, &tell, kNtFileCurrent)) {
|
||||||
ok = SetFilePointerEx(g_fds.p[fd].handle, length, NULL, kNtFileBegin) &&
|
ok = SetFilePointerEx(g_fds.p[fd].handle, length, NULL, kNtFileBegin) &&
|
||||||
SetEndOfFile(g_fds.p[fd].handle);
|
SetEndOfFile(g_fds.p[fd].handle);
|
||||||
SetFilePointerEx(g_fds.p[fd].handle, tell, NULL, kNtFileBegin);
|
SetFilePointerEx(g_fds.p[fd].handle, tell, NULL, kNtFileBegin);
|
||||||
return ok ? 0 : winerr();
|
return ok ? 0 : __winerr();
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,12 +33,22 @@ void InitializeFileDescriptors(void) {
|
||||||
pushmov(&fds->f, 3ul);
|
pushmov(&fds->f, 3ul);
|
||||||
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
|
pushmov(&fds->n, ARRAYLEN(fds->__init_p));
|
||||||
fds->p = fds->__init_p;
|
fds->p = fds->__init_p;
|
||||||
|
if (!IsMetal()) {
|
||||||
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdFile);
|
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdFile);
|
||||||
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile);
|
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdFile);
|
||||||
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
|
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdFile);
|
||||||
fds->__init_p[STDIN_FILENO].handle = GetStdHandle(pushpop(kNtStdInputHandle));
|
fds->__init_p[STDIN_FILENO].handle =
|
||||||
|
GetStdHandle(pushpop(kNtStdInputHandle));
|
||||||
fds->__init_p[STDOUT_FILENO].handle =
|
fds->__init_p[STDOUT_FILENO].handle =
|
||||||
GetStdHandle(pushpop(kNtStdOutputHandle));
|
GetStdHandle(pushpop(kNtStdOutputHandle));
|
||||||
fds->__init_p[STDERR_FILENO].handle =
|
fds->__init_p[STDERR_FILENO].handle =
|
||||||
GetStdHandle(pushpop(kNtStdErrorHandle));
|
GetStdHandle(pushpop(kNtStdErrorHandle));
|
||||||
|
} else {
|
||||||
|
fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial);
|
||||||
|
fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial);
|
||||||
|
fds->__init_p[STDERR_FILENO].kind = pushpop(kFdSerial);
|
||||||
|
fds->__init_p[STDIN_FILENO].handle = 0x3F8;
|
||||||
|
fds->__init_p[STDOUT_FILENO].handle = 0x3F8;
|
||||||
|
fds->__init_p[STDERR_FILENO].handle = 0x3F8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ textwindows char *getcwd$nt(char *buf, size_t size) {
|
||||||
erange();
|
erange();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
winerr();
|
__winerr();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ int getdomainname(char *name, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
nSize = ARRAYLEN(name16);
|
nSize = ARRAYLEN(name16);
|
||||||
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
|
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -25,14 +25,11 @@
|
||||||
/**
|
/**
|
||||||
* Finds open file descriptor slot.
|
* Finds open file descriptor slot.
|
||||||
*/
|
*/
|
||||||
ssize_t createfd(void) {
|
ssize_t __getemptyfd(void) {
|
||||||
size_t fd;
|
for (; g_fds.f < g_fds.n; ++g_fds.f) {
|
||||||
for (;;) {
|
if (g_fds.p[g_fds.f].kind == kFdEmpty) {
|
||||||
while (g_fds.f < g_fds.n) {
|
return g_fds.f;
|
||||||
if (g_fds.p[(fd = g_fds.f++)].kind == kFdEmpty) {
|
|
||||||
return fd;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (growfds() == -1) return -1;
|
return __ensurefds(g_fds.f);
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -50,7 +50,7 @@ int gethostname(char *name, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
nSize = ARRAYLEN(name16);
|
nSize = ARRAYLEN(name16);
|
||||||
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
|
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -46,6 +46,6 @@ textwindows int getpriority$nt(int ignored) {
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,6 @@ textwindows int getrusage$nt(int who, struct rusage *usage) {
|
||||||
FileTimeToTimeVal(&usage->ru_stime, KernelFileTime);
|
FileTimeToTimeVal(&usage->ru_stime, KernelFileTime);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,18 +23,20 @@
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int growfds(void) {
|
int __ensurefds(int fd) {
|
||||||
size_t i, n;
|
size_t i, n;
|
||||||
struct Fd *p;
|
struct Fd *p;
|
||||||
|
if (fd < g_fds.n) return fd;
|
||||||
if (weaken(realloc)) {
|
if (weaken(realloc)) {
|
||||||
if ((p = weaken(realloc)(g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
|
if ((p = weaken(realloc)(
|
||||||
(n = (i = g_fds.n) << 1) * sizeof(*p)))) {
|
g_fds.p != g_fds.__init_p ? g_fds.p : NULL,
|
||||||
|
(n = MAX(fd + 1, (i = g_fds.n) << 1)) * sizeof(*p)))) {
|
||||||
do {
|
do {
|
||||||
p[i++].kind = kFdEmpty;
|
p[i++].kind = kFdEmpty;
|
||||||
} while (i < n);
|
} while (i < n);
|
||||||
g_fds.p = p;
|
g_fds.p = p;
|
||||||
g_fds.n = n;
|
g_fds.n = n;
|
||||||
return 0;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
return enomem();
|
return enomem();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ static textwindows int copyfile$nt(const char *src, const char *dst,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
|
||||||
if ((res->fd = FindFirstFile(name16, &res->windata)) != -1) {
|
if ((res->fd = FindFirstFile(name16, &res->windata)) != -1) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
winerr();
|
__winerr();
|
||||||
free(res);
|
free(res);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ int closedir(DIR *dir) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
rc = close(dir->fd);
|
rc = close(dir->fd);
|
||||||
} else {
|
} else {
|
||||||
rc = FindClose(dir->fd) ? 0 : winerr();
|
rc = FindClose(dir->fd) ? 0 : __winerr();
|
||||||
}
|
}
|
||||||
free(dir);
|
free(dir);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,7 +67,7 @@ textwindows void WinMainForked(void) {
|
||||||
char16_t *p;
|
char16_t *p;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
char16_t var[21 + 1 + 21 + 1];
|
char16_t var[21 + 1 + 21 + 1];
|
||||||
uint32_t i, varlen, protect, access;
|
uint32_t i, varlen, protect, access, oldprot;
|
||||||
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
|
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
|
||||||
if (!varlen || varlen >= ARRAYLEN(var)) return;
|
if (!varlen || varlen >= ARRAYLEN(var)) return;
|
||||||
p = var;
|
p = var;
|
||||||
|
@ -98,11 +98,13 @@ textwindows void WinMainForked(void) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
if (_mmi.p[i].flags & MAP_PRIVATE) {
|
||||||
MapViewOfFileExNuma(
|
MapViewOfFileExNuma((_mmi.p[i].h = CreateFileMappingNuma(
|
||||||
(_mmi.p[i].h = CreateFileMappingNuma(-1, NULL, protect, 0, size, NULL,
|
-1, NULL, kNtPageExecuteReadwrite, 0, size, NULL,
|
||||||
kNtNumaNoPreferredNode)),
|
kNtNumaNoPreferredNode)),
|
||||||
access, 0, 0, size, addr, kNtNumaNoPreferredNode);
|
kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute,
|
||||||
|
0, 0, size, addr, kNtNumaNoPreferredNode);
|
||||||
ReadAll(h, addr, size);
|
ReadAll(h, addr, size);
|
||||||
|
VirtualProtect(addr, size, protect, &oldprot);
|
||||||
} else {
|
} else {
|
||||||
MapViewOfFileExNuma(_mmi.p[i].h, access, 0, 0, size, addr,
|
MapViewOfFileExNuma(_mmi.p[i].h, access, 0, 0, size, addr,
|
||||||
kNtNumaNoPreferredNode);
|
kNtNumaNoPreferredNode);
|
||||||
|
@ -148,7 +150,7 @@ textwindows int fork$nt(void) {
|
||||||
}
|
}
|
||||||
unsetenv("_FORK");
|
unsetenv("_FORK");
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
|
@ -78,7 +78,7 @@ textwindows int ntspawn(
|
||||||
opt_out_lpProcessInformation)) {
|
opt_out_lpProcessInformation)) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
|
|
@ -49,14 +49,14 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
|
||||||
sti.cb = sizeof(sti);
|
sti.cb = sizeof(sti);
|
||||||
sti.dwFlags = kNtStartfUsestdhandles;
|
sti.dwFlags = kNtStartfUsestdhandles;
|
||||||
|
|
||||||
if ((pid = createfd()) == -1) return -1;
|
if ((pid = __getemptyfd()) == -1) return -1;
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
if (stdiofds[i] == -1) {
|
if (stdiofds[i] == -1) {
|
||||||
x = &h;
|
x = &h;
|
||||||
y = &sti.stdiofds[i];
|
y = &sti.stdiofds[i];
|
||||||
if (kIoMotion[i]) xchg(&x, &y);
|
if (kIoMotion[i]) xchg(&x, &y);
|
||||||
if ((tubes[i] = createfd()) != -1 &&
|
if ((tubes[i] = __getemptyfd()) != -1 &&
|
||||||
CreatePipe(x, y, &kNtIsInheritable, 0)) {
|
CreatePipe(x, y, &kNtIsInheritable, 0)) {
|
||||||
g_fds.p[tubes[i]].handle = h;
|
g_fds.p[tubes[i]].handle = h;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -76,7 +76,7 @@ int ttyname_r(int fd, char *buf, size_t size) {
|
||||||
} else if (IsFreebsd()) {
|
} else if (IsFreebsd()) {
|
||||||
return ttyname$freebsd(fd, buf, size);
|
return ttyname$freebsd(fd, buf, size);
|
||||||
} else if (IsWindows()) {
|
} else if (IsWindows()) {
|
||||||
if (isfdkind(fd, kFdFile)) {
|
if (__isfdkind(fd, kFdFile)) {
|
||||||
return ttyname$nt(fd, buf, size);
|
return ttyname$nt(fd, buf, size);
|
||||||
} else {
|
} else {
|
||||||
return ebadf();
|
return ebadf();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
|
||||||
#ifndef __STRICT_ANSI__
|
#ifndef __STRICT_ANSI__
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/calls/struct/itimerval.h"
|
#include "libc/calls/struct/itimerval.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
@ -37,7 +38,7 @@ struct IoctlPtmGet {
|
||||||
|
|
||||||
struct Fds {
|
struct Fds {
|
||||||
size_t f; // arbitrary free slot start search index
|
size_t f; // arbitrary free slot start search index
|
||||||
size_t n; // capacity
|
size_t n; // monotonic capacity
|
||||||
struct Fd {
|
struct Fd {
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
int64_t extra;
|
int64_t extra;
|
||||||
|
@ -47,7 +48,9 @@ struct Fds {
|
||||||
kFdSocket,
|
kFdSocket,
|
||||||
kFdProcess,
|
kFdProcess,
|
||||||
kFdConsole,
|
kFdConsole,
|
||||||
|
kFdSerial,
|
||||||
kFdZip,
|
kFdZip,
|
||||||
|
kFdEpoll,
|
||||||
} kind;
|
} kind;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
} * p;
|
} * p;
|
||||||
|
@ -62,20 +65,12 @@ hidden extern struct NtSystemInfo g_ntsysteminfo;
|
||||||
hidden extern struct NtStartupInfo g_ntstartupinfo;
|
hidden extern struct NtStartupInfo g_ntstartupinfo;
|
||||||
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||||
|
|
||||||
ssize_t createfd(void) hidden;
|
ssize_t __getemptyfd(void) hidden;
|
||||||
int growfds(void) hidden;
|
int __ensurefds(int) hidden;
|
||||||
void removefd(int) hidden;
|
void __removefd(int) hidden;
|
||||||
enum FdKind fdkind(int) hidden nosideeffect;
|
enum FdKind fdkind(int) hidden nosideeffect;
|
||||||
bool isfdopen(int) hidden nosideeffect;
|
bool __isfdopen(int) hidden nosideeffect;
|
||||||
bool isfdkind(int, enum FdKind) hidden nosideeffect;
|
bool __isfdkind(int, enum FdKind) hidden nosideeffect;
|
||||||
|
|
||||||
forceinline bool isfdindex(int fd) {
|
|
||||||
if (!IsTrustworthy()) {
|
|
||||||
return (0 <= fd && fd < g_fds.n);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinline size_t clampio(size_t size) {
|
forceinline size_t clampio(size_t size) {
|
||||||
if (!IsTrustworthy()) {
|
if (!IsTrustworthy()) {
|
||||||
|
@ -267,7 +262,7 @@ bool32 onntconsoleevent$nt(u32) hidden;
|
||||||
void __winalarm(void *, uint32_t, uint32_t) hidden;
|
void __winalarm(void *, uint32_t, uint32_t) hidden;
|
||||||
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
||||||
i64 ntreturn(u32);
|
i64 ntreturn(u32);
|
||||||
i64 winerr(void) nocallback privileged;
|
i64 __winerr(void) nocallback privileged;
|
||||||
|
|
||||||
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
|
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
|
||||||
#define mkntpath2(PATH, FLAGS, PATH16) \
|
#define mkntpath2(PATH, FLAGS, PATH16) \
|
||||||
|
@ -280,6 +275,13 @@ i64 winerr(void) nocallback privileged;
|
||||||
Count; \
|
Count; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
|
│ cosmopolitan § syscalls » drivers ─╬─│┼
|
||||||
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
|
ssize_t readv$serial(struct Fd *, const struct iovec *, int) hidden;
|
||||||
|
ssize_t writev$serial(struct Fd *, const struct iovec *, int) hidden;
|
||||||
|
|
||||||
#undef sigset
|
#undef sigset
|
||||||
#undef i32
|
#undef i32
|
||||||
#undef i64
|
#undef i64
|
||||||
|
|
|
@ -29,13 +29,13 @@ int ioctl$default(int fd, uint64_t request, void *memory) {
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return ioctl$sysv(fd, request, memory);
|
return ioctl$sysv(fd, request, memory);
|
||||||
} else if (isfdopen(fd)) {
|
} else if (__isfdopen(fd)) {
|
||||||
if (g_fds.p[fd].kind == kFdSocket) {
|
if (g_fds.p[fd].kind == kFdSocket) {
|
||||||
handle = g_fds.p[fd].handle;
|
handle = g_fds.p[fd].handle;
|
||||||
if ((rc = weaken(__ioctlsocket$nt)(handle, request, memory)) != -1) {
|
if ((rc = weaken(__ioctlsocket$nt)(handle, request, memory)) != -1) {
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
return weaken(winsockerr)();
|
return weaken(__winsockerr)();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return eopnotsupp();
|
return eopnotsupp();
|
||||||
|
|
|
@ -33,7 +33,7 @@ textwindows int ioctl$tiocgwinsz$nt(int fd, struct winsize *ws) {
|
||||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||||
fds[0] = fd, fds[1] = 1, fds[2] = 0;
|
fds[0] = fd, fds[1] = 1, fds[2] = 0;
|
||||||
for (i = 0; i < ARRAYLEN(fds); ++i) {
|
for (i = 0; i < ARRAYLEN(fds); ++i) {
|
||||||
if (isfdkind(fds[i], kFdFile) || isfdkind(fds[i], kFdConsole)) {
|
if (__isfdkind(fds[i], kFdFile) || __isfdkind(fds[i], kFdConsole)) {
|
||||||
if (GetConsoleMode(g_fds.p[fds[i]].handle, &mode)) {
|
if (GetConsoleMode(g_fds.p[fds[i]].handle, &mode)) {
|
||||||
memset(&sbinfo, 0, sizeof(sbinfo));
|
memset(&sbinfo, 0, sizeof(sbinfo));
|
||||||
sbinfo.cbSize = sizeof(sbinfo);
|
sbinfo.cbSize = sizeof(sbinfo);
|
||||||
|
@ -50,7 +50,7 @@ textwindows int ioctl$tiocgwinsz$nt(int fd, struct winsize *ws) {
|
||||||
ws->ws_ypixel = 0;
|
ws->ws_ypixel = 0;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
winerr();
|
__winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enotty();
|
enotty();
|
||||||
|
|
|
@ -29,10 +29,10 @@ textwindows int ioctl$tiocswinsz$nt(int fd, const struct winsize *ws) {
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
struct NtCoord coord;
|
struct NtCoord coord;
|
||||||
if (!ws) return efault();
|
if (!ws) return efault();
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
if (!GetConsoleMode(g_fds.p[fd].handle, &mode)) return enotty();
|
if (!GetConsoleMode(g_fds.p[fd].handle, &mode)) return enotty();
|
||||||
coord.X = ws->ws_col;
|
coord.X = ws->ws_col;
|
||||||
coord.Y = ws->ws_row;
|
coord.Y = ws->ws_row;
|
||||||
if (!SetConsoleScreenBufferSize(g_fds.p[fd].handle, coord)) return winerr();
|
if (!SetConsoleScreenBufferSize(g_fds.p[fd].handle, coord)) return __winerr();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows bool32 isatty$nt(int fd) {
|
textwindows bool32 isatty$nt(int fd) {
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
return GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
|
return GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ textstartup bool32 ischardev(int fd) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return isfdkind(fd, kFdFile) &&
|
return __isfdkind(fd, kFdFile) &&
|
||||||
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
|
GetFileType(g_fds.p[fd].handle) == kNtFileTypeChar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,6 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
|
||||||
bool isfdkind(int fd, enum FdKind kind) {
|
bool __isfdkind(int fd, enum FdKind kind) {
|
||||||
return isfdindex(fd) && g_fds.p[fd].kind == kind;
|
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind == kind;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,6 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
|
||||||
bool isfdopen(int fd) {
|
bool __isfdopen(int fd) {
|
||||||
return isfdindex(fd) && g_fds.p[fd].kind != kFdEmpty;
|
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/calls/internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
|
|
||||||
textwindows int link$nt(const char *existingpath, const char *newpath) {
|
textwindows int link$nt(const char *existingpath, const char *newpath) {
|
||||||
char16_t newpath16[PATH_MAX];
|
char16_t newpath16[PATH_MAX];
|
||||||
|
@ -30,7 +30,7 @@ textwindows int link$nt(const char *existingpath, const char *newpath) {
|
||||||
if (CreateHardLink(newpath16, existingpath16, NULL)) {
|
if (CreateHardLink(newpath16, existingpath16, NULL)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
|
|
||||||
textwindows int64_t lseek$nt(int fd, int64_t offset, int whence) {
|
textwindows int64_t lseek$nt(int fd, int64_t offset, int whence) {
|
||||||
int64_t res;
|
int64_t res;
|
||||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
if (SetFilePointerEx(g_fds.p[fd].handle, offset, &res, whence)) {
|
if (SetFilePointerEx(g_fds.p[fd].handle, offset, &res, whence)) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ textwindows int madvise$nt(void *addr, size_t length, int advice) {
|
||||||
if (fn(GetCurrentProcess(), &rangecount, ranges, 0)) {
|
if (fn(GetCurrentProcess(), &rangecount, ranges, 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return enosys();
|
return enosys();
|
||||||
|
@ -72,7 +72,7 @@ textwindows int madvise$nt(void *addr, size_t length, int advice) {
|
||||||
if (fn(addr, length, kNtVmOfferPriorityNormal)) {
|
if (fn(addr, length, kNtVmOfferPriorityNormal)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return enosys();
|
return enosys();
|
||||||
|
|
|
@ -31,7 +31,7 @@ static textwindows noinline int mkdir$nt(const char *path, uint32_t mode) {
|
||||||
if (CreateDirectory(path16, NULL)) {
|
if (CreateDirectory(path16, NULL)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ int mprotect(void *addr, uint64_t len, int prot) {
|
||||||
if (__imp_VirtualProtect(addr, len, prot2nt(prot, 0), &oldprot)) {
|
if (__imp_VirtualProtect(addr, len, prot2nt(prot, 0), &oldprot)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/select.internal.h"
|
|
||||||
|
|
||||||
int nanosleep$xnu(const struct timespec *req, struct timespec *rem) {
|
int nanosleep$xnu(const struct timespec *req, struct timespec *rem) {
|
||||||
long millis;
|
long millis;
|
||||||
|
|
|
@ -81,7 +81,7 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||||
(result || flags == F_OK)) {
|
(result || flags == F_OK)) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = __winerr();
|
||||||
}
|
}
|
||||||
close(hImpersonatedToken);
|
close(hImpersonatedToken);
|
||||||
close(hToken);
|
close(hToken);
|
||||||
|
|
|
@ -49,7 +49,7 @@ static textwindows int64_t open$nt$impl(const char *file, uint32_t flags,
|
||||||
(flags & O_EXCL)
|
(flags & O_EXCL)
|
||||||
? kNtFileShareExclusive
|
? kNtFileShareExclusive
|
||||||
: kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
: kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||||
(flags & O_CLOEXEC) ? &kNtIsInheritable : NULL,
|
&kNtIsInheritable,
|
||||||
(flags & O_CREAT) && (flags & O_EXCL)
|
(flags & O_CREAT) && (flags & O_EXCL)
|
||||||
? kNtCreateNew
|
? kNtCreateNew
|
||||||
: (flags & O_CREAT) && (flags & O_TRUNC)
|
: (flags & O_CREAT) && (flags & O_TRUNC)
|
||||||
|
@ -94,7 +94,7 @@ static textwindows ssize_t open$nt$console(const struct NtMagicPaths *mp,
|
||||||
open$nt$impl(mp->conout, (flags & ~O_ACCMODE) | O_WRONLY, mode);
|
open$nt$impl(mp->conout, (flags & ~O_ACCMODE) | O_WRONLY, mode);
|
||||||
assert(g_fds.p[fd].extra != -1);
|
assert(g_fds.p[fd].extra != -1);
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
g_fds.p[fd].kind = kFdConsole;
|
g_fds.p[fd].kind = kFdConsole;
|
||||||
g_fds.p[fd].flags = flags;
|
g_fds.p[fd].flags = flags;
|
||||||
|
@ -111,13 +111,13 @@ static textwindows ssize_t open$nt$file(const char *file, uint32_t flags,
|
||||||
((flags & O_CREAT) && (flags & O_TRUNC))) {
|
((flags & O_CREAT) && (flags & O_TRUNC))) {
|
||||||
return eisdir();
|
return eisdir();
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows ssize_t open$nt(const char *file, uint32_t flags, int32_t mode) {
|
textwindows ssize_t open$nt(const char *file, uint32_t flags, int32_t mode) {
|
||||||
size_t fd;
|
size_t fd;
|
||||||
if ((fd = createfd()) == -1) return -1;
|
if ((fd = __getemptyfd()) == -1) return -1;
|
||||||
if ((flags & O_ACCMODE) == O_RDWR &&
|
if ((flags & O_ACCMODE) == O_RDWR &&
|
||||||
tinystrcmp(file, kNtMagicPaths.devtty) == 0) {
|
tinystrcmp(file, kNtMagicPaths.devtty) == 0) {
|
||||||
return open$nt$console(&kNtMagicPaths, flags, mode, fd);
|
return open$nt$console(&kNtMagicPaths, flags, mode, fd);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens file.
|
* Opens file.
|
||||||
|
|
|
@ -61,24 +61,25 @@ static int openanon$impl(const char *name, unsigned flags,
|
||||||
char pathbuf[hasatleast PATH_MAX]) {
|
char pathbuf[hasatleast PATH_MAX]) {
|
||||||
int fd;
|
int fd;
|
||||||
openanon$genpath(name, state, pathbuf);
|
openanon$genpath(name, state, pathbuf);
|
||||||
if (!IsWindows()) {
|
|
||||||
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
|
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
|
||||||
|
if (!IsWindows()) {
|
||||||
if ((fd = openat$sysv(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
|
if ((fd = openat$sysv(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
|
||||||
unlink(pathbuf);
|
unlink(pathbuf);
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
if ((fd = createfd()) != -1 &&
|
if ((fd = __getemptyfd()) != -1 &&
|
||||||
(g_fds.p[fd].handle = CreateFileA(
|
(g_fds.p[fd].handle = CreateFileA(
|
||||||
pathbuf, kNtGenericRead | kNtGenericWrite, kNtFileShareExclusive,
|
pathbuf, kNtGenericRead | kNtGenericWrite, kNtFileShareExclusive,
|
||||||
(flags & O_CLOEXEC) ? &kNtIsInheritable : NULL, kNtCreateAlways,
|
&kNtIsInheritable, kNtCreateAlways,
|
||||||
(kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal |
|
(kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal |
|
||||||
kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose),
|
kNtFileAttributeTemporary | kNtFileFlagDeleteOnClose),
|
||||||
0)) != -1) {
|
0)) != -1) {
|
||||||
g_fds.p[fd].kind = kFdFile;
|
g_fds.p[fd].kind = kFdFile;
|
||||||
|
g_fds.p[fd].flags = flags;
|
||||||
return fd;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,10 @@
|
||||||
|
|
||||||
textwindows int pipe$nt(int pipefd[2], unsigned flags) {
|
textwindows int pipe$nt(int pipefd[2], unsigned flags) {
|
||||||
int reader, writer;
|
int reader, writer;
|
||||||
if ((reader = createfd()) == -1) return -1;
|
if ((reader = __getemptyfd()) == -1) return -1;
|
||||||
if ((writer = createfd()) == -1) return -1;
|
if ((writer = __getemptyfd()) == -1) return -1;
|
||||||
if (CreatePipe(&g_fds.p[reader].handle, &g_fds.p[writer].handle,
|
if (CreatePipe(&g_fds.p[reader].handle, &g_fds.p[writer].handle,
|
||||||
(flags & O_CLOEXEC) ? NULL : &kNtIsInheritable,
|
&kNtIsInheritable, 0)) {
|
||||||
0 /* let NT pick buffer size */)) {
|
|
||||||
g_fds.p[reader].kind = kFdFile;
|
g_fds.p[reader].kind = kFdFile;
|
||||||
g_fds.p[reader].flags = flags;
|
g_fds.p[reader].flags = flags;
|
||||||
g_fds.p[writer].kind = kFdFile;
|
g_fds.p[writer].kind = kFdFile;
|
||||||
|
@ -37,6 +36,6 @@ textwindows int pipe$nt(int pipefd[2], unsigned flags) {
|
||||||
pipefd[1] = writer;
|
pipefd[1] = writer;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads from file at offset, thus avoiding superfluous lseek().
|
* Reads from file at offset, thus avoiding superfluous lseek().
|
||||||
|
@ -42,12 +42,12 @@
|
||||||
ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
if (fd == -1 || offset < 0) return einval();
|
if (fd == -1 || offset < 0) return einval();
|
||||||
if (isfdkind(fd, kFdZip)) {
|
if (__isfdkind(fd, kFdZip)) {
|
||||||
rc = weaken(__zipos_read)(
|
rc = weaken(__zipos_read)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, buf, size, offset);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, buf, size, offset);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
rc = pread$sysv(fd, buf, size, offset);
|
rc = pread$sysv(fd, buf, size, offset);
|
||||||
} else if (isfdkind(fd, kFdFile)) {
|
} else if (__isfdkind(fd, kFdFile)) {
|
||||||
rc = read$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
|
rc = read$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
|
||||||
} else {
|
} else {
|
||||||
rc = ebadf();
|
rc = ebadf();
|
||||||
|
|
|
@ -43,7 +43,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
||||||
size = MIN(size, 0x7ffff000);
|
size = MIN(size, 0x7ffff000);
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
rc = pwrite$sysv(fd, buf, size, offset);
|
rc = pwrite$sysv(fd, buf, size, offset);
|
||||||
} else if (isfdkind(fd, kFdFile)) {
|
} else if (__isfdkind(fd, kFdFile)) {
|
||||||
rc = write$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
|
rc = write$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, offset);
|
||||||
} else {
|
} else {
|
||||||
return ebadf();
|
return ebadf();
|
||||||
|
|
|
@ -60,7 +60,7 @@ int raise(int sig) {
|
||||||
if (GenerateConsoleCtrlEvent(GetCtrlEvent(sig), 0)) {
|
if (GenerateConsoleCtrlEvent(GetCtrlEvent(sig), 0)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,6 @@ textwindows ssize_t read$nt(struct Fd *fd, const struct iovec *iov,
|
||||||
} else if (NtGetErr() == kNtErrorBrokenPipe) {
|
} else if (NtGetErr() == kNtErrorBrokenPipe) {
|
||||||
return 0; /* read() doesn't EPIPE lool */
|
return 0; /* read() doesn't EPIPE lool */
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,8 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
|
||||||
#include "libc/bits/weaken.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/calls/internal.h"
|
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/macros.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/sock/internal.h"
|
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
#include "libc/zipos/zipos.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from file descriptor.
|
* Reads data from file descriptor.
|
||||||
|
@ -41,24 +32,5 @@
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
ssize_t read(int fd, void *buf, size_t size) {
|
ssize_t read(int fd, void *buf, size_t size) {
|
||||||
ssize_t rc;
|
return readv(fd, &(struct iovec){buf, size}, 1);
|
||||||
if (fd == -1) return einval();
|
|
||||||
if (isfdkind(fd, kFdZip)) {
|
|
||||||
rc =
|
|
||||||
weaken(__zipos_read)((struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
|
|
||||||
(struct iovec[]){{buf, size}}, 1, -1);
|
|
||||||
} else if (!IsWindows()) {
|
|
||||||
rc = read$sysv(fd, buf, size);
|
|
||||||
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
|
|
||||||
rc = read$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1);
|
|
||||||
} else if (isfdkind(fd, kFdSocket)) {
|
|
||||||
rc = weaken(recvfrom$nt)(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, 0,
|
|
||||||
NULL, NULL);
|
|
||||||
} else {
|
|
||||||
rc = ebadf();
|
|
||||||
}
|
|
||||||
if (!IsTrustworthy() && rc != -1) {
|
|
||||||
if ((size_t)rc > size) abort();
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ This program is free software; you can redistribute it and/or modify │
|
||||||
|
│ it under the terms of the GNU General Public License as published by │
|
||||||
|
│ the Free Software Foundation; version 2 of the License. │
|
||||||
|
│ │
|
||||||
|
│ This program is distributed in the hope that it will be useful, but │
|
||||||
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||||
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||||
|
│ General Public License for more details. │
|
||||||
|
│ │
|
||||||
|
│ You should have received a copy of the GNU General Public License │
|
||||||
|
│ along with this program; if not, write to the Free Software │
|
||||||
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
|
│ 02110-1301 USA │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "ape/lib/pc.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
|
|
||||||
|
static bool IsDataAvailable(struct Fd *fd) {
|
||||||
|
return inb(fd->handle + UART_LSR) & UART_TTYDA;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetFirstIov(struct iovec *iov, int iovlen) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < iovlen; ++i) {
|
||||||
|
if (iov[i].iov_len) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t readv$serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||||
|
size_t i, j, got = 0;
|
||||||
|
if ((i = GetFirstIov(iov, iovlen)) != -1) {
|
||||||
|
while (!IsDataAvailable(fd)) asm("pause");
|
||||||
|
i = 0;
|
||||||
|
j = 0;
|
||||||
|
do {
|
||||||
|
++got;
|
||||||
|
((char *)iov[i].iov_base)[j] = inb(fd->handle);
|
||||||
|
if (++j == iov[i].iov_len) {
|
||||||
|
j = 0;
|
||||||
|
if (++i == iovlen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (IsDataAvailable(fd));
|
||||||
|
}
|
||||||
|
return got;
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data to multiple buffers.
|
* Reads data to multiple buffers.
|
||||||
|
@ -31,19 +31,19 @@
|
||||||
* @return number of bytes actually read, or -1 w/ errno
|
* @return number of bytes actually read, or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
if (!IsTrustworthy()) {
|
if (fd < 0) return einval();
|
||||||
if (fd == -1) return einval();
|
|
||||||
if (iovlen < 0) return einval();
|
if (iovlen < 0) return einval();
|
||||||
}
|
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
if (isfdkind(fd, kFdZip)) {
|
|
||||||
return weaken(__zipos_read)(
|
return weaken(__zipos_read)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||||
}
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||||
if (!IsWindows()) {
|
return readv$serial(&g_fds.p[fd], iov, iovlen);
|
||||||
|
} else if (!IsWindows()) {
|
||||||
return readv$sysv(fd, iov, iovlen);
|
return readv$sysv(fd, iov, iovlen);
|
||||||
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
|
} else if (fd < g_fds.n &&
|
||||||
|
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||||
return read$nt(&g_fds.p[fd], iov, iovlen, -1);
|
return read$nt(&g_fds.p[fd], iov, iovlen, -1);
|
||||||
} else if (isfdkind(fd, kFdSocket)) {
|
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdSocket)) {
|
||||||
return weaken(recvfrom$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
return weaken(recvfrom$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
return ebadf();
|
return ebadf();
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
void removefd(int fd) {
|
void __removefd(int fd) {
|
||||||
if (isfdopen(fd)) {
|
if (__isfdopen(fd)) {
|
||||||
g_fds.p[fd].kind = kFdEmpty;
|
g_fds.p[fd].kind = kFdEmpty;
|
||||||
g_fds.f = MIN(g_fds.f, fd);
|
g_fds.f = MIN(g_fds.f, fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,6 @@ textwindows int rename$nt(const char *oldpath, const char *newpath) {
|
||||||
if (MoveFileEx(oldpath16, newpath16, kNtMovefileReplaceExisting)) {
|
if (MoveFileEx(oldpath16, newpath16, kNtMovefileReplaceExisting)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,6 @@ textwindows int rmdir$nt(const char *path) {
|
||||||
if (RemoveDirectory(path16)) {
|
if (RemoveDirectory(path16)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ static textwindows noinline int sched_setaffinity$nt(int pid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = SetAffinityMask(handle ? handle : pid, mask) ? 0 : winerr();
|
rc = SetAffinityMask(handle ? handle : pid, mask) ? 0 : __winerr();
|
||||||
if (handle) CloseHandle(handle);
|
if (handle) CloseHandle(handle);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ textwindows int setitimer$nt(int which, const struct itimerval *newvalue,
|
||||||
if (newvalue) {
|
if (newvalue) {
|
||||||
if (newvalue->it_value.tv_sec && newvalue->it_value.tv_usec) {
|
if (newvalue->it_value.tv_sec && newvalue->it_value.tv_usec) {
|
||||||
if (!(ith = CreateWaitableTimer(NULL, false, NULL))) {
|
if (!(ith = CreateWaitableTimer(NULL, false, NULL))) {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
duetime = -(newvalue->it_value.tv_sec * HECTONANOSECONDS +
|
duetime = -(newvalue->it_value.tv_sec * HECTONANOSECONDS +
|
||||||
newvalue->it_value.tv_usec * 10);
|
newvalue->it_value.tv_usec * 10);
|
||||||
|
|
|
@ -48,6 +48,6 @@ textwindows int setpriority$nt(int nice) {
|
||||||
SetThreadPriority(GetCurrentThread(), p.wut)) {
|
SetThreadPriority(GetCurrentThread(), p.wut)) {
|
||||||
return p.nice;
|
return p.nice;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ static void sigaction$cosmo2native(union metasigaction *sa) {
|
||||||
sa_mask);
|
sa_mask);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ static void sigaction$native2cosmo(union metasigaction *sa) {
|
||||||
sa_mask);
|
sa_mask);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,6 @@ textwindows int stat$nt(const char *path, struct stat *st) {
|
||||||
CloseHandle(fh);
|
CloseHandle(fh);
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about thing.
|
* Returns information about thing.
|
||||||
|
|
|
@ -29,6 +29,6 @@ textwindows int symlink$nt(const char *target, const char *linkpath) {
|
||||||
if (CreateSymbolicLink(linkpath16, target16, flags)) {
|
if (CreateSymbolicLink(linkpath16, target16, flags)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,6 @@ textwindows int sysinfo$nt(struct sysinfo *info) {
|
||||||
info->mem_unit = 1;
|
info->mem_unit = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,5 @@ textwindows int truncate$nt(const char *path, uint64_t length) {
|
||||||
CloseHandle(fh);
|
CloseHandle(fh);
|
||||||
if (ok) return 0;
|
if (ok) return 0;
|
||||||
}
|
}
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,6 @@ textwindows int unlink$nt(const char *name) {
|
||||||
if (DeleteFile(name16)) {
|
if (DeleteFile(name16)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
|
||||||
-1) {
|
-1) {
|
||||||
closeme = true;
|
closeme = true;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return einval();
|
return einval();
|
||||||
|
@ -77,7 +77,7 @@ textwindows int utimensat$nt(int dirfd, const char *path,
|
||||||
if (SetFileTime(fh, NULL, ftp[0], ftp[1])) {
|
if (SetFileTime(fh, NULL, ftp[0], ftp[1])) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = __winerr();
|
||||||
}
|
}
|
||||||
if (closeme) {
|
if (closeme) {
|
||||||
CloseHandle(fh);
|
CloseHandle(fh);
|
||||||
|
|
|
@ -41,7 +41,7 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
|
||||||
uint32_t i, count, timeout;
|
uint32_t i, count, timeout;
|
||||||
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
|
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
|
||||||
if (pid != -1) {
|
if (pid != -1) {
|
||||||
if (!isfdkind(pid, kFdProcess)) {
|
if (!__isfdkind(pid, kFdProcess)) {
|
||||||
return echild();
|
return echild();
|
||||||
}
|
}
|
||||||
handles[0] = g_fds.p[pid].handle;
|
handles[0] = g_fds.p[pid].handle;
|
||||||
|
@ -67,8 +67,8 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
|
||||||
} else {
|
} else {
|
||||||
i = WaitForMultipleObjects(count, handles, false, -1);
|
i = WaitForMultipleObjects(count, handles, false, -1);
|
||||||
}
|
}
|
||||||
if (i == kNtWaitFailed) return winerr();
|
if (i == kNtWaitFailed) return __winerr();
|
||||||
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return winerr();
|
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return __winerr();
|
||||||
if (dwExitCode == kNtStillActive) continue;
|
if (dwExitCode == kNtStillActive) continue;
|
||||||
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
|
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
|
||||||
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
|
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
|
||||||
|
@ -80,6 +80,8 @@ textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
|
||||||
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
|
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
|
||||||
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
|
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
|
||||||
}
|
}
|
||||||
|
CloseHandle(g_fds.p[pids[i]].handle);
|
||||||
|
g_fds.p[pids[i]].kind = kFdEmpty;
|
||||||
return pids[i];
|
return pids[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
* @return -1 w/ few exceptions
|
* @return -1 w/ few exceptions
|
||||||
* @note this is a code-size saving device
|
* @note this is a code-size saving device
|
||||||
*/
|
*/
|
||||||
privileged int64_t winerr(void) {
|
privileged int64_t __winerr(void) {
|
||||||
if (IsWindows()) {
|
if (IsWindows()) {
|
||||||
errno = GetLastError();
|
errno = GetLastError();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -46,6 +46,6 @@ textwindows ssize_t write$nt(struct Fd *fd, const struct iovec *iov,
|
||||||
FlushFileBuffers(fd->handle);
|
FlushFileBuffers(fd->handle);
|
||||||
return wrote;
|
return wrote;
|
||||||
} else {
|
} else {
|
||||||
return winerr();
|
return __winerr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,8 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
|
||||||
#include "libc/bits/weaken.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/calls/internal.h"
|
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/internal.h"
|
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
#include "libc/zipos/zipos.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes data to file descriptor.
|
* Writes data to file descriptor.
|
||||||
|
@ -39,34 +32,5 @@
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
ssize_t write(int fd, const void *buf, size_t size) {
|
ssize_t write(int fd, const void *buf, size_t size) {
|
||||||
ssize_t rc;
|
return writev(fd, &(struct iovec){buf, size}, 1);
|
||||||
size_t wrote;
|
|
||||||
if (fd == -1) return einval();
|
|
||||||
if (isfdkind(fd, kFdZip)) {
|
|
||||||
rc = weaken(__zipos_write)(
|
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
|
|
||||||
(struct iovec[]){{buf, size}}, 1, -1);
|
|
||||||
} else if (!IsWindows()) {
|
|
||||||
rc = write$sysv(fd, buf, size);
|
|
||||||
} else if (isfdkind(fd, kFdSocket)) {
|
|
||||||
rc = weaken(sendto$nt)(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, 0,
|
|
||||||
NULL, 0);
|
|
||||||
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
|
|
||||||
rc = write$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1);
|
|
||||||
} else {
|
|
||||||
return ebadf();
|
|
||||||
}
|
|
||||||
if (rc != -1) {
|
|
||||||
wrote = (size_t)rc;
|
|
||||||
if (wrote == 0) {
|
|
||||||
assert(size == 0);
|
|
||||||
} else {
|
|
||||||
assert(wrote <= size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsTrustworthy() && rc != -1) {
|
|
||||||
if (!rc && size) abort();
|
|
||||||
if ((size_t)rc > size) abort();
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,39 +18,17 @@
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/lib/pc.h"
|
#include "ape/lib/pc.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
#include "libc/stdio/internal.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
|
|
||||||
static void fin(FILE *f) {
|
ssize_t writev$serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||||
f->buf[f->end] = inb(0x3F8);
|
size_t i, j, wrote = 0;
|
||||||
f->end = (f->end + 1) & (f->size - 1);
|
for (i = 0; i < iovlen; ++i) {
|
||||||
}
|
for (j = 0; j < iov[i].iov_len; ++j) {
|
||||||
|
while (!(inb(fd->handle + UART_LSR) & UART_TTYTXR)) asm("pause");
|
||||||
static void fout(FILE *f) {
|
outb(fd->handle, ((char *)iov[i].iov_base)[j]);
|
||||||
outb(0x3F8, f->buf[f->beg]);
|
++wrote;
|
||||||
f->beg = (f->beg + 1) & (f->size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int serialstdio(FILE *f, unsigned char status, void action(FILE *)) {
|
|
||||||
int block = 1;
|
|
||||||
unsigned tally = 0;
|
|
||||||
while (f->end != f->beg) {
|
|
||||||
if (!(inb(0x3F8 + UART_LSR) & status)) {
|
|
||||||
if (!block) break;
|
|
||||||
asm("pause");
|
|
||||||
} else {
|
|
||||||
action(f);
|
|
||||||
tally++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (int)tally;
|
return wrote;
|
||||||
}
|
|
||||||
|
|
||||||
int fsreadbuf(FILE *f) {
|
|
||||||
return serialstdio(f, UART_TTYDA, fin);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fswritebuf(FILE *f) {
|
|
||||||
return serialstdio(f, UART_TTYTXR, fout);
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/zipos/zipos.h"
|
#include "libc/zipos/zipos.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes data from multiple buffers.
|
* Writes data from multiple buffers.
|
||||||
|
@ -35,19 +35,19 @@
|
||||||
* @return number of bytes actually handed off, or -1 w/ errno
|
* @return number of bytes actually handed off, or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
if (!IsTrustworthy()) {
|
if (fd < 0) return einval();
|
||||||
if (fd == -1) return einval();
|
|
||||||
if (iovlen < 0) return einval();
|
if (iovlen < 0) return einval();
|
||||||
}
|
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||||
if (isfdkind(fd, kFdZip)) {
|
|
||||||
return weaken(__zipos_write)(
|
return weaken(__zipos_write)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||||
}
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||||
if (!IsWindows()) {
|
return writev$serial(&g_fds.p[fd], iov, iovlen);
|
||||||
|
} else if (!IsWindows()) {
|
||||||
return writev$sysv(fd, iov, iovlen);
|
return writev$sysv(fd, iov, iovlen);
|
||||||
} else if (isfdkind(fd, kFdFile) || isfdkind(fd, kFdConsole)) {
|
} else if (fd < g_fds.n &&
|
||||||
|
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||||
return write$nt(&g_fds.p[fd], iov, iovlen, -1);
|
return write$nt(&g_fds.p[fd], iov, iovlen, -1);
|
||||||
} else if (isfdkind(fd, kFdSocket)) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||||
return weaken(sendto$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
return weaken(sendto$nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
return ebadf();
|
return ebadf();
|
||||||
|
|
|
@ -82,7 +82,7 @@ textwindows int getntnameservers(struct ResolvConf *resolv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = __winerr();
|
||||||
}
|
}
|
||||||
RegCloseKey(hkInterfaces);
|
RegCloseKey(hkInterfaces);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -24,7 +24,8 @@ int vsprintf(char *, const char *, va_list)
|
||||||
paramsnonnull((2)) nothrow nocallback frownedupon(vsnprintf);
|
paramsnonnull((2)) nothrow nocallback frownedupon(vsnprintf);
|
||||||
int sscanf(const char *, const char *, ...) scanfesque(2);
|
int sscanf(const char *, const char *, ...) scanfesque(2);
|
||||||
int vsscanf(const char *, const char *, va_list);
|
int vsscanf(const char *, const char *, va_list);
|
||||||
int vcscanf(int callback(void *), void *, const char *, va_list);
|
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||||
|
va_list);
|
||||||
char *strerror(int) returnsnonnull nothrow nocallback;
|
char *strerror(int) returnsnonnull nothrow nocallback;
|
||||||
int strerror_r(int, char *, size_t) nothrow nocallback;
|
int strerror_r(int, char *, size_t) nothrow nocallback;
|
||||||
int palandprintf(void *, void *, const char *, va_list) hidden;
|
int palandprintf(void *, void *, const char *, va_list) hidden;
|
||||||
|
|
|
@ -44,7 +44,8 @@
|
||||||
* @param va points to the variadic argument state
|
* @param va points to the variadic argument state
|
||||||
* @see libc/fmt/pflink.h (dynamic memory is not a requirement)
|
* @see libc/fmt/pflink.h (dynamic memory is not a requirement)
|
||||||
*/
|
*/
|
||||||
int vcscanf(int callback(void *), void *arg, const char *fmt, va_list va) {
|
int vcscanf(int callback(void *), int unget(int, void *), void *arg,
|
||||||
|
const char *fmt, va_list va) {
|
||||||
struct FreeMe {
|
struct FreeMe {
|
||||||
struct FreeMe *next;
|
struct FreeMe *next;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
@ -56,13 +57,18 @@ int vcscanf(int callback(void *), void *arg, const char *fmt, va_list va) {
|
||||||
while (c != -1) {
|
while (c != -1) {
|
||||||
switch (p[i++]) {
|
switch (p[i++]) {
|
||||||
case '\0':
|
case '\0':
|
||||||
return items;
|
if (c != -1 && unget) {
|
||||||
|
unget(c, arg);
|
||||||
|
}
|
||||||
|
goto Done;
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\v':
|
case '\v':
|
||||||
while (isspace(c)) c = callback(arg);
|
while (isspace(c)) {
|
||||||
|
c = callback(arg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '%': {
|
case '%': {
|
||||||
uintmax_t number;
|
uintmax_t number;
|
||||||
|
|
|
@ -47,5 +47,5 @@ static int vsscanfcb(void *arg) {
|
||||||
*/
|
*/
|
||||||
int(vsscanf)(const char *str, const char *fmt, va_list va) {
|
int(vsscanf)(const char *str, const char *fmt, va_list va) {
|
||||||
struct StringScannerState state = {(const unsigned char *)str, 0};
|
struct StringScannerState state = {(const unsigned char *)str, 0};
|
||||||
return vcscanf(vsscanfcb, &state, fmt, va);
|
return vcscanf(vsscanfcb, NULL, &state, fmt, va);
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,7 @@
|
||||||
#define DWORDLONG ULONGLONG
|
#define DWORDLONG ULONGLONG
|
||||||
#define PDWORDLONG DWORDLONG*
|
#define PDWORDLONG DWORDLONG*
|
||||||
#define LARGE_INTEGER int64_t
|
#define LARGE_INTEGER int64_t
|
||||||
|
#define PLARGE_INTEGER int64_t*
|
||||||
|
|
||||||
#define ULONG uint32_t
|
#define ULONG uint32_t
|
||||||
#define PULONG ULONG*
|
#define PULONG ULONG*
|
||||||
|
@ -1273,9 +1274,9 @@
|
||||||
#define WSAPROTOCOL_INFO struct NtWsaProtocolInfo
|
#define WSAPROTOCOL_INFO struct NtWsaProtocolInfo
|
||||||
#define LPWSAPROTOCOL_INFO struct NtWsaProtocolInfo*
|
#define LPWSAPROTOCOL_INFO struct NtWsaProtocolInfo*
|
||||||
|
|
||||||
#define _WSABUF iovec$nt
|
#define _WSABUF NtIovec
|
||||||
#define WSABUF struct iovec$nt
|
#define WSABUF struct NtIovec
|
||||||
#define LPWSABUF struct iovec$nt*
|
#define LPWSABUF struct NtIovec*
|
||||||
|
|
||||||
#define _GUID NtGuid
|
#define _GUID NtGuid
|
||||||
#define GUID struct NtGuid
|
#define GUID struct NtGuid
|
||||||
|
@ -1320,9 +1321,9 @@
|
||||||
#define SD_SEND SHUT_WR
|
#define SD_SEND SHUT_WR
|
||||||
#define SD_BOTH SHUT_RDWR
|
#define SD_BOTH SHUT_RDWR
|
||||||
|
|
||||||
#define WSAMSG struct msghdr$nt
|
#define WSAMSG struct NtMsgHdr
|
||||||
#define PWSAMSG struct msghdr$nt*
|
#define PWSAMSG struct NtMsgHdr*
|
||||||
#define LPWSAMSG struct msghdr$nt*
|
#define LPWSAMSG struct NtMsgHdr*
|
||||||
|
|
||||||
#define _MEMORYSTATUSEX NtMemoryStatusEx
|
#define _MEMORYSTATUSEX NtMemoryStatusEx
|
||||||
#define MEMORYSTATUSEX struct NtMemoryStatusEx
|
#define MEMORYSTATUSEX struct NtMemoryStatusEx
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
PKGS += LIBC
|
PKGS += LIBC
|
||||||
|
|
||||||
LIBC_HDRS = $(filter %.h,$(LIBC_FILES))
|
LIBC_HDRS = $(filter %.h,$(LIBC_FILES))
|
||||||
LIBC_FILES := $(wildcard libc/*) $(wildcard libc/internal/*)
|
LIBC_FILES := $(wildcard libc/*)
|
||||||
LIBC_CHECKS = $(LIBC_HDRS:%=o/$(MODE)/%.ok)
|
LIBC_CHECKS = $(LIBC_HDRS:%=o/$(MODE)/%.ok)
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/libc
|
.PHONY: o/$(MODE)/libc
|
||||||
|
|
|
@ -1,24 +1,7 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
||||||
#define COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
#define COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_
|
||||||
|
|
||||||
/**
|
#define COM1 0x0
|
||||||
* @fileoverview PC Serial Line Helpers (8250 UART 16550+).
|
|
||||||
*
|
|
||||||
* <p>These functions provide the baseline of PC telecommunications
|
|
||||||
* support that doesn't require switching context or cpu mode.
|
|
||||||
*
|
|
||||||
* <p>Example use cases:
|
|
||||||
* <ul>
|
|
||||||
* <li>Qemu stdio
|
|
||||||
* <li>Bare metal stdio
|
|
||||||
* <li>FIPS-170-2 SSH alternative
|
|
||||||
* <li>NIC for key-signing servers
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @see www.lammertbies.nl/comm/info/serial-uart.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define COM1 0x0 /* offset in pc bios data area with port number (0x400) */
|
|
||||||
#define COM2 0x2
|
#define COM2 0x2
|
||||||
#define COM3 0x4
|
#define COM3 0x4
|
||||||
#define COM4 0x6
|
#define COM4 0x6
|
||||||
|
@ -40,16 +23,4 @@
|
||||||
#define UART_TTYIDL (1 << 6) /* serial thr empty and line idle */
|
#define UART_TTYIDL (1 << 6) /* serial thr empty and line idle */
|
||||||
#define UART_TTYEDF (1 << 7) /* erroneous data in fifo */
|
#define UART_TTYEDF (1 << 7) /* erroneous data in fifo */
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
void sinit(unsigned short *ports, unsigned count, const char *config);
|
|
||||||
void sputc(unsigned char ch, int port);
|
|
||||||
int sgetc(int port);
|
|
||||||
void sputs(const char *s, int port);
|
|
||||||
void sflush(unsigned short *ports, unsigned count);
|
|
||||||
unsigned char slsr(int port);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_ */
|
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_UART_H_ */
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_AcquireSRWLockExclusive,AcquireSRWLockExclusive,683
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
AcquireSRWLockExclusive:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_AcquireSRWLockExclusive(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn AcquireSRWLockExclusive,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_AcquireSRWLockShared,AcquireSRWLockShared,684
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
AcquireSRWLockShared:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_AcquireSRWLockShared(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn AcquireSRWLockShared,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_DeleteCriticalSection,DeleteCriticalSection,0
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
DeleteCriticalSection:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_DeleteCriticalSection(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn DeleteCriticalSection,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_EnterCriticalSection,EnterCriticalSection,0
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
EnterCriticalSection:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_EnterCriticalSection(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn EnterCriticalSection,globl
|
||||||
|
.previous
|
|
@ -1,2 +1,14 @@
|
||||||
.include "o/libc/nt/codegen.inc"
|
.include "o/libc/nt/codegen.inc"
|
||||||
.imp KernelBase,__imp_GetTickCount64,GetTickCount64,780
|
.imp KernelBase,__imp_GetTickCount64,GetTickCount64,780
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
GetTickCount64:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_GetTickCount64(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn GetTickCount64,globl
|
||||||
|
.previous
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_InitializeCriticalSection,InitializeCriticalSection,0
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
InitializeCriticalSection:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_InitializeCriticalSection(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn InitializeCriticalSection,globl
|
||||||
|
.previous
|
|
@ -1,5 +1,5 @@
|
||||||
.include "o/libc/nt/codegen.inc"
|
.include "o/libc/nt/codegen.inc"
|
||||||
.imp KernelBase,__imp_InitializeCriticalSectionAndSpinCount,InitializeCriticalSectionAndSpinCount,856
|
.imp KernelBase,__imp_InitializeCriticalSectionAndSpinCount,InitializeCriticalSectionAndSpinCount,0
|
||||||
|
|
||||||
.text.windows
|
.text.windows
|
||||||
InitializeCriticalSectionAndSpinCount:
|
InitializeCriticalSectionAndSpinCount:
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_InitializeSRWLock,InitializeSRWLock,1128
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
InitializeSRWLock:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_InitializeSRWLock(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn InitializeSRWLock,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_LeaveCriticalSection,LeaveCriticalSection,0
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
LeaveCriticalSection:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_LeaveCriticalSection(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn LeaveCriticalSection,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_ReleaseSRWLockExclusive,ReleaseSRWLockExclusive,1341
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
ReleaseSRWLockExclusive:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_ReleaseSRWLockExclusive(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn ReleaseSRWLockExclusive,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_ReleaseSRWLockShared,ReleaseSRWLockShared,1342
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
ReleaseSRWLockShared:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_ReleaseSRWLockShared(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn ReleaseSRWLockShared,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,12 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_SetCriticalSectionSpinCount,SetCriticalSectionSpinCount,0
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
SetCriticalSectionSpinCount:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov __imp_SetCriticalSectionSpinCount(%rip),%rax
|
||||||
|
jmp __sysv2nt
|
||||||
|
.endfn SetCriticalSectionSpinCount,globl
|
||||||
|
.previous
|
|
@ -0,0 +1,15 @@
|
||||||
|
.include "o/libc/nt/codegen.inc"
|
||||||
|
.imp KernelBase,__imp_TryAcquireSRWLockExclusive,TryAcquireSRWLockExclusive,1467
|
||||||
|
|
||||||
|
.text.windows
|
||||||
|
TryAcquireSRWLockExclusive:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
.profilable
|
||||||
|
mov %rdi,%rcx
|
||||||
|
sub $32,%rsp
|
||||||
|
call *__imp_TryAcquireSRWLockExclusive(%rip)
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn TryAcquireSRWLockExclusive,globl
|
||||||
|
.previous
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue