Лиха беда начало

This commit is contained in:
2025-01-05 22:43:45 +03:00
parent c300641efc
commit 788b37f613
39 changed files with 3823 additions and 0 deletions

28
Makefile Normal file
View File

@@ -0,0 +1,28 @@
CC = kos32-gcc
LD = kos32-ld
HOME_DIR = $(shell echo ~)
TOOLCHAIN_DIR = $(abspath /home/autobuild/tools/win32/)
CONTRIB_DIR = $(abspath $(HOME_DIR)/kolibrios/contrib)
SDK_DIR = $(CONTRIB_DIR)/sdk
C_LAYER = $(CONTRIB_DIR)/C_Layer
CFLAGS = -fno-ident -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -I $(SDK_DIR)/sources/newlib/libc/include
LDFLAGS = -static -S -nostdlib -T app.lds --subsystem native -L $(TOOLCHAIN_DIR)/lib -L $TOOLCHAIN_DIR/mingw32/lib -L $(SDK_DIR)/lib
INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -DNDEBUG -I..
LIBPATH = -L $(SDK_DIR)/lib -L $(TOOLCHAIN_DIR)/mingw32/lib
SOURCES := lib/microtar/src/microtar.c lib/ccsv/src/ccsv.c \
src/kospm_tar.c src/kospm_list.c src/kospm_common.c \
src/kospm_package.c src/kospm_db.c src/kospm.c
OBJECTS := $(SOURCES:.c=.o)
default: libkospm.a
libkospm.a: $(OBJECTS) Makefile
ar -crs libkospm.a $(OBJECTS)
%.o : %.c Makefile $(SOURCES)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<

30
include/kospm.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* kospm.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "kospm_db.h"
#include "kospm_package.h"
int kospm_install(kospm_db_t *db, char *pkg_file);
int kospm_remove(kospm_db_t *db, char *pkg_name);
int kospm_query(kospm_db_t *db, char *pkg_name);

54
include/kospm_common.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* kospm_common.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*
*/
#ifndef KOSPM_CSV
#define KOSPM_CSV
#include <stdio.h>
#include <stdlib.h>
#include "../lib/ccsv.h"
#include "kospm_list.h"
ccsv_reader_options _kospm_csv_reader_options = {
.delim = ',',
.quote_char = '"',
.skip_initial_space = 1,
.skip_empty_lines = 1,
.skip_comments = 1
};
ccsv_reader_options _kospm_csv_writer_options = {
.delim = ',',
.quote_char = '"'
};
typedef struct {
int col_number;
char *col_name;
} kospm_csv_header_column;
kospm_list_t* _kospm_csv_header_get(FILE* file);
int _kospm_csv_col_get(kospm_list_t* col_list, char* col_name);
#endif

73
include/kospm_db.h Normal file
View File

@@ -0,0 +1,73 @@
/*
* kospm_db.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*
*/
#ifndef KOSPM_DB
#define KOSPM_DB
#include <stdio.h>
#include "kospm_list.h"
#include "kospm_package.h"
#define DB_FOLDER "/kospm/db"
#define METADATA_TABLE "/packages.csv"
#define FILES_TABLE "/files.csv"
char **_kospm_db_metadata_table_header;
char **_kospm_db_files_table_header;
typedef struct kospm_db {
char *db_path;
FILE* metadata_table;
FILE* files_table;
kospm_list_t *packages;
kospm_list_t *files;
} kospm_db_t;
kospm_db_t* kospm_db_init(char *root_dir);
kospm_db_t* kospm_db_open(char *root_dir);
int kospm_db_save(kospm_db_t *db);
int kospm_db_close(kospm_db_t *db);
int kospm_db_package_add(kospm_db_t *db, kospm_package_t *package);
kospm_package_t* kospm_db_package_query(kospm_db_t *db, char *pkg_name);
int kospm_db_package_remove(kospm_db_t *db, char *pkg_name);
int kospm_db_file_add(kospm_db_t *db, char *pkg_name, kospm_package_file_t *file);
kospm_package_t* kospm_db_file_query(kospm_db_t *db, char *file_name);
int kospm_db_file_remove(kospm_db_t *db, char *filename);
int kospm_db_packages_add(kospm_db_t *db, kospm_package_list_t *package_list);
int kospm_db_files_add(kospm_db_t *db, kospm_list_t *file_list);
int kospm_db_packagelist_save(kospm_db_t *db);
int kospm_db_filelist_save(kospm_db_t *db);
#endif

42
include/kospm_list.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* kospm_list.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*
*/
#ifndef KOSPM_LIST
#define KOSPM_LIST
#include "stddef.h"
typedef struct {
void *data;
kospm_list_t *prev;
kospm_list_t *next;
} kospm_list_t;
kospm_list_t* kospm_list_new(void *data);
void kospm_list_add(kospm_list_t **list, void *data);
void kospm_list_del_by_value(kospm_list_t **list, void *data, int (*cmp)(void *, void *));
void kospm_list_free(kospm_list_t *list);
#endif

56
include/kospm_package.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* kospm_package.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*
*/
#ifndef KOSPM_PKG
#define KOSPM_PKG
#include <stdint.h>
#include "kospm_list.h"
#define PKGINFO "PKGINFO.CSV"
#define FILES "FILES.CSV"
#define CACHE "/tmp0/1/kospm/cache/"
typedef struct {
char pkg_name[64];
char *file_name;
} kospm_package_file_t;
typedef struct {
char pkg_name[64];
char pkg_version[16];
char *pkg_description;
} kospm_package_t;
typedef struct {
kospm_list_t *packages;
kospm_list_t *files;
} kospm_package_list_t;
kospm_list_t* kospm_package_metadata_get(FILE* fp);
kospm_list_t* kospm_package_files_get(FILE* fp);
kospm_package_list_t* kospm_package_list_open(char *pkg_file);
int kospm_package_list_close(kospm_package_list_t *package_list);
#endif

31
include/kospm_tar.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* kospm_tar.h
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*
*/
#ifndef KOSPM_TAR
#define KOSPM_TAR
#include "../lib/microtar/src/microtar.h"
int tar_unpack(const char *tar_name,
const char *src_file, const char *dest_file);
#endif

3
kos_build.sh Normal file
View File

@@ -0,0 +1,3 @@
#SHS
/kolibrios/develop/tcc/tcc -r -o libkospm.o lib/microtar/src/microtar.c lib/ccsv/src/ccsv.c src/kospm_tar.c src/kospm_list.c src/kospm_common.c src/kospm_package.c src/kospm_db.c src/kospm.c

50
kospm.geany Normal file
View File

