spc_mach_message_t* spc_serialize(spc_message_t* msg) { spc_mach_message_t* mach_msg; size_t actual_size, content_size, initial_size = msg->content->num_items * 32; // heuristic writer_t writer; writer.start = malloc(initial_size); writer.end = writer.start + initial_size; writer.ptr = writer.start; writer.ports = NULL; writer.num_ports = 0; spc_write(&writer, last_header, 8); spc_write_uint32(&writer, SPC_TYPE_DICT); spc_write_dict(&writer, msg->content); content_size = writer.ptr - writer.start; char* ptr; if (writer.num_ports != 0) { // Must create a complex messge actual_size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t) + writer.num_ports * sizeof(mach_msg_port_descriptor_t) + content_size; mach_msg = malloc(actual_size); mach_msg->header.msgh_bits = MACH_MSGH_BITS_COMPLEX; ptr = (char*)mach_msg + sizeof(mach_msg_header_t); mach_msg_body_t* body = (mach_msg_body_t*)ptr; body->msgh_descriptor_count = writer.num_ports; ptr += sizeof(mach_msg_body_t); for (size_t i = 0; i < writer.num_ports; i++) { mach_msg_port_descriptor_t* descriptor = (mach_msg_port_descriptor_t*)ptr; descriptor->type = MACH_MSG_PORT_DESCRIPTOR; descriptor->name = writer.ports[i].name; descriptor->disposition = writer.ports[i].type; ptr += sizeof(mach_msg_port_descriptor_t); } } else { actual_size = sizeof(mach_msg_header_t) + content_size; mach_msg = malloc(actual_size); mach_msg->header.msgh_bits = 0; ptr = (char*)mach_msg->buf; } // Fill in the mach message mach_msg->header.msgh_remote_port = msg->remote_port.name; mach_msg->header.msgh_local_port = msg->local_port.name; mach_msg->header.msgh_id = msg->id; mach_msg->header.msgh_size = actual_size; mach_msg->header.msgh_bits |= MACH_MSGH_BITS(msg->remote_port.type, msg->local_port.type); memcpy(ptr, writer.start, content_size); free(writer.start); return mach_msg; }
size_t spc_serialize_value(writer_t* writer, spc_value_t value) { size_t bytes_written = 0; bytes_written += spc_write_uint32(writer, value.type); switch (value.type) { case SPC_TYPE_NULL: break; case SPC_TYPE_BOOL: bytes_written += spc_write_uint32(writer, value.value.u64); break; case SPC_TYPE_UINT64: bytes_written += spc_write_uint64(writer, value.value.u64); break; case SPC_TYPE_INT64: bytes_written += spc_write_int64(writer, value.value.i64); break; case SPC_TYPE_DOUBLE: bytes_written += spc_write_double(writer, value.value.dbl); break; case SPC_TYPE_STRING: bytes_written += spc_write_uint32(writer, strlen(value.value.str) + 1); bytes_written += spc_write_str(writer, value.value.str); break; case SPC_TYPE_ARRAY: bytes_written += spc_write_array(writer, value.value.array); break; case SPC_TYPE_DICT: bytes_written += spc_write_dict(writer, value.value.dict); break; case SPC_TYPE_FD: case SPC_TYPE_SEND_PORT: case SPC_TYPE_RECV_PORT: spc_write_port(writer, value.value.port); break; case SPC_TYPE_UUID: bytes_written += spc_write(writer, value.value.ptr, 0x10); break; case SPC_TYPE_DATA: bytes_written += spc_write_uint32(writer, value.value.data.size); bytes_written += spc_write_padded(writer, value.value.data.ptr, value.value.data.size); break; default: printf("Unsupported value type: 0x%x\n", value.type); } return bytes_written; }
int main(int argc, char **argv) { int i, n, off; int c; char *addr; char *path; Spuser *user; Spcfsys *fs; Spcfid *fid; char buf[512]; user = sp_unix_users->uid2user(sp_unix_users, geteuid()); while ((c = getopt(argc, argv, "dp:")) != -1) { switch (c) { case 'd': spc_chatty = 1; break; case 'u': user = sp_unix_users->uname2user(sp_unix_users, optarg); break; default: usage(); } } if (!user) { fprintf(stderr, "cannot retrieve user %d\n", geteuid()); exit(1); } if (argc - optind < 2) usage(); addr = argv[optind]; path = argv[optind+1]; fs = spc_netmount(addr, user, 564, NULL, NULL); fid = spc_open(fs, path, Owrite); if (!fid) { fid = spc_create(fs, path, 0666, Owrite); if (!fid) { fprintf(stderr, "error creating\n"); exit(1); } } off = 0; while ((n = read(0, buf, sizeof(buf))) > 0) { i = spc_write(fid, (u8*) buf, n, off); if (i != n) { fprintf(stderr, "error writing\n"); exit(1); } off += n; } spc_close(fid); spc_umount(fs); exit(0); }