Commit Diff


commit - 0592b956b4fc5a82ee81a89fcaf0d2e0d9811b1a
commit + c7f145d4ed3211b02d766e9f126e27a3dda1b871
blob - e88277ab8971ae6a3ad23c02cd997b622fa49ba3
blob + 54d846210b8e363b82905263928747b7dc1ee431
--- 9pclib.c
+++ 9pclib.c
@@ -71,6 +71,13 @@ write_str_auto(const char *str)
 }
 
 void
+write_buf(const void *d, uint32_t len)
+{
+	write_32(len);
+	evbuffer_add(evb, d, len);
+}
+
+void
 write_64(uint64_t x)
 {
 	x = htole64(x);
@@ -187,6 +194,22 @@ topen(uint32_t fid, uint8_t mode)
 }
 
 void
+tcreate(uint32_t fid, const char *name, uint32_t perm, uint8_t mode)
+{
+	uint32_t	len;
+	uint16_t	nl;
+
+	/* fid[4] name[s] perm[4] mode[1] */
+	nl = strlen(name);
+	len = sizeof(fid) + sizeof(nl) + nl + sizeof(perm) + sizeof(mode);
+	write_hdr_auto(len, Tcreate);
+	write_fid(fid);
+	write_str(nl, name);
+	write_32(perm);
+	write_8(mode);
+}
+
+void
 tread(uint32_t fid, uint64_t off, uint32_t count)
 {
 	uint32_t	len;
@@ -198,3 +221,24 @@ tread(uint32_t fid, uint64_t off, uint32_t count)
 	write_off(off);
 	write_32(count);
 }
+
+void
+twrite(uint32_t fid, uint64_t off, const void *data, uint32_t count)
+{
+	uint32_t	len;
+
+	/* fid[4] off[8] count[4] data[count] */
+	len = sizeof(fid) + sizeof(off) + sizeof(count) + count;
+	write_hdr_auto(len, Twrite);
+	write_fid(fid);
+	write_off(off);
+	write_buf(data, count);
+}
+
+void
+tremove(uint32_t fid)
+{
+	/* fid[4] */
+	write_hdr_auto(sizeof(fid), Tremove);
+	write_fid(fid);
+}
blob - 96accaa0e329fa150af852aeff826ab2951443c6
blob + 8d393d4f53f13f30a3aaa9af215ca2d5de0f15e7
--- 9pclib.h
+++ 9pclib.h
@@ -30,6 +30,7 @@ void		 write_hdr(uint32_t, uint8_t, uint16_t);
 void		 write_hdr_auto(uint32_t, uint8_t);
 void		 write_str(uint16_t, const char *);
 void		 write_str_auto(const char *);
+void		 write_buf(const void *, uint32_t);
 void		 write_64(uint64_t);
 void		 write_32(uint32_t);
 void		 write_16(uint16_t);
@@ -45,6 +46,9 @@ void		 tclunk(uint32_t);
 void		 tflush(uint16_t);
 void		 twalk(uint32_t, uint32_t, const char **, size_t);
 void		 topen(uint32_t, uint8_t);
+void		 tcreate(uint32_t, const char *, uint32_t, uint8_t);
 void		 tread(uint32_t, uint64_t, uint32_t);
+void		 twrite(uint32_t, uint64_t, const void *, uint32_t);
+void		 tremove(uint32_t);
 
 #endif
blob - 1d0e23caf45939f884a7e731f4310714f8482dc1
blob + fb0c86530732d462858c57359e8a544d794d6b06
--- kamirepl.1
+++ kamirepl.1
@@ -105,6 +105,16 @@ to truncate the file or
 .Sq rclose
 to remove the file upon
 .Ic clunk .
+.It Ic create Ar fid Ar name Ar perm Ar mode
+Create the file
+.Ar name
+and open it with
+.Ar mode
+as the given
+.Ar fid.
+.Ar perm
+should be used to select the permissions of the file, but is currently
+unused.
 .It Ic read Ar fid Ar offset Ar count
 Issue a read request for the given
 .Ar fid ,
@@ -115,6 +125,20 @@ at
 and for
 .Ar count
 bytes.
+.It Ic write Ar fid Ar offset Ar content
+Writes
+.Ar content
+to
+.Ar fid
+starting at
+.Ar offset .
+.It Ic remove Ar fid
+Delete the file identified by
+.Ar fid
+and close it.
+Even in case of error,
+.Ar fid
+is clunked.
 .El
 .Sh SEE ALSO
 .Xr kamiftp 1
blob - f9827e42cbace60d30b4d786d251025de8e54fae
blob + 37f52de3fe7bbf4220579af0d172e83adb38b7a4
--- kamirepl.c
+++ kamirepl.c
@@ -79,7 +79,9 @@ static void		 excmd_clunk(const char **, int);
 static void		 excmd_flush(const char **, int);
 static void		 excmd_walk(const char ** , int);
 static void		 excmd_open(const char ** , int);
+static void		 excmd_create(const char ** , int);
 static void		 excmd_read(const char ** , int);
