Page 14 of 16
Re: Newlib
Posted: Fri Mar 11, 2016 2:41 pm
by Siemargl
1. Ошибочка в файловом в/в
При записи на tmp0/1 при окончании места на диске, код ошибки не возвращается
Spoiler:
Code: Select all
void create_file(const char* filename, int size) {
FILE* file = fopen(filename, "rb");
if (file != NULL) {
// Файл уже есть
printf("Use file %s\n", filename);
fclose(file);
return;
}
printf("Create file %s size %d ...\n", filename, size);
file = fopen(filename, "wb");
int rc = 0;
if (file != NULL) {
for (int i = 0; i < size; i++) {
rc = fprintf(file, "%d\n", rand());
if (rc < 0) perror("Error:");
}
rc = fclose(file);
if (rc) perror("Error:");
}
else
perror("Error:");
printf("errno on exit=%d", errno);
}
Серг пофиксил. Кроме того см. примечание по gcc и stderr
viewtopic.php?p=64691#p64691
2. clock() не работает
можно заменить на
Code: Select all
#include "kos32sys.h"
#define CLOCKS_PER_SEC (100)
uint32_t clock1()
{
return get_tick_count();
}
Re: Newlib
Posted: Tue Apr 05, 2016 3:38 pm
by punk_joker
Правильно ли я понимаю, что строковые функции из newlib не работают с ассемблерными строками? Т.е. я немогу скопировать путь возвращаемый OpenDialog например, и для этого придется писать свой вариант функции? Или же это все таки ошибка в реализации функции?
Re: Newlib
Posted: Wed Apr 06, 2016 10:03 pm
by Albom
Судя по исходникам rtfread (файл rtfread.asm, строки 116-124, 848-855), OpenDialog возвращает имя файла в виде ASCIIZ - т.е. с завершающим нулевым символом. Т.е. функции стандартной библиотеки Си для работы со строками должны результат обработать. Код newlib смотрел давно, но не верится, что там ошибка. Скорее всего что-то не так в коде "прослойки Си-ассемблер" (возможно, в выравнивании полей структуры OpenDialog).
Re: Newlib
Posted: Thu Apr 07, 2016 7:59 am
by Serge
Re: Newlib
Posted: Thu Jun 09, 2016 10:01 pm
by GerdtR
Ситуация такая. Код CMM, запуская, прога отрабатывает, корректно завершается, но остаётся висеть один процесс cmm. Причём грузит проц на 100%. Вычислил, что такое происходит, если вызвать fopen-fclose. Причём даже просто писал в main:
Spoiler:
FILE* inih = fopen("/rd/1/settings/c--.ini","rb");
fclose(inih);
return 0;
При этом, я пишу такой код в Hello, и всё как положено работает. Но в CMM обязательно зависнет какой-то поток, если был вызов fopen. Не представляю, в какую сторону искать.
Re: Newlib
Posted: Tue Nov 15, 2016 11:23 pm
by Serge
Сделал конверсию из UTF16 в однобайтные кодировки. Для русского языка
Code: Select all
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE,"C.CP866");
wprintf(L"%S",L"Привет, Мир!\n");
return 0;
}
Поддерживаются CP437, CP720, CP737, CP775, CP850, CP852, CP855, CP857, CP858, CP862, CP866, CP874, CP1125, CP1250, CP1251, CP1252, CP1253, CP1254, CP1255, CP1256, CP1257, CP1258,
CP20866, CP21866, CP101 (GEORGIAN-PS), CP102 (PT154 Kazakhstan)
Spoiler:
-
1.png (63.09 KiB)
Viewed 11285 times
Re: Newlib
Posted: Mon Feb 06, 2017 7:48 pm
by netryx
Serge, хотелось бы нормальной работы функции stat, для аргументов ".","/fd2/1","/hd0/1","/sys" и т.д.
Вроде как в некоторых случаях эта функция возвращает -1 .
Я написал свою реализацию lstat, которая исправляет эти нюансы, но опирается на вашу реализацию stat( из dll-ки ). Можно еще сделать заполнения полей st_dev, st_ino, хотя бы случайными значениями, можно st_ino заполнять хэш суммой канонического имени файла в нижнем регистре. А то моя сборка busybox глючит. Я приведу код, будет понятно почему из-за незаполненого st_ino возникает ошибка :
Code: Select all
/* It is a bad idea to store the archive we are in the process of creating,
* so check the device and inode to be sure that this particular file isn't
* the new tarball */
if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
tbInfo->statBuf.st_ino == statbuf->st_ino) {
error_msg("%s: file is the archive; skipping", fileName);
return( TRUE);
}
Получается совпадения s_ino для записываемого архива tar и помещаемого в него файла.
Еще есть предложения по crt, сделать скрытые параметры, которые не доходят до main, но обрабатываются при запуске приложения. Например, --stdout-to=<file>, --stdin-from=<file>, --stderr-to=<file>. Для перенаправления стандартных потоков в файлы.
Еще хотелось бы реализации функции pipe, dup2, еще бы и fork.
И функции типа (что бы была видна из dll) :
__io_handle* get_global_io_table(){
return __io_tab;
}
Чтобы можно было не меняя dll-ки перенаправить стандартные потоки в виртуальные файлы.
Re: Newlib
Posted: Mon Feb 06, 2017 8:46 pm
by Siemargl
inode есть не у всех файловых систем, мягко говоря.
И функции KOS не возвращают ничего подобного.
Приведенное выражение похоже на проверку симлинка
Re: Newlib
Posted: Mon Feb 06, 2017 9:53 pm
by netryx
Это код из busybox (tar.c), о котором я говорю приводит к ошибке в моей сборке. Если libc stat не заполняет st_ino, то там может быть все что угодно, включая 0. При совпадении dev и inode программа падает с ошибкой, говоря что помещаемый в архив файл сам является создаваемым архивом, в который этот файл пемещается.
Re: Newlib
Posted: Tue Feb 07, 2017 4:05 pm
by Serge
netryx
st_ino должна быть уникальна для каждого файла ? Туда можно писать указатель на структуру с данными файла.
Update.
Посмотрел stat(), лучше хеш писать.
Re: Newlib
Posted: Fri Feb 17, 2017 11:17 am
by netryx
Serge,
Да, st_ino должен быть уникальным для каждого уникального файла (при одном и том же st_dev).
Да ладно. Тот нюанс можно вручную профиксить.
Гораздо больше проблем создает другой нюанс stat:
Не работает stat:
stat .
stat /fd2/1
stat /rd/1
stat /hd0/1
stat /tmp0/1
stat /cd2/1
stat /sys
stat /fd2
Из-за этого может не работать:
busybox ls
busybox mkdir с ключом -p
Распаковщик tar не может создать иерархию каталогов, потому что stat с первым компонентом пути (типа "/tmp0") возвращает -1.
Это может быть от странного поведения функции 70.5 (stat вроде как на нее опирается) : Функция не поддерживает виртуальные папки типа /, /rd и корневые папки типа /rd/1
Я думал что это профиксили в ядре (у меня старая документация), но видимо ошибся.
Удивительно, но работает stat /kolibrios
Пример для тестирования stat:
Code: Select all
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
int main(int argc,char** argv)
{
struct stat buf;
int ret;
const char* arg=".";
if (argc<=1){
printf("\nUsage:\nstat <filename>\n");
//return 0;
}else
arg=argv[1];
if ((ret=stat(arg,&buf))==0){
printf("\nOK stat !file=%s,\nmode:0x%x\n" ,arg,(int)buf.st_mode);
printf("\nst_dev:0x%x" ,(int)buf.st_dev);
printf("\nst_ino:0x%x" ,(int)buf.st_ino);
printf("\nst_nlink:0x%x" ,(int)buf.st_nlink);
printf("\nst_uid:0x%x" ,(int)buf.st_uid);
printf("\nst_gid:0x%x" ,(int)buf.st_gid);
printf("\nst_rdev:0x%x" ,(int)buf.st_rdev);
printf("\nst_size:0x%x" ,(int)buf.st_size);
}else{
printf("\nFailed,ret=%i\n ",ret);
}
return ret;
}
У меня есть небольшая наработка кода, не совсем полностью устраняющая этот нюанс, могу показать (реализация lstat, которая просто парсит переданный в функцию путь, если соответствует определенному шаблону, то возвращает, что это директория, иначе возвращает значение stat из под newlib).
Re: Newlib
Posted: Fri Feb 17, 2017 12:45 pm
by Pathoswithin
Как раз сейчас чиню это для FAT. Для NTFS уже должно работать.
Re: Newlib
Posted: Fri Feb 17, 2017 1:43 pm
by Siemargl
Pathoswithin wrote:Как раз сейчас чиню это для FAT. Для NTFS уже должно работать.
Раз чинишь, глянь, может аттрибуты расширить по подобию stat ?
http://man7.org/linux/man-pages/man2/stat.2.html
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
симлинки имеются в NTFS и ext
/hd0/1 - блокдевайс
- а что stat возвращает в линухе для /, /dev, /dev/sda0 ?
Re: Newlib
Posted: Fri Feb 17, 2017 6:31 pm
by Serge
netryxУдивительно, но работает stat /kolibrios
под /kolibrios монтируется настоящий каталог. В ядре путь разворачивается в реальный, поэтому stat работает.
У меня есть небольшая наработка кода, не совсем полностью устраняющая этот нюанс, могу показать (реализация lstat, которая просто парсит переданный в функцию путь, если соответствует определенному шаблону, то возвращает, что это директория, иначе возвращает значение stat из под newlib).
Это будет замечательно. Выкладывай здесь.
Re: Newlib
Posted: Fri Feb 17, 2017 7:30 pm
by netryx
Serge,
Code: Select all
static void set_rdir(struct stat * buf){
buf->st_mode=(S_IFDIR| S_IRWXU);
buf->st_ino=(unsigned)rand();
buf->st_dev=(unsigned)rand();
buf->st_size=0;
}
static char* expect_num_in_path(char* path,int* is_num){
char* s,c;
*is_num=0;
c=0;
s=path;
while(*s){
c=*s;
s++;
if (c>='0' && c<='9'){
*is_num=1;
}else{
if (c=='/'){
if (*is_num)
*is_num='/';
break;
}else{
is_num=0;
break;
}
}
}
return s;
}
int kolibri_fix_stat(const char * path, struct stat * buf){
char temp[264];
char* s;
char* end_s;
int i,le;
int is_int;
char c;
if (strcmp(path,".")==0 || strcmp(path,"./")==0)
{
set_rdir(buf);
return 0;
}
if (*path!='/'){
if (NULL==realpath(path,temp)){
return -1;
}
}else{
strcpy(temp,path);
}
le=strlen(temp);
if (le<=0) {
return -1;
}
end_s=temp+(le-1);
if (*end_s=='\\' || *end_s=='/'){
temp[le-1]=0;
le--;
}
if (le<=0) {
return -1;
}
for (i=0;i<le;i++){
temp[i]=tolower(temp[i]);
}
if (
strncmp(temp,"/hd",3)==0 ||
strncmp(temp,"/rd",3)==0 ||
strncmp(temp,"/fd",3)==0 ||
strncmp(temp,"/cd",3)==0 ||
strncmp(temp,"/tmp",4)==0
)
{
s=temp+3;
if ( strncmp(temp,"/rd",3)==0 ){
if (temp[3]==0){
set_rdir(buf);
return 0;
}
if (temp[3]=='/' )
s++;
}else{
if ( //temp[4]=='/' &&
strncmp(temp,"/tmp",4)==0 ){
s++;
}
}
s=expect_num_in_path(s,&is_int);
if (is_int ){
if (*s==0 )
{
set_rdir(buf);
return 0;
}
if (is_int=='/'){
s=expect_num_in_path(s,&is_int);
if (*s==0 && is_int){
set_rdir(buf);
return 0;
}
}
}
//not found path liked "/hd0/1"
//
return -1;
}
if (
strcmp(temp,"/")==0 ||
strcmp(temp,"/sys")==0 ||
strcmp(temp,"/kolibrios")==0
)
{
set_rdir(buf);
return 0;
}
return -1;
}
int lstat(const char * path, struct stat * buf){
int ret;
//unimplemented_func_message("lstat");
ret=kolibri_fix_stat(path,buf);
if (ret==0) return ret;
ret= stat(path,buf);
#if 1
if (ret==0){
//fix EQUAL INO BUG
buf->st_ino=(unsigned)rand();
}
#endif
return ret;
}