|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.