@@ -0,0 +1,50 @@
[editor]
line_wrapping=false
line_break_column=72
auto_continue_multiline=true
[file_prefs]
final_new_line=true
ensure_convert_new_lines=false
strip_trailing_spaces=false
replace_tabs=false
[indentation]
indent_width=4
indent_type=1
indent_hard_tab_width=8
detect_indent=false
detect_indent_width=false
indent_mode=2
[project]
name=kospm
base_path=/home/kexa/Документы/npoekt/kospm
description=
[long line marker]
long_line_behaviour=1
long_line_column=72
[files]
current_page=0
FILE_NAME_0=1194;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm.c;0;4
FILE_NAME_1=4136;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm_db.c;0;4
FILE_NAME_2=961;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm_list.c;0;4
FILE_NAME_3=3586;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm_package.c;0;4
FILE_NAME_4=1069;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm_tar.c;0;4
FILE_NAME_5=861;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm.h;0;4
FILE_NAME_6=1948;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm_db.h;0;4
FILE_NAME_7=1205;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm_list.h;0;4
FILE_NAME_8=1498;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm_package.h;0;4
FILE_NAME_9=990;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm_tar.h;0;4
FILE_NAME_10=198;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fkos_build.sh;0;4
FILE_NAME_11=907;Make;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2FMakefile;0;4
FILE_NAME_12=9813;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Flib%2Fccsv%2Finclude%2Fccsv.h;0;4
FILE_NAME_13=0;C++;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Flib%2Fmicrotar%2Fsrc%2Fmicrotar.h;0;4
FILE_NAME_14=17;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Fsrc%2Fkospm_common.c;0;4
FILE_NAME_15=1269;C++;0;EUTF-8;1;1;1;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Finclude%2Fkospm_common.h;0;4
FILE_NAME_16=2814;C;0;EUTF-8;1;1;0;%2Fhome%2Fkexa%2FДокументы%2Fnpoekt%2Fkospm%2Flib%2Fccsv%2Fsrc%2Fccsv.c;0;4
[VTE]
last_dir=/home/kexa

58
lib/ccsv/.gitignore vendored Normal file
View File

@@ -0,0 +1,58 @@
/.vscode
/.vs
tests/write_test.c
rough*.c
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

21
lib/ccsv/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Ayush Tripathy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

117
lib/ccsv/README.md Normal file
View File

@@ -0,0 +1,117 @@
# ccsv
Fast, flexible, easy-to-use CSV reading, writing library for C
For full documentation, see the [docs](https://github.com/Ayush-Tripathy/ccsv/tree/main/docs)
## Usage
### Create a reader object
```c
ccsv_reader *reader = ccsv_init_reader(NULL); // NULL for default options
```
### Create a reader object with custom options
```c
ccsv_reader_options options = {
.delim = ',',
.quote_char = '"',
.skip_initial_space = 0,
.skip_empty_lines = 1,
.skip_comments = 1};
// Initialize the reader with the options
ccsv_reader *reader = ccsv_init_reader(&options);
```
### Read a row with
```c
CSVRow *row = read_row(fp, reader); // Will return NULL if all rows are read
```
`fp` is a FILE pointer to the CSV file you want to read
`reader` is a ccsv_reader object
### Get the number of fields in a row with
```c
int row_len = row->fields_count;
```
### Get a field from a row with
```c
char *field = row->fields[0]; // 0 for the first field
```
### Free the memory allocated to a row with
```c
free_row(row);
```
### Free the memory allocated to the reader with
```c
free(reader);
```
## Example
```c
#include <stdio.h>
#include <stdlib.h>
#include "ccsv.h"
int main(void)
{
FILE *fp = fopen("../../ign.csv", "r"); // Specify the path to your file
if (fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
// Reader object
ccsv_reader *reader = ccsv_init_reader(NULL); // NULL for default options
CSVRow *row;
// Read each row and print each field
while ((row = read_row(fp, reader)) != NULL)
{
int row_len = row->fields_count; // Get number of fields in the row
for (int i = 0; i < row_len; i++)
{
printf("%d.Field: %s\n", i + 1, row->fields[i]); // Print each field
}
printf("\n");
free_row(row); // Free the memory allocated to the row
}
printf("\n\nRows read: %d\n", reader->rows_read); // Print number of rows read
free(reader); // Free the memory allocated to the reader
fclose(fp);
return 0;
}
```
#### You can find more examples in the `examples` folder
Compile with `make ./example_file_name`
For full documentation, see the [docs](https://github.com/Ayush-Tripathy/ccsv/tree/main/docs)
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE)
## Feel free to contribute!

BIN
lib/ccsv/docs/ccsv.pdf Normal file

Binary file not shown.

View File

@@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ccsv.h"
int main(int argc, char *argv[])
{
clock_t start = clock();
if (argc != 2)
{
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
char *filename = argv[1];
ccsv_reader_options options = {.skip_initial_space = 1, .skip_empty_lines = 0};
ccsv_reader *reader = ccsv_open(filename, CCSV_READER, "r", &options, NULL);
if (reader == NULL || ccsv_is_error(reader, NULL))
{
fprintf(stderr, "Error initializing CSV reader\n");
return 1;
}
ccsv_row *row;
size_t fields_count = 0;
while ((row = ccsv_next(reader)) != NULL)
{
fields_count += row->fields_count;
ccsv_free_row(row);
}
printf("%s: %d rows, %ld fields\n", argv[1], reader->rows_read, fields_count);
ccsv_close(reader);
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time taken: %lf seconds\n", time_spent);
return 0;
}

68
lib/ccsv/examples/cpy.c Normal file
View File

@@ -0,0 +1,68 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ccsv.h"
int main(int argc, char *argv[])
{
clock_t start = clock();
if (argc != 2)
{
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
char *filename = argv[1];
ccsv_reader *reader = ccsv_init_reader(NULL, NULL);
if (reader == NULL || reader == (void *)CCSV_ERNOMEM)
{
fprintf(stderr, "Error initializing CSV reader\n");
return 1;
}
FILE *file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "Error opening file\n");
free(reader);
return 1;
}
FILE *output = fopen("output.csv", "w+");
if (output == NULL)
{
fprintf(stderr, "Error opening file\n");
free(reader);
fclose(file);
return 1;
}
ccsv_writer *writer = ccsv_init_writer(NULL, NULL);
ccsv_row *row;
size_t fields_count = 0;
while ((row = read_row(file, reader)) != NULL)
{
fields_count += row->fields_count;
write_row(output, writer, *row);
ccsv_free_row(row);
}
printf("%s - %d rows, %ld fields\n", argv[1], reader->rows_read, fields_count);
printf("Output written to output.csv\n");
fclose(file);
fclose(output);
free(reader);
free(writer);
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time taken: %lf seconds\n", time_spent);
return 0;
}

View File

@@ -0,0 +1,52 @@
#include <stdio.h>
#include <time.h>
#include "ccsv.h"
int main(int argc, char **argv)
{
clock_t start = clock();
if (argc != 3)
{
fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]);
return 1;
}
char *source = argv[1];
char *destination = argv[2];
ccsv_reader *reader = ccsv_open(source, CCSV_READER, "r", NULL, NULL);
if (reader == NULL)
{
fprintf(stderr, "Error initializing CSV reader\n");
return 1;
}
ccsv_writer *writer = ccsv_open(destination, CCSV_WRITER, "w+", NULL, NULL);
if (writer == NULL)
{
fprintf(stderr, "Error initializing CSV writer\n");
return 1;
}
ccsv_row *row;
while ((row = ccsv_next(reader)) != NULL)
{
ccsv_write(writer, *row);
ccsv_free_row(row);
}
printf("Rows read: %d\n", reader->rows_read);
printf("CSV file written to %s\n", destination);
ccsv_close(reader);
ccsv_close(writer);
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time taken: %lf seconds\n", time_spent);
return 0;
}

View File

