Лиха беда начало
This commit is contained in:
28
Makefile
Normal file
28
Makefile
Normal 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
30
include/kospm.h
Normal 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
54
include/kospm_common.h
Normal 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
73
include/kospm_db.h
Normal 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
42
include/kospm_list.h
Normal 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
56
include/kospm_package.h
Normal 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
31
include/kospm_tar.h
Normal 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
3
kos_build.sh
Normal 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
50
kospm.geany
Normal 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
58
lib/ccsv/.gitignore
vendored
Normal 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
21
lib/ccsv/LICENSE
Normal 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
117
lib/ccsv/README.md
Normal 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
BIN
lib/ccsv/docs/ccsv.pdf
Normal file
Binary file not shown.
46
lib/ccsv/examples/count_rf.c
Normal file
46
lib/ccsv/examples/count_rf.c
Normal 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
68
lib/ccsv/examples/cpy.c
Normal 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;
|
||||
}
|
52
lib/ccsv/examples/cpy_new.c
Normal file
52
lib/ccsv/examples/cpy_new.c
Normal 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;
|
||||
}
|
57
lib/ccsv/examples/handling_memory_allocation_failure.c
Normal file
57
lib/ccsv/examples/handling_memory_allocation_failure.c
Normal 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;
|
||||
}
|
8
lib/ccsv/examples/makefile
Normal file
8
lib/ccsv/examples/makefile
Normal 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
|
50
lib/ccsv/examples/print_each_row.c
Normal file
50
lib/ccsv/examples/print_each_row.c
Normal 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;
|
||||
}
|
41
lib/ccsv/examples/print_each_row_ccsv_v0.5.c
Normal file
41
lib/ccsv/examples/print_each_row_ccsv_v0.5.c
Normal 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;
|
||||
}
|
35
lib/ccsv/examples/print_headers.c
Normal file
35
lib/ccsv/examples/print_headers.c
Normal 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;
|
||||
}
|
56
lib/ccsv/examples/with_reader_options.c
Normal file
56
lib/ccsv/examples/with_reader_options.c
Normal 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;
|
||||
}
|
50
lib/ccsv/examples/writer_macros.c
Normal file
50
lib/ccsv/examples/writer_macros.c
Normal 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;
|
||||
}
|
64
lib/ccsv/examples/writing_from_CSVRow_struct.c
Normal file
64
lib/ccsv/examples/writing_from_CSVRow_struct.c
Normal 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;
|
||||
}
|
47
lib/ccsv/examples/writing_from_array.c
Normal file
47
lib/ccsv/examples/writing_from_array.c
Normal 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
442
lib/ccsv/include/ccsv.h
Normal 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
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
8
lib/ccsv/tests/Makefile
Normal 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
|
9
lib/ccsv/tests/test_ccsv.c
Normal file
9
lib/ccsv/tests/test_ccsv.c
Normal 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
19
lib/microtar/LICENSE
Normal 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
99
lib/microtar/README.md
Normal 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
376
lib/microtar/src/microtar.c
Normal 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);
|
||||
}
|
90
lib/microtar/src/microtar.h
Normal file
90
lib/microtar/src/microtar.h
Normal 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
37
src/kospm.c
Normal 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
36
src/kospm_common.c
Normal 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
149
src/kospm_db.c
Normal 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
73
src/kospm_list.c
Normal 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
116
src/kospm_package.c
Normal 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
53
src/kospm_tar.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user