/* write 'n' bytes from 'buf' in the file referenced by 'fd' */ ssize_t fs_write(struct file_s *flip, char *buf, size_t n) { return fs_readwrite(flip, buf, n, FS_WRITE); }
PRIVATE int uds_perform_write(int minor, endpoint_t m_source, size_t size, int pretend) { int rc, peer, i; message fs_m_in; message fs_m_out; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] uds_perform_write() call_count=%d\n", minor, ++call_count); #endif /* skip reads and writes of 0 (or less!) bytes */ if (size <= 0) { return 0; } /* check if we are allowed to write */ if (!(uds_fd_table[minor].mode & S_IWUSR)) { /* socket is shutdown for writing */ errno = EPIPE; return -1; } if (size > PIPE_BUF) { /* message is too big to ever write to the PIPE */ errno = EMSGSIZE; return -1; } if (uds_fd_table[minor].type == SOCK_STREAM || uds_fd_table[minor].type == SOCK_SEQPACKET) { /* if we're writing with a connection oriented socket, * then it needs a peer to write to */ if (uds_fd_table[minor].peer == -1) { if (uds_fd_table[minor].err == ECONNRESET) { uds_fd_table[minor].err = 0; errno = ECONNRESET; } else { errno = ENOTCONN; } return -1; } else { peer = uds_fd_table[minor].peer; } } else /* uds_fd_table[minor].type == SOCK_DGRAM */ { peer = -1; /* locate the "peer" we want to write to */ for (i = 0; i < NR_FDS; i++) { /* look for a SOCK_DGRAM socket that is bound on * the target address */ if (uds_fd_table[i].type == SOCK_DGRAM && uds_fd_table[i].addr.sun_family == AF_UNIX && !strncmp(uds_fd_table[minor].target.sun_path, uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) { peer = i; break; } } if (peer == -1) { errno = ENOENT; return -1; } } /* check if write would overrun buffer. check if message * boundry preserving types (SEQPACKET and DGRAM) wouldn't write * to an empty buffer. check if connectionless sockets have a * target to write to. */ if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) || ((uds_fd_table[minor].type == SOCK_SEQPACKET || uds_fd_table[minor].type == SOCK_DGRAM) && uds_fd_table[peer].size > 0) || (peer == -1)) { if (pretend) { return SUSPEND; } /* if needed revive the reader */ if (uds_fd_table[peer].suspended) { uds_fd_table[peer].ready_to_revive = 1; notify(m_source); } #if DEBUG == 1 printf("(uds) [%d] suspending write request\n", minor); #endif /* Process is reading from an empty pipe, * suspend it so some bytes can be written */ uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE; return SUSPEND; } if (pretend) { return size; } /* Prepare Request to the FS side of PFS */ fs_m_in.m_type = REQ_WRITE; fs_m_in.REQ_INODE_NR = uds_fd_table[peer].inode_nr; fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr; fs_m_in.REQ_SEEK_POS_HI = 0; fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos + uds_fd_table[peer].size; fs_m_in.REQ_NBYTES = size; /* Request the write */ rc = fs_readwrite(&fs_m_in, &fs_m_out); if (rc != OK) { perror("fs_readwrite"); return rc; } /* Process the response */ #if DEBUG == 1 printf("(uds) [%d] write complete\n", minor); #endif /* increase the count of unread bytes */ uds_fd_table[peer].size += fs_m_out.RES_NBYTES; /* fill in the source address to be returned by recvfrom & recvmsg */ if (uds_fd_table[minor].type == SOCK_DGRAM) { memcpy(&uds_fd_table[peer].source, &uds_fd_table[minor].addr, sizeof(struct sockaddr_un)); } /* revive peer that was waiting for us to write */ if (uds_fd_table[peer].suspended) { uds_fd_table[peer].ready_to_revive = 1; notify(m_source); } /* see if peer is blocked on select()*/ if (uds_fd_table[peer].selecting == 1 && fs_m_out.RES_NBYTES > 0) { /* if the peer wants to know about data ready to read * and it doesn't know about it already, then let the peer * know we have data for it. */ if ((uds_fd_table[peer].sel_ops_in & SEL_RD) && !(uds_fd_table[peer].sel_ops_out & SEL_RD)) { /* a read on peer is possible now */ uds_fd_table[peer].sel_ops_out |= SEL_RD; uds_fd_table[peer].status_updated = 1; notify(uds_fd_table[peer].select_proc); } } return fs_m_out.RES_NBYTES; /* return number of bytes written */ }
/* read 'n' bytes from a file a put them on buf */ size_t fs_read(struct file_s *flip, char *buf, size_t n) { return fs_readwrite(flip, buf, n, FS_READ); }
PRIVATE int uds_perform_read(int minor, endpoint_t m_source, size_t size, int pretend) { int rc; message fs_m_in; message fs_m_out; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] uds_perform_read() call_count=%d\n", minor, ++call_count); #endif /* skip reads and writes of 0 (or less!) bytes */ if (size <= 0) { return 0; } /* check if we are allowed to read */ if (!(uds_fd_table[minor].mode & S_IRUSR)) { /* socket is shutdown for reading */ errno = EPIPE; return -1; } if (uds_fd_table[minor].size == 0) { if (pretend) { return SUSPEND; } /* maybe a process is blocked waiting to write? if * needed revive the writer */ if (uds_fd_table[minor].peer != -1 && uds_fd_table[uds_fd_table[minor].peer].suspended) { int peer = uds_fd_table[minor].peer; uds_fd_table[peer].ready_to_revive = 1; notify(m_source); } #if DEBUG == 1 printf("(uds) [%d] suspending read request\n", minor); #endif /* Process is reading from an empty pipe, * suspend it so some bytes can be written */ uds_fd_table[minor].suspended = UDS_SUSPENDED_READ; return SUSPEND; } if (pretend) { return (size > uds_fd_table[minor].size) ? uds_fd_table[minor].size : size; } /* Prepare Request to the FS side of PFS */ fs_m_in.m_type = REQ_READ; fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr; fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr; fs_m_in.REQ_SEEK_POS_HI = 0; fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[minor].pos; fs_m_in.REQ_NBYTES = (size > uds_fd_table[minor].size) ? uds_fd_table[minor].size : size; /* perform the read */ rc = fs_readwrite(&fs_m_in, &fs_m_out); if (rc != OK) { perror("fs_readwrite"); return rc; } /* Process the response */ #if DEBUG == 1 printf("(uds) [%d] read complete\n", minor); #endif /* move the position of the data pointer up to data we haven't * read yet */ uds_fd_table[minor].pos += fs_m_out.RES_NBYTES; /* decrease the number of unread bytes */ uds_fd_table[minor].size -= fs_m_out.RES_NBYTES; /* if we have 0 unread bytes, move the data pointer back to the * start of the buffer */ if (uds_fd_table[minor].size == 0) { uds_fd_table[minor].pos = 0; } /* maybe a big write was waiting for us to read some data, if * needed revive the writer */ if (uds_fd_table[minor].peer != -1 && uds_fd_table[uds_fd_table[minor].peer].suspended) { uds_fd_table[uds_fd_table[minor].peer].ready_to_revive = 1; notify(m_source); } /* see if peer is blocked on select() and a write is possible * (from peer to minor) */ if (uds_fd_table[minor].peer != -1 && uds_fd_table[uds_fd_table[minor].peer].selecting == 1 && (uds_fd_table[minor].size + uds_fd_table[minor].pos + 1 < PIPE_BUF)) { int peer = uds_fd_table[minor].peer; /* if the peer wants to know about write being possible * and it doesn't know about it already, then let the peer know. */ if ((uds_fd_table[peer].sel_ops_in & SEL_WR) && !(uds_fd_table[peer].sel_ops_out & SEL_WR)) { /* a write on peer is possible now */ uds_fd_table[peer].sel_ops_out |= SEL_WR; uds_fd_table[peer].status_updated = 1; notify(uds_fd_table[peer].select_proc); } } return fs_m_out.RES_NBYTES; /* return number of bytes read */ }