Annotation of linux/net/unix.c, revision 1.1

1.1     ! root        1: #include <signal.h>
        !             2: #include <errno.h>
        !             3: #include <linux/string.h>
        !             4: #include <linux/sched.h>
        !             5: #include <linux/kernel.h>
        !             6: #include <asm/system.h>
        !             7: #include <asm/segment.h>
        !             8: #include <sys/socket.h>
        !             9: #include <sys/un.h>
        !            10: #include <sys/stat.h>
        !            11: #include <fcntl.h>
        !            12: #include <termios.h>
        !            13: #include "kern_sock.h"
        !            14: 
        !            15: static struct unix_proto_data {
        !            16:        int refcnt;                     /* cnt of reference 0=free */
        !            17:        struct socket *socket;          /* socket we're bound to */
        !            18:        int protocol;
        !            19:        struct sockaddr_un sockaddr_un;
        !            20:        short sockaddr_len;             /* >0 if name bound */
        !            21:        char *buf;
        !            22:        int bp_head, bp_tail;
        !            23:        struct inode *inode;
        !            24:        struct unix_proto_data *peerupd;
        !            25: } unix_datas[NSOCKETS];
        !            26: #define last_unix_data (unix_datas + NSOCKETS - 1)
        !            27: 
        !            28: #define UN_DATA(SOCK) ((struct unix_proto_data *)(SOCK)->data)
        !            29: #define UN_PATH_OFFSET ((unsigned long)((struct sockaddr_un *)0)->sun_path)
        !            30: 
        !            31: /*
        !            32:  * buffer size must be power of 2. buffer mgmt inspired by pipe code.
        !            33:  * note that buffer contents can wraparound, and we can write one byte less
        !            34:  * than full size to discern full vs empty.
        !            35:  */
        !            36: #define BUF_SIZE PAGE_SIZE
        !            37: #define UN_BUF_AVAIL(UPD) (((UPD)->bp_head - (UPD)->bp_tail) & (BUF_SIZE-1))
        !            38: #define UN_BUF_SPACE(UPD) ((BUF_SIZE-1) - UN_BUF_AVAIL(UPD))
        !            39: 
        !            40: static int unix_proto_init(void);
        !            41: static int unix_proto_create(struct socket *sock, int protocol);
        !            42: static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
        !            43: static int unix_proto_release(struct socket *sock, struct socket *peer);
        !            44: static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
        !            45:                           int sockaddr_len);
        !            46: static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
        !            47:                              int sockaddr_len);
        !            48: static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
        !            49: static int unix_proto_accept(struct socket *sock, struct socket *newsock);
        !            50: static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
        !            51:                              int *usockaddr_len, int peer);
        !            52: static int unix_proto_read(struct socket *sock, char *ubuf, int size,
        !            53:                           int nonblock);
        !            54: static int unix_proto_write(struct socket *sock, char *ubuf, int size,
        !            55:                            int nonblock);
        !            56: static int unix_proto_select(struct socket *sock, int which);
        !            57: static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
        !            58:                            unsigned long arg);
        !            59: 
        !            60: struct proto_ops unix_proto_ops = {
        !            61:        unix_proto_init,
        !            62:        unix_proto_create,
        !            63:        unix_proto_dup,
        !            64:        unix_proto_release,
        !            65:        unix_proto_bind,
        !            66:        unix_proto_connect,
        !            67:        unix_proto_socketpair,
        !            68:        unix_proto_accept,
        !            69:        unix_proto_getname,
        !            70:        unix_proto_read,
        !            71:        unix_proto_write,
        !            72:        unix_proto_select,
        !            73:        unix_proto_ioctl
        !            74: };
        !            75: 
        !            76: #ifdef SOCK_DEBUG
        !            77: void
        !            78: sockaddr_un_printk(struct sockaddr_un *sockun, int sockaddr_len)
        !            79: {
        !            80:        char buf[sizeof(sockun->sun_path) + 1];
        !            81: 
        !            82:        sockaddr_len -= UN_PATH_OFFSET;
        !            83:        if (sockun->sun_family != AF_UNIX)
        !            84:                printk("sockaddr_un: <BAD FAMILY: %d>\n", sockun->sun_family);
        !            85:        else if (sockaddr_len <= 0 || sockaddr_len >= sizeof(buf)-1)
        !            86:                printk("sockaddr_un: <BAD LENGTH: %d>\n", sockaddr_len);
        !            87:        else {
        !            88:                memcpy(buf, sockun->sun_path, sockaddr_len);
        !            89:                buf[sockaddr_len] = '\0';
        !            90:                printk("sockaddr_un: '%s'[%d]\n", buf,
        !            91:                       sockaddr_len + UN_PATH_OFFSET);
        !            92:        }
        !            93: }
        !            94: #endif
        !            95: 
        !            96: static struct unix_proto_data *
        !            97: unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
        !            98: {
        !            99:        struct unix_proto_data *upd;
        !           100: 
        !           101:        for (upd = unix_datas; upd <= last_unix_data; ++upd) {
        !           102:                if (upd->refcnt && upd->socket &&
        !           103:                    upd->sockaddr_len == sockaddr_len &&
        !           104:                    memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
        !           105:                        return upd;
        !           106:        }
        !           107:        return NULL;
        !           108: }
        !           109: 
        !           110: static struct unix_proto_data *
        !           111: unix_data_alloc(void)
        !           112: {
        !           113:        struct unix_proto_data *upd;
        !           114: 
        !           115:        cli();
        !           116:        for (upd = unix_datas; upd <= last_unix_data; ++upd) {
        !           117:                if (!upd->refcnt) {
        !           118:                        upd->refcnt = 1;
        !           119:                        sti();
        !           120:                        upd->socket = NULL;
        !           121:                        upd->sockaddr_len = 0;
        !           122:                        upd->buf = NULL;
        !           123:                        upd->bp_head = upd->bp_tail = 0;
        !           124:                        upd->inode = NULL;
        !           125:                        upd->peerupd = NULL;
        !           126:                        return upd;
        !           127:                }
        !           128:        }
        !           129:        sti();
        !           130:        return NULL;
        !           131: }
        !           132: 
        !           133: static inline void
        !           134: unix_data_ref(struct unix_proto_data *upd)
        !           135: {
        !           136:        ++upd->refcnt;
        !           137:        PRINTK("unix_data_ref: refing data 0x%x (%d)\n", upd, upd->refcnt);
        !           138: }
        !           139: 
        !           140: static void
        !           141: unix_data_deref(struct unix_proto_data *upd)
        !           142: {
        !           143:        if (upd->refcnt == 1) {
        !           144:                PRINTK("unix_data_deref: releasing data 0x%x\n", upd);
        !           145:                if (upd->buf) {
        !           146:                        free_page((unsigned long)upd->buf);
        !           147:                        upd->buf = NULL;
        !           148:                        upd->bp_head = upd->bp_tail = 0;
        !           149:                }
        !           150:        }
        !           151:        --upd->refcnt;
        !           152: }
        !           153: 
        !           154: /*
        !           155:  * upon a create, we allocate an empty protocol data, and grab a page to
        !           156:  * buffer writes
        !           157:  */
        !           158: static int
        !           159: unix_proto_create(struct socket *sock, int protocol)
        !           160: {
        !           161:        struct unix_proto_data *upd;
        !           162: 
        !           163:        PRINTK("unix_proto_create: socket 0x%x, proto %d\n", sock, protocol);
        !           164:        if (protocol != 0) {
        !           165:                PRINTK("unix_proto_create: protocol != 0\n");
        !           166:                return -EINVAL;
        !           167:        }
        !           168:        if (!(upd = unix_data_alloc())) {
        !           169:                printk("unix_proto_create: can't allocate buffer\n");
        !           170:                return -ENOMEM;
        !           171:        }
        !           172:        if (!(upd->buf = (char *)get_free_page())) {
        !           173:                printk("unix_proto_create: can't get page!\n");
        !           174:                unix_data_deref(upd);
        !           175:                return -ENOMEM;
        !           176:        }
        !           177:        upd->protocol = protocol;
        !           178:        upd->socket = sock;
        !           179:        UN_DATA(sock) = upd;
        !           180:        PRINTK("unix_proto_create: allocated data 0x%x\n", upd);
        !           181:        return 0;
        !           182: }
        !           183: 
        !           184: static int
        !           185: unix_proto_dup(struct socket *newsock, struct socket *oldsock)
        !           186: {
        !           187:        struct unix_proto_data *upd = UN_DATA(oldsock);
        !           188: 
        !           189:        return unix_proto_create(newsock, upd->protocol);
        !           190: }
        !           191: 
        !           192: static int
        !           193: unix_proto_release(struct socket *sock, struct socket *peer)
        !           194: {
        !           195:        struct unix_proto_data *upd = UN_DATA(sock);
        !           196: 
        !           197:        PRINTK("unix_proto_release: socket 0x%x, unix_data 0x%x\n",
        !           198:               sock, upd);
        !           199:        if (!upd)
        !           200:                return 0;
        !           201:        if (upd->socket != sock) {
        !           202:                printk("unix_proto_release: socket link mismatch!\n");
        !           203:                return -EINVAL;
        !           204:        }
        !           205:        if (upd->inode) {
        !           206:                PRINTK("unix_proto_release: releasing inode 0x%x\n",
        !           207:                       upd->inode);
        !           208:                iput(upd->inode);
        !           209:                upd->inode = NULL;
        !           210:        }
        !           211:        UN_DATA(sock) = NULL;
        !           212:        upd->socket = NULL;
        !           213:        if (upd->peerupd)
        !           214:                unix_data_deref(upd->peerupd);
        !           215:        unix_data_deref(upd);
        !           216:        return 0;
        !           217: }
        !           218: 
        !           219: /*
        !           220:  * bind a name to a socket. this is where much of the work is done. we
        !           221:  * allocate a fresh page for the buffer, grab the appropriate inode and
        !           222:  * set things up.
        !           223:  *
        !           224:  * XXX what should we do if an address is already bound? here we return
        !           225:  * EINVAL, but it may be necessary to re-bind. i think thats what bsd does
        !           226:  * in the case of datagram sockets
        !           227:  */
        !           228: static int
        !           229: unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
        !           230:                int sockaddr_len)
        !           231: {
        !           232:        struct unix_proto_data *upd = UN_DATA(sock);
        !           233:        char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
        !           234:        int i;
        !           235:        unsigned long old_fs;
        !           236:        unsigned short old_euid;
        !           237: 
        !           238:        PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock,
        !           239:               sockaddr_len);
        !           240:        if (sockaddr_len <= UN_PATH_OFFSET ||
        !           241:            sockaddr_len >= sizeof(struct sockaddr_un)) {
        !           242:                PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len);
        !           243:                return -EINVAL;
        !           244:        }
        !           245:        if (upd->sockaddr_len || upd->inode) {
        !           246:                printk("unix_proto_bind: already bound!\n");
        !           247:                return -EINVAL;
        !           248:        }
        !           249:        verify_area(umyaddr, sockaddr_len);
        !           250:        memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len);
        !           251:        if (upd->sockaddr_un.sun_family != AF_UNIX) {
        !           252:                PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n",
        !           253:                       upd->sockaddr_un.sun_family, AF_UNIX);
        !           254:                return -EINVAL;
        !           255:        }
        !           256: 
        !           257:        /*
        !           258:         *              W A R N I N G
        !           259:         * this is a terrible hack. i want to create a socket in the
        !           260:         * filesystem and get its inode. sys_mknod() can create one for
        !           261:         * me, but it needs superuser privs and doesn't give me the inode.
        !           262:         * we fake suser here and get the file created... ugh.
        !           263:         */
        !           264:        memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
        !           265:        fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
        !           266:        old_fs = get_fs();
        !           267:        set_fs(get_ds());
        !           268:        old_euid = current->euid;
        !           269:        current->euid = 0;
        !           270:        i = sys_mknod(fname, S_IFSOCK, 0);
        !           271:        current->euid = old_euid;
        !           272:        if (i == 0)
        !           273:                i = open_namei(fname, 0, S_IFSOCK, &upd->inode);
        !           274:        set_fs(old_fs);
        !           275:        if (i < 0) {
        !           276:                printk("unix_proto_bind: can't open socket %s\n", fname);
        !           277:                return i;
        !           278:        }
        !           279: 
        !           280:        upd->sockaddr_len = sockaddr_len;       /* now its legal */
        !           281:        PRINTK("unix_proto_bind: bound socket address: ");
        !           282: #ifdef SOCK_DEBUG
        !           283:        sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len);
        !           284: #endif
        !           285:        return 0;
        !           286: }
        !           287: 
        !           288: /*
        !           289:  * perform a connection. we can only connect to unix sockets (i can't for
        !           290:  * the life of me find an application where that wouldn't be the case!)
        !           291:  */
        !           292: static int
        !           293: unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
        !           294:                   int sockaddr_len)
        !           295: {
        !           296:        int i;
        !           297:        struct unix_proto_data *serv_upd;
        !           298:        struct sockaddr_un sockun;
        !           299: 
        !           300:        PRINTK("unix_proto_connect: socket 0x%x, servlen=%d\n", sock,
        !           301:               sockaddr_len);
        !           302:        if (sockaddr_len <= UN_PATH_OFFSET ||
        !           303:            sockaddr_len >= sizeof(struct sockaddr_un)) {
        !           304:                PRINTK("unix_proto_connect: bad length %d\n", sockaddr_len);
        !           305:                return -EINVAL;
        !           306:        }
        !           307:        verify_area(uservaddr, sockaddr_len);
        !           308:        memcpy_fromfs(&sockun, uservaddr, sockaddr_len);
        !           309:        if (sockun.sun_family != AF_UNIX) {
        !           310:                PRINTK("unix_proto_connect: family is %d, not AF_UNIX (%d)\n",
        !           311:                       sockun.sun_family, AF_UNIX);
        !           312:                return -EINVAL;
        !           313:        }
        !           314:        if (!(serv_upd = unix_data_lookup(&sockun, sockaddr_len))) {
        !           315:                PRINTK("unix_proto_connect: can't locate peer\n");
        !           316:                return -EINVAL;
        !           317:        }
        !           318:        if ((i = sock_awaitconn(sock, serv_upd->socket)) < 0) {
        !           319:                PRINTK("unix_proto_connect: can't await connection\n");
        !           320:                return i;
        !           321:        }
        !           322:        unix_data_ref(UN_DATA(sock->conn));
        !           323:        UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
        !           324:        return 0;
        !           325: }
        !           326: 
        !           327: /*
        !           328:  * to do a socketpair, we make just connect the two datas, easy! since we
        !           329:  * always wait on the socket inode, they're no contention for a wait area,
        !           330:  * and deadlock prevention in the case of a process writing to itself is,
        !           331:  * ignored, in true unix fashion!
        !           332:  */
        !           333: static int
        !           334: unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
        !           335: {
        !           336:        struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
        !           337: 
        !           338:        unix_data_ref(upd1);
        !           339:        unix_data_ref(upd2);
        !           340:        upd1->peerupd = upd2;
        !           341:        upd2->peerupd = upd1;
        !           342:        return 0;
        !           343: }
        !           344: 
        !           345: /*
        !           346:  * on accept, we ref the peer's data for safe writes
        !           347:  */
        !           348: static int
        !           349: unix_proto_accept(struct socket *sock, struct socket *newsock)
        !           350: {
        !           351:        PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n",
        !           352:               sock, newsock);
        !           353:        unix_data_ref(UN_DATA(newsock->conn));
        !           354:        UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn);
        !           355:        return 0;
        !           356: }
        !           357: 
        !           358: /*
        !           359:  * gets the current name or the name of the connected socket.
        !           360:  */
        !           361: static int
        !           362: unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
        !           363:                   int *usockaddr_len, int peer)
        !           364: {
        !           365:        struct unix_proto_data *upd;
        !           366:        int len;
        !           367: 
        !           368:        PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
        !           369:               peer ? "peer" : "self");
        !           370:        if (peer) {
        !           371:                if (sock->state != SS_CONNECTED) {
        !           372:                        PRINTK("unix_proto_getname: socket not connected\n");
        !           373:                        return -EINVAL;
        !           374:                }
        !           375:                upd = UN_DATA(sock->conn);
        !           376:        }
        !           377:        else
        !           378:                upd = UN_DATA(sock);
        !           379:        verify_area(usockaddr_len, sizeof(*usockaddr_len));
        !           380:        if ((len = get_fs_long(usockaddr_len)) <= 0)
        !           381:                return -EINVAL;
        !           382:        if (len > upd->sockaddr_len)
        !           383:                len = upd->sockaddr_len;
        !           384:        if (len) {
        !           385:                verify_area(usockaddr, len);
        !           386:                memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
        !           387:        }
        !           388:        put_fs_long(len, usockaddr_len);
        !           389:        return 0;
        !           390: }
        !           391: 
        !           392: /*
        !           393:  * we read from our own buf.
        !           394:  */
        !           395: static int
        !           396: unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
        !           397: {
        !           398:        struct unix_proto_data *upd;
        !           399:        int todo, avail;
        !           400: 
        !           401:        if ((todo = size) <= 0)
        !           402:                return 0;
        !           403:        upd = UN_DATA(sock);
        !           404:        while (!(avail = UN_BUF_AVAIL(upd))) {
        !           405:                if (sock->state != SS_CONNECTED) {
        !           406:                        PRINTK("unix_proto_read: socket not connected\n");
        !           407:                        return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
        !           408:                }
        !           409:                PRINTK("unix_proto_read: no data available...\n");
        !           410:                if (nonblock)
        !           411:                        return -EAGAIN;
        !           412:                interruptible_sleep_on(sock->wait);
        !           413:                if (current->signal & ~current->blocked) {
        !           414:                        PRINTK("unix_proto_read: interrupted\n");
        !           415:                        return -ERESTARTSYS;
        !           416:                }
        !           417:                if (sock->state == SS_DISCONNECTING) {
        !           418:                        PRINTK("unix_proto_read: disconnected\n");
        !           419:                        return 0;
        !           420:                }
        !           421:        }
        !           422: 
        !           423:        /*
        !           424:         * copy from the read buffer into the user's buffer, watching for
        !           425:         * wraparound. then we wake up the writer
        !           426:         */
        !           427:        do {
        !           428:                int part, cando;
        !           429: 
        !           430:                if (avail <= 0) {
        !           431:                        PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
        !           432:                        current->signal |= (1 << (SIGKILL-1));
        !           433:                        return -EINTR;
        !           434:                }
        !           435: 
        !           436:                if ((cando = todo) > avail)
        !           437:                        cando = avail;
        !           438:                if (cando > (part = BUF_SIZE - upd->bp_tail))
        !           439:                        cando = part;
        !           440:                PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
        !           441:                       avail, todo, cando);
        !           442:                verify_area(ubuf, cando);
        !           443:                memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
        !           444:                upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
        !           445:                ubuf += cando;
        !           446:                todo -= cando;
        !           447:                if (sock->state == SS_CONNECTED)
        !           448:                        wake_up(sock->conn->wait);
        !           449:                avail = UN_BUF_AVAIL(upd);
        !           450:        } while (todo && avail);
        !           451:        return size - todo;
        !           452: }
        !           453: 
        !           454: /*
        !           455:  * we write to our peer's buf. when we connected we ref'd this peer so we
        !           456:  * are safe that the buffer remains, even after the peer has disconnected,
        !           457:  * which we check other ways.
        !           458:  */
        !           459: static int
        !           460: unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
        !           461: {
        !           462:        struct unix_proto_data *pupd;
        !           463:        int todo, space;
        !           464: 
        !           465:        if ((todo = size) <= 0)
        !           466:                return 0;
        !           467:        if (sock->state != SS_CONNECTED) {
        !           468:                PRINTK("unix_proto_write: socket not connected\n");
        !           469:                if (sock->state == SS_DISCONNECTING) {
        !           470:                        current->signal |= (1 << (SIGPIPE-1));
        !           471:                        return -EINTR;
        !           472:                }
        !           473:                return -EINVAL;
        !           474:        }
        !           475:        pupd = UN_DATA(sock)->peerupd;  /* safer than sock->conn */
        !           476: 
        !           477:        while (!(space = UN_BUF_SPACE(pupd))) {
        !           478:                PRINTK("unix_proto_write: no space left...\n");
        !           479:                if (nonblock)
        !           480:                        return 0;
        !           481:                interruptible_sleep_on(sock->wait);
        !           482:                if (current->signal & ~current->blocked) {
        !           483:                        PRINTK("unix_proto_write: interrupted\n");
        !           484:                        return -EINTR;
        !           485:                }
        !           486:                if (sock->state == SS_DISCONNECTING) {
        !           487:                        PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
        !           488:                        current->signal |= (1 << (SIGPIPE-1));
        !           489:                        return -EINTR;
        !           490:                }
        !           491:        }
        !           492: 
        !           493:        /*
        !           494:         * copy from the user's buffer to the write buffer, watching for
        !           495:         * wraparound. then we wake up the reader
        !           496:         */
        !           497:        do {
        !           498:                int part, cando;
        !           499: 
        !           500:                if (space <= 0) {
        !           501:                        PRINTK("unix_proto_write: SPACE IS NEGATIVE!!!\n");
        !           502:                        current->signal |= (1 << (SIGKILL-1));
        !           503:                        return -EINTR;
        !           504:                }
        !           505: 
        !           506:                /*
        !           507:                 * we may become disconnected inside this loop, so watch
        !           508:                 * for it (peerupd is safe until we close)
        !           509:                 */
        !           510:                if (sock->state == SS_DISCONNECTING) {
        !           511:                        current->signal |= (1 << (SIGPIPE-1));
        !           512:                        return -EINTR;
        !           513:                }
        !           514:                if ((cando = todo) > space)
        !           515:                        cando = space;
        !           516:                if (cando > (part = BUF_SIZE - pupd->bp_head))
        !           517:                        cando = part;
        !           518:                PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
        !           519:                       space, todo, cando);
        !           520:                verify_area(ubuf, cando);
        !           521:                memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
        !           522:                pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
        !           523:                ubuf += cando;
        !           524:                todo -= cando;
        !           525:                if (sock->state == SS_CONNECTED)
        !           526:                        wake_up(sock->conn->wait);
        !           527:                space = UN_BUF_SPACE(pupd);
        !           528:        } while (todo && space);
        !           529:        return size - todo;
        !           530: }
        !           531: 
        !           532: static int
        !           533: unix_proto_select(struct socket *sock, int which)
        !           534: {
        !           535:        struct unix_proto_data *upd, *peerupd;
        !           536: 
        !           537:        if (which == SEL_IN) {
        !           538:                upd = UN_DATA(sock);
        !           539:                PRINTK("unix_proto_select: there is%s data available\n",
        !           540:                       UN_BUF_AVAIL(upd) ? "" : " no");
        !           541:                if (UN_BUF_AVAIL(upd))  /* even if disconnected */
        !           542:                        return 1;
        !           543:                else if (sock->state != SS_CONNECTED) {
        !           544:                        PRINTK("unix_proto_select: socket not connected (read EOF)\n");
        !           545:                        return 1;
        !           546:                }
        !           547:                else
        !           548:                        return 0;
        !           549:        }
        !           550:        if (which == SEL_OUT) {
        !           551:                if (sock->state != SS_CONNECTED) {
        !           552:                        PRINTK("unix_proto_select: socket not connected (write EOF)\n");
        !           553:                        return 1;
        !           554:                }
        !           555:                peerupd = UN_DATA(sock->conn);
        !           556:                PRINTK("unix_proto_select: there is%s space available\n",
        !           557:                       UN_BUF_SPACE(peerupd) ? "" : " no");
        !           558:                return (UN_BUF_SPACE(peerupd) > 0);
        !           559:        }
        !           560:        /* SEL_EX */
        !           561:        PRINTK("unix_proto_select: there are no exceptions here?!\n");
        !           562:        return 0;
        !           563: }
        !           564: 
        !           565: static int
        !           566: unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        !           567: {
        !           568:        struct unix_proto_data *upd, *peerupd;
        !           569: 
        !           570:        upd = UN_DATA(sock);
        !           571:        peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
        !           572: 
        !           573:        switch (cmd) {
        !           574:        case TIOCINQ:
        !           575:                verify_area((void *)arg, sizeof(unsigned long));
        !           576:                if (UN_BUF_AVAIL(upd) || peerupd)
        !           577:                        put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
        !           578:                else
        !           579:                        put_fs_long(1, (unsigned long *)arg); /* read EOF */
        !           580:                break;
        !           581: 
        !           582:        case TIOCOUTQ:
        !           583:                verify_area((void *)arg, sizeof(unsigned long));
        !           584:                if (peerupd)
        !           585:                        put_fs_long(UN_BUF_SPACE(peerupd),
        !           586:                                    (unsigned long *)arg);
        !           587:                else
        !           588:                        put_fs_long(0, (unsigned long *)arg);
        !           589:                break;
        !           590: 
        !           591:        default:
        !           592:                return -EINVAL;
        !           593:        }
        !           594:        return 0;
        !           595: }
        !           596: 
        !           597: static int
        !           598: unix_proto_init(void)
        !           599: {
        !           600:        struct unix_proto_data *upd;
        !           601: 
        !           602:        PRINTK("unix_proto_init: initializing...\n");
        !           603:        for (upd = unix_datas; upd <= last_unix_data; ++upd)
        !           604:                upd->refcnt = 0;
        !           605:        return 0;
        !           606: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.