From e92852400cd4c197d6e7b8b53d4a07e133a24ddc Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Tue, 1 Jul 2008 13:46:37 -0300 Subject: [PATCH] obexd: Folder listing support. --- obexd/src/ftp.c | 143 ++++++++++++++++++++++++++++++++++++++++++++--- obexd/src/obex.c | 44 +++++++++++---- 2 files changed, 167 insertions(+), 20 deletions(-) diff --git a/obexd/src/ftp.c b/obexd/src/ftp.c index 04ab6237d..25aae3f03 100644 --- a/obexd/src/ftp.c +++ b/obexd/src/ftp.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -52,11 +53,133 @@ #define CAP_FILE CONFIGDIR "/capability.xml" +#define EOL_CHARS "\n" + +#define FL_VERSION "" EOL_CHARS + +#define FL_TYPE "" EOL_CHARS + +#define FL_BODY_BEGIN "" EOL_CHARS + +#define FL_BODY_END "" EOL_CHARS + +#define FL_PARENT_FOLDER_ELEMENT "" EOL_CHARS + +#define FL_FILE_ELEMENT "" EOL_CHARS + +#define FL_FOLDER_ELEMENT "" EOL_CHARS + + +static gchar *file_stat_line(gchar *filename, struct stat fstat, + struct stat dstat) +{ + gchar *perm, atime[17], ctime[17], mtime[17], *result; + + perm = g_strdup_printf("user-perm=\"%s%s%s\" group-perm=\"%s%s%s\" " + "other-perm=\"%s%s%s\"", + (fstat.st_mode & S_IRUSR ? "R" : ""), + (fstat.st_mode & S_IWUSR ? "W" : ""), + (dstat.st_mode & S_IWUSR ? "D" : ""), + (fstat.st_mode & S_IRGRP ? "R" : ""), + (fstat.st_mode & S_IWGRP ? "W" : ""), + (dstat.st_mode & S_IWGRP ? "D" : ""), + (fstat.st_mode & S_IROTH ? "R" : ""), + (fstat.st_mode & S_IWOTH ? "W" : ""), + (dstat.st_mode & S_IWOTH ? "D" : "")); + + strftime(atime, 16, "%Y%m%dT%H%M%S", gmtime(&fstat.st_atime)); + strftime(ctime, 16, "%Y%m%dT%H%M%S", gmtime(&fstat.st_ctime)); + strftime(mtime, 16, "%Y%m%dT%H%M%S", gmtime(&fstat.st_mtime)); + + if (S_ISDIR(fstat.st_mode)) + result = g_strdup_printf(FL_FOLDER_ELEMENT, filename, + perm, atime, mtime, ctime); + else + result = g_strdup_printf(FL_FILE_ELEMENT, filename, fstat.st_size, + perm, atime, mtime, ctime); + + g_free(perm); + + return result; +} + +static gboolean folder_listing(struct obex_session *os, guint32 *size) +{ + struct stat fstat, dstat; + struct dirent *ep; + DIR *dp; + GString *listing; + + listing = g_string_new(FL_VERSION); + listing = g_string_append(listing, FL_TYPE); + listing = g_string_append(listing, FL_BODY_BEGIN); + + if (strcmp(os->current_folder,os->server->folder)) + listing = g_string_append(listing, FL_PARENT_FOLDER_ELEMENT); + + if (stat(os->current_folder, &dstat) < 0) { + error("get_folder_listing: %s(%d)", strerror(errno), errno); + return FALSE; + } + + dp = opendir(os->current_folder); + while (dp && (ep = readdir(dp))) { + gchar *name; + gchar *fullname; + gchar *line; + + if (ep->d_name[0] == '.') + continue; + + name = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL); + if (name == NULL) { + error("g_filename_to_utf8: invalid filename"); + continue; + } + + fullname = g_build_filename(os->current_folder, ep->d_name, NULL); + + if (lstat(fullname, &fstat) < 0) { + debug("lstat: %s(%d)", strerror(errno), errno); + g_free(name); + g_free(fullname); + continue; + } + g_free(fullname); + + line = file_stat_line(name, fstat, dstat); + if (line == NULL) { + g_free(name); + continue; + } + g_free(name); + + listing = g_string_append(listing, line); + g_free(line); + } + closedir(dp); + + listing = g_string_append(listing, FL_BODY_END); + *size = listing->len + 1; + os->buf = (guint8*) g_string_free(listing, FALSE); + + return TRUE; +} + static gboolean get_by_type(struct obex_session *os, gchar *type, guint32 *size) { + if (type == NULL) + return FALSE; + if (g_str_equal(type, CAP_TYPE)) return os_prepare_get(os, CAP_FILE, size); + if (g_str_equal(type, LST_TYPE)) + return folder_listing(os, size); + return FALSE; } @@ -65,6 +188,8 @@ void ftp_get(obex_t *obex, obex_object_t *obj) obex_headerdata_t hv; struct obex_session *os; guint32 size; + gboolean ret; + gchar *path; os = OBEX_GetUserData(obex); if (os == NULL) @@ -73,23 +198,23 @@ void ftp_get(obex_t *obex, obex_object_t *obj) if (os->current_folder == NULL) goto fail; - if (os->name) { - gboolean ret; - gchar *path = g_build_filename(os->current_folder, - os->name, NULL); + if (!get_by_type(os, os->type, &size)) { + if (!os->name) + goto fail; + + path = g_build_filename(os->current_folder, + os->name, NULL); + ret = os_prepare_get(os, path, &size); g_free(path); if (!ret) goto fail; - } else if (os->type) { - if (!get_by_type(os, os->type, &size)) - goto fail; - } else - goto fail; + } hv.bq4 = size; + os->size = size; OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_LENGTH, hv, 4, 0); /* Add body header */ diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 4089b9f0b..897aba90e 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -79,6 +79,28 @@ struct obex_commands ftp = { .setpath = ftp_setpath, }; +static void os_reset_session(struct obex_session *os) +{ + if (os->name) { + g_free(os->name); + os->name = NULL; + } + if (os->type) { + g_free(os->type); + os->type = NULL; + } + if (os->buf) { + g_free(os->buf); + os->buf = NULL; + } + if (os->fd > 0) { + close(os->fd); + os->fd = -1; + } + os->offset = 0; + os->size = 0; +} + static void obex_session_free(struct obex_session *os) { if (os->name) @@ -348,8 +370,13 @@ static gint obex_write(struct obex_session *os, debug("obex_write name: %s type: %s tx_mtu: %d fd: %d", os->name, os->type, os->tx_mtu, os->fd); - if (os->fd < 0) - return -EIO; + if (os->fd < 0) { + if (os->buf == NULL) + return -EIO; + + len = os->size - os->offset; + goto add_header; + } len = read(os->fd, os->buf, os->tx_mtu); if (len < 0) { @@ -359,8 +386,7 @@ static gint obex_write(struct obex_session *os, return -err; } - os->offset += len; - +add_header: if (len == 0) { OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hd, 0, OBEX_FL_STREAM_DATAEND); @@ -370,6 +396,8 @@ static gint obex_write(struct obex_session *os, } hd.bs = os->buf; + os->offset += len; + OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hd, len, OBEX_FL_STREAM_DATA); @@ -581,13 +609,7 @@ static void obex_event(obex_t *obex, obex_object_t *obj, gint mode, case OBEX_CMD_GET: emit_transfer_completed(os->cid, os->offset == os->size); - if (os->fd >= 0) { - close(os->fd); - os->fd = -1; - } - g_free(os->buf); - os->buf = NULL; - os->offset = 0; + os_reset_session(os); break; default: break; -- 2.47.3