update: fix README information
This commit is contained in:
parent
aeb375e8d3
commit
91f513132b
23
README.md
23
README.md
@ -1,11 +1,9 @@
|
|||||||
# matt | MatterLinux package manager
|
# matt | MatterLinux package manager
|
||||||
Simple MPTP server implementation for serving MatterLinux package pools.
|
The new MatterLinux package manager (successor of mp), built on top of [`libmp`](https://git.matterlinux.xyz/Matter/libmp).
|
||||||
Built on top of [`libmp`](https://git.matterlinux.xyz/Matter/libmp).
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
If you are using MatterLinux, this package should be avaliable on the `desktop`
|
If you are using MatterLinux, since it's a core part of the system, this package should
|
||||||
repo, and you can install it with the package manager. If you are not using
|
already be installed If you are not using MatterLinux you can build it from the source and install it.
|
||||||
MatterLinux you can build it from the source and install it.
|
|
||||||
|
|
||||||
To this you will need the following tools and libraries:
|
To this you will need the following tools and libraries:
|
||||||
- gcc
|
- gcc
|
||||||
@ -29,15 +27,10 @@ To install the binary and the configuration files, you can use the `install` com
|
|||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also build the program using docker:
|
|
||||||
```bash
|
|
||||||
docker build --tag pooler .
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
To start a serving pools, specify a configuration file, default configuration file is
|
To get simple usage information, just run the program without any arguments or commands:
|
||||||
installed in the `/etc/pooler` directory:
|
|
||||||
```bash
|
```bash
|
||||||
pooler /etc/pooler/config.ini
|
matt
|
||||||
```
|
```
|
||||||
To learn more about configuration options, see this MatterLinux [wiki page](https://matterlinux.xyz/wiki/pooler).
|
To learn more about usage of this program and the configuration options,
|
||||||
|
see this MatterLinux [wiki page](https://matterlinux.xyz/wiki/matt).
|
||||||
|
60
src/args.c
60
src/args.c
@ -7,41 +7,41 @@
|
|||||||
#include "args.h"
|
#include "args.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void args_add(args_t *args, char *name){
|
void args_add(args_t *args, char *name) {
|
||||||
if(NULL == args->list)
|
if (NULL == args->list)
|
||||||
args->list = malloc(sizeof(arg_t)*(args->count+1));
|
args->list = malloc(sizeof(arg_t) * (args->count + 1));
|
||||||
else
|
else
|
||||||
args->list = realloc(args->list, sizeof(arg_t)*(args->count+1));
|
args->list = realloc(args->list, sizeof(arg_t) * (args->count + 1));
|
||||||
|
|
||||||
args->list[args->count].name = name;
|
args->list[args->count].name = name;
|
||||||
args->list[args->count++].value = NULL;
|
args->list[args->count++].value = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void args_add_value(args_t *args, char *value){
|
void args_add_value(args_t *args, char *value) {
|
||||||
if(NULL != args->list && args->list[args->count-1].value == NULL){
|
if (NULL != args->list && args->list[args->count - 1].value == NULL) {
|
||||||
args->list[args->count-1].value = value;
|
args->list[args->count - 1].value = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NULL == args->list)
|
if (NULL == args->list)
|
||||||
args->list = malloc(sizeof(arg_t)*(args->count+1));
|
args->list = malloc(sizeof(arg_t) * (args->count + 1));
|
||||||
else
|
else
|
||||||
args->list = realloc(args->list, sizeof(arg_t)*(args->count+1));
|
args->list = realloc(args->list, sizeof(arg_t) * (args->count + 1));
|
||||||
|
|
||||||
args->list[args->count].name = NULL;
|
args->list[args->count].name = NULL;
|
||||||
args->list[args->count++].value = value;
|
args->list[args->count++].value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
args_t *args_parse(int argc, char *argv[]){
|
args_t *args_parse(int argc, char *argv[]) {
|
||||||
args_t *args = malloc(sizeof(args_t));
|
args_t *args = malloc(sizeof(args_t));
|
||||||
bzero(args, sizeof(args_t));
|
bzero(args, sizeof(args_t));
|
||||||
|
|
||||||
if(argc <= 1)
|
if (argc <= 1)
|
||||||
return args;
|
return args;
|
||||||
|
|
||||||
for(int i = 1; i < argc; i++){
|
for (int i = 1; i < argc; i++) {
|
||||||
if(startswith(argv[i], "--"))
|
if (startswith(argv[i], "--"))
|
||||||
args_add(args, argv[i]+2);
|
args_add(args, argv[i] + 2);
|
||||||
else
|
else
|
||||||
args_add_value(args, argv[i]);
|
args_add_value(args, argv[i]);
|
||||||
}
|
}
|
||||||
@ -49,41 +49,41 @@ args_t *args_parse(int argc, char *argv[]){
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
void args_free(args_t *args){
|
void args_free(args_t *args) {
|
||||||
free(args->list);
|
free(args->list);
|
||||||
free(args);
|
free(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *args_get_string(args_t *args, char *name){
|
char *args_get_string(args_t *args, char *name) {
|
||||||
for(int i = 0; i < args->count; i++){
|
for (int i = 0; i < args->count; i++) {
|
||||||
if(NULL == args->list[i].name)
|
if (NULL == args->list[i].name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(eq(args->list[i].name, name))
|
if (eq(args->list[i].name, name))
|
||||||
return args->list[i].value;
|
return args->list[i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool args_get_bool(args_t *args, char *name){
|
bool args_get_bool(args_t *args, char *name) {
|
||||||
for(int i = 0; i < args->count; i++){
|
for (int i = 0; i < args->count; i++) {
|
||||||
if(NULL == args->list[i].name)
|
if (NULL == args->list[i].name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(eq(args->list[i].name, name))
|
if (eq(args->list[i].name, name))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int args_get_int(args_t *args, char *name){
|
int args_get_int(args_t *args, char *name) {
|
||||||
for(int i = 0; i < args->count; i++){
|
for (int i = 0; i < args->count; i++) {
|
||||||
if(NULL == args->list[i].name)
|
if (NULL == args->list[i].name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(eq(args->list[i].name, name))
|
if (eq(args->list[i].name, name))
|
||||||
return atoi(args->list[i].value);
|
return atoi(args->list[i].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ typedef struct args {
|
|||||||
} args_t;
|
} args_t;
|
||||||
|
|
||||||
args_t *args_parse(int argc, char *argv[]);
|
args_t *args_parse(int argc, char *argv[]);
|
||||||
char *args_get_string(args_t *args, char *name);
|
char *args_get_string(args_t *args, char *name);
|
||||||
bool args_get_bool(args_t *args, char *name);
|
bool args_get_bool(args_t *args, char *name);
|
||||||
int args_get_int(args_t *args, char *name);
|
int args_get_int(args_t *args, char *name);
|
||||||
void args_free(args_t *args);
|
void args_free(args_t *args);
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
#include <libmp/all.h>
|
#include <libmp/all.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
typedef bool (*cmd_func_t)(lm_ctx_t *ctx, config_t *config, args_t *args);
|
typedef bool (*cmd_func_t)(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||||
|
|
||||||
typedef struct cmd {
|
typedef struct cmd {
|
||||||
char *name;
|
char *name;
|
||||||
char *desc;
|
char *desc;
|
||||||
cmd_func_t func;
|
cmd_func_t func;
|
||||||
} cmd_t;
|
} cmd_t;
|
||||||
|
|
||||||
|
24
src/config.c
24
src/config.c
@ -9,10 +9,10 @@
|
|||||||
#include "intl.h"
|
#include "intl.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
bool config_set(config_t *config, char *key, char *value){
|
bool config_set(config_t *config, char *key, char *value) {
|
||||||
if(eq(key, "tmpdir"))
|
if (eq(key, "tmpdir"))
|
||||||
config->tmpdir = strdup(value);
|
config->tmpdir = strdup(value);
|
||||||
else if(eq(key, "datadir"))
|
else if (eq(key, "datadir"))
|
||||||
config->datadir = strdup(value);
|
config->datadir = strdup(value);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -23,8 +23,8 @@ pool_config_t *config_pool_add(config_t *config, char *name) {
|
|||||||
pool_config_t *pool = malloc(sizeof(pool_config_t));
|
pool_config_t *pool = malloc(sizeof(pool_config_t));
|
||||||
bzero(pool, sizeof(pool_config_t));
|
bzero(pool, sizeof(pool_config_t));
|
||||||
|
|
||||||
pool->name = strdup(name);
|
pool->name = strdup(name);
|
||||||
pool->next = config->pools;
|
pool->next = config->pools;
|
||||||
|
|
||||||
config->pools = pool;
|
config->pools = pool;
|
||||||
config->pool_count++;
|
config->pool_count++;
|
||||||
@ -44,11 +44,11 @@ bool config_pool_contains(config_t *config, char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int config_load_handler(void *data, const char *_section, const char *_key, const char *_value) {
|
int config_load_handler(void *data, const char *_section, const char *_key, const char *_value) {
|
||||||
char *section = (char *)_section, *key = (char *)_key, *value = (char *)_value;
|
char *section = (char *)_section, *key = (char *)_key, *value = (char *)_value;
|
||||||
config_t *config = data;
|
config_t *config = data;
|
||||||
|
|
||||||
if(eq(section, "")){
|
if (eq(section, "")) {
|
||||||
if(config_set(config, key, value))
|
if (config_set(config, key, value))
|
||||||
return 1;
|
return 1;
|
||||||
goto unknown;
|
goto unknown;
|
||||||
}
|
}
|
||||||
@ -84,12 +84,12 @@ bool config_load(lm_ctx_t *ctx, config_t *config, char *file) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NULL == config->tmpdir){
|
if (NULL == config->tmpdir) {
|
||||||
error(_("Please specify \"tmpdir\" in the configuration"));
|
error(_("Please specify \"tmpdir\" in the configuration"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NULL == config->datadir){
|
if (NULL == config->datadir) {
|
||||||
error(_("Please specify \"datadir\" in the configuration"));
|
error(_("Please specify \"datadir\" in the configuration"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ bool config_load(lm_ctx_t *ctx, config_t *config, char *file) {
|
|||||||
}
|
}
|
||||||
pool = pool->next;
|
pool = pool->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ typedef struct pool_config {
|
|||||||
} pool_config_t;
|
} pool_config_t;
|
||||||
|
|
||||||
typedef struct config {
|
typedef struct config {
|
||||||
pool_config_t *pools;
|
pool_config_t *pools;
|
||||||
char *datadir, *tmpdir;
|
char *datadir, *tmpdir;
|
||||||
ssize_t pool_count;
|
ssize_t pool_count;
|
||||||
} config_t;
|
} config_t;
|
||||||
|
|
||||||
bool config_load(lm_ctx_t *ctx, config_t *config, char *file);
|
bool config_load(lm_ctx_t *ctx, config_t *config, char *file);
|
||||||
|
15
src/log.c
15
src/log.c
@ -1,10 +1,9 @@
|
|||||||
#include <sys/ioctl.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <sys/ioctl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -92,10 +91,10 @@ bool bar(float cur, float max) {
|
|||||||
if (per > 100) {
|
if (per > 100) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winsize barwin = {0};
|
struct winsize barwin = {0};
|
||||||
char perc[20];
|
char perc[20];
|
||||||
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &barwin);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &barwin);
|
||||||
sprintf(perc, " %%%.f", per);
|
sprintf(perc, " %%%.f", per);
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ bool bar(float cur, float max) {
|
|||||||
int prog = size * (cur / max);
|
int prog = size * (cur / max);
|
||||||
if (prog > size)
|
if (prog > size)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
printf("\e[?25l");
|
printf("\e[?25l");
|
||||||
|
|
||||||
printf("\r" FG_BOLD "[");
|
printf("\r" FG_BOLD "[");
|
||||||
|
73
src/main.c
73
src/main.c
@ -26,48 +26,48 @@
|
|||||||
#include <libmp/ctx.h>
|
#include <libmp/ctx.h>
|
||||||
#include <libmp/error.h>
|
#include <libmp/error.h>
|
||||||
#include <libmp/util.h>
|
#include <libmp/util.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
#include "intl.h"
|
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "intl.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
cmd_t commands[] = {
|
cmd_t commands[] = {
|
||||||
{.name="list", .desc="list all the installed packages", .func=cmd_list},
|
{.name = "list", .desc = "list all the installed packages", .func = cmd_list },
|
||||||
{.name="sync", .desc="update the pool info and package lists", .func=cmd_sync},
|
{.name = "sync", .desc = "update the pool info and package lists", .func = cmd_sync },
|
||||||
{.name="install", .desc="install package(s) from remote pools", .func=cmd_install},
|
{.name = "install", .desc = "install package(s) from remote pools", .func = cmd_install},
|
||||||
{.name="remove", .desc="remove installed package(s)", .func=NULL},
|
{.name = "remove", .desc = "remove installed package(s)", .func = NULL },
|
||||||
{.name="update", .desc="update installed package(s)", .func=NULL},
|
{.name = "update", .desc = "update installed package(s)", .func = NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
char *config_file = NULL, *root_dir = NULL;
|
char *config_file = NULL, *root_dir = NULL;
|
||||||
char *full_datadir = NULL, *full_tmpdir = NULL;
|
char *full_datadir = NULL, *full_tmpdir = NULL;
|
||||||
args_t *args = NULL;
|
args_t *args = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
config_t config;
|
config_t config;
|
||||||
lm_ctx_t ctx;
|
lm_ctx_t ctx;
|
||||||
|
|
||||||
lm_ctx_init(&ctx);
|
lm_ctx_init(&ctx);
|
||||||
args = args_parse(argc, argv);
|
args = args_parse(argc, argv);
|
||||||
|
|
||||||
if((config_file = args_get_string(args, "config")) == NULL)
|
if ((config_file = args_get_string(args, "config")) == NULL)
|
||||||
config_file = "/etc/matt/config.ini";
|
config_file = "/etc/matt/config.ini";
|
||||||
|
|
||||||
if(!config_load(&ctx, &config, config_file))
|
if (!config_load(&ctx, &config, config_file))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if(args->count <= 0 || args->list[0].name != NULL)
|
if (args->count <= 0 || args->list[0].name != NULL)
|
||||||
goto help;
|
goto help;
|
||||||
|
|
||||||
if((root_dir = args_get_string(args, "root")) == NULL)
|
if ((root_dir = args_get_string(args, "root")) == NULL)
|
||||||
root_dir = "/";
|
root_dir = "/";
|
||||||
|
|
||||||
if(!lm_ctx_set_root(&ctx, root_dir)){
|
if (!lm_ctx_set_root(&ctx, root_dir)) {
|
||||||
if(LM_ERR_CtxRootNoWrite == lm_error())
|
if (LM_ERR_CtxRootNoWrite == lm_error())
|
||||||
error(_("Failed to access the root directory, are you running as root?"));
|
error(_("Failed to access the root directory, are you running as root?"));
|
||||||
else
|
else
|
||||||
error(_("Bad root directory (%s): %s"), root_dir, lm_strerror());
|
error(_("Bad root directory (%s): %s"), root_dir, lm_strerror());
|
||||||
@ -75,50 +75,51 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
full_datadir = join_alloc(root_dir, config.datadir);
|
full_datadir = join_alloc(root_dir, config.datadir);
|
||||||
full_tmpdir = join_alloc(root_dir, config.tmpdir);
|
full_tmpdir = join_alloc(root_dir, config.tmpdir);
|
||||||
|
|
||||||
if(!lm_ctx_set_data(&ctx, full_datadir)){
|
if (!lm_ctx_set_data(&ctx, full_datadir)) {
|
||||||
error(_("Bad datadir (%s): %s"), full_datadir, lm_strerror());
|
error(_("Bad datadir (%s): %s"), full_datadir, lm_strerror());
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lm_ctx_set_temp(&ctx, full_tmpdir)){
|
if (!lm_ctx_set_temp(&ctx, full_tmpdir)) {
|
||||||
error(_("Bad tmpdir (%s): %s"), full_tmpdir, lm_strerror());
|
error(_("Bad tmpdir (%s): %s"), full_tmpdir, lm_strerror());
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool_config_t *pool = config.pools;
|
pool_config_t *pool = config.pools;
|
||||||
while (NULL != pool) {
|
while (NULL != pool) {
|
||||||
if(!lm_ctx_pool_add(&ctx, pool->name, pool->url)){
|
if (!lm_ctx_pool_add(&ctx, pool->name, pool->url)) {
|
||||||
error(_("Failed to add pool "FG_BOLD"%s"FG_RESET" to the list: %s"), pool->name, lm_strerror());
|
error(_("Failed to add pool " FG_BOLD "%s" FG_RESET " to the list: %s"), pool->name, lm_strerror());
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
pool = pool->next;
|
pool = pool->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < sizeof(commands)/sizeof(cmd_t); i++){
|
for (int i = 0; i < sizeof(commands) / sizeof(cmd_t); i++) {
|
||||||
if(eq(commands[i].name, args->list[0].value)){
|
if (eq(commands[i].name, args->list[0].value)) {
|
||||||
ret = commands[i].func(&ctx, &config, args);
|
ret = commands[i].func(&ctx, &config, args);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error(_("Command not found: "FG_BOLD"%s"), args->list[0].value);
|
error(_("Command not found: " FG_BOLD "%s"), args->list[0].value);
|
||||||
help:
|
help:
|
||||||
info(_("MatterLinux package manager (version %s)"), VERSION);
|
info(_("MatterLinux package manager (version %s)"), VERSION);
|
||||||
info(_("Usage: "FG_BOLD"%s [command] <options> <arguments>"), argv[0]);
|
info(_("Usage: " FG_BOLD "%s [command] <options> <arguments>"), argv[0]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
info(_("Here is a list of available commands:"));
|
info(_("Here is a list of available commands:"));
|
||||||
|
|
||||||
for(int i = 0; i < sizeof(commands)/sizeof(cmd_t); i++)
|
for (int i = 0; i < sizeof(commands) / sizeof(cmd_t); i++)
|
||||||
printf(" "FG_BOLD"%s"FG_RESET":\t %s\n", commands[i].name, commands[i].desc);
|
printf(" " FG_BOLD "%s" FG_RESET ":\t %s\n", commands[i].name, commands[i].desc);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
info(_("To list different options, use commands with "FG_BOLD"--help"FG_RESET" option"));
|
info(_("To list different options, use commands with " FG_BOLD "--help" FG_RESET " option"));
|
||||||
info(_("Here is a list of available global options:"));
|
info(_("Here is a list of available global options:"));
|
||||||
|
|
||||||
printf(_(" "FG_BOLD"--config"FG_RESET":\t specify the configuration file (default is /etc/matt/config.ini)\n"));
|
printf(
|
||||||
printf(_(" "FG_BOLD"--root"FG_RESET":\t specify a custom root directory (default is /)\n\n"));
|
_(" " FG_BOLD "--config" FG_RESET ":\t specify the configuration file (default is /etc/matt/config.ini)\n"));
|
||||||
|
printf(_(" " FG_BOLD "--root" FG_RESET ":\t specify a custom root directory (default is /)\n\n"));
|
||||||
|
|
||||||
info(_("Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"));
|
info(_("Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"));
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
bool startswith(char *str, char *sub){
|
bool startswith(char *str, char *sub) {
|
||||||
size_t strl = strlen(str);
|
size_t strl = strlen(str);
|
||||||
size_t subl = strlen(sub);
|
size_t subl = strlen(sub);
|
||||||
|
|
||||||
if(subl > strl)
|
if (subl > strl)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return strncmp(sub, str, subl) == 0;
|
return strncmp(sub, str, subl) == 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user