summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@server-speed.net>2011-03-07 19:00:06 +0100
committerFlorian Pritz <bluewind@server-speed.net>2011-03-20 21:08:32 +0100
commit913ed7c9d756407212c56205d23cc2a06d25511a (patch)
tree72fa248b2cec43cc54487027fe55695b1927cb8d
parent483ddd7630faaa5942907659e658db3fe91c898b (diff)
use helper script instead of curl for uploading
Signed-off-by: Florian Pritz <bluewind@server-speed.net>
-rw-r--r--.gitignore2
-rw-r--r--Makefile19
-rw-r--r--fb.c.in203
-rw-r--r--fb.in21
4 files changed, 225 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 13615f8..ac30b82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
dist
fb.1
fb
+fb-upload
+fb.c
diff --git a/Makefile b/Makefile
index eeb2679..c48bbc4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,33 +1,44 @@
VERSION:=$(shell git describe --dirty | sed 's/^v//')
MANDIR=/usr/share/man
BINDIR=/usr/bin
+LIBDIR=/usr/lib
+CC=gcc
+CFLAGS=-O2 -std=c99 -Wall -Wextra -pedantic
-all: fb.1 fb
+all: fb.1 fb fb-upload
fb: fb.in
@[ -n "$(VERSION)" ] || (echo "Error: version detection failed"; exit 1)
- sed 's/@VERSION@/$(VERSION)/' fb.in > fb
+ sed 's|@VERSION@|$(VERSION)|; s|@LIBDIR@|$(LIBDIR)|' fb.in > fb
chmod 755 fb
+fb.c: fb.c.in
+ sed 's/@VERSION@/$(VERSION)/' fb.c.in > fb.c
+
+fb-upload: fb.c
+ $(CC) $(CFLAGS) -lcurl -lm -o fb-upload fb.c
+
fb.1: fb.pod
pod2man -c "" fb.pod fb.1
clean:
- rm -f fb.1 fb
+ rm -f fb.1 fb fb.c fb-upload
rm -rf dist
install: all
install -Dm755 fb $(DESTDIR)$(BINDIR)/fb
+ install -Dm755 fb-upload $(DESTDIR)$(LIBDIR)/fb-upload
install -Dm644 fb.1 $(DESTDIR)$(MANDIR)/man1/fb.1
uninstall:
rm -f $(DESTDIR)$(BINDIR)/fb
+ rm -f $(DESTDIR)$(LIBDIR)/fb-upload
rm -f $(DESTDIR)$(MANDIR)/man1/fb.1
dist: all
@[ -n "$(VERSION)" ] || (echo "Error: version detection failed"; exit 1)
mkdir -p dist/fb-$(VERSION)
- cp -a fb fb.in fb.pod fb.1 COPYING Makefile dist/fb-$(VERSION)
+ cp -a fb fb.c fb.in fb.pod fb.1 COPYING Makefile dist/fb-$(VERSION)
sed -i 's/^VERSION:=.*$$/VERSION:="'$(VERSION)'"/' dist/fb-$(VERSION)/Makefile
cd dist; tar -czf fb-$(VERSION).tar.gz fb-$(VERSION)
diff --git a/fb.c.in b/fb.c.in
new file mode 100644
index 0000000..2b5ceea
--- /dev/null
+++ b/fb.c.in
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libgen.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+/* struct which holds the persistent data for progress_callback */
+struct progressData {
+ struct timeval starttime;
+ struct timeval last;
+ double ullast;
+ int lastStringLength;
+};
+
+/* load the contents of file fn into data */
+int load_file(const char *fn, char **data, size_t *data_size)
+{
+ FILE *fp;
+ size_t buf_size = 1024*1024; /* use 1MiB chunks */
+ int size = 0;
+
+ fp = fopen(fn, "rb");
+ if (fp == NULL) {
+ perror("load_file");
+ return 1;
+ }
+
+ /* read the file in buf_size chunks and appened the data to *data */
+ while (!feof(fp)) {
+ *data = realloc(*data, *data_size + buf_size);
+ if (*data == NULL) {
+ perror("load_file");
+ return 1;
+ }
+ size = fread(*data + *data_size, sizeof(char), buf_size, fp);
+ *data_size += size;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+void format_bytes(double bytes, char *buf)
+{
+ double base = 0;
+ char suffix[][4] = {"B", "KiB", "MiB", "GiB", "TiB"};
+
+ base = log(bytes) / log(1024);
+
+ snprintf(buf, 64, "%.2f%s", pow(1024, base - floor(base)), suffix[(int)floor(base)]);
+}
+
+int progress_callback(void *cb_data,
+ double dltotal, double dlnow,
+ double ultotal, double ulnow)
+{
+ struct timeval now;
+ struct progressData *data = (struct progressData *)cb_data;
+ double timeSpent = 0;
+ int printed = 0;
+ char speed[64];
+ char total[64];
+
+ if (0 == ulnow)
+ return 0;
+
+ /* upload complete; clean up */
+ if (ulnow >= ultotal) {
+ fprintf(stderr, "\r");
+ return 0;
+ }
+
+ gettimeofday(&now, NULL);
+
+ /* only refresh once a second */
+ if (data->last.tv_sec == now.tv_sec)
+ return 0;
+
+ /* calculate time between this and the last call in seconds */
+ timeSpent =
+ (double)(now.tv_sec - data->last.tv_sec) +
+ (double)(now.tv_usec - data->last.tv_usec) / 1000000.0;
+
+ format_bytes((ulnow - data->ullast) / timeSpent, (char *)&speed);
+ format_bytes(ulnow, (char *)&total);
+
+ /* print the progress */
+ printed = fprintf(stderr,
+ "\r%s/s uploaded: %.1f%% = %s",
+ speed, /* upload speed */
+ ulnow * 100.0 / ultotal, /* percent uploaded */
+ total); /* total data uploaded */
+
+ /* pad the string if the last one was longer to remove left over characters */
+ if (data->lastStringLength > printed)
+ fprintf(stderr, "%*s", data->lastStringLength - printed, "");
+
+ /* save current values for the next run */
+ data->ullast = ulnow;
+ data->last = now;
+ data->lastStringLength = printed;
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ CURL *curl;
+ CURLcode res;
+
+ char *userAgent = "fb-client/@VERSION@";
+
+ struct progressData cb_data = {
+ .starttime = {.tv_sec = 0, .tv_usec = 0},
+ .last = {.tv_sec = 0, .tv_usec = 0},
+ .ullast = 0.0,
+ .lastStringLength = 0
+ };
+ struct stat statbuf;
+
+ struct curl_httppost *formpost=NULL;
+ struct curl_httppost *lastptr=NULL;
+ struct curl_slist *headerlist=NULL;
+ static const char buf[] = "Expect:";
+ struct curl_forms forms[4];
+
+ char *data = NULL;
+ size_t data_size = 0;
+
+ /* simple arg check */
+ if(argc != 3)
+ return 1;
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
+ fprintf(stderr, "Error initializing curl");
+ return 10;
+ }
+
+ if(stat(argv[2], &statbuf) == -1) {
+ perror("fb-upload");
+ return 1;
+ }
+
+ /* load files with 0 size (/proc files for example) into memory so we can
+ * determine their real length */
+ if (statbuf.st_size == 0) {
+ if (load_file(argv[2], &data, &data_size) != 0) {
+ return 1;
+ }
+ forms[0].option = CURLFORM_BUFFER;
+ forms[0].value = basename(argv[2]);
+ forms[1].option = CURLFORM_BUFFERPTR;
+ forms[1].value = data;
+ forms[2].option = CURLFORM_BUFFERLENGTH;
+ forms[2].value = (char *)data_size;
+ forms[3].option = CURLFORM_END;
+ } else {
+ forms[0].option = CURLFORM_FILE;
+ forms[0].value = argv[2];
+ forms[1].option = CURLFORM_END;
+ }
+
+ /* Fill in the file upload field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "file",
+ CURLFORM_ARRAY, forms,
+ CURLFORM_END);
+
+ curl = curl_easy_init();
+ /* initialize custom header list (stating that Expect: 100-continue is not
+ wanted */
+ headerlist = curl_slist_append(headerlist, buf);
+ if(curl) {
+ /* what URL that receives this POST */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &cb_data);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent);
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+ gettimeofday(&cb_data.starttime, NULL);
+ res = curl_easy_perform(curl);
+
+ /* cleanup */
+ curl_easy_cleanup(curl);
+ curl_formfree(formpost);
+ curl_slist_free_all (headerlist);
+ curl_global_cleanup();
+ free(data);
+ }
+ return 0;
+}
diff --git a/fb.in b/fb.in
index f6877ae..ce85695 100644
--- a/fb.in
+++ b/fb.in
@@ -25,6 +25,7 @@ WARNSIZE=10485760
USERAGENT="fb-client/$VERSION"
CLIPBOARD=""
EXITCODE=0
+LIBDIR="@LIBDIR@"
do_upload() {
local EXTRA=""
@@ -53,9 +54,6 @@ do_upload() {
file="$TMPDIR/$basefilename.xz"
fi
- if [ "$EXTENSION" ]; then
- EXTRA="-F extension=$EXTENSION"
- fi
TMPFILE=`mktemp "$TMPDIR/data.XXXXXX"`
if [ `stat -c %s -- "$file"` -gt "$WARNSIZE" ]; then
WARNSIZE=`curl -s "$PASTEBIN/file/get_max_size"`
@@ -65,21 +63,12 @@ do_upload() {
return 1
fi
fi
- CURLOPTS="-# -n -L -A $USERAGENT $EXTRA"
- if [ `stat -c %s -- "$file"` -eq "0" ] || echo "$file" | grep -F -q ","; then
- basefilename=`echo "$basefilename" | tr -d ,`
- if ! curl $CURLOPTS -F "file=@-;filename=$basefilename" "$PASTEBIN/file/do_upload" < "$file" > $TMPFILE; then
- EXITCODE=1
- return 1
- fi
- else
- if ! curl $CURLOPTS -F "file=@$file" "$PASTEBIN/file/do_upload" > $TMPFILE; then
- EXITCODE=1
- return 1
- fi
+ if ! $LIBDIR/fb-upload "$PASTEBIN/file/do_upload" "$file" > $TMPFILE; then
+ EXITCODE=1
+ return 1
fi
sed '$d' $TMPFILE >&2
- URL=`tail -1 $TMPFILE`
+ URL=`tail -1 $TMPFILE`"$EXTENSION"
echo $URL
CLIPBOARD="$CLIPBOARD $URL"
}