@@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
FILE *csv_file = fopen("../../ign.csv", "r");
if (csv_file == NULL)
{
perror("Error opening file");
return 1;
}
ccsv_reader_options options = {
.delim = ',', // Example delimiter, change according to your CSV file
.quote_char = '"',
.skip_initial_space = 0,
// Add other options if necessary
};
ccsv_reader *reader = ccsv_init_reader(&options, NULL);
if (reader == NULL || ccsv_is_error(reader, NULL))
{
fprintf(stderr, "Error initializing CSV reader\n");
fclose(csv_file);
return 1;
}
ccsv_row *row;
short err_status;
while (1)
{
row = read_row(csv_file, reader);
if (row == NULL && ccsv_is_error(reader, &err_status))
{
if (err_status == CCSV_ERNOMEM)
fprintf(stderr, "Memory allocation failure while reading row\n");
break;
}
int fields_count = row->fields_count;
for (int i = 0; i < fields_count; ++i)
{
printf("%s\t", row->fields[i]);
}
printf("\n");
ccsv_free_row(row);
}
printf("\n\nRows read: %d\n", reader->rows_read);
fclose(csv_file);
free(reader);
return 0;
}

View File

@@ -0,0 +1,8 @@
CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -I../include
%: %.c
$(CC) $(CFLAGS) -o $@.out $< ../src/ccsv.c
clean:
rm -f *.out

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
// ** There is new way to read rows in ccsv v0.5.0 **
// ** Check examples/print_each_row_ccsv_v0.5.c **
FILE *fp = fopen("../../ign.csv", "r"); // Specify the path to your file
if (fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
// Reader object
ccsv_reader *reader = ccsv_init_reader(NULL, NULL); // NULL for default options
/*
Default options:
delim = ','
quote_char = '"'
skip_initial_space = 0
skip_empty_lines = 0
skip_comments = 0
*/
ccsv_row *row;
// Read each row and print each field
while ((row = read_row(fp, reader)) != NULL)
{
int row_len = row->fields_count; // Get number of fields in the row
for (int i = 0; i < row_len; i++)
{
printf("%d.Field: %s\n", i + 1, row->fields[i]); // Print each field
}
printf("\n");
ccsv_free_row(row); // Free the memory allocated to the row
}
printf("\n\nRows read: %d\n", reader->rows_read); // Print number of rows read
free(reader); // Free the memory allocated to the reader
fclose(fp);
return 0;
}

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
ccsv_reader_options options = {
.delim = ',',
.quote_char = '"',
.skip_comments = 1,
.skip_initial_space = 0,
.skip_empty_lines = 0,
};
// Reader object
ccsv_reader *reader = ccsv_open("../../comments.csv", CCSV_READER, "r", &options, NULL); // NULL for default options
if (reader == NULL)
{
fprintf(stderr, "Error initializing CSV reader\n");
return 1;
}
ccsv_row *row;
// Read each row and print each field
while ((row = ccsv_next(reader)) != NULL)
{
int row_len = row->fields_count; // Get number of fields in the row
for (int i = 0; i < row_len; i++)
{
printf("%d.Field: %s\n", i + 1, row->fields[i]); // Print each field
}
printf("\n");
ccsv_free_row(row); // Free the memory allocated to the row
}
printf("\n\nRows read: %d\n", reader->rows_read); // Print number of rows read
ccsv_close(reader); // Close the reader
return 0;
}

View File

@@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
FILE *fp = fopen("../../ign.csv", "r"); // Specify the path to your file
if (fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
// ** There is new way to read rows in ccsv v0.5.0 **
// ** Check examples/print_each_row_ccsv_v0.5.c **
// Reader object
ccsv_reader *reader = ccsv_init_reader(NULL, NULL); // NULL for default options
ccsv_row *row = read_row(fp, reader);
int row_len = row->fields_count; // Get number of fields in the row
for (int i = 0; i < row_len; i++)
{
printf("%d.Field: %s\n", i + 1, row->fields[i]); // Print each field
}
ccsv_free_row(row); // Free the memory allocated to the row
free(reader); // Free the memory allocated to the reader
fclose(fp);
return 0;
}

View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
FILE *fp = fopen("../../ign.csv", "r"); // Specify the path to your file
if (fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
/*
------- Way 1 -------
ccsv_reader_options *options = (ccsv_reader_options *)malloc(sizeof(ccsv_reader_options));
options->delim = ',';
options->quote_char = '"';
options->skip_initial_space = 0;
*/
/* OR */
ccsv_reader_options options = {
.delim = ',',
.quote_char = '"',
.skip_initial_space = 0,
.skip_empty_lines = 1,
.skip_comments = 1};
// Reader object
ccsv_reader *reader = ccsv_init_reader(&options, NULL); // NULL for default options
// free(options); /* If you used Way 1 */
ccsv_row *row;
// Read each row and print each field
while ((row = read_row(fp, reader)) != NULL)
{
int row_len = row->fields_count; // Get number of fields in the row
for (int i = 0; i < row_len; i++)
{
printf("%s\t", row->fields[i]); // Print each field
}
printf("\n");
ccsv_free_row(row); // Free the memory allocated to the row
}
printf("\n\nRows read: %d\n", reader->rows_read); // Print number of rows read
free(reader); // Free the memory allocated to the reader
fclose(fp);
return 0;
}

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include "ccsv.h"
int main(void)
{
// Initialize ccsv_writer_options
ccsv_writer_options options = {
.delim = ',',
.quote_char = '"'
// Add other options if necessary
};
// Initialize the writer
ccsv_writer *writer = ccsv_init_writer(&options, NULL);
if (writer == NULL)
{
fprintf(stderr, "Error initializing CSV writer\n");
return 1;
}
FILE *file = fopen("output.csv", "w+");
if (file == NULL)
{
fprintf(stderr, "Error opening file\n");
free(writer);
return 1;
}
CCSV_WRITE_ROW_START(file, writer); // Write row start
CCSV_WRITE_FIELD(file, writer, "hi"); // Write field
CCSV_WRITE_FIELD(file, writer, "hello, world!"); // Write field
CCSV_WRITE_FIELD(file, writer, "\"escapedword\""); // Write field
CCSV_WRITE_ROW_END(file, writer, NULL); // Write row end
short err_status;
if (ccsv_is_error(writer, &err_status))
{
fprintf(stderr, "Error writing CSV row from string: %s\n", ccsv_get_status_message(err_status));
fclose(file);
free(writer);
return 1;
}
fclose(file);
free(writer);
return 0;
}

View File

@@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include "ccsv.h"
int main(void)
{
// Initialize ccsv_writer_options
ccsv_writer_options options = {
.delim = ',',
.quote_char = '"'
// Add other options if necessary
};
// Initialize the writer
ccsv_writer *writer = ccsv_init_writer(&options, NULL);
if (writer == NULL)
{
fprintf(stderr, "Error initializing CSV writer\n");
return 1;
}
ccsv_reader *reader = ccsv_init_reader(NULL, NULL);
FILE *dest_file = fopen("output.csv", "a+");
if (dest_file == NULL)
{
fprintf(stderr, "Error opening file\n");
free(writer);
return 1;
}
FILE *source_file = fopen("../../ign.csv", "r");
if (source_file == NULL)
{
fprintf(stderr, "Error opening file\n");
free(writer);
return 1;
}
ccsv_row *row = read_row(source_file, reader);
write_row(dest_file, writer, *row); // Pass the value of the row pointer
ccsv_free_row(row); // Free the row
row = read_row(source_file, reader); // Read the next row
write_row(dest_file, writer, *row); // Write row to file
ccsv_free_row(row); // Free the row
if (ccsv_is_error(writer, NULL))
{
fprintf(stderr, "Error writing CSV row.\n");
fclose(dest_file);
fclose(source_file);
free(reader);
free(writer);
return 1;
}
fclose(dest_file);
fclose(source_file);
free(reader);
free(writer);
return 0;
}