+static void		 excmd_write(const char **, int);
 static void		 excmd(const char **, int);
 
 static const char	*pp_qid_type(uint8_t);
@@ -535,8 +537,44 @@ excmd_open(const char **argv, int argc)
 
 usage:
 	log_warnx("usage: open fid mode [flag]");
+}
+
+/* create fid path perm mode */
+static void
+excmd_create(const char **argv, int argc)
+{
+	const char	*errstr;
+	uint32_t	 fid;
+	uint8_t		 mode = 0;
+
+	if (argc != 5)
+		goto usage;
+
+	fid = strtonum(argv[1], 0, UINT32_MAX, &errstr);
+	if (errstr != NULL) {
+		log_warnx("fid is %s: %s", errstr, argv[1]);
+		return;
+	}
+
+	/* parse mode */
+	if (!strcmp("write", argv[4]) || !strcmp("w", argv[4]))
+		mode = KOWRITE;
+	else if (!strcmp("readwrite", argv[4]) || !strcmp("rw", argv[4]))
+		mode = KORDWR;
+	else {	    
+		log_warnx("invalid mode %s for create", argv[4]);
+		return;
+	}
+
+	tcreate(fid, argv[2], 0, mode);
+	do_send();
+	return;
+
+usage:
+	log_warnx("usage: create fid path perm mode ; perm is unused");
 }
 
+
 /* read fid offset count */
 static void
 excmd_read(const char **argv, int argc)
@@ -573,9 +611,66 @@ excmd_read(const char **argv, int argc)
 
 usage:
 	log_warnx("usage: read fid offset count");
+}
+
+/* write fid offset content */
+static void
+excmd_write(const char **argv, int argc)
+{
+	uint64_t	 off;
+	uint32_t	 fid, count;
+	const char	*errstr;
+
+	if (argc != 4)
+		goto usage;
+
+	fid = strtonum(argv[1], 0, UINT32_MAX, &errstr);
+	if (errstr != NULL) {
+		log_warnx("fid is %s: %s", errstr, argv[1]);
+		return;
+	}
+
+	/* should really be UINT64_MAX but... */
+	off = strtonum(argv[2], 0, UINT32_MAX, &errstr);
+	if (errstr != NULL) {
+		log_warnx("offset is %s: %s", errstr, argv[2]);
+		return;
+	}
+
+	count = strlen(argv[3]);
+	twrite(fid, off, argv[3], count);
+	do_send();
+	return;
+
+usage:
+	log_warnx("usage: write fid offset content");
 }
 
+/* remove fid */
 static void
+excmd_remove(const char **argv, int argc)
+{
+	const char	*errstr;
+	uint32_t	 fid;
+
+	if (argc != 2)
+		goto usage;
+
+	fid = strtonum(argv[1], 0, UINT32_MAX, &errstr);
+	if (errstr != NULL) {
+		log_warnx("fid is %s: %s", errstr, argv[1]);
+		return;
+	}
+
+	tremove(fid);
+	do_send();
+	return;
+
+usage:
+	log_warnx("usage: remove fid");
+}
+
+static void
 excmd(const char **argv, int argc)
 {
 	struct cmd {
@@ -588,7 +683,11 @@ excmd(const char **argv, int argc)
 		{"flush",	excmd_flush},
 		{"walk",	excmd_walk},
 		{"open",	excmd_open},
+		{"create",	excmd_create},
 		{"read",	excmd_read},
+		{"write",	excmd_write},
+		/* TODO: stat */
+		{"remove",	excmd_remove},
 	};
 	size_t i;
 
@@ -736,9 +835,10 @@ pp_msg(uint32_t len, uint8_t type, uint16_t tag, const
 		break;
 
 	case Ropen:
+	case Rcreate:
 		if (len != QIDSIZE + 4) {
-			printf("invalid Ropen: expected %d bytes; "
-			    "got %u\n", QIDSIZE + 4, len);
+			printf("invalid %s: expected %d bytes; "
+			    "got %u\n", pp_msg_type(type), QIDSIZE + 4, len);
 			break;
 		}
 
@@ -777,9 +877,29 @@ pp_msg(uint32_t len, uint8_t type, uint16_t tag, const
 		strvisx(v, d, count, VIS_SAFE | VIS_TAB | VIS_NL | VIS_CSTYLE);
 		printf("data=%s", v);
 		free(v);
+
+		break;
+
+	case Rwrite:
+		if (len != sizeof(count)) {
+			printf("invalid Rwrite: expected %zu data bytes; "
+			    "got %u\n", sizeof(count), len);
+			break;
+		}
 
+		memcpy(&count, d, sizeof(count));
+		d += sizeof(count);
+		len -= sizeof(count);
+		count = le32toh(count);
+
+		printf("count=%d", count);
 		break;
 
+	case Rremove:
+		if (len != 0)
+			printf("invalid Rremove: %"PRIu32" extra bytes", len);
+		break;
+
 	case Rerror:
 		memcpy(&slen, d, sizeof(slen));
 		d += sizeof(slen);