commit aae369b9c8eaa3ce7c1a262258d54bc0d7a18ec7 Author: kento2 Date: Wed Sep 9 18:41:42 2026 +0200 . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84c048a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/extension.c b/extension.c new file mode 100644 index 0000000..212d857 --- /dev/null +++ b/extension.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#include "pipeshare.h" + +#define MAX(a,b) (a>b?a:b) + +#define failmagic(...) do { \ + carp(__VA_ARGS__,": ",magic_error(magic)); \ + return 0; \ + } while(0) + +int extension(int64 fd,char result[16]) +{ + magic_t magic=magic_open(MAGIC_EXTENSION); + if(!magic) failmagic("initialize libmagic"); + if(magic_load(magic,NULL)<0) failmagic("load magic database"); + const char *extensions=magic_descriptor(magic,fd); + if(!extensions) failmagic("get magic data"); + + size_t l=MAX(str_chr(extensions,'/'),16); + byte_copy(result,l,extensions); + result[l]=0; + magic_close(magic); + if(str_equal(result,"???")) + str_copy(result,"txt"); + return 1; +} + +#undef failmagic diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..7e4bbad --- /dev/null +++ b/meson.build @@ -0,0 +1,29 @@ +project( + 'pipeshare', 'c', + default_options: [ + 'c_std=c99', + 'warning_level=2', + ], +) + +cc = meson.get_compiler('c') +deps = [ + cc.find_library('libowfat'), + dependency('libmagic'), +] + +executable('pipeshare', files( + './pipeshare.c', + './send_stdin.c', + './extension.c', +), dependencies:deps, install:true) + +executable('pipeshare-clean', files( + './pipeshare-clean.c', +), dependencies:deps, install:true) + + +install_man([ + './pipeshare.1', + './pipeshare-clean.1', +]) diff --git a/pipeshare-clean.1 b/pipeshare-clean.1 new file mode 100644 index 0000000..e3493bd --- /dev/null +++ b/pipeshare-clean.1 @@ -0,0 +1,23 @@ +.TH pipeshare 1 +.SH NAME +pipeshare-clean \- remove old files +.SH SYNOPSIS +pipeshare-clean [-C dir] +.SH OPTIONS +\-C dir + chdir into dir at startup +.SH DESCRIPTION +if \-C is given, pipeshare-clean cd's into the specified +directory. +It then walks through all files that do not have a file +extension(i.e. do not contain a dot in their name) and for +each whose last chagne is older than 14 days, prompts the +user whether to delete it or not. If it is marked for +deletion, the file along with any other file starting with +the same prefix(id) are deleted. +.PP +The confirmation prompt is used to avoid accidental deletion +of files when pipeshare-clean is used from the wrong working +directory. +.SH "SEE ALSO" +pipeshare(1) diff --git a/pipeshare-clean.c b/pipeshare-clean.c new file mode 100644 index 0000000..e22ce2b --- /dev/null +++ b/pipeshare-clean.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define dieusage() die(100,argv0," [-C dir]") +#define dienoarg(OPT) \ + do { \ + carp("missing argument for -"OPT); \ + dieusage(); \ + } while(0) + +static time_t now,expiration; + +static int prompt_confirm(char *file) +{ + char c; + buffer_puts(buffer_1,"remove "); + buffer_puts(buffer_1,file); + buffer_putsflush(buffer_1,"? [y/N]"); + if (read(0,&c,1)<=0) return 0; + return c=='y' || c=='Y'; +} + +static void delete_shared(char *id) +{ + DIR *dir; + struct dirent *ent; + dir=opendir("."); + if (!dir) diesys(111,"opendir"); + while ((ent=readdir(dir))) + if (str_start(ent->d_name,id)) + unlink(ent->d_name); + closedir(dir); +} + +static void run(void) +{ + DIR *dir; + struct dirent *ent; + struct stat st; + dir=opendir("."); + if (!dir) diesys(111,"opendir"); + while ((ent=readdir(dir))) { + if (str_chr(ent->d_name,'.')!=str_len(ent->d_name)) + continue; + if (stat(ent->d_name,&st)<0) + diesys(111,"stat ",ent->d_name); + /* ignore alias */ + if (now-st.st_mtime > expiration) { + if (!prompt_confirm(ent->d_name)) + continue; + buffer_putsflush(buffer_1,"\n"); + delete_shared(ent->d_name); + } + } +} + +int main(int argc, char **argv) +{ + int i; + char *dir="."; + errmsg_iam(*argv); + for (i=1;i +#include +#include +#include +#include +#include + +#include "pipeshare.h" + +#define dieusage() die(100,argv0," [-C dir]") +#define dienoarg(OPT) \ + do { \ + carp("missing argument for -"OPT); \ + dieusage(); \ + } while(0) + +static char *wwwbase=NULL; + +static int mkaliasfile(char *id,char ext[16]) +{ + char *alias; + size_t l; + alias=alloca(str_len(id)+17); + l=str_copy(alias,id); + alias[l++]='.'; + l+=str_copy(alias+l,ext); + alias[l]=0; + if(symlink(id,alias)<0) { + carpsys("symlink ",id," -> ",alias); + return 0; + } + + return 1; +} + +int main(int argc, char **argv) +{ + int i; + char *dir="."; + char tmp[]="./XXXXXX"; + int tmpfd; + char ext[16]; + errmsg_iam(*argv); + for (i=1;i + +int send_stdin(int64 fd); + +int extension(int64 fd,char result[16]); + +#endif diff --git a/send_stdin.c b/send_stdin.c new file mode 100644 index 0000000..101c937 --- /dev/null +++ b/send_stdin.c @@ -0,0 +1,31 @@ +#include + +#include "pipeshare.h" + +int send_stdin(int64 fd) +{ + char buf[8192]; + int r; + uint64 readpos=0,writepos=0; + int eof=0; + for(;;){ + if(eof && writepos>=readpos)break; + if(!eof && readpos < sizeof buf) { + r=io_tryread(0,buf+readpos,(sizeof buf)-readpos); + if(r<=-2){carpsys("read stdin");return 0;} + if(r==0)eof=1; + if(r>0)readpos+=r; + } + if(writepos0){ + writepos+=r; + if(writepos==readpos) + readpos=writepos=0; + } + } + } + return 1; +} +