View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/ccsv.h"
int main(void)
{
// Initialize ccsv_writer_options
ccsv_writer_options options = {
.delim = ',',
.quote_char = '"'
// Add other options if necessary
};
// Initialize the writer
ccsv_writer *writer = ccsv_init_writer(&options, NULL);
if (writer == NULL)
{
fprintf(stderr, "Error initializing CSV writer\n");
return 1;
}
FILE *file = fopen("output.csv", "a+");
if (file == NULL)
{
fprintf(stderr, "Error opening file\n");
free(writer);
return 1;
}
char *row_string[] = {"hi", "hello", "hello, world!", "\"escapedword\"", "hola", "bonjour"};
write_row_from_array(file, writer, row_string, ARRAY_LEN(row_string)); /* Write row to file */
short err_status;
if (ccsv_is_error(writer, &err_status))
{
fprintf(stderr, "Error writing CSV row from string: %s\n", ccsv_get_status_message(err_status));
fclose(file);
free(writer);
return 1;
}
fclose(file);
free(writer);
return 0;
}

442
lib/ccsv/include/ccsv.h Normal file
View File

@@ -0,0 +1,442 @@
// File: ccsv.h
// Created: 2023 by Ayush Tripathy
// github.com/Ayush-Tripathy
/*
* CCSV - A CSV parser and writer library for C.
* Version: 0.1
*
* For full documentation, see the README.md file.
*/
/*
MIT License
Copyright (c) 2023 Ayush Tripathy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <stdio.h>
#include <stdbool.h>
#define CCSV_VERSION 0.1f
#ifdef __cplusplus
extern "C"
{
#endif
// File sizes
#define CCSV_LARGE_FILE_SIZE 524288000ULL /* 500 MiB */
#define CCSV_MED_FILE_SIZE 20971520ULL /* 20 MiB */
// Buffer sizes
#define CCSV_HIGH_BUFFER_SIZE 65536 /* 64 KiB */
#define CCSV_MED_BUFFER_SIZE 16384 /* 16 KiB */
#define CCSV_LOW_BUFFER_SIZE 2048 /* 2 KiB */
#define CCSV_BUFFER_SIZE 8096
#define MAX_FIELD_SIZE 256
// Default values
#define CCSV_DELIMITER 0x2c
#define CCSV_QUOTE_CHAR 0x22
#define CCSV_CR 0x0d
#define CCSV_LF 0x0a
#define CCSV_SPACE 0x20
#define CCSV_TAB 0x09
#define CCSV_COMMENT_CHAR 0x23
#define CCSV_NULL_CHAR 0x00
#define DEFAULT_DELIMITER CCSV_DELIMITER
#define DEFAULT_QUOTE_CHAR CCSV_QUOTE_CHAR
#define DEFAULT_ESCAPE_CHAR CCSV_QUOTE_CHAR
#define DEFAULT_COMMENT_CHAR CCSV_COMMENT_CHAR
#define TOTAL_ERROR_MESSAGES 7
// Return codes
#define CCSV_SUCCESS 0
#define CCSV_ERROR -1
#define CCSV_ERNOMEM -2
#define CCSV_ERINVALID -3
#define CCSV_ERNULLFP -6 /* File pointer is NULL */
#define CCSV_ERMODE -7 /* Invalid mode */
#define CCSV_EROPEN -8 /* Error opening file */
#define CCSV_ERINVOBJTYPE -9 /* Invalid object type */
#define CCSV_ERNULLROW -10 /* Row is NULL */
#define CCSV_ERBUFNTALLOC -11 /* Buffer not allocated */
#define WRITE_SUCCESS CCSV_SUCCESS
#define WRITE_STARTED 1
#define WRITE_ENDED 2
#define WRITE_ERNOTSTARTED -4 /* Writer not started */
#define WRITE_ERNOMEM CCSV_ERNOMEM
#define WRITE_ERINVALID CCSV_ERINVALID
#define WRITE_ERALWRITING -5 /* Already writing field */
// Object types
#define CCSV_READER 21
#define CCSV_WRITER 22
#define ARRAY_LEN(array) sizeof(array) / sizeof(array[0])
// Writer Macros
/* Start new row */
#define CCSV_WRITE_ROW_START(fp, writer) _write_row_start(fp, writer)
/* Write field */
#define CCSV_WRITE_FIELD(fp, writer, string) \
if (writer->__state == WRITER_ROW_START) \
{ \
writer->__state = WRITER_WRITING_FIELD; \
} \
else \
{ \
fputc(writer->__delim, fp); \
} \
_write_field(fp, writer, string);
/* End row, with an additional field */
#define CCSV_WRITE_ROW_END(fp, writer, last_field) \
if (last_field) \
{ \
_write_field(fp, writer, last_field); \
} \
_write_row_end(fp, writer);
typedef enum State
{
FIELD_START, /* Start of field */
FIELD_NOT_STARTED, /* Spaces before field start */
FIELD_END, /* End of field */
FIELD_STARTED, /* Inside field */
INSIDE_QUOTED_FIELD, /* Inside quoted field */
MAY_BE_ESCAPED /* Quote char detected inside quoted field */
} State;
typedef enum WriterState
{
WRITER_NOT_STARTED, /* Writer not started */
WRITER_ROW_START, /* Writer setup done */
WRITER_WRITING_FIELD, /* Field writing started */
WRITER_ROW_END /* Row writing ended */
} WriterState;
typedef struct ccsv_reader_options
{
char delim;
char quote_char;
char comment_char;
char escape_char;
int skip_initial_space;
int skip_empty_lines;
int skip_comments;
} ccsv_reader_options;
typedef struct ccsv_reader
{
int rows_read;
char __delim;
char __quote_char;
char __comment_char;
char __escape_char;
int __skip_initial_space;
int __skip_empty_lines;
int __skip_comments;
char *__buffer;
size_t __buffer_pos;
size_t __buffer_size;
bool __buffer_allocated;
FILE *__fp;
short status;
short object_type;
} ccsv_reader;
typedef struct ccsv_row
{
char **fields;
int fields_count;
} ccsv_row;
typedef struct ccsv_writer_options
{
char delim;
char quote_char;
char escape_char;
} ccsv_writer_options;
typedef struct ccsv_writer
{
char __delim;
char __quote_char;
char __escape_char;
WriterState __state;
FILE *__fp;
short write_status;
short object_type;
} ccsv_writer;
// Public functions ------------------------------------------------------------------------
/* -------- General -------- */
/*
* This function opens a file and attaches it with specified object.
*
* returns:
* void*: pointer to the object
*/
void *ccsv_open(const char *filename, short object_type, const char *mode, void *options, short *status);
/*
* This function closes the ccsv object (reader or writer).
*
* params:
* obj: pointer to the object
*/
void ccsv_close(void *obj);
/*
* This function returns the status message for the given status code.
*
* params:
* status: status code
*
* returns:
* char*: pointer to the status message
*/
const char *ccsv_get_status_message(short status);
/*
* This function returns if error occurred in the object.
*
* params:
* obj: pointer to the object
*
* returns:
* int: 1, if error occurred
* int: 0, if no error occurred
*/
int ccsv_is_error(void *obj, short *status);
/* -------- Reader -------- */
/*
* This function initializes the parser with the given parameters, and
* returns a pointer to the parser.
*
* params:
* options: pointer to the reader options struct
*
* returns:
* ccsv_reader*: pointer to the reader
*/
ccsv_reader *ccsv_init_reader(ccsv_reader_options *options, short *status);
/*
* This function reads a row from the file pointer, and returns a pointer
* to CSVRow struct.
*
* params:
* fp: file pointer
* parser: pointer to the parser
*
* returns:
* CSVRow*: pointer to the CSVRow struct
*/
ccsv_row *read_row(FILE *fp, ccsv_reader *parser);
/*
* This function reads a row from reader, and returns a pointer
* to CSVRow struct.
*
* params:
* reader: pointer to the reader
*
* returns:
* CSVRow*: pointer to the CSVRow struct
*/
ccsv_row *ccsv_next(ccsv_reader *reader);
/*
* This function frees the memory allocated to the CSVRow struct.
*
* params:
* row: pointer to the CSVRow struct
*/
void ccsv_free_row(ccsv_row *row);
/* -------- Writer -------- */
/*
* This function initializes the writer with the given parameters, and
* returns a pointer to the writer.
*
* params:
* options: pointer to the writer options struct
*
* returns:
* ccsv_writer*: pointer to the writer
*
*/
ccsv_writer *ccsv_init_writer(ccsv_writer_options *options, short *status);
/*
* This function writes a row (from CSVRow struct) to the file pointer.
*/
int ccsv_write(ccsv_writer *writer, ccsv_row row);
/*
* This function writes a row (from string array) to the file pointer.
*
* params:
* writer: pointer to the writer
* row_string: pointer to the row string
*
* returns:
* int: 0, if successful
* CSV_ERNOMEM, if memory allocation failed
*/
int ccsv_write_from_array(ccsv_writer *writer, char **fields, int fields_len);
/*
* This function writes a row (from CSVRow struct) to the file pointer.
*
* params:
* fp: file pointer
* writer: pointer to the writer
* row: CSVRow struct
*/
int write_row(FILE *fp, ccsv_writer *writer, ccsv_row row);
/*
*This function writes a row (from string array) to the file pointer.
*
* params:
* fp: file pointer
* writer: pointer to the writer
* row_string: pointer to the row string
*
* returns:
* int: 0, if successful
* CSV_ERNOMEM, if memory allocation failed
*/
int write_row_from_array(FILE *fp, ccsv_writer *writer, char **fields, int row_len);
// Private functions -----------------------------------------------------------------------
/*
* This function returns the object type of the object.
*
* params:
* obj: pointer to the object
*
* returns:
* int: object type
*/
int _get_object_type(void *obj);
/*
* This function reads a row from the file pointer, and returns a pointer to CSVRow struct.
*
* params:
* fp: file pointer
* reader: pointer to the reader
*
* returns:
* CSVRow*: pointer to the CSVRow struct
*/
ccsv_row *_read_row(FILE *fp, ccsv_reader *reader);
/*
* This function reads a row from the file pointer, and returns a pointer to CSVRow struct.
*
* params:
* fp: file pointer
* reader: pointer to the reader
*
* returns:
* CSVRow*: pointer to the CSVRow struct
*/
ccsv_row *_next(FILE *fp, ccsv_reader *reader);
/*
* This functions checks if the reader buffer is empty.
*/
int _is_buffer_empty(ccsv_reader *reader);
/*
*This function frees multiple pointers.
*
* params:
* num: number of pointers to free
* ...: pointers to free
*
*/
void _free_multiple(int num, ...);
/*
* This function writes a field to the file pointer.
*
* params:
* fp: file pointer
* writer: pointer to the writer
* string: pointer to the string
* string_len: length of the string
* string_pos: pointer to the position of the string
*
* returns:
* size_t: number of characters written
*/
int _write_field(FILE *fp, ccsv_writer *writer, const char *string);
/*
*This function writes a row start to the file pointer.
*
* params:
* fp: file pointer
* writer: pointer to the writer
*
* returns:
* int: WRITE_STARTED, if successful
* int: WRITE_ERALWRITING, if already writing field
*/
int _write_row_start(FILE *fp, ccsv_writer *writer);
/*
* This function writes a row end to the file pointer.
*
* params:
* fp: file pointer
* writer: pointer to the writer
*
* returns:
* int: WRITE_ENDED, if successful
* int: WRITE_ERNOTSTARTED, if writer not started
*/
int _write_row_end(FILE *fp, ccsv_writer *writer);
#ifdef __cplusplus
}
#endif

