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
punk_joker
C opendial должны работать. Посмотри http://websvn.kolibrios.org/filedetails ... endial.asm

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
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;
}