summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvictor <victor@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-01-12 23:43:12 +0800
committervictor <victor@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2005-01-12 23:43:12 +0800
commitebfb5cf86e54df87bdbd952cfed7714325d530a3 (patch)
treed54ef1ad8ebb83cdeac1186d738b50fb71bb05fb
parent81714aa12e87b72e4dcddde246afb8011f7b06f0 (diff)
downloadpttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar.gz
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar.bz2
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar.lz
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar.xz
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.tar.zst
pttbbs-ebfb5cf86e54df87bdbd952cfed7714325d530a3.zip
implement basic cp(1), fix "/bin/cp: Argument list too long."
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@2393 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--include/proto.h1
-rw-r--r--mbbsd/announce.c4
-rw-r--r--mbbsd/stuff.c101
3 files changed, 103 insertions, 3 deletions
diff --git a/include/proto.h b/include/proto.h
index 005dcb17..61897662 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -543,6 +543,7 @@ void setdirpath(char *buf, char *direct, char *fname);
int str_checksum(char *str);
void show_help(char * const helptext[]);
void show_helpfile(const char * helpfile);
+int copy_file(char *src, char *dst);
int belong(char *filelist, char *key);
char *Cdatedate(time_t *clock);
void sethomeman(char *buf, const char *userid);
diff --git a/mbbsd/announce.c b/mbbsd/announce.c
index c580dc6e..2ac04137 100644
--- a/mbbsd/announce.c
+++ b/mbbsd/announce.c
@@ -354,9 +354,7 @@ a_pasteitem(menu_t * pm, int mode)
} else if (dashd(copyfile)) {
stampdir(newpath, &item);
memcpy(copytitle, "¡»", 2);
- snprintf(buf, sizeof(buf),
- "/bin/cp -r %s/* %s/.D* %s", copyfile, copyfile,
- newpath);
+ copy_file(copyfile, newpath);
system(buf);
} else {
outs("µLªk«þ¨©¡I");
diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c
index e46db52c..d3c6c9b0 100644
--- a/mbbsd/stuff.c
+++ b/mbbsd/stuff.c
@@ -346,6 +346,101 @@ dashd(char *fname)
return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode));
}
+#define BUFFER_SIZE 8192
+static int copy_file_to_file(char *src, char *dst)
+{
+ char buf[BUFFER_SIZE];
+ int fdr, fdw, len;
+
+ if ((fdr = open(src, O_RDONLY)) < 0)
+ return -1;
+
+ if ((fdw = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
+ close(fdr);
+ return -1;
+ }
+
+ while (1) {
+ len = read(fdr, buf, sizeof(buf));
+ if (len <= 0)
+ break;
+ write(fdw, buf, len);
+ if (len < BUFFER_SIZE)
+ break;
+ }
+
+ close(fdr);
+ close(fdw);
+ return 0;
+}
+#undef BUFFER_SIZE
+
+static int copy_file_to_dir(char *src, char *dst)
+{
+ char buf[256];
+ char *slash;
+ if ((slash = rindex(src, '/')) == NULL)
+ sprintf(buf, "%s/%s", dst, src);
+ else
+ sprintf(buf, "%s/%s", dst, slash);
+ return copy_file_to_file(src, buf);
+}
+
+static int copy_dir_to_dir(char *src, char *dst)
+{
+ DIR *dir;
+ struct dirent *entry;
+ struct stat st;
+ char buf[256], buf2[256];
+
+ if (stat(dst, &st) < 0)
+ if (mkdir(dst, 0700) < 0)
+ return -1;
+
+ if ((dir = opendir(src)) == NULL)
+ return -1;
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
+ continue;
+ sprintf(buf, "%s/%s", src, entry->d_name);
+ sprintf(buf2, "%s/%s", dst, entry->d_name);
+ if (stat(buf, &st) < 0)
+ continue;
+ if (S_ISDIR(st.st_mode))
+ mkdir(buf2, 0700);
+ copy_file(buf, buf2);
+ }
+
+ closedir(dir);
+ return 0;
+}
+
+/**
+ * copy src to dst (recursively)
+ * @param src and dst are file or dir
+ * @return -1 if failed
+ */
+int copy_file(char *src, char *dst)
+{
+ struct stat st;
+
+ if (stat(dst, &st) == 0 && S_ISDIR(st.st_mode)) {
+ if (stat(src, &st) < 0)
+ return -1;
+
+ if (S_ISDIR(st.st_mode))
+ return copy_dir_to_dir(src, dst);
+ else if (S_ISREG(st.st_mode))
+ return copy_file_to_dir(src, dst);
+ return -1;
+ }
+ else if (stat(src, &st) == 0 && S_ISDIR(st.st_mode))
+ return copy_dir_to_dir(src, dst);
+ return copy_file_to_file(src, dst);
+}
+
int
belong(char *filelist, char *key)
{
@@ -882,6 +977,9 @@ int toconnect(char *host, int port)
return sock;
}
+/**
+ * same as read(2), but read until exactly size len
+ */
int toread(int fd, void *buf, int len)
{
int l;
@@ -895,6 +993,9 @@ int toread(int fd, void *buf, int len)
return l;
}
+/**
+ * same as write(2), but write until exactly size len
+ */
int towrite(int fd, void *buf, int len)
{
int l;