1179
lib/ccsv/src/ccsv.c Normal file

File diff suppressed because it is too large Load Diff

8
lib/ccsv/tests/Makefile Normal file
View File

@@ -0,0 +1,8 @@
CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -I../include
%: %.c
$(CC) $(CFLAGS) -o $@.out $< ../src/ccsv.c
clean:
rm -f *.out

View File

@@ -0,0 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include "ccsv.h"
int main(void)
{
return 0;
}

19
lib/microtar/LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2017 rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

99
lib/microtar/README.md Normal file
View File

@@ -0,0 +1,99 @@
# microtar
A lightweight tar library written in ANSI C
## Basic Usage
The library consists of `microtar.c` and `microtar.h`. These two files can be
dropped into an existing project and compiled along with it.
#### Reading
```c
mtar_t tar;
mtar_header_t h;
char *p;
/* Open archive for reading */
mtar_open(&tar, "test.tar", "r");
/* Print all file names and sizes */
while ( (mtar_read_header(&tar, &h)) != MTAR_ENULLRECORD ) {
printf("%s (%d bytes)\n", h.name, h.size);
mtar_next(&tar);
}
/* Load and print contents of file "test.txt" */
mtar_find(&tar, "test.txt", &h);
p = calloc(1, h.size + 1);
mtar_read_data(&tar, p, h.size);
printf("%s", p);
free(p);
/* Close archive */
mtar_close(&tar);
```
#### Writing
```c
mtar_t tar;
const char *str1 = "Hello world";
const char *str2 = "Goodbye world";
/* Open archive for writing */
mtar_open(&tar, "test.tar", "w");
/* Write strings to files `test1.txt` and `test2.txt` */
mtar_write_file_header(&tar, "test1.txt", strlen(str1));
mtar_write_data(&tar, str1, strlen(str1));
mtar_write_file_header(&tar, "test2.txt", strlen(str2));
mtar_write_data(&tar, str2, strlen(str2));
/* Finalize -- this needs to be the last thing done before closing */
mtar_finalize(&tar);
/* Close archive */
mtar_close(&tar);
```
## Error handling
All functions which return an `int` will return `MTAR_ESUCCESS` if the operation
is successful. If an error occurs an error value less-than-zero will be
returned; this value can be passed to the function `mtar_strerror()` to get its
corresponding error string.
## Wrapping a stream
If you want to read or write from something other than a file, the `mtar_t`
struct can be manually initialized with your own callback functions and a
`stream` pointer.
All callback functions are passed a pointer to the `mtar_t` struct as their
first argument. They should return `MTAR_ESUCCESS` if the operation succeeds
without an error, or an integer below zero if an error occurs.
After the `stream` field has been set, all required callbacks have been set and
all unused fields have been zeroset the `mtar_t` struct can be safely used with
the microtar functions. `mtar_open` *should not* be called if the `mtar_t`
struct was initialized manually.
#### Reading
The following callbacks should be set for reading an archive from a stream:
Name | Arguments | Description
--------|------------------------------------------|---------------------------
`read` | `mtar_t *tar, void *data, unsigned size` | Read data from the stream
`seek` | `mtar_t *tar, unsigned pos` | Set the position indicator
`close` | `mtar_t *tar` | Close the stream
#### Writing
The following callbacks should be set for writing an archive to a stream:
Name | Arguments | Description
--------|------------------------------------------------|---------------------
`write` | `mtar_t *tar, const void *data, unsigned size` | Write data to the stream
## License
This library is free software; you can redistribute it and/or modify it under
the terms of the MIT license. See [LICENSE](LICENSE) for details.

