diff options
-rw-r--r-- | sfshare-daemon/src/samba_share.c | 650 | ||||
-rw-r--r-- | sfshare-daemon/src/samba_share.h | 67 | ||||
-rw-r--r-- | sfshare-daemon/src/sfshared.c | 37 |
3 files changed, 754 insertions, 0 deletions
diff --git a/sfshare-daemon/src/samba_share.c b/sfshare-daemon/src/samba_share.c new file mode 100644 index 0000000..873460a --- /dev/null +++ b/sfshare-daemon/src/samba_share.c @@ -0,0 +1,650 @@ +#include <string.h> //strlen + +#include <glib.h> +#include <glib/gstdio.h> + +#include "samba_share.h" + + +#define SECTIONS_COUNT 3 //Count of special sections in smb.conf +#define KEYWORDS_COUNT 6 //Count of keywords used for setup share in smb.conf + +// [share name], "path =", "commennt =", "read only =", "writable =, writeable =, write ok =", "guest ok =" +const gchar *keywords[KEYWORDS_COUNT] = {"[" ,"path", "comment", "read only", "writ", "guest"}; + +typedef enum keywords_id +{ + SHARE_NAME_ID = 0, + PATH_ID, + COMMENT_ID, + READ_ONLY_ID, + WRTITABLE_ID, + GUEST_OK_ID +} TKeywords_id; + +gchar *smb_conf_path = "/etc/samba/smb.conf"; +const gchar *smb_special_section[SECTIONS_COUNT] = {"global", "homes", "printers"}; + + +/* +* Function changes path to smb.conf to path +*/ +void ChangeSmbConfPath(const gchar *path) +{ + g_free(smb_conf_path); + + smb_conf_path = g_strdup(path); +} + + +/* +* Save string str as new smb.conf +*/ +gint WriteSmbConf(const gchar *content) +{ + FILE *smb_file; + + //smb.conf - File exist test + if(!g_file_test(smb_conf_path, G_FILE_TEST_EXISTS)) + { + g_error("Config file \"%s\" does not exist!", smb_conf_path); + return 1; + } + + //Try open smb.conf - rewrite all + smb_file = fopen(smb_conf_path, "w"); + if(smb_file == NULL) + { + g_error("Can not open file \"%s\"! Maybe, you dont have rights for change smb.conf", smb_conf_path); + return 1; + } + + //Write to smb.conf + if(fputs(content,smb_file) == EOF) + { + g_error("Can not write to file \"%s\"!", smb_conf_path); + return 1; + } + + fclose(smb_file); + + return 0; +} + + + +/* +* Function free TSmbConfItem from memmory +*/ +void SmbConfItem_free(TSmbConfItem *item) +{ + g_string_free(item->guest_ok, TRUE); + g_string_free(item->writable, TRUE); + g_string_free(item->read_only, TRUE); + g_string_free(item->comment, TRUE); + g_string_free(item->path, TRUE); + g_string_free(item->name, TRUE); + + g_free(item); +} + + +/* +* Function allocs memory for TSmbConfItem +*/ +TSmbConfItem* SmbConfItem_new0() +{ + TSmbConfItem *ret; + ret = g_malloc(sizeof(struct smb_conf_item)); + + ret->name = g_string_new(""); + ret->path = g_string_new(""); + ret->comment = g_string_new(""); + ret->read_only = g_string_new(""); + ret->writable = g_string_new(""); + ret->guest_ok = g_string_new(""); + + return ret; +} + +/* +* Function allocs memory for TSmbConfItem +*/ +TSmbConfItem* SmbConfItem_new(gchar *name, gchar *path, gchar *comment, gchar *read_only, gchar *writable, gchar *guest_ok) +{ + TSmbConfItem *ret; + ret = g_malloc(sizeof(struct smb_conf_item)); + + ret->name = g_string_new(name); + ret->path = g_string_new(path); + ret->comment = g_string_new(comment); + ret->read_only = g_string_new(read_only); + ret->writable = g_string_new(writable); + ret->guest_ok = g_string_new(guest_ok); + + return ret; +} + +/* +* Function returns new array +*/ +GPtrArray* SharedItemsArray_new() +{ + GPtrArray *ret = g_ptr_array_new(); + return ret; +} + + +/* +* Destroy array +*/ +void SharedItemsArray_free(GPtrArray *array) +{ + TSmbConfItem *tmp; + for(int i = 0; i < array->len; i++) + { + tmp = g_ptr_array_index(array,i); + SmbConfItem_free(tmp); + } + + g_ptr_array_free(array, TRUE); +} + + +/* +* Parse line of smb.conf and fill competent field of item structure +* return id of keyword found on line (txt) +*/ +void ParseShareItem(gchar *txt, TSmbConfItem *item) +{ + gchar *lower = g_ascii_strdown(txt, strlen(txt)); + + //Find keywords on line *txt + gint i; + for(i = 0; i < KEYWORDS_COUNT; i++) + { + gchar *point; + if((point = g_strrstr(lower,keywords[i])) != NULL) + { + //Keywords must be at begining of line + if(point == lower) + break; + } + } + + //Save atributes - Boolean variables case-insensitive - yes, no, true, false, 1, or 0 + switch(i) + { + // [share name] + case SHARE_NAME_ID: + { + g_string_append_len(item->name, txt + 1, strlen(txt)-2); + } + break; + + // path = + case PATH_ID: + { + gchar *tmp; + if((tmp = g_strrstr(txt,"=")) != NULL) + { + g_string_assign(item->path, g_strstrip(tmp + 1)); + } + } + break; + + // comment = + case COMMENT_ID: + { + gchar *tmp; + if((tmp = g_strrstr(txt,"=")) != NULL) + { + g_string_assign(item->comment, g_strstrip(tmp + 1)); + } + } + break; + + // read only = + case READ_ONLY_ID: + { + gchar *tmp; + if((tmp = g_strrstr(lower,"=")) != NULL) + { + g_strstrip(++tmp); + + if(g_strcmp0(tmp, "yes") && g_strcmp0(tmp, "true") && g_strcmp0(tmp, "1")) + g_string_assign(item->read_only,"no"); + else + g_string_assign(item->read_only,"yes"); + } + } + + // writ = writable, writeable, write ok = + case WRTITABLE_ID: + { + gchar *tmp; + if((tmp = g_strrstr(lower,"=")) != NULL) + { + g_strstrip(++tmp); + + if(g_strcmp0(tmp, "yes") && g_strcmp0(tmp, "true") && g_strcmp0(tmp, "1")) + g_string_assign(item->read_only,"no"); + else + g_string_assign(item->read_only,"yes"); + } + } + break; + + // guest ok = + case GUEST_OK_ID: + { + gchar *tmp; + if((tmp = g_strrstr(lower,"=")) != NULL) + { + g_strstrip(++tmp); + + if(g_strcmp0(tmp, "yes") && g_strcmp0(tmp, "true") && g_strcmp0(tmp, "1")) + g_string_assign(item->guest_ok,"no"); + else + g_string_assign(item->guest_ok,"yes"); + } + } + break; + + default: + break; + } + + g_free(lower); +} + + + +/* +* Funciton loads all share section to array +*/ +gint LoadSmbConf(GPtrArray *shared_items) +{ + + FILE *smb_file; //Samba config file + gchar *line; //Line buffer + gboolean skip = FALSE; //Skip lines of special sections + + gint arr_index = shared_items->len - 1; //Count of items in shared_items array - 1; + + //smb.conf - File exist test + if(!g_file_test(smb_conf_path, G_FILE_TEST_EXISTS)) + { + g_error("Config file \"%s\" not exist!", smb_conf_path); + return 1; + } + + //Try open smb.conf + smb_file = fopen(smb_conf_path, "r"); + if(smb_file == NULL) + { + g_error("Can not open file \"%s\"!", smb_conf_path); + return 1; + } + + //Inicialize buffers + line = g_strnfill(BUFSIZ, '\0'); + + //Parse smb.conf file and load shared folders setings + while(fgets(line, BUFSIZ, smb_file)) + { + //Remove white space + g_strstrip(line); + + //Skip comments and empty lines + if(line[0] == ';' || line[0] == '#' || line[0] == '\0') + continue; + + if(line[0] == '[') + { + skip = FALSE; + + //Test special sections + for(int i = 0; i < SECTIONS_COUNT; i++) + { + if(g_strrstr(line,smb_special_section[i]) != NULL) + { + skip = TRUE; + break; + } + } + + if(!skip) + { + //Start of share section - alloc new item of array + TSmbConfItem *tmp_item = SmbConfItem_new0(); + + //Add item to array + g_ptr_array_add(shared_items, (gpointer) tmp_item); + arr_index++; + + //Print error if pointers are different + if (g_ptr_array_index (shared_items, arr_index) != (gpointer) tmp_item) + g_error("LoadSmbConf(GPtrArray **shared_items): got %p instead of %p\n", + g_ptr_array_index(shared_items, arr_index), tmp_item); + } + } + + //Skip special sections (global, homes, printers) + if(skip) + continue; + + TSmbConfItem *tmp = g_ptr_array_index(shared_items, arr_index); + + //Recognize parameters and fill in item + ParseShareItem(line, tmp); + + //g_print("%s\n", line); + + } + + //Free + g_free(line); + + //SmbConfItem_free(&tmp_item); + fclose(smb_file); + + return 0; +} + + +/* +* Returns share imte if directory [path] is shared, +* if not return NULL; +*/ +TSmbConfItem *IsShared(GPtrArray *shared_items, const gchar *path) +{ + TSmbConfItem *ret = NULL; + TSmbConfItem *tmp; + for(int i = 0; i < shared_items->len; i++) + { + tmp = g_ptr_array_index(shared_items,i); + if(g_strrstr(tmp->path->str,path)) + { + ret = tmp; + break; + } + } + + return ret; +} + + +/* +* Write ne share section or change chare section defined by share parameter +*/ +gint WriteShare(GPtrArray *shared_items, TSmbConfItem *share) +{ + + TSmbConfItem *item; //Shared item + FILE *smb_file; //Samba config file + GString *smb_conf_new; //Content of smb.conf + gchar *line; //Line buffer + gchar *tmp; //Temp + + gboolean new_share = FALSE; + gboolean change = FALSE; + + + item = IsShared(shared_items, share->path->str); + + //If item is not shared we just append it to end of smb.conf + if(!item) + new_share = TRUE; + + + //smb.conf - File exist test + if(!g_file_test(smb_conf_path, G_FILE_TEST_EXISTS)) + { + g_error("Config file \"%s\" does not exist!", smb_conf_path); + return 1; + } + + //Try open smb.conf - rewrite all + smb_file = fopen(smb_conf_path, "r"); + if(smb_file == NULL) + { + g_error("Can not open file \"%s\"!", smb_conf_path); + return 1; + } + + //Inicialize buffers + smb_conf_new = g_string_new(""); + line = g_strnfill(BUFSIZ, '\0'); + tmp = g_strnfill(BUFSIZ, '\0'); + + + //Load smb.conf, change or add share section share + while(fgets(line, BUFSIZ, smb_file)) + { + gchar *orig = g_strdup(line); + + //Remove white space + g_strstrip(line); + + if(!new_share) //Find section to change + if(line[0] == '[') + { + change = FALSE; + + //Is this section to change? + if(g_strrstr(line,item->name->str)) + { + change = TRUE; + } + } + + if(!change || new_share) + { + //Just copy text from smb.conf + g_string_append(smb_conf_new,orig); + } + else + { + //Change this line + + gchar *lower = g_ascii_strdown(line, strlen(line)); //lower line + + //Find keywords on line *txt + gint i; + for(i = 0; i < KEYWORDS_COUNT; i++) + { + gchar *point; + if((point = g_strrstr(lower,keywords[i])) != NULL) + { + //Keywords must be at begining of line + if(point == lower) + break; + } + } + + //Change atributes - Boolean variables case-insensitive - yes, no, true, false, 1, or 0 + switch(i) + { + // [share name] + case SHARE_NAME_ID: + { + g_sprintf(tmp,"[%s]\n",share->name->str); + g_string_append(smb_conf_new,tmp); + } + break; + + + // path = + case PATH_ID: + { + //no change + } + break; + + + // comment = + case COMMENT_ID: + { + g_sprintf(tmp,"\tcomment = %s\n",share->comment->str); + g_string_append(smb_conf_new,tmp); + } + break; + + + // read only = + case READ_ONLY_ID: + { + g_sprintf(tmp,"\tread only = %s\n",share->read_only->str); + g_string_append(smb_conf_new,tmp); + } + + + // writ = writable, writeable, write ok = + case WRTITABLE_ID: + { + g_sprintf(tmp,"\twritable = %s\n",share->writable->str); + g_string_append(smb_conf_new,tmp); + } + break; + + + // guest ok = + case GUEST_OK_ID: + { + g_sprintf(tmp,"\tguest ok = %s\n",share->guest_ok->str); + g_string_append(smb_conf_new,tmp); + } + break; + + default: + break; + } + + g_free(lower); + } + + g_free(orig); + } + + + if(new_share) + { + g_sprintf(tmp,"\n[%s]\n",share->name->str); + g_string_append(smb_conf_new,tmp); + + g_sprintf(tmp,"\tpath = %s\n",share->path->str); + g_string_append(smb_conf_new,tmp); + + g_sprintf(tmp,"\tcomment = %s\n",share->comment->str); + g_string_append(smb_conf_new,tmp); + + g_sprintf(tmp,"\tread only = %s\n",share->read_only->str); + g_string_append(smb_conf_new,tmp); + + g_sprintf(tmp,"\twritable = %s\n",share->writable->str); + g_string_append(smb_conf_new,tmp); + + g_sprintf(tmp,"\tguest ok = %s\n",share->guest_ok->str); + g_string_append(smb_conf_new,tmp); + + } + + //Write deleted share to smb.conf + WriteSmbConf(smb_conf_new->str); + + fclose(smb_file); + + g_free(line); + g_free(tmp); + + g_string_free(smb_conf_new,TRUE); + + return 0; +} + + + +/* +* Function erase shared section containing path from smb.conf +* shared_items must by actual! +*/ +gint DeleteShare(GPtrArray *shared_items, const gchar *path) +{ + FILE *smb_file; //Samba config file + GString *smb_conf_new; //Content of smb.conf + gchar *line; //Line buffer + gchar *orig; //Original line + TSmbConfItem *skip_item; //Skip this share + gboolean skip = FALSE; //Skip lines (erase from config) + + skip_item = IsShared(shared_items, path); + + if(!skip_item) + { + g_warning("Directory \"%s\" is NOT shared",path); + return -1; + } + + + //smb.conf - File exist test + if(!g_file_test(smb_conf_path, G_FILE_TEST_EXISTS)) + { + g_error("Config file \"%s\" does not exist!", smb_conf_path); + return -1; + } + + //Try open smb.conf - rewrite all + smb_file = fopen(smb_conf_path, "r"); + if(smb_file == NULL) + { + g_error("Can not open file \"%s\"!", smb_conf_path); + return -1; + } + + //Inicialize buffers + smb_conf_new = g_string_new(""); + line = g_strnfill(BUFSIZ, '\0'); + orig = g_strnfill(BUFSIZ, '\0'); + + + //Load smb.conf WITHOUT section skip_name (section containing path) + while(fgets(line, BUFSIZ, smb_file)) + { + g_stpcpy(orig, line); + + //Remove white space + g_strstrip(line); + + if(line[0] == '[') + { + skip = FALSE; + + //Test special sections + if(g_strrstr(line,skip_item->name->str)) + { + skip = TRUE; + } + } + + if(!skip) + { + g_string_append(smb_conf_new,orig); + } + } + + //Write deleted share to smb.conf + WriteSmbConf(smb_conf_new->str); + + fclose(smb_file); + + g_free(line); + g_free(orig); + + g_string_free(smb_conf_new,TRUE); + + return 0; +} + + + diff --git a/sfshare-daemon/src/samba_share.h b/sfshare-daemon/src/samba_share.h new file mode 100644 index 0000000..2100565 --- /dev/null +++ b/sfshare-daemon/src/samba_share.h @@ -0,0 +1,67 @@ +#ifndef SAMBA_SHARE_H +#define SAMBA_SHARE_H + +#include <glib.h> + +/* +config path +load config +parse config +write share +delete share +reload service +*/ + + +// +// int WriteShare(); +// +// int DeleteShare(); +// +// void ReloadService(); +// +// +// std::string LoadConfig(); +// std::string ParseConfig(); +// +// std::string smb_conf_path; +// std::string smb_conf; + +typedef struct smb_conf_item +{ + GString *name; // [share name] + GString *path; // path = /path/to/folder + GString *comment; // comment = Some text comment + GString *read_only; // read only = yes | no + GString *writable; // writable = yes | no ... writeable, write ok + GString *guest_ok; // guest ok = yes | no +} TSmbConfItem; + + +//Funciton loads all share section to array +gint LoadSmbConf(GPtrArray *shared_items); + +//Function erase shared section containing path from smb.conf +gint DeleteShare(GPtrArray *shared_items, const gchar *path); + + +gint WriteShare(GPtrArray *shared_items, TSmbConfItem *share); + + +//Function changes path to smb.conf to path +void ChangeSmbConfPath(const gchar *path); + + +//Function returns new array +GPtrArray* SharedItemsArray_new(); + +//Function destroy Share Items Array +void SharedItemsArray_free(GPtrArray *array); + + +TSmbConfItem* SmbConfItem_new(gchar *name, gchar *path, gchar *comment, gchar *read_only, gchar *writable, gchar *guest_ok); +TSmbConfItem* SmbConfItem_new0(); + + +void SmbConfItem_free(TSmbConfItem *item); +#endif diff --git a/sfshare-daemon/src/sfshared.c b/sfshare-daemon/src/sfshared.c new file mode 100644 index 0000000..9a0cdc1 --- /dev/null +++ b/sfshare-daemon/src/sfshared.c @@ -0,0 +1,37 @@ +#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h> +#include <glib/gstdio.h> + +#include "samba_share.h" +
+int main()
+{ + GPtrArray *shared_items = SharedItemsArray_new();
+ LoadSmbConf(shared_items); + + DeleteShare(shared_items,"/test"); + + TSmbConfItem *test; + for(int i = 0; i < shared_items->len; i++) + { + test = g_ptr_array_index(shared_items, i); + g_print("%s\n", test->path->str); + + } + SharedItemsArray_free(shared_items); + + + shared_items = SharedItemsArray_new();
+ LoadSmbConf(shared_items); + + test = SmbConfItem_new("testik", "/test", "Commentar", "no", "yes", "yes"); + + WriteShare(shared_items, test); + + SmbConfItem_free(test); + + SharedItemsArray_free(shared_items); +
+ return 0;
+}
|