376
lib/microtar/src/microtar.c Normal file
View File

@@ -0,0 +1,376 @@
/*
* Copyright (c) 2017 rxi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "microtar.h"
typedef struct {
char name[100];
char mode[8];
char owner[8];
char group[8];
char size[12];
char mtime[12];
char checksum[8];
char type;
char linkname[100];
char _padding[255];
} mtar_raw_header_t;
static unsigned round_up(unsigned n, unsigned incr) {
return n + (incr - n % incr) % incr;
}
static unsigned checksum(const mtar_raw_header_t* rh) {
unsigned i;
unsigned char *p = (unsigned char*) rh;
unsigned res = 256;
for (i = 0; i < offsetof(mtar_raw_header_t, checksum); i++) {
res += p[i];
}
for (i = offsetof(mtar_raw_header_t, type); i < sizeof(*rh); i++) {
res += p[i];
}
return res;
}
static int tread(mtar_t *tar, void *data, unsigned size) {
int err = tar->read(tar, data, size);
tar->pos += size;
return err;
}
static int twrite(mtar_t *tar, const void *data, unsigned size) {
int err = tar->write(tar, data, size);
tar->pos += size;
return err;
}
static int write_null_bytes(mtar_t *tar, int n) {
int i, err;
char nul = '\0';
for (i = 0; i < n; i++) {
err = twrite(tar, &nul, 1);
if (err) {
return err;
}
}
return MTAR_ESUCCESS;
}
static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) {
unsigned chksum1, chksum2;
/* If the checksum starts with a null byte we assume the record is NULL */
if (*rh->checksum == '\0') {
return MTAR_ENULLRECORD;
}
/* Build and compare checksum */
chksum1 = checksum(rh);
sscanf(rh->checksum, "%o", &chksum2);
if (chksum1 != chksum2) {
return MTAR_EBADCHKSUM;
}
/* Load raw header into header */
sscanf(rh->mode, "%o", &h->mode);
sscanf(rh->owner, "%o", &h->owner);
sscanf(rh->size, "%o", &h->size);
sscanf(rh->mtime, "%o", &h->mtime);
h->type = rh->type;
strcpy(h->name, rh->name);
strcpy(h->linkname, rh->linkname);
return MTAR_ESUCCESS;
}
static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) {
unsigned chksum;
/* Load header into raw header */
memset(rh, 0, sizeof(*rh));
sprintf(rh->mode, "%o", h->mode);
sprintf(rh->owner, "%o", h->owner);
sprintf(rh->size, "%o", h->size);
sprintf(rh->mtime, "%o", h->mtime);
rh->type = h->type ? h->type : MTAR_TREG;
strcpy(rh->name, h->name);
strcpy(rh->linkname, h->linkname);
/* Calculate and write checksum */
chksum = checksum(rh);
sprintf(rh->checksum, "%06o", chksum);
rh->checksum[7] = ' ';
return MTAR_ESUCCESS;
}
const char* mtar_strerror(int err) {
switch (err) {
case MTAR_ESUCCESS : return "success";
case MTAR_EFAILURE : return "failure";
case MTAR_EOPENFAIL : return "could not open";
case MTAR_EREADFAIL : return "could not read";
case MTAR_EWRITEFAIL : return "could not write";
case MTAR_ESEEKFAIL : return "could not seek";
case MTAR_EBADCHKSUM : return "bad checksum";
case MTAR_ENULLRECORD : return "null record";
case MTAR_ENOTFOUND : return "file not found";
}
return "unknown error";
}
static int file_write(mtar_t *tar, const void *data, unsigned size) {
unsigned res = fwrite(data, 1, size, tar->stream);
return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL;
}
static int file_read(mtar_t *tar, void *data, unsigned size) {
unsigned res = fread(data, 1, size, tar->stream);
return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL;
}
static int file_seek(mtar_t *tar, unsigned offset) {
int res = fseek(tar->stream, offset, SEEK_SET);
return (res == 0) ? MTAR_ESUCCESS : MTAR_ESEEKFAIL;
}
static int file_close(mtar_t *tar) {
fclose(tar->stream);
return MTAR_ESUCCESS;
}
int mtar_open(mtar_t *tar, const char *filename, const char *mode) {
int err;
mtar_header_t h;
/* Init tar struct and functions */
memset(tar, 0, sizeof(*tar));
tar->write = file_write;
tar->read = file_read;
tar->seek = file_seek;
tar->close = file_close;
/* Assure mode is always binary */
if ( strchr(mode, 'r') ) mode = "rb";
if ( strchr(mode, 'w') ) mode = "wb";
if ( strchr(mode, 'a') ) mode = "ab";
/* Open file */
tar->stream = fopen(filename, mode);
if (!tar->stream) {
return MTAR_EOPENFAIL;
}
/* Read first header to check it is valid if mode is `r` */
if (*mode == 'r') {
err = mtar_read_header(tar, &h);
if (err != MTAR_ESUCCESS) {
mtar_close(tar);
return err;
}
}
/* Return ok */
return MTAR_ESUCCESS;
}
int mtar_close(mtar_t *tar) {
return tar->close(tar);
}
int mtar_seek(mtar_t *tar, unsigned pos) {
int err = tar->seek(tar, pos);
tar->pos = pos;
return err;
}
int mtar_rewind(mtar_t *tar) {
tar->remaining_data = 0;
tar->last_header = 0;
return mtar_seek(tar, 0);
}
int mtar_next(mtar_t *tar) {
int err, n;
mtar_header_t h;
/* Load header */
err = mtar_read_header(tar, &h);
if (err) {
return err;
}
/* Seek to next record */
n = round_up(h.size, 512) + sizeof(mtar_raw_header_t);
return mtar_seek(tar, tar->pos + n);
}
int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h) {
int err;
mtar_header_t header;
/* Start at beginning */
err = mtar_rewind(tar);
if (err) {
return err;
}
/* Iterate all files until we hit an error or find the file */
while ( (err = mtar_read_header(tar, &header)) == MTAR_ESUCCESS ) {
if ( !strcmp(header.name, name) ) {
if (h) {
*h = header;
}
return MTAR_ESUCCESS;
}
mtar_next(tar);
}
/* Return error */
if (err == MTAR_ENULLRECORD) {
err = MTAR_ENOTFOUND;
}
return err;
}
int mtar_read_header(mtar_t *tar, mtar_header_t *h) {
int err;
mtar_raw_header_t rh;
/* Save header position */
tar->last_header = tar->pos;
/* Read raw header */
err = tread(tar, &rh, sizeof(rh));
if (err) {
return err;
}
/* Seek back to start of header */
err = mtar_seek(tar, tar->last_header);
if (err) {
return err;
}
/* Load raw header into header struct and return */
return raw_to_header(h, &rh);
}
int mtar_read_data(mtar_t *tar, void *ptr, unsigned size) {
int err;
/* If we have no remaining data then this is the first read, we get the size,
* set the remaining data and seek to the beginning of the data */
if (tar->remaining_data == 0) {
mtar_header_t h;
/* Read header */
err = mtar_read_header(tar, &h);
if (err) {
return err;
}
/* Seek past header and init remaining data */
err = mtar_seek(tar, tar->pos + sizeof(mtar_raw_header_t));
if (err) {
return err;
}
tar->remaining_data = h.size;
}
/* Read data */
err = tread(tar, ptr, size);
if (err) {
return err;
}
tar->remaining_data -= size;
/* If there is no remaining data we've finished reading and seek back to the
* header */
if (tar->remaining_data == 0) {
return mtar_seek(tar, tar->last_header);
}
return MTAR_ESUCCESS;
}
int mtar_write_header(mtar_t *tar, const mtar_header_t *h) {
mtar_raw_header_t rh;
/* Build raw header and write */
header_to_raw(&rh, h);
tar->remaining_data = h->size;
return twrite(tar, &rh, sizeof(rh));
}
int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size) {
mtar_header_t h;
/* Build header */
memset(&h, 0, sizeof(h));
strcpy(h.name, name);
h.size = size;
h.type = MTAR_TREG;
h.mode = 0664;
/* Write header */
return mtar_write_header(tar, &h);
}
int mtar_write_dir_header(mtar_t *tar, const char *name) {
mtar_header_t h;
/* Build header */
memset(&h, 0, sizeof(h));
strcpy(h.name, name);
h.type = MTAR_TDIR;
h.mode = 0775;
/* Write header */
return mtar_write_header(tar, &h);
}
int mtar_write_data(mtar_t *tar, const void *data, unsigned size) {
int err;
/* Write data */
err = twrite(tar, data, size);
if (err) {
return err;
}
tar->remaining_data -= size;
/* Write padding if we've written all the data for this file */
if (tar->remaining_data == 0) {
return write_null_bytes(tar, round_up(tar->pos, 512) - tar->pos);
}
return MTAR_ESUCCESS;
}
int mtar_finalize(mtar_t *tar) {
/* Write two NULL records */
return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2);
}

View File

@@ -0,0 +1,90 @@
/**
* Copyright (c) 2017 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See `microtar.c` for details.
*/
#ifndef MICROTAR_H
#define MICROTAR_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#define MTAR_VERSION "0.1.0"
enum {
MTAR_ESUCCESS = 0,
MTAR_EFAILURE = -1,
MTAR_EOPENFAIL = -2,
MTAR_EREADFAIL = -3,
MTAR_EWRITEFAIL = -4,
MTAR_ESEEKFAIL = -5,
MTAR_EBADCHKSUM = -6,
MTAR_ENULLRECORD = -7,
MTAR_ENOTFOUND = -8
};
enum {
MTAR_TREG = '0',
MTAR_TLNK = '1',
MTAR_TSYM = '2',
MTAR_TCHR = '3',
MTAR_TBLK = '4',
MTAR_TDIR = '5',
MTAR_TFIFO = '6'
};
typedef struct {
unsigned mode;
unsigned owner;
unsigned size;
unsigned mtime;
unsigned type;
char name[100];
char linkname[100];
} mtar_header_t;
typedef struct mtar_t mtar_t;
struct mtar_t {
int (*read)(mtar_t *tar, void *data, unsigned size);
int (*write)(mtar_t *tar, const void *data, unsigned size);
int (*seek)(mtar_t *tar, unsigned pos);
int (*close)(mtar_t *tar);
void *stream;
unsigned pos;
unsigned remaining_data;
unsigned last_header;
};
const char* mtar_strerror(int err);
int mtar_open(mtar_t *tar, const char *filename, const char *mode);
int mtar_close(mtar_t *tar);
int mtar_seek(mtar_t *tar, unsigned pos);
int mtar_rewind(mtar_t *tar);
int mtar_next(mtar_t *tar);
int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h);
int mtar_read_header(mtar_t *tar, mtar_header_t *h);
int mtar_read_data(mtar_t *tar, void *ptr, unsigned size);
int mtar_write_header(mtar_t *tar, const mtar_header_t *h);
int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size);
int mtar_write_dir_header(mtar_t *tar, const char *name);
int mtar_write_data(mtar_t *tar, const void *data, unsigned size);
int mtar_finalize(mtar_t *tar);
#ifdef __cplusplus
}
#endif
#endif

37
src/kospm.c Normal file
View File

@@ -0,0 +1,37 @@
/*
* kospm.c
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "../include/kospm.h"
int kospm_install(char *root_dir, char *pkg_file){
kospm_db_t *db = kospm_db_open(root_dir);
kospm_package_list_t *package_list = kospm_package_list_open(pkg_file);
kospm_db_packages_add(db, package_list->packages);
kospm_db_files_add(db, package_list->files);
kospm_package_list_close(package_list);
kospm_db_save(db);
kospm_db_close(db);
return 0;
}

36
src/kospm_common.c Normal file
View File

@@ -0,0 +1,36 @@
#include <string.h>
#include "../include/kospm_common.h"
kospm_list_t* _kospm_csv_header_get(FILE *file){
ccsv_reader *reader = ccsv_init_reader(&_kospm_csv_reader_options);
kospm_list_t *header = (kospm_list_t*)malloc(sizeof(kospm_list_t));
ccsv_row *row;
kospm_csv_header_column *head_elem;
fseek(fp, 0, SEEK_SET);
if ((row = read_row(fp, reader)) != NULL){
for (int i = 0; i < row->fields_count; i++){
head_elem->col_number = i;
head_elem->col_name = row->fields[i];
kospm_list_add(header, head_elem);
}
}
ccsv_free_row(row);
free(reader);
return header;
}
int _kospm_csv_col_get(kospm_list_t* col_list, char* col_name){
kospm_list_t *current = col_list;
while(strcmp(current->data->col_name, col_name) || current!=NULL){
current=current->next;
}
if(current==NULL){return -1;}
return current->data->col_num;
}

149
src/kospm_db.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* kospm_db.c
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <stddef.h>
#include <string.h>
#include "../include/kospm_db.h"
#include "../include/kospm_common.h"
int _kospm_db_metadata_list_write(FILE* metadata_table, kospm_list_t *metadata_list){
kospm_list_t *metadata_col_list = _kospm_csv_header_get(db->metadata_table);
kospm_list_t *current = metadata_list;
short *write_status;
ccsv_writer *writer = ccsv_init_writer(&_kospm_csv_writer_options, write_status);
char **metadata = malloc(12*sizeof(char*));
while(*current!=NULL){
metadata[_kospm_csv_col_get(metadata_col_list, "name")] = current->data->pkg_name;
metadata[_kospm_csv_col_get(metadata_col_list, "version")] = current->data->pkg_version;
metadata[_kospm_csv_col_get(metadata_col_list, "description")] = current->data->pkg_description;
write_row_from_array(metadata_table, writer, metadata, 12);
}
free(metadata);
return 0;
}
int _kospm_db_files_list_write(FILE* files_table, kospm_list_t *file_list){
kospm_list_t *files_col_list = _kospm_csv_header_get(db->files_table);
kospm_list_t *current = file_list;
short *write_status;
ccsv_writer *writer = ccsv_init_writer(&_kospm_csv_writer_options, write_status);
char **file = malloc(4*sizeof(char*));
while(*current!=NULL){
file[_kospm_csv_col_get(files_col_list, "pkgname")] = current->data->pkg_name;
file[_kospm_csv_col_get(files_col_list, "filename")] = current->data->file_name;
write_row_from_array(metadata_table, writer, metadata, 4);
}
free(metadata);
return 0;
}
kospm_db_t* kospm_db_init(char *root_dir){
kospm_db_t *db = (kospm_db_t*)malloc(sizeof(kospm_db_t));
db->path = strcat(root_dir, DB_FOLDER);
db->metadata_table = fopen(strcat(db->path, METADATA_TABLE), "a+");
db->files_table = fopen(strcat(db->path, FILES_TABLE), "a+");
fprintf(metadata_table, "name, version, description");
fprintf(files_table, "pkgname, filename");
freopen(strcat(db->path, METADATA_TABLE), "r+", db->metadata_table);
freopen(strcat(db->path, FILES_TABLE), "r+", db->files_table);
return db;
}
kospm_db_t* kospm_db_open(char *root_dir){
kospm_db_t *db = (kospm_db_t*)malloc(sizeof(kospm_db_t));
db->path = strcat(root_dir, DB_FOLDER);
db->metadata_table = fopen(strcat(db->path, METADATA_TABLE), "r+");
db->files_table = fopen(strcat(db->path, FILES_TABLE), "r+");
db->packages = kospm_package_metadata_get(metadata_table);
db->files = kospm_package_files_get(files_table);
return db;
}
int kospm_db_save(kospm_db_t *db){
_kospm_db_metadata_list_write(db->metadata_table, db->packages);
_kospm_db_files_list_write(db->files_table, db->files);
return 0;
}
int kospm_db_close(kospm_db_t *db){
kospm_list_free(db->files);
kospm_list_free(db->packages);
fclose(db->files_table);
fclose(db->metadata_table);
free(db);
return 0;
}
int kospm_db_package_add(kospm_db_t *db, kospm_package_t *package){
kospm_list_add(db->packages, package);
return 0;
}
int kospm_db_packages_add(kospm_db_t *db, kospm_list_t *package_list){
kospm_list_t *current = package_list;
while(*current!=NULL){
kospm_list_add(db->packages, current->data);
*current = package_list->next;
}
return 0;
}
int kospm_db_file_add(kospm_db_t *db, char *pkg_name, kospm_package_file_t *file){
kospm_list_add(db->files, file);
return 0;
}
int kospm_db_files_add(kospm_db_t *db, kospm_list_t *file_list){
kospm_list_t *current = file_list;
while(*current!=NULL){
kospm_list_add(db->files, current->data);
*current = package_list->next;
}
return 0;
}

73
src/kospm_list.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* kospm_list.c
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "../include/kospm_list.h"
kospm_list_t* kospm_list_new(void *data) {
kospm_list_t *node = (kospm_list_t*)malloc(sizeof(kospm_list_t));
node->data = data;
node->next = NULL;
node->prev = NULL;
return node;
}
void kospm_list_add(kospm_list_t **list, void *data) {
kospm_list_t *new_node = kospm_list_new(data);
if (*list == NULL) {
*list = new_node;
} else {
kospm_list_t *current = *list;
while (current->next != NULL) {
current = current->next;
}
current->next = new_node;
new_node->prev = current;
}
}
void kospm_list_del_by_value(kospm_list_t **list, void *data, int (*cmp)(void *, void *)) {
kospm_list_t *current = *list;
while (current != NULL) {
if (cmp(current->data, data) == 0) {
if (current->prev != NULL) {
current->prev->next = current->next;
} else {
*list = current->next;
}
if (current->next != NULL) {
current->next->prev = current->prev;
}
free(current);
break;
}
current = current->next;
}
}
void kospm_list_free(kospm_list_t *list) {
while (list != NULL) {
kospm_list_t *temp = list;
list = list->next;
free(temp);
}
}

116
src/kospm_package.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* kospm_package.c
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <stdio.h>
#include <string.h>
#include "../lib/microtar/src/microtar.h"
#include "../include/kospm_tar.h"
#include "../lib/ccsv/include/ccsv.h"
#include "../include/kospm_package.h"
#include "../include/kospm_common.h"
kospm_list_t* kospm_package_files_get(FILE* fp){
kospm_list_t *file_list = (kospm_list_t*)malloc(sizeof(kospm_list_t));
kospm_package_file_t *file;
char *files_path = strcat(CACHE, FILES);
char *files_fields[] = {"pkgname", "filename"};
short *read_status;
ccsv_reader *reader = ccsv_init_reader(&_kospm_csv_reader_options, read_status);
kospm_list_t *files_col_list = _kospm_csv_header_get(fp);
ccsv_row *row;
while ((row = read_row(fp, reader)) != NULL) {
file = (kospm_package_file_t*)malloc(sizeof(kospm_package_file_t));
file->pkg_name = row->fields[_kospm_csv_col_number_get(files_col_list, files_fields[0])];
file->file_name = row->fields[_kospm_csv_col_number_get(files_col_list, files_fields[1])];
kospm_list_add(file_list, file);
}
kospm_list_free(files_col_list);
ccsv_free_row(row);
free(reader);
return file_list;
}
kospm_list_t* kospm_package_metadata_get(FILE* fp){
kospm_list_t *metadata_list = (kospm_list_t*)malloc(sizeof(kospm_list_t));
kospm_package_t *package;
char *pkginfo_path = strcat(CACHE, PKGINFO);
char *metadata_fields[] = {"name", "version", "description"};
short *read_status;
ccsv_reader *reader = ccsv_init_reader(&_kospm_csv_reader_options, read_status);
kospm_list_t *metadata_col_list = _kospm_csv_header_get(fp);
ccsv_row *row;
while ((row = read_row(fp, reader)) != NULL) {
package = (kospm_package_t*)malloc(sizeof(kospm_package_t));
package->pkg_name = row.fields[_kospm_csv_col_get(metadata_col_list, metadata_fields[0])];
package->pkg_version = row.fields[_kospm_csv_col_get(metadata_col_list, metadata_fields[1])];
package->pkg_description = row.fields[_kospm_csv_col_get(metadata_col_list, metadata_fields[2])];
kospm_list_add(metadata_list, package);
}
kospm_list_free(metadata_col_list);
ccsv_free_row(row);
free(reader);
return metadata_list;
}
kospm_package_list_t *kospm_package_list_open(char *pkg_file){
kospm_package_list_t *package_list = (kospm_package_list_t*)malloc(sizeof(kospm_package_list_t));
FILE* metadata_fp;
FILE* files_fp;
char *pkginfo_path = strcat(CACHE, PKGINFO);
char *files_path = strcat(CACHE, FILES);
tar_unpack(pkg_file, PKGINFO, pkginfo_path);
tar_unpack(pkg_file, FILES, files_path);
metadata_fp = fopen(pkginfo_path, "r");
files_fp = fopen(files_path, "r");
package_list->packages = kospm_package_metadata_get(metadata_fp);
package_list->files = kospm_package_files_get(files_fp);
free(reader);
fclose(metadata_fp);
fclose(files_fp);
return package_list;
}
int kospm_package_list_close(kospm_package_list_t *package_list){
kospm_list_free(package_list->packages);
kospm_list_free(package_list->files);
free(package_list);
return 0;
}

53
src/kospm_tar.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* kospm_tar.c
*
* Copyright 2024 keXa <nikitospikalov2008@gmail.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <stdlib.h>
#include "../include/kospm_tar.h"
int tar_unpack(const char *tar_name, const char *src_file,
const char *dest_file){
mtar_t tar;
mtar_header_t header;
if(mtar_open(tar, tar_name, "r") != MTAR_ESUCCESS){return 1;}
if (mtar_find(&tar, file_to_extract, &header) != MTAR_ESUCCESS) {
return 1;
}
FILE *output_file = fopen(header.name, "wb");
if (!output_file) {
mtar_close(&tar);
return 1;
}
char *buffer = malloc(header.size);
if (mtar_read_data(&tar, buffer, header.size) == MTAR_ESUCCESS) {
fwrite(buffer, 1, header.size, output_file);
}
free(buffer);
fclose(output_file);
mtar_close(&tar);
return 0;
}